diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/animation/Animation.java b/api/src/main/java/com/bartlomiejpluta/base/api/animation/Animation.java index 4bbf1a5e..d4859564 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/animation/Animation.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/animation/Animation.java @@ -1,5 +1,6 @@ package com.bartlomiejpluta.base.api.animation; +import com.bartlomiejpluta.base.api.color.Colorful; import com.bartlomiejpluta.base.api.map.layer.base.Layer; import com.bartlomiejpluta.base.api.move.Movable; import com.bartlomiejpluta.base.internal.program.Updatable; @@ -8,7 +9,7 @@ import com.bartlomiejpluta.base.util.path.Path; import java.util.concurrent.CompletableFuture; -public interface Animation extends Movable, Animated, Renderable, Updatable { +public interface Animation extends Movable, Animated, Colorful, Renderable, Updatable { Integer getRepeat(); diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/character/Character.java b/api/src/main/java/com/bartlomiejpluta/base/api/character/Character.java index dd82628c..5f599756 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/character/Character.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/character/Character.java @@ -1,6 +1,7 @@ package com.bartlomiejpluta.base.api.character; import com.bartlomiejpluta.base.api.animation.Animated; +import com.bartlomiejpluta.base.api.color.Colorful; import com.bartlomiejpluta.base.api.entity.Entity; import com.bartlomiejpluta.base.api.move.Direction; import com.bartlomiejpluta.base.api.move.Movable; @@ -26,10 +27,10 @@ import java.util.concurrent.CompletableFuture; * damaged box). * *

This interface combines movement capabilities ({@link Movable}), animation features - * ({@link Animated}), and entity properties ({@link Entity}) to create a complete + * ({@link Animated}), coloring capabilities ({@link Colorful}), and entity properties ({@link Entity}) to create a complete * character system for 2D games. */ -public interface Character extends Movable, Animated, Entity { +public interface Character extends Movable, Animated, Colorful, Entity { /** * Initiates movement in the specified direction. diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/color/Colorful.java b/api/src/main/java/com/bartlomiejpluta/base/api/color/Colorful.java new file mode 100644 index 00000000..117283dc --- /dev/null +++ b/api/src/main/java/com/bartlomiejpluta/base/api/color/Colorful.java @@ -0,0 +1,123 @@ +package com.bartlomiejpluta.base.api.color; + +import org.joml.Vector3fc; +import org.joml.Vector4fc; + +/** + * Interface for objects that can be colored and have their color properties modified. + * This interface provides a comprehensive API for managing RGBA color values using + * various input formats including JOML vectors, individual float components, and + * packed integer values. + * + *

Color components are expected to be in the range [0.0, 1.0] for float values, + * where 0.0 represents no intensity and 1.0 represents full intensity.

+ */ +public interface Colorful { + + /** + * Returns the current color of this object. + * + * @return a Vector4fc containing the RGBA color components, where: + * x = red, y = green, z = blue, w = alpha. + * All components are in the range [0.0, 1.0]. + */ + Vector4fc getColor(); + + /** + * Sets the color of this object using a 4D vector. + * + * @param color a Vector4fc containing the RGBA color components, where: + * x = red, y = green, z = blue, w = alpha. + * All components should be in the range [0.0, 1.0]. + * @throws NullPointerException if color is null + */ + void setColor(Vector4fc color); + + /** + * Sets the RGB color components of this object using a 3D vector. + * The alpha component will remain unchanged or be set to a default value. + * + * @param color a Vector3fc containing the RGB color components, where: + * x = red, y = green, z = blue. + * All components should be in the range [0.0, 1.0]. + * @throws NullPointerException if color is null + */ + void setColor(Vector3fc color); + + /** + * Sets the RGBA color components of this object using individual float values. + * + * @param red the red component in the range [0.0, 1.0] + * @param green the green component in the range [0.0, 1.0] + * @param blue the blue component in the range [0.0, 1.0] + * @param alpha the alpha component in the range [0.0, 1.0] + */ + void setColor(float red, float green, float blue, float alpha); + + /** + * Sets the RGB color components of this object using individual float values. + * The alpha component will remain unchanged or be set to a default value. + * + * @param red the red component in the range [0.0, 1.0] + * @param green the green component in the range [0.0, 1.0] + * @param blue the blue component in the range [0.0, 1.0] + */ + void setColor(float red, float green, float blue); + + /** + * Sets the color of this object using a packed RGBA integer value. + * The integer is expected to be in RGBA format where each component + * occupies 8 bits in the range [0, 255] and is automatically converted + * to the [0.0, 1.0] range by dividing by 255. + * + *

The bit layout is as follows:

+ * + * + *

For example, {@code 0xFF0000FF} represents full red with full alpha, + * while green and blue are zero.

+ * + * @param rgba the packed RGBA color value + */ + default void setColor(int rgba) { + setColor( + ((rgba >>> 24) & 0xFF) / 255f, + ((rgba >>> 16) & 0xFF) / 255f, + ((rgba >>> 8) & 0xFF) / 255f, + (rgba & 0xFF) / 255f + ); + } + + /** + * Sets only the red color component of this object. + * + * @param red the red component in the range [0.0, 1.0] + */ + void setRed(float red); + + /** + * Sets only the green color component of this object. + * + * @param green the green component in the range [0.0, 1.0] + */ + void setGreen(float green); + + /** + * Sets only the blue color component of this object. + * + * @param blue the blue component in the range [0.0, 1.0] + */ + void setBlue(float blue); + + /** + * Sets only the alpha (transparency) component of this object. + * + * @param alpha the alpha component in the range [0.0, 1.0], where + * 0.0 is fully transparent and 1.0 is fully opaque + */ + void setAlpha(float alpha); +} diff --git a/api/src/main/java/com/bartlomiejpluta/base/api/icon/Icon.java b/api/src/main/java/com/bartlomiejpluta/base/api/icon/Icon.java index 094b56ce..21f6c5f0 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/api/icon/Icon.java +++ b/api/src/main/java/com/bartlomiejpluta/base/api/icon/Icon.java @@ -1,8 +1,9 @@ package com.bartlomiejpluta.base.api.icon; +import com.bartlomiejpluta.base.api.color.Colorful; import com.bartlomiejpluta.base.api.entity.Entity; -public interface Icon extends Entity { +public interface Icon extends Colorful, Entity { void changeIcon(int row, int column); void changeIcon(String iconSetUid, int row, int column); diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/animation/AnimationDelegate.java b/api/src/main/java/com/bartlomiejpluta/base/lib/animation/AnimationDelegate.java index b351a4e3..a3a5d135 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/animation/AnimationDelegate.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/animation/AnimationDelegate.java @@ -11,9 +11,7 @@ import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.internal.object.Placeable; import com.bartlomiejpluta.base.internal.render.ShaderManager; import com.bartlomiejpluta.base.util.path.Path; -import org.joml.Matrix4fc; -import org.joml.Vector2fc; -import org.joml.Vector2ic; +import org.joml.*; import java.util.concurrent.CompletableFuture; @@ -294,6 +292,51 @@ public abstract class AnimationDelegate implements Animation { return animation.getLayer(); } + @Override + public Vector4fc getColor() { + return animation.getColor(); + } + + @Override + public void setColor(Vector4fc color) { + animation.setColor(color); + } + + @Override + public void setColor(Vector3fc color) { + animation.setColor(color); + } + + @Override + public void setColor(float red, float green, float blue, float alpha) { + animation.setColor(red, green, blue, alpha); + } + + @Override + public void setColor(float red, float green, float blue) { + animation.setColor(red, green, blue); + } + + @Override + public void setRed(float red) { + animation.setRed(red); + } + + @Override + public void setGreen(float green) { + animation.setGreen(green); + } + + @Override + public void setBlue(float blue) { + animation.setBlue(blue); + } + + @Override + public void setAlpha(float alpha) { + animation.setAlpha(alpha); + } + @Override public void render(Screen screen, Camera camera, ShaderManager shaderManager) { animation.render(screen, camera, shaderManager); diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/character/CharacterDelegate.java b/api/src/main/java/com/bartlomiejpluta/base/lib/character/CharacterDelegate.java index 5479ce34..838b2eca 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/character/CharacterDelegate.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/character/CharacterDelegate.java @@ -12,9 +12,7 @@ import com.bartlomiejpluta.base.api.move.Movement; import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.internal.object.Placeable; import com.bartlomiejpluta.base.internal.render.ShaderManager; -import org.joml.Matrix4fc; -import org.joml.Vector2fc; -import org.joml.Vector2ic; +import org.joml.*; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; @@ -328,6 +326,51 @@ public abstract class CharacterDelegate implements Character { character.abortMove(); } + @Override + public Vector4fc getColor() { + return character.getColor(); + } + + @Override + public void setColor(Vector4fc color) { + character.setColor(color); + } + + @Override + public void setColor(Vector3fc color) { + character.setColor(color); + } + + @Override + public void setColor(float red, float green, float blue, float alpha) { + character.setColor(red, green, blue, alpha); + } + + @Override + public void setColor(float red, float green, float blue) { + character.setColor(red, green, blue); + } + + @Override + public void setRed(float red) { + character.setRed(red); + } + + @Override + public void setGreen(float green) { + character.setGreen(green); + } + + @Override + public void setBlue(float blue) { + character.setBlue(blue); + } + + @Override + public void setAlpha(float alpha) { + character.setAlpha(alpha); + } + @Override public void update(float dt) { character.update(dt); diff --git a/api/src/main/java/com/bartlomiejpluta/base/lib/icon/IconDelegate.java b/api/src/main/java/com/bartlomiejpluta/base/lib/icon/IconDelegate.java index 0f2f073d..57f17f6d 100644 --- a/api/src/main/java/com/bartlomiejpluta/base/lib/icon/IconDelegate.java +++ b/api/src/main/java/com/bartlomiejpluta/base/lib/icon/IconDelegate.java @@ -11,9 +11,7 @@ import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.internal.object.Placeable; import com.bartlomiejpluta.base.internal.render.ShaderManager; import lombok.NonNull; -import org.joml.Matrix4fc; -import org.joml.Vector2fc; -import org.joml.Vector2ic; +import org.joml.*; import java.util.function.Consumer; @@ -249,6 +247,51 @@ public abstract class IconDelegate implements Icon { icon.handleEvent(event); } + @Override + public Vector4fc getColor() { + return icon.getColor(); + } + + @Override + public void setColor(Vector4fc color) { + icon.setColor(color); + } + + @Override + public void setColor(Vector3fc color) { + icon.setColor(color); + } + + @Override + public void setColor(float red, float green, float blue, float alpha) { + icon.setColor(red, green, blue, alpha); + } + + @Override + public void setColor(float red, float green, float blue) { + icon.setColor(red, green, blue); + } + + @Override + public void setRed(float red) { + icon.setRed(red); + } + + @Override + public void setGreen(float green) { + icon.setGreen(green); + } + + @Override + public void setBlue(float blue) { + icon.setBlue(blue); + } + + @Override + public void setAlpha(float alpha) { + icon.setAlpha(alpha); + } + @Override public void update(float dt) { icon.update(dt); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/material/Material.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/material/Material.java index a3ce75c2..a222627b 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/material/Material.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/material/Material.java @@ -1,5 +1,8 @@ package com.bartlomiejpluta.base.engine.core.gl.object.material; +import com.bartlomiejpluta.base.engine.core.gl.object.color.Color; +import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture; +import com.bartlomiejpluta.base.engine.core.gl.object.texture.TexturedMaterial; import com.bartlomiejpluta.base.internal.render.Renderable; import org.joml.Vector3fc; import org.joml.Vector4fc; @@ -28,4 +31,18 @@ public interface Material extends Renderable { int getRows(); float[][] getTextureCoordinatesForAllFrames(); + + /** + * Creates a material with single, uniform color. + */ + static Material unicolor(float red, float green, float blue, float alpha) { + return new Color(red, green, blue, alpha); + } + + /** + * Creates a textured material + */ + static TexturedMaterial textured(Texture texture) { + return new TexturedMaterial(texture); + } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/Texture.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/Texture.java index aa5870dc..38cbe8b3 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/Texture.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/Texture.java @@ -2,11 +2,10 @@ package com.bartlomiejpluta.base.engine.core.gl.object.texture; import com.bartlomiejpluta.base.api.camera.Camera; import com.bartlomiejpluta.base.api.screen.Screen; -import com.bartlomiejpluta.base.engine.core.gl.object.color.Color; -import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName; import com.bartlomiejpluta.base.engine.error.AppException; import com.bartlomiejpluta.base.internal.gc.Disposable; +import com.bartlomiejpluta.base.internal.render.Renderable; import com.bartlomiejpluta.base.internal.render.ShaderManager; import lombok.Getter; import org.joml.Vector2f; @@ -21,7 +20,7 @@ import static org.lwjgl.opengl.GL13.glActiveTexture; import static org.lwjgl.stb.STBImage.stbi_failure_reason; import static org.lwjgl.stb.STBImage.stbi_load_from_memory; -public class Texture extends Color implements Material, Disposable { +public class Texture implements Renderable, Disposable { private static final int DESIRED_CHANNELS = 4; private final int textureId; @@ -42,10 +41,10 @@ public class Texture extends Color implements Material, Disposable { private final int columns; @Getter - private final Vector2fc spriteFragment; + private final Vector2fc frameFragment; @Getter - private final Vector2fc spriteSize; + private final Vector2fc frameSize; Texture(String textureFilename, ByteBuffer buffer, int rows, int columns) { try (var stack = MemoryStack.stackPush()) { @@ -74,12 +73,11 @@ public class Texture extends Color implements Material, Disposable { this.rows = rows; this.columns = columns; - this.spriteFragment = new Vector2f(1 / (float) columns, 1 / (float) rows); - this.spriteSize = new Vector2f(width, height).mul(spriteFragment); + this.frameFragment = new Vector2f(1 / (float) columns, 1 / (float) rows); + this.frameSize = new Vector2f(width, height).mul(frameFragment); } } - @Override public float[][] getTextureCoordinatesForAllFrames() { var array = new float[rows * columns][]; @@ -95,7 +93,7 @@ public class Texture extends Color implements Material, Disposable { } public float[] getTextureCoordinates(int x, int y) { - return getTextureCoordinates(x * (int) spriteSize.x(), y * (int) spriteSize.y(), (int) spriteSize.x(), (int) spriteSize.y()); + return getTextureCoordinates(x * (int) frameSize.x(), y * (int) frameSize.y(), (int) frameSize.x(), (int) frameSize.y()); } public float[] getTextureCoordinates(int textureX, int textureY, int tileWidth, int tileHeight) { @@ -118,7 +116,6 @@ public class Texture extends Color implements Material, Disposable { @Override public void render(Screen screen, Camera camera, ShaderManager shaderManager) { shaderManager.setUniform(UniformName.UNI_HAS_OBJECT_TEXTURE, true); - shaderManager.setUniform(UniformName.UNI_OBJECT_COLOR, color); shaderManager.setUniform(UniformName.UNI_TEXTURE_SAMPLER, 0); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textureId); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/TexturedMaterial.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/TexturedMaterial.java new file mode 100644 index 00000000..5fe61045 --- /dev/null +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/core/gl/object/texture/TexturedMaterial.java @@ -0,0 +1,73 @@ +package com.bartlomiejpluta.base.engine.core.gl.object.texture; + +import com.bartlomiejpluta.base.api.camera.Camera; +import com.bartlomiejpluta.base.api.screen.Screen; +import com.bartlomiejpluta.base.engine.core.gl.object.color.Color; +import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; +import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName; +import com.bartlomiejpluta.base.internal.render.ShaderManager; +import lombok.Getter; +import lombok.NonNull; +import org.joml.Vector2fc; + +@Getter +public class TexturedMaterial extends Color implements Material { + private final Texture texture; + + public TexturedMaterial(@NonNull Texture texture) { + this.texture = texture; + } + + @Override + public float[][] getTextureCoordinatesForAllFrames() { + return texture.getTextureCoordinatesForAllFrames(); + } + + @Override + public int getColumns() { + return texture.getColumns(); + } + + @Override + public int getRows() { + return texture.getRows(); + } + + public String getFileName() { + return texture.getFileName(); + } + + public int getHeight() { + return texture.getHeight(); + } + + public int getWidth() { + return texture.getWidth(); + } + + public Vector2fc getFrameFragment() { + return texture.getFrameFragment(); + } + + public Vector2fc getFrameSize() { + return texture.getFrameSize(); + } + + public float[] getTextureCoordinates(int id) { + return texture.getTextureCoordinates(id); + } + + public float[] getTextureCoordinates(int x, int y) { + return texture.getTextureCoordinates(x, y); + } + + public float[] getTextureCoordinates(int textureX, int textureY, int tileWidth, int tileHeight) { + return texture.getTextureCoordinates(textureX, textureY, tileWidth, tileHeight); + } + + @Override + public void render(Screen screen, Camera camera, ShaderManager shaderManager) { + shaderManager.setUniform(UniformName.UNI_OBJECT_COLOR, color); + texture.render(screen, camera, shaderManager); + } +} diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/animation/model/DefaultAnimation.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/animation/model/DefaultAnimation.java index 2b27089d..fe152144 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/animation/model/DefaultAnimation.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/animation/model/DefaultAnimation.java @@ -6,6 +6,7 @@ import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer; import com.bartlomiejpluta.base.api.move.AnimationMovement; import com.bartlomiejpluta.base.api.move.Direction; import com.bartlomiejpluta.base.api.move.Movement; +import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadMesh; import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture; import com.bartlomiejpluta.base.engine.world.movement.MovableSprite; @@ -19,6 +20,7 @@ import org.joml.Vector2fc; import java.util.concurrent.CompletableFuture; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; import static com.bartlomiejpluta.base.util.path.PathProgress.DONE; import static com.bartlomiejpluta.base.util.path.PathProgress.SEGMENT_FAILED; @@ -52,11 +54,11 @@ public class DefaultAnimation extends MovableSprite implements Animation { private final CompletableFuture future = new CompletableFuture<>(); public DefaultAnimation(QuadMesh mesh, Texture texture, @NonNull Vector2fc[] frames) { - super(mesh, texture); + super(mesh, textured(texture)); this.frames = frames; this.lastFrameIndex = frames.length - 1; - this.animationSpriteSize = texture.getSpriteSize(); + this.animationSpriteSize = texture.getFrameSize(); super.setScale(animationSpriteSize.x() * animationScale.x, animationSpriteSize.y() * animationScale.y); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/character/model/DefaultCharacter.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/character/model/DefaultCharacter.java index e6aba496..5de5e8d5 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/character/model/DefaultCharacter.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/character/model/DefaultCharacter.java @@ -7,6 +7,7 @@ import com.bartlomiejpluta.base.api.map.layer.object.ObjectLayer; import com.bartlomiejpluta.base.api.move.CharacterMovement; import com.bartlomiejpluta.base.api.move.Direction; import com.bartlomiejpluta.base.api.move.Movement; +import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadMesh; import com.bartlomiejpluta.base.engine.error.AppException; import com.bartlomiejpluta.base.engine.world.character.manager.CharacterSetManager; @@ -24,6 +25,7 @@ import java.util.Queue; import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; import static java.util.Objects.requireNonNull; @EqualsAndHashCode(callSuper = true) @@ -59,13 +61,13 @@ public class DefaultCharacter extends MovableSprite implements Character { } private DefaultCharacter(QuadMesh mesh, @NonNull CharacterSet characterSet, @NonNull CharacterSetManager characterSetManager, int defaultSpriteColumn) { - super(mesh, characterSet.getTexture()); + super(mesh, textured(characterSet.getTexture())); this.defaultSpriteColumn = defaultSpriteColumn; this.characterSetManager = characterSetManager; this.faceDirection = Direction.DOWN; this.characterSet = characterSet; - this.characterSetSize = characterSet.getTexture().getSpriteSize(); + this.characterSetSize = characterSet.getTexture().getFrameSize(); super.setScale(characterSetSize.x() * characterScale.x, characterSetSize.y() * characterScale.y); @@ -115,9 +117,9 @@ public class DefaultCharacter extends MovableSprite implements Character { @Override public void changeCharacterSet(String characterSetUid) { this.characterSet = characterSetManager.loadObject(characterSetUid); - this.characterSetSize = characterSet.getTexture().getSpriteSize(); + this.characterSetSize = characterSet.getTexture().getFrameSize(); super.setScale(characterSetSize.x() * characterScale.x, characterSetSize.y() * characterScale.y); - setMaterial(characterSet.getTexture()); + applyTextureAndPreserveCurrentColor(characterSet.getTexture()); } @Override diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/icon/model/DefaultIcon.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/icon/model/DefaultIcon.java index 947ef80c..29a792c7 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/icon/model/DefaultIcon.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/icon/model/DefaultIcon.java @@ -18,6 +18,8 @@ import org.joml.Vector2fc; import java.util.function.Consumer; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; + public class DefaultIcon extends Sprite implements Icon { private final EventHandler eventHandler = new EventHandler(); private final IconSetManager iconSetManager; @@ -49,11 +51,11 @@ public class DefaultIcon extends Sprite implements Icon { } private DefaultIcon(@NonNull IconSetManager iconSetManager, QuadMesh mesh, @NonNull Texture texture, @NonNull String iconSetUid, int row, int column) { - super(mesh, texture); + super(mesh, textured(texture)); this.iconSetManager = iconSetManager; setFrame(row, column); - this.iconSetSize = texture.getSpriteSize(); + this.iconSetSize = texture.getFrameSize(); super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y); this.iconSetUid = iconSetUid; @@ -81,14 +83,14 @@ public class DefaultIcon extends Sprite implements Icon { @Override public void changeIcon(String iconSetUid, int row, int column) { var texture = iconSetManager.loadObject(iconSetUid); - setMaterial(texture); + applyTextureAndPreserveCurrentColor(texture); setFrame(row, column); this.iconSetUid = iconSetUid; this.iconSetRow = row; this.iconSetColumn = column; - this.iconSetSize = texture.getSpriteSize(); + this.iconSetSize = texture.getFrameSize(); super.setScale(iconSetSize.x() * iconScale.x, iconSetSize.y() * iconScale.y); } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/image/model/DefaultImage.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/image/model/DefaultImage.java index 44af96a1..bc325bd2 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/image/model/DefaultImage.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/image/model/DefaultImage.java @@ -3,11 +3,14 @@ package com.bartlomiejpluta.base.engine.world.image.model; import com.bartlomiejpluta.base.api.image.Image; import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadMesh; +import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture; import com.bartlomiejpluta.base.engine.world.object.Sprite; import lombok.Getter; import lombok.NonNull; import org.joml.Vector2f; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; + @Getter public class DefaultImage extends Sprite implements Image { private final Vector2f imageScale = new Vector2f(1, 1); @@ -17,8 +20,8 @@ public class DefaultImage extends Sprite implements Image { private final int width; private final int height; - public DefaultImage(QuadMesh mesh, @NonNull Material texture, int primaryWidth, int primaryHeight, int factor) { - super(mesh, texture); + public DefaultImage(QuadMesh mesh, @NonNull Texture texture, int primaryWidth, int primaryHeight, int factor) { + super(mesh, textured(texture)); this.primaryWidth = primaryWidth; this.primaryHeight = primaryHeight; this.factor = factor; diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/autotile/BaseAutoTileLayer.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/autotile/BaseAutoTileLayer.java index a3bf3ad7..3da75e49 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/autotile/BaseAutoTileLayer.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/autotile/BaseAutoTileLayer.java @@ -41,7 +41,7 @@ public abstract class BaseAutoTileLayer extends BaseLayer { tileSet.getTexture(), rows * 4, columns * 4, - new Vector2f(tileSet.getTexture().getSpriteSize()).div(2) + new Vector2f(tileSet.getTexture().getFrameSize()).div(2) ); stream(layer).forEach(tiles -> fill(tiles, EMPTY_TILE)); diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/color/DefaultColorLayer.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/color/DefaultColorLayer.java index 6f55f335..0229580c 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/color/DefaultColorLayer.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/color/DefaultColorLayer.java @@ -4,7 +4,6 @@ import com.bartlomiejpluta.base.api.camera.Camera; import com.bartlomiejpluta.base.api.map.layer.color.ColorLayer; import com.bartlomiejpluta.base.api.map.model.GameMap; import com.bartlomiejpluta.base.api.screen.Screen; -import com.bartlomiejpluta.base.engine.core.gl.object.color.Color; import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.MeshManager; import com.bartlomiejpluta.base.engine.world.map.layer.base.BaseLayer; @@ -15,6 +14,8 @@ import lombok.NonNull; import org.joml.Matrix4fc; import org.joml.Vector2fc; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.unicolor; + public class DefaultColorLayer extends BaseLayer implements ColorLayer { private static final float QUAD_WIDTH = 1; private static final float QUAD_HEIGHT = 1; @@ -150,7 +151,7 @@ public class DefaultColorLayer extends BaseLayer implements ColorLayer { private static class ColorPlane extends Sprite { public ColorPlane(@NonNull MeshManager meshManager, float red, float green, float blue, float alpha) { - super(meshManager.createQuad(QUAD_WIDTH, QUAD_HEIGHT, QUAD_ORIGIN_X, QUAD_ORIGIN_Y), new Color(red, green, blue, alpha)); + super(meshManager.createQuad(QUAD_WIDTH, QUAD_HEIGHT, QUAD_ORIGIN_X, QUAD_ORIGIN_Y), unicolor(red, green, blue, alpha)); } } } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/ChunkManager.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/ChunkManager.java index 41892dd9..362877f2 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/ChunkManager.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/ChunkManager.java @@ -34,7 +34,7 @@ public class ChunkManager implements Renderable, Disposable { } public ChunkManager(MeshManager meshManager, Texture tileSet, int rows, int columns, int chunkSize) { - this(meshManager, tileSet, rows, columns, tileSet.getSpriteSize(), chunkSize); + this(meshManager, tileSet, rows, columns, tileSet.getFrameSize(), chunkSize); } public ChunkManager(MeshManager meshManager, @NonNull Texture tileSet, int rows, int columns, @NonNull Vector2fc tileSize, int chunkSize) { diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/TileChunk.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/TileChunk.java index 8d80e436..40a76044 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/TileChunk.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/map/layer/util/TileChunk.java @@ -2,12 +2,11 @@ package com.bartlomiejpluta.base.engine.world.map.layer.util; import com.bartlomiejpluta.base.api.camera.Camera; import com.bartlomiejpluta.base.api.screen.Screen; -import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.Mesh; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.MeshManager; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadTemplate; import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture; -import com.bartlomiejpluta.base.engine.core.gl.shader.constant.Shader; +import com.bartlomiejpluta.base.engine.core.gl.object.texture.TexturedMaterial; import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName; import com.bartlomiejpluta.base.engine.world.object.Model; import com.bartlomiejpluta.base.internal.gc.Disposable; @@ -17,8 +16,10 @@ import com.bartlomiejpluta.base.internal.render.Renderable; import com.bartlomiejpluta.base.internal.render.ShaderManager; import lombok.NonNull; +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; + public class TileChunk extends Model implements Placeable, Renderable, Disposable, BoundingBox { - private final Texture tileSet; + private final TexturedMaterial tileSet; private final Mesh mesh; private final int chunkSize; private final QuadTemplate template; @@ -30,10 +31,10 @@ public class TileChunk extends Model implements Placeable, Renderable, Disposabl } public TileChunk(@NonNull MeshManager meshManager, @NonNull Texture tileSet, int chunkSize, float originX, float originY) { - this.tileSet = tileSet; + this.tileSet = textured(tileSet); this.chunkSize = chunkSize; this.mesh = meshManager.createMesh(chunkSize * chunkSize); - this.template = new QuadTemplate(tileSet.getSpriteSize().x(), tileSet.getSpriteSize().y(), originX, originY); + this.template = new QuadTemplate(tileSet.getFrameSize().x(), tileSet.getFrameSize().y(), originX, originY); this.originX = originX; this.originY = originY; } @@ -82,7 +83,7 @@ public class TileChunk extends Model implements Placeable, Renderable, Disposabl @Override public float getMaxX() { float scaledOriginX = originX * scaleX; - float scaledChunkWidth = chunkSize * tileSet.getSpriteSize().x() * scaleX; + float scaledChunkWidth = chunkSize * tileSet.getFrameSize().x() * scaleX; return getPosition().x() + scaledChunkWidth - scaledOriginX; } @@ -95,7 +96,7 @@ public class TileChunk extends Model implements Placeable, Renderable, Disposabl @Override public float getMaxY() { float scaledOriginY = originY * scaleY; - float scaledChunkHeight = chunkSize * tileSet.getSpriteSize().y() * scaleY; + float scaledChunkHeight = chunkSize * tileSet.getFrameSize().y() * scaleY; return getPosition().y() + scaledChunkHeight - scaledOriginY; } diff --git a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/object/Sprite.java b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/object/Sprite.java index bf7efb42..1dab7c96 100644 --- a/engine/src/main/java/com/bartlomiejpluta/base/engine/world/object/Sprite.java +++ b/engine/src/main/java/com/bartlomiejpluta/base/engine/world/object/Sprite.java @@ -4,6 +4,7 @@ import com.bartlomiejpluta.base.api.camera.Camera; import com.bartlomiejpluta.base.api.screen.Screen; import com.bartlomiejpluta.base.engine.core.gl.object.material.Material; import com.bartlomiejpluta.base.engine.core.gl.object.mesh.QuadMesh; +import com.bartlomiejpluta.base.engine.core.gl.object.texture.Texture; import com.bartlomiejpluta.base.engine.core.gl.shader.constant.UniformName; import com.bartlomiejpluta.base.engine.world.location.LocationableModel; import com.bartlomiejpluta.base.internal.render.BoundingBox; @@ -12,6 +13,10 @@ import com.bartlomiejpluta.base.internal.render.ShaderManager; import lombok.EqualsAndHashCode; import lombok.Getter; import lombok.NonNull; +import org.joml.Vector3fc; +import org.joml.Vector4fc; + +import static com.bartlomiejpluta.base.engine.core.gl.object.material.Material.textured; @EqualsAndHashCode(callSuper = true) public abstract class Sprite extends LocationableModel implements Renderable, BoundingBox { @@ -49,6 +54,19 @@ public abstract class Sprite extends LocationableModel implements Renderable, Bo updateTextureCoordinates(); } + /** + * Replaces current material with textured one but preserves the color. + * For example if some sprite is 0.4 opaque but needs to change its texture, + * this function will apply new texture keeping the 0.4 opacity in opposite to {@link #setMaterial(Material)}, + * which completely replaces the material including its color. + * @param texture - desired texture to be applied + */ + protected void applyTextureAndPreserveCurrentColor(@NonNull Texture texture) { + var currentColor = material.getColor(); + setMaterial(textured(texture)); + material.setColor(currentColor); + } + public void setFrame(int row, int column) { setFrame(row * material.getColumns() + column); } @@ -83,6 +101,42 @@ public abstract class Sprite extends LocationableModel implements Renderable, Bo return getPosition().y() + scaledChunkHeight - scaledOriginY; } + public Vector4fc getColor() { + return material.getColor(); + } + + public void setColor(Vector4fc color) { + material.setColor(color); + } + + public void setColor(Vector3fc color) { + material.setColor(color); + } + + public void setColor(float red, float green, float blue, float alpha) { + material.setColor(red, green, blue, alpha); + } + + public void setColor(float red, float green, float blue) { + material.setColor(red, green, blue); + } + + public void setRed(float red) { + material.setRed(red); + } + + public void setGreen(float green) { + material.setGreen(green); + } + + public void setBlue(float blue) { + material.setBlue(blue); + } + + public void setAlpha(float alpha) { + material.setAlpha(alpha); + } + @Override public void render(Screen screen, Camera camera, ShaderManager shaderManager) { if (!camera.containsBox(this)) {