mirror of
https://github.com/Kapendev/parin.git
synced 2025-04-26 04:59:54 +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.
|
||||
struct TextId {
|
||||
GenerationalIndex data;
|
||||
|
||||
alias data this;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
@ -295,6 +296,7 @@ struct Texture {
|
|||
/// Represents an identifier for a managed resource.
|
||||
struct TextureId {
|
||||
GenerationalIndex data;
|
||||
|
||||
alias data this;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
@ -386,6 +388,7 @@ struct Font {
|
|||
/// Represents an identifier for a managed resource.
|
||||
struct FontId {
|
||||
GenerationalIndex data;
|
||||
|
||||
alias data this;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
@ -528,6 +531,7 @@ struct Sound {
|
|||
/// Represents an identifier for a managed resource.
|
||||
struct SoundId {
|
||||
GenerationalIndex data;
|
||||
|
||||
alias data this;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
@ -811,6 +815,7 @@ struct EngineFlags {
|
|||
bool isPixelSnapped;
|
||||
bool isPixelPerfect;
|
||||
bool isCursorVisible;
|
||||
bool canUseAssetsPath;
|
||||
}
|
||||
|
||||
struct EngineFullscreenState {
|
||||
|
@ -902,6 +907,7 @@ struct EngineViewport {
|
|||
Viewport data;
|
||||
int targetWidth;
|
||||
int targetHeight;
|
||||
|
||||
alias data this;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
@ -931,16 +937,16 @@ struct EngineState {
|
|||
EngineResources resources;
|
||||
EngineFullscreenState fullscreenState;
|
||||
|
||||
Color borderColor;
|
||||
Sz tickCount;
|
||||
LStr assetsPath;
|
||||
LStr tempText;
|
||||
|
||||
Camera currentCamera;
|
||||
Viewport currentViewport;
|
||||
|
||||
Color borderColor;
|
||||
Filter defaultFilter;
|
||||
Wrap defaultWrap;
|
||||
Sz tickCount;
|
||||
rl.FilePathList filePathListBuffer;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
|
@ -1114,11 +1120,30 @@ IStr toAssetsPath(IStr path) {
|
|||
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.
|
||||
/// The resource remains valid until this function is called again.
|
||||
/// Supports both forward slashes and backslashes in file paths.
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1126,7 +1151,8 @@ Result!IStr loadTempText(IStr path) {
|
|||
/// The resource must be manually freed.
|
||||
/// Supports both forward slashes and backslashes in file paths.
|
||||
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.
|
||||
|
@ -1157,7 +1183,8 @@ TextId loadText(IStr path, Sz tag = 0) {
|
|||
/// Supports both forward slashes and backslashes in file paths.
|
||||
@trusted
|
||||
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.setWrap(engineState.defaultWrap);
|
||||
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.
|
||||
@trusted
|
||||
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) {
|
||||
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.
|
||||
@trusted
|
||||
Result!Sound loadRawSound(IStr path, float volume, float pitch) {
|
||||
auto targetPath = canUseAssetsPath ? path.toAssetsPath() : path;
|
||||
auto value = Sound();
|
||||
if (path.endsWith(".wav")) {
|
||||
value.data = rl.LoadSound(path.toAssetsPath().toCStr().getOr());
|
||||
value.data = rl.LoadSound(targetPath.toCStr().getOr());
|
||||
} else {
|
||||
value.data = rl.LoadMusicStream(path.toAssetsPath().toCStr().getOr());
|
||||
value.data = rl.LoadMusicStream(targetPath.toCStr().getOr());
|
||||
}
|
||||
value.setVolume(volume);
|
||||
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.
|
||||
/// Supports both forward slashes and backslashes in file paths.
|
||||
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.
|
||||
|
@ -1292,6 +1322,7 @@ void openWindow(int width, int height, IStr appPath, IStr title = "Parin") {
|
|||
engineState.viewport.color = gray;
|
||||
engineState.fullscreenState.lastWindowWidth = width;
|
||||
engineState.fullscreenState.lastWindowHeight = height;
|
||||
engineState.flags.canUseAssetsPath = true;
|
||||
engineState.assetsPath.append(pathConcat(appPath.pathDir, "assets"));
|
||||
engineState.tempText.reserve(8192);
|
||||
// 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());
|
||||
|
||||
// The main loop.
|
||||
if (rl.IsFileDropped) {
|
||||
engineState.filePathListBuffer = rl.LoadDroppedFiles();
|
||||
}
|
||||
auto dt = deltaTime;
|
||||
auto result = _updateFunc(dt);
|
||||
engineState.tickCount = (engineState.tickCount + 1) % engineState.tickCount.max;
|
||||
if (rl.IsFileDropped) {
|
||||
rl.UnloadDroppedFiles(engineState.filePathListBuffer);
|
||||
engineState.filePathListBuffer = rl.FilePathList();
|
||||
}
|
||||
|
||||
// End drawing.
|
||||
if (isResolutionLocked) {
|
||||
|
@ -1780,7 +1818,15 @@ bool isDown(char key) {
|
|||
/// Returns true if the specified key is currently pressed.
|
||||
@trusted
|
||||
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.
|
||||
|
@ -1804,7 +1850,15 @@ bool isPressed(char key) {
|
|||
/// Returns true if the specified key was pressed.
|
||||
@trusted
|
||||
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.
|
||||
|
@ -1828,7 +1882,15 @@ bool isReleased(char key) {
|
|||
/// Returns true if the specified key was released.
|
||||
@trusted
|
||||
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.
|
||||
|
@ -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.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
||||
if (isPixelSnapped || isPixelPerfect) {
|
||||
rl.rlTranslatef(-origin.x.floor(), -origin.y.floor(), 0.0f);
|
||||
} else {
|
||||
rl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||
}
|
||||
rl.rlTranslatef(-origin.x.floor(), -origin.y.floor(), 0.0f);
|
||||
rl.DrawTextCodepoint(font.data, rune, rl.Vector2(0.0f, 0.0f), font.size, options.color.toRl());
|
||||
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.rlScalef(options.scale.x, options.scale.y, 1.0f);
|
||||
if (isPixelSnapped || isPixelPerfect) {
|
||||
rl.rlTranslatef(floor(-origin.x), floor(-origin.y), 0.0f);
|
||||
} else {
|
||||
rl.rlTranslatef(-origin.x, -origin.y, 0.0f);
|
||||
}
|
||||
rl.rlTranslatef(floor(-origin.x), floor(-origin.y), 0.0f);
|
||||
auto textOffsetY = 0.0f; // Offset between lines (on linebreak '\n').
|
||||
auto textOffsetX = 0.0f; // Offset X to next character to draw.
|
||||
auto i = 0;
|
||||
|
|
|
@ -71,7 +71,9 @@ struct TileMap {
|
|||
int tileHeight = 16;
|
||||
Vec2 position;
|
||||
|
||||
alias data this;
|
||||
enum maxRowCount = data.maxRowCount;
|
||||
enum maxColCount = data.maxColCount;
|
||||
enum maxCapacity = data.maxCapacity;
|
||||
|
||||
@safe @nogc nothrow:
|
||||
|
||||
|
@ -84,6 +86,79 @@ struct TileMap {
|
|||
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() {
|
||||
return cast(int) (softMaxColCount * tileWidth);
|
||||
}
|
||||
|
@ -189,7 +264,7 @@ struct TileMap {
|
|||
|
||||
void popFront() {
|
||||
position.x += 1;
|
||||
if (position.x >= TileMap.maxColCount) {
|
||||
if (position.x >= maxColCount) {
|
||||
position.x = first.x;
|
||||
position.y += 1;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue