Compare commits
3 Commits
721185c413
...
2dc18a01fb
Author | SHA1 | Date |
---|---|---|
DaniTheSkunk | 2dc18a01fb | |
DaniTheSkunk | 903e5246dc | |
DaniTheSkunk | 009f80dd3a |
26
Test.java
26
Test.java
|
@ -1,4 +1,5 @@
|
||||||
import com.danitheskunk.skunkworks.*;
|
import com.danitheskunk.skunkworks.*;
|
||||||
|
import com.danitheskunk.skunkworks.gfx.Color;
|
||||||
|
|
||||||
public class Test {
|
public class Test {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
@ -26,8 +27,9 @@ public class Test {
|
||||||
var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16));
|
var tileset = window.loadTextureArray("C:\\stream\\coding\\rlc\\tilemap.png", new Vec2i(16, 16));
|
||||||
var font = window.loadFontTileset("EGA8x14.png");
|
var font = window.loadFontTileset("EGA8x14.png");
|
||||||
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16*8.f);
|
var font2 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16*8.f);
|
||||||
|
var font3 = window.loadFontTTF("fonts\\LiberationSans-Regular.ttf", 16);
|
||||||
var tex = window.loadTexture(img);
|
var tex = window.loadTexture(img);
|
||||||
var slice = window.loadNineSlice("demoassets\\9slice-1.png");
|
var slice = window.loadNineSlice("demoassets\\9slice-2.png");
|
||||||
//window.setDebug(true);
|
//window.setDebug(true);
|
||||||
|
|
||||||
while(!window.shouldClose()) {
|
while(!window.shouldClose()) {
|
||||||
|
@ -35,23 +37,27 @@ public class Test {
|
||||||
var renderContext = window.renderStart();
|
var renderContext = window.renderStart();
|
||||||
renderContext.drawTextureRectangle(
|
renderContext.drawTextureRectangle(
|
||||||
new Recti(0, 0, 1280, 720),
|
new Recti(0, 0, 1280, 720),
|
||||||
tex
|
tex,
|
||||||
);
|
false
|
||||||
renderContext.drawTextureRectangle(
|
|
||||||
new Recti(new Vec2i(200, 100), tex2.getSize()),
|
|
||||||
tex2
|
|
||||||
);
|
);
|
||||||
|
//renderContext.drawTextureRectangle(
|
||||||
|
// new Recti(new Vec2i(200, 100), tex2.getSize()),
|
||||||
|
// tex2,
|
||||||
|
// true
|
||||||
|
//);
|
||||||
|
|
||||||
renderContext.drawTextureRectangle(
|
renderContext.drawTextureRectangle(
|
||||||
new Recti(new Vec2i(400, 400), new Vec2i(16, 16)),
|
new Recti(new Vec2i(400, 400), new Vec2i(160, 160)),
|
||||||
tileset.get(0x30)
|
tileset.get(0x30),
|
||||||
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
renderContext.drawString(new Vec2i(100, 100), "hello world mew", font);
|
|
||||||
renderContext.drawString(new Vec2i(710, 140), "hello world mew", font2);
|
renderContext.drawString(new Vec2i(710, 140), "hello world mew", font2);
|
||||||
|
|
||||||
|
|
||||||
renderContext.drawNineSlice(slice, new Recti(100, 100, 1080, 520));
|
renderContext.drawNineSlice(slice, new Recti(100, 100, 75, 23));
|
||||||
|
//renderContext.drawString(new Vec2i(118, 117), "Meow", font3, new Color(0,0,0));
|
||||||
|
renderContext.drawString(new Vec2i(122, 105), "Meow", font, new Color(0,0,0));
|
||||||
window.renderFinish(renderContext);
|
window.renderFinish(renderContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,20 +8,76 @@ import static org.lwjgl.opengl.GL46.*;
|
||||||
class RenderContext extends BaseRenderContext implements IRenderContext {
|
class RenderContext extends BaseRenderContext implements IRenderContext {
|
||||||
private final TextureAtlas atlas;
|
private final TextureAtlas atlas;
|
||||||
private final int texCoordIndex;
|
private final int texCoordIndex;
|
||||||
|
private final int texOffsetIndex;
|
||||||
|
private final int texSizeIndex;
|
||||||
|
private final int tintIndex;
|
||||||
|
|
||||||
public RenderContext(TextureAtlas atlas, int texCoordIndex) {
|
public RenderContext(TextureAtlas atlas, int texCoordIndex, int texOffsetIndex, int texSizeIndex, int tintIndex) {
|
||||||
this.atlas = atlas;
|
this.atlas = atlas;
|
||||||
this.texCoordIndex = texCoordIndex;
|
this.texCoordIndex = texCoordIndex;
|
||||||
|
this.texOffsetIndex = texOffsetIndex;
|
||||||
|
this.texSizeIndex = texSizeIndex;
|
||||||
|
this.tintIndex = tintIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawNineSlice(NineSlice slice, Recti rect) {
|
public void drawNineSlice(NineSlice slice, Recti rect) {
|
||||||
var centerWidth = Math.min(0, rect.getWidth() - slice.getLeft().getSize().getX() - slice.getRight().getSize().getX());
|
var centerWidth = Math.max(0, rect.getWidth() - slice.getLeft().getSize().getX() - slice.getRight().getSize().getX());
|
||||||
var centerHeight = Math.min(0, rect.getHeight() - slice.getTop().getSize().getY() - slice.getBottom().getSize().getY());
|
var centerHeight = Math.max(0, rect.getHeight() - slice.getTop().getSize().getY() - slice.getBottom().getSize().getY());
|
||||||
var pos = rect.getPos();
|
var pos = rect.getPos();
|
||||||
var size = rect.getSize();
|
var size = rect.getSize();
|
||||||
|
|
||||||
drawTexture(pos, slice.getTopLeft());
|
drawTexture(pos, slice.getTopLeft());
|
||||||
|
drawTexture(new Vec2i(pos.getX() + slice.getLeft().getWidth() + centerWidth, pos.getY()), slice.getTopRight());
|
||||||
|
drawTexture(new Vec2i(pos.getX(), pos.getY() + slice.getTop().getHeight() + centerHeight), slice.getBottomLeft());
|
||||||
|
drawTexture(Vec2i.add(pos, slice.getTopLeft().getSize(), new Vec2i(centerWidth, centerHeight)), slice.getBottomRight());
|
||||||
|
|
||||||
|
drawTextureRectangle(new Recti(Vec2i.add(pos, slice.getTopLeft().getSize()), new Vec2i(centerWidth, centerHeight)), slice.getCenter(), true);
|
||||||
|
|
||||||
|
//top
|
||||||
|
drawTextureRectangle(
|
||||||
|
new Recti(
|
||||||
|
pos.getX() + slice.getLeft().getWidth(),
|
||||||
|
pos.getY(),
|
||||||
|
centerWidth,
|
||||||
|
slice.getTop().getHeight()
|
||||||
|
),
|
||||||
|
slice.getTop(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//bottom
|
||||||
|
drawTextureRectangle(
|
||||||
|
new Recti(
|
||||||
|
pos.getX() + slice.getLeft().getWidth(),
|
||||||
|
pos.getY() + slice.getTop().getHeight() + centerHeight,
|
||||||
|
centerWidth,
|
||||||
|
slice.getTop().getHeight()
|
||||||
|
),
|
||||||
|
slice.getBottom(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//left
|
||||||
|
drawTextureRectangle(
|
||||||
|
new Recti(
|
||||||
|
pos.getX(),
|
||||||
|
pos.getY() + slice.getTop().getHeight(),
|
||||||
|
slice.getLeft().getWidth(),
|
||||||
|
centerHeight
|
||||||
|
),
|
||||||
|
slice.getLeft(),
|
||||||
|
true
|
||||||
|
);
|
||||||
|
//right
|
||||||
|
drawTextureRectangle(
|
||||||
|
new Recti(
|
||||||
|
pos.getX() + slice.getLeft().getWidth() + centerWidth,
|
||||||
|
pos.getY() + slice.getTop().getHeight(),
|
||||||
|
slice.getLeft().getWidth(),
|
||||||
|
centerHeight
|
||||||
|
),
|
||||||
|
slice.getRight(),
|
||||||
|
true
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -52,53 +108,79 @@ class RenderContext extends BaseRenderContext implements IRenderContext {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawTexture(Vec2i pos, ITexture texture) {
|
public void drawTexture(Vec2i pos, ITexture texture) {
|
||||||
drawTextureRectangle(new Recti(pos, texture.getSize()), texture);
|
drawTextureRectangle(new Recti(pos, texture.getSize()), texture, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawTexture(Vec2i pos, ITexture texture, Color color) {
|
public void drawTexture(Vec2i pos, ITexture texture, Color color) {
|
||||||
drawTextureRectangle(new Recti(pos, texture.getSize()), texture, color);
|
drawTextureRectangle(new Recti(pos, texture.getSize()), texture, color, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawTextureRectangle(Recti rect, ITexture texture) {
|
public void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat) {
|
||||||
drawTextureRectangle(rect, texture, Color.WHITE);
|
drawTextureRectangle(rect, texture, Color.WHITE, repeat);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawTextureRectangle(Recti rect, ITexture texture, Color color) {
|
public void drawTextureRectangle(Recti rect, ITexture texture, Color color, boolean repeat) {
|
||||||
var tex = (Texture)texture;
|
var tex = (Texture) texture;
|
||||||
|
|
||||||
var tl = rect.getTopLeft();
|
var tl = rect.getTopLeft();
|
||||||
var tr = rect.getTopRight();
|
var tr = rect.getTopRight();
|
||||||
var bl = rect.getBottomLeft();
|
var bl = rect.getBottomLeft();
|
||||||
var br = rect.getBottomRight();
|
var br = rect.getBottomRight();
|
||||||
|
|
||||||
|
/*
|
||||||
var ttl = Vec2i.divf(tex.getTexArea().getTopLeft(), atlas.getSize());
|
var ttl = Vec2i.divf(tex.getTexArea().getTopLeft(), atlas.getSize());
|
||||||
var ttr = Vec2i.divf(tex.getTexArea().getTopRight(), atlas.getSize());
|
var ttr = Vec2i.divf(tex.getTexArea().getTopRight(), atlas.getSize());
|
||||||
var tbl = Vec2i.divf(tex.getTexArea().getBottomLeft(), atlas.getSize());
|
var tbl = Vec2i.divf(tex.getTexArea().getBottomLeft(), atlas.getSize());
|
||||||
var tbr = Vec2i.divf(tex.getTexArea().getBottomRight(), atlas.getSize());
|
var tbr = Vec2i.divf(tex.getTexArea().getBottomRight(), atlas.getSize());
|
||||||
|
*/
|
||||||
|
|
||||||
glColor4f(
|
var topleft = tex.getTexArea().getTopLeft();
|
||||||
|
//var size = repeat ? tex.getSize() : rect.getSize();
|
||||||
|
var size = repeat ? tex.getSize() : new Vec2i(100000, 100000);
|
||||||
|
/*var ttl = Vec2i.ZERO;
|
||||||
|
var ttr = Vec2i.sub(tex.getTexArea().getTopRight(), topleft);
|
||||||
|
var tbl = Vec2i.sub(tex.getTexArea().getBottomLeft(), topleft);
|
||||||
|
var tbr = Vec2i.sub(tex.getTexArea().getBottomRight(), topleft);
|
||||||
|
*/
|
||||||
|
var ttl = Vec2i.ZERO;
|
||||||
|
var ttr = new Vec2i(rect.getWidth(), 0);
|
||||||
|
var tbl = new Vec2i(0, rect.getHeight());
|
||||||
|
var tbr = new Vec2i(rect.getWidth(), rect.getHeight());
|
||||||
|
|
||||||
|
if(!repeat) {
|
||||||
|
ttr = Vec2i.sub(tex.getTexArea().getTopRight(), topleft);
|
||||||
|
tbl = Vec2i.sub(tex.getTexArea().getBottomLeft(), topleft);
|
||||||
|
tbr = Vec2i.sub(tex.getTexArea().getBottomRight(), topleft);
|
||||||
|
}
|
||||||
|
|
||||||
|
glUniform3f(
|
||||||
|
tintIndex,
|
||||||
color.getR() / 255.0f,
|
color.getR() / 255.0f,
|
||||||
color.getG() / 255.0f,
|
color.getG() / 255.0f,
|
||||||
color.getB() / 255.0f,
|
color.getB() / 255.0f
|
||||||
color.getA() / 255.0f
|
//color.getA() / 255.0f
|
||||||
);
|
);
|
||||||
|
|
||||||
|
glUniform2i(texOffsetIndex, topleft.getX(), topleft.getY());
|
||||||
|
glUniform2i(texSizeIndex, size.getX(), size.getY());
|
||||||
|
glBegin(GL_TRIANGLES);
|
||||||
//counterclockwise triangles
|
//counterclockwise triangles
|
||||||
glVertexAttrib2d(texCoordIndex, tbl.getX(), tbl.getY());
|
glVertexAttribI2i(texCoordIndex, tbl.getX(), tbl.getY());
|
||||||
glVertex2i(bl.getX(), bl.getY());
|
glVertex2i(bl.getX(), bl.getY());
|
||||||
glVertexAttrib2d(texCoordIndex, ttr.getX(), ttr.getY());
|
glVertexAttribI2i(texCoordIndex, ttr.getX(), ttr.getY());
|
||||||
glVertex2i(tr.getX(), tr.getY());
|
glVertex2i(tr.getX(), tr.getY());
|
||||||
glVertexAttrib2d(texCoordIndex, ttl.getX(), ttl.getY());
|
glVertexAttribI2i(texCoordIndex, ttl.getX(), ttl.getY());
|
||||||
glVertex2i(tl.getX(), tl.getY());
|
glVertex2i(tl.getX(), tl.getY());
|
||||||
|
|
||||||
glVertexAttrib2d(texCoordIndex, ttr.getX(), ttr.getY());
|
glVertexAttribI2i(texCoordIndex, ttr.getX(), ttr.getY());
|
||||||
glVertex2i(tr.getX(), tr.getY());
|
glVertex2i(tr.getX(), tr.getY());
|
||||||
glVertexAttrib2d(texCoordIndex, tbl.getX(), tbl.getY());
|
glVertexAttribI2i(texCoordIndex, tbl.getX(), tbl.getY());
|
||||||
glVertex2i(bl.getX(), bl.getY());
|
glVertex2i(bl.getX(), bl.getY());
|
||||||
glVertexAttrib2d(texCoordIndex, tbr.getX(), tbr.getY());
|
glVertexAttribI2i(texCoordIndex, tbr.getX(), tbr.getY());
|
||||||
glVertex2i(br.getX(), bl.getY());
|
glVertex2i(br.getX(), bl.getY());
|
||||||
|
glEnd();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,6 +22,17 @@ class Texture implements ITexture {
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public Vec2i getSize() { return this.img.getSize(); }
|
public Vec2i getSize() { return this.img.getSize(); }
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getWidth() {
|
||||||
|
return img.getWidth();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getHeight() {
|
||||||
|
return img.getHeight();
|
||||||
|
}
|
||||||
|
|
||||||
void setTexArea(Recti texArea) {
|
void setTexArea(Recti texArea) {
|
||||||
this.texArea = texArea;
|
this.texArea = texArea;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,13 @@ public class Window extends BaseWindow {
|
||||||
textureAtlas = new TextureAtlas();
|
textureAtlas = new TextureAtlas();
|
||||||
program = new Program(vertexSource, fragmentSource);
|
program = new Program(vertexSource, fragmentSource);
|
||||||
program.use();
|
program.use();
|
||||||
renderContext = new RenderContext(textureAtlas, program.getAttribLocation("texCoord"));
|
renderContext = new RenderContext(
|
||||||
|
textureAtlas,
|
||||||
|
program.getAttribLocation("texCoord"),
|
||||||
|
program.getUniformLocation("texOffset"),
|
||||||
|
program.getUniformLocation("texSize"),
|
||||||
|
program.getUniformLocation("tint")
|
||||||
|
);
|
||||||
glProgramUniform2f(program.program, program.getUniformLocation("windowSize"), size.getX(), size.getY());
|
glProgramUniform2f(program.program, program.getUniformLocation("windowSize"), size.getX(), size.getY());
|
||||||
|
|
||||||
shouldClose = false;
|
shouldClose = false;
|
||||||
|
@ -98,9 +104,9 @@ public class Window extends BaseWindow {
|
||||||
@Override
|
@Override
|
||||||
public void renderFinish(IRenderContext context) {
|
public void renderFinish(IRenderContext context) {
|
||||||
if(debug) {
|
if(debug) {
|
||||||
context.drawTextureRectangle(new Recti(Vec2i.ZERO, size), textureAtlas.getAtlasTexture());
|
context.drawTextureRectangle(new Recti(Vec2i.ZERO, size), textureAtlas.getAtlasTexture(), true);
|
||||||
}
|
}
|
||||||
glEnd();
|
//glEnd();
|
||||||
glfwSwapBuffers(window);
|
glfwSwapBuffers(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +117,7 @@ public class Window extends BaseWindow {
|
||||||
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
|
||||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||||
program.use();
|
program.use();
|
||||||
glBegin(GL_TRIANGLES);
|
//glBegin(GL_TRIANGLES);
|
||||||
return renderContext;
|
return renderContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +145,7 @@ public class Window extends BaseWindow {
|
||||||
private static String vertexSource = """
|
private static String vertexSource = """
|
||||||
#version 450
|
#version 450
|
||||||
layout(location = 0) in vec2 pos;
|
layout(location = 0) in vec2 pos;
|
||||||
layout(location = 1) in vec2 texCoord;
|
layout(location = 1) in ivec2 texCoord;
|
||||||
layout(location = 2) uniform vec2 windowSize;
|
layout(location = 2) uniform vec2 windowSize;
|
||||||
layout(location = 1) out vec2 out_texCoord;
|
layout(location = 1) out vec2 out_texCoord;
|
||||||
void main() {
|
void main() {
|
||||||
|
@ -152,10 +158,14 @@ public class Window extends BaseWindow {
|
||||||
#version 450
|
#version 450
|
||||||
layout(location = 1) in vec2 texCoord;
|
layout(location = 1) in vec2 texCoord;
|
||||||
layout(binding = 0) uniform sampler2D tex;
|
layout(binding = 0) uniform sampler2D tex;
|
||||||
|
layout(location = 3) uniform ivec2 texOffset;
|
||||||
|
layout(location = 4) uniform ivec2 texSize;
|
||||||
|
layout(location = 5) uniform vec3 tint;
|
||||||
out vec4 color;
|
out vec4 color;
|
||||||
void main() {
|
void main() {
|
||||||
//color = vec4(texCoord.x, texCoord.y, 0.7f, 1.0f);
|
//color = vec4(vec2(texCoord).x/1000.f, 0.2f, 0.7f, 1.0f);
|
||||||
color = texture(tex, texCoord);
|
//color = texture(tex, texCoord);
|
||||||
|
color = texelFetch(tex, ivec2(mod(texCoord, texSize)) + texOffset, 0) * vec4(tint, 1.0f);
|
||||||
}
|
}
|
||||||
""";
|
""";
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,10 @@ import java.nio.IntBuffer;
|
||||||
|
|
||||||
abstract public class BaseRenderContext implements IRenderContext {
|
abstract public class BaseRenderContext implements IRenderContext {
|
||||||
public void drawString(Vec2i pos, String string, IFont font) {
|
public void drawString(Vec2i pos, String string, IFont font) {
|
||||||
|
drawString(pos, string, font, Color.WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void drawString(Vec2i pos, String string, IFont font, Color color) {
|
||||||
int x = pos.getX();
|
int x = pos.getX();
|
||||||
int y = pos.getY();
|
int y = pos.getY();
|
||||||
IntBuffer buf;
|
IntBuffer buf;
|
||||||
|
@ -22,7 +26,7 @@ abstract public class BaseRenderContext implements IRenderContext {
|
||||||
int ch = buf.get(i);
|
int ch = buf.get(i);
|
||||||
var tex = font.getTexture(ch);
|
var tex = font.getTexture(ch);
|
||||||
var off = font.getOffset(ch);
|
var off = font.getOffset(ch);
|
||||||
drawTextureRectangle(new Recti(Vec2i.add(new Vec2i(x, y), off), tex.getSize()), tex);
|
drawTextureRectangle(new Recti(Vec2i.add(new Vec2i(x, y), off), tex.getSize()), tex, color, true);
|
||||||
x += font.getXAdvance(ch);
|
x += font.getXAdvance(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,9 +7,10 @@ public interface IRenderContext {
|
||||||
void drawNineSlice(NineSlice slice, Recti rect); //todo: add rounding mode
|
void drawNineSlice(NineSlice slice, Recti rect); //todo: add rounding mode
|
||||||
void drawRectangle(Recti rect, Color color);
|
void drawRectangle(Recti rect, Color color);
|
||||||
void drawString(Vec2i pos, String string, IFont font);
|
void drawString(Vec2i pos, String string, IFont font);
|
||||||
|
void drawString(Vec2i pos, String string, IFont font, Color color);
|
||||||
void drawTexture(Vec2i pos, ITexture texture);
|
void drawTexture(Vec2i pos, ITexture texture);
|
||||||
void drawTexture(Vec2i pos, ITexture texture, Color color);
|
void drawTexture(Vec2i pos, ITexture texture, Color color);
|
||||||
void drawTextureRectangle(Recti rect, ITexture texture);
|
void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat);
|
||||||
void drawTextureRectangle(Recti rect, ITexture texture, Color color);
|
void drawTextureRectangle(Recti rect, ITexture texture, Color color, boolean repeat);
|
||||||
//todo: drawTextureRectangleRepeat
|
//todo: drawTextureRectangleRepeat
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,4 +4,6 @@ import com.danitheskunk.skunkworks.Vec2i;
|
||||||
|
|
||||||
public interface ITexture {
|
public interface ITexture {
|
||||||
Vec2i getSize();
|
Vec2i getSize();
|
||||||
|
int getWidth();
|
||||||
|
int getHeight();
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 148 B After Width: | Height: | Size: 162 B |
Binary file not shown.
After Width: | Height: | Size: 228 B |
Loading…
Reference in New Issue