TPL refactor, unified line endings, JavaDoc and full switch to SmartSeverity

This commit is contained in:
Tefek 2020-09-08 23:32:20 +02:00
parent 60fae86237
commit 2b065249ee
64 changed files with 4471 additions and 4306 deletions

View File

@ -51,6 +51,7 @@ version numbers.*
### Normal priority
* The collision system for PlutoStatic
* Improve image loading capabilities, possibly rewrite PlutoLib#TPL
### Low priority
* Polishing PlutoLib

View File

@ -7,5 +7,21 @@
* `Logger`'s output filenames now look cleaner with `log--YYYY-MM-DD--HH-MM-SS.txt`
* `[Logger#setup]` can now throw `IOException`
* `[PlutoCore]` As a result, `[PlutoApplication#run]` can now throw `Exception`
* `[PlutoLib]` Updated JavaDoc in `ResourceAddress`, `TPL`, `TPNImage`
* `[PlutoLib]` Added `ResourceAddress#openRead` and `ResourceAddress#openWrite`
* `[PlutoLib]` Code cleanup in `MiniTime`, `TPL`
* `[PlutoLib]` Deprecated `TPL#load(String)` in favor of `TPL#load(ResourceAddress)`,
`TPL#load(File)` and `TPL#load(Path)`
* `[PlutoTexturing]` Deprecated the `String` variant of `Texture#load`
to reflect this change
* `[PlutoSpritesheet]` Removed the usage of this method
in `DisposablePlaceholderSprite`
* `[PlutoLib]` Added an option to flip loaded images with `TPL#loadImageSpecial`
and added respective `TPL#loadSpecial` for every `TPL#load`
* `[PlutoLib]` *Removed* `TPJImage`
* `[PlutoLib]` Removed `TPL#loadPixels`
* `[PlutoCore]` Updated `GLFWImageUtil` to remove the usage of `TPJImage`
* `[PlutoCore]` `[PlutoApplication]` now properly closes the `Logger` on exit
* `[PlutoLib]` Various typo fixes
* `[Pluto*]` Deprecated `Severity` for `SmartSeverity` and replaced all usages
* `[Pluto*]` Deprecated `CRLF` with `LF` in all Java source files

View File

@ -48,8 +48,6 @@ public class CursorPositionCallback extends GLFWCursorPosCallback
public boolean isInside(int x, int y, int x2, int y2)
{
boolean inside = this.getX() > x && this.getX() < x2 && this.getY() > y && this.getY() < y2;
return inside;
return this.getX() > x && this.getX() < x2 && this.getY() > y && this.getY() < y2;
}
}

View File

@ -1,5 +1,12 @@
package cz.tefek.pluto;
/**
* Constants shared by all Pluto libraries.
*
* @since pre-alpha
*
* @author 493msi
*/
public class Pluto
{
public static final boolean DEBUG_MODE = Boolean.valueOf(System.getProperty("cz.tefek.pluto.debug"));
@ -8,41 +15,57 @@ public class Pluto
/**
* The year version number, changes with breaking API changes.
*
* @since pre-alpha
* */
public static final int VERSION_YEAR = 20;
/**
* The major version number, changes with breaking API changes.
*
* @since pre-alpha
* */
public static final int VERSION_MAJOR = 2;
/**
* The minor version number, changes with backwards-compatible API changes.
*
* @since pre-alpha
* */
public static final int VERSION_MINOR = 0;
/**
* The patch number, changes with backwards-compatible fixes and patches.
*
* @since pre-alpha
* */
public static final int VERSION_PATCH = 0;
/**
* Denotes whether this build is a pre-release build.
*
* @since pre-alpha
* */
public static final boolean PRERELEASE = true;
/**
* The name of this pre-release, e.g. alpha, beta, RC and similar.
*
* @since pre-alpha
* */
public static final String PRERELEASE_NAME = "alpha";
/**
* The pre-release patch number, incremented by 1 with *any* pre-release change.
* The pre-release patch number, incremented by 1 with *any* pre-release update.
*
* @since pre-alpha
* */
public static final int PRERELEASE_PATCH = 1;
/**
* The combined version string.
*
* @since pre-alpha
* */
public static final String VERSION = VERSION_YEAR + "." + VERSION_MAJOR + "." + VERSION_MINOR + "." + VERSION_PATCH + (PRERELEASE ? "-" + PRERELEASE_NAME + "." + PRERELEASE_PATCH : "");
}

