code style and arrangement change

This commit is contained in:
DaniTheSkunk 2022-11-22 22:10:56 +00:00
parent 7339ca69a7
commit 45344c589c
53 changed files with 1703 additions and 1447 deletions

View File

@ -4,6 +4,10 @@
<option name="RIGHT_MARGIN" value="80" /> <option name="RIGHT_MARGIN" value="80" />
<option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" /> <option name="WRAP_WHEN_TYPING_REACHES_RIGHT_MARGIN" value="true" />
<option name="ENABLE_SECOND_REFORMAT" value="true" /> <option name="ENABLE_SECOND_REFORMAT" value="true" />
<JavaCodeStyleSettings>
<option name="ANNOTATION_PARAMETER_WRAP" value="5" />
<option name="NEW_LINE_AFTER_LPAREN_IN_ANNOTATION" value="true" />
</JavaCodeStyleSettings>
<editorconfig> <editorconfig>
<option name="ENABLED" value="false" /> <option name="ENABLED" value="false" />
</editorconfig> </editorconfig>
@ -26,12 +30,301 @@
<option name="PARENTHESES_EXPRESSION_LPAREN_WRAP" value="true" /> <option name="PARENTHESES_EXPRESSION_LPAREN_WRAP" value="true" />
<option name="PARENTHESES_EXPRESSION_RPAREN_WRAP" value="true" /> <option name="PARENTHESES_EXPRESSION_RPAREN_WRAP" value="true" />
<option name="BINARY_OPERATION_WRAP" value="5" /> <option name="BINARY_OPERATION_WRAP" value="5" />
<option name="FOR_STATEMENT_WRAP" value="5" />
<option name="FOR_STATEMENT_RPAREN_ON_NEXT_LINE" value="true" />
<option name="ARRAY_INITIALIZER_WRAP" value="5" />
<option name="ARRAY_INITIALIZER_LBRACE_ON_NEXT_LINE" value="true" />
<option name="WHILE_BRACE_FORCE" value="3" /> <option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
<option name="WRAP_LONG_LINES" value="true" /> <option name="WRAP_LONG_LINES" value="true" />
<indentOptions> <indentOptions>
<option name="CONTINUATION_INDENT_SIZE" value="4" /> <option name="CONTINUATION_INDENT_SIZE" value="4" />
<option name="USE_TAB_CHARACTER" value="true" /> <option name="USE_TAB_CHARACTER" value="true" />
</indentOptions> </indentOptions>
<arrangement>
<groups />
<rules>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PUBLIC>true</PUBLIC>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PROTECTED>true</PROTECTED>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PRIVATE>true</PRIVATE>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
<STATIC>true</STATIC>
</AND>
</match>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PUBLIC>true</PUBLIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PROTECTED>true</PROTECTED>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<FINAL>true</FINAL>
<PRIVATE>true</PRIVATE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PUBLIC>true</PUBLIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PROTECTED>true</PROTECTED>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PACKAGE_PRIVATE>true</PACKAGE_PRIVATE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<FIELD>true</FIELD>
<PRIVATE>true</PRIVATE>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<FIELD>true</FIELD>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<INITIALIZER_BLOCK>true</INITIALIZER_BLOCK>
</match>
</rule>
</section>
<section>
<rule>
<match>
<CONSTRUCTOR>true</CONSTRUCTOR>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<METHOD>true</METHOD>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<METHOD>true</METHOD>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<ENUM>true</ENUM>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<INTERFACE>true</INTERFACE>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<AND>
<CLASS>true</CLASS>
<STATIC>true</STATIC>
</AND>
</match>
<order>BY_NAME</order>
</rule>
</section>
<section>
<rule>
<match>
<CLASS>true</CLASS>
</match>
<order>BY_NAME</order>
</rule>
</section>
</rules>
</arrangement>
</codeStyleSettings> </codeStyleSettings>
<codeStyleSettings language="Markdown"> <codeStyleSettings language="Markdown">
<option name="RIGHT_MARGIN" value="60" /> <option name="RIGHT_MARGIN" value="60" />

View File

@ -13,13 +13,13 @@ import com.danitheskunk.skunkworks.nodes.NodeRoot;
import org.lwjgl.glfw.GLFW; import org.lwjgl.glfw.GLFW;
public abstract class BaseGame { public abstract class BaseGame {
protected Engine engine;
protected AudioEngine audioEngine; protected AudioEngine audioEngine;
protected IFont debugFont;
protected Engine engine;
protected Mixer mixer; protected Mixer mixer;
protected NodeRoot rootNode;
protected SamplePlayer samplePlayer; protected SamplePlayer samplePlayer;
protected IWindow window; protected IWindow window;
protected IFont debugFont;
protected NodeRoot rootNode;
public BaseGame(Vec2i windowSize, String windowTitle) { public BaseGame(Vec2i windowSize, String windowTitle) {
this.audioEngine = new AudioEngine(44100, 256, 8); this.audioEngine = new AudioEngine(44100, 256, 8);
@ -36,6 +36,39 @@ public abstract class BaseGame {
init(); init();
} }
protected void init() {
}
protected ISample loadSample(String path) {
return audioEngine.loadSample(path);
}
protected ITexture loadTexture(String path) {
return window.loadTexture(path);
}
protected void playSample(ISample sample) {
samplePlayer.play(sample);
}
protected void playSample(ISample sample, boolean looping) {
samplePlayer.play(sample, looping);
}
protected void render(IRenderContext rc) {
//rc.drawString(new Vec2i(8, 8), "Welcome to Skunkworks, please
// overide the render method to get started", debugFont, Color
// .LIGHT_GRAY);
}
protected void render3D(IRenderContext3D rc3d) {
}
protected void renderPre(IRenderContext rc) {
}
public void run() { public void run() {
double lastTime, currentTime, delta; double lastTime, currentTime, delta;
@ -63,40 +96,7 @@ public abstract class BaseGame {
} }
} }
protected void render3D(IRenderContext3D rc3d) {
}
protected void init() {
}
protected void renderPre(IRenderContext rc) {
}
protected void render(IRenderContext rc) {
//rc.drawString(new Vec2i(8, 8), "Welcome to Skunkworks, please
// overide the render method to get started", debugFont, Color
// .LIGHT_GRAY);
}
protected void update(double delta) { protected void update(double delta) {
} }
protected ISample loadSample(String path) {
return audioEngine.loadSample(path);
}
protected void playSample(ISample sample) {
samplePlayer.play(sample);
}
protected void playSample(ISample sample, boolean looping) {
samplePlayer.play(sample, looping);
}
protected ITexture loadTexture(String path) {
return window.loadTexture(path);
}
} }

View File

@ -20,6 +20,13 @@ abstract public class BaseWindow implements IWindow {
return engine; return engine;
} }
@Override
public IFont loadFontTTF(String path, float size) {
var bytes = engine.loadBytes(path);
return new FontTTF(bytes, size, this);
}
@Override @Override
public IFont loadFontTileset(String path) { public IFont loadFontTileset(String path) {
var img = engine.loadImage(path); var img = engine.loadImage(path);
@ -29,13 +36,6 @@ abstract public class BaseWindow implements IWindow {
return new FontTileset(tex); return new FontTileset(tex);
} }
@Override
public IFont loadFontTTF(String path, float size) {
var bytes = engine.loadBytes(path);
return new FontTTF(bytes, size, this);
}
@Override @Override
public NineSlice loadNineSlice(Image image) { public NineSlice loadNineSlice(Image image) {
int x1 = -1; int x1 = -1;
@ -73,34 +73,29 @@ abstract public class BaseWindow implements IWindow {
} }
var tl = image.getSubImage(new Recti(1, 1, x1 - 1, y1 - 1)); var tl = image.getSubImage(new Recti(1, 1, x1 - 1, y1 - 1));
var top = image.getSubImage(new Recti(x1, 1, x2 - x1, y1 - 1)); var top = image.getSubImage(new Recti(x1, 1, x2 - x1, y1 - 1));
var tr = image.getSubImage(new Recti( var tr = image.getSubImage(new Recti(x2,
x2,
1, 1,
image.getWidth() - x2, image.getWidth() - x2,
y1 - 1 y1 - 1
)); ));
var left = image.getSubImage(new Recti(1, y1, x1 - 1, y2 - y1)); var left = image.getSubImage(new Recti(1, y1, x1 - 1, y2 - y1));
var center = image.getSubImage(new Recti(x1, y1, x2 - x1, y2 - y1)); var center = image.getSubImage(new Recti(x1, y1, x2 - x1, y2 - y1));
var right = image.getSubImage(new Recti( var right = image.getSubImage(new Recti(x2,
x2,
y1, y1,
image.getWidth() - x2, image.getWidth() - x2,
y2 - y1 y2 - y1
)); ));
var bl = image.getSubImage(new Recti( var bl = image.getSubImage(new Recti(1,
1,
y2, y2,
x1 - 1, x1 - 1,
image.getHeight() - y2 image.getHeight() - y2
)); ));
var bottom = image.getSubImage(new Recti( var bottom = image.getSubImage(new Recti(x1,
x1,
y2, y2,
x2 - x1, x2 - x1,
image.getHeight() - y2 image.getHeight() - y2
)); ));
var br = image.getSubImage(new Recti( var br = image.getSubImage(new Recti(x2,
x2,
y2, y2,
image.getWidth() - x2, image.getWidth() - x2,
image.getHeight() - y2 image.getHeight() - y2

View File

@ -1,16 +1,13 @@
package com.danitheskunk.skunkworks; package com.danitheskunk.skunkworks;
import java.io.BufferedInputStream;
import java.io.InputStreamReader;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
public class Data { public class Data {
private LinkedHashMap<String, LinkedHashMap<String, String>> data;
private String currentCategory;
private Runnable callback; private Runnable callback;
private String currentCategory;
private final LinkedHashMap<String, LinkedHashMap<String, String>> data;
public Data(ByteBuffer data) { public Data(ByteBuffer data) {
this.data = new LinkedHashMap<>(); this.data = new LinkedHashMap<>();
@ -19,13 +16,8 @@ public class Data {
StandardCharsets.UTF_8.decode(data).toString().lines().forEach(this::processLine); StandardCharsets.UTF_8.decode(data).toString().lines().forEach(this::processLine);
} }
public void reload(ByteBuffer data) { public String get(String category, String key) {
this.data.clear(); return data.get(category).get(key);
this.data.put("", new LinkedHashMap<>());
StandardCharsets.UTF_8.decode(data).toString().lines().forEach(this::processLine);
if(callback != null) {
callback.run();
}
} }
public void onReload(Runnable callback) { public void onReload(Runnable callback) {
@ -37,14 +29,19 @@ public class Data {
var parts = line.split("=", 2); var parts = line.split("=", 2);
data.get(currentCategory).put(parts[0].strip(), parts[1].strip()); data.get(currentCategory).put(parts[0].strip(), parts[1].strip());
} else if(line.startsWith("[") && line.endsWith("]")) { } else if(line.startsWith("[") && line.endsWith("]")) {
currentCategory = line.substring(1, line.length()-1); currentCategory = line.substring(1, line.length() - 1);
if(!data.containsKey(currentCategory)) { if(!data.containsKey(currentCategory)) {
data.put(currentCategory, new LinkedHashMap<>()); data.put(currentCategory, new LinkedHashMap<>());
} }
} }
} }
public String get(String category, String key) { public void reload(ByteBuffer data) {
return data.get(category).get(key); this.data.clear();
this.data.put("", new LinkedHashMap<>());
StandardCharsets.UTF_8.decode(data).toString().lines().forEach(this::processLine);
if(callback != null) {
callback.run();
}
} }
} }

View File

@ -17,9 +17,9 @@ import static com.danitheskunk.skunkworks.gfx.GraphicsBackend.OPENGL;
public class Engine { public class Engine {
private final GraphicsBackend graphicsBackend; private final GraphicsBackend graphicsBackend;
private final WatchService watchService;
private final Map<WatchKey, Callable<Boolean>> watchCallbacks; private final Map<WatchKey, Callable<Boolean>> watchCallbacks;
private final Map<WatchKey, Path> watchPaths; private final Map<WatchKey, Path> watchPaths;
private final WatchService watchService;
//Constructors //Constructors
public Engine() { public Engine() {
@ -52,10 +52,6 @@ public class Engine {
return buf; return buf;
} }
public Image loadImage(String path) {
return new Image(loadBytes(path));
}
public Data loadData(String path) { public Data loadData(String path) {
return new Data(loadBytes(path)); return new Data(loadBytes(path));
} }
@ -69,19 +65,8 @@ public class Engine {
return data; return data;
} }
//requires engine.tick() to be called regularly public Image loadImage(String path) {
public void watchFile(String path, Callable<Boolean> callback) { return new Image(loadBytes(path));
var p = Paths.get(path);
var dir = p.getParent();
try {
var key = dir.register(watchService,
StandardWatchEventKinds.ENTRY_MODIFY
);
watchCallbacks.put(key, callback);
watchPaths.put(key, p.getFileName());
} catch(IOException e) {
throw new RuntimeException(e);
}
} }
public IWindow openWindow(Vec2i size, String title) { public IWindow openWindow(Vec2i size, String title) {
@ -107,4 +92,19 @@ public class Engine {
} }
} }
} }
//requires engine.tick() to be called regularly
public void watchFile(String path, Callable<Boolean> callback) {
var p = Paths.get(path);
var dir = p.getParent();
try {
var key = dir.register(watchService,
StandardWatchEventKinds.ENTRY_MODIFY
);
watchCallbacks.put(key, callback);
watchPaths.put(key, p.getFileName());
} catch(IOException e) {
throw new RuntimeException(e);
}
}
} }

View File

@ -8,10 +8,16 @@ import java.util.List;
public interface IWindow { public interface IWindow {
Engine getEngine(); Engine getEngine();
IFont loadFontTileset(String path); Vec2i getMousePos();
boolean isMouseClicked(int button);
boolean isMouseDown(int button);
IFont loadFontTTF(String path, float size); IFont loadFontTTF(String path, float size);
IFont loadFontTileset(String path);
NineSlice loadNineSlice(Image image); NineSlice loadNineSlice(Image image);
NineSlice loadNineSlice(String path); NineSlice loadNineSlice(String path);
@ -26,10 +32,10 @@ public interface IWindow {
void renderFinish(IRenderContext context); void renderFinish(IRenderContext context);
IRenderContext renderStart();
void renderFinish3D(IRenderContext3D context); void renderFinish3D(IRenderContext3D context);
IRenderContext renderStart();
IRenderContext3D renderStart3D(); IRenderContext3D renderStart3D();
//needs to be run after rendering //needs to be run after rendering
@ -37,15 +43,9 @@ public interface IWindow {
void setDebug(boolean on); void setDebug(boolean on);
boolean shouldClose();
void setStretchMode(WindowStretchMode mode); void setStretchMode(WindowStretchMode mode);
Vec2i getMousePos(); boolean shouldClose();
boolean isMouseClicked(int button);
boolean isMouseDown(int button);
void tick(); void tick();
} }

View File

@ -11,26 +11,6 @@ public final class Mat4f {
set(3, 3, 1.0); set(3, 3, 1.0);
} }
public double get(int x, int y) {
return data[x + y * 4];
}
public void set(int x, int y, double val) {
data[x + y * 4] = val;
}
public double[] asArray() {
return data;
}
public float[] asFloatArray() {
var arr = new float[16];
for(int i = 0; i < 16; ++i) {
arr[i] = (float)data[i];
}
return arr;
}
public static Mat4f perspective( public static Mat4f perspective(
double fovy, double aspect, double zNear, double zFar double fovy, double aspect, double zNear, double zFar
) { ) {
@ -65,4 +45,24 @@ public final class Mat4f {
//mat.set(3, 3, 0); //mat.set(3, 3, 0);
return mat; return mat;
} }
public double[] asArray() {
return data;
}
public float[] asFloatArray() {
var arr = new float[16];
for(int i = 0; i < 16; ++i) {
arr[i] = (float) data[i];
}
return arr;
}
public double get(int x, int y) {
return data[x + y * 4];
}
public void set(int x, int y, double val) {
data[x + y * 4] = val;
}
} }

View File

@ -14,37 +14,12 @@ public final class Recti {
this.size = size; this.size = size;
} }
//getters public boolean contains(Vec2i vec) {
public Vec2i getPos() { var br = getBottomRight();
return pos; return vec.getX() >= pos.getX() &&
} vec.getY() >= pos.getY() &&
vec.getX() < br.getX() &&
public Vec2i getSize() { vec.getY() < br.getY();
return size;
}
public int getX() {
return pos.getX();
}
public int getY() {
return pos.getY();
}
public int getWidth() {
return size.getX();
}
public int getHeight() {
return size.getY();
}
public Vec2i getTopLeft() {
return pos;
}
public Vec2i getTopRight() {
return new Vec2i(pos.getX() + size.getX(), pos.getY());
} }
public Vec2i getBottomLeft() { public Vec2i getBottomLeft() {
@ -55,11 +30,36 @@ public final class Recti {
return Vec2i.add(pos, size); return Vec2i.add(pos, size);
} }
public boolean contains(Vec2i vec) { public int getHeight() {
var br = getBottomRight(); return size.getY();
return vec.getX() >= pos.getX() && }
vec.getY() >= pos.getY() &&
vec.getX() < br.getX() && //getters
vec.getY() < br.getY(); public Vec2i getPos() {
return pos;
}
public Vec2i getSize() {
return size;
}
public Vec2i getTopLeft() {
return pos;
}
public Vec2i getTopRight() {
return new Vec2i(pos.getX() + size.getX(), pos.getY());
}
public int getWidth() {
return size.getX();
}
public int getX() {
return pos.getX();
}
public int getY() {
return pos.getY();
} }
} }

View File

@ -8,7 +8,7 @@ public class Test extends BaseGame {
private Terminal term; private Terminal term;
public Test() { public Test() {
super(new Vec2i(40*12, 22*12), "Skunkworks"); super(new Vec2i(40 * 12, 22 * 12), "Skunkworks");
} }
public static void main(String[] args) { public static void main(String[] args) {

View File

@ -1,6 +1,5 @@
package com.danitheskunk.skunkworks; package com.danitheskunk.skunkworks;
import com.danitheskunk.skunkworks.gfx.IRenderContext;
import com.danitheskunk.skunkworks.gfx.IRenderContext3D; import com.danitheskunk.skunkworks.gfx.IRenderContext3D;
public class Test3D extends BaseGame { public class Test3D extends BaseGame {

View File

@ -4,8 +4,8 @@ import com.danitheskunk.skunkworks.audio.ISample;
import com.danitheskunk.skunkworks.nodes.NodeSprite; import com.danitheskunk.skunkworks.nodes.NodeSprite;
public class TestNode extends BaseGame { public class TestNode extends BaseGame {
NodeSprite sprite;
ISample kick; ISample kick;
NodeSprite sprite;
public TestNode() { public TestNode() {
super(new Vec2i(1280, 720), "Skunkworks"); super(new Vec2i(1280, 720), "Skunkworks");

View File

@ -5,21 +5,9 @@ import com.danitheskunk.skunkworks.audio.nodes.Mixer;
import com.danitheskunk.skunkworks.audio.nodes.Node; import com.danitheskunk.skunkworks.audio.nodes.Node;
import com.danitheskunk.skunkworks.audio.nodes.SamplePlayer; import com.danitheskunk.skunkworks.audio.nodes.SamplePlayer;
import com.danitheskunk.skunkworks.audio.nodes.Sine; import com.danitheskunk.skunkworks.audio.nodes.Sine;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.ALC;
import javax.sound.sampled.*;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.openal.AL10.*;
import static org.lwjgl.openal.ALC10.*;
public class TestSound { public class TestSound {
public static void main(String args[]) throws InterruptedException { public static void main(String[] args) throws InterruptedException {
var engine = new AudioEngine(44100, 256, 16); var engine = new AudioEngine(44100, 256, 16);
var mix = new Mixer(engine, 4); var mix = new Mixer(engine, 4);
var sin1 = new Sine(engine, 440); var sin1 = new Sine(engine, 440);

View File

@ -15,25 +15,10 @@ public final class Vec2f {
return new Vec2f(a.x + b.x, a.y + b.y); return new Vec2f(a.x + b.x, a.y + b.y);
} }
public static Vec2f sub(Vec2f a, Vec2f b) {
return new Vec2f(a.x - b.x, a.y - b.y);
}
public static Vec2f mul(Vec2f a, double b) {
return new Vec2f(a.x * b, a.y * b);
}
public static Vec2f div(Vec2f a, double b) { public static Vec2f div(Vec2f a, double b) {
return new Vec2f(a.x / b, a.y / b); return new Vec2f(a.x / b, a.y / b);
} }
public static Vec2f tween(Vec2f a, Vec2f b, double amount) {
return new Vec2f(
Util.tweenDouble(a.x, b.x, amount),
Util.tweenDouble(a.y, b.y, amount)
);
}
public static Vec2f div(Vec2i a, Vec2i b) { public static Vec2f div(Vec2i a, Vec2i b) {
return new Vec2f( return new Vec2f(
(double) a.getX() / (double) b.getX(), (double) a.getX() / (double) b.getX(),
@ -41,6 +26,21 @@ public final class Vec2f {
); );
} }
public static Vec2f mul(Vec2f a, double b) {
return new Vec2f(a.x * b, a.y * b);
}
public static Vec2f sub(Vec2f a, Vec2f b) {
return new Vec2f(a.x - b.x, a.y - b.y);
}
public static Vec2f tween(Vec2f a, Vec2f b, double amount) {
return new Vec2f(
Util.tweenDouble(a.x, b.x, amount),
Util.tweenDouble(a.y, b.y, amount)
);
}
//getters and setters //getters and setters
public double getX() { public double getX() {
return x; return x;

View File

@ -28,19 +28,6 @@ public final class Vec2i {
return new Vec2i(a.x + b.x + c.x + d.x, a.y + b.y + c.y + d.y); return new Vec2i(a.x + b.x + c.x + d.x, a.y + b.y + c.y + d.y);
} }
public static Vec2i sub(Vec2i a, Vec2i b) {
return new Vec2i(a.x - b.x, a.y - b.y);
}
public static Vec2i mul(Vec2i a, int b) {
return new Vec2i(a.x * b, a.y * b);
}
public static Vec2i mul(Vec2i a, Vec2i b) {
return new Vec2i(a.x * b.x, a.y * b.y);
}
public static Vec2i div(Vec2i a, int b) { public static Vec2i div(Vec2i a, int b) {
return new Vec2i(a.x / b, a.y / b); return new Vec2i(a.x / b, a.y / b);
} }
@ -65,18 +52,20 @@ public final class Vec2i {
return new Vec2f(a.x / (double) b.x, a.y / (double) b.y); return new Vec2f(a.x / (double) b.x, a.y / (double) b.y);
} }
public static Vec2i min(Vec2i a, Vec2i b) {
return new Vec2i(Math.min(a.x, b.x), Math.min(a.y, b.y));
}
public static Vec2i max(Vec2i a, Vec2i b) { public static Vec2i max(Vec2i a, Vec2i b) {
return new Vec2i(Math.max(a.x, b.x), Math.max(a.y, b.y)); return new Vec2i(Math.max(a.x, b.x), Math.max(a.y, b.y));
} }
public static Vec2i tween(Vec2i a, Vec2i b, double amount) { public static Vec2i min(Vec2i a, Vec2i b) {
return new Vec2i(Util.tweenInt(a.x, b.x, amount), return new Vec2i(Math.min(a.x, b.x), Math.min(a.y, b.y));
Util.tweenInt(a.y, b.y, amount) }
);
public static Vec2i mul(Vec2i a, int b) {
return new Vec2i(a.x * b, a.y * b);
}
public static Vec2i mul(Vec2i a, Vec2i b) {
return new Vec2i(a.x * b.x, a.y * b.y);
} }
public static Vec2i mul(Vec2f a, Vec2i b) { public static Vec2i mul(Vec2f a, Vec2i b) {
@ -86,9 +75,18 @@ public final class Vec2i {
} }
public static Vec2i mul(Vec2i a, double b) { public static Vec2i mul(Vec2i a, double b) {
return new Vec2i((int)(a.x / b), (int)(a.y / b)); return new Vec2i((int) (a.x / b), (int) (a.y / b));
} }
public static Vec2i sub(Vec2i a, Vec2i b) {
return new Vec2i(a.x - b.x, a.y - b.y);
}
public static Vec2i tween(Vec2i a, Vec2i b, double amount) {
return new Vec2i(Util.tweenInt(a.x, b.x, amount),
Util.tweenInt(a.y, b.y, amount)
);
}
public int getX() { public int getX() {
return x; return x;
@ -99,6 +97,6 @@ public final class Vec2i {
} }
public Vec2f toVec2f() { public Vec2f toVec2f() {
return new Vec2f((double) x, (double) y); return new Vec2f(x, y);
} }
} }

View File

@ -1,8 +1,8 @@
package com.danitheskunk.skunkworks; package com.danitheskunk.skunkworks;
public final class Vec3f { public final class Vec3f {
public static Vec3f ZERO = new Vec3f(0, 0, 0);
public static Vec3f ONE = new Vec3f(1, 1, 1); public static Vec3f ONE = new Vec3f(1, 1, 1);
public static Vec3f ZERO = new Vec3f(0, 0, 0);
private final double x, y, z; private final double x, y, z;
public Vec3f(double x, double y, double z) { public Vec3f(double x, double y, double z) {

View File

@ -1,14 +1,22 @@
package com.danitheskunk.skunkworks.audio; package com.danitheskunk.skunkworks.audio;
public class AudioBuffer { public class AudioBuffer {
private double[] left; private final double[] left;
private double[] right; private final double[] right;
public AudioBuffer(int size) { public AudioBuffer(int size) {
left = new double[size]; left = new double[size];
right = new double[size]; right = new double[size];
} }
public double getLeft(int pos) {
return left[pos];
}
public double getRight(int pos) {
return right[pos];
}
public int getSize() { public int getSize() {
return left.length; return left.length;
} }
@ -17,12 +25,4 @@ public class AudioBuffer {
this.left[pos] = left; this.left[pos] = left;
this.right[pos] = right; this.right[pos] = right;
} }
public double getLeft(int pos) {
return left[pos];
}
public double getRight(int pos) {
return right[pos];
}
} }

View File

@ -18,13 +18,14 @@ import static org.lwjgl.openal.AL10.*;
import static org.lwjgl.openal.ALC10.*; import static org.lwjgl.openal.ALC10.*;
public class AudioEngine { public class AudioEngine {
private int sampleRate; private final int bufferCount;
private int bufferSize; private final int bufferSize;
private int bufferCount; private final long context;
private long device; private final long device;
private long context;
private int source;
private Node node; private Node node;
private final int sampleRate;
private final int source;
public AudioEngine(int sampleRate, int bufferSize, int bufferCount) { public AudioEngine(int sampleRate, int bufferSize, int bufferCount) {
this.sampleRate = sampleRate; this.sampleRate = sampleRate;
this.bufferSize = bufferSize; this.bufferSize = bufferSize;
@ -50,8 +51,10 @@ public class AudioEngine {
alSourcePlay(source); alSourcePlay(source);
} }
public int getBufferSize() { private void addEmptyBuffer() {
return bufferSize; var buf = alGenBuffers();
fillBuffer(buf);
alSourceQueueBuffers(source, buf);
} }
public void close() { public void close() {
@ -72,37 +75,16 @@ public class AudioEngine {
alBufferData(buffer, AL_FORMAT_STEREO16, shortBuffer, sampleRate); alBufferData(buffer, AL_FORMAT_STEREO16, shortBuffer, sampleRate);
} }
private void addEmptyBuffer() { public int getBufferSize() {
var buf = alGenBuffers(); return bufferSize;
fillBuffer(buf);
alSourceQueueBuffers(source, buf);
}
public void refill() {
var bufCount = alGetSourcei(source, AL_BUFFERS_PROCESSED);
var bufs = new int[bufCount];
alSourceUnqueueBuffers(source, bufs);
for(int i = 0; i < bufCount; ++i) {
fillBuffer(bufs[i]);
alSourceQueueBuffers(source, bufs[i]);
}
if(alGetSourcei(source, AL_SOURCE_STATE) != AL_PLAYING) {
System.out.println("buffer underrun, addng buffer");
addEmptyBuffer();
alSourcePlay(source);
}
}
public int getSampleRate() {
return sampleRate;
} }
public Node getNode() { public Node getNode() {
return node; return node;
} }
public void setNode(Node node) { public int getSampleRate() {
this.node = node; return sampleRate;
} }
public ISample loadSample(String path) { public ISample loadSample(String path) {
@ -154,4 +136,23 @@ public class AudioEngine {
} }
return sample; return sample;
} }
public void refill() {
var bufCount = alGetSourcei(source, AL_BUFFERS_PROCESSED);
var bufs = new int[bufCount];
alSourceUnqueueBuffers(source, bufs);
for(int i = 0; i < bufCount; ++i) {
fillBuffer(bufs[i]);
alSourceQueueBuffers(source, bufs[i]);
}
if(alGetSourcei(source, AL_SOURCE_STATE) != AL_PLAYING) {
System.out.println("buffer underrun, addng buffer");
addEmptyBuffer();
alSourcePlay(source);
}
}
public void setNode(Node node) {
this.node = node;
}
} }

View File

@ -8,9 +8,9 @@ public interface ISample {
double getSampleRight(int pos); double getSampleRight(int pos);
void setSamplei(int pos, short left); boolean isStereo();
void setSamplei(int pos, short left, short right); void setSamplei(int pos, short left, short right);
boolean isStereo(); void setSamplei(int pos, short left);
} }

View File

@ -1,8 +1,8 @@
package com.danitheskunk.skunkworks.audio; package com.danitheskunk.skunkworks.audio;
public class Samplei implements ISample { public class Samplei implements ISample {
private short[] left; private final short[] left;
private short[] right; private final short[] right;
public Samplei(int length, boolean stereo) { public Samplei(int length, boolean stereo) {
left = new short[length]; left = new short[length];
@ -30,8 +30,8 @@ public class Samplei implements ISample {
} }
@Override @Override
public void setSamplei(int pos, short left) { public boolean isStereo() {
this.left[pos] = left; return left != right;
} }
@Override @Override
@ -41,7 +41,7 @@ public class Samplei implements ISample {
} }
@Override @Override
public boolean isStereo() { public void setSamplei(int pos, short left) {
return left != right; this.left[pos] = left;
} }
} }

View File

@ -4,7 +4,7 @@ import com.danitheskunk.skunkworks.audio.AudioBuffer;
import com.danitheskunk.skunkworks.audio.AudioEngine; import com.danitheskunk.skunkworks.audio.AudioEngine;
public class Mixer extends Node { public class Mixer extends Node {
private int channels; private final int channels;
public Mixer(AudioEngine engine, int channels) { public Mixer(AudioEngine engine, int channels) {
super(engine, channels, 1); super(engine, channels, 1);

View File

@ -4,12 +4,12 @@ import com.danitheskunk.skunkworks.audio.AudioBuffer;
import com.danitheskunk.skunkworks.audio.AudioEngine; import com.danitheskunk.skunkworks.audio.AudioEngine;
public abstract class Node { public abstract class Node {
private int inCount; private final AudioEngine engine;
private int outCount; private final int[] inConnectionSlots;
private boolean[] isOutConnected; private final Node[] inConnections;
private Node[] inConnections; private final int inCount;
private int[] inConnectionSlots; private final boolean[] isOutConnected;
private AudioEngine engine; private final int outCount;
public Node(AudioEngine engine, int inCount, int outCount) { public Node(AudioEngine engine, int inCount, int outCount) {
this.inCount = inCount; this.inCount = inCount;
@ -43,6 +43,13 @@ public abstract class Node {
dst.inConnectionSlots[dstSlot] = srcSlot; dst.inConnectionSlots[dstSlot] = srcSlot;
} }
public abstract AudioBuffer getBuffer(int slot);
protected AudioBuffer getBufferFromInput(int inSlot) {
if(inConnections[inSlot] == null) return null;
return inConnections[inSlot].getBuffer(inConnectionSlots[inSlot]);
}
public AudioEngine getEngine() { public AudioEngine getEngine() {
return engine; return engine;
} }
@ -54,11 +61,4 @@ public abstract class Node {
public int getOutCount() { public int getOutCount() {
return outCount; return outCount;
} }
public abstract AudioBuffer getBuffer(int slot);
protected AudioBuffer getBufferFromInput(int inSlot) {
if(inConnections[inSlot] == null) return null;
return inConnections[inSlot].getBuffer(inConnectionSlots[inSlot]);
}
} }

View File

@ -8,7 +8,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class SamplePlayer extends Node { public class SamplePlayer extends Node {
private List<PlayingSample> samples; private final List<PlayingSample> samples;
public SamplePlayer(AudioEngine engine) { public SamplePlayer(AudioEngine engine) {
super(engine, 0, 1); super(engine, 0, 1);
@ -57,8 +57,8 @@ public class SamplePlayer extends Node {
} }
private static class PlayingSample { private static class PlayingSample {
boolean loop;
ISample sample; ISample sample;
int tick; int tick;
boolean loop;
} }
} }

View File

@ -4,8 +4,8 @@ import com.danitheskunk.skunkworks.audio.AudioBuffer;
import com.danitheskunk.skunkworks.audio.AudioEngine; import com.danitheskunk.skunkworks.audio.AudioEngine;
public class Sine extends Node { public class Sine extends Node {
private final double freq;
private int tick; private int tick;
private double freq;
public Sine(AudioEngine engine, double freq) { public Sine(AudioEngine engine, double freq) {
super(engine, 0, 1); super(engine, 0, 1);

View File

@ -3,9 +3,9 @@ package com.danitheskunk.skunkworks.backends.gl;
import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.opengl.GL46.*;
public class Program { public class Program {
Shader vertex;
Shader fragment; Shader fragment;
int program; int program;
Shader vertex;
public Program(String vertexSource, String fragmentSource) { public Program(String vertexSource, String fragmentSource) {
vertex = new Shader(vertexSource, GL_VERTEX_SHADER); vertex = new Shader(vertexSource, GL_VERTEX_SHADER);
@ -17,14 +17,14 @@ public class Program {
glLinkProgram(program); glLinkProgram(program);
} }
public void use() {
glUseProgram(program);
}
public int getAttribLocation(String attrib) { public int getAttribLocation(String attrib) {
return glGetAttribLocation(program, attrib); return glGetAttribLocation(program, attrib);
} }
public Shader getFragment() {
return fragment;
}
public int getUniformLocation(String attrib) { public int getUniformLocation(String attrib) {
return glGetUniformLocation(program, attrib); return glGetUniformLocation(program, attrib);
} }
@ -33,7 +33,7 @@ public class Program {
return vertex; return vertex;
} }
public Shader getFragment() { public void use() {
return fragment; glUseProgram(program);
} }
} }

View File

@ -41,15 +41,17 @@ class RenderContext extends BaseRenderContext implements IRenderContext {
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( drawTexture(
new Vec2i(pos.getX() + slice.getLeft().getWidth() + centerWidth, new Vec2i(pos.getX(),
pos.getY() pos.getY() + slice.getTop().getHeight() + centerHeight
), ),
slice.getTopRight() slice.getBottomLeft()
); );
drawTexture(new Vec2i(pos.getX(),
pos.getY() + slice.getTop().getHeight() + centerHeight
), slice.getBottomLeft());
drawTexture(Vec2i.add(pos, drawTexture(Vec2i.add(pos,
slice.getTopLeft().getSize(), slice.getTopLeft().getSize(),
new Vec2i(centerWidth, centerHeight) new Vec2i(centerWidth, centerHeight)

View File

@ -2,6 +2,7 @@ package com.danitheskunk.skunkworks.backends.gl;
import com.danitheskunk.skunkworks.Vec3f; import com.danitheskunk.skunkworks.Vec3f;
import com.danitheskunk.skunkworks.gfx.BaseRenderContext3D; import com.danitheskunk.skunkworks.gfx.BaseRenderContext3D;
import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.opengl.GL46.*;
public class RenderContext3D extends BaseRenderContext3D { public class RenderContext3D extends BaseRenderContext3D {

View File

@ -3,8 +3,8 @@ package com.danitheskunk.skunkworks.backends.gl;
import static org.lwjgl.opengl.GL46.*; import static org.lwjgl.opengl.GL46.*;
public class Shader { public class Shader {
private int shader; private final int shader;
private int type; private final int type;
public Shader(String source, int type) { public Shader(String source, int type) {
this.type = type; this.type = type;

View File

@ -14,6 +14,11 @@ class Texture implements ITexture {
this.img = img; this.img = img;
} }
@Override
public int getHeight() {
return img.getHeight();
}
//setters //setters
Image getImg() { Image getImg() {
return img; return img;
@ -24,20 +29,15 @@ class Texture implements ITexture {
return this.img.getSize(); return this.img.getSize();
} }
Recti getTexArea() {
return texArea;
}
@Override @Override
public int getWidth() { public int getWidth() {
return img.getWidth(); return img.getWidth();
} }
@Override
public int getHeight() {
return img.getHeight();
}
Recti getTexArea() {
return texArea;
}
void setTexArea(Recti texArea) { void setTexArea(Recti texArea) {
this.texArea = texArea; this.texArea = texArea;
} }

View File

@ -13,11 +13,11 @@ import java.util.List;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
class TextureAtlas { class TextureAtlas {
final private int textureID;
private final List<Texture> textures; private final List<Texture> textures;
private Texture atlasTexture; //for debugging private Texture atlasTexture; //for debugging
private Image img; private Image img;
private boolean shouldUpdate; private boolean shouldUpdate;
final private int textureID;
TextureAtlas() { TextureAtlas() {
img = new Image(new Vec2i(32, 32)); img = new Image(new Vec2i(32, 32));
@ -33,15 +33,10 @@ class TextureAtlas {
} }
public void bind() {
glBindTexture(GL_TEXTURE_2D, textureID);
}
ITexture addTexture(Image img) { ITexture addTexture(Image img) {
//todo: do the actual texture stuff //todo: do the actual texture stuff
//this.img = img; //this.img = img;
var texture = new Texture( var texture = new Texture(new Recti(new Vec2i(0, 0), img.getSize()),
new Recti(new Vec2i(0, 0), img.getSize()),
img img
); );
textures.add(texture); textures.add(texture);
@ -49,23 +44,25 @@ class TextureAtlas {
return texture; return texture;
} }
public void bind() {
glBindTexture(GL_TEXTURE_2D, textureID);
}
void doubleAtlasSize() { void doubleAtlasSize() {
img = new Image(Vec2i.mul(img.getSize(), 2)); img = new Image(Vec2i.mul(img.getSize(), 2));
System.out.printf( System.out.printf("Resized atlas to %dx%d\n",
"Resized atlas to %dx%d\n",
img.getSize().getX(), img.getSize().getX(),
img.getSize().getY() img.getSize().getY()
); );
atlasTexture = new Texture(new Recti(Vec2i.ZERO, img.getSize()), img); atlasTexture = new Texture(new Recti(Vec2i.ZERO, img.getSize()), img);
} }
public void update() { public Texture getAtlasTexture() {
if(shouldUpdate) { return atlasTexture;
repack(); }
updateImage();
uploadToGpu(); public Vec2i getSize() {
shouldUpdate = false; return img.getSize();
}
} }
void repack() { void repack() {
@ -108,6 +105,15 @@ class TextureAtlas {
} }
} }
public void update() {
if(shouldUpdate) {
repack();
updateImage();
uploadToGpu();
shouldUpdate = false;
}
}
void updateImage() { void updateImage() {
for(var tex : textures) { for(var tex : textures) {
img.drawImage(tex.getImg(), tex.getTexArea().getPos()); img.drawImage(tex.getImg(), tex.getTexArea().getPos());
@ -131,14 +137,6 @@ class TextureAtlas {
); );
} }
public Texture getAtlasTexture() {
return atlasTexture;
}
public Vec2i getSize() {
return img.getSize();
}
private static class TextureHeightComparator implements Comparator<Texture> { private static class TextureHeightComparator implements Comparator<Texture> {
@Override @Override
public int compare(Texture o1, Texture o2) { public int compare(Texture o1, Texture o2) {

View File

@ -18,18 +18,7 @@ import static org.lwjgl.opengl.GL46.*;
import static org.lwjgl.system.MemoryUtil.NULL; import static org.lwjgl.system.MemoryUtil.NULL;
public class Window extends BaseWindow { public class Window extends BaseWindow {
private static String vertexSource = """ private static final String fragmentSource = """
#version 450
layout(location = 0) in vec2 pos;
layout(location = 1) in ivec2 texCoord;
layout(location = 2) uniform vec2 windowSize;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = vec4(pos / windowSize * vec2(2.0f, -2.0f) + vec2(-1.0f, 1.0f), 0.0f, 1.0f);
out_texCoord = texCoord;
}
""";
private static String fragmentSource = """
#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;
@ -47,18 +36,7 @@ public class Window extends BaseWindow {
} }
} }
"""; """;
private static String vertexSource3D = """ private static final String fragmentSource3D = """
#version 450
layout(location = 0) in vec3 pos;
//layout(location = 1) in ivec2 texCoord;
layout(location = 2) uniform mat4 projection;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = projection * vec4(pos, 1.0f);
out_texCoord.x = pos.z;
}
""";
private static String fragmentSource3D = """
#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;
@ -69,18 +47,7 @@ public class Window extends BaseWindow {
color = vec4(1.0, texCoord.x / 2, 1.0, 1.0); color = vec4(1.0, texCoord.x / 2, 1.0, 1.0);
} }
"""; """;
private static String vertexSourceScaler = """ private static final String fragmentSourceScaler = """
#version 450
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 texCoord;
layout(location = 2) uniform vec2 windowSize;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = vec4(pos / windowSize * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f);
out_texCoord = texCoord;
}
""";
private static String fragmentSourceScaler = """
#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;
@ -96,22 +63,55 @@ public class Window extends BaseWindow {
//color = vec4(texCoord.xy, 0.0, 1.0); //color = vec4(texCoord.xy, 0.0, 1.0);
} }
"""; """;
private static final String vertexSource = """
#version 450
layout(location = 0) in vec2 pos;
layout(location = 1) in ivec2 texCoord;
layout(location = 2) uniform vec2 windowSize;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = vec4(pos / windowSize * vec2(2.0f, -2.0f) + vec2(-1.0f, 1.0f), 0.0f, 1.0f);
out_texCoord = texCoord;
}
""";
private static final String vertexSource3D = """
#version 450
layout(location = 0) in vec3 pos;
//layout(location = 1) in ivec2 texCoord;
layout(location = 2) uniform mat4 projection;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = projection * vec4(pos, 1.0f);
out_texCoord.x = pos.z;
}
""";
private static final String vertexSourceScaler = """
#version 450
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 texCoord;
layout(location = 2) uniform vec2 windowSize;
layout(location = 1) out vec2 out_texCoord;
void main() {
gl_Position = vec4(pos / windowSize * vec2(2.0f, 2.0f) + vec2(-1.0f, -1.0f), 0.0f, 1.0f);
out_texCoord = texCoord;
}
""";
private final int framebuffer;
private final int framebufferTex;
private final Program program; private final Program program;
private final Program program3D; private final Program program3D;
private final Program programScaler; private final Program programScaler;
private final RenderContext renderContext; private final RenderContext renderContext;
private final RenderContext3D renderContext3D; private final RenderContext3D renderContext3D;
private final Vec2i size; private final Vec2i size;
private Vec2i windowSize;
private final TextureAtlas textureAtlas; private final TextureAtlas textureAtlas;
private final long window; private final long window;
private boolean debug; private boolean debug;
private final Mat4f projection;
private boolean shouldClose; private boolean shouldClose;
private final int framebuffer; private final boolean[] stateMouseClicked;
private final int framebufferTex; private final boolean[] stateMouseDown;
private boolean[] stateMouseClicked; private Vec2i windowSize;
private boolean[] stateMouseDown;
private Mat4f projection;
public Window(Vec2i size, String title, Engine engine) { public Window(Vec2i size, String title, Engine engine) {
super(engine); super(engine);
@ -201,26 +201,53 @@ public class Window extends BaseWindow {
System.out.println(GL11.glGetInteger(GL_MAX_TEXTURE_SIZE)); System.out.println(GL11.glGetInteger(GL_MAX_TEXTURE_SIZE));
} }
private void mouseButtonCallback( @Override
long window, int button, int action, int mods public Vec2i getMousePos() {
) { //todo: scale mouse to stretchMode
switch(action) { double[] x = {0.0};
case GLFW_PRESS -> { double[] y = {0.0};
this.stateMouseClicked[button] = true; glfwGetCursorPos(window, x, y);
this.stateMouseDown[button] = true; var mousePos = new Vec2i((int) x[0], (int) y[0]);
var scaledMousePos = switch(this.stretchMode) {
case STRETCH -> {
var stretch = Vec2f.div(this.size, this.windowSize);
yield Vec2i.mul(stretch, mousePos);
} }
case GLFW_RELEASE -> { case ASPECT -> {
this.stateMouseDown[button] = false; var scale = Vec2f.div(this.size, this.windowSize);
var scalef = Math.max(scale.getX(), scale.getY());
var off = Vec2f.div(Vec2i.sub(windowSize,
Vec2f.mul(size.toVec2f(), 1.0 / scalef).toVec2i()
).toVec2f(), 2).toVec2i();
yield Vec2i.mul(Vec2i.sub(mousePos, off), 1.0 / scalef);
} }
} case INTEGER -> {
var scale = Vec2i.div(this.windowSize, this.size);
var scalei = Math.max(1, Math.min(scale.getX(), scale.getY()));
var off = Vec2i.div(Vec2i.sub(windowSize,
Vec2i.mul(size, scalei)
), 2);
yield Vec2i.div(Vec2i.sub(mousePos, off), scalei);
}
};
return Vec2i.max(Vec2i.ZERO,
Vec2i.min(Vec2i.sub(size, new Vec2i(1, 1)), scaledMousePos)
);
} }
private void windowSizeCallback(long window, int width, int height) { @Override
System.out.printf("new window size %d x %d\n", width, height); public boolean isMouseClicked(int button) {
windowSize = new Vec2i(width, height); return this.stateMouseClicked[button];
glViewport(0, 0, width, height); }
//glLoadIdentity();
//glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f); @Override
public boolean isMouseDown(int button) {
return this.stateMouseDown[button];
} }
@Override @Override
@ -258,6 +285,20 @@ public class Window extends BaseWindow {
return loadTextureArray(img, tileSize); return loadTextureArray(img, tileSize);
} }
private void mouseButtonCallback(
long window, int button, int action, int mods
) {
switch(action) {
case GLFW_PRESS -> {
this.stateMouseClicked[button] = true;
this.stateMouseDown[button] = true;
}
case GLFW_RELEASE -> {
this.stateMouseDown[button] = false;
}
}
}
@Override @Override
public void renderFinish(IRenderContext context) { public void renderFinish(IRenderContext context) {
if(debug) { if(debug) {
@ -268,6 +309,10 @@ public class Window extends BaseWindow {
} }
} }
public void renderFinish3D(IRenderContext3D context) {
}
@Override @Override
public IRenderContext renderStart() { public IRenderContext renderStart() {
program.use(); program.use();
@ -281,10 +326,6 @@ public class Window extends BaseWindow {
return renderContext; return renderContext;
} }
public void renderFinish3D(IRenderContext3D context) {
}
@Override @Override
public IRenderContext3D renderStart3D() { public IRenderContext3D renderStart3D() {
program3D.use(); program3D.use();
@ -295,8 +336,7 @@ public class Window extends BaseWindow {
glClearColor(0.f, 1.f, 0.f, 1.0f); glClearColor(0.f, 1.f, 0.f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glBegin(GL_TRIANGLES); //glBegin(GL_TRIANGLES);
glUniformMatrix4fv( glUniformMatrix4fv(program3D.getUniformLocation("projection"),
program3D.getUniformLocation("projection"),
true, true,
projection.asFloatArray() projection.asFloatArray()
); );
@ -391,7 +431,6 @@ public class Window extends BaseWindow {
glfwSwapBuffers(window); glfwSwapBuffers(window);
} }
@Override @Override
public void setDebug(boolean on) { public void setDebug(boolean on) {
this.debug = on; this.debug = on;
@ -402,55 +441,6 @@ public class Window extends BaseWindow {
return shouldClose; return shouldClose;
} }
@Override
public Vec2i getMousePos() {
//todo: scale mouse to stretchMode
double[] x = {0.0};
double[] y = {0.0};
glfwGetCursorPos(window, x, y);
var mousePos = new Vec2i((int) x[0], (int) y[0]);
var scaledMousePos = switch(this.stretchMode) {
case STRETCH -> {
var stretch = Vec2f.div(this.size, this.windowSize);
yield Vec2i.mul(stretch, mousePos);
}
case ASPECT -> {
var scale = Vec2f.div(this.size, this.windowSize);
var scalef = Math.max(scale.getX(), scale.getY());
var off = Vec2f.div(Vec2i.sub(windowSize,
Vec2f.mul(size.toVec2f(), 1.0 / scalef).toVec2i()
).toVec2f(), 2).toVec2i();
yield Vec2i.mul(Vec2i.sub(mousePos, off), 1.0 / scalef);
}
case INTEGER -> {
var scale = Vec2i.div(this.windowSize, this.size);
var scalei = Math.max(1, Math.min(scale.getX(), scale.getY()));
var off = Vec2i.div(Vec2i.sub(windowSize,
Vec2i.mul(size, scalei)
), 2);
yield Vec2i.div(Vec2i.sub(mousePos, off), scalei);
}
};
return Vec2i.max(Vec2i.ZERO,
Vec2i.min(Vec2i.sub(size, new Vec2i(1, 1)), scaledMousePos)
);
}
@Override
public boolean isMouseClicked(int button) {
return this.stateMouseClicked[button];
}
@Override
public boolean isMouseDown(int button) {
return this.stateMouseDown[button];
}
@Override @Override
public void tick() { //one tick per update call? public void tick() { //one tick per update call?
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
@ -462,4 +452,12 @@ public class Window extends BaseWindow {
Arrays.fill(stateMouseClicked, false); Arrays.fill(stateMouseClicked, false);
glfwPollEvents(); glfwPollEvents();
} }
private void windowSizeCallback(long window, int width, int height) {
System.out.printf("new window size %d x %d\n", width, height);
windowSize = new Vec2i(width, height);
glViewport(0, 0, width, height);
//glLoadIdentity();
//glOrtho(0.0f, width, height, 0.0f, 0.0f, 1.0f);
}
} }

View File

@ -33,10 +33,12 @@ 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( drawTextureRectangle(
Vec2i.add(new Vec2i(x, y), off), new Recti(Vec2i.add(new Vec2i(x, y), off), tex.getSize()),
tex.getSize() tex,
), tex, color, true); color,
true
);
x += font.getXAdvance(ch); x += font.getXAdvance(ch);
} }
} }
@ -63,22 +65,18 @@ abstract public class BaseRenderContext implements IRenderContext {
drawTexture(pixelPos, fullFont.getTexture(0xdb), bgColor); drawTexture(pixelPos, fullFont.getTexture(0xdb), bgColor);
if(isHalfWidth && halfFont != null) { if(isHalfWidth && halfFont != null) {
drawTexture( drawTexture(pixelPos,
pixelPos,
halfFont.getTexture(terminal.getLeftHalfChar(charPos)), halfFont.getTexture(terminal.getLeftHalfChar(charPos)),
fgColor fgColor
); );
drawTexture( drawTexture(new Vec2i(pixelPos.getX() + halfCharSize.getX(),
new Vec2i(
pixelPos.getX() + halfCharSize.getX(),
pixelPos.getY() pixelPos.getY()
), ),
halfFont.getTexture(terminal.getRightHalfChar(charPos)), halfFont.getTexture(terminal.getRightHalfChar(charPos)),
fgColor fgColor
); );
} else { } else {
drawTexture( drawTexture(pixelPos,
pixelPos,
fullFont.getTexture(terminal.getChar(charPos)), fullFont.getTexture(terminal.getChar(charPos)),
fgColor fgColor
); );

View File

@ -1,7 +1,5 @@
package com.danitheskunk.skunkworks.gfx; package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.Mat4f;
abstract public class BaseRenderContext3D implements IRenderContext3D { abstract public class BaseRenderContext3D implements IRenderContext3D {
} }

View File

@ -1,18 +1,18 @@
package com.danitheskunk.skunkworks.gfx; package com.danitheskunk.skunkworks.gfx;
public final class Color { public final class Color {
public final static Color WHITE = new Color(255, 255, 255);
public final static Color LIGHT_GRAY = new Color(192, 192, 192);
public final static Color GRAY = new Color(128, 128, 128);
public final static Color DARK_GRAY = new Color(64, 64, 64);
public final static Color BLACK = new Color(0, 0, 0); public final static Color BLACK = new Color(0, 0, 0);
public final static Color RED = new Color(255, 0, 0);
public final static Color GREEN = new Color(0, 255, 0);
public final static Color BLUE = new Color(0, 0, 255); public final static Color BLUE = new Color(0, 0, 255);
public final static Color YELLOW = new Color(255, 255, 0);
public final static Color MAGENTA = new Color(255, 0, 255);
public final static Color CYAN = new Color(0, 255, 255); public final static Color CYAN = new Color(0, 255, 255);
public final static Color DARK_GRAY = new Color(64, 64, 64);
public final static Color GRAY = new Color(128, 128, 128);
public final static Color GREEN = new Color(0, 255, 0);
public final static Color LIGHT_GRAY = new Color(192, 192, 192);
public final static Color MAGENTA = new Color(255, 0, 255);
public final static Color RED = new Color(255, 0, 0);
public final static Color TRANS_BLACK = new Color(0, 0, 0, 0); public final static Color TRANS_BLACK = new Color(0, 0, 0, 0);
public final static Color WHITE = new Color(255, 255, 255);
public final static Color YELLOW = new Color(255, 255, 0);
private final int r, g, b, a; private final int r, g, b, a;
@ -30,20 +30,20 @@ public final class Color {
this.a = a; this.a = a;
} }
public int getR() { public int getA() {
return r; return a;
}
public int getG() {
return g;
} }
public int getB() { public int getB() {
return b; return b;
} }
public int getA() { public int getG() {
return a; return g;
}
public int getR() {
return r;
} }
@Override @Override

View File

@ -14,17 +14,18 @@ public interface IRenderContext {
void drawString(Vec2i pos, String string, IFont font, Color color); void drawString(Vec2i pos, String string, IFont font, Color color);
void drawTerminal(Terminal terminal);
void drawTerminal(Terminal terminal, Vec2i pos);
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, boolean repeat); void drawTextureRectangle(Recti rect, ITexture texture, boolean repeat);
void drawTextureRectangle(Recti rect, ITexture texture, Color color, void drawTextureRectangle(
boolean repeat); Recti rect, ITexture texture, Color color, boolean repeat
);
void drawTerminal(Terminal terminal);
void drawTerminal(Terminal terminal, Vec2i pos);
//todo: drawTextureRectangleRepeat //todo: drawTextureRectangleRepeat
} }

View File

@ -3,9 +3,9 @@ package com.danitheskunk.skunkworks.gfx;
import com.danitheskunk.skunkworks.Vec2i; import com.danitheskunk.skunkworks.Vec2i;
public interface ITexture { public interface ITexture {
int getHeight();
Vec2i getSize(); Vec2i getSize();
int getWidth(); int getWidth();
int getHeight();
} }

View File

@ -32,41 +32,6 @@ public class Image {
this.size = size; this.size = size;
} }
//getters
public byte[] getData() {
return data;
}
public Vec2i getSize() {
return size;
}
public int getWidth() {
return size.getX();
}
public int getHeight() {
return size.getY();
}
public Color getPixel(Vec2i pos) {
int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
return new Color(
((int) data[i]) & 0xFF,
((int) data[i + 1]) & 0xFF,
((int) data[i + 2]) & 0xFF,
((int) data[i + 3]) & 0xFF
);
}
public void setPixel(Vec2i pos, Color col) {
int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
data[i] = (byte) (col.getR() & 0xFF);
data[i + 1] = (byte) (col.getG() & 0xFF);
data[i + 2] = (byte) (col.getB() & 0xFF);
data[i + 3] = (byte) (col.getA() & 0xFF);
}
public void drawImage(Image srcImage, Vec2i destPos) { public void drawImage(Image srcImage, Vec2i destPos) {
drawImage(srcImage, destPos, new Recti(Vec2i.ZERO, drawImage(srcImage, destPos, new Recti(Vec2i.ZERO,
srcImage.getSize())); srcImage.getSize()));
@ -85,9 +50,43 @@ public class Image {
} }
} }
//getters
public byte[] getData() {
return data;
}
public int getHeight() {
return size.getY();
}
public Color getPixel(Vec2i pos) {
int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
return new Color(((int) data[i]) & 0xFF,
((int) data[i + 1]) & 0xFF,
((int) data[i + 2]) & 0xFF,
((int) data[i + 3]) & 0xFF
);
}
public Vec2i getSize() {
return size;
}
public Image getSubImage(Recti rect) { public Image getSubImage(Recti rect) {
Image img = new Image(rect.getSize()); Image img = new Image(rect.getSize());
img.drawImage(this, Vec2i.ZERO, rect); img.drawImage(this, Vec2i.ZERO, rect);
return img; return img;
} }
public int getWidth() {
return size.getX();
}
public void setPixel(Vec2i pos, Color col) {
int i = pos.getX() * 4 + pos.getY() * 4 * size.getX();
data[i] = (byte) (col.getR() & 0xFF);
data[i + 1] = (byte) (col.getG() & 0xFF);
data[i + 2] = (byte) (col.getB() & 0xFF);
data[i + 3] = (byte) (col.getA() & 0xFF);
}
} }

View File

@ -1,19 +1,21 @@
package com.danitheskunk.skunkworks.gfx; package com.danitheskunk.skunkworks.gfx;
public class NineSlice { public class NineSlice {
private ITexture topLeft; private final ITexture bottom;
private ITexture topRight; private final ITexture bottomLeft;
private ITexture bottomLeft; private final ITexture bottomRight;
private ITexture bottomRight; private final ITexture center;
private ITexture top; private final ITexture left;
private ITexture right; private final ITexture right;
private ITexture bottom; private final ITexture top;
private ITexture left; private final ITexture topLeft;
private ITexture center; private final ITexture topRight;
public NineSlice(ITexture topLeft, ITexture topRight, ITexture bottomLeft, public NineSlice(
ITexture topLeft, ITexture topRight, ITexture bottomLeft,
ITexture bottomRight, ITexture top, ITexture right, ITexture bottom, ITexture bottomRight, ITexture top, ITexture right, ITexture bottom,
ITexture left, ITexture center) { ITexture left, ITexture center
) {
this.topLeft = topLeft; this.topLeft = topLeft;
this.topRight = topRight; this.topRight = topRight;
this.bottomLeft = bottomLeft; this.bottomLeft = bottomLeft;
@ -25,12 +27,8 @@ public class NineSlice {
this.center = center; this.center = center;
} }
public ITexture getTopLeft() { public ITexture getBottom() {
return topLeft; return bottom;
}
public ITexture getTopRight() {
return topRight;
} }
public ITexture getBottomLeft() { public ITexture getBottomLeft() {
@ -41,23 +39,27 @@ public class NineSlice {
return bottomRight; return bottomRight;
} }
public ITexture getTop() { public ITexture getCenter() {
return top; return center;
}
public ITexture getRight() {
return right;
}
public ITexture getBottom() {
return bottom;
} }
public ITexture getLeft() { public ITexture getLeft() {
return left; return left;
} }
public ITexture getCenter() { public ITexture getRight() {
return center; return right;
}
public ITexture getTop() {
return top;
}
public ITexture getTopLeft() {
return topLeft;
}
public ITexture getTopRight() {
return topRight;
} }
} }

View File

@ -2,48 +2,48 @@ package com.danitheskunk.skunkworks.gfx.font;
public class Cp437 { public class Cp437 {
public final static int BOX_DOUBLE_BOTTOM_LEFT = 0xBB;
public final static int BOX_DOUBLE_BOTTOM_SINGLE_LEFT = 0xB7;
public final static int BOX_DOUBLE_CROSS = 0xCE;
public final static int BOX_DOUBLE_HORIZONTAL = 0xCD;
public final static int BOX_DOUBLE_HORIZONTAL_BOTTOM = 0xCB;
public final static int BOX_DOUBLE_HORIZONTAL_SINGLE_BOTTOM = 0xD1;
public final static int BOX_DOUBLE_HORIZONTAL_SINGLE_TOP = 0xCF;
public final static int BOX_DOUBLE_RIGHT_BOTTOM = 0xC9;
public final static int BOX_DOUBLE_RIGHT_SINGLE_BOTTOM = 0xD5;
public final static int BOX_DOUBLE_TOP_LEFT = 0xBC;
public final static int BOX_DOUBLE_TOP_RIGHT = 0xC8;
public final static int BOX_DOUBLE_TOP_SINGLE_LEFT = 0xBD;
public final static int BOX_DOUBLE_TOP_SINGLE_RIGHT = 0xD3;
public final static int BOX_DOUBLE_VERTICAL = 0xBA;
public final static int BOX_DOUBLE_VERTICAL_LEFT = 0xB9;
public final static int BOX_DOUBLE_VERTICAL_RIGHT = 0xCC;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_HORIZONTAL = 0xD7;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_LEFT = 0xB6;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_RIGHT = 0xC7;
public final static int BOX_DOUBlE_HORIZONTAL_TOP = 0xCA;
public final static int BOX_SINGLE_BOTTOM_DOUBLE_LEFT = 0xB8;
public final static int BOX_SINGLE_BOTTOM_LEFT = 0xBF;
public final static int BOX_SINGLE_CROSS = 0xC5;
public final static int BOX_SINGLE_HORIZONTAL = 0xC4;
public final static int BOX_SINGLE_HORIZONTAL_BOTTOM = 0xC2;
public final static int BOX_SINGLE_HORIZONTAL_DOUBLE_BOTTOM = 0xD2;
public final static int BOX_SINGLE_HORIZONTAL_DOUBLE_TOP = 0xD0;
public final static int BOX_SINGLE_HORIZONTAL_TOP = 0xC1;
public final static int BOX_SINGLE_RIGHT_BOTTOM = 0xDA;
public final static int BOX_SINGLE_RIGHT_DOUBLE_BOTTOM = 0xD6;
public final static int BOX_SINGLE_TOP_DOUBLE_LEFT = 0xBE;
public final static int BOX_SINGLE_TOP_DOUBLE_RIGHT = 0xD4;
public final static int BOX_SINGLE_TOP_LEFT = 0xD9;
public final static int BOX_SINGLE_TOP_RIGHT = 0xC0;
//box drawing names... name part priority: (SINGLE/DOUBLE modifier first, //box drawing names... name part priority: (SINGLE/DOUBLE modifier first,
// only when it changes), CROSS, VERTICAL, HORIZONTAL, TOP, RIGHT, BOTTOM, // only when it changes), CROSS, VERTICAL, HORIZONTAL, TOP, RIGHT, BOTTOM,
// LEFT // LEFT
public final static int BOX_SINGLE_VERTICAL = 0xB3; public final static int BOX_SINGLE_VERTICAL = 0xB3;
public final static int BOX_SINGLE_VERTICAL_LEFT = 0xB4;
public final static int BOX_SINGLE_VERTICAL_DOUBLE_LEFT = 0xB5;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_LEFT = 0xB6;
public final static int BOX_DOUBLE_BOTTOM_SINGLE_LEFT = 0xB7;
public final static int BOX_SINGLE_BOTTOM_DOUBLE_LEFT = 0xB8;
public final static int BOX_DOUBLE_VERTICAL_LEFT = 0xB9;
public final static int BOX_DOUBLE_VERTICAL = 0xBA;
public final static int BOX_DOUBLE_BOTTOM_LEFT = 0xBB;
public final static int BOX_DOUBLE_TOP_LEFT = 0xBC;
public final static int BOX_DOUBLE_TOP_SINGLE_LEFT = 0xBD;
public final static int BOX_SINGLE_TOP_DOUBLE_LEFT = 0xBE;
public final static int BOX_SINGLE_BOTTOM_LEFT = 0xBF;
public final static int BOX_SINGLE_TOP_RIGHT = 0xC0;
public final static int BOX_SINGLE_HORIZONTAL_TOP = 0xC1;
public final static int BOX_SINGLE_HORIZONTAL_BOTTOM = 0xC2;
public final static int BOX_SINGLE_VERTICAL_RIGHT = 0xC3;
public final static int BOX_SINGLE_HORIZONTAL = 0xC4;
public final static int BOX_SINGLE_CROSS = 0xC5;
public final static int BOX_SINGLE_VERTICAL_DOUBLE_RIGHT = 0xC6;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_RIGHT = 0xC7;
public final static int BOX_DOUBLE_TOP_RIGHT = 0xC8;
public final static int BOX_DOUBLE_RIGHT_BOTTOM = 0xC9;
public final static int BOX_DOUBlE_HORIZONTAL_TOP = 0xCA;
public final static int BOX_DOUBLE_HORIZONTAL_BOTTOM = 0xCB;
public final static int BOX_DOUBLE_VERTICAL_RIGHT = 0xCC;
public final static int BOX_DOUBLE_HORIZONTAL = 0xCD;
public final static int BOX_DOUBLE_CROSS = 0xCE;
public final static int BOX_DOUBLE_HORIZONTAL_SINGLE_TOP = 0xCF;
public final static int BOX_SINGLE_HORIZONTAL_DOUBLE_TOP = 0xD0;
public final static int BOX_DOUBLE_HORIZONTAL_SINGLE_BOTTOM = 0xD1;
public final static int BOX_SINGLE_HORIZONTAL_DOUBLE_BOTTOM = 0xD2;
public final static int BOX_DOUBLE_TOP_SINGLE_RIGHT = 0xD3;
public final static int BOX_SINGLE_TOP_DOUBLE_RIGHT = 0xD4;
public final static int BOX_DOUBLE_RIGHT_SINGLE_BOTTOM = 0xD5;
public final static int BOX_SINGLE_RIGHT_DOUBLE_BOTTOM = 0xD6;
public final static int BOX_DOUBLE_VERTICAL_SINGLE_HORIZONTAL = 0xD7;
public final static int BOX_SINGLE_VERTICAL_DOUBLE_HORIZONTAL = 0xD8; public final static int BOX_SINGLE_VERTICAL_DOUBLE_HORIZONTAL = 0xD8;
public final static int BOX_SINGLE_TOP_LEFT = 0xD9; public final static int BOX_SINGLE_VERTICAL_DOUBLE_LEFT = 0xB5;
public final static int BOX_SINGLE_RIGHT_BOTTOM = 0xDA; public final static int BOX_SINGLE_VERTICAL_DOUBLE_RIGHT = 0xC6;
public final static int BOX_SINGLE_VERTICAL_LEFT = 0xB4;
public final static int BOX_SINGLE_VERTICAL_RIGHT = 0xC3;
} }

View File

@ -13,10 +13,10 @@ import static org.lwjgl.stb.STBTruetype.*;
public class FontTTF implements IFont { public class FontTTF implements IFont {
HashMap<Integer, Char> chars; HashMap<Integer, Char> chars;
STBTTFontinfo info;
int lineHeight; int lineHeight;
float size; float size;
float unscaled_size; float unscaled_size;
STBTTFontinfo info;
IWindow window; IWindow window;
public FontTTF(ByteBuffer buffer, float size, IWindow window) { public FontTTF(ByteBuffer buffer, float size, IWindow window) {
@ -39,8 +39,9 @@ public class FontTTF implements IFont {
this.size = stbtt_ScaleForPixelHeight(info, size); this.size = stbtt_ScaleForPixelHeight(info, size);
//precache ascii characters //precache ascii characters
for(int i = 32; i < 128; ++i) for(int i = 32; i < 128; ++i) {
cacheChar(i); cacheChar(i);
}
} }
void cacheChar(int ch) { void cacheChar(int ch) {
@ -54,8 +55,7 @@ public class FontTTF implements IFont {
int[] leftSideBearing = {0}; int[] leftSideBearing = {0};
ITexture tex; ITexture tex;
var bufmono = stbtt_GetCodepointBitmap( var bufmono = stbtt_GetCodepointBitmap(info,
info,
size, size,
size, size,
ch, ch,
@ -74,22 +74,43 @@ public class FontTTF implements IFont {
buf.put(b); buf.put(b);
} }
buf.flip(); buf.flip();
tex = window.loadTexture(new Image( tex = window.loadTexture(new Image(buf,
buf,
new Vec2i(width[0], height[0]) new Vec2i(width[0], height[0])
)); ));
} else { } else {
tex = window.loadTexture(new Image(Vec2i.ZERO)); tex = window.loadTexture(new Image(Vec2i.ZERO));
} }
stbtt_GetCodepointHMetrics(info, ch, advanceWidth, leftSideBearing); stbtt_GetCodepointHMetrics(info, ch, advanceWidth, leftSideBearing);
var c = new Char( var c = new Char(tex,
tex,
(int) (advanceWidth[0] * size), (int) (advanceWidth[0] * size),
new Vec2i(xoff[0], yoff[0]) new Vec2i(xoff[0], yoff[0])
); );
chars.put(ch, c); chars.put(ch, c);
} }
@Override
public int getLineHeight(int ch) {
cacheChar(ch);
return lineHeight;
}
@Override
public Vec2i getMonospaceSize() {
throw new RuntimeException("Not a monospace font");
}
@Override
public Vec2i getOffset(int ch) {
cacheChar(ch);
return chars.get(ch).off;
}
@Override
public ITexture getTexture(int ch) {
cacheChar(ch);
return chars.get(ch).tex;
}
@Override @Override
public int getXAdvance(int ch) { public int getXAdvance(int ch) {
cacheChar(ch); cacheChar(ch);
@ -106,33 +127,10 @@ public class FontTTF implements IFont {
return false; return false;
} }
@Override
public Vec2i getMonospaceSize() {
throw new RuntimeException("Not a monospace font");
}
@Override
public int getLineHeight(int ch) {
cacheChar(ch);
return lineHeight;
}
@Override
public Vec2i getOffset(int ch) {
cacheChar(ch);
return chars.get(ch).off;
}
@Override
public ITexture getTexture(int ch) {
cacheChar(ch);
return chars.get(ch).tex;
}
private class Char { private class Char {
ITexture tex;
int advance; int advance;
Vec2i off; Vec2i off;
ITexture tex;
Char(ITexture tex, int advance, Vec2i off) { Char(ITexture tex, int advance, Vec2i off) {
this.tex = tex; this.tex = tex;

View File

@ -6,14 +6,37 @@ import com.danitheskunk.skunkworks.gfx.ITexture;
import java.util.List; import java.util.List;
public class FontTileset implements IFont { public class FontTileset implements IFont {
private List<ITexture> textures; private final Vec2i charSize;
private Vec2i charSize; private final List<ITexture> textures;
public FontTileset(List<ITexture> textures) { public FontTileset(List<ITexture> textures) {
this.textures = textures; this.textures = textures;
this.charSize = textures.get(0).getSize(); this.charSize = textures.get(0).getSize();
} }
@Override
public int getLineHeight(int ch) {
return charSize.getY();
}
@Override
public Vec2i getMonospaceSize() {
return charSize;
}
@Override
public Vec2i getOffset(int ch) {
return Vec2i.ZERO;
}
@Override
public ITexture getTexture(int ch) {
if(ch >= 256 || ch < 0) {
ch = 0;
}
return textures.get(ch);
}
@Override @Override
public int getXAdvance(int ch) { public int getXAdvance(int ch) {
return charSize.getX(); return charSize.getX();
@ -28,27 +51,4 @@ public class FontTileset implements IFont {
public boolean isMonospace() { public boolean isMonospace() {
return true; return true;
} }
@Override
public Vec2i getMonospaceSize() {
return charSize;
}
@Override
public int getLineHeight(int ch) {
return charSize.getY();
}
@Override
public Vec2i getOffset(int ch) {
return Vec2i.ZERO;
}
@Override
public ITexture getTexture(int ch) {
if(ch >= 256 || ch < 0) {
ch = 0;
}
return textures.get(ch);
}
} }

View File

@ -6,6 +6,8 @@ import com.danitheskunk.skunkworks.gfx.ITexture;
public interface IFont { public interface IFont {
int getLineHeight(int ch); int getLineHeight(int ch);
Vec2i getMonospaceSize();
Vec2i getOffset(int ch); Vec2i getOffset(int ch);
ITexture getTexture(int ch); ITexture getTexture(int ch);
@ -15,6 +17,4 @@ public interface IFont {
boolean isCP437(); boolean isCP437();
boolean isMonospace(); boolean isMonospace();
Vec2i getMonospaceSize();
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
package com.danitheskunk.skunkworks.nodes; package com.danitheskunk.skunkworks.nodes;
public abstract class BaseTween { public abstract class BaseTween {
protected int endFrame;
protected double progress; protected double progress;
protected int startFrame; protected int startFrame;
protected int endFrame;
protected Runnable thenFunc; protected Runnable thenFunc;
public BaseTween() { public BaseTween() {
@ -11,9 +11,7 @@ public abstract class BaseTween {
thenFunc = null; thenFunc = null;
} }
public void setProgress(double progress) { protected abstract void apply();
this.progress = progress;
}
public BaseTween delay(int frames) { public BaseTween delay(int frames) {
startFrame += frames; startFrame += frames;
@ -21,10 +19,12 @@ public abstract class BaseTween {
return this; return this;
} }
public void setProgress(double progress) {
this.progress = progress;
}
public BaseTween then(Runnable func) { public BaseTween then(Runnable func) {
thenFunc = func; thenFunc = func;
return this; return this;
} }
protected abstract void apply();
} }

View File

@ -20,18 +20,6 @@ public class Node implements Iterable<Node> {
pos = Vec2f.ZERO; pos = Vec2f.ZERO;
} }
public Node getParent() {
return parent;
}
public Vec2f getPos() {
return pos;
}
public void setPos(Vec2f pos) {
this.pos = pos;
}
public void add(Node node) { public void add(Node node) {
if(node.parent != null) { if(node.parent != null) {
throw new RuntimeException("Can't add node to two nodes"); throw new RuntimeException("Can't add node to two nodes");
@ -40,22 +28,23 @@ public class Node implements Iterable<Node> {
children.add(node); children.add(node);
} }
public void remove(Node node) {
node.parent = null;
children.remove(node);
}
public void render(IRenderContext rc) {
for(var child : this) {
child.render(rc);
}
}
public Vec2f getAbsolutePos() { public Vec2f getAbsolutePos() {
if(parent == null) return pos; if(parent == null) return pos;
return Vec2f.add(parent.getAbsolutePos(), pos); return Vec2f.add(parent.getAbsolutePos(), pos);
} }
public int getCurrentFrame() {
return getRoot().getCurrentFrame();
}
public Node getParent() {
return parent;
}
public Vec2f getPos() {
return pos;
}
public NodeRoot getRoot() { public NodeRoot getRoot() {
var node = this; var node = this;
while(node.parent != null) { while(node.parent != null) {
@ -70,16 +59,27 @@ public class Node implements Iterable<Node> {
return children.iterator(); return children.iterator();
} }
public int getCurrentFrame() {
return getRoot().getCurrentFrame();
}
protected void prepareTween(BaseTween tween, int frames) { protected void prepareTween(BaseTween tween, int frames) {
var root = getRoot(); var root = getRoot();
tween.startFrame = root.getCurrentFrame(); tween.startFrame = root.getCurrentFrame();
tween.endFrame = tween.startFrame + frames; tween.endFrame = tween.startFrame + frames;
} }
public void remove(Node node) {
node.parent = null;
children.remove(node);
}
public void render(IRenderContext rc) {
for(var child : this) {
child.render(rc);
}
}
public void setPos(Vec2f pos) {
this.pos = pos;
}
public TweenPos tweenPos(Vec2f to, int frames) { public TweenPos tweenPos(Vec2f to, int frames) {
var tween = new TweenPos(); var tween = new TweenPos();
tween.start = pos; tween.start = pos;
@ -91,8 +91,8 @@ public class Node implements Iterable<Node> {
public class TweenPos extends BaseTween { public class TweenPos extends BaseTween {
private Vec2f start;
private Vec2f end; private Vec2f end;
private Vec2f start;
@Override @Override
protected void apply() { protected void apply() {

View File

@ -1,10 +1,9 @@
package com.danitheskunk.skunkworks.nodes; package com.danitheskunk.skunkworks.nodes;
import com.danitheskunk.skunkworks.Timestep; import com.danitheskunk.skunkworks.Timestep;
import com.danitheskunk.skunkworks.Vec2f;
public class NodeRoot extends Node { public class NodeRoot extends Node {
private Tweener tweener; private final Tweener tweener;
public NodeRoot() { public NodeRoot() {
tweener = new Tweener(Timestep.FIXED); tweener = new Tweener(Timestep.FIXED);
@ -15,11 +14,11 @@ public class NodeRoot extends Node {
return tweener.getCurrentFrame(); return tweener.getCurrentFrame();
} }
public void tick() {
tweener.tick();
}
public Tweener getTweener() { public Tweener getTweener() {
return tweener; return tweener;
} }
public void tick() {
tweener.tick();
}
} }

View File

@ -15,12 +15,12 @@ public class NodeSprite extends Node {
return texture; return texture;
} }
public void setTexture(ITexture texture) {
this.texture = texture;
}
@Override @Override
public void render(IRenderContext rc) { public void render(IRenderContext rc) {
rc.drawTexture(getAbsolutePos().toVec2i(), texture); rc.drawTexture(getAbsolutePos().toVec2i(), texture);
} }
public void setTexture(ITexture texture) {
this.texture = texture;
}
} }

View File

@ -6,9 +6,9 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Tweener { public class Tweener {
private Timestep timestepMode;
private List<BaseTween> tweens;
private int currentFrame; private int currentFrame;
private final Timestep timestepMode;
private final List<BaseTween> tweens;
public Tweener(Timestep timestepMode) { public Tweener(Timestep timestepMode) {
this.timestepMode = timestepMode; this.timestepMode = timestepMode;
@ -16,6 +16,10 @@ public class Tweener {
this.currentFrame = 0; this.currentFrame = 0;
} }
public void add(BaseTween tween) {
tweens.add(tween);
}
public int getCurrentFrame() { public int getCurrentFrame() {
return currentFrame; return currentFrame;
} }
@ -43,8 +47,4 @@ public class Tweener {
} }
++currentFrame; ++currentFrame;
} }
public void add(BaseTween tween) {
tweens.add(tween);
}
} }

View File

@ -8,45 +8,44 @@ import com.sun.jna.platform.win32.WinNT;
import com.sun.jna.win32.W32APIOptions; import com.sun.jna.win32.W32APIOptions;
public interface Dwm extends Library { public interface Dwm extends Library {
Dwm INSTANCE = Native.load( WinDef.DWORD DWMWA_ALLOW_NCPAINT = new WinDef.DWORD(4);
"dwmapi", WinDef.DWORD DWMWA_CAPTION_BUTTON_BOUNDS = new WinDef.DWORD(5);
WinDef.DWORD DWMWA_CLOAK = new WinDef.DWORD(13);
WinDef.DWORD DWMWA_CLOAKED = new WinDef.DWORD(14);
WinDef.DWORD DWMWA_DISALLOW_PEEK = new WinDef.DWORD(11);
WinDef.DWORD DWMWA_EXCLUDED_FROM_PEEK = new WinDef.DWORD(12);
WinDef.DWORD DWMWA_EXTENDED_FRAME_BOUNDS = new WinDef.DWORD(9);
WinDef.DWORD DWMWA_FLIP3D_POLICY = new WinDef.DWORD(8);
WinDef.DWORD DWMWA_FORCE_ICONIC_REPRESENTATION = new WinDef.DWORD(7);
WinDef.DWORD DWMWA_FREEZE_REPRESENTATION = new WinDef.DWORD(15);
WinDef.DWORD DWMWA_HAS_ICONIC_BITMAP = new WinDef.DWORD(10);
WinDef.DWORD DWMWA_LAST = new WinDef.DWORD(16);
WinDef.DWORD DWMWA_NCRENDERING_ENABLED = new WinDef.DWORD(1);
WinDef.DWORD DWMWA_NCRENDERING_POLICY = new WinDef.DWORD(2);
WinDef.DWORD DWMWA_NONCLIENT_RTL_LAYOUT = new WinDef.DWORD(6);
WinDef.DWORD DWMWA_TRANSITIONS_FORCEDISABLED = new WinDef.DWORD(3);
WinDef.DWORD DWMWA_WINDOW_CORNER_PREFERENCE = new WinDef.DWORD(33);
WinDef.DWORD DWMWCP_DEFAULT = new WinDef.DWORD(0);
//todo: fix/complete DWMWA list
WinDef.DWORD DWMWCP_DONOTROUND = new WinDef.DWORD(1);
WinDef.DWORD DWMWCP_ROUND = new WinDef.DWORD(2);
WinDef.DWORD DWMWCP_ROUNDSMALL = new WinDef.DWORD(3);
Dwm INSTANCE = Native.load("dwmapi",
Dwm.class, Dwm.class,
W32APIOptions.DEFAULT_OPTIONS W32APIOptions.DEFAULT_OPTIONS
); );
WinNT.HRESULT DwmExtendFrameIntoClientArea(
WinDef.HWND hwnd, MARGINS pMarInset
);
WinDef.DWORD DWMWA_NCRENDERING_ENABLED = new WinDef.DWORD(1); WinNT.HRESULT DwmGetWindowAttribute(
WinDef.DWORD DWMWA_NCRENDERING_POLICY = new WinDef.DWORD(2); WinDef.HWND hwnd, WinDef.DWORD dwAttribute, Pointer pvAttribute,
WinDef.DWORD DWMWA_TRANSITIONS_FORCEDISABLED = new WinDef.DWORD(3); WinDef.DWORD cbAttribute
WinDef.DWORD DWMWA_ALLOW_NCPAINT = new WinDef.DWORD(4); );
WinDef.DWORD DWMWA_CAPTION_BUTTON_BOUNDS = new WinDef.DWORD(5);
WinDef.DWORD DWMWA_NONCLIENT_RTL_LAYOUT = new WinDef.DWORD(6);
WinDef.DWORD DWMWA_FORCE_ICONIC_REPRESENTATION = new WinDef.DWORD(7);
WinDef.DWORD DWMWA_FLIP3D_POLICY = new WinDef.DWORD(8);
WinDef.DWORD DWMWA_EXTENDED_FRAME_BOUNDS = new WinDef.DWORD(9);
WinDef.DWORD DWMWA_HAS_ICONIC_BITMAP = new WinDef.DWORD(10);
WinDef.DWORD DWMWA_DISALLOW_PEEK = new WinDef.DWORD(11);
WinDef.DWORD DWMWA_EXCLUDED_FROM_PEEK = new WinDef.DWORD(12);
WinDef.DWORD DWMWA_CLOAK = new WinDef.DWORD(13);
WinDef.DWORD DWMWA_CLOAKED = new WinDef.DWORD(14);
WinDef.DWORD DWMWA_FREEZE_REPRESENTATION = new WinDef.DWORD(15);
WinDef.DWORD DWMWA_LAST = new WinDef.DWORD(16);
WinDef.DWORD DWMWA_WINDOW_CORNER_PREFERENCE = new WinDef.DWORD(33);
//todo: fix/complete DWMWA list
WinDef.DWORD DWMWCP_DEFAULT = new WinDef.DWORD(0); WinNT.HRESULT DwmSetWindowAttribute(
WinDef.DWORD DWMWCP_DONOTROUND = new WinDef.DWORD(1); WinDef.HWND hwnd, WinDef.DWORD dwAttribute, Pointer pvAttribute,
WinDef.DWORD DWMWCP_ROUND = new WinDef.DWORD(2); WinDef.DWORD cbAttribute
WinDef.DWORD DWMWCP_ROUNDSMALL = new WinDef.DWORD(3); );
WinNT.HRESULT DwmExtendFrameIntoClientArea(WinDef.HWND hwnd,
MARGINS pMarInset);
WinNT.HRESULT DwmGetWindowAttribute(WinDef.HWND hwnd,
WinDef.DWORD dwAttribute, Pointer pvAttribute,
WinDef.DWORD cbAttribute);
WinNT.HRESULT DwmSetWindowAttribute(WinDef.HWND hwnd,
WinDef.DWORD dwAttribute, Pointer pvAttribute,
WinDef.DWORD cbAttribute);
} }

View File

@ -9,13 +9,12 @@ public class MARGINS extends Structure implements Structure.ByReference {
public int cxLeftWidth; public int cxLeftWidth;
public int cxRightWidth; public int cxRightWidth;
public int cyTopHeight;
public int cyBottomHeight; public int cyBottomHeight;
public int cyTopHeight;
@Override @Override
protected List<String> getFieldOrder() { protected List<String> getFieldOrder() {
return Arrays.asList( return Arrays.asList("cxLeftWidth",
"cxLeftWidth",
"cxRightWidth", "cxRightWidth",
"cyTopHeight", "cyTopHeight",
"cyBottomHeight" "cyBottomHeight"

View File

@ -5,15 +5,15 @@ import com.sun.jna.platform.win32.WinDef;
@Structure.FieldOrder({"cbSize", "rcTitleBar", "rgstate"}) @Structure.FieldOrder({"cbSize", "rcTitleBar", "rgstate"})
public class TITLEBARINFO extends Structure { public class TITLEBARINFO extends Structure {
// Index constants
public static final int TITLE_BAR = 0;
public static final int RESERVED = 1;
public static final int MINIMIZE_BUTTON = 2;
public static final int MAXIMIZE_BUTTON = 3;
public static final int HELP_BUTTON = 4;
public static final int CLOSE_BUTTON = 5;
// Child amount constant // Child amount constant
public static final int CCHILDREN_TITLEBAR = 5; public static final int CCHILDREN_TITLEBAR = 5;
public static final int CLOSE_BUTTON = 5;
public static final int HELP_BUTTON = 4;
public static final int MAXIMIZE_BUTTON = 3;
public static final int MINIMIZE_BUTTON = 2;
public static final int RESERVED = 1;
// Index constants
public static final int TITLE_BAR = 0;
public int cbSize; public int cbSize;
public WinDef.RECT rcTitleBar; public WinDef.RECT rcTitleBar;
public int[] rgstate; public int[] rgstate;

View File

@ -6,19 +6,26 @@ import com.sun.jna.platform.win32.WinDef;
import com.sun.jna.win32.W32APIOptions; import com.sun.jna.win32.W32APIOptions;
public interface User32Extra extends User32 { public interface User32Extra extends User32 {
User32Extra INSTANCE = Native.load( int HSHELL_WINDOWCREATED = 1;
"user32", User32Extra INSTANCE = Native.load("user32",
User32Extra.class, User32Extra.class,
W32APIOptions.DEFAULT_OPTIONS W32APIOptions.DEFAULT_OPTIONS
); );
int PM_NOREMOVE = 0x00;
int PM_NOYIELD = 0x02;
int PM_REMOVE = 0x01;
// States // States
int STATE_SYSTEM_FOCUSABLE = 0x00100000; int STATE_SYSTEM_FOCUSABLE = 0x00100000;
int STATE_SYSTEM_INVISIBLE = 0x00008000; int STATE_SYSTEM_INVISIBLE = 0x00008000;
int STATE_SYSTEM_OFFSCREEN = 0x00010000; int STATE_SYSTEM_OFFSCREEN = 0x00010000;
int STATE_SYSTEM_UNAVAILABLE = 0x00000001;
int STATE_SYSTEM_PRESSED = 0x00000008; int STATE_SYSTEM_PRESSED = 0x00000008;
int STATE_SYSTEM_UNAVAILABLE = 0x00000001;
// https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
int VK_LBUTTON = 0x01;
int VK_MBUTTON = 0x04;
int VK_RBUTTON = 0x02;
int WH_SHELL = 10;
int WM_TIMER = 0x0113;
// Extended Styles // Extended Styles
// https://docs.microsoft.com/en-gb/windows/desktop/winmsg/extended-window-styles // https://docs.microsoft.com/en-gb/windows/desktop/winmsg/extended-window-styles
int WS_EX_ACCEPTFILES = 0x00000010; int WS_EX_ACCEPTFILES = 0x00000010;
@ -46,40 +53,23 @@ public interface User32Extra extends User32 {
int WS_EX_TOPMOST = 0x00000008; int WS_EX_TOPMOST = 0x00000008;
int WS_EX_TRANSPARENT = 0x00000020; int WS_EX_TRANSPARENT = 0x00000020;
int WS_EX_WINDOWEDGE = 0x00000100; int WS_EX_WINDOWEDGE = 0x00000100;
long WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE); long WS_EX_OVERLAPPEDWINDOW = (WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE);
long WS_EX_PALETTEWINDOW = ( long WS_EX_PALETTEWINDOW = (
WS_EX_WINDOWEDGE | WS_EX_WINDOWEDGE | WS_EX_TOOLWINDOW | WS_EX_TOPMOST
WS_EX_TOOLWINDOW |
WS_EX_TOPMOST
); );
int WH_SHELL = 10; HCURSOR GetCursor();
int WM_TIMER = 0x0113;
int HSHELL_WINDOWCREATED = 1;
// https://docs.microsoft.com/en-us/windows/desktop/inputdev/virtual-key-codes
int VK_LBUTTON = 0x01;
int VK_RBUTTON = 0x02;
int VK_MBUTTON = 0x04;
int PM_NOREMOVE = 0x00;
int PM_REMOVE = 0x01;
int PM_NOYIELD = 0x02;
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-gettitlebarinfo
boolean GetTitleBarInfo(WinDef.HWND hwnd, TITLEBARINFO titlebarinfo);
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getlastactivepopup // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getlastactivepopup
WinDef.HWND GetLastActivePopup(WinDef.HWND hwnd); WinDef.HWND GetLastActivePopup(WinDef.HWND hwnd);
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-isiconic // https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-gettitlebarinfo
boolean IsIconic(WinDef.HWND hwnd); boolean GetTitleBarInfo(WinDef.HWND hwnd, TITLEBARINFO titlebarinfo);
HCURSOR GetCursor();
WinDef.HWND GetTopWindow(HWND hWnd); WinDef.HWND GetTopWindow(HWND hWnd);
WinDef.HWND GetWindow(HWND hWnd, int flag); WinDef.HWND GetWindow(HWND hWnd, int flag);
// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-isiconic
boolean IsIconic(WinDef.HWND hwnd);
} }

View File

@ -6,12 +6,12 @@ import com.sun.jna.win32.W32APIOptions;
public interface WinUserExtra extends WinUser, public interface WinUserExtra extends WinUser,
com.sun.jna.win32.StdCallLibrary { com.sun.jna.win32.StdCallLibrary {
WinUserExtra INSTANCE = Native.load( WinUserExtra INSTANCE = Native.load("user32",
"user32",
WinUserExtra.class, WinUserExtra.class,
W32APIOptions.DEFAULT_OPTIONS W32APIOptions.DEFAULT_OPTIONS
); );
//todo: lpTimerFunc should be TIMERPROC //todo: lpTimerFunc should be TIMERPROC
UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse, PVOID lpTimerFunc); UINT_PTR SetTimer(HWND hWnd, UINT_PTR nIDEvent, UINT uElapse,
PVOID lpTimerFunc);
} }

View File

@ -12,7 +12,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Window { public class Window {
private WinDef.HWND hwnd; private final WinDef.HWND hwnd;
public Window(WinDef.HWND hwnd) { public Window(WinDef.HWND hwnd) {
this.hwnd = hwnd; this.hwnd = hwnd;
@ -62,13 +62,13 @@ public class Window {
public static void onKey() { public static void onKey() {
var user32 = User32Extra.INSTANCE; var user32 = User32Extra.INSTANCE;
var kernel32 = Kernel32.INSTANCE; var kernel32 = Kernel32.INSTANCE;
var res = user32.SetWindowsHookEx( var res = user32.SetWindowsHookEx(User32Extra.WH_KEYBOARD_LL,
User32Extra.WH_KEYBOARD_LL,
new WinUser.HOOKPROC() { new WinUser.HOOKPROC() {
public WinDef.LRESULT callback(int nCode, WinDef.WPARAM wparam public WinDef.LRESULT callback(
, WinDef.LPARAM lparam) { int nCode, WinDef.WPARAM wparam, WinDef.LPARAM lparam
var kb = new WinUser.KBDLLHOOKSTRUCT().newInstance( ) {
WinUser.KBDLLHOOKSTRUCT.class, var kb =
new WinUser.KBDLLHOOKSTRUCT().newInstance(WinUser.KBDLLHOOKSTRUCT.class,
lparam.toPointer() lparam.toPointer()
); );
System.out.println(kb.vkCode); System.out.println(kb.vkCode);
@ -105,11 +105,11 @@ public class Window {
var kernel32 = Kernel32.INSTANCE; var kernel32 = Kernel32.INSTANCE;
var hmod = kernel32.GetModuleHandle("kernel32.dll"); var hmod = kernel32.GetModuleHandle("kernel32.dll");
//todo: try RegisterShellHookWindow instead //todo: try RegisterShellHookWindow instead
var res = user32.SetWindowsHookEx( var res = user32.SetWindowsHookEx(User32Extra.WH_SHELL,
User32Extra.WH_SHELL,
new WinUser.HOOKPROC() { new WinUser.HOOKPROC() {
public WinDef.LRESULT callback(int nCode, WinDef.WPARAM wparam public WinDef.LRESULT callback(
, WinDef.LPARAM lparam) { int nCode, WinDef.WPARAM wparam, WinDef.LPARAM lparam
) {
System.out.println("got some message b"); System.out.println("got some message b");
if(nCode == User32Extra.HSHELL_WINDOWCREATED) { if(nCode == User32Extra.HSHELL_WINDOWCREATED) {
System.out.println("window created"); System.out.println("window created");
@ -163,7 +163,7 @@ public class Window {
if((style & User32.WS_TILED) != 0) str.append("ws_tiled, "); if((style & User32.WS_TILED) != 0) str.append("ws_tiled, ");
if((style & User32.WS_VISIBLE) != 0) str.append("ws_visible, "); if((style & User32.WS_VISIBLE) != 0) str.append("ws_visible, ");
if((style & User32.WS_VSCROLL) != 0) str.append("ws_vscroll, "); if((style & User32.WS_VSCROLL) != 0) str.append("ws_vscroll, ");
System.out.println(str.toString()); System.out.println(str);
} }
public void debugPrintStylesEx() { public void debugPrintStylesEx() {
@ -218,7 +218,184 @@ public class Window {
"ws_ex_transparent, "); "ws_ex_transparent, ");
if((style & User32Extra.WS_EX_WINDOWEDGE) != 0) str.append( if((style & User32Extra.WS_EX_WINDOWEDGE) != 0) str.append(
"ws_ex_windowedge, "); "ws_ex_windowedge, ");
System.out.println(str.toString()); System.out.println(str);
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Window)) {
return false;
}
return ((Window) o).hwnd.equals(this.hwnd);
}
public String getClassName() {
var user32 = User32Extra.INSTANCE;
char[] chars = new char[1024];
user32.GetClassName(hwnd, chars, 1024);
return Util.nullTerminatedCharArrayToString(chars);
}
public String getExecutableName() {
var user32 = User32Extra.INSTANCE;
var kernel32 = Kernel32.INSTANCE;
var handle =
kernel32.OpenProcess(WinNT.PROCESS_QUERY_LIMITED_INFORMATION,
false,
getProcessId()
);
char[] chars = new char[1024];
var len = new IntByReference();
len.setValue(1024);
kernel32.QueryFullProcessImageName(handle, 0, chars, len);
return Util.nullTerminatedCharArrayToString(chars);
}
public String getKey() {
return getExecutableName() + " $ " + getClassName();
}
private int getProcessId() {
var user32 = User32Extra.INSTANCE;
var ref = new IntByReference();
user32.GetWindowThreadProcessId(hwnd, ref);
return ref.getValue();
}
private int getStyle() {
var user32 = User32Extra.INSTANCE;
return user32.GetWindowLong(hwnd, WinUser.GWL_STYLE);
}
private int getStyleEx() {
var user32 = User32Extra.INSTANCE;
return user32.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
}
public String getTitle() {
var user32 = User32Extra.INSTANCE;
char[] chars = new char[1024];
user32.GetWindowText(hwnd, chars, 1024);
return Util.nullTerminatedCharArrayToString(chars);
}
private TITLEBARINFO getTitleBarInfo() {
var user32 = User32Extra.INSTANCE;
var tb = new TITLEBARINFO();
user32.GetTitleBarInfo(hwnd, tb);
return tb;
}
public boolean isClass(String str) {
return str.equals(getClassName());
}
public boolean isDwmCloaked() {
var user32 = User32Extra.INSTANCE;
var dwm = Dwm.INSTANCE;
var out = new IntByReference();
dwm.DwmGetWindowAttribute(hwnd,
Dwm.DWMWA_CLOAKED,
out.getPointer(),
new WinDef.DWORD(WinDef.DWORD.SIZE)
);
var val = out.getValue();
return val != 0;
}
public boolean isExecutableName(String str) {
return str.equals(getExecutableName());
}
public boolean isInAltTabList() {
var user32 = User32Extra.INSTANCE;
var walk = user32.GetAncestor(hwnd, WinUser.GA_ROOTOWNER);
WinDef.HWND test;
var window = new Window(hwnd);
if(walk == null) return false;
return walk.equals(hwnd) &&
user32.IsWindowVisible(hwnd) &&
window.getTitle().length() > 0 &&
!window.isToolWindow() &&
!window.isDwmCloaked() &&
!window.getClassName().equals("Progman");
}
private boolean isTitleBarVisible() {
var tb = getTitleBarInfo();
return (tb.rgstate[0] & User32Extra.STATE_SYSTEM_INVISIBLE) == 0;
}
public boolean isToolWindow() {
return (getStyleEx() & User32Extra.WS_EX_TOOLWINDOW) != 0;
}
public void move(Recti rectangle) {
var user32 = User32Extra.INSTANCE;
var dwm = Dwm.INSTANCE;
var pos = rectangle.getPos();
var size = rectangle.getSize();
var rect_with_shadow = new WinDef.RECT();
var rect_without_shadow = new WinDef.RECT();
var rect = new WinDef.RECT();
user32.GetWindowRect(hwnd, rect_with_shadow);
dwm.DwmGetWindowAttribute(hwnd,
Dwm.DWMWA_EXTENDED_FRAME_BOUNDS,
rect_without_shadow.getPointer(),
new WinDef.DWORD(rect_without_shadow.size())
);
rect_without_shadow.read();
var left_shadow = rect_without_shadow.left - rect_with_shadow.left;
var right_shadow = rect_with_shadow.right - rect_without_shadow.right;
var top_shadow = rect_without_shadow.top - rect_with_shadow.top;
var bottom_shaddow = rect_with_shadow.bottom -
rect_without_shadow.bottom;
rect.left = pos.getX() - left_shadow;
rect.top = pos.getY() - top_shadow;
rect.right = pos.getX() + size.getX() + right_shadow;
rect.bottom = pos.getY() + size.getY() + bottom_shaddow;
//user32.AdjustWindowRect(rect, new WinDef.DWORD(WinUser
// .WS_OVERLAPPEDWINDOW), new WinDef.BOOL(false));
//var style = getStyle();
//var styleex = getStyleEx();
//style &= ~(User32Extra.WS_CAPTION | User32Extra.WS_MINIMIZEBOX |
// User32Extra.WS_SYSMENU);
//styleex &= ~(User32Extra.WS_EX_DLGMODALFRAME | User32Extra
// .WS_EX_CLIENTEDGE | User32Extra.WS_EX_STATICEDGE);
//style |= User32Extra.WS_POPUP;
//user32.AdjustWindowRectEx(rect, new WinDef.DWORD(style), new WinDef
// .BOOL(false), new WinDef.DWORD(styleex));
user32.MoveWindow(hwnd,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
true
);
//user32.MoveWindow(hwnd, pos.getX(), pos.getY(), size.getX(), size
// .getY(), true);
user32.SetWindowPos(hwnd,
null,
0,
0,
0,
0,
WinUser.SWP_FRAMECHANGED |
WinUser.SWP_NOZORDER |
WinUser.SWP_NOOWNERZORDER |
WinUser.SWP_NOMOVE |
WinUser.SWP_NOSIZE |
WinUser.SWP_NOACTIVATE
);
} }
public void setBorder(boolean border) { public void setBorder(boolean border) {
@ -259,202 +436,20 @@ public class Window {
public void setBorderRounded(boolean rounded) { public void setBorderRounded(boolean rounded) {
var round = rounded ? Dwm.DWMWCP_ROUND : Dwm.DWMWCP_DONOTROUND; var round = rounded ? Dwm.DWMWCP_ROUND : Dwm.DWMWCP_DONOTROUND;
var roundref = new WinDef.DWORDByReference(round); var roundref = new WinDef.DWORDByReference(round);
Dwm.INSTANCE.DwmSetWindowAttribute( Dwm.INSTANCE.DwmSetWindowAttribute(hwnd,
hwnd,
Dwm.DWMWA_WINDOW_CORNER_PREFERENCE, Dwm.DWMWA_WINDOW_CORNER_PREFERENCE,
roundref.getPointer(), roundref.getPointer(),
new WinDef.DWORD(WinDef.DWORD.SIZE) new WinDef.DWORD(WinDef.DWORD.SIZE)
); );
} }
public String getClassName() {
var user32 = User32Extra.INSTANCE;
char[] chars = new char[1024];
user32.GetClassName(hwnd, chars, 1024);
return Util.nullTerminatedCharArrayToString(chars);
}
public String getExecutableName() {
var user32 = User32Extra.INSTANCE;
var kernel32 = Kernel32.INSTANCE;
var handle = kernel32.OpenProcess(
WinNT.PROCESS_QUERY_LIMITED_INFORMATION,
false,
getProcessId()
);
char[] chars = new char[1024];
var len = new IntByReference();
len.setValue(1024);
kernel32.QueryFullProcessImageName(handle, 0, chars, len);
return Util.nullTerminatedCharArrayToString(chars);
}
public String getKey() {
return getExecutableName() + " $ " + getClassName();
}
private int getStyle() {
var user32 = User32Extra.INSTANCE;
return user32.GetWindowLong(hwnd, WinUser.GWL_STYLE);
}
private void setStyle(int style) { private void setStyle(int style) {
var user32 = User32Extra.INSTANCE; var user32 = User32Extra.INSTANCE;
user32.SetWindowLong(hwnd, WinUser.GWL_STYLE, style); user32.SetWindowLong(hwnd, WinUser.GWL_STYLE, style);
} }
private int getStyleEx() {
var user32 = User32Extra.INSTANCE;
return user32.GetWindowLong(hwnd, WinUser.GWL_EXSTYLE);
}
private void setStyleEx(int style) { private void setStyleEx(int style) {
var user32 = User32Extra.INSTANCE; var user32 = User32Extra.INSTANCE;
user32.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, style); user32.SetWindowLong(hwnd, WinUser.GWL_EXSTYLE, style);
} }
private boolean isTitleBarVisible() {
var tb = getTitleBarInfo();
return (tb.rgstate[0] & User32Extra.STATE_SYSTEM_INVISIBLE) == 0;
}
public String getTitle() {
var user32 = User32Extra.INSTANCE;
char[] chars = new char[1024];
user32.GetWindowText(hwnd, chars, 1024);
return Util.nullTerminatedCharArrayToString(chars);
}
private TITLEBARINFO getTitleBarInfo() {
var user32 = User32Extra.INSTANCE;
var tb = new TITLEBARINFO();
user32.GetTitleBarInfo(hwnd, tb);
return tb;
}
private int getProcessId() {
var user32 = User32Extra.INSTANCE;
var ref = new IntByReference();
user32.GetWindowThreadProcessId(hwnd, ref);
return ref.getValue();
}
public boolean isDwmCloaked() {
var user32 = User32Extra.INSTANCE;
var dwm = Dwm.INSTANCE;
var out = new IntByReference();
dwm.DwmGetWindowAttribute(
hwnd,
Dwm.DWMWA_CLOAKED,
out.getPointer(),
new WinDef.DWORD(WinDef.DWORD.SIZE)
);
var val = out.getValue();
return val != 0;
}
public boolean isClass(String str) {
return str.equals(getClassName());
}
public boolean isExecutableName(String str) {
return str.equals(getExecutableName());
}
public boolean isInAltTabList() {
var user32 = User32Extra.INSTANCE;
var walk = user32.GetAncestor(hwnd, WinUser.GA_ROOTOWNER);
WinDef.HWND test;
var window = new Window(hwnd);
if(walk == null) return false;
return walk.equals(hwnd) &&
user32.IsWindowVisible(hwnd) &&
window.getTitle().length() > 0 &&
!window.isToolWindow() &&
!window.isDwmCloaked() &&
!window.getClassName().equals("Progman");
}
public boolean isToolWindow() {
return (getStyleEx() & User32Extra.WS_EX_TOOLWINDOW) != 0;
}
public void move(Recti rectangle) {
var user32 = User32Extra.INSTANCE;
var dwm = Dwm.INSTANCE;
var pos = rectangle.getPos();
var size = rectangle.getSize();
var rect_with_shadow = new WinDef.RECT();
var rect_without_shadow = new WinDef.RECT();
var rect = new WinDef.RECT();
user32.GetWindowRect(hwnd, rect_with_shadow);
dwm.DwmGetWindowAttribute(
hwnd,
Dwm.DWMWA_EXTENDED_FRAME_BOUNDS,
rect_without_shadow.getPointer(),
new WinDef.DWORD(rect_without_shadow.size())
);
rect_without_shadow.read();
var left_shadow = rect_without_shadow.left - rect_with_shadow.left;
var right_shadow = rect_with_shadow.right - rect_without_shadow.right;
var top_shadow = rect_without_shadow.top - rect_with_shadow.top;
var bottom_shaddow = rect_with_shadow.bottom -
rect_without_shadow.bottom;
rect.left = pos.getX() - left_shadow;
rect.top = pos.getY() - top_shadow;
rect.right = pos.getX() + size.getX() + right_shadow;
rect.bottom = pos.getY() + size.getY() + bottom_shaddow;
//user32.AdjustWindowRect(rect, new WinDef.DWORD(WinUser
// .WS_OVERLAPPEDWINDOW), new WinDef.BOOL(false));
//var style = getStyle();
//var styleex = getStyleEx();
//style &= ~(User32Extra.WS_CAPTION | User32Extra.WS_MINIMIZEBOX |
// User32Extra.WS_SYSMENU);
//styleex &= ~(User32Extra.WS_EX_DLGMODALFRAME | User32Extra
// .WS_EX_CLIENTEDGE | User32Extra.WS_EX_STATICEDGE);
//style |= User32Extra.WS_POPUP;
//user32.AdjustWindowRectEx(rect, new WinDef.DWORD(style), new WinDef
// .BOOL(false), new WinDef.DWORD(styleex));
user32.MoveWindow(
hwnd,
rect.left,
rect.top,
rect.right - rect.left,
rect.bottom - rect.top,
true
);
//user32.MoveWindow(hwnd, pos.getX(), pos.getY(), size.getX(), size
// .getY(), true);
user32.SetWindowPos(
hwnd,
null,
0,
0,
0,
0,
WinUser.SWP_FRAMECHANGED |
WinUser.SWP_NOZORDER |
WinUser.SWP_NOOWNERZORDER |
WinUser.SWP_NOMOVE |
WinUser.SWP_NOSIZE |
WinUser.SWP_NOACTIVATE
);
}
@Override
public boolean equals(Object o) {
if(!(o instanceof Window)) {
return false;
}
return ((Window) o).hwnd.equals(this.hwnd);
}
} }