Add support for Paint which includes gradients and images in GUI
This commit is contained in:
@@ -19,6 +19,10 @@ public interface GUI extends Renderable, Disposable, KeyEventHandler {
|
||||
|
||||
Color createColor();
|
||||
|
||||
Paint createPaint();
|
||||
|
||||
Image getImage(String imageUid);
|
||||
|
||||
void beginPath();
|
||||
|
||||
void closePath();
|
||||
@@ -71,13 +75,25 @@ public interface GUI extends Renderable, Disposable, KeyEventHandler {
|
||||
|
||||
void setFillColor(Color color);
|
||||
|
||||
void setFillPaint(Paint paint);
|
||||
|
||||
void fill();
|
||||
|
||||
void setStrokeColor(Color color);
|
||||
|
||||
void setStrokePaint(Paint paint);
|
||||
|
||||
void setStrokeWidth(float width);
|
||||
|
||||
void stroke();
|
||||
|
||||
void boxGradient(float x, float y, float width, float height, float radius, float feather, Color inner, Color outer, Paint target);
|
||||
|
||||
void linearGradient(float x, float y, float endX, float endY, Color start, Color end, Paint target);
|
||||
|
||||
void radialGradient(float x, float y, float innerRadius, float outerRadius, Color start, Color end, Paint target);
|
||||
|
||||
void imagePattern(float x, float y, float width, float height, float angle, float alpha, Image image, Paint target);
|
||||
|
||||
void clip(float x, float y, float width, float height);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.bartlomiejpluta.base.api.game.gui.base;
|
||||
|
||||
public interface Image {
|
||||
int getWidth();
|
||||
|
||||
int getHeight();
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
package com.bartlomiejpluta.base.api.game.gui.base;
|
||||
|
||||
public interface Paint {
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.bartlomiejpluta.base.api.game.gui.component;
|
||||
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.GUI;
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.Image;
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.Paint;
|
||||
import com.bartlomiejpluta.base.api.game.screen.Screen;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
public class ImageView extends BaseComponent {
|
||||
private final GUI gui;
|
||||
private final Paint paint;
|
||||
|
||||
private Image image;
|
||||
private float angle = 0;
|
||||
private float opacity = 1;
|
||||
private float scaleX = 1;
|
||||
private float scaleY = 1;
|
||||
|
||||
public ImageView(GUI gui, String imageUid) {
|
||||
this.gui = requireNonNull(gui);
|
||||
this.paint = gui.createPaint();
|
||||
this.image = gui.getImage(imageUid);
|
||||
}
|
||||
|
||||
public void setImage(String imageUid) {
|
||||
this.image = gui.getImage(imageUid);
|
||||
}
|
||||
|
||||
public void setAngle(float angle) {
|
||||
this.angle = angle;
|
||||
}
|
||||
|
||||
public void setOpacity(float opacity) {
|
||||
this.opacity = opacity;
|
||||
}
|
||||
|
||||
public void setScaleX(float scaleX) {
|
||||
this.scaleX = scaleX;
|
||||
}
|
||||
|
||||
public void setScaleY(float scaleY) {
|
||||
this.scaleY = scaleY;
|
||||
}
|
||||
|
||||
public void setScale(float scaleX, float scaleY) {
|
||||
this.scaleX = scaleX;
|
||||
this.scaleY = scaleY;
|
||||
}
|
||||
|
||||
public void setScale(float scale) {
|
||||
this.scaleX = scale;
|
||||
this.scaleY = scale;
|
||||
}
|
||||
|
||||
public Image getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public float getAngle() {
|
||||
return angle;
|
||||
}
|
||||
|
||||
public float getOpacity() {
|
||||
return opacity;
|
||||
}
|
||||
|
||||
public float getScaleX() {
|
||||
return scaleX;
|
||||
}
|
||||
|
||||
public float getScaleY() {
|
||||
return scaleY;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getContentWidth() {
|
||||
return image.getWidth() * scaleX;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getContentHeight() {
|
||||
return image.getHeight() * scaleY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(Screen screen, GUI gui) {
|
||||
var posX = x + paddingLeft;
|
||||
var posY = y + paddingTop;
|
||||
var width = getWidth() - paddingLeft - paddingRight;
|
||||
var height = getHeight() - paddingTop - paddingBottom;
|
||||
|
||||
gui.beginPath();
|
||||
gui.drawRectangle(posX, posY, width, height);
|
||||
gui.imagePattern(posX, posY, width, height, angle, opacity, image, paint);
|
||||
gui.setFillPaint(paint);
|
||||
gui.fill();
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@ import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.lwjgl.nanovg.NVGColor;
|
||||
import org.lwjgl.nanovg.NVGPaint;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.*;
|
||||
@@ -32,8 +33,9 @@ public class NanoVGGUI implements GUI {
|
||||
private ScreenWidget screenWidget;
|
||||
|
||||
private final List<NanoVGColor> colors = new LinkedList<>();
|
||||
private final List<NanoVGPaint> paints = new LinkedList<>();
|
||||
private final Set<String> loadedFonts = new HashSet<>();
|
||||
private final Map<String, Integer> loadedImages = new HashMap<>();
|
||||
private final Map<String, NanoVGImage> loadedImages = new HashMap<>();
|
||||
|
||||
public void init(Screen screen) {
|
||||
context = nvgCreate(NVG_ANTIALIAS | NVG_STENCIL_STROKES);
|
||||
@@ -73,6 +75,35 @@ public class NanoVGGUI implements GUI {
|
||||
return color;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Paint createPaint() {
|
||||
log.info("Creating new GUI paint");
|
||||
var paint = new NanoVGPaint(NVGPaint.create());
|
||||
paints.add(paint);
|
||||
return paint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image getImage(String imageUid) {
|
||||
var image = loadedImages.get(imageUid);
|
||||
|
||||
if (image == null) {
|
||||
log.info("Loading GUI image with UID: [{}]", imageUid);
|
||||
var data = imageManager.loadObjectByteBuffer(imageUid);
|
||||
var handle = nvgCreateImageMem(context, 0, data);
|
||||
var width = new int[1];
|
||||
var height = new int[1];
|
||||
nvgImageSize(context, handle, width, height);
|
||||
|
||||
log.info("GUI image with UID: [{}] and size {}x{} has been loaded", imageUid, width, height);
|
||||
image = new NanoVGImage(handle, width[0], height[0]);
|
||||
|
||||
loadedImages.put(imageUid, image);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginPath() {
|
||||
nvgBeginPath(context);
|
||||
@@ -168,6 +199,11 @@ public class NanoVGGUI implements GUI {
|
||||
nvgFillColor(context, ((NanoVGColor) color).getColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFillPaint(Paint paint) {
|
||||
nvgFillPaint(context, ((NanoVGPaint) paint).getPaint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void fill() {
|
||||
nvgFill(context);
|
||||
@@ -178,11 +214,75 @@ public class NanoVGGUI implements GUI {
|
||||
nvgStrokeColor(context, ((NanoVGColor) color).getColor());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrokePaint(Paint paint) {
|
||||
nvgStrokePaint(context, ((NanoVGPaint) paint).getPaint());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stroke() {
|
||||
nvgStroke(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void boxGradient(float x, float y, float width, float height, float radius, float feather, Color inner, Color outer, Paint target) {
|
||||
nvgBoxGradient(
|
||||
context,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
radius,
|
||||
feather,
|
||||
((NanoVGColor) inner).getColor(),
|
||||
((NanoVGColor) outer).getColor(),
|
||||
((NanoVGPaint) target).getPaint()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void linearGradient(float x, float y, float endX, float endY, Color start, Color end, Paint target) {
|
||||
nvgLinearGradient(
|
||||
context,
|
||||
x,
|
||||
y,
|
||||
endX,
|
||||
endY,
|
||||
((NanoVGColor) start).getColor(),
|
||||
((NanoVGColor) end).getColor(),
|
||||
((NanoVGPaint) target).getPaint()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void radialGradient(float x, float y, float innerRadius, float outerRadius, Color start, Color end, Paint target) {
|
||||
nvgRadialGradient(
|
||||
context,
|
||||
x,
|
||||
y,
|
||||
innerRadius,
|
||||
outerRadius,
|
||||
((NanoVGColor) start).getColor(),
|
||||
((NanoVGColor) end).getColor(),
|
||||
((NanoVGPaint) target).getPaint()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void imagePattern(float x, float y, float width, float height, float angle, float alpha, Image image, Paint target) {
|
||||
nvgImagePattern(
|
||||
context,
|
||||
x,
|
||||
y,
|
||||
width,
|
||||
height,
|
||||
angle,
|
||||
((NanoVGImage) image).getImageHandle(),
|
||||
alpha,
|
||||
((NanoVGPaint) target).getPaint()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStrokeWidth(float width) {
|
||||
nvgStrokeWidth(context, width);
|
||||
@@ -255,7 +355,15 @@ public class NanoVGGUI implements GUI {
|
||||
public void dispose() {
|
||||
log.info("Disposing GUI color buffers");
|
||||
colors.forEach(NanoVGColor::dispose);
|
||||
log.info("Disposed {} GUI colors", colors.size());
|
||||
log.info("Disposed {} GUI color buffers", colors.size());
|
||||
|
||||
log.info("Disposing GUI paint buffers");
|
||||
paints.forEach(NanoVGPaint::dispose);
|
||||
log.info("Disposed {} GUI paint buffers", paints.size());
|
||||
|
||||
log.info("Disposing GUI images");
|
||||
loadedImages.values().stream().map(NanoVGImage::getImageHandle).forEach(h -> nvgDeleteImage(context, h));
|
||||
log.info("Disposed {} GUI images", loadedImages.size());
|
||||
|
||||
log.info("Disposing GUI context");
|
||||
nvgDelete(context);
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.bartlomiejpluta.base.engine.gui.render;
|
||||
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.Image;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.ToString;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
public class NanoVGImage implements Image {
|
||||
private final int imageHandle;
|
||||
private final int width;
|
||||
private final int height;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package com.bartlomiejpluta.base.engine.gui.render;
|
||||
|
||||
import com.bartlomiejpluta.base.api.game.gui.base.Paint;
|
||||
import com.bartlomiejpluta.base.api.internal.gc.Disposable;
|
||||
import lombok.*;
|
||||
import org.lwjgl.nanovg.NVGPaint;
|
||||
|
||||
@Getter
|
||||
@ToString
|
||||
@EqualsAndHashCode
|
||||
@RequiredArgsConstructor
|
||||
public class NanoVGPaint implements Paint, Disposable {
|
||||
|
||||
@NonNull
|
||||
private final NVGPaint paint;
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
paint.free();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user