View File

@ -129,7 +129,7 @@ public class MiniTime
for (int i = 1; i < nrs.length; i++)
{
var type = letters[i - 1];
int number = 0;
int number;
try
{
@ -196,10 +196,12 @@ public class MiniTime
/**
* Converts a time span between two Unix-epoch millisecond time points to a
* MiniTime string. <i>Note ALL time spans larger or equal than
* {@link Integer#MAX_VALUE} will be permanently converted to "forever".</i>
* {@link Integer#MAX_VALUE} weeks will be permanently converted to "forever".
* Inputting {@link Long#MAX_VALUE} for the future time point has the same effect.</i>
*
* @param before The first time point in Unix-time milliseconds
* @param after The first time point in Unix-time milliseconds
*
* @return The resulting MiniTime string
*
* @throws IllegalArgumentException on a negative time duration
@ -220,10 +222,12 @@ public class MiniTime
/**
* Converts a time span between now and a future time point in Unix-epoch
* milliseconds to a MiniTime string. <i>Note ALL time spans larger or equal
* than {@link Integer#MAX_VALUE} will be permanently converted to
* "forever".</i>
* than {@link Integer#MAX_VALUE} weeks will be permanently converted to
* "forever". Inputting {@link Long#MAX_VALUE} for the future time point
* has the same effect.</i>
*
* @param future The future time point in Unix time milliseconds
*
* @param future The source time span in milliseconds
* @return The resulting MiniTime string
*
* @throws IllegalArgumentException on a negative time duration
@ -245,7 +249,7 @@ public class MiniTime
/**
* Converts a time span milliseconds to a MiniTime string. <i>Note ALL time
* spans larger or equal than {@link Integer#MAX_VALUE} will be permanently
* spans larger or equal than {@link Integer#MAX_VALUE} weeks will be permanently
* converted to "forever".</i>
*
* @param diff The source time span in milliseconds

View File

@ -1,15 +1,14 @@
package cz.tefek.pluto.io.asl.resource;
import javax.annotation.Nullable;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.nio.file.FileSystems;
import java.nio.file.Path;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
import cz.tefek.pluto.modloader.ModLoaderCore;
/**
@ -94,13 +93,11 @@ public class ResourceAddress
if (as.length == 1)
{
Logger.log(Severity.WARNING, "Please do not use tier 1 addresses, so it doesn't conflict with core assets.");
Logger.log(SmartSeverity.WARNING, "Please do not use tier 1 addresses, so it doesn't conflict with core assets.");
}
for (int i = 0; i < as.length; i++)
for (String branch : as)
{
var branch = as[i];
if (branch.length() < 1 || branch.length() > MAX_BRANCH_STRING_LENGTH)
{
throw new IllegalArgumentException("Length of branch must be higher than 0 and lower than 33, this is not an essay.");
@ -151,9 +148,9 @@ public class ResourceAddress
return raddress;
}
public ResourceAddress fileExtension(String ext)
public ResourceAddress fileExtension(@Nullable String ext)
{
if (ext == null || ext == "")
if (ext == null || "".equals(ext))
{
this.fileExtension = null;
return this;
@ -213,15 +210,7 @@ public class ResourceAddress
@Override
public String toString()
{
StringBuilder sbPath = new StringBuilder(this.resSubscriber.getMod().getModID());
sbPath.append("$");
sbPath.append(this.subAddressToString());
String path = sbPath.toString();
return path;
return this.resSubscriber.getMod().getModID() + "$" + this.subAddressToString();
}
public ResourceAddress copy()
@ -246,12 +235,10 @@ public class ResourceAddress
if (this.hasFileExtension())
{
sbPath.append("." + this.fileExtension);
sbPath.append(".").append(this.fileExtension);
}
String path = sbPath.toString();
return path;
return sbPath.toString();
}
public String subAddressToString()
@ -293,7 +280,7 @@ public class ResourceAddress
var pathBuilder = new StringBuilder(this.resSubscriber.getRootPath());
final var separator = FileSystems.getDefault().getSeparator();
pathBuilder.append(separator);
pathBuilder.append(this.subAddress.stream().collect(Collectors.joining(separator)));
pathBuilder.append(String.join(separator, this.subAddress));
if (this.hasFileExtension())
{

View File

@ -1,16 +1,15 @@
package cz.tefek.pluto.io.asl.resource.type;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import cz.tefek.pluto.io.asl.resource.Resource;
import cz.tefek.pluto.io.asl.resource.ResourceAddress;
import cz.tefek.pluto.io.asl.resource.ResourceHelper;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
/**
* {@link ResourceAddress} in, {@link BufferedImage} out.
@ -38,7 +37,7 @@ public class ResourceImage extends Resource<BufferedImage>
}
catch (IOException e)
{
Logger.log(Severity.ERROR, "Could not load BufferedImage: " + this.address.toString() + ", will load placeholder.");
Logger.log(SmartSeverity.ERROR, "Could not load BufferedImage: " + this.address.toString() + ", will load placeholder.");
Logger.log(e);
try
@ -47,7 +46,7 @@ public class ResourceImage extends Resource<BufferedImage>
}
catch (IOException e1)
{
Logger.log(Severity.ERROR, "Placeholder BufferedImage not found: " + ResourceHelper.GLOBAL_ROOT + "data/assets/err/missingTex.png");
Logger.log(SmartSeverity.ERROR, "Placeholder BufferedImage not found: " + ResourceHelper.GLOBAL_ROOT + "data/assets/err/missingTex.png");
Logger.log("This is not good! :C");
Logger.log(e1);

View File

@ -1,13 +1,13 @@
package cz.tefek.pluto.io.asl.resource.type;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import cz.tefek.pluto.io.asl.resource.Resource;
import cz.tefek.pluto.io.asl.resource.ResourceAddress;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
/**
* {@link ResourceAddress} in, {@link InputStream} out.
@ -26,12 +26,12 @@ public class ResourceInputStream extends Resource<InputStream>
{
try
{
return new FileInputStream(this.address.toPath());
return Files.newInputStream(this.address.toNIOPath());
}
catch (IOException e)
{
Logger.log(Severity.EXCEPTION, "Failed to open " + this.address + "!");
Logger.log(Severity.EXCEPTION, e);
Logger.log(SmartSeverity.ERROR, "Failed to open " + this.address + "!");
Logger.log(e);
}
return null;

View File

@ -30,7 +30,7 @@ public class Logger
private static OutputStream fileLog = null;
/**
* Initializes up the logger and replaces the standard output and standard error output with the logger methods.
* Initializes the logger and replaces the standard output and standard error output with the logger methods.
*
* <p>
* <em>

View File

@ -4,7 +4,10 @@ package cz.tefek.pluto.io.logger;
* Message severity.
*
* @author 493msi
*
* @deprecated Use {@link SmartSeverity} instead.
*/
@Deprecated
public enum Severity implements ISeverity
{
INFO("[INFO] ", false),
@ -19,6 +22,7 @@ public enum Severity implements ISeverity
Severity(String name, boolean usesStdErr)
{
this.displayName = name;
this.usesStdErr = usesStdErr;
}
@Override

View File

@ -1,35 +0,0 @@
package cz.tefek.pluto.tpl;
public class TPJImage
{
int[] data;
int width;
int height;
public TPJImage(int[] pixels, int width, int height)
{
this.data = pixels;
this.width = width;
this.height = height;
}
public int getWidth()
{
return this.width;
}
public int getHeight()
{
return this.height;
}
public int[] getData()
{
return this.data;
}
public int pixelAt(int x, int y)
{
return this.data[x + y * this.width];
}
}

View File

@ -1,14 +1,17 @@
package cz.tefek.pluto.tpl;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.awt.image.DataBuffer;
import java.awt.image.DataBufferByte;
import java.awt.image.Raster;
import java.awt.image.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.annotation.Nullable;
import javax.imageio.ImageIO;
import cz.tefek.pluto.io.asl.resource.ResourceAddress;
@ -16,172 +19,294 @@ import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.SmartSeverity;
/**
* Quick ABGR (8-bit per channel, 32 bits per pixel) texture loader for OpenGL
* use. Color component swizzling may be needed.
* Quick ABGR (8-bit per channel, 32 bits per pixel) image loader for OpenGL textures.
* Color component swizzling may be needed.
*
* FIXME: Refactor {@link TPL#loadBufferedImage}
*
* @author 493msi
*
* @see TPNImage
*
* @since pre-alpha
*/
public class TPL
{
private static final int PLACEHOLDER_SIZE = 16;
private static final int PLACEHOLDER_CHECKEDBOARD = 8;
private static final int PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE = PLACEHOLDER_SIZE / PLACEHOLDER_CHECKEDBOARD;
public static TPNImage load(ResourceAddress file)
private static final BufferedImage placeholder;
static
{
return file == null ? loadImage(null) : load(file.toPath());
placeholder = new BufferedImage(PLACEHOLDER_SIZE, PLACEHOLDER_SIZE, BufferedImage.TYPE_INT_ARGB);
var data = placeholder.getData();
var dataBuffer = (DataBufferInt) data.getDataBuffer();
for (int i = 0; i < PLACEHOLDER_SIZE * PLACEHOLDER_SIZE; i++)
{
int x = i % PLACEHOLDER_SIZE;
int y = i / PLACEHOLDER_SIZE;
boolean checker = x / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2 == y / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2;
dataBuffer.setElem(i, checker ? 0xFFFF0000 : 0xFF000000);
}
}
public static TPNImage load(String file)
// TODO: Fix this mess
private static BufferedImage loadBufferedImage(@Nullable Object source)
{
if (file == null)
{
return loadImage(null);
}
var inputStream = (InputStream) null;
try
{
return loadImage(ImageIO.read(new File(file)));
if (source instanceof ResourceAddress)
{
inputStream = Files.newInputStream(((ResourceAddress) source).toNIOPath());
}
else if (source instanceof String)
{
inputStream = new FileInputStream((String) source);
}
else if (source instanceof File)
{
inputStream = new FileInputStream((File) source);
}
else if (source instanceof Path)
{
inputStream = Files.newInputStream((Path) source);
}
if (inputStream != null)
{
return ImageIO.read(inputStream);
}
}
catch (Exception e)
{
Logger.log(SmartSeverity.ERROR, "[TPL] Image could not be loaded: " + file);
Logger.log(SmartSeverity.ERROR, "[TPL] Image could not be loaded: " + source);
Logger.log(e);
return loadImage(null);
}
}
public static TPNImage loadImage(BufferedImage image)
finally
{
boolean remake = false;
int width = 0;
int height = 0;
try
{
if (inputStream != null)
inputStream.close();
}
catch (IOException e)
{
Logger.log(SmartSeverity.ERROR, "[TPL] Failed to close: " + source);
Logger.log(e);
}
}
return placeholder;
}
/**
* Loads an image from a file the denoted by the input {@link ResourceAddress} into a {@link TPNImage} buffer.
*
* If the input {@link ResourceAddress} is null, a placeholder will be generated.
*
* @param address The source {@link ResourceAddress}, from which the image will be loaded
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since pre-alpha
* */
public static TPNImage load(@Nullable ResourceAddress address)
{
return loadImage(loadBufferedImage(address));
}
/**
* Loads an image from the denoted filename to a {@link TPNImage} buffer.
*
* If the input filename is null, a placeholder will be generated.
*
* @deprecated Use the {@link TPL#load(ResourceAddress)} or {@link TPL#load(File)} variants.
*
* @param filename The source filename, from which the image will be loaded
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since pre-alpha
* */
@Deprecated
public static TPNImage load(@Nullable String filename)
{
return loadImage(loadBufferedImage(filename));
}
/**
* Loads an image from the input {@link File} into a {@link TPNImage} buffer.
*
* If the input {@link File} is null, a placeholder will be generated.
*
* @param file The source {@link File}, from which the image will be loaded
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage load(@Nullable File file)
{
return loadImage(loadBufferedImage(file));
}
/**
* Loads an image from a file the denoted by the input {@link Path} into a {@link TPNImage} buffer.
*
* If the input {@link Path} is null, a placeholder will be generated.
*
* @param path The source {@link Path}, from which the image will be loaded
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage load(@Nullable Path path)
{
return loadImage(loadBufferedImage(path));
}
/**
* Loads an image from a file the denoted by the input {@link ResourceAddress} into a {@link TPNImage} buffer.
*
* If the input {@link ResourceAddress} is null, a placeholder will be generated.
*
* @param address The source {@link ResourceAddress}, from which the image will be loaded
* @param flipY Whether the image should flipped vertically (for OpenGL uses)
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage loadSpecial(@Nullable ResourceAddress address, boolean flipY)
{
return loadImageSpecial(loadBufferedImage(address), flipY);
}
/**
* Loads an image from the input {@link File} into a {@link TPNImage} buffer.
*
* If the input {@link File} is null, a placeholder will be generated.
*
* @param file The source {@link File}, from which the image will be loaded
* @param flipY Whether the image should flipped vertically (for OpenGL uses)
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage load(@Nullable File file, boolean flipY)
{
return loadImageSpecial(loadBufferedImage(file), flipY);
}
/**
* Loads an image from a file the denoted by the input {@link Path} into a {@link TPNImage} buffer.
*
* If the input {@link Path} is null, a placeholder will be generated.
*
* @param path The source {@link Path}, from which the image will be loaded
* @param flipY Whether the image should flipped vertically (for OpenGL uses)
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage loadSpecial(@Nullable Path path, boolean flipY)
{
return loadImageSpecial(loadBufferedImage(path), flipY);
}
/**
* Writes a {@link BufferedImage} into a {@link TPNImage} buffer.
*
* If the input {@link Path} is null, a placeholder will be generated.
*
* @param image The source {@link BufferedImage}
* @param flipY Whether the image should flipped vertically (for OpenGL uses)
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since 20.2.0.0-alpha.1
* */
public static TPNImage loadImageSpecial(@Nullable BufferedImage image, boolean flipY)
{
if (image == null)
{
Logger.log(SmartSeverity.WARNING, "[TPL] Null BufferedImage supplied, generating a placeholder.");
remake = true;
return loadImageSpecial(placeholder, flipY);
}
else
{
width = image.getWidth();
height = image.getHeight();
int width = image.getWidth();
int height = image.getHeight();
if (width > 16384 || height > 16384 || width < 1 || height < 1)
{
Logger.log(SmartSeverity.ERROR, "[TPL] BufferedImage size is invalid (< 1 or > 16384), generating a placeholder.");
remake = true;
return loadImageSpecial(placeholder, flipY);
}
}
if (remake)
{
width = PLACEHOLDER_SIZE;
height = PLACEHOLDER_SIZE;
Logger.log(SmartSeverity.INFO, "[TPL] Generating a substitute image...");
ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4);
buffer.order(ByteOrder.nativeOrder());
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
boolean checker = x / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2 == y / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2;
buffer.put((byte) 0xff); // A
buffer.put((byte) 0x00); // B
buffer.put((byte) 0x00); // G
buffer.put((byte) (checker ? 0xff : 0x00)); // R
}
buffer.flip();
return new TPNImage(buffer, width, height);
}
ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder());
BufferedImage copy = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_4BYTE_ABGR);
Graphics2D imgGraphics = copy.createGraphics();
imgGraphics.drawImage(image, 0, copy.getHeight(), copy.getWidth(), 0, 0, 0, image.getWidth(), image.getHeight(), null); // I wonder if this is pixel-perfect
imgGraphics.drawImage(image,
0, flipY ? copy.getHeight() : 0, copy.getWidth(), flipY ? 0 : copy.getHeight(),
0, 0, image.getWidth(), image.getHeight(),
null); // I wonder if this is pixel-perfect
imgGraphics.dispose();
Raster data = copy.getData();
Raster data = copy.getRaster();
DataBuffer dataBuffer = data.getDataBuffer();
DataBufferByte byteBuffer = (DataBufferByte) dataBuffer;
byte[] byteData = byteBuffer.getData();
ByteBuffer buffer = ByteBuffer.allocateDirect(width * height * 4).order(ByteOrder.nativeOrder());
buffer.put(byteData);
buffer.flip();
return new TPNImage(buffer, width, height);
}
public static TPJImage loadPixels(String file)
/**
* Writes a {@link BufferedImage} into a {@link TPNImage} buffer.
*
* If the input {@link Path} is null, a placeholder will be generated.
*
* @param image The source {@link BufferedImage}
*
* @return The output {@link TPNImage}, never null
*
* @see TPNImage
*
* @since pre-alpha
* */
public static TPNImage loadImage(@Nullable BufferedImage image)
{
TPJImage tImg = null;
BufferedImage image = null;
boolean remake = false;
int width = 0;
int height = 0;
try
{
image = ImageIO.read(new File(file));
width = image.getWidth();
height = image.getHeight();
}
catch (Exception e)
{
Logger.log(SmartSeverity.ERROR, "[TPL] Image could not be loaded: " + file);
Logger.log(e);
remake = true;
}
if (width > 16384 || height > 16384 || width < 1 || height < 1)
{
Logger.log(SmartSeverity.ERROR, "[TPL] Image size is invalid (< 1 or > 16384): " + file);
Logger.log(SmartSeverity.ERROR, "[TPL] A replacement will be generated.");
remake = true;
}
if (remake)
{
width = PLACEHOLDER_SIZE;
height = PLACEHOLDER_SIZE;
tImg = new TPJImage(new int[width * height], width, height);
Logger.log(SmartSeverity.INFO, "[TPL] Generating a substitute image...");
for (int i = 0; i < width * height; i++)
{
int x = i % width;
int y = i / width;
boolean checker = x / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2 == y / PLACEHOLDER_CHECKEDBOARD_SQUARE_SIZE % 2;
tImg.data[i] = checker ? 0xffff0000 : 0xff000000;
}
return tImg;
}
tImg = new TPJImage(new int[width * height], width, height);
for (int i = 0; i < width * height; i++)
{
int pixel = image.getRGB(i % width, i / width);
tImg.data[i] = pixel;
}
return tImg;
return loadImageSpecial(image, true);
}
}

View File

@ -2,12 +2,32 @@ package cz.tefek.pluto.tpl;
import java.nio.ByteBuffer;
/**
* A wrapper around a native color buffer for easier handling
* by various APIs, such as OpenGL and GLFW.
*
* @implNote TPNImage is <em>always</em> ABGR due to image format
* limitations of {@link java.awt.image.BufferedImage}
*
* @author 493msi
*
* @since pre-alpha
*/
public class TPNImage
{
ByteBuffer data;
int width;
int height;
private final ByteBuffer data;
private final int width;
private final int height;
/**
* Creates a new {@link TPNImage} from the specified buffer, width and height.
*
* @param bfr The input {@link ByteBuffer}
* @param width This image's width
* @param height This image's height
*
* @since pre-alpha
* */
public TPNImage(ByteBuffer bfr, int width, int height)
{
this.data = bfr;
@ -15,18 +35,39 @@ public class TPNImage
this.height = height;
}
/**
* Returns the width of the color buffer.
*
* @return The width of this {@link TPNImage}
*
* @since pre-alpha
* */
public int getWidth()
{
return this.width;
}
/**
* Returns the height of the color buffer.
*
* @return The height of this {@link TPNImage}
*
* @since pre-alpha
* */
public int getHeight()
{
return this.height;
}
/**
* Returns a read-only view of the color buffer.
*
* @return This image's color {@link ByteBuffer}
*
* @since pre-alpha
* */
public ByteBuffer getData()
{
return this.data;
return this.data.asReadOnlyBuffer();
}
}

