mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-27 21:49:57 +03:00
Font and tile map fix.
This commit is contained in:
parent
1ee5d1a9aa
commit
0bfc42f18d
2 changed files with 154 additions and 25 deletions
|
@ -206,6 +206,7 @@ struct DrawOptions {
|
||||||
/// Represents an identifier for a managed resource.
|
/// Represents an identifier for a managed resource.
|
||||||
struct TextId {
|
struct TextId {
|
||||||
GenerationalIndex data;
|
GenerationalIndex data;
|
||||||
|
|
||||||
alias data this;
|
alias data this;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -295,6 +296,7 @@ struct Texture {
|
||||||
/// Represents an identifier for a managed resource.
|
/// Represents an identifier for a managed resource.
|
||||||
struct TextureId {
|
struct TextureId {
|
||||||
GenerationalIndex data;
|
GenerationalIndex data;
|
||||||
|
|
||||||
alias data this;
|
alias data this;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -386,6 +388,7 @@ struct Font {
|
||||||
/// Represents an identifier for a managed resource.
|
/// Represents an identifier for a managed resource.
|
||||||
struct FontId {
|
struct FontId {
|
||||||
GenerationalIndex data;
|
GenerationalIndex data;
|
||||||
|
|
||||||
alias data this;
|
alias data this;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -528,6 +531,7 @@ struct Sound {
|
||||||
/// Represents an identifier for a managed resource.
|
/// Represents an identifier for a managed resource.
|
||||||
struct SoundId {
|
struct SoundId {
|
||||||
GenerationalIndex data;
|
GenerationalIndex data;
|
||||||
|
|
||||||
alias data this;
|
alias data this;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -811,6 +815,7 @@ struct EngineFlags {
|
||||||
bool isPixelSnapped;
|
bool isPixelSnapped;
|
||||||
bool isPixelPerfect;
|
bool isPixelPerfect;
|
||||||
bool isCursorVisible;
|
bool isCursorVisible;
|
||||||
|
bool canUseAssetsPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct EngineFullscreenState {
|
struct EngineFullscreenState {
|
||||||
|
@ -902,6 +907,7 @@ struct EngineViewport {
|
||||||
Viewport data;
|
Viewport data;
|
||||||
int targetWidth;
|
int targetWidth;
|
||||||
int targetHeight;
|
int targetHeight;
|
||||||
|
|
||||||
alias data this;
|
alias data this;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
@ -931,16 +937,16 @@ struct EngineState {
|
||||||
EngineResources resources;
|
EngineResources resources;
|
||||||
EngineFullscreenState fullscreenState;
|
EngineFullscreenState fullscreenState;
|
||||||
|
|
||||||
|
Color borderColor;
|
||||||
|
Sz tickCount;
|
||||||
LStr assetsPath;
|
LStr assetsPath;
|
||||||
LStr tempText;
|
LStr tempText;
|
||||||
|
|
||||||
Camera currentCamera;
|
Camera currentCamera;
|
||||||
Viewport currentViewport;
|
Viewport currentViewport;
|
||||||
|
|
||||||
Color borderColor;
|
|
||||||
Filter defaultFilter;
|
Filter defaultFilter;
|
||||||
Wrap defaultWrap;
|
Wrap defaultWrap;
|
||||||
Sz tickCount;
|
rl.FilePathList filePathListBuffer;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
|
||||||
|
@ -1114,11 +1120,30 @@ IStr toAssetsPath(IStr path) {
|
||||||
return pathConcat(assetsPath, path).pathFormat();
|
return pathConcat(assetsPath, path).pathFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool canUseAssetsPath() {
|
||||||
|
return engineState.flags.canUseAssetsPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCanUseAssetsPath(bool value) {
|
||||||
|
engineState.flags.canUseAssetsPath = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
@trusted
|
||||||
|
IStr[] droppedFilePaths() {
|
||||||
|
static IStr[128] buffer;
|
||||||
|
|
||||||
|
foreach (i; 0 .. engineState.filePathListBuffer.count) {
|
||||||
|
buffer[i] = engineState.filePathListBuffer.paths[i].toStr();
|
||||||
|
}
|
||||||
|
return buffer[0 .. engineState.filePathListBuffer.count];
|
||||||
|
}
|
||||||
|
|
||||||
/// Loads a text file from the assets folder.
|
/// Loads a text file from the assets folder.
|
||||||
/// The resource remains valid until this function is called again.
|
/// The resource remains valid until this function is called again.
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
Result!IStr loadTempText(IStr path) {
|
Result!IStr loadTempText(IStr path) {
|
||||||
auto fault = readTextIntoBuffer(path.toAssetsPath(), engineState.tempText);
|
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||||
|
auto fault = readTextIntoBuffer(targetPath, engineState.tempText);
|
||||||
return Result!IStr(engineState.tempText.items, fault);
|
return Result!IStr(engineState.tempText.items, fault);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,7 +1151,8 @@ Result!IStr loadTempText(IStr path) {
|
||||||
/// The resource must be manually freed.
|
/// The resource must be manually freed.
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
Result!LStr loadRawText(IStr path) {
|
Result!LStr loadRawText(IStr path) {
|
||||||
return readText(path.toAssetsPath());
|
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||||
|
return readText(targetPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Loads a text file from the assets folder.
|
/// Loads a text file from the assets folder.
|
||||||
|
@ -1157,7 +1183,8 @@ TextId loadText(IStr path, Sz tag = 0) {
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
@trusted
|
@trusted
|
||||||
Result!Texture loadRawTexture(IStr path) {
|
Result!Texture loadRawTexture(IStr path) {
|
||||||
auto value = rl.LoadTexture(path.toAssetsPath().toCStr().getOr()).toParin();
|
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||||
|
auto value = rl.LoadTexture(targetPath.toCStr().getOr()).toParin();
|
||||||
value.setFilter(engineState.defaultFilter);
|
value.setFilter(engineState.defaultFilter);
|
||||||
value.setWrap(engineState.defaultWrap);
|
value.setWrap(engineState.defaultWrap);
|
||||||
return Result!Texture(value, value.isEmpty.toFault(Fault.cantFind));
|
return Result!Texture(value, value.isEmpty.toFault(Fault.cantFind));
|
||||||
|
@ -1191,7 +1218,8 @@ TextureId loadTexture(IStr path, Sz tag = 0) {
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
@trusted
|
@trusted
|
||||||
Result!Font loadRawFont(IStr path, int size, int runeSpacing, int lineSpacing, IStr32 runes = "") {
|
Result!Font loadRawFont(IStr path, int size, int runeSpacing, int lineSpacing, IStr32 runes = "") {
|
||||||
auto value = rl.LoadFontEx(path.toAssetsPath().toCStr().getOr(), size, runes == "" ? null : cast(int*) runes.ptr, cast(int) runes.length).toParin();
|
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 == engineFont.data.texture.id) {
|
||||||
value = Font();
|
value = Font();
|
||||||
}
|
}
|
||||||
|
@ -1230,11 +1258,12 @@ FontId loadFont(IStr path, int size, int runeSpacing, int lineSpacing, IStr32 ru
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
@trusted
|
@trusted
|
||||||
Result!Sound loadRawSound(IStr path, float volume, float pitch) {
|
Result!Sound loadRawSound(IStr path, float volume, float pitch) {
|
||||||
|
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||||
auto value = Sound();
|
auto value = Sound();
|
||||||
if (path.endsWith(".wav")) {
|
if (path.endsWith(".wav")) {
|
||||||
value.data = rl.LoadSound(path.toAssetsPath().toCStr().getOr());
|
value.data = rl.LoadSound(targetPath.toCStr().getOr());
|
||||||
} else {
|
} else {
|
||||||
value.data = rl.LoadMusicStream(path.toAssetsPath().toCStr().getOr());
|
value.data = rl.LoadMusicStream(targetPath.toCStr().getOr());
|
||||||
}
|
}
|
||||||
value.setVolume(volume);
|
value.setVolume(volume);
|
||||||
value.setPitch(pitch);
|
value.setPitch(pitch);
|
||||||
|
@ -1267,7 +1296,8 @@ SoundId loadSound(IStr path, float volume, float pitch, Sz tag = 0) {
|
||||||
/// Saves a text file to the assets folder.
|
/// Saves a text file to the assets folder.
|
||||||
/// Supports both forward slashes and backslashes in file paths.
|
/// Supports both forward slashes and backslashes in file paths.
|
||||||
Fault saveText(IStr path, IStr text) {
|
Fault saveText(IStr path, IStr text) {
|
||||||
return writeText(path.toAssetsPath(), text);
|
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||||
|
return writeText(targetPath, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Frees all managed resources associated with the given tag, or all if no tag is specified.
|
/// Frees all managed resources associated with the given tag, or all if no tag is specified.
|
||||||
|
@ -1292,6 +1322,7 @@ void openWindow(int width, int height, IStr appPath, IStr title = "Parin") {
|
||||||
engineState.viewport.color = gray;
|
engineState.viewport.color = gray;
|
||||||
engineState.fullscreenState.lastWindowWidth = width;
|
engineState.fullscreenState.lastWindowWidth = width;
|
||||||
engineState.fullscreenState.lastWindowHeight = height;
|
engineState.fullscreenState.lastWindowHeight = height;
|
||||||
|
engineState.flags.canUseAssetsPath = true;
|
||||||
engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets"));
|
engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets"));
|
||||||
engineState.tempText.reserve(8192);
|
engineState.tempText.reserve(8192);
|
||||||
// NOTE: This line is used for fixing an alpha bug with render textures.
|
// NOTE: This line is used for fixing an alpha bug with render textures.
|
||||||
|
@ -1316,9 +1347,16 @@ void updateWindow(bool function(float dt) updateFunc) {
|
||||||
rl.ClearBackground(engineState.viewport.color.toRl());
|
rl.ClearBackground(engineState.viewport.color.toRl());
|
||||||
|
|
||||||
// The main loop.
|
// The main loop.
|
||||||
|
if (rl.IsFileDropped) {
|
||||||
|
engineState.filePathListBuffer = rl.LoadDroppedFiles();
|
||||||
|
}
|
||||||
auto dt = deltaTime;
|
auto dt = deltaTime;
|
||||||
auto result = _updateFunc(dt);
|
auto result = _updateFunc(dt);
|
||||||
engineState.tickCount = (engineState.tickCount + 1) % engineState.tickCount.max;
|
engineState.tickCount = (engineState.tickCount + 1) % engineState.tickCount.max;
|
||||||
|
if (rl.IsFileDropped) {
|
||||||
|
rl.UnloadDroppedFiles(engineState.filePathListBuffer);
|
||||||
|
engineState.filePathListBuffer = rl.FilePathList();
|
||||||
|
}
|
||||||
|
|
||||||
// End drawing.
|
// End drawing.
|
||||||
if (isResolutionLocked) {
|
if (isResolutionLocked) {
|
||||||
|
@ -1780,7 +1818,15 @@ bool isDown(char key) {
|
||||||
/// Returns true if the specified key is currently pressed.
|
/// Returns true if the specified key is currently pressed.
|
||||||
@trusted
|
@trusted
|
||||||
bool isDown(Keyboard key) {
|
bool isDown(Keyboard key) {
|
||||||
return rl.IsKeyDown(key);
|
if (key == Keyboard.shift) {
|
||||||
|
return rl.IsKeyDown(key) || rl.IsKeyDown(rl.KEY_RIGHT_SHIFT);
|
||||||
|
} else if (key == Keyboard.ctrl) {
|
||||||
|
return rl.IsKeyDown(key) || rl.IsKeyDown(rl.KEY_RIGHT_CONTROL);
|
||||||
|
} else if (key == Keyboard.alt) {
|
||||||
|
return rl.IsKeyDown(key) || rl.IsKeyDown(rl.KEY_RIGHT_ALT);
|
||||||
|
} else {
|
||||||
|
return rl.IsKeyDown(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the specified key is currently pressed.
|
/// Returns true if the specified key is currently pressed.
|
||||||
|
@ -1804,7 +1850,15 @@ bool isPressed(char key) {
|
||||||
/// Returns true if the specified key was pressed.
|
/// Returns true if the specified key was pressed.
|
||||||
@trusted
|
@trusted
|
||||||
bool isPressed(Keyboard key) {
|
bool isPressed(Keyboard key) {
|
||||||
return rl.IsKeyPressed(key);
|
if (key == Keyboard.shift) {
|
||||||
|
return rl.IsKeyPressed(key) || rl.IsKeyPressed(rl.KEY_RIGHT_SHIFT);
|
||||||
|
} else if (key == Keyboard.ctrl) {
|
||||||
|
return rl.IsKeyPressed(key) || rl.IsKeyPressed(rl.KEY_RIGHT_CONTROL);
|
||||||
|
} else if (key == Keyboard.alt) {
|
||||||
|
return rl.IsKeyPressed(key) || rl.IsKeyPressed(rl.KEY_RIGHT_ALT);
|
||||||
|
} else {
|
||||||
|
return rl.IsKeyPressed(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the specified key was pressed.
|
/// Returns true if the specified key was pressed.
|
||||||
|
@ -1828,7 +1882,15 @@ bool isReleased(char key) {
|
||||||
/// Returns true if the specified key was released.
|
/// Returns true if the specified key was released.
|
||||||
@trusted
|
@trusted
|
||||||
bool isReleased(Keyboard key) {
|
bool isReleased(Keyboard key) {
|
||||||
return rl.IsKeyReleased(key);
|
if (key == Keyboard.shift) {
|
||||||
|
return rl.IsKeyReleased(key) || rl.IsKeyReleased(rl.KEY_RIGHT_SHIFT);
|
||||||
|
} else if (key == Keyboard.ctrl) {
|
||||||
|
return rl.IsKeyReleased(key) || rl.IsKeyReleased(rl.KEY_RIGHT_CONTROL);
|
||||||
|
} else if (key == Keyboard.alt) {
|
||||||
|
return rl.IsKeyReleased(key) || rl.IsKeyReleased(rl.KEY_RIGHT_ALT);
|
||||||
|
} else {
|
||||||
|
return rl.IsKeyReleased(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the specified key was released.
|
/// Returns true if the specified key was released.
|
||||||
|
@ -2094,11 +2156,7 @@ void drawRune(Font font, dchar rune, Vec2 position, DrawOptions options = DrawOp
|
||||||
}
|
}
|
||||||
rl.rlRotatef(options.rotation, 0.0f, 0.0f, 1.0f);
|
rl.rlRotatef(options.rotation, 0.0f, 0.0f, 1.0f);
|
||||||
rl.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
rl.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
||||||
if (isPixelSnapped || isPixelPerfect) {
|
rl.rlTranslatef(-origin.x.floor(), -origin.y.floor(), 0.0f);
|
||||||
rl.rlTranslatef(-origin.x.floor(), -origin.y.floor(), 0.0f);
|
|
||||||
} else {
|
|
||||||
rl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
|
||||||
}
|
|
||||||
rl.DrawTextCodepoint(font.data, rune, rl.Vector2(0.0f, 0.0f), font.size, options.color.toRl());
|
rl.DrawTextCodepoint(font.data, rune, rl.Vector2(0.0f, 0.0f), font.size, options.color.toRl());
|
||||||
rl.rlPopMatrix();
|
rl.rlPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -2122,11 +2180,7 @@ void drawText(Font font, IStr text, Vec2 position, DrawOptions options = DrawOpt
|
||||||
}
|
}
|
||||||
rl.rlRotatef(options.rotation, 0.0f, 0.0f, 1.0f);
|
rl.rlRotatef(options.rotation, 0.0f, 0.0f, 1.0f);
|
||||||
rl.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
rl.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
||||||
if (isPixelSnapped || isPixelPerfect) {
|
rl.rlTranslatef(floor(-origin.x), floor(-origin.y), 0.0f);
|
||||||
rl.rlTranslatef(floor(-origin.x), floor(-origin.y), 0.0f);
|
|
||||||
} else {
|
|
||||||
rl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
|
||||||
}
|
|
||||||
auto textOffsetY = 0.0f; // Offset between lines (on linebreak '\n').
|
auto textOffsetY = 0.0f; // Offset between lines (on linebreak '\n').
|
||||||
auto textOffsetX = 0.0f; // Offset X to next character to draw.
|
auto textOffsetX = 0.0f; // Offset X to next character to draw.
|
||||||
auto i = 0;
|
auto i = 0;
|
||||||
|
|
|
@ -71,7 +71,9 @@ struct TileMap {
|
||||||
int tileHeight = 16;
|
int tileHeight = 16;
|
||||||
Vec2 position;
|
Vec2 position;
|
||||||
|
|
||||||
alias data this;
|
enum maxRowCount = data.maxRowCount;
|
||||||
|
enum maxColCount = data.maxColCount;
|
||||||
|
enum maxCapacity = data.maxCapacity;
|
||||||
|
|
||||||
@safe @nogc nothrow:
|
@safe @nogc nothrow:
|
||||||
|
|
||||||
|
@ -84,6 +86,79 @@ struct TileMap {
|
||||||
this.data.fill(-1);
|
this.data.fill(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ref short opIndex(Sz row, Sz col) {
|
||||||
|
if (!has(row, col)) {
|
||||||
|
assert(0, "Tile `[{}, {}]` does not exist.".format(row, col));
|
||||||
|
}
|
||||||
|
return data[row, col];
|
||||||
|
}
|
||||||
|
|
||||||
|
ref short opIndex(IVec2 position) {
|
||||||
|
return opIndex(position.y, position.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void opIndexAssign(short rhs, Sz row, Sz col) {
|
||||||
|
if (!has(row, col)) {
|
||||||
|
assert(0, "Tile `[{}, {}]` does not exist.".format(row, col));
|
||||||
|
}
|
||||||
|
data[row, col] = rhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void opIndexAssign(short rhs, IVec2 position) {
|
||||||
|
return opIndexAssign(rhs, position.y, position.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
void opIndexOpAssign(IStr op)(T rhs, Sz row, Sz col) {
|
||||||
|
if (!has(row, col)) {
|
||||||
|
assert(0, "Tile `[{}, {}]` does not exist.".format(row, col));
|
||||||
|
}
|
||||||
|
mixin("tiles[colCount * row + col]", op, "= rhs;");
|
||||||
|
}
|
||||||
|
|
||||||
|
void opIndexOpAssign(IStr op)(T rhs, IVec2 position) {
|
||||||
|
return opIndexOpAssign!(op)(rhs, position.y, position.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
Sz opDollar(Sz dim)() {
|
||||||
|
static if (dim == 0) {
|
||||||
|
return rowCount;
|
||||||
|
} else static if (dim == 1) {
|
||||||
|
return colCount;
|
||||||
|
} else {
|
||||||
|
assert(0, "WTF!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Sz rowCount() {
|
||||||
|
return data.length == 0 ? 0 : softMaxRowCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
Sz colCount() {
|
||||||
|
return data.length == 0 ? 0 : softMaxColCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmpty() {
|
||||||
|
return data.isEmpty;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has(Sz row, Sz col) {
|
||||||
|
return row < softMaxRowCount && col < softMaxColCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool has(IVec2 position) {
|
||||||
|
return has(position.y, position.x);
|
||||||
|
}
|
||||||
|
|
||||||
|
@trusted
|
||||||
|
void fill(short value) {
|
||||||
|
data.fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@trusted
|
||||||
|
void free() {
|
||||||
|
data.free();
|
||||||
|
}
|
||||||
|
|
||||||
int width() {
|
int width() {
|
||||||
return cast(int) (softMaxColCount * tileWidth);
|
return cast(int) (softMaxColCount * tileWidth);
|
||||||
}
|
}
|
||||||
|
@ -189,7 +264,7 @@ struct TileMap {
|
||||||
|
|
||||||
void popFront() {
|
void popFront() {
|
||||||
position.x += 1;
|
position.x += 1;
|
||||||
if (position.x >= TileMap.maxColCount) {
|
if (position.x >= maxColCount) {
|
||||||
position.x = first.x;
|
position.x = first.x;
|
||||||
position.y += 1;
|
position.y += 1;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue