Merge branch 'main' into faster-scene-transitions

This commit is contained in:
tomtee
2026-09-17 17:31:40 +00:00
committed by GitHub
13 changed files with 428 additions and 214 deletions
-3
View File
@@ -107,9 +107,6 @@ public:
/* 0x115 */ u8 mDPDPoint;
/* 0x116 */ u8 field_0x116;
/* 0x117 */ u8 field_0x117;
#if TARGET_PC
bool mPresenting;
#endif
}; // Size: 0x118
#endif /* MSG_SCRN_D_MSG_SCRN_3SELECT_H */
-6
View File
@@ -119,12 +119,6 @@ public:
/* 0x3E0 */ u8 field_0x3E0;
/* 0x3E1 */ u8 mTimerVisible;
/* 0x3E2 */ u8 field_0x3e2;
#if TARGET_PC
bool mPresentStep = false;
bool mPresentOpening = false;
bool mPresentClosing = false;
bool mPresentTimerSlide = false;
#endif
};
class dTimer_c : public msg_class {
+8
View File
@@ -509,6 +509,10 @@ body.animate-in .intro-item {
text-align: right;
}
#menu-list button.mod-update-link {
justify-content: flex-end;
}
body.mirrored #menu-list {
align-items: flex-start;
}
@@ -517,6 +521,10 @@ body.animate-in .intro-item {
text-align: left;
}
body.mirrored #menu-list button.mod-update-link {
justify-content: flex-start;
}
eyebrow {
display: none;
}
+20 -7
View File
@@ -333,21 +333,24 @@ select-button:disabled {
cursor: default;
}
select-button key,
select-button value {
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
select-button key {
font-family: var(--font-family-heading);
font-weight: bold;
font-size: var(--font-size-xl);
text-transform: uppercase;
flex: 0 0 auto;
white-space: nowrap;
flex: 0 1 auto;
}
select-button value {
flex: 1 1 auto;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1 0 20%;
text-align: right;
font-size: var(--font-size-2xl);
}
@@ -361,6 +364,16 @@ select-button input {
font-size: var(--font-size-2xl);
}
select-button icon {
display: none;
flex: 0 0 auto;
}
select-button.has-icon icon,
select-button.group-button icon {
display: inline-block;
}
select-button.group-button icon {
flex: 0 0 24dp;
margin-left: auto;
+1 -1
View File
@@ -914,7 +914,7 @@ void jmessage_tReference::addCharAlpha() {
}
void jmessage_tReference::addCharAllAlphaRate() {
dusk::vdt::advance_toward_frame(mCharAllAlphaRate, 1.0f, mAddCharAllAlphaRate);
mCharAllAlphaRate = std::min(mCharAllAlphaRate + mAddCharAllAlphaRate, 1.0f);
}
#endif
+94 -53
View File
@@ -24,10 +24,9 @@
#include "f_op/f_op_msg_mng.h"
#include <cstdio>
#include <cstring>
#include "JSystem/JKernel/JKRExpHeap.h"
#include "m_Do/m_Do_controller_pad.h"
#include "m_Do/m_Do_lib.h"
#include "JSystem/JKernel/JKRExpHeap.h"
#if TARGET_PC
#include "dusk/interp/user_interface.h"
@@ -39,9 +38,20 @@
#include "dusk/settings.h"
#include "dusk/version.hpp"
#include <absl/container/flat_hash_map.h>
#include <algorithm>
#include <array>
#include <vector>
namespace {
struct MessageAnimation {
int phase = -1;
dusk::vdt::FrameAnimation frame, alpha;
};
absl::flat_hash_map<const dMsgObject_c*, MessageAnimation> sMessageAnimations;
} // namespace
#endif
static void dMsgObject_addFundRaising(s16 param_0);
@@ -321,6 +331,7 @@ dMsgObject_HIO_c::dMsgObject_HIO_c() {
int dMsgObject_c::_create(msg_class* param_1) {
#if TARGET_PC
sMessageAnimations.erase(this);
if (dusk::version::isRegionJpn())
g_MsgObject_HIO_c.mBoxTalkScaleX = 1.1f;
else
@@ -572,12 +583,33 @@ int dMsgObject_c::_draw() {
}
#if TARGET_PC
static void startAnimation(dMsgObject_c& message, int phase, f32 from, f32 target) {
auto& animations = sMessageAnimations[&message];
auto& animation = animations.frame;
if (animations.phase != phase) {
animation.start(from, target);
} else {
animation.approach(from, target);
}
animations.phase = phase;
}
void dMsgObject_c::presentAnims() {
if (mpScrnDraw == NULL || mpOutFont == NULL) {
if (mpScrnDraw == NULL || mpOutFont == NULL || !dusk::game_clock::g_frameTiming.interpolating) {
return;
}
const auto found = sMessageAnimations.find(this);
if (found == sMessageAnimations.end()) {
return;
}
auto& animations = found->second;
if (animations.phase < 0) {
return;
}
const u16 status = getStatusLocal();
const u16 status = animations.phase;
auto& animation = animations.frame;
const f32 frame = animation.advance(getStatusLocal() == animations.phase ? field_0x16a : animation.value());
f32 target = 0.0f;
if (status == 2) {
if (isPlaceMessage() || isStaffMessage()) {
@@ -590,33 +622,19 @@ void dMsgObject_c::presentAnims() {
} else {
target = g_MsgObject_HIO_c.mBoxAppearFrame;
}
dusk::vdt::advance_toward_frame(field_0x16a, target, 1.0f);
const f32 ratio = dusk::vdt::clamped_fraction(frame, target);
mpScrnDraw->fukiAlpha(ratio);
mpOutFont->setAlphaRatio(ratio);
if (isKanbanMessage() || isPlaceMessage() || isStaffMessage() || isBossMessage()) {
f32 ratio = dusk::vdt::clamped_fraction(field_0x16a, target);
mpScrnDraw->fukiScale(ratio);
mpScrnDraw->fukiAlpha(ratio);
mpOutFont->setAlphaRatio(ratio);
} else if (isBookMessage()) {
if (field_0x16a <= g_MsgObject_HIO_c.mBoxAppearFrame) {
f32 ratio = dusk::vdt::clamped_fraction(field_0x16a, g_MsgObject_HIO_c.mBoxAppearFrame);
mpScrnDraw->fukiAlpha(ratio);
mpOutFont->setAlphaRatio(ratio);
} else {
mpScrnDraw->fukiAlpha(1.0f);
mpOutFont->setAlphaRatio(1.0f);
}
s16 waitEnd = g_MsgObject_HIO_c.mBoxAppearFrame + g_MsgObject_HIO_c.mWaitFrame;
if (field_0x16a >= waitEnd &&
field_0x16a <= waitEnd + g_MsgObject_HIO_c.mLightAppearFrame)
{
f32 scale = dusk::vdt::clamped_fraction(field_0x16a - waitEnd, g_MsgObject_HIO_c.mLightAppearFrame);
if (frame >= waitEnd && frame <= waitEnd + g_MsgObject_HIO_c.mLightAppearFrame) {
f32 scale = dusk::vdt::clamped_fraction(frame - waitEnd, g_MsgObject_HIO_c.mLightAppearFrame);
mpScrnDraw->fukiScale(scale);
}
} else {
f32 ratio = dusk::vdt::clamped_fraction(field_0x16a, target);
mpScrnDraw->fukiScale(1.0f);
mpScrnDraw->fukiAlpha(ratio);
mpOutFont->setAlphaRatio(ratio);
}
} else if (status == 17) {
if (isKanbanMessage() || isBookMessage()) {
@@ -628,33 +646,27 @@ void dMsgObject_c::presentAnims() {
} else {
target = 5.0f;
}
dusk::vdt::advance_toward_frame(field_0x16a, target, 1.0f);
f32 ratio = dusk::vdt::clamped_fraction(field_0x16a, target);
f32 ratio = dusk::vdt::clamped_fraction(frame, target);
mpScrnDraw->fukiAlpha(1.0f - ratio);
if (isBookMessage()) {
mpScrnDraw->fukiScale(1.0f - ratio);
}
mpOutFont->setAlphaRatio(1.0f - ratio);
} else if (status == 6) {
if (isBookMessage() && field_0x16a > 0) {
dusk::vdt::advance_toward_frame(field_0x16a, 0.0f, 1.0f);
f32 alpha = (10 - field_0x16a) / 10.0f;
if (isBookMessage() && frame > 0) {
f32 alpha = (10 - frame) / 10.0f;
mpScrnDraw->fontAlpha(alpha);
mpOutFont->setAlphaRatio(alpha);
}
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
if (pRef->getCharAllAlphaRate() < 1.0f) {
pRef->addCharAllAlphaRate();
f32 alpha = pRef->getCharAllAlphaRate();
f32 alpha = animations.alpha.advance(pRef->getCharAllAlphaRate());
mpScrnDraw->setCharAlphaRate(alpha);
mpOutFont->setAlphaRatio(alpha);
}
} else if (status == 5 && isBookMessage() &&
(isSend() || field_0x16a > 0))
{
dusk::vdt::advance_toward_frame(field_0x16a, 10.0f, 1.0f);
if (field_0x16a <= 10) {
f32 alpha = (10 - field_0x16a) / 10.0f;
} else if (status == 5 && isBookMessage() && (field_0x199 || frame > 0)) {
if (frame <= 10) {
f32 alpha = (10 - frame) / 10.0f;
mpScrnDraw->fontAlpha(alpha);
mpOutFont->setAlphaRatio(alpha);
}
@@ -663,6 +675,7 @@ void dMsgObject_c::presentAnims() {
#endif
int dMsgObject_c::_delete() {
IF_DUSK(sMessageAnimations.erase(this));
mpResCont->destroyResource_all();
if (mpScrnDraw != NULL) {
JKR_DELETE(mpScrnDraw);
@@ -1052,9 +1065,16 @@ void dMsgObject_c::waitProc() {
}
void dMsgObject_c::openProc() {
#if TARGET_PC
auto& animations = sMessageAnimations[this];
if (field_0x16a == 0) {
animations.phase = -1;
animations.alpha = {};
}
#endif
if (isMidonaMessage()) {
bool uVar12 = 0;
if (DUSK_IF_ELSE(!mpScrnDraw->isSelectAnimeActive(), field_0x16a == 0)) {
if (field_0x16a == 0) {
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
field_0x1a3 = 0;
if (mpRefer->getMsgID() == 0x7fa) {
@@ -1078,7 +1098,7 @@ void dMsgObject_c::openProc() {
field_0x16a = 9;
}
if (mpRefer->getMsgID() == 0x7fa) {
mpScrnDraw->selectAnimeMove(2, getSelectCursorPosLocal(), uVar12);
mpScrnDraw->selectAnimeMove(DUSK_IF_ELSE(3, 2), getSelectCursorPosLocal(), uVar12);
} else {
if (getSelectCursorPosLocal() != 0xff) {
mpScrnDraw->selectAnimeMove(2, getSelectCursorPosLocal() + 1, uVar12);
@@ -1088,7 +1108,7 @@ void dMsgObject_c::openProc() {
}
}
}
IF_NOT_DUSK(field_0x16a++);
field_0x16a++;
s16 sVar7;
if (isKanbanMessage()) {
sVar7 = g_MsgObject_HIO_c.mBoxAppearFrame;
@@ -1134,7 +1154,9 @@ void dMsgObject_c::openProc() {
}
mpRenProc->setTextInitPos(mpScrnDraw->getTextBoxPosX(), mpScrnDraw->getTextBoxPosY());
mpRenProc->setTextScale(mpScrnDraw->getTextBoxScaleX(), mpScrnDraw->getTextBoxScaleY());
IF_DUSK(startAnimation(*this, 2, field_0x16a - 1.0f, sVar7));
if (field_0x16a >= sVar7) {
IF_DUSK(animations.frame.finish(field_0x16a));
mpScrnDraw->fukiTrans(0.0f, 0.0f);
for (int i = 0; i < 3; i++) {
mpRenProc->setSelTextInitPos(i, mpScrnDraw->getSelTextBoxPosX(i),
@@ -1154,9 +1176,16 @@ void dMsgObject_c::openProc() {
}
void dMsgObject_c::outnowProc() {
IF_DUSK(auto& animations = sMessageAnimations[this]);
mpRefer->shiftCharCountBuffer();
if (isBookMessage() && field_0x16a DUSK_IF_ELSE(>, !=) 0) {
IF_NOT_DUSK(field_0x16a--);
field_0x16a--;
#if TARGET_PC
startAnimation(*this, 6, field_0x16a + 1.0f, 0.0f);
if (field_0x16a == 0) {
animations.frame.finish(0.0f);
}
#endif
f32 alpha = (10 - field_0x16a) / 10.0f;
mpScrnDraw->fontAlpha(alpha);
mpOutFont->setAlphaRatio(alpha);
@@ -1167,12 +1196,24 @@ void dMsgObject_c::outnowProc() {
jmessage_tReference* pRef =
(jmessage_tReference*)mpRenProc->getReference();
if (pRef->getCharAllAlphaRate() < 1.0f) {
IF_DUSK(const f32 before = pRef->getCharAllAlphaRate());
if (mDoCPd_c::getTrigA(0)) {
pRef->setCharAllAlphaRate(1.0f);
} else {
IF_NOT_DUSK(pRef->addCharAllAlphaRate());
pRef->addCharAllAlphaRate();
}
f32 alpha = pRef->getCharAllAlphaRate();
#if TARGET_PC
if (animations.phase != 6) {
animations.frame.finish(field_0x16a);
}
animations.phase = 6;
if (alpha >= 1.0f) {
animations.alpha.finish(alpha);
} else {
animations.alpha.approach(before, 1.0f, alpha - before);
}
#endif
mpScrnDraw->setCharAlphaRate(alpha);
mpOutFont->setAlphaRatio(alpha);
} else if (mpRefer->isLightEnd()) {
@@ -1220,17 +1261,20 @@ void dMsgObject_c::outnowProc() {
}
void dMsgObject_c::outwaitProc() {
IF_DUSK(auto& animations = sMessageAnimations[this]);
jmessage_tReference* pRef =
(jmessage_tReference*)mpRenProc->getReference();
mpScrnDraw->arwAnimeMove();
if (isBookMessage()) {
if (isSend() || field_0x16a DUSK_IF_ELSE(>, !=) 0) {
IF_NOT_DUSK(field_0x16a++);
field_0x16a++;
IF_DUSK(startAnimation(*this, 5, field_0x16a - 1.0f, 10.0f));
if (field_0x16a <= 10) {
f32 alpha = (10 - field_0x16a) / 10.0f;
mpScrnDraw->fontAlpha(alpha);
mpOutFont->setAlphaRatio(alpha);
if (field_0x16a >= 10) {
IF_DUSK(animations.frame.finish(10.0f));
field_0x172++;
mpRefer->setPageNum(field_0x172);
mpCtrl->render_synchronize();
@@ -1323,11 +1367,7 @@ void dMsgObject_c::selectProc() {
pRef->setSelectPos(pointerChoice);
}
#endif
if (mDoCPd_c::getTrigA(0)
#if TARGET_PC
|| pointerConfirm
#endif
) {
if (mDoCPd_c::getTrigA(0) IF_DUSK(|| pointerConfirm)) {
if (getSelectCursorPosLocal() != 0xff) {
field_0x1a3 = 1;
}
@@ -1349,15 +1389,13 @@ void dMsgObject_c::selectProc() {
}
field_0x1a3 = 2;
}
#ifndef TARGET_PC
jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference();
#endif
IF_NOT_DUSK(jmessage_tReference* pRef = (jmessage_tReference*)mpRenProc->getReference());
if (getStatusLocal() == 8) {
if (isMidonaMessage() && field_0x1a3 != 0) {
if (field_0x1a3 == 2 && getSelectCancelPos() == 3) {
iVar8 = true;
} else {
while (!iVar8) {
IF_NOT_DUSK(while (!iVar8)) {
if (getSelectCursorPosLocal() != 0xff) {
iVar8 =
mpScrnDraw->selectAnimeMove(2, getSelectCursorPosLocal() + 1, uVar7);
@@ -1381,7 +1419,7 @@ void dMsgObject_c::selectProc() {
if (field_0x1a3 == 2 && getSelectCancelPos() == 4) {
iVar8 = true;
} else {
while (!iVar8) {
IF_NOT_DUSK(while (!iVar8)) {
iVar8 = mpScrnDraw->selectAnimeMove(3, getSelectCursorPosLocal(), uVar7);
}
}
@@ -1506,7 +1544,8 @@ void dMsgObject_c::finishProc() {
}
void dMsgObject_c::endProc() {
IF_NOT_DUSK(field_0x16a++);
field_0x16a++;
IF_DUSK(auto& animations = sMessageAnimations[this]);
s16 sVar4 = 5;
if (isKanbanMessage() || isBookMessage()) {
sVar4 = g_MsgObject_HIO_c.field_0x304;
@@ -1515,6 +1554,7 @@ void dMsgObject_c::endProc() {
} else if (isBossMessage()) {
sVar4 = g_MsgObject_HIO_c.mBossNameFadeOut;
}
IF_DUSK(startAnimation(*this, 17, field_0x16a - 1.0f, sVar4));
f32 dVar6 = (f32)field_0x16a / sVar4;
mpScrnDraw->fukiAlpha(1.0f - dVar6);
if (isBookMessage()) {
@@ -1522,6 +1562,7 @@ void dMsgObject_c::endProc() {
}
mpOutFont->setAlphaRatio(1.0f - dVar6);
if (field_0x16a >= sVar4) {
IF_DUSK(animations.frame.finish(field_0x16a));
mpScrnDraw->arwAnimeInit();
mpScrnDraw->dotAnimeInit();
if (mNoDemoFlag && !field_0x4d4) {
+192 -105
View File
@@ -21,7 +21,24 @@
#include "dusk/menu_pointer.h"
#include "dusk/version.hpp"
#include "d/d_msg_scrn_talk.h"
#include "JSystem/J3DGraphBase/J3DTransform.h"
#include <absl/container/flat_hash_map.h>
namespace {
struct SelectionAnimation {
dusk::vdt::FrameAnimation bck[3], bpk, btk;
f32 paneFrames[3] = {-1.0f, -1.0f, -1.0f};
f32 scaleFrames[3] = {};
f32 appliedFrames[3] = {-1.0f, -1.0f, -1.0f};
};
absl::flat_hash_map<const dMsgScrn3Select_c*, SelectionAnimation> sSelectionAnimations;
void selectTransform(dMsgScrn3Select_c& screen, int selection, bool preserveScale, f32 step = 0.0f, f32 target = 0.0f);
bool hit_choice_pane(CPaneMgr* pane, f32 padding) {
return pane != NULL && pane->getPanePtr() != NULL && pane->getPanePtr()->isVisible() &&
dusk::menu_pointer::hit_pane(pane, padding);
@@ -29,6 +46,13 @@ bool hit_choice_pane(CPaneMgr* pane, f32 padding) {
} // namespace
#endif
#define PROC_OPEN2_BCK_START 190.0f
#define PROC_OPEN2_BCK_END 199.0f
#define PROC_CHANGE_BCK_START_A 300.0f
#define PROC_CHANGE_BCK_START_B 400.0f
#define PROC_CHANGE_BCK_END_A 303.0f
#define PROC_CHANGE_BCK_END_B 403.0f
typedef void (dMsgScrn3Select_c::*processFn)();
DUSK_GAME_DATA processFn process[] = {
&dMsgScrn3Select_c::open1Proc, &dMsgScrn3Select_c::open2Proc, &dMsgScrn3Select_c::waitProc,
@@ -36,6 +60,7 @@ DUSK_GAME_DATA processFn process[] = {
};
dMsgScrn3Select_c::dMsgScrn3Select_c() {
IF_DUSK(sSelectionAnimations.erase(this));
static u64 const tag_name[3][12] = {
// A
'a_n', 'a_g', 'a_gr', 'a_m', MULTI_CHAR('w_yes_00'), MULTI_CHAR('w_yes_01'), MULTI_CHAR('w_yes_02'), MULTI_CHAR('w_yes_03'), MULTI_CHAR('w_yes_04'),
@@ -62,7 +87,7 @@ dMsgScrn3Select_c::dMsgScrn3Select_c() {
mpAnmBck = (J2DAnmTransform*)J2DAnmLoaderDataBase::load(
JKRGetNameResource("zelda_window_3menu.bck", dComIfGp_getMsgArchive(0)));
mBckFrame = 0.0f;
mBckFrame = 190.0f;
mBckFrame = PROC_OPEN2_BCK_START;
mOffsetX = 0.0f;
mpAnmBpk = (J2DAnmColorKey*)J2DAnmLoaderDataBase::load(
@@ -316,12 +341,12 @@ dMsgScrn3Select_c::dMsgScrn3Select_c() {
mDPDPoint = 0xFF;
field_0x116 = 0xFF;
field_0x117 = 0;
IF_DUSK(mPresenting = false);
mSelMsgInactiveCol.set(0xFF, 0xFF, 0xFF, 0xFF);
}
dMsgScrn3Select_c::~dMsgScrn3Select_c() {
IF_DUSK(sSelectionAnimations.erase(this));
JKR_DELETE(mpScreen);
mpScreen = NULL;
@@ -445,15 +470,47 @@ void dMsgScrn3Select_c::translate(f32 i_x, f32 i_y) {
#if TARGET_PC
void dMsgScrn3Select_c::presentAnims() {
if (mProcess >= PROC_MAX_e) {
const auto found = sSelectionAnimations.find(this);
if (found == sSelectionAnimations.end()) {
return;
}
mPresenting = true;
if (mProcess == PROC_OPEN2_e || mProcess == PROC_CHANGE_e || mProcess == PROC_CLOSE_e) {
(this->*process[mProcess])();
auto& animations = found->second;
if (animations.paneFrames[0] < 0.0f ||
(mProcess == PROC_MAX_e && animations.appliedFrames[0] == animations.paneFrames[0]))
{
return;
}
dusk::vdt::present_looping(mBpkFrame, mpAnmBpk, 1.0f);
dusk::vdt::present_looping(mBtkFrame, mpAnmBtk, 1.0f);
const u8 updates = field_0x114;
field_0x114 = 0;
for (int i = 0; i < 3; ++i) {
auto* pane = mpSel_c[i]->getPanePtr();
const f32 frame = animations.bck[i].advance(animations.paneFrames[i]);
if (frame == animations.appliedFrames[i]) {
continue;
}
animations.appliedFrames[i] = frame;
mpAnmBck->setFrame(frame);
pane->setAnimation(mpAnmBck);
pane->animationTransform();
pane->setAnimation((J2DAnmTransform*)nullptr);
if (pane->field_0x4 != 0xFFFF) {
J3DTransformInfo layout;
if (animations.scaleFrames[i] >= 0.0f) {
mpAnmBck->setFrame(animations.scaleFrames[i]);
mpAnmBck->getTransform(pane->field_0x4, &layout);
pane->scale(layout.mScale.x, layout.mScale.z);
}
if (mProcess == PROC_OPEN2_e && mBckFrame == PROC_OPEN2_BCK_START) {
mpAnmBck->setFrame(PROC_OPEN2_BCK_START);
mpAnmBck->getTransform(pane->field_0x4, &layout);
pane->translate(layout.mTranslate.x, pane->getTranslateY());
}
}
onAnimeUpdate(i);
}
mpAnmBpk->setFrame(animations.bpk.advance(mBpkFrame));
mpAnmBtk->setFrame(animations.btk.advance(mBtkFrame));
mpScreen->animation();
for (int i = 0; i < 3; i++) {
@@ -467,7 +524,7 @@ void dMsgScrn3Select_c::presentAnims() {
}
selectTrans();
mPresenting = false;
field_0x114 = updates;
}
#endif
@@ -518,6 +575,10 @@ void dMsgScrn3Select_c::draw(f32 i_xPos, f32 i_yPos) {
}
void dMsgScrn3Select_c::selAnimeInit(u8 i_selNum, u8 i_selNo, u8 param_2, f32 i_width, u8 param_4) {
#if TARGET_PC
auto& animations = sSelectionAnimations[this];
animations = {};
#endif
mSelNo = i_selNo;
field_0x110 = i_selNo;
mSelNum = i_selNum;
@@ -569,11 +630,13 @@ void dMsgScrn3Select_c::selAnimeInit(u8 i_selNum, u8 i_selNo, u8 param_2, f32 i_
break;
}
mBckFrame = 190.0f;
mBckFrame = PROC_OPEN2_BCK_START;
IF_DUSK(mProcess = PROC_OPEN1_e);
for (int i = 0; i < 3; i++) {
selectAnimeTransform(i);
}
IF_DUSK(presentAnims());
selectScale();
selectTrans();
@@ -595,23 +658,46 @@ void dMsgScrn3Select_c::selAnimeInit(u8 i_selNum, u8 i_selNo, u8 param_2, f32 i_
}
mProcess = PROC_OPEN1_e;
#if TARGET_PC
animations.bpk.start(mBpkFrame, 0.0f, 1.0f, mpAnmBpk->getFrameMax());
animations.btk.start(mBtkFrame, 0.0f, 1.0f, mpAnmBtk->getFrameMax());
#endif
}
bool dMsgScrn3Select_c::selAnimeMove(u8 i_selNum, u8 param_1, bool param_2) {
IF_DUSK(auto& animations = sSelectionAnimations[this]);
field_0x110 = param_1;
mSelNum = i_selNum;
field_0x114 = 0;
field_0x108 = param_2;
#if TARGET_PC
pointerMove();
dMsgObject_c* msg = dMsgObject_getMsgObjectClass();
if (mProcess >= PROC_MAX_e) {
return false;
}
#endif
const bool midnaPending = msg != NULL && msg->isMidonaMessage() && msg->field_0x1a3 != 0 &&
msg->mpScrnDraw != NULL &&
static_cast<dMsgScrnTalk_c*>(msg->mpScrnDraw)->mpSelect_c == this;
if (!midnaPending) {
pointerMove();
}
const bool finishingMidna = midnaPending && (msg->getStatusLocal() == 8 || msg->getStatusLocal() == 9);
do {
(this->*process[mProcess])();
mBpkFrame = std::fmod(mBpkFrame + 1.0f, mpAnmBpk->getFrameMax());
mBtkFrame = std::fmod(mBtkFrame + 1.0f, mpAnmBtk->getFrameMax());
} while (finishingMidna && mProcess != PROC_SELECT_e && mProcess < PROC_MAX_e);
if (finishingMidna) {
for (int i = 0; i < 3; ++i) {
animations.bck[i].finish(animations.paneFrames[i]);
}
animations.bpk.start(mBpkFrame, 0.0f, 1.0f, mpAnmBpk->getFrameMax());
animations.btk.start(mBtkFrame, 0.0f, 1.0f, mpAnmBtk->getFrameMax());
}
presentAnims();
#else
(this->*process[mProcess])();
#if !TARGET_PC
mBpkFrame++;
if (mBpkFrame >= mpAnmBpk->getFrameMax()) {
mBpkFrame -= mpAnmBpk->getFrameMax();
@@ -708,14 +794,18 @@ bool dMsgScrn3Select_c::selAnimeEnd() {
field_0x114 = 0;
if (mProcess != PROC_CLOSE_e) {
mBckFrame = 199.0f;
mBckFrame = PROC_OPEN2_BCK_END;
for (int i = 0; i < 3; i++) {
#if TARGET_PC
selectTransform(*this, i, true);
#else
f32 scale_x = mpSel_c[i]->getPanePtr()->getScaleX();
f32 scale_y = mpSel_c[i]->getPanePtr()->getScaleY();
selectAnimeTransform(i);
mpSel_c[i]->getPanePtr()->scale(scale_x, scale_y);
#endif
}
mProcess = PROC_CLOSE_e;
@@ -724,21 +814,22 @@ bool dMsgScrn3Select_c::selAnimeEnd() {
(this->*process[mProcess])();
#if !TARGET_PC
mBpkFrame++;
if (mBpkFrame >= mpAnmBpk->getFrameMax()) {
mBpkFrame -= mpAnmBpk->getFrameMax();
}
mpAnmBpk->setFrame(mBpkFrame);
IF_NOT_DUSK(mpAnmBpk->setFrame(mBpkFrame));
mBtkFrame++;
if (mBtkFrame >= mpAnmBtk->getFrameMax()) {
mBtkFrame -= mpAnmBtk->getFrameMax();
}
#if TARGET_PC
presentAnims();
#else
mpAnmBtk->setFrame(mBtkFrame);
mpScreen->animation();
#endif
for (int i = 0; i < 3; i++) {
if (i == mSelNo) {
@@ -751,6 +842,7 @@ bool dMsgScrn3Select_c::selAnimeEnd() {
}
selectTrans();
#endif
return mProcess == PROC_MAX_e ? TRUE : FALSE;
}
@@ -801,30 +893,28 @@ void dMsgScrn3Select_c::open1Proc() {
mBckFrame = sel_anm_frame[mSelNo];
for (int i = 0; i < 3; i++) {
#if TARGET_PC
selectAnimeTransform(i);
#else
f32 x = mpSel_c[i]->getPosX();
selectAnimeTransform(i);
mpSel_c[i]->move(x, mpSel_c[i]->getPosY());
#endif
}
}
mBckFrame = 190.0f;
mBckFrame = PROC_OPEN2_BCK_START;
mProcess = PROC_OPEN2_e;
}
void dMsgScrn3Select_c::open2Proc() {
f32 sel_anm_frame[3] = {204.0f, 304.0f, 404.0f};
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 199.0f, 1.0f);
}
#else
mBckFrame++;
#endif
mpSelectCursor->setAlphaRate(1.0f);
if (mBckFrame >= 199.0f) {
if (mBckFrame >= PROC_OPEN2_BCK_END) {
if (mSelNo != 0xFF) {
mBckFrame = sel_anm_frame[mSelNo];
}
@@ -834,11 +924,15 @@ void dMsgScrn3Select_c::open2Proc() {
}
for (int i = 0; i < 3; i++) {
#if TARGET_PC
selectTransform(*this, i, true, mProcess == PROC_OPEN2_e ? 1.0f : 0.0f, PROC_OPEN2_BCK_END);
#else
f32 scale_x = mpSel_c[i]->getPanePtr()->getScaleX();
f32 scale_y = mpSel_c[i]->getPanePtr()->getScaleY();
selectAnimeTransform(i);
mpSel_c[i]->getPanePtr()->scale(scale_x, scale_y);
#endif
}
}
@@ -858,56 +952,56 @@ void dMsgScrn3Select_c::selectProc() {
switch (mLastSelNo) {
case 0:
if (mSelNo == 1) {
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
selectAnimeTransform(1);
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
selectAnimeTransform(0);
} else if (mSelNo == 2) {
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
selectAnimeTransform(2);
mBckFrame = 400.0f;
mBckFrame = PROC_CHANGE_BCK_START_B;
selectAnimeTransform(0);
}
break;
case 1:
if (mSelNo == 0) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
selectAnimeTransform(0);
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
selectAnimeTransform(1);
} else if (mSelNo == 2) {
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
selectAnimeTransform(2);
mBckFrame = 400.0f;
mBckFrame = PROC_CHANGE_BCK_START_B;
selectAnimeTransform(1);
}
break;
case 2:
if (mSelNo == 1) {
mBckFrame = 400.0f;
mBckFrame = PROC_CHANGE_BCK_START_B;
selectAnimeTransform(1);
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
selectAnimeTransform(2);
} else if (mSelNo == 0) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
selectAnimeTransform(0);
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
selectAnimeTransform(2);
}
break;
case 0xFF:
if (mSelNo == 0) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
} else if (mSelNo == 1) {
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
} else if (mSelNo == 2) {
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
}
for (int i = 0; i < 3; i++) {
@@ -928,13 +1022,13 @@ void dMsgScrn3Select_c::selectProc() {
void dMsgScrn3Select_c::changeProc() {
if (mSelNo == 0xFF) {
if (mLastSelNo == 0) {
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
selectAnimeTransform(0);
} else if (mLastSelNo == 1) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
selectAnimeTransform(1);
} else if (mLastSelNo == 2) {
mBckFrame = 400.0f;
mBckFrame = PROC_CHANGE_BCK_START_B;
selectAnimeTransform(2);
}
@@ -944,38 +1038,28 @@ void dMsgScrn3Select_c::changeProc() {
case 0:
if (mSelNo == 1) {
if (field_0x108 != 0) {
mBckFrame = 303.0f;
mBckFrame = PROC_CHANGE_BCK_END_A;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 303.0f, 1.0f);
}
#else
mBckFrame++;
#endif
}
selectAnimeTransform(0);
DUSK_IF_ELSE(selectTransform(*this, 0, false, 1.0f, PROC_CHANGE_BCK_END_A),
selectAnimeTransform(0));
if (mBckFrame >= 303.0f) {
if (mBckFrame >= PROC_CHANGE_BCK_END_A) {
mProcess = PROC_SELECT_e;
}
} else if (mSelNo == 2) {
if (field_0x108 != 0) {
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 403.0f, 1.0f);
}
#else
mBckFrame++;
#endif
}
selectAnimeTransform(0);
DUSK_IF_ELSE(selectTransform(*this, 0, false, 1.0f, PROC_CHANGE_BCK_END_B),
selectAnimeTransform(0));
if (mBckFrame >= 403.0f) {
if (mBckFrame >= PROC_CHANGE_BCK_END_B) {
mProcess = PROC_SELECT_e;
}
}
@@ -983,38 +1067,28 @@ void dMsgScrn3Select_c::changeProc() {
case 1:
if (mSelNo == 0) {
if (field_0x108 != 0) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 300.0f, 1.0f);
}
#else
mBckFrame--;
#endif
}
selectAnimeTransform(1);
DUSK_IF_ELSE(selectTransform(*this, 1, false, -1.0f, PROC_CHANGE_BCK_START_A),
selectAnimeTransform(1));
if (mBckFrame <= 300.0f) {
if (mBckFrame <= PROC_CHANGE_BCK_START_A) {
mProcess = PROC_SELECT_e;
}
} else if (mSelNo == 2) {
if (field_0x108 != 0) {
mBckFrame = 403.0f;
mBckFrame = PROC_CHANGE_BCK_END_B;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 403.0f, 1.0f);
}
#else
mBckFrame++;
#endif
}
selectAnimeTransform(1);
DUSK_IF_ELSE(selectTransform(*this, 1, false, 1.0f, PROC_CHANGE_BCK_END_B),
selectAnimeTransform(1));
if (mBckFrame >= 403.0f) {
if (mBckFrame >= PROC_CHANGE_BCK_END_B) {
mProcess = PROC_SELECT_e;
}
}
@@ -1022,38 +1096,28 @@ void dMsgScrn3Select_c::changeProc() {
case 2:
if (mSelNo == 1) {
if (field_0x108 != 0) {
mBckFrame = 400.0f;
mBckFrame = PROC_CHANGE_BCK_START_B;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 400.0f, 1.0f);
}
#else
mBckFrame--;
#endif
}
selectAnimeTransform(2);
DUSK_IF_ELSE(selectTransform(*this, 2, false, -1.0f, PROC_CHANGE_BCK_START_B),
selectAnimeTransform(2));
if (mBckFrame <= 400.0f) {
if (mBckFrame <= PROC_CHANGE_BCK_START_B) {
mProcess = PROC_SELECT_e;
}
} else if (mSelNo == 0) {
if (field_0x108 != 0) {
mBckFrame = 300.0f;
mBckFrame = PROC_CHANGE_BCK_START_A;
} else {
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 300.0f, 1.0f);
}
#else
mBckFrame--;
#endif
}
selectAnimeTransform(2);
DUSK_IF_ELSE(selectTransform(*this, 2, false, -1.0f, PROC_CHANGE_BCK_START_A),
selectAnimeTransform(2));
if (mBckFrame <= 300.0f) {
if (mBckFrame <= PROC_CHANGE_BCK_START_A) {
mProcess = PROC_SELECT_e;
}
}
@@ -1064,23 +1128,21 @@ void dMsgScrn3Select_c::changeProc() {
void dMsgScrn3Select_c::closeProc() {
mpSelectCursor->setAlphaRate(0.0f);
#if TARGET_PC
if (mPresenting) {
dusk::vdt::advance_toward_frame(mBckFrame, 190.0f, 1.0f);
}
#else
mBckFrame--;
#endif
for (int i = 0; i < 3; i++) {
#if TARGET_PC
selectTransform(*this, i, true, -1.0f, PROC_OPEN2_BCK_START);
#else
f32 scale_x = mpSel_c[i]->getPanePtr()->getScaleX();
f32 scale_y = mpSel_c[i]->getPanePtr()->getScaleY();
selectAnimeTransform(i);
mpSel_c[i]->getPanePtr()->scale(scale_x, scale_y);
#endif
}
if (mBckFrame <= 190.0f) {
if (mBckFrame <= PROC_OPEN2_BCK_START) {
mProcess = PROC_MAX_e;
}
}
@@ -1227,11 +1289,36 @@ void dMsgScrn3Select_c::selectTrans() {
}
}
#if TARGET_PC
namespace {
void selectTransform(dMsgScrn3Select_c& screen, int selection, bool preserveScale, f32 step, f32 target) {
auto& animations = sSelectionAnimations[&screen];
animations.appliedFrames[selection] = -1.0f;
auto& visual = animations.bck[selection];
if (step != 0.0f && screen.mBckFrame != target) {
visual.approach(screen.mBckFrame - step, target);
} else {
visual.finish(screen.mBckFrame);
}
if (!preserveScale) {
animations.scaleFrames[selection] = -1.0f;
} else if (animations.scaleFrames[selection] < 0.0f) {
animations.scaleFrames[selection] = animations.paneFrames[selection];
}
animations.paneFrames[selection] = screen.mBckFrame;
}
} // namespace
#endif
void dMsgScrn3Select_c::selectAnimeTransform(int i_sel) {
#if TARGET_PC
selectTransform(*this, i_sel, false);
#else
mpAnmBck->setFrame(mBckFrame);
mpSel_c[i_sel]->getPanePtr()->setAnimation(mpAnmBck);
mpSel_c[i_sel]->getPanePtr()->animationTransform();
mpSel_c[i_sel]->getPanePtr()->setAnimation((J2DAnmTransform*)NULL);
onAnimeUpdate(i_sel);
#endif
}
+50 -21
View File
@@ -26,6 +26,21 @@
#if TARGET_PC
#include "dusk/interp/user_interface.h"
#include "dusk/version.hpp"
#include <absl/container/flat_hash_map.h>
namespace {
struct TimerAnimation {
dusk::vdt::FrameAnimation close;
bool presenting = false;
bool opening = false;
bool closing = false;
bool slide = false;
};
absl::flat_hash_map<const dDlst_TimerScrnDraw_c*, TimerAnimation> sTimerAnimations;
} // namespace
#endif
static int dTimer_createStart2D(s32 param_0, u16 param_1);
@@ -216,7 +231,7 @@ int dTimer_c::_execute() {
if (m_timer_mode == 3 || m_timer_mode == 4 || m_timer_mode == 6 || m_timer_mode == 5) {
#if TARGET_PC
mp_tm_scrn->mPresentTimerSlide = true;
sTimerAnimations[mp_tm_scrn].slide = true;
#else
f32 pos_y = mp_tm_scrn->getTimerTransY();
if (pos_y < 145.0f) {
@@ -296,6 +311,11 @@ static f32 dummyLiteralOrder2() {
int dTimer_c::_draw() {
if (dComIfGp_isPauseFlag() || dMsgObject_isTalkNowCheck()) {
#if TARGET_PC
if (m_mode == 8 && dusk::game_clock::is_presentation_frame()) {
mp_tm_scrn->presentAnims();
}
#endif
return 1;
}
@@ -483,6 +503,7 @@ bool dTimer_c::isStart() {
}
dDlst_TimerScrnDraw_c::dDlst_TimerScrnDraw_c() {
IF_DUSK(sTimerAnimations.erase(this));
field_0x3e2 = 0;
mHIOType = 0;
field_0x3D8 = 0;
@@ -1121,8 +1142,9 @@ void dDlst_TimerScrnDraw_c::setShowType(u8 i_type) {
void dDlst_TimerScrnDraw_c::anime() {
#if TARGET_PC
if (!mPresentStep) {
mPresentOpening = true;
auto& animations = sTimerAnimations[this];
if (!animations.presenting) {
animations.opening = true;
return;
}
const f32 previousFrame = field_0x3D8;
@@ -1196,18 +1218,22 @@ void dDlst_TimerScrnDraw_c::anime() {
}
BOOL dDlst_TimerScrnDraw_c::closeAnime() {
#if TARGET_PC
if (!mPresentStep) {
mPresentClosing = true;
return field_0x3D8 >= 7.0f;
}
#endif
BOOL var_r31 = false;
DUSK_IF_ELSE(dusk::vdt::advance_toward_frame(field_0x3D8, 7.0f, 1.0f), field_0x3D8++);
#if TARGET_PC
auto& animations = sTimerAnimations[this];
if (!animations.presenting) {
animations.closing = true;
field_0x3D8 = std::min(field_0x3D8 + 1.0f, 7.0f);
animations.close.approach(field_0x3D8 - 1.0f, 7.0f);
}
const f32 frame = animations.presenting ? animations.close.advance(field_0x3D8) : field_0x3D8;
#else
field_0x3D8++;
#endif
if (field_0x3D8 <= 7) {
f32 temp_f31 = acc(7, field_0x3D8, 0);
f32 temp_f30 = acc(7, 7 - field_0x3D8, 0);
if (DUSK_IF_ELSE(frame, field_0x3D8) <= 7) {
f32 temp_f31 = acc(7, DUSK_IF_ELSE(frame, field_0x3D8), 0);
f32 temp_f30 = acc(7, 7 - DUSK_IF_ELSE(frame, field_0x3D8), 0);
f32 temp_f1 = temp_f31 * -50.0f;
if (mpTimeParent != NULL) {
@@ -1355,8 +1381,9 @@ s32 dDlst_TimerScrnDraw_c::createStart(u16 i_messageID) {
#if TARGET_PC
void dDlst_TimerScrnDraw_c::presentAnims() {
mPresentStep = true;
if (mPresentTimerSlide) {
auto& animations = sTimerAnimations[this];
animations.presenting = true;
if (animations.slide) {
dusk::vdt::advance_toward_frame(mTimerTransY, 145.0f, 25.0f);
if (field_0x3e2 != 0 && mHIOType == 0) {
setTimerPos(g_drawHIO.mMiniGame.mTimerPosX_4x3,
@@ -1366,10 +1393,10 @@ void dDlst_TimerScrnDraw_c::presentAnims() {
g_drawHIO.mMiniGame.mTimerPosY[mHIOType]);
}
}
if (mPresentClosing) {
if (animations.closing) {
closeAnime();
} else {
if (mPresentOpening) {
if (animations.opening) {
anime();
}
const bool event = dComIfGp_event_getMode() == 1;
@@ -1381,8 +1408,8 @@ void dDlst_TimerScrnDraw_c::presentAnims() {
const f32 previous = frame;
dusk::vdt::advance_toward_frame(frame, hidden ? 5.0f : 0.0f, 1.0f);
if (ready || frame != previous) {
const f32 rate = timer ? acc(5.0f, 5.0f - frame, 0.0f) :
1.0f - acc(5.0f, frame, 0.0f);
const f32 rate = timer ? acc(5.0f, 5.0f - frame, 0.0f)
: 1.0f - acc(5.0f, frame, 0.0f);
pane->setAlphaRate(mParentAlpha * alpha * rate);
}
pane->alphaAnimeStart(frame);
@@ -1395,7 +1422,7 @@ void dDlst_TimerScrnDraw_c::presentAnims() {
fade(mpImageParent, hideCounter, field_0x3E0 != 0,
g_drawHIO.mMiniGame.mIconAlpha[mHIOType], false);
}
mPresentStep = false;
animations.presenting = false;
}
#endif
@@ -1725,7 +1752,9 @@ u8 dTimer_isReadyFlag() {
return 0;
}
dDlst_TimerScrnDraw_c::~dDlst_TimerScrnDraw_c() {}
dDlst_TimerScrnDraw_c::~dDlst_TimerScrnDraw_c() {
IF_DUSK(sTimerAnimations.erase(this));
}
int dTimer_c::createGetIn(cXyz i_pos) {
return mp_tm_scrn->createGetIn(i_pos);
+10 -16
View File
@@ -4,7 +4,6 @@
#include <algorithm>
#include <chrono>
#include <unordered_map>
namespace dusk::game_clock {
@@ -20,13 +19,11 @@ native_clock::time_point s_previousNativeSample{};
game_clock::time_point s_latestGameSample{};
game_clock::time_point s_currentSnapshotTime{};
game_clock::time_point s_pendingSimTime{};
std::unordered_map<uintptr_t, game_clock::time_point> s_intervalLastSample;
uint64_t s_presentationEpoch = 1;
bool s_timingModeInitialized = false;
bool s_previousSeparatePresentation = false;
bool s_previousInterpolating = false;
bool s_previousTimeStopped = false;
float s_presentationDtSeconds = kUiInitialDt;
constexpr game_clock::duration kSimPeriodDuration =
std::chrono::duration_cast<game_clock::duration>(std::chrono::duration<float>(kSimPeriod));
@@ -39,7 +36,7 @@ float ui_dt() {
}
const float maximumDt = kUiMaximumDt * aurora::time::scale();
return std::clamp(s_presentationDtSeconds, 0.0f, maximumDt);
return std::clamp(g_frameTiming.dt, 0.0f, maximumDt);
}
} // namespace
@@ -86,7 +83,6 @@ const FrameTiming& advance() {
.dt = std::chrono::duration<float>(gameFrameGap).count(),
.presentationEpoch = s_presentationEpoch,
};
s_presentationDtSeconds = out.dt;
const float timeScale = aurora::time::scale();
const bool interpolating =
@@ -169,21 +165,19 @@ float sample_interpolation_step() {
return std::clamp(step, 0.0f, 1.0f);
}
double sample_time() {
const auto now = s_simTickActive ? s_pendingSimTime : game_clock::now();
return std::chrono::duration<double>(now.time_since_epoch()).count();
}
float original_frames() {
return ui_dt() / kSimPeriod;
}
float consume_interval(const void* consumer) {
const auto key = reinterpret_cast<uintptr_t>(consumer);
const auto now = s_simTickActive ? s_pendingSimTime : game_clock::now();
const float timeScale = aurora::time::scale();
float dt = kUiInitialDt * timeScale;
if (const auto it = s_intervalLastSample.find(key); it != s_intervalLastSample.end()) {
dt = std::chrono::duration<float>(now - it->second).count();
const float maximumDt = std::max(kUiMaximumDt * timeScale, kSimPeriod);
dt = std::min(dt, maximumDt);
}
s_intervalLastSample[key] = now;
float consume_interval(double& lastSample) {
const double now = sample_time();
const float dt = std::max(0.0, now - lastSample);
lastSample = now;
return dt;
}
+2 -1
View File
@@ -33,7 +33,8 @@ float sample_interpolation_step();
bool is_sim_frame();
bool is_presentation_frame();
float consume_interval(const void* consumer);
double sample_time();
float consume_interval(double& lastSample);
// Sets the effective simulation rate through the game clock time scale.
void set_sim_rate(float hz);
+49
View File
@@ -15,6 +15,55 @@
namespace dusk::vdt {
class FrameAnimation {
public:
void start(f32 from, f32 target, f32 speed = 1.0f, f32 period = 0.0f) {
mFrame = from;
mTarget = target;
mSpeed = speed;
mPeriod = period;
mTime = game_clock::sample_time();
mEpoch = game_clock::g_frameTiming.presentationEpoch;
}
void approach(f32 from, f32 target, f32 speed = 1.0f) {
if (mTarget != target || std::abs(mSpeed - speed) > 0.000001f || mPeriod != 0.0f ||
mEpoch != game_clock::g_frameTiming.presentationEpoch)
{
start(from, target, speed);
}
}
void finish(f32 frame) { start(frame, frame, 0.0f); }
f32 advance(f32 logicalFrame) {
const f32 frames = game_clock::consume_interval(mTime) / game_clock::kSimPeriod;
if (!game_clock::g_frameTiming.interpolating ||
mEpoch != game_clock::g_frameTiming.presentationEpoch)
{
mFrame = logicalFrame;
mEpoch = game_clock::g_frameTiming.presentationEpoch;
} else if (mPeriod > 0.0f) {
mFrame = std::fmod(mFrame + mSpeed * frames, mPeriod);
} else {
const f32 step = mSpeed * frames;
mFrame = mFrame < mTarget ? std::min(mFrame + step, mTarget)
: std::max(mFrame - step, mTarget);
}
return mFrame;
}
f32 value() const { return mFrame; }
private:
f32 mFrame = 0.0f;
f32 mTarget = 0.0f;
f32 mSpeed = 0.0f;
f32 mPeriod = 0.0f;
double mTime = 0.0;
u64 mEpoch = 0;
};
inline f32 clamped_fraction(f32 timer, f32 duration) {
if (duration <= 0.0f) {
return 1.0f;
+1 -1
View File
@@ -16,7 +16,7 @@ void Component::update() {
}
bool Component::focus() {
if (disabled() || !mRoot->IsVisible(true)) {
if (disabled()) {
return false;
}
// Can we focus self?
+1
View File
@@ -80,6 +80,7 @@ void SelectButton::update_props(Props props) {
if (!props.icon.empty()) {
mIconElem->SetClass(props.icon, true);
}
mRoot->SetClass("has-icon", !props.icon.empty());
}
set_value_label(props.value);
set_modified(props.modified);