View File

@ -1,5 +1,7 @@
package cz.tefek.pluto.engine.graphics.sprite;
import java.awt.image.BufferedImage;
import cz.tefek.pluto.engine.graphics.texture.MagFilter;
import cz.tefek.pluto.engine.graphics.texture.MinFilter;
import cz.tefek.pluto.engine.graphics.texture.WrapMode;
@ -11,7 +13,7 @@ public class DisposablePlaceholderSprite extends DisposableTextureSprite
{
super(new RectangleTexture());
this.spriteTexture.load((String) null, MagFilter.NEAREST, MinFilter.NEAREST, WrapMode.CLAMP_TO_EDGE, WrapMode.CLAMP_TO_EDGE);
this.spriteTexture.load((BufferedImage) null, MagFilter.NEAREST, MinFilter.NEAREST, WrapMode.CLAMP_TO_EDGE, WrapMode.CLAMP_TO_EDGE);
this.width = this.spriteTexture.getWidth();
this.height = this.spriteTexture.getHeight();
}

View File

@ -6,7 +6,7 @@ import cz.tefek.pluto.engine.graphics.sprite.Sprite;
import cz.tefek.pluto.engine.graphics.sprite.SpriteDisposable;
import cz.tefek.pluto.engine.graphics.sprite.TileSprite;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
public abstract class TiledSpriteSheet<T> extends SpriteSheet<T>
{
@ -65,7 +65,7 @@ public abstract class TiledSpriteSheet<T> extends SpriteSheet<T>
protected void expand()
{
Logger.logf(Severity.INFO, "Spritesheet #%d: Expanding from %dx%d to ", this.id, this.spriteSheetWidth, this.spriteSheetHeight);
Logger.logf(SmartSeverity.INFO, "Spritesheet #%d: Expanding from %dx%d to ", this.id, this.spriteSheetWidth, this.spriteSheetHeight);
this.spriteSheetWidth *= 2;
this.spriteSheetHeight *= 2;
@ -79,7 +79,7 @@ public abstract class TiledSpriteSheet<T> extends SpriteSheet<T>
protected void upscale(int factor)
{
Logger.logf(Severity.INFO, "Spritesheet #%d: Upscaling from %dx%d to ", this.id, this.tileWidth, this.tileHeight);
Logger.logf(SmartSeverity.INFO, "Spritesheet #%d: Upscaling from %dx%d to ", this.id, this.tileWidth, this.tileHeight);
this.tileWidth *= factor;
this.tileHeight *= factor;

View File

@ -3,6 +3,8 @@ package cz.tefek.pluto.engine.buffer;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWImage;
import java.nio.file.Path;
import cz.tefek.pluto.tpl.TPL;
/**
@ -28,23 +30,27 @@ public class GLFWImageUtil
{
var icon = GLFWImage.create(icons.length);
for (int iconIndex = 0; iconIndex < icons.length; iconIndex++)
for (String iconPath : icons)
{
var img = TPL.loadPixels(icons[iconIndex]);
var img = TPL.loadSpecial(Path.of(iconPath), false);
var imgData = img.getData();
var imgWidth = img.getWidth();
var imgHeight = img.getHeight();
int imgWidth = img.getWidth();
int imgHeight = img.getHeight();
var byteBuf = BufferUtils.createByteBuffer(imgWidth * imgHeight * 4);
int pixelCount = imgWidth * imgHeight;
int bytesPerPixel = 4;
var byteBuf = BufferUtils.createByteBuffer(pixelCount * bytesPerPixel);
for (int i = 0; i < imgHeight * imgWidth; i++)
byte[] px = new byte[bytesPerPixel];
for (int i = 0; i < pixelCount; i++)
{
var data = imgData[i];
px[3] = imgData.get(); // A
px[2] = imgData.get(); // B
px[1] = imgData.get(); // G
px[0] = imgData.get(); // R
byteBuf.put((byte) ((data & 0x00ff0000) >> 16));
byteBuf.put((byte) ((data & 0x0000ff00) >> 8));
byteBuf.put((byte) (data & 0x000000ff));
byteBuf.put((byte) ((data & 0xff000000) >> 24));
byteBuf.put(px);
}
byteBuf.flip();

View File

@ -1,10 +1,6 @@
package cz.tefek.pluto.engine.display;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.glfw.GLFWErrorCallback;
import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.glfw.GLFWVidMode;
import org.lwjgl.glfw.GLFWWindowSizeCallback;
import org.lwjgl.glfw.*;
import org.lwjgl.opengl.ARBDebugOutput;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL33;
@ -13,7 +9,6 @@ import org.lwjgl.system.MemoryUtil;
import cz.tefek.pluto.engine.gl.GLDebugInfo;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
/**
@ -72,7 +67,7 @@ public class Display
{
if (Display.this.debugMode)
{
Logger.logf(Severity.INFO, "Resized to %dx%d.\n", width, height);
Logger.logf(SmartSeverity.INFO, "Resized to %dx%d.\n", width, height);
}
Display.this.width = width;

View File

@ -1,23 +1,21 @@
package cz.tefek.pluto.engine.graphics.texture;
import java.util.Arrays;
import org.lwjgl.opengl.GL33;
import org.lwjgl.system.MemoryUtil;
import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;
import java.util.Arrays;
import cz.tefek.pluto.io.asl.resource.ResourceAddress;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
import cz.tefek.pluto.tpl.TPL;
import cz.tefek.pluto.tpl.TPNImage;
public abstract class Texture
{
protected int glID = 0;
protected int glID;
protected final int type;
protected final int dimensions;
@ -138,7 +136,7 @@ public abstract class Texture
{
if (wrapOptions.length != this.dimensions)
{
Logger.log(Severity.ERROR, "Error: WrapMode option count does not match texture's dimensions.");
Logger.log(SmartSeverity.ERROR, "Error: WrapMode option count does not match texture's dimensions.");
return this;
}
@ -198,6 +196,7 @@ public abstract class Texture
this.load(file.toPath(), magFilter, minFilter, wrap);
}
@Deprecated
public void load(String file, MagFilter magFilter, MinFilter minFilter, WrapMode... wrap)
{
TPNImage image = TPL.load(file);

View File

@ -1,13 +1,13 @@
package cz.tefek.pluto.engine.graphics.texture.texture2d;
import java.util.Arrays;
import org.lwjgl.opengl.GL33;
import java.util.Arrays;
import cz.tefek.pluto.engine.graphics.texture.Texture;
import cz.tefek.pluto.engine.graphics.texture.WrapMode;
import cz.tefek.pluto.io.logger.Logger;
import cz.tefek.pluto.io.logger.Severity;
import cz.tefek.pluto.io.logger.SmartSeverity;
public class RectangleTexture extends Texture
{
@ -27,7 +27,7 @@ public class RectangleTexture extends Texture
{
if (Arrays.stream(wrapOptions).anyMatch(WrapMode.repeatModes::contains))
{
Logger.log(Severity.ERROR, "Error: Rectangle textures do not support repeat wrap modes!");
Logger.log(SmartSeverity.ERROR, "Error: Rectangle textures do not support repeat wrap modes!");
return this;
}