Add Ruby-accessible delta clocks (microseconds)

This commit is contained in:
Struma 2021-02-25 21:29:21 -05:00 committed by Roza
parent d4d2b7c7cb
commit 02c06be88a
9 changed files with 120 additions and 3 deletions

View file

@ -104,6 +104,7 @@ void CUSLBindingInit();
void httpBindingInit();
RB_METHOD(mkxpDelta);
RB_METHOD(mriPrint);
RB_METHOD(mriP);
RB_METHOD(mkxpDataDirectory);
@ -188,6 +189,7 @@ static void mriBindingInit() {
assert(!"unreachable");
VALUE mod = rb_define_module("System");
_rb_define_module_function(mod, "delta", mkxpDelta);
_rb_define_module_function(mod, "data_directory", mkxpDataDirectory);
_rb_define_module_function(mod, "set_window_title", mkxpSetTitle);
_rb_define_module_function(mod, "show_settings", mkxpSettingsMenu);
@ -244,6 +246,7 @@ static void printP(int argc, VALUE *argv, const char *convMethod,
showMsg(RSTRING_PTR(dispString));
}
RB_METHOD(mriPrint) {
RB_UNUSED_PARAM;
@ -260,6 +263,12 @@ RB_METHOD(mriP) {
return Qnil;
}
RB_METHOD(mkxpDelta) {
RB_UNUSED_PARAM;
return ULL2NUM(shState->runTime());
}
RB_METHOD(mkxpDataDirectory) {
RB_UNUSED_PARAM;

View file

@ -25,6 +25,12 @@
#include "binding-types.h"
#include "exception.h"
RB_METHOD(graphicsDelta) {
RB_UNUSED_PARAM;
return ULL2NUM(shState->graphics().getDelta());
}
RB_METHOD(graphicsUpdate)
{
RB_UNUSED_PARAM;
@ -255,6 +261,7 @@ void graphicsBindingInit()
{
VALUE module = rb_define_module("Graphics");
_rb_define_module_function(module, "delta", graphicsDelta);
_rb_define_module_function(module, "update", graphicsUpdate);
_rb_define_module_function(module, "freeze", graphicsFreeze);
_rb_define_module_function(module, "transition", graphicsTransition);

View file

@ -28,6 +28,12 @@
#include <SDL_joystick.h>
#include <string>
RB_METHOD(inputDelta) {
RB_UNUSED_PARAM;
return ULL2NUM(shState->input().getDelta());
}
RB_METHOD(inputUpdate) {
RB_UNUSED_PARAM;
@ -138,6 +144,19 @@ RB_METHOD(inputCount) {
return UINT2NUM(shState->input().count(num));
}
RB_METHOD(inputRepeatTime) {
RB_UNUSED_PARAM;
rb_check_argc(argc, 1);
VALUE button;
rb_scan_args(argc, argv, "1", &button);
int num = getButtonArg(&button);
return ULL2NUM(shState->input().repeatTime(num));
}
RB_METHOD(inputPressEx) {
RB_UNUSED_PARAM;
@ -208,6 +227,20 @@ RB_METHOD(inputCountEx) {
return UINT2NUM(shState->input().repeatcount(NUM2INT(button), 1));
}
RB_METHOD(inputRepeatTimeEx) {
RB_UNUSED_PARAM;
VALUE button;
rb_scan_args(argc, argv, "1", &button);
if (SYMBOL_P(button)) {
int num = getScancodeArg(&button);
return ULL2NUM(shState->input().repeatTimeEx(num, 0));
}
return ULL2NUM(shState->input().repeatTimeEx(NUM2INT(button), 1));
}
RB_METHOD(inputDir4) {
RB_UNUSED_PARAM;
@ -357,17 +390,20 @@ static elementsN(buttonCodes);
void inputBindingInit() {
VALUE module = rb_define_module("Input");
_rb_define_module_function(module, "delta", inputDelta);
_rb_define_module_function(module, "update", inputUpdate);
_rb_define_module_function(module, "press?", inputPress);
_rb_define_module_function(module, "trigger?", inputTrigger);
_rb_define_module_function(module, "repeat?", inputRepeat);
_rb_define_module_function(module, "release?", inputRelease);
_rb_define_module_function(module, "count", inputCount);
_rb_define_module_function(module, "time?", inputRepeatTime);
_rb_define_module_function(module, "pressex?", inputPressEx);
_rb_define_module_function(module, "triggerex?", inputTriggerEx);
_rb_define_module_function(module, "repeatex?", inputRepeatEx);
_rb_define_module_function(module, "releaseex?", inputReleaseEx);
_rb_define_module_function(module, "repeatcount", inputCountEx);
_rb_define_module_function(module, "timeex?", inputRepeatTimeEx);
_rb_define_module_function(module, "dir4", inputDir4);
_rb_define_module_function(module, "dir8", inputDir8);

View file

@ -421,6 +421,9 @@ struct GraphicsPrivate {
int frameCount;
int brightness;
unsigned long long last_update;
FPSLimiter fpsLimiter;
// Can be set from Ruby. Takes priority over config setting.
@ -440,7 +443,7 @@ struct GraphicsPrivate {
screen(scRes.x, scRes.y), threadData(rtData),
glCtx(SDL_GL_GetCurrentContext()), frameRate(DEF_FRAMERATE),
frameCount(0), brightness(255), fpsLimiter(frameRate),
useFrameSkip(rtData->config.frameSkip), frozen(false) {
useFrameSkip(rtData->config.frameSkip), frozen(false), last_update() {
recalculateScreenSize(rtData);
updateScreenResoRatio(rtData);
@ -584,6 +587,10 @@ Graphics::Graphics(RGSSThreadData *data) {
Graphics::~Graphics() { delete p; }
unsigned long long Graphics::getDelta() {
return shState->runTime() - p->last_update;
}
void Graphics::update() {
p->checkShutDownReset();
p->checkSyncLock();
@ -612,6 +619,7 @@ void Graphics::update() {
p->checkResize();
p->redrawScreen();
p->last_update = shState->runTime();
}
void Graphics::freeze() {

View file

@ -34,6 +34,8 @@ struct AtomicFlag;
class Graphics
{
public:
unsigned long long getDelta();
void update();
void freeze();
void transition(int duration = 8,

View file

@ -680,9 +680,13 @@ struct InputPrivate
int rawRepeating;
unsigned int repeatCount;
unsigned int rawRepeatCount;
unsigned long long repeatTime;
unsigned long long rawRepeatTime;
unsigned int repeatStart;
unsigned int repeatDelay;
unsigned long long last_update;
struct
{
@ -708,6 +712,8 @@ struct InputPrivate
InputPrivate(const RGSSThreadData &rtData)
{
last_update = 0;
initStaticKbBindings();
initMsBindings();
@ -1005,12 +1011,15 @@ struct InputPrivate
else
{
rawRepeatCount = 0;
rawRepeatTime = shState->runTime();
rawRepeating = i;
}
break;
return;
}
}
rawRepeating = -1;
}
void updateDir4()
@ -1101,6 +1110,10 @@ Input::Input(const RGSSThreadData &rtData)
p = new InputPrivate(rtData);
}
unsigned long long Input::getDelta() {
return shState->runTime() - p->last_update;
}
void Input::recalcRepeat(unsigned int fps) {
p->recalcRepeatTime(fps);
}
@ -1126,8 +1139,10 @@ void Input::update()
{
p->repeating = repeatCand;
p->repeatCount = 0;
p->repeatTime = shState->runTime();
p->getState(repeatCand).repeated = true;
p->last_update = p->repeatTime;
return;
}
@ -1146,10 +1161,12 @@ void Input::update()
bool repeated = p->repeatCount >= p->repeatStart && ((p->repeatCount+1) & p->repeatDelay) == 0;
p->getState(p->repeating).repeated |= repeated;
p->last_update = shState->runTime();
return;
}
p->repeating = None;
p->last_update = shState->runTime();
}
std::vector<std::string> Input::getBindings(ButtonCode code) {
@ -1203,6 +1220,13 @@ unsigned int Input::count(int button) {
return p->repeatCount;
}
unsigned long long Input::repeatTime(int button) {
if (button != p->repeating)
return 0;
return shState->runTime() - p->repeatTime;
}
bool Input::isPressedEx(int code, bool isVKey)
{
return p->getStateRaw(code, isVKey).pressed;
@ -1239,6 +1263,19 @@ unsigned int Input::repeatcount(int code, bool isVKey) {
return p->rawRepeatCount;
}
unsigned long long Input::repeatTimeEx(int code, bool isVKey) {
int c = code;
if (isVKey) {
try { c = vKeyToScancode[code]; }
catch (...) { return 0; }
}
if (c != p->rawRepeating)
return 0;
return shState->runTime() - p->rawRepeatTime;
}
int Input::dir4Value()
{
return p->dir4Data.active;

View file

@ -55,6 +55,7 @@ public:
void recalcRepeat(unsigned int fps);
unsigned long long getDelta();
void update();
std::vector<std::string> getBindings(ButtonCode code);
@ -64,11 +65,13 @@ public:
bool isRepeated(int button);
bool isReleased(int button);
unsigned int count(int button);
unsigned long long repeatTime(int button);
bool isPressedEx(int code, bool isVKey);
bool isTriggeredEx(int code, bool isVKey);
bool isRepeatedEx(int code, bool isVKey);
bool isReleasedEx(int code, bool isVKey);
unsigned int repeatcount(int code, bool isVKey);
unsigned long long repeatTimeEx(int code, bool isVKey);
int dir4Value();
int dir8Value();

View file

@ -41,6 +41,7 @@
#include <unistd.h>
#include <stdio.h>
#include <string>
#include <chrono>
SharedState *SharedState::instance = 0;
int SharedState::rgssVersion = 0;
@ -97,6 +98,8 @@ struct SharedStatePrivate
Quad gpQuad;
unsigned int stampCounter;
std::chrono::time_point<std::chrono::high_resolution_clock> startupTime;
SharedStatePrivate(RGSSThreadData *threadData)
: bindingData(0),
@ -113,6 +116,9 @@ struct SharedStatePrivate
fontState(threadData->config),
stampCounter(0)
{
startupTime = std::chrono::high_resolution_clock::now();
/* Shaders have been compiled in ShaderSet's constructor */
if (gl.ReleaseShaderCompiler)
gl.ReleaseShaderCompiler();
@ -357,6 +363,12 @@ Font &SharedState::defaultFont() const
return *p->defaultFont;
}
unsigned long long SharedState::runTime() {
if (!p) return 0;
const auto now = std::chrono::high_resolution_clock::now();
return std::chrono::duration_cast<std::chrono::microseconds>(now - p->startupTime).count();
}
unsigned int SharedState::genTimeStamp()
{
return p->stampCounter++;

View file

@ -84,6 +84,9 @@ struct SharedState
sigc::signal<void> prepareDraw;
unsigned int genTimeStamp();
// Returns time since SharedState was constructed in microseconds
unsigned long long runTime();
/* Returns global quad IBO, and ensures it has indices
* for at least minSize quads */