diff --git a/assets/README.md b/assets/README.md new file mode 100644 index 0000000..a6efc6e --- /dev/null +++ b/assets/README.md @@ -0,0 +1,4 @@ +# Assets + +* [Atlas](atlas.png): By [Kapendev](https://kapendev.itch.io), CC0 +* [Monogram](monogram.png): By [DATAGOBLIN](https://datagoblin.itch.io/monogram), CC0 diff --git a/examples/atlas.png b/assets/atlas.png similarity index 100% rename from examples/atlas.png rename to assets/atlas.png diff --git a/assets/monogram.png b/assets/monogram.png new file mode 100644 index 0000000..7930662 Binary files /dev/null and b/assets/monogram.png differ diff --git a/dub.json b/dub.json index 3033876..139f3bb 100644 --- a/dub.json +++ b/dub.json @@ -9,6 +9,9 @@ "dependencies": { "joka": "*" }, + "stringImportPaths": [ + "assets" + ], "subPackages" : [ "setup", "web" diff --git a/examples/README.md b/examples/README.md index 054fc8c..1826df2 100644 --- a/examples/README.md +++ b/examples/README.md @@ -4,7 +4,7 @@ This folder provides example projects to help you get started. > [!NOTE] > If an example uses textures, -> be sure to download the [atlas.png](atlas.png) file and place it in the project's assets folder. +> be sure to download the [atlas.png](../assets/atlas.png) file and place it in the project's assets folder. ## Categories diff --git a/examples/ui/handle.d b/examples/ui/handle.d index 4a22312..b2bcc84 100644 --- a/examples/ui/handle.d +++ b/examples/ui/handle.d @@ -14,7 +14,7 @@ bool update(float dt) { setUiFocus(0); setUiStartPoint(Vec2(8)); // Toggle the limit of the drag handle. - if (uiButton(Vec2(80, 30), "Limit: {}".format(handleOptions.dragLimit))) { + if (uiButton(Vec2(100, 30), "Limit: {}".format(handleOptions.dragLimit))) { if (handleOptions.dragLimit) handleOptions.dragLimit = UiDragLimit.none; else handleOptions.dragLimit = UiDragLimit.viewport; } diff --git a/source/parin/engine.d b/source/parin/engine.d index a28d1ba..82143cc 100644 --- a/source/parin/engine.d +++ b/source/parin/engine.d @@ -169,6 +169,7 @@ enum Mouse : ubyte { /// A type representing a limited set of gamepad buttons. enum Gamepad : ubyte { + none = rl.GAMEPAD_BUTTON_UNKNOWN, /// Not a button. left = rl.GAMEPAD_BUTTON_LEFT_FACE_LEFT, /// The left button. right = rl.GAMEPAD_BUTTON_LEFT_FACE_RIGHT, /// The right button. up = rl.GAMEPAD_BUTTON_LEFT_FACE_UP, /// The up button. @@ -973,6 +974,7 @@ struct EngineState { EngineResources resources; EngineFullscreenState fullscreenState; + Font font; Color borderColor; Sz tickCount; LStr assetsPath; @@ -995,6 +997,7 @@ struct EngineState { // } viewport.free(); resources.free(); + font.free(); tempText.free(); assetsPath.free(); this = EngineState(); @@ -1106,17 +1109,16 @@ rl.Camera2D toRl(Camera camera, Viewport viewport = Viewport()) { /// Converts an ASCII bitmap font texture into a font. /// The texture will be freed when the font is freed. // NOTE: The number of items allocated for this font is calculated as: (font width / tile width) * (font height / tile height) +// NOTE: This function assumes that raylib uses malloc. @trusted Font toFont(Texture texture, int tileWidth, int tileHeight) { if (texture.isEmpty || tileWidth <= 0|| tileHeight <= 0) return Font(); auto result = Font(); result.lineSpacing = tileHeight; - auto rowCount = texture.height / tileHeight; auto colCount = texture.width / tileWidth; auto maxCount = rowCount * colCount; - result.data.baseSize = tileHeight; result.data.glyphCount = maxCount; result.data.glyphPadding = 0; @@ -1291,7 +1293,7 @@ TextureId loadTexture(IStr path, Sz tag = 0) { Result!Font loadRawFont(IStr path, int size, int runeSpacing, int lineSpacing, IStr32 runes = "") { auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path; auto value = rl.LoadFontEx(targetPath.toCStr().getOr(), size, runes == "" ? null : cast(int*) runes.ptr, cast(int) runes.length).toParin(); - if (value.data.texture.id == engineFont.data.texture.id) { + if (value.data.texture.id == rl.GetFontDefault().texture.id) { value = Font(); } value.runeSpacing = runeSpacing; @@ -1420,9 +1422,7 @@ void openUrl(IStr url = "https://github.com/Kapendev/parin") { /// You should avoid calling this function manually. @trusted void openWindow(int width, int height, IStr appPath, IStr title = "Parin") { - if (rl.IsWindowReady) { - return; - } + if (rl.IsWindowReady) return; rl.SetConfigFlags(rl.FLAG_WINDOW_RESIZABLE | rl.FLAG_VSYNC_HINT); rl.SetTraceLogLevel(rl.LOG_ERROR); rl.InitWindow(width, height, title.toCStr().getOr()); @@ -1438,6 +1438,12 @@ void openWindow(int width, int height, IStr appPath, IStr title = "Parin") { engineState.tempText.reserve(8192); // NOTE: This line is used for fixing an alpha bug with render textures. rl.rlSetBlendFactorsSeparate(0x0302, 0x0303, 1, 0x0303, 0x8006, 0x8006); + // Load default engine assets. + auto monogramData = cast(const(ubyte)[]) import("monogram.png"); + auto monogramImage = rl.LoadImageFromMemory(".png", monogramData.ptr, cast(int) monogramData.length); + auto monogramTexture = rl.LoadTextureFromImage(monogramImage); + engineState.font = monogramTexture.toParin().toFont(6, 12); + rl.UnloadImage(monogramImage); } /// Updates the window every frame with the given function. @@ -1668,10 +1674,7 @@ void setBorderColor(Color value) { /// Returns the default engine font. This font should not be freed. @trusted Font engineFont() { - auto result = rl.GetFontDefault().toParin(); - result.runeSpacing = 1; - result.lineSpacing = 10; - return result; + return engineState.font; } /// Returns the default filter mode for textures. diff --git a/source/parin/ui.d b/source/parin/ui.d index 3706e15..4316cc6 100644 --- a/source/parin/ui.d +++ b/source/parin/ui.d @@ -358,10 +358,10 @@ void drawUiText(Vec2 size, IStr text, Vec2 point, UiOptions options = UiOptions( case Alignment.center: break; case Alignment.right: textPoint.x -= options.alignmentOffset; break; } - auto textOptions = DrawOptions(options.alignment, cast(int) size.x.round()); + auto textOptions = DrawOptions(options.alignment, cast(int) size.x.floor()); textOptions.hook = Hook.center; if (options.isDisabled) textOptions.color.a = defaultUiAlpha; - drawText(font, text, textPoint.round(), textOptions); + drawText(font, text, textPoint.floor(), textOptions); } void uiText(Vec2 size, IStr text, UiOptions options = UiOptions()) { @@ -581,7 +581,7 @@ void drawUiTextField(Vec2 size, Str text, Vec2 point, UiOptions options = UiOpti if (!options.isDisabled) { auto rect = Rect(textPoint.x + textSize.x + 1.0f, textPoint.y, font.size * 0.05f, font.size).area(Hook.center); rect.subTopBottom(rect.size.y * 0.1f); - rect = rect.round(); + rect = rect.floor(); if (rect.size.x == 0.0f) rect.size.x = 1.0f; drawRect(rect, defaultUiDisabledColor); }