Working on menus
Build and Test / build (push) Has been cancelled

This commit is contained in:
2026-05-14 10:41:32 +02:00
parent 0a7da1a7a9
commit 367f37e6f8
9 changed files with 118 additions and 17 deletions
@@ -34,8 +34,6 @@ public class DiceOSAdapter extends ApplicationAdapter {
private int offsetY = 0; private int offsetY = 0;
private GraphicsContext gc; private GraphicsContext gc;
private BitmapFont font;
@Override @Override
public void create() { public void create() {
log.info("DiceOS starting..."); log.info("DiceOS starting...");
@@ -50,8 +48,6 @@ public class DiceOSAdapter extends ApplicationAdapter {
task.onStartup(); task.onStartup();
} }
font = resourceLoader.loadFont("system/font");
log.info("DiceOS started!"); log.info("DiceOS started!");
} }
@@ -67,7 +63,8 @@ public class DiceOSAdapter extends ApplicationAdapter {
cursorService.setScale(scaling); cursorService.setScale(scaling);
gc = new GraphicsContext(screenViewport.getCamera(), display.getBatch(), displayHeight, displayWidth, font); gc = new GraphicsContext(screenViewport.getCamera(), display.getBatch(), displayHeight, displayWidth,
DiceOS.getResourceLoader().getDefaultFont().getBitmapFont());
} }
@Override @Override
@@ -1,5 +1,6 @@
package be.seeseemelk.diceos.system; package be.seeseemelk.diceos.system;
import be.seeseemelk.diceos.system.toolkit.events.MouseClickEvent;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input; import com.badlogic.gdx.Input;
import com.badlogic.gdx.InputAdapter; import com.badlogic.gdx.InputAdapter;
@@ -7,6 +8,8 @@ import io.avaje.inject.Component;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import java.awt.event.KeyEvent;
@Slf4j @Slf4j
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
@@ -24,6 +27,19 @@ public class InputService implements OnStartup {
} else if (keycode == Input.Keys.ESCAPE) { } else if (keycode == Input.Keys.ESCAPE) {
Gdx.app.exit(); Gdx.app.exit();
} }
//DiceOS.getWindowService().onEvent(new KeyEvent(keycode));
return false;
}
@Override
public boolean touchUp(int screenX, int screenY, int pointer, int button) {
DiceOS.getWindowService().onEvent(new MouseClickEvent(screenX, screenY, MouseClickEvent.Button.LEFT, MouseClickEvent.Action.RELEASED));
return false;
}
@Override
public boolean touchDown(int screenX, int screenY, int pointer, int button) {
DiceOS.getWindowService().onEvent(new MouseClickEvent(screenX, screenY, MouseClickEvent.Button.LEFT, MouseClickEvent.Action.PRESSED));
return false; return false;
} }
}); });
@@ -1,5 +1,6 @@
package be.seeseemelk.diceos.system; package be.seeseemelk.diceos.system;
import be.seeseemelk.diceos.system.font.Font;
import be.seeseemelk.diceos.system.font.FontLoader; import be.seeseemelk.diceos.system.font.FontLoader;
import be.seeseemelk.diceos.system.font.FontMetadata; import be.seeseemelk.diceos.system.font.FontMetadata;
import be.seeseemelk.diceos.system.gfx.NinePatchLoader; import be.seeseemelk.diceos.system.gfx.NinePatchLoader;
@@ -18,6 +19,14 @@ import tools.jackson.dataformat.toml.TomlFactory;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
/**
* A utility class responsible for loading and caching graphical and textual assets used in the application.
* It manages various types of resources including pixmaps, textures, nine-patches, and fonts, ensuring that
* assets are loaded only once and subsequently reused to optimize performance.
*
* The class supports loading assets from specified file paths and caches them in memory. It implements a
* lazy-loading mechanism to defer loading until a resource is requested.
*/
@Slf4j @Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@Component @Component
@@ -25,7 +34,7 @@ public class ResourceLoader {
private final Map<String, Pixmap> pixmaps = new HashMap<>(); private final Map<String, Pixmap> pixmaps = new HashMap<>();
private final Map<String, Texture> textures = new HashMap<>(); private final Map<String, Texture> textures = new HashMap<>();
private final Map<String, NinePatch> ninePatches = new HashMap<>(); private final Map<String, NinePatch> ninePatches = new HashMap<>();
private final Map<String, BitmapFont> fonts = new HashMap<>(); private final Map<String, Font> fonts = new HashMap<>();
private final ObjectMapper mapper = new ObjectMapper(new TomlFactory()); private final ObjectMapper mapper = new ObjectMapper(new TomlFactory());
public Pixmap loadPixmap(String path) { public Pixmap loadPixmap(String path) {
@@ -36,6 +45,13 @@ public class ResourceLoader {
return textures.computeIfAbsent(path, p -> new Texture(Gdx.files.internal(p))); return textures.computeIfAbsent(path, p -> new Texture(Gdx.files.internal(p)));
} }
/**
* Loads and retrieves a {@link NinePatch} object for the given image path. The method caches loaded
* {@link NinePatch} instances to avoid redundant processing of the same asset.
*
* @param path the file path of the image to load as a 9-patch
* @return the loaded {@link NinePatch} instance corresponding to the specified image path
*/
public NinePatch loadNinePatch(String path) { public NinePatch loadNinePatch(String path) {
return ninePatches.computeIfAbsent(path, p -> { return ninePatches.computeIfAbsent(path, p -> {
var pixmap = loadPixmap(p); var pixmap = loadPixmap(p);
@@ -44,16 +60,28 @@ public class ResourceLoader {
}); });
} }
public BitmapFont loadFont(String path) { /**
* Loads and retrieves a {@link Font} object for the given file path.
* The method caches loaded {@link Font} instances to avoid redundant
* processing of the same asset.
*
* @param path the file path of the font to load
* @return the loaded {@link Font} instance corresponding to the specified file path
*/
public Font loadFont(String path) {
return fonts.computeIfAbsent(path, this::loadBitmapfont); return fonts.computeIfAbsent(path, this::loadBitmapfont);
} }
private BitmapFont loadBitmapfont(String path) { public Font getDefaultFont() {
return loadFont("system/font");
}
private Font loadBitmapfont(String path) {
log.info("Loading bitmap font from {}", path); log.info("Loading bitmap font from {}", path);
var metadataString = Gdx.files.internal(path + ".toml").readString(); var metadataString = Gdx.files.internal(path + ".toml").readString();
var metadata = mapper.readValue(metadataString, FontMetadata.class); var metadata = mapper.readValue(metadataString, FontMetadata.class);
@Cleanup("dispose") var pixmap = loadPixmap(metadata.getGeneral().getSource()); @Cleanup("dispose") var pixmap = loadPixmap(metadata.getGeneral().getSource());
return FontLoader.loadBitmapfont(pixmap, metadata); return new Font(FontLoader.loadBitmapfont(pixmap, metadata));
} }
} }
@@ -2,14 +2,18 @@ package be.seeseemelk.diceos.system;
import be.seeseemelk.diceos.system.gfx.GraphicsContext; import be.seeseemelk.diceos.system.gfx.GraphicsContext;
import be.seeseemelk.diceos.system.toolkit.Window; import be.seeseemelk.diceos.system.toolkit.Window;
import be.seeseemelk.diceos.system.toolkit.events.Event;
import be.seeseemelk.diceos.system.toolkit.events.MouseClickEvent;
import be.seeseemelk.diceos.system.toolkit.menu.Menu; import be.seeseemelk.diceos.system.toolkit.menu.Menu;
import com.badlogic.gdx.graphics.g2d.NinePatch; import com.badlogic.gdx.graphics.g2d.NinePatch;
import io.avaje.inject.Component; import io.avaje.inject.Component;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@Slf4j
@RequiredArgsConstructor @RequiredArgsConstructor
@Component @Component
public class WindowService implements OnStartup { public class WindowService implements OnStartup {
@@ -65,11 +69,24 @@ public class WindowService implements OnStartup {
// Render menubar items // Render menubar items
gc.save(); gc.save();
gc.translate(5, 0); gc.translate(10, 0);
for (var submenu : menu.getItems()) { for (var submenu : menu.getItems()) {
submenu.paint(gc); submenu.paint(gc);
gc.translate(submenu.getWidth(), 0); gc.translate(submenu.getWidth() + 4, 0);
} }
gc.restore(); gc.restore();
} }
void onEvent(Event event) {
switch (event) {
case MouseClickEvent e -> onMouseClickEvent(e);
default -> {}
}
}
private void onMouseClickEvent(MouseClickEvent event) {
if (event.getY() <= 14) {
log.info("Clicking on menubar");
}
}
} }
@@ -0,0 +1,26 @@
package be.seeseemelk.diceos.system.font;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
/**
* Represents a font used for rendering text, providing utilities
* for measuring text dimensions.
*/
@RequiredArgsConstructor
public class Font {
@Getter
private final BitmapFont bitmapFont;
/**
* Calculates the width of the given text when rendered with the current font.
* @param text The text to measure.
* @return The width of the text in pixels.
*/
public int getTextWidth(String text) {
var layout = new com.badlogic.gdx.graphics.g2d.GlyphLayout();
layout.setText(bitmapFont, text);
return (int) layout.width;
}
}
@@ -195,7 +195,7 @@ public class FontLoader {
if (!isBlack) { if (!isBlack) {
currentTiming.glyphEnd = x; currentTiming.glyphEnd = x;
state = State.WAITING_FOR_GLYPH_WIDTHS; state = State.WAITING_FOR_GLYPH_WIDTHS;
log.info("Found glyph width: {} (from {} to {})", currentTiming.getGlyphWidth(), currentTiming.glyphStart, currentTiming.glyphEnd); //log.info("Found glyph width: {} (from {} to {})", currentTiming.getGlyphWidth(), currentTiming.glyphStart, currentTiming.glyphEnd);
} }
} }
} }
@@ -16,6 +16,13 @@ public class GeneralSection {
*/ */
private String order; private String order;
// @gemini implement
private int lineHeight; private int lineHeight;
public int getLineHeight() {
return lineHeight;
}
public void setLineHeight(int lineHeight) {
this.lineHeight = lineHeight;
}
} }
@@ -17,9 +17,17 @@ public class MouseClickEvent extends MouseEvent {
*/ */
private final Button button; private final Button button;
/**
* The action performed in the mouse click event, indicating whether the mouse button
* was pressed or released.
*/
private final Action action;
public enum Button { public enum Button {
LEFT, LEFT, RIGHT,
RIGHT, }
;
public enum Action {
PRESSED, RELEASED
} }
} }
@@ -1,6 +1,7 @@
package be.seeseemelk.diceos.system.toolkit.menu; package be.seeseemelk.diceos.system.toolkit.menu;
import be.seeseemelk.diceos.system.DiceOS; import be.seeseemelk.diceos.system.DiceOS;
import be.seeseemelk.diceos.system.font.Font;
import be.seeseemelk.diceos.system.gfx.GraphicsContext; import be.seeseemelk.diceos.system.gfx.GraphicsContext;
import lombok.Getter; import lombok.Getter;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
@@ -13,6 +14,7 @@ import java.util.List;
public class Menu implements MenuItem { public class Menu implements MenuItem {
private final String title; private final String title;
private final List<MenuItem> items = new ArrayList<>(); private final List<MenuItem> items = new ArrayList<>();
private final Font font = DiceOS.getResourceLoader().getDefaultFont();
public Menu add(MenuItem item) { public Menu add(MenuItem item) {
items.add(item); items.add(item);
@@ -26,7 +28,7 @@ public class Menu implements MenuItem {
@Override @Override
public int getWidth() { public int getWidth() {
return items.stream().mapToInt(MenuItem::getWidth).max().orElse(0); return font.getTextWidth(title);
} }
@Override @Override