From c22fdf1993a72add7c2c4a8fb5f4721d6447410d Mon Sep 17 00:00:00 2001 From: Andrew Dey Date: Wed, 11 Aug 2021 09:15:56 -0400 Subject: [PATCH 01/42] (#104) add X11 to list of supported hardware accelerations --- src/example/java/tech/fastj/example/engineconfig/Main.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/example/java/tech/fastj/example/engineconfig/Main.java b/src/example/java/tech/fastj/example/engineconfig/Main.java index 9638f735..71fe075b 100644 --- a/src/example/java/tech/fastj/example/engineconfig/Main.java +++ b/src/example/java/tech/fastj/example/engineconfig/Main.java @@ -65,8 +65,10 @@ public static void main(String[] args) { /* Now, we'll move onto configureHardwareAcceleration. * By making use of java2d, FastJ supports a few hardware-accelerated graphics APIs: - * - OpenGL - * - Direct3D + * - OpenGL, for devices of all OSes + * - Direct3D, for Windows devices + * - X11, for Linux devices + * As well as CPURender, for software rendering. * * With that in mind, "FastJEngine#configureHardwareAcceleration" allows you to configure * the type of hardware acceleration your game uses. This is set using the "HWAccel" enum. From 60e8e64a173413b8fc887da5bb377c6cf1bae04c Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Thu, 12 Aug 2021 11:42:40 -0400 Subject: [PATCH 02/42] (#106) remove translation from setMetrics --- src/main/java/tech/fastj/graphics/game/Text2D.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/game/Text2D.java b/src/main/java/tech/fastj/graphics/game/Text2D.java index c87082eb..f7ded2d1 100644 --- a/src/main/java/tech/fastj/graphics/game/Text2D.java +++ b/src/main/java/tech/fastj/graphics/game/Text2D.java @@ -2,6 +2,7 @@ import tech.fastj.engine.FastJEngine; import tech.fastj.math.Pointf; +import tech.fastj.math.Transform2D; import tech.fastj.graphics.Drawable; import tech.fastj.systems.control.Scene; @@ -205,8 +206,12 @@ private void setMetrics(Graphics2D g) { int textWidth = fm.stringWidth(text); int textHeight = fm.getHeight(); - Pointf translation = getTranslation(); - final Rectangle2D.Float bounds = new Rectangle2D.Float(translation.x, translation.y, textWidth, textHeight); + final Rectangle2D.Float bounds = new Rectangle2D.Float( + Transform2D.DefaultTranslation.x, + Transform2D.DefaultTranslation.y, + textWidth, + textHeight + ); setCollisionPath(createMetricsPath(bounds)); From c49e50c8c07d90d82d26f6ef3df4aa9190d5ad12 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 20 Aug 2021 23:44:48 -0400 Subject: [PATCH 03/42] (#108) added base ideas for image loading/sprite cutting --- .../tech/fastj/graphics/util/ImageUtil.java | 103 ++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 src/main/java/tech/fastj/graphics/util/ImageUtil.java diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/graphics/util/ImageUtil.java new file mode 100644 index 00000000..a90be678 --- /dev/null +++ b/src/main/java/tech/fastj/graphics/util/ImageUtil.java @@ -0,0 +1,103 @@ +package tech.fastj.graphics.util; + +import tech.fastj.engine.FastJEngine; + +import javax.imageio.ImageIO; +import java.awt.AWTException; +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.GraphicsEnvironment; +import java.awt.Image; +import java.awt.ImageCapabilities; +import java.awt.Transparency; +import java.awt.image.BufferedImage; +import java.awt.image.VolatileImage; +import java.io.IOException; +import java.nio.file.Path; + +public class ImageUtil { + + public static VolatileImage createVolatileImage(int width, int height) { + try { + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleVolatileImage( + width, + height, + new ImageCapabilities(true), + Transparency.TRANSLUCENT + ); + } catch (AWTException e) { + throw new IllegalStateException("Issue creating volatile image", e); + } + } + + public static BufferedImage createBufferedImage(int width, int height) { + return GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getDefaultConfiguration().createCompatibleImage( + width, + height, + Transparency.TRANSLUCENT + ); + } + + public static void drawToImage(Image reusedImage, Path pathToSecondImage) { + Graphics2D graphics2D = (Graphics2D) reusedImage.getGraphics(); + FastJEngine.log(pathToSecondImage.toAbsolutePath().toString()); + Image imageFromPath; + try { + imageFromPath = ImageIO.read(pathToSecondImage.toAbsolutePath().toFile()); + } catch (IOException e) { + throw new IllegalStateException("e", e); + } + graphics2D.setBackground(new Color(0, 0, 0, 0)); + graphics2D.clearRect(0, 0, reusedImage.getWidth(null), reusedImage.getHeight(null)); + graphics2D.drawImage(imageFromPath, null, null); + graphics2D.dispose(); + } + + public static BufferedImage[][] createSpriteSheet(BufferedImage bufferedImage, int horizontalImageCount, int verticalImageCount) { + int bufferedImageWidth = bufferedImage.getWidth(); + int expectedHorizontalImagePixels = bufferedImageWidth / horizontalImageCount; + float actualHorizontalImagePixels = bufferedImageWidth / (float) horizontalImageCount; + + if (expectedHorizontalImagePixels != actualHorizontalImagePixels) { + FastJEngine.warning( + String.format( + "The horizontal image count given (%d) may cause pixel loss, as not all images will receive the same amount. The calculated pixel count %f is derived from \"%d / %d\".", + horizontalImageCount, + actualHorizontalImagePixels, + bufferedImageWidth, + horizontalImageCount + ) + ); + } + + int bufferedImageHeight = bufferedImage.getHeight(); + int expectedVerticalImagePixels = bufferedImageHeight / verticalImageCount; + float actualVerticalImagePixels = bufferedImageHeight / (float) verticalImageCount; + + if (expectedVerticalImagePixels != actualVerticalImagePixels) { + FastJEngine.warning( + String.format( + "The vertical image count given (%d) may cause pixel loss, as not all images will receive the same amount. The calculated pixel count %f is derived from \"%d / %d\".", + verticalImageCount, + actualVerticalImagePixels, + bufferedImageHeight, + verticalImageCount + ) + ); + } + + BufferedImage[][] spriteSheet = new BufferedImage[verticalImageCount][horizontalImageCount]; + for (int i = 0; i < spriteSheet.length; i++) { + for (int j = 0; j < spriteSheet[0].length; j++) { + spriteSheet[i][j] = bufferedImage.getSubimage( + j * expectedHorizontalImagePixels, + i * expectedVerticalImagePixels, + expectedHorizontalImagePixels, + expectedVerticalImagePixels + ); + } + } + + return spriteSheet; + } +} From 909328c30c373a807c723fa806005a80c7687005 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 21 Aug 2021 00:50:46 -0400 Subject: [PATCH 04/42] added missing exception message --- src/main/java/tech/fastj/graphics/util/ImageUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/graphics/util/ImageUtil.java index a90be678..f8890947 100644 --- a/src/main/java/tech/fastj/graphics/util/ImageUtil.java +++ b/src/main/java/tech/fastj/graphics/util/ImageUtil.java @@ -45,7 +45,7 @@ public static void drawToImage(Image reusedImage, Path pathToSecondImage) { try { imageFromPath = ImageIO.read(pathToSecondImage.toAbsolutePath().toFile()); } catch (IOException e) { - throw new IllegalStateException("e", e); + throw new IllegalStateException("Couldn't get the image at \"" + pathToSecondImage.toAbsolutePath() + "\"", e); } graphics2D.setBackground(new Color(0, 0, 0, 0)); graphics2D.clearRect(0, 0, reusedImage.getWidth(null), reusedImage.getHeight(null)); From 1b4d0124f39fdc843c0cfe26943afe9530bc35ff Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 21 Aug 2021 01:10:30 -0400 Subject: [PATCH 05/42] (#108) switch to single array for spritesheets --- .../java/tech/fastj/graphics/util/ImageUtil.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/graphics/util/ImageUtil.java index f8890947..a4f8519e 100644 --- a/src/main/java/tech/fastj/graphics/util/ImageUtil.java +++ b/src/main/java/tech/fastj/graphics/util/ImageUtil.java @@ -53,7 +53,7 @@ public static void drawToImage(Image reusedImage, Path pathToSecondImage) { graphics2D.dispose(); } - public static BufferedImage[][] createSpriteSheet(BufferedImage bufferedImage, int horizontalImageCount, int verticalImageCount) { + public static BufferedImage[] createSpriteSheet(BufferedImage bufferedImage, int horizontalImageCount, int verticalImageCount) { int bufferedImageWidth = bufferedImage.getWidth(); int expectedHorizontalImagePixels = bufferedImageWidth / horizontalImageCount; float actualHorizontalImagePixels = bufferedImageWidth / (float) horizontalImageCount; @@ -86,15 +86,17 @@ public static BufferedImage[][] createSpriteSheet(BufferedImage bufferedImage, i ); } - BufferedImage[][] spriteSheet = new BufferedImage[verticalImageCount][horizontalImageCount]; - for (int i = 0; i < spriteSheet.length; i++) { - for (int j = 0; j < spriteSheet[0].length; j++) { - spriteSheet[i][j] = bufferedImage.getSubimage( + BufferedImage[] spriteSheet = new BufferedImage[verticalImageCount * horizontalImageCount]; + int spriteSheetIndex = 0; + for (int i = 0; i < verticalImageCount; i++) { + for (int j = 0; j < horizontalImageCount; j++) { + spriteSheet[spriteSheetIndex] = bufferedImage.getSubimage( j * expectedHorizontalImagePixels, i * expectedVerticalImagePixels, expectedHorizontalImagePixels, expectedVerticalImagePixels ); + spriteSheetIndex++; } } From afced5d647fcf485b8e744756813784830df3902 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 01:03:04 -0400 Subject: [PATCH 06/42] (#108) added utility method to load buffered images --- src/main/java/tech/fastj/graphics/util/ImageUtil.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/graphics/util/ImageUtil.java index a4f8519e..397c7101 100644 --- a/src/main/java/tech/fastj/graphics/util/ImageUtil.java +++ b/src/main/java/tech/fastj/graphics/util/ImageUtil.java @@ -38,6 +38,14 @@ public static BufferedImage createBufferedImage(int width, int height) { ); } + public static BufferedImage loadBufferedImage(Path pathToImage) { + try { + return ImageIO.read(pathToImage.toAbsolutePath().toFile()); + } catch (IOException e) { + throw new IllegalStateException("Couldn't get the image at \"" + pathToImage.toAbsolutePath() + "\"", e); + } + } + public static void drawToImage(Image reusedImage, Path pathToSecondImage) { Graphics2D graphics2D = (Graphics2D) reusedImage.getGraphics(); FastJEngine.log(pathToSecondImage.toAbsolutePath().toString()); From 403ea7405ef93698323af87ba87dcc5a8391cb62 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 01:03:38 -0400 Subject: [PATCH 07/42] (#108) Add Sprite2D and simple animation system --- .../fastj/graphics/game/AnimationStyle.java | 7 + .../tech/fastj/graphics/game/Sprite2D.java | 170 ++++++++++++++++++ .../fastj/graphics/game/Sprite2DBuilder.java | 49 +++++ 3 files changed, 226 insertions(+) create mode 100644 src/main/java/tech/fastj/graphics/game/AnimationStyle.java create mode 100644 src/main/java/tech/fastj/graphics/game/Sprite2D.java create mode 100644 src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java diff --git a/src/main/java/tech/fastj/graphics/game/AnimationStyle.java b/src/main/java/tech/fastj/graphics/game/AnimationStyle.java new file mode 100644 index 00000000..d01bebbb --- /dev/null +++ b/src/main/java/tech/fastj/graphics/game/AnimationStyle.java @@ -0,0 +1,7 @@ +package tech.fastj.graphics.game; + +public enum AnimationStyle { + ContinuousLoop, + Static, + PlayUntilEnd +} diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2D.java b/src/main/java/tech/fastj/graphics/game/Sprite2D.java new file mode 100644 index 00000000..1cccde0e --- /dev/null +++ b/src/main/java/tech/fastj/graphics/game/Sprite2D.java @@ -0,0 +1,170 @@ +package tech.fastj.graphics.game; + +import tech.fastj.graphics.util.DrawUtil; + +import tech.fastj.systems.control.Scene; +import tech.fastj.systems.control.SimpleManager; + +import java.awt.Graphics2D; +import java.awt.geom.AffineTransform; +import java.awt.image.BufferedImage; +import java.util.Arrays; +import java.util.Objects; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +public class Sprite2D extends GameObject { + + public static final int DefaultStartingFrame = 0; + public static final int DefaultAnimationFPS = 12; + public static final AnimationStyle DefaultAnimationStyle = AnimationStyle.ContinuousLoop; + + private BufferedImage[] sprites; + private int currentFrame; + private int animationFPS = DefaultAnimationFPS; + private AnimationStyle animationStyle; + + private ScheduledExecutorService spriteAnimator; + + Sprite2D(BufferedImage[] sprites) { + this.sprites = sprites; + setCollisionPath(DrawUtil.createPath(DrawUtil.createBoxFromImage(sprites[0]))); + resetSpriteAnimator(); + } + + public static Sprite2DBuilder create(BufferedImage[] sprites) { + return new Sprite2DBuilder(sprites); + } + + public int getCurrentFrame() { + return currentFrame; + } + + public int getAnimationFPS() { + return animationFPS; + } + + public AnimationStyle getAnimationStyle() { + return animationStyle; + } + + public Sprite2D setCurrentFrame(int currentFrame) { + this.currentFrame = currentFrame; + return this; + } + + public Sprite2D setAnimationFPS(int animationFPS) { + this.animationFPS = animationFPS; + resetSpriteAnimator(); + return this; + } + + public Sprite2D setAnimationStyle(AnimationStyle animationStyle) { + this.animationStyle = animationStyle; + return this; + } + + @Override + public void render(Graphics2D g) { + if (!shouldRender()) { + return; + } + + AffineTransform oldTransform = (AffineTransform) g.getTransform().clone(); + g.transform(getTransformation()); + + g.drawImage(sprites[currentFrame], null, null); + + g.setTransform(oldTransform); + } + + @Override + public void destroy(Scene origin) { + sprites = null; + currentFrame = -1; + animationFPS = -1; + animationStyle = null; + + super.destroyTheRest(origin); + } + + @Override + public void destroy(SimpleManager origin) { + sprites = null; + currentFrame = -1; + animationFPS = -1; + animationStyle = null; + + super.destroyTheRest(origin); + } + + private void resetSpriteAnimator() { + if (spriteAnimator != null) { + spriteAnimator.shutdownNow(); + spriteAnimator = null; + } + + spriteAnimator = Executors.newSingleThreadScheduledExecutor(); + spriteAnimator.scheduleAtFixedRate( + () -> { + switch (animationStyle) { + case Static: { + break; + } + case ContinuousLoop: { + currentFrame++; + if (currentFrame == sprites.length) { + currentFrame = 0; + } + break; + } + case PlayUntilEnd: { + if (currentFrame < sprites.length - 1) { + currentFrame++; + } + break; + } + } + }, + 1000 / animationFPS, + 1000 / animationFPS, + TimeUnit.MILLISECONDS + ); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || getClass() != other.getClass()) { + return false; + } + if (!super.equals(other)) { + return false; + } + Sprite2D sprite2D = (Sprite2D) other; + return currentFrame == sprite2D.currentFrame + && animationFPS == sprite2D.animationFPS + && animationStyle == sprite2D.animationStyle + && Arrays.equals(sprites, sprite2D.sprites); + } + + @Override + public int hashCode() { + int result = Objects.hash(currentFrame, animationFPS, animationStyle); + result = 31 * result + Arrays.hashCode(sprites); + return result; + } + + @Override + public String toString() { + return "Sprite2D{" + + "sprites=" + Arrays.toString(sprites) + + ", currentFrame=" + currentFrame + + ", animationFPS=" + animationFPS + + ", animationStyle=" + animationStyle + + '}'; + } +} diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java b/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java new file mode 100644 index 00000000..5b35cd40 --- /dev/null +++ b/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java @@ -0,0 +1,49 @@ +package tech.fastj.graphics.game; + +import java.awt.image.BufferedImage; +import java.util.Objects; + +public class Sprite2DBuilder { + + private final BufferedImage[] sprites; + private int startingFrame = Sprite2D.DefaultStartingFrame; + private int animationFPS = Sprite2D.DefaultAnimationFPS; + private AnimationStyle animationStyle = Sprite2D.DefaultAnimationStyle; + + Sprite2DBuilder(BufferedImage[] sprites) { + this.sprites = Objects.requireNonNull(sprites, "The array of image sprites must not be null."); + } + + public Sprite2DBuilder withStartingFrame(int startingFrame) { + if (startingFrame < 0) { + throw new IllegalArgumentException("The starting frame value must not be less than 0."); + } + if (startingFrame >= sprites.length) { + throw new IllegalArgumentException("The starting frame value must not be more than the amount of sprite images."); + } + + this.startingFrame = startingFrame; + return this; + } + + public Sprite2DBuilder withAnimationFPS(int animationFPS) { + if (animationFPS < 1) { + throw new IllegalArgumentException("The animation FPS must not be less than 1 FPS."); + } + + this.animationFPS = animationFPS; + return this; + } + + public Sprite2DBuilder withAnimationStyle(AnimationStyle animationStyle) { + this.animationStyle = Objects.requireNonNull(animationStyle, "The animation style must not be null."); + return this; + } + + public Sprite2D build() { + return new Sprite2D(sprites) + .setCurrentFrame(startingFrame) + .setAnimationFPS(animationFPS) + .setAnimationStyle(animationStyle); + } +} From f5a10923ead4d4cf5a4319cb52d49f7e1c6611b6 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 15:48:35 -0400 Subject: [PATCH 08/42] (#113) Add simple implementation of resource manager --- src/main/java/module-info.java | 1 + .../java/tech/fastj/resources/Resource.java | 15 ++++ .../tech/fastj/resources/ResourceManager.java | 80 +++++++++++++++++++ .../tech/fastj/resources/ResourceState.java | 6 ++ 4 files changed, 102 insertions(+) create mode 100644 src/main/java/tech/fastj/resources/Resource.java create mode 100644 src/main/java/tech/fastj/resources/ResourceManager.java create mode 100644 src/main/java/tech/fastj/resources/ResourceState.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 00be9d62..70ca3192 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -21,6 +21,7 @@ exports tech.fastj.engine; exports tech.fastj.math; + exports tech.fastj.resources; exports tech.fastj.graphics; exports tech.fastj.graphics.display; diff --git a/src/main/java/tech/fastj/resources/Resource.java b/src/main/java/tech/fastj/resources/Resource.java new file mode 100644 index 00000000..f146884b --- /dev/null +++ b/src/main/java/tech/fastj/resources/Resource.java @@ -0,0 +1,15 @@ +package tech.fastj.resources; + +import java.nio.file.Path; + +public interface Resource { + ResourceState getResourceState(); + + Path getPath(); + + Resource load(); + + T get(); + + void unload(); +} diff --git a/src/main/java/tech/fastj/resources/ResourceManager.java b/src/main/java/tech/fastj/resources/ResourceManager.java new file mode 100644 index 00000000..54326ec3 --- /dev/null +++ b/src/main/java/tech/fastj/resources/ResourceManager.java @@ -0,0 +1,80 @@ +package tech.fastj.resources; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ConcurrentHashMap; + +public abstract class ResourceManager, V> { + + protected final Map resourceStorage; + protected final Map pathToUUIDMap; + protected final Map idToPathMap; + + public ResourceManager() { + resourceStorage = new ConcurrentHashMap<>(); + pathToUUIDMap = new ConcurrentHashMap<>(); + idToPathMap = new ConcurrentHashMap<>(); + } + + public abstract T createResource(Path resourcePath); + + public List loadResource(Path... resourcePaths) { + List resources = new ArrayList<>(); + Arrays.stream(resourcePaths).parallel().forEach(path -> resources.add(loadResource(path))); + + return resources; + } + + public T loadResource(Path resourcePath) { + return loadResource(pathToId(resourcePath.toAbsolutePath())); + } + + public T getResource(Path resourcePath) { + return getResource(pathToId(resourcePath)); + } + + public T unloadResource(Path resourcePath) { + return unloadResource(pathToId(resourcePath)); + } + + public void unloadAllResources() { + resourceStorage.forEach((path, resource) -> resource.unload()); + } + + @SuppressWarnings("unchecked") + private T loadResource(String resourceId) { + return resourceStorage.compute(resourceId, (id, imageResource) -> { + if (imageResource == null) { + imageResource = createResource(idToPath(resourceId)); + } + + return (T) imageResource.load(); + }); + } + + private T getResource(String resourceId) { + return resourceStorage.computeIfAbsent(resourceId, id -> loadResource(idToPath(resourceId))); + } + + private T unloadResource(String resourceId) { + return resourceStorage.computeIfPresent(resourceId, (id, imageResource) -> { + imageResource.unload(); + return imageResource; + }); + } + + private String pathToId(Path resourcePath) { + UUID uuid = pathToUUIDMap.computeIfAbsent(resourcePath, path -> UUID.randomUUID()); + String id = resourcePath.toAbsolutePath() + uuid.toString(); + idToPathMap.put(id, resourcePath); + return id; + } + + private Path idToPath(String resourceId) { + return idToPathMap.get(resourceId); + } +} diff --git a/src/main/java/tech/fastj/resources/ResourceState.java b/src/main/java/tech/fastj/resources/ResourceState.java new file mode 100644 index 00000000..99020193 --- /dev/null +++ b/src/main/java/tech/fastj/resources/ResourceState.java @@ -0,0 +1,6 @@ +package tech.fastj.resources; + +public enum ResourceState { + Loaded, + Unloaded +} From 5befcde09b437d533965a04c74c7bd1b6d1b83da Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 15:49:18 -0400 Subject: [PATCH 09/42] (#108, #113) Add image resource management --- src/main/java/module-info.java | 1 + .../fastj/graphics/image/ImageResource.java | 56 +++++++++++++++++++ .../graphics/image/ImageResourceManager.java | 13 +++++ 3 files changed, 70 insertions(+) create mode 100644 src/main/java/tech/fastj/graphics/image/ImageResource.java create mode 100644 src/main/java/tech/fastj/graphics/image/ImageResourceManager.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 70ca3192..5b38f6ff 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -27,6 +27,7 @@ exports tech.fastj.graphics.display; exports tech.fastj.graphics.game; exports tech.fastj.graphics.gradients; + exports tech.fastj.graphics.image; exports tech.fastj.graphics.io; exports tech.fastj.graphics.ui; exports tech.fastj.graphics.ui.elements; diff --git a/src/main/java/tech/fastj/graphics/image/ImageResource.java b/src/main/java/tech/fastj/graphics/image/ImageResource.java new file mode 100644 index 00000000..fa74cb5c --- /dev/null +++ b/src/main/java/tech/fastj/graphics/image/ImageResource.java @@ -0,0 +1,56 @@ +package tech.fastj.graphics.image; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.file.Path; + +import tech.fastj.resources.Resource; +import tech.fastj.resources.ResourceState; + +public class ImageResource implements Resource { + + private final Path imagePath; + private ResourceState resourceState; + private BufferedImage imageResource; + + public ImageResource(Path imagePath) { + this.imagePath = imagePath; + resourceState = ResourceState.Unloaded; + } + + @Override + public ResourceState getResourceState() { + return resourceState; + } + + @Override + public Path getPath() { + return imagePath; + } + + @Override + public ImageResource load() { + Path absoluteResourcePath = imagePath.toAbsolutePath(); + + try { + imageResource = ImageIO.read(imagePath.toAbsolutePath().toFile()); + resourceState = ResourceState.Loaded; + return this; + } catch (IOException exception) { + throw new IllegalStateException("Couldn't load the image at path \"" + absoluteResourcePath + "\".", exception); + } + } + + @Override + public BufferedImage get() { + return imageResource; + } + + @Override + public void unload() { + imageResource.flush(); + imageResource = null; + resourceState = ResourceState.Unloaded; + } +} diff --git a/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java b/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java new file mode 100644 index 00000000..156a39aa --- /dev/null +++ b/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java @@ -0,0 +1,13 @@ +package tech.fastj.graphics.image; + +import java.awt.image.BufferedImage; +import java.nio.file.Path; + +import tech.fastj.resources.ResourceManager; + +public class ImageResourceManager extends ResourceManager { + @Override + public ImageResource createResource(Path resourcePath) { + return new ImageResource(resourcePath); + } +} From 60df1b589cf337990afd8f575990df8acaa6350e Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 16:28:36 -0400 Subject: [PATCH 10/42] small exception message change --- src/main/java/tech/fastj/graphics/image/ImageResource.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/graphics/image/ImageResource.java b/src/main/java/tech/fastj/graphics/image/ImageResource.java index fa74cb5c..d0bd4771 100644 --- a/src/main/java/tech/fastj/graphics/image/ImageResource.java +++ b/src/main/java/tech/fastj/graphics/image/ImageResource.java @@ -38,7 +38,7 @@ public ImageResource load() { resourceState = ResourceState.Loaded; return this; } catch (IOException exception) { - throw new IllegalStateException("Couldn't load the image at path \"" + absoluteResourcePath + "\".", exception); + throw new IllegalStateException("A file was not found at \"" + absoluteResourcePath + "\".", exception); } } From ab30fc9e747a520b094153242c826c2f9a51bbc0 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 16:47:25 -0400 Subject: [PATCH 11/42] small exception message/variable name changes --- .../tech/fastj/graphics/util/ImageUtil.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/graphics/util/ImageUtil.java index 397c7101..92775c8a 100644 --- a/src/main/java/tech/fastj/graphics/util/ImageUtil.java +++ b/src/main/java/tech/fastj/graphics/util/ImageUtil.java @@ -38,22 +38,23 @@ public static BufferedImage createBufferedImage(int width, int height) { ); } - public static BufferedImage loadBufferedImage(Path pathToImage) { + public static BufferedImage loadBufferedImage(Path imagePath) { + Path absoluteResourcePath = imagePath.toAbsolutePath(); try { - return ImageIO.read(pathToImage.toAbsolutePath().toFile()); - } catch (IOException e) { - throw new IllegalStateException("Couldn't get the image at \"" + pathToImage.toAbsolutePath() + "\"", e); + return ImageIO.read(absoluteResourcePath.toFile()); + } catch (IOException exception) { + throw new IllegalStateException("An image file was not found at \"" + absoluteResourcePath + "\".", exception); } } - public static void drawToImage(Image reusedImage, Path pathToSecondImage) { + public static void drawToImage(Image reusedImage, Path secondImagePath) { Graphics2D graphics2D = (Graphics2D) reusedImage.getGraphics(); - FastJEngine.log(pathToSecondImage.toAbsolutePath().toString()); + FastJEngine.log(secondImagePath.toAbsolutePath().toString()); Image imageFromPath; try { - imageFromPath = ImageIO.read(pathToSecondImage.toAbsolutePath().toFile()); + imageFromPath = ImageIO.read(secondImagePath.toAbsolutePath().toFile()); } catch (IOException e) { - throw new IllegalStateException("Couldn't get the image at \"" + pathToSecondImage.toAbsolutePath() + "\"", e); + throw new IllegalStateException("Couldn't get the image at \"" + secondImagePath.toAbsolutePath() + "\"", e); } graphics2D.setBackground(new Color(0, 0, 0, 0)); graphics2D.clearRect(0, 0, reusedImage.getWidth(null), reusedImage.getHeight(null)); From 7cf2dc0fe34844cb8ba6ca7d7cec35625adb37e2 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 16:48:38 -0400 Subject: [PATCH 12/42] (#113) Migrate image loading to use ImageUtil --- .../fastj/graphics/image/ImageResource.java | 28 ++++++++----------- .../graphics/image/ImageResourceManager.java | 4 +-- 2 files changed, 13 insertions(+), 19 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/image/ImageResource.java b/src/main/java/tech/fastj/graphics/image/ImageResource.java index d0bd4771..341b6ae2 100644 --- a/src/main/java/tech/fastj/graphics/image/ImageResource.java +++ b/src/main/java/tech/fastj/graphics/image/ImageResource.java @@ -1,18 +1,18 @@ package tech.fastj.graphics.image; -import javax.imageio.ImageIO; -import java.awt.image.BufferedImage; -import java.io.IOException; -import java.nio.file.Path; +import tech.fastj.graphics.util.ImageUtil; import tech.fastj.resources.Resource; import tech.fastj.resources.ResourceState; +import java.awt.image.BufferedImage; +import java.nio.file.Path; + public class ImageResource implements Resource { private final Path imagePath; private ResourceState resourceState; - private BufferedImage imageResource; + private BufferedImage imageFile; public ImageResource(Path imagePath) { this.imagePath = imagePath; @@ -31,26 +31,20 @@ public Path getPath() { @Override public ImageResource load() { - Path absoluteResourcePath = imagePath.toAbsolutePath(); - - try { - imageResource = ImageIO.read(imagePath.toAbsolutePath().toFile()); - resourceState = ResourceState.Loaded; - return this; - } catch (IOException exception) { - throw new IllegalStateException("A file was not found at \"" + absoluteResourcePath + "\".", exception); - } + imageFile = ImageUtil.loadBufferedImage(imagePath); + resourceState = ResourceState.Loaded; + return this; } @Override public BufferedImage get() { - return imageResource; + return imageFile; } @Override public void unload() { - imageResource.flush(); - imageResource = null; + imageFile.flush(); + imageFile = null; resourceState = ResourceState.Unloaded; } } diff --git a/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java b/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java index 156a39aa..3a0f6b69 100644 --- a/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java +++ b/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java @@ -1,10 +1,10 @@ package tech.fastj.graphics.image; +import tech.fastj.resources.ResourceManager; + import java.awt.image.BufferedImage; import java.nio.file.Path; -import tech.fastj.resources.ResourceManager; - public class ImageResourceManager extends ResourceManager { @Override public ImageResource createResource(Path resourcePath) { From 58263925cd268ade5befbe03da0ece11148b7311 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 16:54:22 -0400 Subject: [PATCH 13/42] (#108, #113) Moved images/models to resources package --- .../tech/fastj/example/bullethell/scenes/GameScene.java | 2 +- .../java/tech/fastj/example/modelreadwrite/Main.java | 2 +- src/main/java/module-info.java | 7 ++++--- .../image => resources/images}/ImageResource.java | 4 +--- .../image => resources/images}/ImageResourceManager.java | 2 +- .../{graphics/util => resources/images}/ImageUtil.java | 2 +- .../{graphics/util => resources/models}/ModelUtil.java | 4 +--- .../fastj/{graphics/io => resources/models}/PsdfUtil.java | 2 +- .../io => resources/models}/SupportedModelFormats.java | 2 +- .../java/unittest/testcases/graphics/io/PsdfUtilTests.java | 4 ++-- 10 files changed, 14 insertions(+), 17 deletions(-) rename src/main/java/tech/fastj/{graphics/image => resources/images}/ImageResource.java (92%) rename src/main/java/tech/fastj/{graphics/image => resources/images}/ImageResourceManager.java (90%) rename src/main/java/tech/fastj/{graphics/util => resources/images}/ImageUtil.java (99%) rename src/main/java/tech/fastj/{graphics/util => resources/models}/ModelUtil.java (96%) rename src/main/java/tech/fastj/{graphics/io => resources/models}/PsdfUtil.java (99%) rename src/main/java/tech/fastj/{graphics/io => resources/models}/SupportedModelFormats.java (91%) diff --git a/src/example/java/tech/fastj/example/bullethell/scenes/GameScene.java b/src/example/java/tech/fastj/example/bullethell/scenes/GameScene.java index 05a59cdd..eb2fc67f 100644 --- a/src/example/java/tech/fastj/example/bullethell/scenes/GameScene.java +++ b/src/example/java/tech/fastj/example/bullethell/scenes/GameScene.java @@ -10,7 +10,7 @@ import tech.fastj.graphics.game.Polygon2D; import tech.fastj.graphics.game.Text2D; import tech.fastj.graphics.util.DrawUtil; -import tech.fastj.graphics.util.ModelUtil; +import tech.fastj.resources.models.ModelUtil; import tech.fastj.systems.control.Scene; diff --git a/src/example/java/tech/fastj/example/modelreadwrite/Main.java b/src/example/java/tech/fastj/example/modelreadwrite/Main.java index eb8e7ebd..fcfdf6ce 100644 --- a/src/example/java/tech/fastj/example/modelreadwrite/Main.java +++ b/src/example/java/tech/fastj/example/modelreadwrite/Main.java @@ -5,7 +5,7 @@ import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; import tech.fastj.graphics.util.DrawUtil; -import tech.fastj.graphics.util.ModelUtil; +import tech.fastj.resources.models.ModelUtil; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index 5b38f6ff..ec3ae583 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -21,14 +21,11 @@ exports tech.fastj.engine; exports tech.fastj.math; - exports tech.fastj.resources; exports tech.fastj.graphics; exports tech.fastj.graphics.display; exports tech.fastj.graphics.game; exports tech.fastj.graphics.gradients; - exports tech.fastj.graphics.image; - exports tech.fastj.graphics.io; exports tech.fastj.graphics.ui; exports tech.fastj.graphics.ui.elements; exports tech.fastj.graphics.util; @@ -37,6 +34,10 @@ exports tech.fastj.input.keyboard; exports tech.fastj.input.mouse; + exports tech.fastj.resources; + exports tech.fastj.resources.images; + exports tech.fastj.resources.models; + exports tech.fastj.systems.audio; exports tech.fastj.systems.audio.state; exports tech.fastj.systems.behaviors; diff --git a/src/main/java/tech/fastj/graphics/image/ImageResource.java b/src/main/java/tech/fastj/resources/images/ImageResource.java similarity index 92% rename from src/main/java/tech/fastj/graphics/image/ImageResource.java rename to src/main/java/tech/fastj/resources/images/ImageResource.java index 341b6ae2..19826bbe 100644 --- a/src/main/java/tech/fastj/graphics/image/ImageResource.java +++ b/src/main/java/tech/fastj/resources/images/ImageResource.java @@ -1,6 +1,4 @@ -package tech.fastj.graphics.image; - -import tech.fastj.graphics.util.ImageUtil; +package tech.fastj.resources.images; import tech.fastj.resources.Resource; import tech.fastj.resources.ResourceState; diff --git a/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java b/src/main/java/tech/fastj/resources/images/ImageResourceManager.java similarity index 90% rename from src/main/java/tech/fastj/graphics/image/ImageResourceManager.java rename to src/main/java/tech/fastj/resources/images/ImageResourceManager.java index 3a0f6b69..49822bd8 100644 --- a/src/main/java/tech/fastj/graphics/image/ImageResourceManager.java +++ b/src/main/java/tech/fastj/resources/images/ImageResourceManager.java @@ -1,4 +1,4 @@ -package tech.fastj.graphics.image; +package tech.fastj.resources.images; import tech.fastj.resources.ResourceManager; diff --git a/src/main/java/tech/fastj/graphics/util/ImageUtil.java b/src/main/java/tech/fastj/resources/images/ImageUtil.java similarity index 99% rename from src/main/java/tech/fastj/graphics/util/ImageUtil.java rename to src/main/java/tech/fastj/resources/images/ImageUtil.java index 92775c8a..9aed7b0d 100644 --- a/src/main/java/tech/fastj/graphics/util/ImageUtil.java +++ b/src/main/java/tech/fastj/resources/images/ImageUtil.java @@ -1,4 +1,4 @@ -package tech.fastj.graphics.util; +package tech.fastj.resources.images; import tech.fastj.engine.FastJEngine; diff --git a/src/main/java/tech/fastj/graphics/util/ModelUtil.java b/src/main/java/tech/fastj/resources/models/ModelUtil.java similarity index 96% rename from src/main/java/tech/fastj/graphics/util/ModelUtil.java rename to src/main/java/tech/fastj/resources/models/ModelUtil.java index 03efa2d7..f0fc8342 100644 --- a/src/main/java/tech/fastj/graphics/util/ModelUtil.java +++ b/src/main/java/tech/fastj/resources/models/ModelUtil.java @@ -1,10 +1,8 @@ -package tech.fastj.graphics.util; +package tech.fastj.resources.models; import tech.fastj.engine.CrashMessages; import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; -import tech.fastj.graphics.io.PsdfUtil; -import tech.fastj.graphics.io.SupportedModelFormats; import tech.fastj.systems.fio.FileUtil; diff --git a/src/main/java/tech/fastj/graphics/io/PsdfUtil.java b/src/main/java/tech/fastj/resources/models/PsdfUtil.java similarity index 99% rename from src/main/java/tech/fastj/graphics/io/PsdfUtil.java rename to src/main/java/tech/fastj/resources/models/PsdfUtil.java index 55af4d2b..89df0bd7 100644 --- a/src/main/java/tech/fastj/graphics/io/PsdfUtil.java +++ b/src/main/java/tech/fastj/resources/models/PsdfUtil.java @@ -1,4 +1,4 @@ -package tech.fastj.graphics.io; +package tech.fastj.resources.models; import tech.fastj.engine.CrashMessages; import tech.fastj.engine.FastJEngine; diff --git a/src/main/java/tech/fastj/graphics/io/SupportedModelFormats.java b/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java similarity index 91% rename from src/main/java/tech/fastj/graphics/io/SupportedModelFormats.java rename to src/main/java/tech/fastj/resources/models/SupportedModelFormats.java index 07fd3844..55fea719 100644 --- a/src/main/java/tech/fastj/graphics/io/SupportedModelFormats.java +++ b/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java @@ -1,4 +1,4 @@ -package tech.fastj.graphics.io; +package tech.fastj.resources.models; import java.util.Arrays; diff --git a/src/test/java/unittest/testcases/graphics/io/PsdfUtilTests.java b/src/test/java/unittest/testcases/graphics/io/PsdfUtilTests.java index 6f67e81f..944a01d9 100644 --- a/src/test/java/unittest/testcases/graphics/io/PsdfUtilTests.java +++ b/src/test/java/unittest/testcases/graphics/io/PsdfUtilTests.java @@ -6,9 +6,9 @@ import tech.fastj.graphics.game.Polygon2D; import tech.fastj.graphics.game.RenderStyle; import tech.fastj.graphics.gradients.Gradients; -import tech.fastj.graphics.io.SupportedModelFormats; +import tech.fastj.resources.models.SupportedModelFormats; import tech.fastj.graphics.util.DrawUtil; -import tech.fastj.graphics.util.ModelUtil; +import tech.fastj.resources.models.ModelUtil; import java.awt.BasicStroke; import java.awt.Color; From f35b4ef07ff6b3eb4486c934c92ca72de092b9f9 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 16:58:42 -0400 Subject: [PATCH 14/42] moved FileUtil to package resources.files --- src/main/java/module-info.java | 2 +- .../tech/fastj/{systems/fio => resources/files}/FileUtil.java | 2 +- src/main/java/tech/fastj/resources/models/ModelUtil.java | 2 +- src/main/java/tech/fastj/systems/audio/AudioManager.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/tech/fastj/{systems/fio => resources/files}/FileUtil.java (95%) diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index ec3ae583..c968dab7 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -35,6 +35,7 @@ exports tech.fastj.input.mouse; exports tech.fastj.resources; + exports tech.fastj.resources.files; exports tech.fastj.resources.images; exports tech.fastj.resources.models; @@ -42,6 +43,5 @@ exports tech.fastj.systems.audio.state; exports tech.fastj.systems.behaviors; exports tech.fastj.systems.control; - exports tech.fastj.systems.fio; exports tech.fastj.systems.tags; } diff --git a/src/main/java/tech/fastj/systems/fio/FileUtil.java b/src/main/java/tech/fastj/resources/files/FileUtil.java similarity index 95% rename from src/main/java/tech/fastj/systems/fio/FileUtil.java rename to src/main/java/tech/fastj/resources/files/FileUtil.java index 39e563b9..8fce33a4 100644 --- a/src/main/java/tech/fastj/systems/fio/FileUtil.java +++ b/src/main/java/tech/fastj/resources/files/FileUtil.java @@ -1,4 +1,4 @@ -package tech.fastj.systems.fio; +package tech.fastj.resources.files; import java.nio.file.Path; diff --git a/src/main/java/tech/fastj/resources/models/ModelUtil.java b/src/main/java/tech/fastj/resources/models/ModelUtil.java index f0fc8342..31c15350 100644 --- a/src/main/java/tech/fastj/resources/models/ModelUtil.java +++ b/src/main/java/tech/fastj/resources/models/ModelUtil.java @@ -4,7 +4,7 @@ import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; -import tech.fastj.systems.fio.FileUtil; +import tech.fastj.resources.files.FileUtil; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/tech/fastj/systems/audio/AudioManager.java b/src/main/java/tech/fastj/systems/audio/AudioManager.java index 09e76996..a9d8d577 100644 --- a/src/main/java/tech/fastj/systems/audio/AudioManager.java +++ b/src/main/java/tech/fastj/systems/audio/AudioManager.java @@ -4,7 +4,7 @@ import tech.fastj.engine.FastJEngine; import tech.fastj.systems.audio.state.PlaybackState; -import tech.fastj.systems.fio.FileUtil; +import tech.fastj.resources.files.FileUtil; import javax.sound.sampled.*; import java.io.IOException; From cfe487881e9668e8d8bc781562ceff38b8d7dda8 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 21:47:36 -0400 Subject: [PATCH 15/42] small formatting fixes --- src/main/java/tech/fastj/engine/FastJEngine.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index af8940fd..256ddd30 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -204,8 +204,7 @@ public static void configureHardwareAcceleration(HWAccel hardwareAcceleration) { private static boolean isSystemSupportingHA(HWAccel hardwareAcceleration) { if (hardwareAcceleration.equals(HWAccel.Direct3D)) { return System.getProperty("os.name").startsWith("Win"); - } - else if (hardwareAcceleration.equals(HWAccel.X11)) { + } else if (hardwareAcceleration.equals(HWAccel.X11)) { return System.getProperty("os.name").startsWith("Linux"); } return true; @@ -307,7 +306,6 @@ public static void setTargetUPS(int ups) { * In both situations, the game engine will be closed via {@link FastJEngine#forceCloseGame()} beforehand. * * @param shouldThrowExceptions The {@code boolean} to set whether exceptions should be thrown. - * * @since 1.5.0 */ public static void setShouldThrowExceptions(boolean shouldThrowExceptions) { @@ -370,7 +368,7 @@ public static void run() { if (shouldThrowExceptions) { throw exception; } else { - exception.printStackTrace(); + exception.fillInStackTrace().printStackTrace(); } } } @@ -440,7 +438,6 @@ public static void error(T errorMessage, Exception exception) { * otherwise, such as adding a game object to a scene while in an {@link LogicManager#update(Display)} call. * * @param action Disposable action to be run after the next {@link LogicManager#update(Display)} call. - * * @since 1.4.0 */ public static void runAfterUpdate(Runnable action) { @@ -454,7 +451,6 @@ public static void runAfterUpdate(Runnable action) { * otherwise, such as adding a game object to a scene while in an {@link LogicManager#update(Display)} call. * * @param action Disposable action to be run after the next {@link LogicManager#render(Display)} call. - * * @since 1.5.0 */ public static void runAfterRender(Runnable action) { From 2c276b0847adb651fd158b0b0e579f98c4880897 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 21:50:04 -0400 Subject: [PATCH 16/42] add shutdown hooks for the sprite animator --- src/main/java/tech/fastj/graphics/game/Sprite2D.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2D.java b/src/main/java/tech/fastj/graphics/game/Sprite2D.java index 1cccde0e..f6e1cfc0 100644 --- a/src/main/java/tech/fastj/graphics/game/Sprite2D.java +++ b/src/main/java/tech/fastj/graphics/game/Sprite2D.java @@ -81,6 +81,7 @@ public void render(Graphics2D g) { @Override public void destroy(Scene origin) { + spriteAnimator.shutdownNow(); sprites = null; currentFrame = -1; animationFPS = -1; @@ -91,6 +92,7 @@ public void destroy(Scene origin) { @Override public void destroy(SimpleManager origin) { + spriteAnimator.shutdownNow(); sprites = null; currentFrame = -1; animationFPS = -1; From c70edba92edd49fc7299b1cc2830d29e336bf1d4 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 21:50:57 -0400 Subject: [PATCH 17/42] added DrawableManager.destroyGameObject/UIElement/AllLists to handle destroying Drawables in DrawableManager --- .../systems/control/DrawableManager.java | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/main/java/tech/fastj/systems/control/DrawableManager.java b/src/main/java/tech/fastj/systems/control/DrawableManager.java index 3213ea02..6f6730d0 100644 --- a/src/main/java/tech/fastj/systems/control/DrawableManager.java +++ b/src/main/java/tech/fastj/systems/control/DrawableManager.java @@ -72,6 +72,18 @@ public void removeGameObject(GameObject gameObject) { removeGameObject(gameObject.getID()); } + public void destroyGameObjects(SimpleManager manager) { + for (GameObject gameObject : gameObjects.values()) { + gameObject.destroy(manager); + } + } + + public void destroyGameObjects(Scene scene) { + for (GameObject gameObject : gameObjects.values()) { + gameObject.destroy(scene); + } + } + /** Removes any null values from the list of game objects for the manager. */ public void refreshGameObjectList() { gameObjects.entrySet().removeIf(Objects::isNull); @@ -111,6 +123,18 @@ public void removeUIElement(UIElement guiObject) { removeUIElement(guiObject.getID()); } + public void destroyUIElements(SimpleManager manager) { + for (UIElement uiElement : uiElements.values()) { + uiElement.destroy(manager); + } + } + + public void destroyUIElements(Scene scene) { + for (UIElement uiElement : uiElements.values()) { + uiElement.destroy(scene); + } + } + /** Removes any null values from the list of ui elements for the manager. */ public void refreshUIElementList() { uiElements.entrySet().removeIf(Objects::isNull); @@ -123,6 +147,16 @@ public void clearUIElements() { /* reset */ + public void destroyAllLists(Scene scene) { + destroyGameObjects(scene); + destroyUIElements(scene); + } + + public void destroyAllLists(SimpleManager manager) { + destroyGameObjects(manager); + destroyUIElements(manager); + } + /** Removes all game objects and ui elements from the manager. */ public void clearAllLists() { clearGameObjects(); From 3cafc887f34e4178fad7ccdb3a64460756589cd0 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 21:51:43 -0400 Subject: [PATCH 18/42] (#114) Added missing call to Scene.reset Bug Fixes: - Added missing call to `Scene.reset` for each scene in `SceneManager` during a call to `SceneManager.reset`. --- src/main/java/tech/fastj/systems/control/SceneManager.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/tech/fastj/systems/control/SceneManager.java b/src/main/java/tech/fastj/systems/control/SceneManager.java index 545572b2..c81cbb43 100644 --- a/src/main/java/tech/fastj/systems/control/SceneManager.java +++ b/src/main/java/tech/fastj/systems/control/SceneManager.java @@ -71,10 +71,11 @@ public void receivedInputEvent(InputEvent inputEvent) { /** Resets the logic manager. */ @Override public void reset() { - for (Scene s : scenes.values()) { - if (s.isInitialized()) { - s.unload(FastJEngine.getDisplay()); + for (Scene scene : scenes.values()) { + if (scene.isInitialized()) { + scene.unload(FastJEngine.getDisplay()); } + scene.reset(); } scenes.clear(); } From d9fb04edb0976c214b14acc1229863e4605e9859 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 21:58:45 -0400 Subject: [PATCH 19/42] (#115) Added calls to destroy Drawables in Scene/SimpleManager --- src/main/java/tech/fastj/systems/control/Scene.java | 1 + .../java/tech/fastj/systems/control/SimpleManager.java | 7 ++++--- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/tech/fastj/systems/control/Scene.java b/src/main/java/tech/fastj/systems/control/Scene.java index eb7a6ac7..70b70f38 100644 --- a/src/main/java/tech/fastj/systems/control/Scene.java +++ b/src/main/java/tech/fastj/systems/control/Scene.java @@ -123,6 +123,7 @@ public void clearAllLists() { public void reset() { this.setInitialized(false); this.destroyBehaviorListeners(); + drawableManager.destroyAllLists(this); this.clearAllLists(); camera.reset(); } diff --git a/src/main/java/tech/fastj/systems/control/SimpleManager.java b/src/main/java/tech/fastj/systems/control/SimpleManager.java index 50fe395a..832007e7 100644 --- a/src/main/java/tech/fastj/systems/control/SimpleManager.java +++ b/src/main/java/tech/fastj/systems/control/SimpleManager.java @@ -86,11 +86,12 @@ public Camera getCamera() { @Override public void reset() { - camera.reset(); this.destroyBehaviorListeners(); - inputManager.clearAllLists(); + drawableManager.destroyAllLists(this); + this.clearBehaviorListeners(); drawableManager.clearAllLists(); + inputManager.clearAllLists(); this.clearTaggableEntities(); - this.clearBehaviorListeners(); + camera.reset(); } } From bf2197e1b6781d4b08f8b8f820f6b6a02fd77acd Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 22 Aug 2021 22:01:44 -0400 Subject: [PATCH 20/42] (#113) Add resource manager handling New Additions: - `ResourceManager` constant to store all resource managers -- one instance per manager class. - `FastJEngine.addResourceManager` -- method to add a manager of a specific type (the resource type must also be specified) - `FastJEngine.getResourceManager` -- mwthod to get a manager of a specific type --- .../java/tech/fastj/engine/FastJEngine.java | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index 256ddd30..e811177c 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -8,6 +8,8 @@ import tech.fastj.input.keyboard.Keyboard; import tech.fastj.input.mouse.Mouse; +import tech.fastj.resources.Resource; +import tech.fastj.resources.ResourceManager; import tech.fastj.systems.audio.AudioManager; import tech.fastj.systems.audio.StreamedAudioPlayer; import tech.fastj.systems.behaviors.BehaviorManager; @@ -16,7 +18,9 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -73,6 +77,9 @@ public class FastJEngine { private static final List AfterUpdateList = new ArrayList<>(); private static final List AfterRenderList = new ArrayList<>(); + // Resources + private static final Map>, ResourceManager, ?>> ResourceManagers = new HashMap<>(); + private FastJEngine() { throw new java.lang.IllegalStateException(); } @@ -357,6 +364,18 @@ public static double getFPSData(FPSValue dataType) { } } + @SuppressWarnings("unchecked") + public static , T extends ResourceManager> void addResourceManager(T resourceManager, Class resourceClass) { + ResourceManagers.put((Class>) resourceClass, (ResourceManager, ?>) resourceManager); + } + + @SuppressWarnings("unchecked") + public static , T extends ResourceManager> T getResourceManager(Class resourceClass) { + return (T) ResourceManagers.computeIfAbsent((Class>) resourceClass, rClass -> { + throw new IllegalStateException("No resource manager was added for the resource type \"" + resourceClass.getTypeName() + "\"."); + }); + } + /** Runs the game. */ public static void run() { initEngine(); @@ -557,6 +576,8 @@ private static void exit() { TagManager.reset(); AfterUpdateList.clear(); AfterRenderList.clear(); + ResourceManagers.forEach(((resourceClass, resourceResourceManager) -> resourceResourceManager.unloadAllResources())); + ResourceManagers.clear(); // engine speed variables targetFPS = 0; From d527a93d53083a81b20f86eeca5b02d1b6caee7e Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 12:06:04 -0400 Subject: [PATCH 21/42] (#113) added default resource managers --- src/main/java/tech/fastj/engine/FastJEngine.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index e811177c..3e05cd7b 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -10,6 +10,8 @@ import tech.fastj.input.mouse.Mouse; import tech.fastj.resources.Resource; import tech.fastj.resources.ResourceManager; +import tech.fastj.resources.images.ImageResource; +import tech.fastj.resources.images.ImageResourceManager; import tech.fastj.systems.audio.AudioManager; import tech.fastj.systems.audio.StreamedAudioPlayer; import tech.fastj.systems.behaviors.BehaviorManager; @@ -127,6 +129,11 @@ public static void init(String gameTitle, LogicManager gameManager, int fps, int fpsLogger = Executors.newSingleThreadScheduledExecutor(); configure(fps, ups, windowResolution, internalResolution, hardwareAcceleration); + addDefaultResourceManagers(); + } + + private static void addDefaultResourceManagers() { + addResourceManager(new ImageResourceManager(), ImageResource.class); } /** From dbf4dd3a93402c23b0eeeecffab278831ca72ad8 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 12:06:58 -0400 Subject: [PATCH 22/42] make sprite animator null after Sprite2D destruction --- src/main/java/tech/fastj/graphics/game/Sprite2D.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2D.java b/src/main/java/tech/fastj/graphics/game/Sprite2D.java index f6e1cfc0..645c1402 100644 --- a/src/main/java/tech/fastj/graphics/game/Sprite2D.java +++ b/src/main/java/tech/fastj/graphics/game/Sprite2D.java @@ -82,6 +82,7 @@ public void render(Graphics2D g) { @Override public void destroy(Scene origin) { spriteAnimator.shutdownNow(); + spriteAnimator = null; sprites = null; currentFrame = -1; animationFPS = -1; From ca33005a215efe38dd912793f7276ecbace2307d Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 12:13:19 -0400 Subject: [PATCH 23/42] (#86) Replaced all HashMaps with ConcurrentHashMap Bug Fixes: - (#86) Fixed issue where occasional `ConcurrentModificationException`s woulc crop up thanks to slight issues with consistent multithreaded/event-based inputs (keyboard, mouse, window, etc). --- src/main/java/tech/fastj/engine/FastJEngine.java | 4 ++-- src/main/java/tech/fastj/input/keyboard/Keyboard.java | 3 ++- .../java/tech/fastj/input/keyboard/KeyboardStateEvent.java | 3 ++- src/main/java/tech/fastj/input/mouse/Mouse.java | 3 ++- src/main/java/tech/fastj/systems/audio/AudioManager.java | 5 +++-- .../java/tech/fastj/systems/behaviors/BehaviorManager.java | 6 ++++-- .../java/tech/fastj/systems/control/DrawableManager.java | 6 ++++-- src/main/java/tech/fastj/systems/control/SceneManager.java | 4 ++-- src/main/java/tech/fastj/systems/tags/TagManager.java | 4 ++-- 9 files changed, 23 insertions(+), 15 deletions(-) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index 3e05cd7b..f6017654 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -20,9 +20,9 @@ import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -80,7 +80,7 @@ public class FastJEngine { private static final List AfterRenderList = new ArrayList<>(); // Resources - private static final Map>, ResourceManager, ?>> ResourceManagers = new HashMap<>(); + private static final Map>, ResourceManager, ?>> ResourceManagers = new ConcurrentHashMap<>(); private FastJEngine() { throw new java.lang.IllegalStateException(); diff --git a/src/main/java/tech/fastj/input/keyboard/Keyboard.java b/src/main/java/tech/fastj/input/keyboard/Keyboard.java index 66aeb7e4..d6010935 100644 --- a/src/main/java/tech/fastj/input/keyboard/Keyboard.java +++ b/src/main/java/tech/fastj/input/keyboard/Keyboard.java @@ -6,6 +6,7 @@ import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -21,7 +22,7 @@ */ public class Keyboard implements KeyListener { - private static final Map Keys = new HashMap<>(); + private static final Map Keys = new ConcurrentHashMap<>(); private static String lastKeyPressed = ""; private static ScheduledExecutorService keyChecker; diff --git a/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java b/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java index b44e87e3..9f307591 100644 --- a/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java +++ b/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java @@ -3,9 +3,10 @@ import java.awt.event.KeyEvent; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; public class KeyboardStateEvent implements KeyboardEvent { - private static final Map KeyboardMap = new HashMap<>(); + private static final Map KeyboardMap = new ConcurrentHashMap<>(); private final KeyEvent keyEvent; private final Keys key; diff --git a/src/main/java/tech/fastj/input/mouse/Mouse.java b/src/main/java/tech/fastj/input/mouse/Mouse.java index f7d721c0..75c8d14d 100644 --- a/src/main/java/tech/fastj/input/mouse/Mouse.java +++ b/src/main/java/tech/fastj/input/mouse/Mouse.java @@ -14,6 +14,7 @@ import java.awt.geom.PathIterator; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; @@ -31,7 +32,7 @@ public class Mouse implements MouseListener, MouseMotionListener, MouseWheelListener { private static final ScheduledExecutorService MouseExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()); - private static final Map MouseButtons = new HashMap<>(); + private static final Map MouseButtons = new ConcurrentHashMap<>(); private static final int InitialMouseButton = -1; private static final int InitialScrollDirection = 0; diff --git a/src/main/java/tech/fastj/systems/audio/AudioManager.java b/src/main/java/tech/fastj/systems/audio/AudioManager.java index a9d8d577..d1d8b05f 100644 --- a/src/main/java/tech/fastj/systems/audio/AudioManager.java +++ b/src/main/java/tech/fastj/systems/audio/AudioManager.java @@ -12,6 +12,7 @@ import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -23,8 +24,8 @@ */ public class AudioManager { - private static final Map MemoryAudioFiles = new HashMap<>(); - private static final Map StreamedAudioFiles = new HashMap<>(); + private static final Map MemoryAudioFiles = new ConcurrentHashMap<>(); + private static final Map StreamedAudioFiles = new ConcurrentHashMap<>(); private static ExecutorService audioEventExecutor = Executors.newWorkStealingPool(); /** diff --git a/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java b/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java index 1ffc0921..b69f50df 100644 --- a/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java +++ b/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java @@ -7,6 +7,8 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; /** * Class to manage behavior listeners for all {@link BehaviorHandler}s. @@ -16,7 +18,7 @@ */ public class BehaviorManager { - private static final Map> BehaviorListenerLists = new HashMap<>(); + private static final Map> BehaviorListenerLists = new ConcurrentHashMap<>(); private BehaviorManager() { throw new java.lang.IllegalStateException(); @@ -62,7 +64,7 @@ public static void removeListener(BehaviorHandler behaviorHandler, GameObject li */ public static void addListenerList(BehaviorHandler behaviorHandler) { if (!BehaviorListenerLists.containsKey(behaviorHandler)) { - BehaviorListenerLists.put(behaviorHandler, new LinkedHashMap<>()); + BehaviorListenerLists.put(behaviorHandler, new ConcurrentHashMap<>()); } } diff --git a/src/main/java/tech/fastj/systems/control/DrawableManager.java b/src/main/java/tech/fastj/systems/control/DrawableManager.java index 6f6730d0..8629bbd3 100644 --- a/src/main/java/tech/fastj/systems/control/DrawableManager.java +++ b/src/main/java/tech/fastj/systems/control/DrawableManager.java @@ -7,6 +7,8 @@ import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; /** * Class to manage {@link Drawable} objects. @@ -21,8 +23,8 @@ public class DrawableManager { /** Initializes a {@code DrawableManager}'s internals. */ public DrawableManager() { - gameObjects = new LinkedHashMap<>(); - uiElements = new LinkedHashMap<>(); + gameObjects = new ConcurrentHashMap<>(); + uiElements = new ConcurrentHashMap<>(); } /** diff --git a/src/main/java/tech/fastj/systems/control/SceneManager.java b/src/main/java/tech/fastj/systems/control/SceneManager.java index c81cbb43..f9d65870 100644 --- a/src/main/java/tech/fastj/systems/control/SceneManager.java +++ b/src/main/java/tech/fastj/systems/control/SceneManager.java @@ -6,9 +6,9 @@ import java.awt.event.InputEvent; import java.util.Collections; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; /** * The manager which allows for control over the scenes in a game. @@ -18,7 +18,7 @@ */ public abstract class SceneManager implements LogicManager { - private final Map scenes = new LinkedHashMap<>(); + private final Map scenes = new ConcurrentHashMap<>(); private Scene currentScene; private boolean switchingScenes; diff --git a/src/main/java/tech/fastj/systems/tags/TagManager.java b/src/main/java/tech/fastj/systems/tags/TagManager.java index 4514d3dd..bd1a2d8f 100644 --- a/src/main/java/tech/fastj/systems/tags/TagManager.java +++ b/src/main/java/tech/fastj/systems/tags/TagManager.java @@ -3,9 +3,9 @@ import tech.fastj.graphics.Drawable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; /** @@ -17,7 +17,7 @@ public class TagManager { private static final List MasterTagList = new ArrayList<>(); - private static final Map> EntityLists = new HashMap<>(); + private static final Map> EntityLists = new ConcurrentHashMap<>(); private TagManager() { throw new java.lang.IllegalStateException(); From 5d227f3ea36473083d76fb97facf957d93d9c4f1 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 18:38:35 -0400 Subject: [PATCH 24/42] (#110) add TexturePaint builder --- src/main/java/module-info.java | 1 + .../graphics/textures/TextureBuilder.java | 35 +++++++++++++++++++ .../fastj/graphics/textures/Textures.java | 16 +++++++++ 3 files changed, 52 insertions(+) create mode 100644 src/main/java/tech/fastj/graphics/textures/TextureBuilder.java create mode 100644 src/main/java/tech/fastj/graphics/textures/Textures.java diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java index c968dab7..bfd555b0 100644 --- a/src/main/java/module-info.java +++ b/src/main/java/module-info.java @@ -26,6 +26,7 @@ exports tech.fastj.graphics.display; exports tech.fastj.graphics.game; exports tech.fastj.graphics.gradients; + exports tech.fastj.graphics.textures; exports tech.fastj.graphics.ui; exports tech.fastj.graphics.ui.elements; exports tech.fastj.graphics.util; diff --git a/src/main/java/tech/fastj/graphics/textures/TextureBuilder.java b/src/main/java/tech/fastj/graphics/textures/TextureBuilder.java new file mode 100644 index 00000000..a56a7abb --- /dev/null +++ b/src/main/java/tech/fastj/graphics/textures/TextureBuilder.java @@ -0,0 +1,35 @@ +package tech.fastj.graphics.textures; + +import tech.fastj.engine.FastJEngine; + +import tech.fastj.resources.images.ImageResource; + +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.nio.file.Path; +import java.util.Objects; + +public class TextureBuilder { + + private final BufferedImage texture; + private final Rectangle2D textureLocation; + + TextureBuilder(BufferedImage texture, Rectangle2D textureLocation) { + this.texture = Objects.requireNonNull(texture, "The provided texture image must not be null."); + this.textureLocation = Objects.requireNonNull(textureLocation, "The provided texture location must not be null."); + } + + public TexturePaint build() { + return new TexturePaint(texture, textureLocation); + } + + static TextureBuilder builder(BufferedImage texture, Rectangle2D textureLocation) { + return new TextureBuilder(texture, textureLocation); + } + + static TextureBuilder builder(Path texturePath, Rectangle2D textureLocation) { + BufferedImage texture = FastJEngine.getResourceManager(ImageResource.class).getResource(texturePath).get(); + return new TextureBuilder(texture, textureLocation); + } +} diff --git a/src/main/java/tech/fastj/graphics/textures/Textures.java b/src/main/java/tech/fastj/graphics/textures/Textures.java new file mode 100644 index 00000000..bc46ba54 --- /dev/null +++ b/src/main/java/tech/fastj/graphics/textures/Textures.java @@ -0,0 +1,16 @@ +package tech.fastj.graphics.textures; + +import java.awt.TexturePaint; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.nio.file.Path; + +public class Textures { + public static TexturePaint create(Path texturePath, Rectangle2D textureLocation) { + return TextureBuilder.builder(texturePath, textureLocation).build(); + } + + public static TexturePaint create(BufferedImage texture, Rectangle2D textureLocation) { + return TextureBuilder.builder(texture, textureLocation).build(); + } +} From e60f3fbe0bce4e908e6085520a20a85dbcf613c5 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 22:05:37 -0400 Subject: [PATCH 25/42] (#113) add method to get path of resource, change loadResource to non-compute method --- .../tech/fastj/resources/ResourceManager.java | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/main/java/tech/fastj/resources/ResourceManager.java b/src/main/java/tech/fastj/resources/ResourceManager.java index 54326ec3..58f1bdec 100644 --- a/src/main/java/tech/fastj/resources/ResourceManager.java +++ b/src/main/java/tech/fastj/resources/ResourceManager.java @@ -7,6 +7,7 @@ import java.util.Map; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.atomic.AtomicReference; public abstract class ResourceManager, V> { @@ -29,6 +30,21 @@ public List loadResource(Path... resourcePaths) { return resources; } + public Path tryFindPathOfResource(V rawResource) { + AtomicReference resultingPath = new AtomicReference<>(); + resourceStorage.forEach((id, resource) -> { + if (resource.get().equals(rawResource)) { + resultingPath.set(idToPath(id)); + } + }); + + if (resultingPath.get() == null) { + throw new IllegalArgumentException("Couldn't find a matching path for resource " + rawResource); + } + + return resultingPath.get(); + } + public T loadResource(Path resourcePath) { return loadResource(pathToId(resourcePath.toAbsolutePath())); } @@ -47,13 +63,12 @@ public void unloadAllResources() { @SuppressWarnings("unchecked") private T loadResource(String resourceId) { - return resourceStorage.compute(resourceId, (id, imageResource) -> { - if (imageResource == null) { - imageResource = createResource(idToPath(resourceId)); - } + T imageResource = resourceStorage.get(resourceId); + if (imageResource == null) { + imageResource = createResource(idToPath(resourceId)); + } - return (T) imageResource.load(); - }); + return (T) imageResource.load(); } private T getResource(String resourceId) { From 23900b78af17119ebb918d266a18771e8dac130d Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 22:06:37 -0400 Subject: [PATCH 26/42] (#110) support TexturePaint in PsdfUtil parsing/writing --- .../tech/fastj/resources/models/PsdfUtil.java | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/resources/models/PsdfUtil.java b/src/main/java/tech/fastj/resources/models/PsdfUtil.java index 89df0bd7..a01fbe20 100644 --- a/src/main/java/tech/fastj/resources/models/PsdfUtil.java +++ b/src/main/java/tech/fastj/resources/models/PsdfUtil.java @@ -11,17 +11,23 @@ import tech.fastj.graphics.gradients.Gradients; import tech.fastj.graphics.gradients.LinearGradientBuilder; import tech.fastj.graphics.gradients.RadialGradientBuilder; +import tech.fastj.graphics.textures.Textures; +import tech.fastj.graphics.util.DrawUtil; + +import tech.fastj.resources.images.ImageResource; import java.awt.BasicStroke; import java.awt.Color; import java.awt.LinearGradientPaint; import java.awt.Paint; import java.awt.RadialGradientPaint; +import java.awt.TexturePaint; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class PsdfUtil { @@ -47,6 +53,7 @@ public static Polygon2D[] parse(List lines) { RenderStyle renderStyle = Polygon2D.DefaultRenderStyle; Paint fillPaint = Polygon2D.DefaultFill; + String texturePath = ""; BasicStroke outlineStroke = Polygon2D.DefaultOutlineStroke; Color outlineColor = Polygon2D.DefaultOutlineColor; @@ -67,6 +74,11 @@ public static Polygon2D[] parse(List lines) { fillPaint = parsePaint(tokens); break; } + case ParsingKeys.FillPaintTexture: { + System.out.println("texture!"); + texturePath = parseTexture(tokens); + break; + } case ParsingKeys.OutlineStroke: { outlineStroke = parseOutlineStroke(tokens); break; @@ -95,18 +107,25 @@ public static Polygon2D[] parse(List lines) { // if end of polygon, add polygon to array if (tokens.length == 4 && tokens[3].equals(";")) { assert polygons != null; + polygons[polygonsIndex] = Polygon2D.create(polygonPoints.toArray(new Pointf[0]), renderStyle, shouldRender) - .withFill(fillPaint) .withOutline(outlineStroke, outlineColor) .withTransform(translation, rotation, scale) .build(); + if (!texturePath.isBlank()) { + fillPaint = Textures.create(Path.of(texturePath), DrawUtil.createRect(polygons[polygonsIndex].getBounds())); + } + + polygons[polygonsIndex].setFill(fillPaint); + // reset values polygonPoints.clear(); shouldRender = Drawable.DefaultShouldRender; renderStyle = Polygon2D.DefaultRenderStyle; fillPaint = Polygon2D.DefaultFill; + texturePath = ""; outlineStroke = Polygon2D.DefaultOutlineStroke; outlineColor = Polygon2D.DefaultOutlineColor; @@ -195,6 +214,31 @@ private static Paint parsePaint(String[] tokens) { } } + private static String parseTexture(String[] tokens) { + StringBuilder pathBuilder = new StringBuilder(); + + if (!tokens[1].startsWith("\"") || !tokens[tokens.length - 1].endsWith("\"")) { + throw new IllegalArgumentException( + "The given path " + Arrays.toString(tokens) + " does not start and end with quotation marks." + ); + } + + if (tokens.length == 2) { + pathBuilder.append(tokens[1], 1, tokens[1].length() - 1); + } else if (tokens.length == 3) { + pathBuilder.append(tokens[1], 1, tokens.length); + pathBuilder.append(tokens[2], 2, tokens.length - 1); + } else { + pathBuilder.append(tokens[1], 1, tokens.length); + for (int i = 2; i < tokens.length - 1; i++) { + pathBuilder.append(tokens[i]); + } + pathBuilder.append(tokens[tokens.length - 1], 0, tokens.length - 1); + } + + return pathBuilder.toString(); + } + private static BasicStroke parseOutlineStroke(String[] tokens) { int basicStrokeCap; switch (Integer.parseInt(tokens[2])) { @@ -338,6 +382,8 @@ private static void writeFill(StringBuilder fileContents, Paint paint) { writeFillRadialGradient(fileContents, (RadialGradientPaint) paint); } else if (paint instanceof Color) { writeFillColor(fileContents, (Color) paint); + } else if (paint instanceof TexturePaint) { + writeTexture(fileContents, (TexturePaint) paint); } else { FastJEngine.error( CrashMessages.UnimplementedMethodError.errorMessage, @@ -414,6 +460,14 @@ private static void writeFillColor(StringBuilder fileContents, Color color) { .append(color.getAlpha()); } + private static void writeTexture(StringBuilder fileContents, TexturePaint texturePaint) { + fileContents.append(ParsingKeys.FillPaintTexture) + .append(' ') + .append('\"') + .append(FastJEngine.getResourceManager(ImageResource.class).tryFindPathOfResource(texturePaint.getImage()).toString()) + .append('\"'); + } + private static void writeOutline(StringBuilder fileContents, BasicStroke outlineStroke, Color outlineColor) { fileContents.append(LineSeparator) .append(PsdfUtil.ParsingKeys.OutlineStroke) @@ -488,6 +542,7 @@ private ParsingKeys() { public static final String FillPaintColor = "c"; public static final String FillPaintLinearGradient = "lg"; public static final String FillPaintRadialGradient = "rg"; + public static final String FillPaintTexture = "tx"; public static final String OutlineStroke = "otls"; public static final String OutlineColor = "otlc"; public static final String Transform = "tfm"; From 44fdff0969f56551a12ef0193a3412b416f06c25 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Fri, 27 Aug 2021 22:31:36 -0400 Subject: [PATCH 27/42] remove stray print --- src/main/java/tech/fastj/resources/models/PsdfUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/tech/fastj/resources/models/PsdfUtil.java b/src/main/java/tech/fastj/resources/models/PsdfUtil.java index a01fbe20..b39e10c7 100644 --- a/src/main/java/tech/fastj/resources/models/PsdfUtil.java +++ b/src/main/java/tech/fastj/resources/models/PsdfUtil.java @@ -75,7 +75,6 @@ public static Polygon2D[] parse(List lines) { break; } case ParsingKeys.FillPaintTexture: { - System.out.println("texture!"); texturePath = parseTexture(tokens); break; } From 8dc9137a8bc6bf096274125a86517a93ac6dff20 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:15:58 -0400 Subject: [PATCH 28/42] (#113) Use ImageResource to back raw BufferedImage --- .../tech/fastj/graphics/game/Sprite2D.java | 27 ++++++++++++++--- .../fastj/graphics/game/Sprite2DBuilder.java | 30 +++++++++++++++---- 2 files changed, 47 insertions(+), 10 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2D.java b/src/main/java/tech/fastj/graphics/game/Sprite2D.java index 645c1402..aa958f92 100644 --- a/src/main/java/tech/fastj/graphics/game/Sprite2D.java +++ b/src/main/java/tech/fastj/graphics/game/Sprite2D.java @@ -2,6 +2,8 @@ import tech.fastj.graphics.util.DrawUtil; +import tech.fastj.resources.images.ImageResource; +import tech.fastj.resources.images.ImageUtil; import tech.fastj.systems.control.Scene; import tech.fastj.systems.control.SimpleManager; @@ -19,7 +21,10 @@ public class Sprite2D extends GameObject { public static final int DefaultStartingFrame = 0; public static final int DefaultAnimationFPS = 12; public static final AnimationStyle DefaultAnimationStyle = AnimationStyle.ContinuousLoop; + public static final int DefaultHorizontalImageCount = 1; + public static final int DefaultVerticalImageCount = 1; + private ImageResource spritesResource; private BufferedImage[] sprites; private int currentFrame; private int animationFPS = DefaultAnimationFPS; @@ -27,14 +32,24 @@ public class Sprite2D extends GameObject { private ScheduledExecutorService spriteAnimator; - Sprite2D(BufferedImage[] sprites) { - this.sprites = sprites; + Sprite2D(ImageResource spritesResource, int horizontalImageCount, int verticalImageCount) { + this.spritesResource = spritesResource; setCollisionPath(DrawUtil.createPath(DrawUtil.createBoxFromImage(sprites[0]))); + resetSpriteSheet(horizontalImageCount, verticalImageCount); resetSpriteAnimator(); } - public static Sprite2DBuilder create(BufferedImage[] sprites) { - return new Sprite2DBuilder(sprites); + public static Sprite2DBuilder create(ImageResource spritesResource) { + return new Sprite2DBuilder(spritesResource); + } + + public static Sprite2D fromImageResource(ImageResource spritesResource) { + return new Sprite2DBuilder(spritesResource).build(); + } + + public void changeSpriteResource(ImageResource spritesResource, int horizontalImageCount, int verticalImageCount) { + this.spritesResource = spritesResource; + resetSpriteSheet(horizontalImageCount, verticalImageCount); } public int getCurrentFrame() { @@ -102,6 +117,10 @@ public void destroy(SimpleManager origin) { super.destroyTheRest(origin); } + private void resetSpriteSheet(int horizontalImageCount, int verticalImageCount) { + sprites = ImageUtil.createSpriteSheet(this.spritesResource.get(), horizontalImageCount, verticalImageCount); + } + private void resetSpriteAnimator() { if (spriteAnimator != null) { spriteAnimator.shutdownNow(); diff --git a/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java b/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java index 5b35cd40..ef2a7c37 100644 --- a/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java +++ b/src/main/java/tech/fastj/graphics/game/Sprite2DBuilder.java @@ -1,24 +1,42 @@ package tech.fastj.graphics.game; -import java.awt.image.BufferedImage; +import tech.fastj.resources.images.ImageResource; + import java.util.Objects; public class Sprite2DBuilder { - private final BufferedImage[] sprites; + private final ImageResource spriteResource; + private int startingFrame = Sprite2D.DefaultStartingFrame; private int animationFPS = Sprite2D.DefaultAnimationFPS; + private int horizontalImageCount = Sprite2D.DefaultHorizontalImageCount; + private int verticalImageCount = Sprite2D.DefaultVerticalImageCount; private AnimationStyle animationStyle = Sprite2D.DefaultAnimationStyle; - Sprite2DBuilder(BufferedImage[] sprites) { - this.sprites = Objects.requireNonNull(sprites, "The array of image sprites must not be null."); + Sprite2DBuilder(ImageResource spriteResource) { + this.spriteResource = Objects.requireNonNull(spriteResource, "The sprite resource instance must not be null."); + } + + public Sprite2DBuilder withImageCount(int horizontalImageCount, int verticalImageCount) { + if (horizontalImageCount < 1) { + throw new IllegalArgumentException("The given horizontal image count must not be less than 1."); + } + if (verticalImageCount < 1) { + throw new IllegalArgumentException("The given vertical image count must not be less than 1."); + } + + this.horizontalImageCount = horizontalImageCount; + this.verticalImageCount = verticalImageCount; + + return this; } public Sprite2DBuilder withStartingFrame(int startingFrame) { if (startingFrame < 0) { throw new IllegalArgumentException("The starting frame value must not be less than 0."); } - if (startingFrame >= sprites.length) { + if (startingFrame >= (horizontalImageCount * verticalImageCount)) { throw new IllegalArgumentException("The starting frame value must not be more than the amount of sprite images."); } @@ -41,7 +59,7 @@ public Sprite2DBuilder withAnimationStyle(AnimationStyle animationStyle) { } public Sprite2D build() { - return new Sprite2D(sprites) + return new Sprite2D(spriteResource, horizontalImageCount, verticalImageCount) .setCurrentFrame(startingFrame) .setAnimationFPS(animationFPS) .setAnimationStyle(animationStyle); From 82c42c001c474de09d2f445e345c8a0c87734ab0 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:29:24 -0400 Subject: [PATCH 29/42] Revert to standard stacktrace printing --- src/main/java/tech/fastj/engine/FastJEngine.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index f6017654..9314e901 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -394,7 +394,7 @@ public static void run() { if (shouldThrowExceptions) { throw exception; } else { - exception.fillInStackTrace().printStackTrace(); + exception.printStackTrace(); } } } From ddf32b0484e044757192cdff9e42e4abd6ecf37b Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:30:43 -0400 Subject: [PATCH 30/42] (#86) revert input maps to HashMap to alleviate occasional null pointers from unpopulated values --- src/main/java/tech/fastj/input/keyboard/Keyboard.java | 2 +- src/main/java/tech/fastj/input/mouse/Mouse.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/tech/fastj/input/keyboard/Keyboard.java b/src/main/java/tech/fastj/input/keyboard/Keyboard.java index d6010935..acdf9c74 100644 --- a/src/main/java/tech/fastj/input/keyboard/Keyboard.java +++ b/src/main/java/tech/fastj/input/keyboard/Keyboard.java @@ -22,7 +22,7 @@ */ public class Keyboard implements KeyListener { - private static final Map Keys = new ConcurrentHashMap<>(); + private static final Map Keys = new HashMap<>(); private static String lastKeyPressed = ""; private static ScheduledExecutorService keyChecker; diff --git a/src/main/java/tech/fastj/input/mouse/Mouse.java b/src/main/java/tech/fastj/input/mouse/Mouse.java index 75c8d14d..6ce1fec4 100644 --- a/src/main/java/tech/fastj/input/mouse/Mouse.java +++ b/src/main/java/tech/fastj/input/mouse/Mouse.java @@ -32,7 +32,7 @@ public class Mouse implements MouseListener, MouseMotionListener, MouseWheelListener { private static final ScheduledExecutorService MouseExecutor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors()); - private static final Map MouseButtons = new ConcurrentHashMap<>(); + private static final Map MouseButtons = new HashMap<>(); private static final int InitialMouseButton = -1; private static final int InitialScrollDirection = 0; From 0480ce36a154665a2a475a00f3d71d5618b2a5a9 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:37:00 -0400 Subject: [PATCH 31/42] change file extension to return empty string when no extension is given, rather than the original path --- src/main/java/tech/fastj/resources/files/FileUtil.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/resources/files/FileUtil.java b/src/main/java/tech/fastj/resources/files/FileUtil.java index 8fce33a4..46c54c08 100644 --- a/src/main/java/tech/fastj/resources/files/FileUtil.java +++ b/src/main/java/tech/fastj/resources/files/FileUtil.java @@ -15,11 +15,16 @@ public class FileUtil { *

* This method does not account for file extensions with more than one dot ({@code .}) -- in cases like * those, only the last part of the extension will be returned. + *

+ * For paths which contain no file extension, an empty {@code String} will be returned. * * @param filePath The {@code Path} to get the file extension of. * @return The {@code Path}'s file extension. */ public static String getFileExtension(Path filePath) { - return filePath.toString().substring(filePath.toString().lastIndexOf(".") + 1); + if (filePath.toString().contains(".")) { + return filePath.toString().substring(filePath.toString().lastIndexOf(".") + 1); + } + return ""; } } From 8187ffc1c7efb6fe7a89459c6921dc6159493d5a Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:38:02 -0400 Subject: [PATCH 32/42] add method to write buffered images to a file --- .../java/tech/fastj/resources/images/ImageUtil.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/main/java/tech/fastj/resources/images/ImageUtil.java b/src/main/java/tech/fastj/resources/images/ImageUtil.java index 9aed7b0d..292ba14a 100644 --- a/src/main/java/tech/fastj/resources/images/ImageUtil.java +++ b/src/main/java/tech/fastj/resources/images/ImageUtil.java @@ -2,6 +2,8 @@ import tech.fastj.engine.FastJEngine; +import tech.fastj.resources.files.FileUtil; + import javax.imageio.ImageIO; import java.awt.AWTException; import java.awt.Color; @@ -47,6 +49,15 @@ public static BufferedImage loadBufferedImage(Path imagePath) { } } + public static void writeBufferedImage(BufferedImage image, Path imagePath) { + Path absoluteResourcePath = imagePath.toAbsolutePath(); + try { + ImageIO.write(image, FileUtil.getFileExtension(imagePath), absoluteResourcePath.toFile()); + } catch (IOException exception) { + throw new IllegalStateException("An error occurred while trying to write an image to \"" + absoluteResourcePath + "\".", exception); + } + } + public static void drawToImage(Image reusedImage, Path secondImagePath) { Graphics2D graphics2D = (Graphics2D) reusedImage.getGraphics(); FastJEngine.log(secondImagePath.toAbsolutePath().toString()); From 35ddb4cb030b487a71d624650c84d5246a905497 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:42:23 -0400 Subject: [PATCH 33/42] remove stray log output --- src/main/java/tech/fastj/resources/images/ImageUtil.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/tech/fastj/resources/images/ImageUtil.java b/src/main/java/tech/fastj/resources/images/ImageUtil.java index 292ba14a..f040e224 100644 --- a/src/main/java/tech/fastj/resources/images/ImageUtil.java +++ b/src/main/java/tech/fastj/resources/images/ImageUtil.java @@ -60,7 +60,6 @@ public static void writeBufferedImage(BufferedImage image, Path imagePath) { public static void drawToImage(Image reusedImage, Path secondImagePath) { Graphics2D graphics2D = (Graphics2D) reusedImage.getGraphics(); - FastJEngine.log(secondImagePath.toAbsolutePath().toString()); Image imageFromPath; try { imageFromPath = ImageIO.read(secondImagePath.toAbsolutePath().toFile()); From 3c23d10afa7c120dcdc8c1dc7ccf9a0a2ca27f74 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 10:50:52 -0400 Subject: [PATCH 34/42] (#110) Fixed texture path parsing inconsistencies Bug Fixes: - switched to getting specific token length rather than token array length - corrected start position for 3-length tokens (originally, it would cut off some of the parsed path) --- src/main/java/tech/fastj/resources/models/PsdfUtil.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/tech/fastj/resources/models/PsdfUtil.java b/src/main/java/tech/fastj/resources/models/PsdfUtil.java index b39e10c7..0f90f3aa 100644 --- a/src/main/java/tech/fastj/resources/models/PsdfUtil.java +++ b/src/main/java/tech/fastj/resources/models/PsdfUtil.java @@ -225,14 +225,14 @@ private static String parseTexture(String[] tokens) { if (tokens.length == 2) { pathBuilder.append(tokens[1], 1, tokens[1].length() - 1); } else if (tokens.length == 3) { - pathBuilder.append(tokens[1], 1, tokens.length); - pathBuilder.append(tokens[2], 2, tokens.length - 1); + pathBuilder.append(tokens[1], 1, tokens[1].length()); + pathBuilder.append(tokens[2], 0, tokens[2].length() - 1); } else { pathBuilder.append(tokens[1], 1, tokens.length); for (int i = 2; i < tokens.length - 1; i++) { pathBuilder.append(tokens[i]); } - pathBuilder.append(tokens[tokens.length - 1], 0, tokens.length - 1); + pathBuilder.append(tokens[tokens.length - 1], 0, tokens[tokens.length - 1].length() - 1); } return pathBuilder.toString(); From 81245a19c6319a1fcc8dfc86aa36bd249835bdcc Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 14:20:03 -0400 Subject: [PATCH 35/42] (#10) Added .obj writer (implementation not complete) --- .../tech/fastj/resources/models/ObjUtil.java | 134 ++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 src/main/java/tech/fastj/resources/models/ObjUtil.java diff --git a/src/main/java/tech/fastj/resources/models/ObjUtil.java b/src/main/java/tech/fastj/resources/models/ObjUtil.java new file mode 100644 index 00000000..98ca4d1f --- /dev/null +++ b/src/main/java/tech/fastj/resources/models/ObjUtil.java @@ -0,0 +1,134 @@ +package tech.fastj.resources.models; + +import tech.fastj.engine.CrashMessages; +import tech.fastj.math.Pointf; +import tech.fastj.graphics.game.Model2D; +import tech.fastj.graphics.game.Polygon2D; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; + +public class ObjUtil { + + private static final String LineSeparator = System.lineSeparator(); + + private ObjUtil() { + throw new java.lang.IllegalStateException(); + } + + public static Polygon2D[] parse(List lines) { + return null; + } + + public static void write(Path destinationPath, Model2D model) { + StringBuilder fileContents = new StringBuilder(); + writeTimestamp(fileContents); + + int vertexCount = 0; + + for (int i = 0; i < model.getPolygons().length; i++) { + writeVertexes(fileContents, model.getPolygons()[i]); + } + + writeVertexTextures(fileContents); + + for (int i = 0; i < model.getPolygons().length; i++) { + Polygon2D polygon = model.getPolygons()[i]; + writeObject(fileContents, polygon, i + 1); + writeFaces(fileContents, polygon, vertexCount); + + vertexCount += polygon.getPoints().length; + } + + try { + Files.writeString(destinationPath, fileContents, StandardCharsets.US_ASCII); + } catch (IOException exception) { + throw new IllegalStateException(CrashMessages.theGameCrashed("a ." + SupportedModelFormats.Obj + " file writing error."), exception); + } + } + + private static void writeTimestamp(StringBuilder fileContents) { + fileContents.append("# Generated by the FastJ Game Engine https://github.com/fastjengine/FastJ") + .append(LineSeparator) + .append("# Timestamp: ") + .append(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeVertexes(StringBuilder fileContents, Polygon2D polygon) { + for (int j = 0; j < polygon.getPoints().length; j++) { + Pointf vertex = polygon.getPoints()[j]; + fileContents.append(ParsingKeys.Vertex) + .append(' ') + .append(String.format("%4f", vertex.x)) + .append(' ') + .append(String.format("%4f", vertex.y)) + .append(' ') + .append(String.format("%4f", 0f)) + .append(LineSeparator); + } + } + + private static void writeVertexTextures(StringBuilder fileContents) { + fileContents.append(LineSeparator); + fileContents.append(ParsingKeys.VertexTexture) + .append(' ') + .append(0) + .append(' ') + .append(0) + .append(LineSeparator); + fileContents.append(ParsingKeys.VertexTexture) + .append(' ') + .append(1) + .append(' ') + .append(0) + .append(LineSeparator); + fileContents.append(ParsingKeys.VertexTexture) + .append(' ') + .append(1) + .append(' ') + .append(1) + .append(LineSeparator); + fileContents.append(ParsingKeys.VertexTexture) + .append(' ') + .append(0) + .append(' ') + .append(1) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeObject(StringBuilder fileContents, Polygon2D polygon, int polygonIndex) { + fileContents.append(ParsingKeys.ObjectName) + .append(' ') + .append("Polygon2D_") + .append(polygonIndex) + .append(LineSeparator); + } + + private static void writeFaces(StringBuilder fileContents, Polygon2D polygon, int vertexCount) { + fileContents.append(ParsingKeys.ObjectFace); + for (int i = 1; i <= polygon.getPoints().length; i++) { + fileContents.append(' ').append(vertexCount + i); + } + fileContents.append(LineSeparator).append(LineSeparator); + } + + public static class ParsingKeys { + private ParsingKeys() { + throw new java.lang.IllegalStateException(); + } + + public static final String Empty = ""; + public static final String Vertex = "v"; + public static final String VertexTexture = "vt"; + public static final String ObjectName = "g"; + public static final String ObjectFace = "f"; + } +} From e30d566cc7538f26cfbf619ba32010b8d7c7d6d8 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sat, 28 Aug 2021 23:49:09 -0400 Subject: [PATCH 36/42] (#10) Add .mtl support alongside .obj writing --- .../fastj/resources/models/ModelUtil.java | 6 +- .../tech/fastj/resources/models/MtlUtil.java | 224 ++++++++++++++++++ .../tech/fastj/resources/models/ObjUtil.java | 100 +++++--- .../models/SupportedModelFormats.java | 4 +- 4 files changed, 295 insertions(+), 39 deletions(-) create mode 100644 src/main/java/tech/fastj/resources/models/MtlUtil.java diff --git a/src/main/java/tech/fastj/resources/models/ModelUtil.java b/src/main/java/tech/fastj/resources/models/ModelUtil.java index 31c15350..f79a47c8 100644 --- a/src/main/java/tech/fastj/resources/models/ModelUtil.java +++ b/src/main/java/tech/fastj/resources/models/ModelUtil.java @@ -23,11 +23,13 @@ private ModelUtil() { } private static final Map, Polygon2D[]>> ModelParser = Map.of( - SupportedModelFormats.Psdf, PsdfUtil::parse + SupportedModelFormats.Psdf, PsdfUtil::parse, + SupportedModelFormats.Obj, ObjUtil::parse ); private static final Map> ModelWriter = Map.of( - SupportedModelFormats.Psdf, PsdfUtil::write + SupportedModelFormats.Psdf, PsdfUtil::write, + SupportedModelFormats.Obj, ObjUtil::write ); /** diff --git a/src/main/java/tech/fastj/resources/models/MtlUtil.java b/src/main/java/tech/fastj/resources/models/MtlUtil.java new file mode 100644 index 00000000..7eeda6f9 --- /dev/null +++ b/src/main/java/tech/fastj/resources/models/MtlUtil.java @@ -0,0 +1,224 @@ +package tech.fastj.resources.models; + +import tech.fastj.engine.CrashMessages; +import tech.fastj.engine.FastJEngine; +import tech.fastj.math.Maths; +import tech.fastj.math.Pointf; +import tech.fastj.graphics.Boundary; +import tech.fastj.graphics.game.Model2D; +import tech.fastj.graphics.game.Polygon2D; + +import tech.fastj.resources.files.FileUtil; +import tech.fastj.resources.images.ImageResource; +import tech.fastj.resources.images.ImageUtil; + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.LinearGradientPaint; +import java.awt.Paint; +import java.awt.RadialGradientPaint; +import java.awt.TexturePaint; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class MtlUtil { + + private static final String LineSeparator = System.lineSeparator(); + + private MtlUtil() { + throw new java.lang.IllegalStateException(); + } + + public static void write(Path destinationPath, Model2D model) { + Path destinationPathWithoutSpaces = Path.of(destinationPath.toString().replace(' ', '_')); + StringBuilder fileContents = new StringBuilder(); + writeTimestamp(fileContents); + + for (int i = 0; i < model.getPolygons().length; i++) { + Polygon2D polygon2D = model.getPolygons()[i]; + writeMaterial(fileContents, polygon2D, destinationPathWithoutSpaces, i + 1); + } + + try { + Files.writeString(destinationPathWithoutSpaces, fileContents, StandardCharsets.US_ASCII); + } catch (IOException exception) { + throw new IllegalStateException(CrashMessages.theGameCrashed("a .mtl file writing error."), exception); + } + } + + private static void writeMaterial(StringBuilder fileContents, Polygon2D polygon, Path destinationPath, int materialIndex) { + fileContents.append(ParsingKeys.NewMaterial) + .append(' ') + .append("Polygon2D_material_") + .append(materialIndex) + .append(LineSeparator); + + Paint material = polygon.getFill(); + if (material instanceof LinearGradientPaint || material instanceof RadialGradientPaint) { + writeGradientMaterial(fileContents, polygon, destinationPath, materialIndex); + } else if (material instanceof Color) { + writeColorMaterial(fileContents, (Color) material); + } else if (material instanceof TexturePaint) { + writeTextureMaterial(fileContents, (TexturePaint) material, destinationPath, materialIndex); + } else { + FastJEngine.error( + CrashMessages.UnimplementedMethodError.errorMessage, + new UnsupportedOperationException( + "Writing paints other than LinearGradientPaint, RadialGradientPaint, Color, or TexturePaint is not supported." + + System.lineSeparator() + + "Check the github to confirm you are on the latest version, as that version may have more implemented features." + ) + ); + } + } + + private static void writeGradientMaterial(StringBuilder fileContents, Polygon2D polygon, Path destinationPath, int materialIndex) { + writeDefaultColorValues(fileContents); + + int extensionIndex = destinationPath.toString().indexOf(FileUtil.getFileExtension(destinationPath)); + Path texturePath = Path.of(destinationPath.toString().substring(0, extensionIndex - 1).replace(' ', '_') + "_gradient_" + materialIndex + ".png"); + + Pointf polygonSize = Pointf.subtract(polygon.getBound(Boundary.BottomRight), polygon.getBound(Boundary.TopLeft)).multiply(2f); + BufferedImage bufferedImage = ImageUtil.createBufferedImage((int) (polygonSize.x / 2) + 1, (int) (polygonSize.y / 2) + 1); + + Graphics2D graphics2D = bufferedImage.createGraphics(); + graphics2D.setPaint(polygon.getFill()); + graphics2D.translate(-bufferedImage.getWidth(), -bufferedImage.getHeight()); + graphics2D.fillRect(0, 0, (int) polygonSize.x + 1, (int) polygonSize.y + 1); + graphics2D.dispose(); + + ImageUtil.writeBufferedImage(bufferedImage, texturePath); + fileContents.append(ParsingKeys.TextureImage) + .append(' ') + .append(texturePath) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeTextureMaterial(StringBuilder fileContents, TexturePaint material, Path destinationPath, int materialIndex) { + writeDefaultColorValues(fileContents); + + Path texturePath; + try { + texturePath = FastJEngine.getResourceManager(ImageResource.class).tryFindPathOfResource(material.getImage()).toAbsolutePath(); + if (texturePath.toString().contains("\\s+")) { + throw new IllegalStateException("The file path for a texture image in .mtl cannot contain whitespace."); + } + } catch (IllegalArgumentException exception) { + int extensionIndex = destinationPath.toString().indexOf(FileUtil.getFileExtension(destinationPath)); + texturePath = Path.of(destinationPath.toString().substring(0, extensionIndex - 1) + "_image_" + materialIndex + ".png"); + ImageUtil.writeBufferedImage(material.getImage(), texturePath); + } + + fileContents.append(ParsingKeys.TextureImage) + .append(' ') + .append(texturePath) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeDefaultColorValues(StringBuilder fileContents) { + fileContents.append(ParsingKeys.AmbientColor) + .append(' ') + .append(String.format("%6f", 1f)) + .append(' ') + .append(String.format("%6f", 1f)) + .append(' ') + .append(String.format("%6f", 1f)) + .append(LineSeparator); + fileContents.append(ParsingKeys.DiffuseColor) + .append(' ') + .append(String.format("%6f", 1f)) + .append(' ') + .append(String.format("%6f", 1f)) + .append(' ') + .append(String.format("%6f", 1f)) + .append(LineSeparator); + writeSpecularValues(fileContents); + fileContents.append(ParsingKeys.Transparency) + .append(' ') + .append(String.format("%6f", 1f)) + .append(LineSeparator); + fileContents.append(ParsingKeys.IlluminationMode) + .append(' ') + .append(1) + .append(LineSeparator); + } + + private static void writeTimestamp(StringBuilder fileContents) { + fileContents.append("# Generated by the FastJ Game Engine https://github.com/fastjengine/FastJ") + .append(LineSeparator) + .append("# Timestamp: ") + .append(new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date())) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeColorMaterial(StringBuilder fileContents, Color colorMaterial) { + fileContents.append(ParsingKeys.AmbientColor) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getRed(), 0f, 255f))) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getGreen(), 0f, 255f))) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getBlue(), 0f, 255f))) + .append(LineSeparator); + fileContents.append(ParsingKeys.DiffuseColor) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getRed(), 0f, 255f))) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getGreen(), 0f, 255f))) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getBlue(), 0f, 255f))) + .append(LineSeparator); + + writeSpecularValues(fileContents); + + fileContents.append(ParsingKeys.Transparency) + .append(' ') + .append(String.format("%6f", Maths.normalize(colorMaterial.getAlpha(), 0f, 255f))) + .append(LineSeparator); + fileContents.append(ParsingKeys.IlluminationMode) + .append(' ') + .append(1) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeSpecularValues(StringBuilder fileContents) { + fileContents.append(ParsingKeys.SpecularColor) + .append(' ') + .append(String.format("%6f", 0f)) + .append(' ') + .append(String.format("%6f", 0f)) + .append(' ') + .append(String.format("%6f", 0f)) + .append(LineSeparator); + fileContents.append(ParsingKeys.SpecularExponent) + .append(' ') + .append(String.format("%6f", 1f)) + .append(LineSeparator); + } + + public static class ParsingKeys { + private ParsingKeys() { + throw new java.lang.IllegalStateException(); + } + + public static final String Empty = ""; + public static final String NewMaterial = "newmtl"; + public static final String AmbientColor = "Ka"; + public static final String DiffuseColor = "Kd"; + public static final String SpecularColor = "Ks"; + public static final String SpecularExponent = "Ns"; + public static final String Transparency = "d"; + public static final String IlluminationMode = "illum"; + public static final String TextureMap = "map_Ka"; + public static final String TextureImage = "map_Kd"; + } +} diff --git a/src/main/java/tech/fastj/resources/models/ObjUtil.java b/src/main/java/tech/fastj/resources/models/ObjUtil.java index 98ca4d1f..9dbc472f 100644 --- a/src/main/java/tech/fastj/resources/models/ObjUtil.java +++ b/src/main/java/tech/fastj/resources/models/ObjUtil.java @@ -1,10 +1,14 @@ package tech.fastj.resources.models; import tech.fastj.engine.CrashMessages; +import tech.fastj.math.Maths; import tech.fastj.math.Pointf; +import tech.fastj.graphics.Boundary; import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; +import tech.fastj.resources.files.FileUtil; + import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; @@ -29,17 +33,27 @@ public static void write(Path destinationPath, Model2D model) { StringBuilder fileContents = new StringBuilder(); writeTimestamp(fileContents); - int vertexCount = 0; + Path destinationPathWithoutSpaces = Path.of(destinationPath.toString().replace(' ', '_')); + int extensionIndex = destinationPathWithoutSpaces.toString().indexOf(FileUtil.getFileExtension(destinationPathWithoutSpaces)); + Path materialPath = Path.of(destinationPathWithoutSpaces.toString().substring(0, extensionIndex) + "mtl"); + + writeMaterialLib(fileContents, materialPath); + int vertexCount = 0; for (int i = 0; i < model.getPolygons().length; i++) { - writeVertexes(fileContents, model.getPolygons()[i]); + writeVertexes(fileContents, model.getPolygons()[i], i); } + fileContents.append(LineSeparator); - writeVertexTextures(fileContents); + for (int i = 0; i < model.getPolygons().length; i++) { + writeVertexTextures(fileContents, model.getPolygons()[i]); + } + fileContents.append(LineSeparator); for (int i = 0; i < model.getPolygons().length; i++) { Polygon2D polygon = model.getPolygons()[i]; - writeObject(fileContents, polygon, i + 1); + writeObject(fileContents, i + 1); + writeMaterialUsage(fileContents, i + 1); writeFaces(fileContents, polygon, vertexCount); vertexCount += polygon.getPoints().length; @@ -48,8 +62,13 @@ public static void write(Path destinationPath, Model2D model) { try { Files.writeString(destinationPath, fileContents, StandardCharsets.US_ASCII); } catch (IOException exception) { - throw new IllegalStateException(CrashMessages.theGameCrashed("a ." + SupportedModelFormats.Obj + " file writing error."), exception); + throw new IllegalStateException( + CrashMessages.theGameCrashed("a ." + SupportedModelFormats.Obj + " file writing error."), + exception + ); } + + MtlUtil.write(materialPath, model); } private static void writeTimestamp(StringBuilder fileContents) { @@ -61,7 +80,16 @@ private static void writeTimestamp(StringBuilder fileContents) { .append(LineSeparator); } - private static void writeVertexes(StringBuilder fileContents, Polygon2D polygon) { + private static void writeMaterialLib(StringBuilder fileContents, Path materialPath) { + fileContents.append(ParsingKeys.MaterialLib) + .append(' ') + .append(materialPath.toString()) + .append(LineSeparator) + .append(LineSeparator); + } + + private static void writeVertexes(StringBuilder fileContents, Polygon2D polygon, int polygonIndex) { + float vertexSpace = polygonIndex / 1000f; for (int j = 0; j < polygon.getPoints().length; j++) { Pointf vertex = polygon.getPoints()[j]; fileContents.append(ParsingKeys.Vertex) @@ -70,41 +98,28 @@ private static void writeVertexes(StringBuilder fileContents, Polygon2D polygon) .append(' ') .append(String.format("%4f", vertex.y)) .append(' ') - .append(String.format("%4f", 0f)) + .append(String.format("%4f", vertexSpace)) .append(LineSeparator); } } - private static void writeVertexTextures(StringBuilder fileContents) { - fileContents.append(LineSeparator); - fileContents.append(ParsingKeys.VertexTexture) - .append(' ') - .append(0) - .append(' ') - .append(0) - .append(LineSeparator); - fileContents.append(ParsingKeys.VertexTexture) - .append(' ') - .append(1) - .append(' ') - .append(0) - .append(LineSeparator); - fileContents.append(ParsingKeys.VertexTexture) - .append(' ') - .append(1) - .append(' ') - .append(1) - .append(LineSeparator); - fileContents.append(ParsingKeys.VertexTexture) - .append(' ') - .append(0) - .append(' ') - .append(1) - .append(LineSeparator) - .append(LineSeparator); + private static void writeVertexTextures(StringBuilder fileContents, Polygon2D polygon) { + Pointf space = Pointf.subtract(polygon.getBound(Boundary.BottomRight), polygon.getBound(Boundary.TopLeft)); + Pointf topLeft = polygon.getBound(Boundary.TopLeft); + + for (int j = 0; j < polygon.getPoints().length; j++) { + float circleX = Maths.normalize(polygon.getPoints()[j].x - topLeft.x, 0f, space.x); + float circleY = Maths.normalize(polygon.getPoints()[j].y - topLeft.y, 0f, space.y); + fileContents.append(ParsingKeys.VertexTexture) + .append(' ') + .append(String.format("%4f", circleX)) + .append(' ') + .append(String.format("%4f", circleY)) + .append(LineSeparator); + } } - private static void writeObject(StringBuilder fileContents, Polygon2D polygon, int polygonIndex) { + private static void writeObject(StringBuilder fileContents, int polygonIndex) { fileContents.append(ParsingKeys.ObjectName) .append(' ') .append("Polygon2D_") @@ -112,10 +127,21 @@ private static void writeObject(StringBuilder fileContents, Polygon2D polygon, i .append(LineSeparator); } + private static void writeMaterialUsage(StringBuilder fileContents, int polygonIndex) { + fileContents.append(ParsingKeys.UseMaterial) + .append(' ') + .append("Polygon2D_material_") + .append(polygonIndex) + .append(LineSeparator); + } + private static void writeFaces(StringBuilder fileContents, Polygon2D polygon, int vertexCount) { fileContents.append(ParsingKeys.ObjectFace); for (int i = 1; i <= polygon.getPoints().length; i++) { - fileContents.append(' ').append(vertexCount + i); + fileContents.append(' ') + .append(vertexCount + i) + .append('/') + .append(vertexCount + i); } fileContents.append(LineSeparator).append(LineSeparator); } @@ -126,9 +152,11 @@ private ParsingKeys() { } public static final String Empty = ""; + public static final String MaterialLib = "mtllib"; public static final String Vertex = "v"; public static final String VertexTexture = "vt"; public static final String ObjectName = "g"; + public static final String UseMaterial = "usemtl"; public static final String ObjectFace = "f"; } } diff --git a/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java b/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java index 55fea719..acf9caae 100644 --- a/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java +++ b/src/main/java/tech/fastj/resources/models/SupportedModelFormats.java @@ -4,6 +4,7 @@ public class SupportedModelFormats { public static final String Psdf = "psdf"; + public static final String Obj = "obj"; public static final String valuesString = Arrays.toString(values()); @@ -13,7 +14,8 @@ private SupportedModelFormats() { public static String[] values() { return new String[]{ - Psdf + Psdf, + Obj }; } } From f8dab1967888d6319f0b9ab44f5ab0a4ee806484 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 29 Aug 2021 00:26:26 -0400 Subject: [PATCH 37/42] (#10) Add outline support to .obj export --- .../tech/fastj/resources/models/MtlUtil.java | 29 ++++++++++- .../tech/fastj/resources/models/ObjUtil.java | 49 +++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/src/main/java/tech/fastj/resources/models/MtlUtil.java b/src/main/java/tech/fastj/resources/models/MtlUtil.java index 7eeda6f9..5edbb742 100644 --- a/src/main/java/tech/fastj/resources/models/MtlUtil.java +++ b/src/main/java/tech/fastj/resources/models/MtlUtil.java @@ -52,9 +52,27 @@ public static void write(Path destinationPath, Model2D model) { } private static void writeMaterial(StringBuilder fileContents, Polygon2D polygon, Path destinationPath, int materialIndex) { + switch (polygon.getRenderStyle()) { + case Fill: { + writeFillMaterial(fileContents, polygon, destinationPath, materialIndex); + break; + } + case Outline: { + writeOutlineMaterial(fileContents, polygon, materialIndex); + break; + } + case FillAndOutline: { + writeFillMaterial(fileContents, polygon, destinationPath, materialIndex); + writeOutlineMaterial(fileContents, polygon, materialIndex); + break; + } + } + } + + private static void writeFillMaterial(StringBuilder fileContents, Polygon2D polygon, Path destinationPath, int materialIndex) { fileContents.append(ParsingKeys.NewMaterial) .append(' ') - .append("Polygon2D_material_") + .append("Polygon2D_material_fill_") .append(materialIndex) .append(LineSeparator); @@ -77,6 +95,15 @@ private static void writeMaterial(StringBuilder fileContents, Polygon2D polygon, } } + private static void writeOutlineMaterial(StringBuilder fileContents, Polygon2D polygon, int materialIndex) { + fileContents.append(ParsingKeys.NewMaterial) + .append(' ') + .append("Polygon2D_material_outline_") + .append(materialIndex) + .append(LineSeparator); + writeColorMaterial(fileContents, polygon.getOutlineColor()); + } + private static void writeGradientMaterial(StringBuilder fileContents, Polygon2D polygon, Path destinationPath, int materialIndex) { writeDefaultColorValues(fileContents); diff --git a/src/main/java/tech/fastj/resources/models/ObjUtil.java b/src/main/java/tech/fastj/resources/models/ObjUtil.java index 9dbc472f..399c5488 100644 --- a/src/main/java/tech/fastj/resources/models/ObjUtil.java +++ b/src/main/java/tech/fastj/resources/models/ObjUtil.java @@ -53,8 +53,7 @@ public static void write(Path destinationPath, Model2D model) { for (int i = 0; i < model.getPolygons().length; i++) { Polygon2D polygon = model.getPolygons()[i]; writeObject(fileContents, i + 1); - writeMaterialUsage(fileContents, i + 1); - writeFaces(fileContents, polygon, vertexCount); + writeMaterial(fileContents, polygon, i + 1, vertexCount); vertexCount += polygon.getPoints().length; } @@ -127,10 +126,41 @@ private static void writeObject(StringBuilder fileContents, int polygonIndex) { .append(LineSeparator); } - private static void writeMaterialUsage(StringBuilder fileContents, int polygonIndex) { + private static void writeMaterial(StringBuilder fileContents, Polygon2D polygon, int polygonIndex, int vertexCount) { + switch (polygon.getRenderStyle()) { + case Fill: { + writeFillMaterialUsage(fileContents, polygonIndex); + writeFaces(fileContents, polygon, vertexCount); + break; + } + case Outline: { + writeOutlineMaterialUsage(fileContents, polygonIndex); + writeLines(fileContents, polygon, vertexCount); + break; + } + case FillAndOutline: { + writeFillMaterialUsage(fileContents, polygonIndex); + writeFaces(fileContents, polygon, vertexCount); + writeOutlineMaterialUsage(fileContents, polygonIndex); + writeLines(fileContents, polygon, vertexCount); + break; + } + } + fileContents.append(LineSeparator); + } + + private static void writeFillMaterialUsage(StringBuilder fileContents, int polygonIndex) { + fileContents.append(ParsingKeys.UseMaterial) + .append(' ') + .append("Polygon2D_material_fill_") + .append(polygonIndex) + .append(LineSeparator); + } + + private static void writeOutlineMaterialUsage(StringBuilder fileContents, int polygonIndex) { fileContents.append(ParsingKeys.UseMaterial) .append(' ') - .append("Polygon2D_material_") + .append("Polygon2D_material_outline_") .append(polygonIndex) .append(LineSeparator); } @@ -143,7 +173,15 @@ private static void writeFaces(StringBuilder fileContents, Polygon2D polygon, in .append('/') .append(vertexCount + i); } - fileContents.append(LineSeparator).append(LineSeparator); + fileContents.append(LineSeparator); + } + + private static void writeLines(StringBuilder fileContents, Polygon2D polygon, int vertexCount) { + fileContents.append(ParsingKeys.ObjectLine); + for (int i = 1; i <= polygon.getPoints().length; i++) { + fileContents.append(' ').append(vertexCount + i); + } + fileContents.append(LineSeparator); } public static class ParsingKeys { @@ -158,5 +196,6 @@ private ParsingKeys() { public static final String ObjectName = "g"; public static final String UseMaterial = "usemtl"; public static final String ObjectFace = "f"; + public static final String ObjectLine = "l"; } } From 69c9e32aba33f55bd14cb0e6543cae771f7886db Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 12 Sep 2021 14:07:59 -0400 Subject: [PATCH 38/42] added method abstraction to read file lines (Files#readAllLines) --- .../tech/fastj/resources/files/FileUtil.java | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/main/java/tech/fastj/resources/files/FileUtil.java b/src/main/java/tech/fastj/resources/files/FileUtil.java index 46c54c08..c2997c6c 100644 --- a/src/main/java/tech/fastj/resources/files/FileUtil.java +++ b/src/main/java/tech/fastj/resources/files/FileUtil.java @@ -1,6 +1,11 @@ package tech.fastj.resources.files; +import tech.fastj.engine.CrashMessages; + +import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; /** * Class that provides supplementary methods for working with files and {@link Path}s. @@ -27,4 +32,22 @@ public static String getFileExtension(Path filePath) { } return ""; } + + /** + * Reads all lines of a file, as an abstraction of {@link Files#readAllLines(Path)} which handles the possible + * {@link IOException}. + * + * @param filePath The {@code Path} of the file to read. + * @return The lines of the file. + */ + public static List readFileLines(Path filePath) { + try { + return Files.readAllLines(filePath); + } catch (IOException exception) { + throw new IllegalStateException( + CrashMessages.theGameCrashed("an issue while trying to read file \"" + filePath.toAbsolutePath() + "\"."), + exception + ); + } + } } From 8651abd6fe41cc1a7673cba5990c1b35bff98ec6 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 12 Sep 2021 14:13:28 -0400 Subject: [PATCH 39/42] (#113) added default resource managers to load on FastJEngine class load --- src/main/java/tech/fastj/engine/FastJEngine.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/tech/fastj/engine/FastJEngine.java b/src/main/java/tech/fastj/engine/FastJEngine.java index 9314e901..6b19822e 100644 --- a/src/main/java/tech/fastj/engine/FastJEngine.java +++ b/src/main/java/tech/fastj/engine/FastJEngine.java @@ -86,6 +86,14 @@ private FastJEngine() { throw new java.lang.IllegalStateException(); } + static { + /* I never thought I would find a use for one of these, but I would rather the default resource managers be + added as soon as the FastJEngine class is loaded. + Rather than assume the engine will be initialized, it makes more sense for it to activate upon + initialization. */ + addDefaultResourceManagers(); + } + /** * Initializes the game engine with the specified title and logic manager. *

@@ -129,7 +137,6 @@ public static void init(String gameTitle, LogicManager gameManager, int fps, int fpsLogger = Executors.newSingleThreadScheduledExecutor(); configure(fps, ups, windowResolution, internalResolution, hardwareAcceleration); - addDefaultResourceManagers(); } private static void addDefaultResourceManagers() { From 25dbd12bf4b1773ed57360ee9f99f12cc140ca8f Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 12 Sep 2021 15:17:56 -0400 Subject: [PATCH 40/42] (#10, #113) Added .obj and .mtl parsing Other Changes: - The .obj parser handles multiple files where internal file paths are based on the starting file path. As a result, the file path is passed to the parsers as well as to the writers. --- .../fastj/resources/models/ModelUtil.java | 29 ++---- .../tech/fastj/resources/models/MtlUtil.java | 91 +++++++++++++++++- .../tech/fastj/resources/models/ObjUtil.java | 92 ++++++++++++++++++- .../tech/fastj/resources/models/PsdfUtil.java | 2 +- 4 files changed, 190 insertions(+), 24 deletions(-) diff --git a/src/main/java/tech/fastj/resources/models/ModelUtil.java b/src/main/java/tech/fastj/resources/models/ModelUtil.java index f79a47c8..d3fdf361 100644 --- a/src/main/java/tech/fastj/resources/models/ModelUtil.java +++ b/src/main/java/tech/fastj/resources/models/ModelUtil.java @@ -1,12 +1,10 @@ package tech.fastj.resources.models; -import tech.fastj.engine.CrashMessages; import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; import tech.fastj.resources.files.FileUtil; -import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; @@ -14,7 +12,7 @@ import java.util.List; import java.util.Map; import java.util.function.BiConsumer; -import java.util.function.Function; +import java.util.function.BiFunction; public class ModelUtil { @@ -22,7 +20,7 @@ private ModelUtil() { throw new java.lang.IllegalStateException(); } - private static final Map, Polygon2D[]>> ModelParser = Map.of( + private static final Map, Polygon2D[]>> ModelParser = Map.of( SupportedModelFormats.Psdf, PsdfUtil::parse, SupportedModelFormats.Obj, ObjUtil::parse ); @@ -41,28 +39,19 @@ private ModelUtil() { * Furthermore, this allows for easy use of the {@code Model2D} class, allowing you to directly use the resulting * array from this method to create a {@code Model2D} object. * - * @param fileLocation Location of the file. + * @param modelPath File location of the model. * @return An array of {@code Polygon2D}s. */ - public static Polygon2D[] loadModel(Path fileLocation) { - if (!Files.exists(fileLocation, LinkOption.NOFOLLOW_LINKS)) { - throw new IllegalArgumentException("A file was not found at \"" + fileLocation.toAbsolutePath() + "\"."); + public static Polygon2D[] loadModel(Path modelPath) { + if (!Files.exists(modelPath, LinkOption.NOFOLLOW_LINKS)) { + throw new IllegalArgumentException("A file was not found at \"" + modelPath.toAbsolutePath() + "\"."); } - String fileExtension = FileUtil.getFileExtension(fileLocation); + String fileExtension = FileUtil.getFileExtension(modelPath); checkFileExtension(fileExtension); - List lines; - try { - lines = Files.readAllLines(fileLocation); - } catch (IOException exception) { - throw new IllegalStateException( - CrashMessages.theGameCrashed("an issue while trying to parse file \"" + fileLocation.toAbsolutePath() + "\"."), - exception - ); - } - - return ModelParser.get(fileExtension).apply(lines); + List lines = FileUtil.readFileLines(modelPath); + return ModelParser.get(fileExtension).apply(modelPath, lines); } /** diff --git a/src/main/java/tech/fastj/resources/models/MtlUtil.java b/src/main/java/tech/fastj/resources/models/MtlUtil.java index 5edbb742..9105426f 100644 --- a/src/main/java/tech/fastj/resources/models/MtlUtil.java +++ b/src/main/java/tech/fastj/resources/models/MtlUtil.java @@ -7,6 +7,8 @@ import tech.fastj.graphics.Boundary; import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; +import tech.fastj.graphics.textures.Textures; +import tech.fastj.graphics.util.DrawUtil; import tech.fastj.resources.files.FileUtil; import tech.fastj.resources.images.ImageResource; @@ -25,6 +27,7 @@ import java.nio.file.Path; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; public class MtlUtil { @@ -34,6 +37,93 @@ private MtlUtil() { throw new java.lang.IllegalStateException(); } + public static void parse(Polygon2D polygon, Path materialPath, String materialName, boolean isFill) { + if (materialName.isBlank()) { + return; + } + + List lines = FileUtil.readFileLines(materialPath); + int materialIndex = lines.indexOf( + lines.stream() + .filter(line -> line.startsWith(ParsingKeys.NewMaterial + " " + materialName)) + .findFirst() + .orElseThrow(() -> new IllegalStateException("Couldn't find material \"" + materialName + "\" in file \"" + materialPath.toAbsolutePath() + "\".")) + ); + + for (int i = materialIndex + 1; i < lines.size(); i++) { + String[] tokens = lines.get(i).split("\\s+"); + switch (tokens[0]) { + case ParsingKeys.AmbientColor: { + parseColor( + polygon, + Float.parseFloat(tokens[1]), + Float.parseFloat(tokens[2]), + Float.parseFloat(tokens[3]), + isFill + ); + break; + } + case ParsingKeys.DiffuseColor: + case ParsingKeys.SpecularColor: + case ParsingKeys.SpecularExponent: { + break; + } + case ParsingKeys.Transparency: { + parseColorAlpha(polygon, Float.parseFloat(tokens[1]), isFill); + break; + } + case ParsingKeys.TextureImage: { + String materialPathString = materialPath.toString(); + String materialFileName = materialPath.getFileName().toString(); + Path imagePath = Path.of(materialPathString.substring(0, materialPathString.indexOf(materialFileName)) + tokens[1]); + parseImageTexture(polygon, imagePath); + break; + } + case ParsingKeys.NewMaterial: { + return; + } + } + } + } + + public static void parseColor(Polygon2D polygon, float red, float green, float blue, boolean isFill) { + Color color = new Color((int) (red * 255), (int) (green * 255), (int) (blue * 255)); + if (isFill) { + polygon.setFill(color); + } else { + polygon.setOutlineColor(color); + } + } + + public static void parseColorAlpha(Polygon2D polygon, float alpha, boolean isFill) { + if (isFill) { + Color color = (Color) polygon.getFill(); + polygon.setFill( + new Color( + color.getRed(), + color.getGreen(), + color.getBlue(), + (int) (alpha * 255) + ) + ); + } else { + Color color = polygon.getOutlineColor(); + polygon.setOutlineColor( + new Color( + color.getRed(), + color.getGreen(), + color.getBlue(), + (int) (alpha * 255) + ) + ); + } + } + + public static void parseImageTexture(Polygon2D polygon, Path imagePath) { + FastJEngine.getResourceManager(ImageResource.class).loadResource(imagePath); + polygon.setFill(Textures.create(imagePath, DrawUtil.createRect(polygon.getBounds()))); + } + public static void write(Path destinationPath, Model2D model) { Path destinationPathWithoutSpaces = Path.of(destinationPath.toString().replace(' ', '_')); StringBuilder fileContents = new StringBuilder(); @@ -245,7 +335,6 @@ private ParsingKeys() { public static final String SpecularExponent = "Ns"; public static final String Transparency = "d"; public static final String IlluminationMode = "illum"; - public static final String TextureMap = "map_Ka"; public static final String TextureImage = "map_Kd"; } } diff --git a/src/main/java/tech/fastj/resources/models/ObjUtil.java b/src/main/java/tech/fastj/resources/models/ObjUtil.java index 399c5488..6df21954 100644 --- a/src/main/java/tech/fastj/resources/models/ObjUtil.java +++ b/src/main/java/tech/fastj/resources/models/ObjUtil.java @@ -6,6 +6,7 @@ import tech.fastj.graphics.Boundary; import tech.fastj.graphics.game.Model2D; import tech.fastj.graphics.game.Polygon2D; +import tech.fastj.graphics.game.RenderStyle; import tech.fastj.resources.files.FileUtil; @@ -14,6 +15,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -25,8 +27,94 @@ private ObjUtil() { throw new java.lang.IllegalStateException(); } - public static Polygon2D[] parse(List lines) { - return null; + public static Polygon2D[] parse(Path modelPath, List lines) { + List polygons = new ArrayList<>(); + List vertexes = new ArrayList<>(); + + + Path materialLibraryPath = null; + String currentMaterial = ""; + + for (String line : lines) { + String[] tokens = line.split("\\s+"); + switch (tokens[0]) { + case ParsingKeys.Vertex: { + vertexes.add(parseVertex(tokens)); + break; + } + case ParsingKeys.ObjectFace: { + Pointf[] vertexesFromFaces = parseVertexesFromFaces(vertexes, tokens); + + Polygon2D polygonFromVertexes = Polygon2D.fromPoints(vertexesFromFaces); + MtlUtil.parse(polygonFromVertexes, materialLibraryPath, currentMaterial, true); + polygons.add(polygonFromVertexes); + break; + } + case ParsingKeys.ObjectLine: { + Pointf[] vertexesFromFaces = new Pointf[tokens.length - 1]; + boolean isLastPolygonOutline = false; + int lastPolygonIndex = polygons.size() - 1; + + for (int j = 0; j < tokens.length - 1; j++) { + int vertexesIndex = Integer.parseInt(tokens[j + 1].split("/")[0]); + vertexesFromFaces[j] = new Pointf( + vertexes.get(vertexesIndex - 1)[0], + vertexes.get(vertexesIndex - 1)[1] + ); + isLastPolygonOutline = polygons.get(lastPolygonIndex).getPoints()[j].equals(vertexesFromFaces[j]); + } + + if (isLastPolygonOutline) { + polygons.get(lastPolygonIndex).setRenderStyle(RenderStyle.FillAndOutline); + MtlUtil.parse(polygons.get(lastPolygonIndex), materialLibraryPath, currentMaterial, false); + } else { + Polygon2D polygonFromVertexes = Polygon2D.create(vertexesFromFaces, RenderStyle.Outline).build(); + MtlUtil.parse(polygonFromVertexes, materialLibraryPath, currentMaterial, false); + polygons.add(polygonFromVertexes); + } + break; + } + case ParsingKeys.MaterialLib: { + materialLibraryPath = Path.of( + modelPath.toString().substring( + 0, + modelPath.toString().indexOf(modelPath.getFileName().toString()) + ) + tokens[1] + // filenames and paths in .obj files cannot contain spaces, allowing us to use a non-robust + // solution for tokens. + ); + break; + } + case ParsingKeys.UseMaterial: { + // material names in .obj files cannot contain spaces, allowing us to use a non-robust solution for + // tokens. + currentMaterial = tokens[1]; + break; + } + } + } + return polygons.toArray(new Polygon2D[0]); + } + + private static Pointf[] parseVertexesFromFaces(List vertexes, String[] tokens) { + Pointf[] vertexesFromFaces = new Pointf[tokens.length - 1]; + for (int j = 1; j < tokens.length; j++) { + int vertexesIndex = Integer.parseInt(tokens[Math.min(j, tokens.length - 1)].split("/")[0]); + vertexesFromFaces[j - 1] = new Pointf( + vertexes.get(vertexesIndex - 1)[0], + vertexes.get(vertexesIndex - 1)[1] + ); + } + + return vertexesFromFaces; + } + + private static float[] parseVertex(String[] tokens) { + return new float[]{ + Float.parseFloat(tokens[1]), + Float.parseFloat(tokens[2]), + Float.parseFloat(tokens[3]) + }; } public static void write(Path destinationPath, Model2D model) { diff --git a/src/main/java/tech/fastj/resources/models/PsdfUtil.java b/src/main/java/tech/fastj/resources/models/PsdfUtil.java index 0f90f3aa..8c1305dd 100644 --- a/src/main/java/tech/fastj/resources/models/PsdfUtil.java +++ b/src/main/java/tech/fastj/resources/models/PsdfUtil.java @@ -44,7 +44,7 @@ private PsdfUtil() { * @param lines The .psdf file, split line by line. * @return An array of {@code Polygon2D}s. */ - public static Polygon2D[] parse(List lines) { + public static Polygon2D[] parse(Path modelPath, List lines) { Polygon2D[] polygons = null; int polygonsIndex = 0; From 9b851356c39363466a186d6db3e2dde6a125f07f Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 12 Sep 2021 16:11:09 -0400 Subject: [PATCH 41/42] formatted code --- .../tech/fastj/graphics/display/Display.java | 6 +++--- src/main/java/tech/fastj/input/InputManager.java | 16 ++++++++-------- .../java/tech/fastj/input/keyboard/Keyboard.java | 5 ++--- .../tech/fastj/input/keyboard/KeyboardEvent.java | 1 + .../fastj/input/keyboard/KeyboardStateEvent.java | 1 - src/main/java/tech/fastj/input/mouse/Mouse.java | 5 ++--- src/main/java/tech/fastj/math/Pointf.java | 1 - .../tech/fastj/systems/audio/AudioManager.java | 3 +-- .../fastj/systems/behaviors/BehaviorManager.java | 3 --- .../fastj/systems/control/DrawableManager.java | 2 -- .../java/tech/fastj/systems/tags/TagManager.java | 4 +++- 11 files changed, 20 insertions(+), 27 deletions(-) diff --git a/src/main/java/tech/fastj/graphics/display/Display.java b/src/main/java/tech/fastj/graphics/display/Display.java index bbe52cb2..869ea133 100644 --- a/src/main/java/tech/fastj/graphics/display/Display.java +++ b/src/main/java/tech/fastj/graphics/display/Display.java @@ -10,6 +10,9 @@ import tech.fastj.graphics.util.DisplayUtil; import tech.fastj.graphics.util.DrawUtil; +import tech.fastj.input.keyboard.Keyboard; +import tech.fastj.input.mouse.Mouse; + import javax.swing.JFrame; import java.awt.Canvas; import java.awt.Color; @@ -28,9 +31,6 @@ import java.util.LinkedHashMap; import java.util.Map; -import tech.fastj.input.keyboard.Keyboard; -import tech.fastj.input.mouse.Mouse; - /** * Class that draws to a screen using a combination of Swing's JFrame, and AWT's Canvas. * diff --git a/src/main/java/tech/fastj/input/InputManager.java b/src/main/java/tech/fastj/input/InputManager.java index f9fb588b..1d7a281c 100644 --- a/src/main/java/tech/fastj/input/InputManager.java +++ b/src/main/java/tech/fastj/input/InputManager.java @@ -1,13 +1,5 @@ package tech.fastj.input; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.awt.event.MouseEvent; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.BiConsumer; - import tech.fastj.input.keyboard.Keyboard; import tech.fastj.input.keyboard.KeyboardActionListener; import tech.fastj.input.keyboard.KeyboardEvent; @@ -16,6 +8,14 @@ import tech.fastj.input.mouse.Mouse; import tech.fastj.input.mouse.MouseActionListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.BiConsumer; + /** * Class to manage user input and input event processing. *

diff --git a/src/main/java/tech/fastj/input/keyboard/Keyboard.java b/src/main/java/tech/fastj/input/keyboard/Keyboard.java index acdf9c74..b7e743ee 100644 --- a/src/main/java/tech/fastj/input/keyboard/Keyboard.java +++ b/src/main/java/tech/fastj/input/keyboard/Keyboard.java @@ -2,18 +2,17 @@ import tech.fastj.engine.FastJEngine; +import tech.fastj.input.InputManager; + import java.awt.event.KeyEvent; import java.awt.event.KeyListener; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; -import tech.fastj.input.InputManager; - /** * Class that stores key input information from the {@code Display}. * diff --git a/src/main/java/tech/fastj/input/keyboard/KeyboardEvent.java b/src/main/java/tech/fastj/input/keyboard/KeyboardEvent.java index b195ed46..c9df6e36 100644 --- a/src/main/java/tech/fastj/input/keyboard/KeyboardEvent.java +++ b/src/main/java/tech/fastj/input/keyboard/KeyboardEvent.java @@ -4,5 +4,6 @@ public interface KeyboardEvent { KeyEvent getKeyEvent(); + String getKeyName(); } diff --git a/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java b/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java index 9f307591..e730c408 100644 --- a/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java +++ b/src/main/java/tech/fastj/input/keyboard/KeyboardStateEvent.java @@ -1,7 +1,6 @@ package tech.fastj.input.keyboard; import java.awt.event.KeyEvent; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; diff --git a/src/main/java/tech/fastj/input/mouse/Mouse.java b/src/main/java/tech/fastj/input/mouse/Mouse.java index 6ce1fec4..9bece338 100644 --- a/src/main/java/tech/fastj/input/mouse/Mouse.java +++ b/src/main/java/tech/fastj/input/mouse/Mouse.java @@ -5,6 +5,8 @@ import tech.fastj.graphics.Drawable; import tech.fastj.graphics.display.Display; +import tech.fastj.input.InputManager; + import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.awt.event.MouseMotionListener; @@ -14,14 +16,11 @@ import java.awt.geom.PathIterator; import java.util.HashMap; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import tech.fastj.input.InputManager; - /** * Mouse class that takes mouse input from the {@code Display}, and uses it to store variables about the mouse's current * state. diff --git a/src/main/java/tech/fastj/math/Pointf.java b/src/main/java/tech/fastj/math/Pointf.java index 31c26e0a..f7399471 100644 --- a/src/main/java/tech/fastj/math/Pointf.java +++ b/src/main/java/tech/fastj/math/Pointf.java @@ -339,7 +339,6 @@ public static float[] inverseLerp(Pointf p, Pointf p1, float v) { * @return An array of floats containing the resulting inverse linear interpolations of the {@code Pointf}s' {@code * x} and {@code y} values. * @see Maths#inverseLerp(float, float, float) - * * @since 1.5.0 */ public static float[] inverseLerp(Pointf p, Pointf p1, float v1, float v2) { diff --git a/src/main/java/tech/fastj/systems/audio/AudioManager.java b/src/main/java/tech/fastj/systems/audio/AudioManager.java index d1d8b05f..2d3948ac 100644 --- a/src/main/java/tech/fastj/systems/audio/AudioManager.java +++ b/src/main/java/tech/fastj/systems/audio/AudioManager.java @@ -3,14 +3,13 @@ import tech.fastj.engine.CrashMessages; import tech.fastj.engine.FastJEngine; -import tech.fastj.systems.audio.state.PlaybackState; import tech.fastj.resources.files.FileUtil; +import tech.fastj.systems.audio.state.PlaybackState; import javax.sound.sampled.*; import java.io.IOException; import java.net.URL; import java.nio.file.Path; -import java.util.HashMap; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutorService; diff --git a/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java b/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java index b69f50df..b7b9b1a8 100644 --- a/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java +++ b/src/main/java/tech/fastj/systems/behaviors/BehaviorManager.java @@ -3,12 +3,9 @@ import tech.fastj.graphics.game.GameObject; import java.util.ArrayList; -import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentSkipListMap; /** * Class to manage behavior listeners for all {@link BehaviorHandler}s. diff --git a/src/main/java/tech/fastj/systems/control/DrawableManager.java b/src/main/java/tech/fastj/systems/control/DrawableManager.java index 8629bbd3..1dd5812c 100644 --- a/src/main/java/tech/fastj/systems/control/DrawableManager.java +++ b/src/main/java/tech/fastj/systems/control/DrawableManager.java @@ -4,11 +4,9 @@ import tech.fastj.graphics.game.GameObject; import tech.fastj.graphics.ui.UIElement; -import java.util.LinkedHashMap; import java.util.Map; import java.util.Objects; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentSkipListMap; /** * Class to manage {@link Drawable} objects. diff --git a/src/main/java/tech/fastj/systems/tags/TagManager.java b/src/main/java/tech/fastj/systems/tags/TagManager.java index bd1a2d8f..87613b6f 100644 --- a/src/main/java/tech/fastj/systems/tags/TagManager.java +++ b/src/main/java/tech/fastj/systems/tags/TagManager.java @@ -39,7 +39,9 @@ public static List getEntityList(TagHandler tagHandler) { * @param tag The tag to add. */ public static void addTagToMasterList(String tag) { - if (!MasterTagList.contains(tag)) MasterTagList.add(tag); + if (!MasterTagList.contains(tag)) { + MasterTagList.add(tag); + } } /** Removes all the tags from the master list. */ From e5402fd169292d6cf79b1b04405cfe37df43d469 Mon Sep 17 00:00:00 2001 From: lucasstarsz Date: Sun, 12 Sep 2021 16:30:58 -0400 Subject: [PATCH 42/42] added default/empty cases --- .../java/tech/fastj/resources/models/MtlUtil.java | 12 +++++++----- .../java/tech/fastj/resources/models/ObjUtil.java | 4 ++++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/tech/fastj/resources/models/MtlUtil.java b/src/main/java/tech/fastj/resources/models/MtlUtil.java index 9105426f..6dc471ab 100644 --- a/src/main/java/tech/fastj/resources/models/MtlUtil.java +++ b/src/main/java/tech/fastj/resources/models/MtlUtil.java @@ -63,11 +63,6 @@ public static void parse(Polygon2D polygon, Path materialPath, String materialNa ); break; } - case ParsingKeys.DiffuseColor: - case ParsingKeys.SpecularColor: - case ParsingKeys.SpecularExponent: { - break; - } case ParsingKeys.Transparency: { parseColorAlpha(polygon, Float.parseFloat(tokens[1]), isFill); break; @@ -82,6 +77,13 @@ public static void parse(Polygon2D polygon, Path materialPath, String materialNa case ParsingKeys.NewMaterial: { return; } + case ParsingKeys.DiffuseColor: + case ParsingKeys.SpecularColor: + case ParsingKeys.SpecularExponent: + case ParsingKeys.Empty: + default: { + break; + } } } } diff --git a/src/main/java/tech/fastj/resources/models/ObjUtil.java b/src/main/java/tech/fastj/resources/models/ObjUtil.java index 6df21954..9771e70f 100644 --- a/src/main/java/tech/fastj/resources/models/ObjUtil.java +++ b/src/main/java/tech/fastj/resources/models/ObjUtil.java @@ -91,6 +91,10 @@ public static Polygon2D[] parse(Path modelPath, List lines) { currentMaterial = tokens[1]; break; } + case ParsingKeys.Empty: + default: { + break; + } } } return polygons.toArray(new Polygon2D[0]);