Changed version.

This commit is contained in:
Kapendev 2025-04-16 17:02:23 +03:00
parent 58e94cdd56
commit 2252231aa5
15 changed files with 830 additions and 15 deletions

View file

@ -1,4 +1,4 @@
# Parin
# 🍩 Parin
A delightfully simple and lightweight 2D game engine for the D programming language.
@ -24,9 +24,11 @@ mixin runGame!(ready, update, finish);
Parin is packed with powerful features to get you started quickly:
* Intuitive immediate mode UI
* Efficient tile map structures
* Flexible dialogue system with a stack-oriented scripting language
* Atlas-based animation library
* Pixel-perfect physics engine
* Cross-language support for the core library
* ...and more!
## Cross-Platform

View file

@ -13,7 +13,6 @@
"source"
],
"subPackages" : [
"packages/mapy",
"packages/rin",
"packages/setup",
"packages/web"

813
scripts/capi.d Executable file
View file

@ -0,0 +1,813 @@
#!/bin/env -S dmd -run
// [Noby Script]
enum outputFileBaseName = "parin.h";
int main(string[] args) {
logw("Not done yet.");
return 1;
auto tempPath = pathConcat("source", "parin", "engine.d");
if (!tempPath.isF) { echo("Can't find parin file."); return 1; }
Str api = null;
api.reserve(8192);
api ~= "#ifndef PARIN_H\n#define PARIN_H\n\n";
auto parinContent = cat(tempPath);
auto hasApiPart = false;
while (parinContent.length) {
auto line = parinContent.skipLine();
if (0) {
} else if (hasApiPart) {
hasApiPart = false;
api ~= line;
api ~= '\n';
} else if (line.startsWith("extern(C)")) {
hasApiPart = true;
}
}
api ~= "\n#endif // PARIN_H\n";
paste(outputFileBaseName, api);
return 0;
}
// [Noby Library]
Level minLogLevel = Level.info;
bool isCmdLineHidden = false;
enum cloneExt = "._clone";
enum Level : ubyte {
none,
info,
warning,
error,
}
bool isX(IStr path) {
import std.file;
return path.exists;
}
bool isF(IStr path) {
import std.file;
return path.isX && path.isFile;
}
bool isD(IStr path) {
import std.file;
return path.isX && path.isDir;
}
void echo(A...)(A args) {
import std.stdio;
writeln(args);
}
void echon(A...)(A args) {
import std.stdio;
write(args);
}
void echof(A...)(IStr text, A args) {
import std.stdio;
writefln(text, args);
}
void echofn(A...)(IStr text, A args) {
import std.stdio;
writef(text, args);
}
void cp(IStr source, IStr target) {
import std.file;
copy(source, target);
}
void rm(IStr path) {
import std.file;
if (path.isX) remove(path);
}
void mv(IStr source, IStr target) {
cp(source, target);
rm(source);
}
void mkdir(IStr path, bool isRecursive = false) {
import std.file;
if (!path.isX) {
if (isRecursive) mkdirRecurse(path);
else std.file.mkdir(path);
}
}
void rmdir(IStr path, bool isRecursive = false) {
import std.file;
if (path.isX) {
if (isRecursive) rmdirRecurse(path);
else std.file.rmdir(path);
}
}
IStr pwd() {
import std.file;
return getcwd();
}
IStr cat(IStr path) {
import std.file;
return path.isX ? readText(path) : "";
}
IStr[] ls(IStr path = ".", bool isRecursive = false) {
import std.file;
IStr[] result = [];
foreach (file; dirEntries(cast(string) path, isRecursive ? SpanMode.breadth : SpanMode.shallow)) {
result ~= file.name;
}
return result;
}
IStr[] find(IStr path, IStr ext, bool isRecursive = false) {
import std.file;
IStr[] result = [];
foreach (file; dirEntries(cast(string) path, isRecursive ? SpanMode.breadth : SpanMode.shallow)) {
if (file.endsWith(ext)) result ~= file.name;
}
return result;
}
IStr read() {
import std.stdio;
return readln().trim();
}
IStr readYesNo(IStr text, IStr firstValue = "?") {
auto result = firstValue;
while (true) {
if (result.length == 0) result = "Y";
if (result.isYesOrNo) break;
echon(text, " [Y/n] ");
result = read();
}
return result;
}
IStr format(A...)(IStr text, A args...) {
import std.format;
return format(text, args);
}
bool isYes(IStr arg) {
return (arg.length == 1 && (arg[0] == 'Y' || arg[0] == 'y'));
}
bool isNo(IStr arg) {
return (arg.length == 1 && (arg[0] == 'N' || arg[0] == 'n'));
}
bool isYesOrNo(IStr arg) {
return arg.isYes || arg.isNo;
}
void clear(IStr path = ".", IStr ext = "") {
foreach (file; ls(path)) {
if (file.endsWith(ext)) rm(file);
}
}
void paste(IStr path, IStr content, bool isOnlyMaking = false) {
import std.file;
if (isOnlyMaking) {
if (!path.isX) write(path, content);
} else {
write(path, content);
}
}
void clone(IStr path) {
if (path.isX) cp(path, path ~ cloneExt);
}
void restore(IStr path, bool isOnlyRemoving = false) {
auto clonePath = path ~ cloneExt;
if (clonePath.isX) {
if (!isOnlyRemoving) paste(path, cat(clonePath));
rm(clonePath);
}
}
void log(Level level, IStr text) {
if (minLogLevel == 0 || minLogLevel > level) return;
with (Level) final switch (level) {
case info: echo("[INFO] ", text); break;
case warning: echo("[WARNING] ", text); break;
case error: echo("[ERROR] ", text); break;
case none: break;
}
}
void logi(IStr text) {
log(Level.info, text);
}
void logw(IStr text) {
log(Level.warning, text);
}
void loge(IStr text) {
log(Level.error, text);
}
void logf(A...)(Level level, IStr text, A args) {
log(level, text.fmt(args));
}
int cmd(IStr[] args...) {
import std.process;
if (!isCmdLineHidden) echo("[CMD] ", args);
try {
return spawnProcess(args).wait();
} catch (Exception e) {
return 1;
}
}
// The following code is copied from Joka: https://github.com/Kapendev/joka/blob/main/source/joka/ascii.d
alias Sz = size_t; /// The result of sizeof, ...
alias Str = char[]; /// A string slice of chars.
alias Str16 = wchar[]; /// A string slice of wchars.
alias Str32 = dchar[]; /// A string slice of dchars.
alias IStr = const(char)[]; /// A string slice of constant chars.
alias IStr16 = const(wchar)[]; /// A string slice of constant wchars.
alias IStr32 = const(dchar)[]; /// A string slice of constant dchars.
alias CStr = char*; /// A C string of chars.
alias CStr16 = wchar*; /// A C string of wchars.
alias CStr32 = dchar*; /// A C string of dchars.
alias ICStr = const(char)*; /// A C string of constant chars.
alias ICStr16 = const(wchar)*; /// A C string of constant wchars.
alias ICStr32 = const(dchar)*; /// A C string of constant dchars.
/// A type representing error values.
enum Fault : ubyte {
none, /// Not an error.
some, /// A generic error.
bug, /// An implementation error.
invalid, /// An invalid data error.
overflow, /// An overflow error.
assertion, /// An assertion error.
cantParse, /// A parse error.
cantFind, /// A wrong path error.
cantOpen, /// An open permissions error.
cantClose, /// A close permissions error.
cantRead, /// A read permissions error.
cantWrite, /// A write permissions error.
}
enum digitChars = "0123456789"; /// The set of digits.
enum upperChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; /// The set of uppercase letters.
enum lowerChars = "abcdefghijklmnopqrstuvwxyz"; /// The set of lowercase letters.
enum alphaChars = upperChars ~ lowerChars; /// The set of letters.
enum spaceChars = " \t\v\r\n\f"; /// The set of whitespace characters.
enum symbolChars = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"; /// The set of symbol characters.
version (Windows) {
enum pathSep = '\\';
enum pathSepStr = "\\";
enum pathSepOther = '/';
enum pathSepOtherStr = "/";
} else {
enum pathSep = '/'; /// The primary OS path separator as a character.
enum pathSepStr = "/"; /// The primary OS path separator as a string.
enum pathSepOther = '\\'; /// The complementary OS path separator as a character.
enum pathSepOtherStr = "\\"; /// The complementary OS path separator as a string.
}
/// Returns true if the character is a symbol (!, ", ...).
pragma(inline, true);
bool isSymbol(char c) {
return (c >= '!' && c <= '/') || (c >= ':' && c <= '@') || (c >= '[' && c <= '`') || (c >= '{' && c <= '~');
}
/// Returns true if the character is a digit (0-9).
pragma(inline, true);
bool isDigit(char c) {
return c >= '0' && c <= '9';
}
/// Returns true if the character is an uppercase letter (A-Z).
pragma(inline, true);
bool isUpper(char c) {
return c >= 'A' && c <= 'Z';
}
/// Returns true the character is a lowercase letter (a-z).
pragma(inline, true);
bool isLower(char c) {
return c >= 'a' && c <= 'z';
}
/// Returns true if the character is an alphabetic letter (A-Z or a-z).
pragma(inline, true);
bool isAlpha(char c) {
return isLower(c) || isUpper(c);
}
/// Returns true if the character is a whitespace character (space, tab, ...).
pragma(inline, true);
bool isSpace(char c) {
return (c >= '\t' && c <= '\r') || (c == ' ');
}
/// Returns true if the string represents a C string.
pragma(inline, true);
bool isCStr(IStr str) {
return str.length != 0 && str[$ - 1] == '\0';
}
/// Converts the character to uppercase if it is a lowercase letter.
char toUpper(char c) {
return isLower(c) ? cast(char) (c - 32) : c;
}
/// Converts all lowercase letters in the string to uppercase.
void toUpper(Str str) {
foreach (ref c; str) c = toUpper(c);
}
/// Converts the character to lowercase if it is an uppercase letter.
char toLower(char c) {
return isUpper(c) ? cast(char) (c + 32) : c;
}
/// Converts all uppercase letters in the string to lowercase.
void toLower(Str str) {
foreach (ref c; str) c = toLower(c);
}
/// Returns the length of the C string.
@trusted
Sz cStrLength(ICStr str) {
Sz result = 0;
while (str[result] != '\0') result += 1;
return result;
}
/// Returns true if the two strings are equal, ignoring case.
bool equalsNoCase(IStr str, IStr other) {
if (str.length != other.length) return false;
foreach (i; 0 .. str.length) if (toUpper(str[i]) != toUpper(other[i])) return false;
return true;
}
/// Returns true if the string is equal to the specified character, ignoring case.
bool equalsNoCase(IStr str, char other) {
return equalsNoCase(str, charToStr(other));
}
/// Returns true if the string starts with the specified substring.
bool startsWith(IStr str, IStr start) {
if (str.length < start.length) return false;
return str[0 .. start.length] == start;
}
/// Returns true if the string starts with the specified character.
bool startsWith(IStr str, char start) {
return startsWith(str, charToStr(start));
}
/// Returns true if the string ends with the specified substring.
bool endsWith(IStr str, IStr end) {
if (str.length < end.length) return false;
return str[$ - end.length .. $] == end;
}
/// Returns true if the string ends with the specified character.
bool endsWith(IStr str, char end) {
return endsWith(str, charToStr(end));
}
/// Counts the number of occurrences of the specified substring in the string.
int countItem(IStr str, IStr item) {
int result = 0;
if (str.length < item.length || item.length == 0) return result;
foreach (i; 0 .. str.length - item.length) {
if (str[i .. i + item.length] == item) {
result += 1;
i += item.length - 1;
}
}
return result;
}
/// Counts the number of occurrences of the specified character in the string.
int countItem(IStr str, char item) {
return countItem(str, charToStr(item));
}
/// Finds the starting index of the first occurrence of the specified substring in the string, or returns -1 if not found.
int findStart(IStr str, IStr item) {
if (str.length < item.length || item.length == 0) return -1;
foreach (i; 0 .. str.length - item.length + 1) {
if (str[i .. i + item.length] == item) return cast(int) i;
}
return -1;
}
/// Finds the starting index of the first occurrence of the specified character in the string, or returns -1 if not found.
int findStart(IStr str, char item) {
return findStart(str, charToStr(item));
}
/// Finds the ending index of the first occurrence of the specified substring in the string, or returns -1 if not found.
int findEnd(IStr str, IStr item) {
if (str.length < item.length || item.length == 0) return -1;
foreach_reverse (i; 0 .. str.length - item.length + 1) {
if (str[i .. i + item.length] == item) return cast(int) i;
}
return -1;
}
/// Finds the ending index of the first occurrence of the specified character in the string, or returns -1 if not found.
int findEnd(IStr str, char item) {
return findEnd(str, charToStr(item));
}
/// Finds the first occurrence of the specified item in the slice, or returns -1 if not found.
int findItem(IStr[] items, IStr item) {
foreach (i, it; items) if (it == item) return cast(int) i;
return -1;
}
/// Finds the first occurrence of the specified start in the slice, or returns -1 if not found.
int findItemThatStartsWith(IStr[] items, IStr start) {
foreach (i, it; items) if (it.startsWith(start)) return cast(int) i;
return -1;
}
/// Finds the first occurrence of the specified end in the slice, or returns -1 if not found.
int findItemThatEndsWith(IStr[] items, IStr end) {
foreach (i, it; items) if (it.endsWith(end)) return cast(int) i;
return -1;
}
/// Removes whitespace characters from the beginning of the string.
IStr trimStart(IStr str) {
IStr result = str;
while (result.length > 0) {
if (isSpace(result[0])) result = result[1 .. $];
else break;
}
return result;
}
/// Removes whitespace characters from the end of the string.
IStr trimEnd(IStr str) {
IStr result = str;
while (result.length > 0) {
if (isSpace(result[$ - 1])) result = result[0 .. $ - 1];
else break;
}
return result;
}
/// Removes whitespace characters from both the beginning and end of the string.
IStr trim(IStr str) {
return str.trimStart().trimEnd();
}
/// Removes the specified prefix from the beginning of the string if it exists.
IStr removePrefix(IStr str, IStr prefix) {
if (str.startsWith(prefix)) return str[prefix.length .. $];
else return str;
}
/// Removes the specified suffix from the end of the string if it exists.
IStr removeSuffix(IStr str, IStr suffix) {
if (str.endsWith(suffix)) return str[0 .. $ - suffix.length];
else return str;
}
/// Advances the string by the specified number of characters.
IStr advanceStr(IStr str, Sz amount) {
if (str.length < amount) return str[$ .. $];
else return str[amount .. $];
}
/// Copies characters from the source string to the destination string starting at the specified index.
@trusted
Fault copyChars(Str str, IStr source, Sz startIndex = 0) {
if (str.length < source.length + startIndex) return Fault.overflow;
foreach (i, c; source) str[startIndex + i] = c;
return Fault.none;
}
/// Copies characters from the source string to the destination string starting at the specified index and adjusts the length of the destination string.
Fault copyStr(ref Str str, IStr source, Sz startIndex = 0) {
auto fault = copyChars(str, source, startIndex);
if (fault) return fault;
str = str[0 .. startIndex + source.length];
return Fault.none;
}
/// Concatenates the strings.
/// Writes into the buffer and returns the result.
IStr concatIntoBuffer(Str buffer, IStr[] args...) {
if (args.length == 0) return ".";
auto result = buffer;
auto length = 0;
foreach (i, arg; args) {
result.copyChars(arg, length);
length += arg.length;
}
result = result[0 .. length];
return result;
}
/// Concatenates the strings using a static buffer and returns the result.
IStr concat(IStr[] args...) {
static char[512][4] buffers = void;
static byte bufferIndex = 0;
if (args.length == 0) return ".";
bufferIndex = (bufferIndex + 1) % buffers.length;
return concatIntoBuffer(buffers[bufferIndex][], args);
}
/// Returns the directory of the path, or "." if there is no directory.
IStr pathDirName(IStr path) {
auto end = findEnd(path, pathSepStr);
if (end == -1) return ".";
else return path[0 .. end];
}
/// Returns the extension of the path.
IStr pathExtName(IStr path) {
auto end = findEnd(path, ".");
if (end == -1) return "";
else return path[end .. $];
}
/// Returns the base name of the path.
IStr pathBaseName(IStr path) {
auto end = findEnd(path, pathSepStr);
if (end == -1) return path;
else return path[end + 1 .. $];
}
/// Returns the base name of the path without the extension.
IStr pathBaseNameNoExt(IStr path) {
return path.pathBaseName[0 .. $ - path.pathExtName.length];
}
/// Removes path separators from the beginning of the path.
IStr pathTrimStart(IStr path) {
IStr result = path;
while (result.length > 0) {
if (result[0] == pathSep || result[0] == pathSepOther) result = result[1 .. $];
else break;
}
return result;
}
/// Removes path separators from the end of the path.
IStr pathTrimEnd(IStr path) {
IStr result = path;
while (result.length > 0) {
if (result[$ - 1] == pathSep || result[$ - 1] == pathSepOther) result = result[0 .. $ - 1];
else break;
}
return result;
}
/// Removes path separators from the beginning and end of the path.
IStr pathTrim(IStr path) {
return path.pathTrimStart().pathTrimEnd();
}
/// Formats the path to a standard form, normalizing separators.
IStr pathFormat(IStr path) {
static char[512][4] buffers = void;
static byte bufferIndex = 0;
if (path.length == 0) return ".";
bufferIndex = (bufferIndex + 1) % buffers.length;
auto result = buffers[bufferIndex][];
foreach (i, c; path) {
if (c == pathSepOther) {
result[i] = pathSep;
} else {
result[i] = c;
}
}
result = result[0 .. path.length];
return result;
}
/// Concatenates the paths, ensuring proper path separators between them.
IStr pathConcat(IStr[] args...) {
static char[512][4] buffers = void;
static byte bufferIndex = 0;
if (args.length == 0) return ".";
bufferIndex = (bufferIndex + 1) % buffers.length;
auto result = buffers[bufferIndex][];
auto length = 0;
auto isFirst = true;
foreach (i, arg; args) {
if (arg.length == 0) continue;
auto cleanArg = arg;
if (cleanArg[0] == pathSep || cleanArg[0] == pathSepOther) {
cleanArg = cleanArg.pathTrimStart();
if (isFirst) {
result[length] = pathSep;
length += 1;
}
}
cleanArg = cleanArg.pathTrimEnd();
result.copyChars(cleanArg, length);
length += cleanArg.length;
if (i != args.length - 1) {
result[length] = pathSep;
length += 1;
}
isFirst = false;
}
if (length == 0) return ".";
result = result[0 .. length];
return result;
}
/// Skips over the next occurrence of the specified separator in the string, returning the substring before the separator and updating the input string to start after the separator.
IStr skipValue(ref inout(char)[] str, IStr sep) {
if (str.length < sep.length || sep.length == 0) {
str = str[$ .. $];
return "";
}
foreach (i; 0 .. str.length - sep.length) {
if (str[i .. i + sep.length] == sep) {
auto line = str[0 .. i];
str = str[i + sep.length .. $];
return line;
}
}
auto line = str[0 .. $];
if (str[$ - sep.length .. $] == sep) {
line = str[0 .. $ - 1];
}
str = str[$ .. $];
return line;
}
/// Skips over the next occurrence of the specified separator in the string, returning the substring before the separator and updating the input string to start after the separator.
IStr skipValue(ref inout(char)[] str, char sep) {
return skipValue(str, charToStr(sep));
}
/// Skips over the next line in the string, returning the substring before the line break and updating the input string to start after the line break.
IStr skipLine(ref inout(char)[] str) {
return skipValue(str, '\n');
}
/// Converts the boolean value to its string representation.
IStr boolToStr(bool value) {
return value ? "true" : "false";
}
/// Converts the character to its string representation.
IStr charToStr(char value) {
static char[1] buffer = void;
auto result = buffer[];
result[0] = value;
result = result[0 .. 1];
return result;
}
/// Converts the unsigned long value to its string representation.
IStr unsignedToStr(ulong value) {
static char[64] buffer = void;
auto result = buffer[];
if (value == 0) {
result[0] = '0';
result = result[0 .. 1];
} else {
auto digitCount = 0;
for (auto temp = value; temp != 0; temp /= 10) {
result[$ - 1 - digitCount] = (temp % 10) + '0';
digitCount += 1;
}
result = result[$ - digitCount .. $];
}
return result;
}
/// Converts the signed long value to its string representation.
IStr signedToStr(long value) {
static char[64] buffer = void;
auto result = buffer[];
if (value < 0) {
auto temp = unsignedToStr(-value);
result[0] = '-';
result.copyStr(temp, 1);
} else {
auto temp = unsignedToStr(value);
result.copyStr(temp, 0);
}
return result;
}
/// Converts the double value to its string representation with the specified precision.
IStr doubleToStr(double value, ulong precision = 2) {
static char[64] buffer = void;
if (precision == 0) {
return signedToStr(cast(long) value);
}
auto result = buffer[];
auto cleanNumber = value;
auto rightDigitCount = 0;
while (cleanNumber != cast(double) (cast(long) cleanNumber)) {
rightDigitCount += 1;
cleanNumber *= 10;
}
// Add extra zeros at the end if needed.
// I do this because it makes it easier to remove the zeros later.
if (precision > rightDigitCount) {
foreach (j; 0 .. precision - rightDigitCount) {
rightDigitCount += 1;
cleanNumber *= 10;
}
}
// Digits go in the buffer from right to left.
auto cleanNumberStr = signedToStr(cast(long) cleanNumber);
auto i = result.length;
// Check two cases: 0.NN, N.NN
if (cast(long) value == 0) {
if (value < 0.0) {
cleanNumberStr = cleanNumberStr[1 .. $];
}
i -= cleanNumberStr.length;
result.copyChars(cleanNumberStr, i);
foreach (j; 0 .. rightDigitCount - cleanNumberStr.length) {
i -= 1;
result[i] = '0';
}
i -= 2;
result.copyChars("0.", i);
if (value < 0.0) {
i -= 1;
result[i] = '-';
}
} else {
i -= rightDigitCount;
result.copyChars(cleanNumberStr[$ - rightDigitCount .. $], i);
i -= 1;
result[i] = '.';
i -= cleanNumberStr.length - rightDigitCount;
result.copyChars(cleanNumberStr[0 .. $ - rightDigitCount], i);
}
// Remove extra zeros at the end if needed.
if (precision < rightDigitCount) {
result = result[0 .. cast(Sz) ($ - rightDigitCount + precision)];
}
return result[i .. $];
}
/// Converts the C string to a string.
@trusted
IStr cStrToStr(ICStr value) {
return value[0 .. value.cStrLength];
}
/// Converts the enum value to its string representation.
IStr enumToStr(T)(T value) {
switch (value) {
static foreach (m; __traits(allMembers, T)) {
mixin("case T.", m, ": return m;");
}
default: assert(0, "WTF!");
}
}
/// Converts the string value to its enum representation.
// NOTE: This function is adapted from Joka and modified for Noby.
T toEnum(T)(IStr str) {
switch (str) {
static foreach (m; __traits(allMembers, T)) {
mixin("case m: return T.", m, ";");
}
default: return T.init;
}
}

View file

@ -10,7 +10,7 @@ enum header = `
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
`[1 .. $ - 1];

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
/// The `engine` module functions as a lightweight 2D game engine.
@ -19,7 +19,8 @@ public import joka.types;
@trusted @nogc nothrow:
extern(C) __gshared EngineState* engineState;
extern(C)
__gshared EngineState* engineState;
alias EngineUpdateFunc = bool function(float dt);
alias EngineReadyFinishFunc = void function();

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
// TODO: Think about gaps in an atlas texture.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
module parin;

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
// TODO: Update all the doc comments here.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
/// The `rl` module provides access to the raylib library.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
/// The `rayib` module provides access to the raylib.h functions.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
/// The `rlgl` module provides access to the rlgl.h functions.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
// TODO: Think about gaps in an atlas texture.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
// TODO: Update all the doc comments here.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
// TODO: Update all the doc comments here.

View file

@ -3,7 +3,7 @@
// SPDX-License-Identifier: MIT
// Email: alexandroskapretsos@gmail.com
// Project: https://github.com/Kapendev/parin
// Version: v0.0.41
// Version: v0.0.42
// ---
/// The `ui` module functions as a immediate mode UI library.