TPL refactor, unified line endings, JavaDoc and full switch to SmartSeverity
This commit is contained in:
parent
60fae86237
commit
2b065249ee
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 : "");
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue