Some rin changes and added viewport info.

This commit is contained in:
Kapendev 2025-01-29 17:23:20 +02:00
parent 5ee7533861
commit 7860192128
2 changed files with 78 additions and 67 deletions

View file

@ -5,24 +5,47 @@ import parin.story;
RinState rinState;
enum helpMsg = `
Usage:
rin [options] script
rin [options] -e expression
Options:
-d Executes in debug mode.
-l Executes in linear mode.
-e Executes a single expression.
`[1 .. $ - 1];
struct RinState {
IStr scriptPath;
Story story;
bool executeMode;
}
void printError(Sz index, IStr text) {
IStr prepareErrorMsg(Fault fault) {
switch (fault) with (Fault) {
case overflow: return "Label is too long.";
case cantParse: return "Invalid character at the beginning of the line.";
default: return "WTF!";
}
}
IStr updateErrorMsg(Fault fault) {
switch (fault) with (Fault) {
case assertion: return "Assertion failed.";
case invalid: return "Invalid arguments passed to the `{}` operator.".format(rinState.story.faultOp);
case overflow: return "A word or number is too long.";
case cantParse: return "A word, number, or operator contains invalid characters.";
default: return "WTF!";
}
}
void printScriptError(Sz index, IStr text) {
printfln("\n{}({}): {}", rinState.scriptPath, index, text);
}
Fault prepareStory() {
if (auto fault = rinState.story.prepare()) {
auto index = rinState.story.faultPrepareIndex + 1;
switch (fault) with (Fault) {
overflow: printError(index, "Label is too long."); break;
cantParse: printError(index, "Invalid character at the beginning of the line."); break;
default: break;
}
printScriptError(rinState.story.faultPrepareIndex + 1, prepareErrorMsg(fault));
return fault;
}
return Fault.none;
@ -31,14 +54,7 @@ Fault prepareStory() {
Fault updateStory() {
if (rinState.story.hasText) println(rinState.story.text);
if (auto fault = rinState.story.update()) {
auto index = rinState.story.lineIndex + 1;
switch (fault) with (Fault) {
case assertion: printError(index, "Assertion failed."); break;
case invalid: printError(index, "Invalid arguments passed to the `{}` operator.".format(rinState.story.faultOp)); break;
case overflow: printError(index, "A word or number is too long."); break;
case cantParse: printError(index, "A word, number, or operator contains invalid characters."); break;
default: break;
}
printScriptError(rinState.story.lineIndex + 1, updateErrorMsg(fault));
return fault;
}
return Fault.none;
@ -46,21 +62,15 @@ Fault updateStory() {
int rinMain(string[] args) {
if (args.length == 1) {
println("Usage:");
println(" rin [options] script");
println(" rin [options] -execute expression");
println("Options:");
println(" -debug Executes in debug mode.");
println(" -linear Executes in linear mode.");
println(" -execute Executes a single expression.");
println(helpMsg);
return 0;
}
auto executeIndex = 0LU;
foreach (i, arg; args) {
switch (arg) {
case "-debug": rinState.story.debugMode = true; break;
case "-linear": rinState.story.linearMode = true; break;
case "-execute": rinState.executeMode = true; executeIndex = i; break;
case "-d": rinState.story.debugMode = true; break;
case "-l": rinState.story.linearMode = true; break;
case "-e": rinState.executeMode = true; executeIndex = i; break;
default: break;
}
}
@ -71,21 +81,15 @@ int rinMain(string[] args) {
expression.append(' ');
}
if (auto fault = rinState.story.execute(expression[])) {
switch (fault) with (Fault) {
case assertion: println("Assertion failed."); break;
case invalid: println("Invalid arguments passed to the `{}` operator.".format(rinState.story.faultOp)); break;
case overflow: println("A word or number is too long."); break;
case cantParse: println("A word, number, or operator contains invalid characters."); break;
default: break;
}
println(updateErrorMsg(fault));
return 1;
}
} else {
rinState.scriptPath = args[$ - 1];
if (auto fault = readTextIntoBuffer(rinState.scriptPath, rinState.story.script)) {
switch (fault) {
case Fault.cantOpen: println("Can't open `{}`.".format(rinState.scriptPath)); break;
case Fault.cantRead: println("Can't read `{}`.".format(rinState.scriptPath)); break;
switch (fault) with (Fault) {
case cantOpen: printfln("Can't open `{}`.", rinState.scriptPath); break;
case cantRead: printfln("Can't read `{}`.", rinState.scriptPath); break;
default: break;
}
return 1;

View file

@ -54,8 +54,8 @@ enum Filter : ubyte {
/// A type representing texture wrapping modes.
enum Wrap : ubyte {
clamp = rl.TEXTURE_WRAP_CLAMP, // Clamps texture.
repeat = rl.TEXTURE_WRAP_REPEAT, // Repeats texture.
clamp = rl.TEXTURE_WRAP_CLAMP, /// Clamps texture.
repeat = rl.TEXTURE_WRAP_REPEAT, /// Repeats texture.
}
/// A type representing blending modes.
@ -865,6 +865,15 @@ struct EngineResourceGroup(T) {
}
}
/// A structure with information about the engine viewport, including its area.
struct EngineViewportInfo {
Rect area; /// The area covered by the viewport.
Vec2 minSize; /// The minimum size that the viewport can be.
Vec2 maxSize; /// The maximum size that the viewport can be.
Vec2 ratio; /// The ratio between minSize and maxSize.
float minRatio = 0.0f; /// The minimum ratio between minSize and maxSize.
}
struct EngineViewport {
Viewport data;
int targetWidth;
@ -1341,31 +1350,14 @@ void updateWindow(bool function(float dt) updateFunc) {
// End drawing.
if (isResolutionLocked) {
auto minSize = engineState.viewport.size;
auto maxSize = windowSize;
auto ratio = maxSize / minSize;
auto minRatio = min(ratio.x, ratio.y);
if (isPixelPerfect) {
auto roundMinRatio = minRatio.round();
auto floorMinRation = minRatio.floor();
minRatio = minRatio.equals(roundMinRatio, 0.015f) ? roundMinRatio : floorMinRation;
}
auto targetSize = minSize * Vec2(minRatio);
auto targetPosition = maxSize * Vec2(0.5f) - targetSize * Vec2(0.5f);
auto info = engineViewportInfo;
rl.EndTextureMode();
rl.BeginDrawing();
rl.ClearBackground(engineState.borderColor.toRl());
rl.DrawTexturePro(
engineState.viewport.toRl().texture,
rl.Rectangle(0.0f, 0.0f, minSize.x, -minSize.y),
rl.Rectangle(
floor(targetPosition.x),
floor(targetPosition.y),
ratio.x == minRatio ? targetSize.x : floor(targetSize.x),
ratio.y == minRatio ? targetSize.y : floor(targetSize.y),
),
rl.Rectangle(0.0f, 0.0f, info.minSize.x, -info.minSize.y),
info.area.toRl(),
rl.Vector2(0.0f, 0.0f),
0.0f,
rl.Color(255, 255, 255, 255),
@ -1571,6 +1563,28 @@ Fault setWindowIconFromFiles(IStr path) {
return Fault.none;
}
/// Returns information about the engine viewport, including its area.
EngineViewportInfo engineViewportInfo() {
auto result = EngineViewportInfo();
result.minSize = engineState.viewport.size;
result.maxSize = windowSize;
auto ratio = result.maxSize / result.minSize;
result.minRatio = min(ratio.x, ratio.y);
if (isPixelPerfect) {
auto roundMinRatio = result.minRatio.round();
auto floorMinRation = result.minRatio.floor();
result.minRatio = result.minRatio.equals(roundMinRatio, 0.015f) ? roundMinRatio : floorMinRation;
}
auto targetSize = result.minSize * Vec2(result.minRatio);
auto targetPosition = result.maxSize * Vec2(0.5f) - targetSize * Vec2(0.5f);
result.area = Rect(
targetPosition.floor(),
ratio.x == result.minRatio ? targetSize.x : floor(targetSize.x),
ratio.y == result.minRatio ? targetSize.y : floor(targetSize.y),
);
return result;
}
/// Returns the default engine font. This font should not be freed.
@trusted
Font engineFont() {
@ -1711,17 +1725,10 @@ Vec2 mouse() {
// Touch works on desktop, web and mobile.
auto rlMouse = rl.GetTouchPosition(0);
if (isResolutionLocked) {
auto window = windowSize;
auto minRatio = min(window.x / engineState.viewport.width, window.y / engineState.viewport.height);
if (isPixelPerfect) {
auto roundMinRatio = minRatio.round();
auto floorMinRation = minRatio.floor();
minRatio = minRatio.equals(roundMinRatio, 0.015f) ? roundMinRatio : floorMinRation;
}
auto targetSize = engineState.viewport.size * Vec2(minRatio);
auto info = engineViewportInfo;
return Vec2(
(rlMouse.x - (window.x - targetSize.x) * 0.5f) / minRatio,
(rlMouse.y - (window.y - targetSize.y) * 0.5f) / minRatio,
(rlMouse.x - (info.maxSize.x - info.area.size.x) * 0.5f) / info.minRatio,
(rlMouse.y - (info.maxSize.y - info.area.size.y) * 0.5f) / info.minRatio,
);
} else {
return rlMouse.toParin();