Support of IsKeyPressed that only trigger for the frame it is pressed on.

This commit is contained in:
2026-08-09 11:23:56 -04:00
parent 681267f445
commit d52c77a017
16 changed files with 151 additions and 34 deletions
+18 -1
View File
@@ -5,13 +5,16 @@
#include <game.h>
#include <Core/Common/EnumUtils.h>
#include <Core/HAL/Filesystem/Filesystem.h>
#include <Core/HAL/Keyboard/Keyboard.h>
#include <Core/JulietInit.h>
#include <Core/Logging/LogManager.h>
#include <Core/Memory/MemoryArena.h>
#include <Entity/Entity.h>
#include <Entity/EntityManager.h>
#include <Graphics/Camera.h>
#include <imgui.h>
GameState* gGameState = nullptr;
GameState* GetGameState()
@@ -92,5 +95,19 @@ extern "C" JULIET_API void __cdecl GameUpdate(Juliet::GameData* params, [[maybe_
printf("Rock has %d health points\n", rock->Health);
}
// printf("Updating game...\n");
if (IsKeyPressed(ScanCode::F1))
{
gGameState->Mode = static_cast<GameMode>((ToUnderlying(gGameState->Mode) + 1) % 2);
}
if (gGameState->Mode == GameMode::Play)
{
// update game
}
if (gGameState->Mode == GameMode::Debug)
{
ImGui::Begin("Debug");
ImGui::End();
}
}
+8
View File
@@ -10,12 +10,20 @@ struct World
EntityManager* EntityManager;
};
enum class GameMode
{
Play,
Debug
};
struct GameState
{
Juliet::Arena* TotalArena;
World* World;
GameMode Mode = GameMode::Play;
float TotalTime;
int Score;
};
@@ -17,7 +17,7 @@ namespace Juliet
virtual ~IApplication() = default;
virtual void Init(NonNullPtr<Arena> arena) = 0;
virtual void Shutdown() = 0;
virtual void Update() = 0;
virtual void Update(float deltaTime) = 0;
virtual bool IsRunning() = 0;
// Accessors for Engine Systems
@@ -118,4 +118,6 @@ namespace Juliet
// Add an event onto the event queue.
// TODO : support array of events
extern JULIET_API bool AddEvent(SystemEvent& event);
extern void Events_NewFrame(float deltaTime);
} // namespace Juliet
+8 -1
View File
@@ -8,12 +8,18 @@ namespace Juliet
{
using KeyboardID = uint8;
enum class KeyState : bool
enum class KeyPosition : bool
{
Up = false,
Down = true
};
struct KeyState
{
KeyPosition Position;
float Time;
};
struct Key
{
ScanCode ScanCode;
@@ -22,6 +28,7 @@ namespace Juliet
};
extern JULIET_API bool IsKeyDown(ScanCode scanCode);
extern JULIET_API bool IsKeyPressed(ScanCode scanCode);
extern JULIET_API KeyMod GetKeyModState();
extern JULIET_API KeyCode GetKeyCodeFromScanCode(ScanCode scanCode, KeyMod keyModState);
+5
View File
@@ -31,6 +31,11 @@ namespace Juliet
} // namespace Memory
namespace Time
{
uint64 Timestamp();
} // namespace Time
namespace Debug
{
JULIET_API bool IsDebuggerPresent();
@@ -12,6 +12,7 @@
#include <Core/Memory/Utils.h>
// For GET_X_LPARAM, GET_Y_LPARAM.
#include <Core/HAL/OS/OS.h>
#include <windowsx.h>
#ifdef JULIET_ENABLE_IMGUI
@@ -157,7 +158,7 @@ namespace Juliet::Win32
LRESULT returnCode = -1;
// Wait until the window state is created before doing anything
auto* windowState = GetWindowStateFromHandle(handle);
Window32State* windowState = GetWindowStateFromHandle(handle);
if (!windowState)
{
return CallWindowProcA(DefWindowProcA, handle, message, wParam, lParam);
@@ -188,7 +189,7 @@ namespace Juliet::Win32
SendWindowEvent(windowState->Window, EventType::Window_Close_Request);
}
SendKeyboardKey(1, kGlobalKeyboardID, key, KeyState::Down);
SendKeyboardKey(Time::Timestamp(), kGlobalKeyboardID, key, KeyPosition::Down);
returnCode = 0;
break;
@@ -197,7 +198,7 @@ namespace Juliet::Win32
case WM_KEYUP:
{
Key key = GetScanScodeFromWinScanCode(wParam, lParam);
SendKeyboardKey(1, kGlobalKeyboardID, key, KeyState::Up);
SendKeyboardKey(Time::Timestamp(), kGlobalKeyboardID, key, KeyPosition::Up);
returnCode = 0;
break;
+41 -13
View File
@@ -15,14 +15,14 @@ namespace Juliet
KeyMod KeyModState;
} KeyboardState;
bool SendKeyboardKey_Internal(uint64 timestamp, KeyboardID /*ID*/, Key key, KeyState keyState)
bool SendKeyboardKey_Internal(uint64 timestamp, KeyboardID /*ID*/, Key key, KeyPosition keyPosition)
{
Assert(key.KeyCode == KeyCode::Unknown); // At this point Keycode is not yet extracted
auto& keyboardState = KeyboardState; // Needed because MSVC debugger ignores variable in anonymouse namespace
auto type = EventType::None;
const bool isKeyDown = keyState == KeyState::Down;
const bool isKeyDown = keyPosition == KeyPosition::Down;
if (isKeyDown)
{
type = EventType::Key_Down;
@@ -40,21 +40,21 @@ namespace Juliet
// If state didn't change, this is a key repeat
if (isKeyDown)
{
if (currentKeyState == KeyState::Down)
if (currentKeyState.Position == KeyPosition::Down)
{
isKeyRepeat = true;
}
}
else
{
if (currentKeyState == KeyState::Up)
if (currentKeyState.Position == KeyPosition::Up)
{
return false;
}
}
keyboardState.KeyState[ToUnderlying(key.ScanCode)] = keyState;
key.KeyCode = GetKeyCodeFromScanCode(key.ScanCode, keyboardState.KeyModState);
currentKeyState.Position = keyPosition;
key.KeyCode = GetKeyCodeFromScanCode(key.ScanCode, keyboardState.KeyModState);
}
else if (key.Raw == 0)
{
@@ -99,7 +99,7 @@ namespace Juliet
evt.Type = type;
evt.Data.Keyboard.AssociatedKeyboardID = kGlobalKeyboardID;
evt.Data.Keyboard.Key = key;
evt.Data.Keyboard.KeyState = keyState;
evt.Data.Keyboard.KeyState = { keyPosition };
evt.Data.Keyboard.KeyModeState = keyboardState.KeyModState;
bool evtPosted = AddEvent(evt);
@@ -108,14 +108,42 @@ namespace Juliet
}
} // namespace
bool SendKeyboardKey(uint64 timestamp, KeyboardID ID, Key key, KeyState keyState)
bool SendKeyboardKey(uint64 timestamp, KeyboardID ID, Key key, KeyPosition keyPosition)
{
return SendKeyboardKey_Internal(timestamp, ID, key, keyState);
return SendKeyboardKey_Internal(timestamp, ID, key, keyPosition);
}
void UpdateKeyboardstate(float deltaTime)
{
for (KeyState& state : KeyboardState.KeyState)
{
if (state.Position == KeyPosition::Down)
{
if (state.Time < 0.0f)
{
state.Time = 0.0f;
}
else
{
state.Time += deltaTime;
}
}
else
{
state.Time = -1.0f;
}
}
}
bool IsKeyDown(ScanCode scanCode)
{
return KeyboardState.KeyState[ToUnderlying(scanCode)] == KeyState::Down;
return KeyboardState.KeyState[ToUnderlying(scanCode)].Position == KeyPosition::Down;
}
bool IsKeyPressed(ScanCode scanCode)
{
auto& keyState = KeyboardState.KeyState[ToUnderlying(scanCode)];
return keyState.Position == KeyPosition::Down && keyState.Time == 0.0f;
}
KeyMod GetKeyModState()
@@ -129,9 +157,9 @@ namespace Juliet
return GetKeyCodeFromDefaultMapping(scanCode, keyModState);
}
static_assert(sizeof(KeyState) == sizeof(bool));
static_assert(ToUnderlying(KeyState::Down) == true);
static_assert(ToUnderlying(KeyState::Up) == false);
static_assert(sizeof(KeyPosition) == sizeof(bool));
static_assert(ToUnderlying(KeyPosition::Down) == true);
static_assert(ToUnderlying(KeyPosition::Up) == false);
static_assert(sizeof(ScanCode) == sizeof(uint16));
static_assert(ToUnderlying(ScanCode::Count) == 512);
} // namespace Juliet
+2 -1
View File
@@ -5,7 +5,8 @@
namespace Juliet
{
extern bool SendKeyboardKey(uint64 timestamp, KeyboardID ID, Key key, KeyState keyState);
extern bool SendKeyboardKey(uint64 timestamp, KeyboardID ID, Key key, KeyPosition keyPosition);
extern void UpdateKeyboardstate(float deltaTime);
extern const KeyboardID kGlobalKeyboardID;
} // namespace Juliet
@@ -1,6 +1,8 @@
#include <Core/HAL/Display/DisplayDevice.h>
#include <Core/HAL/Event/SystemEvent.h>
#include <Core/HAL/Event/Keyboard_Private.h>
#pragma push_macro("global")
#undef global
@@ -87,4 +89,10 @@ namespace Juliet
return AddEvent_Internal(event);
}
void Events_NewFrame(float deltaTime)
{
UpdateKeyboardstate(deltaTime);
}
} // namespace Juliet
+8
View File
@@ -21,6 +21,14 @@ namespace Juliet
}
} // namespace Memory
namespace Time
{
uint64 Timestamp()
{
return Internal::OS_Timestamp();
}
} // namespace Time
namespace Debug
{
bool IsDebuggerPresent()
+6
View File
@@ -13,6 +13,12 @@ namespace Juliet
{
bool IsDebuggerPresent();
} // namespace Debug::Internal
namespace Time::Internal
{
uint64 OS_Timestamp();
}
namespace Internal
{
int OS_Main(EntryPointFunc entryPointFunc, int argc, wchar_t** argv);
+11
View File
@@ -45,6 +45,17 @@ namespace Juliet
}
} // namespace Memory::Internal
namespace Time::Internal
{
uint64 OS_Timestamp()
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
return (static_cast<uint64>(ft.dwHighDateTime) << 32) + ft.dwLowDateTime;
}
} // namespace Time::Internal
namespace Debug::Internal
{
bool IsDebuggerPresent()
+27 -1
View File
@@ -1,6 +1,7 @@
#include <Engine/Engine.h>
#include <Core/Common/CoreUtils.h>
#include <Core/HAL/Event/SystemEvent.h>
#include <Core/HAL/Filesystem/Filesystem_Private.h>
#include <Core/JulietInit.h>
#include <Core/Logging/LogManager.h>
@@ -18,6 +19,14 @@
#include <imgui.h>
#endif
// TODO Move to os hal for query perf
#ifdef _WIN32
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <Windows.h>
#endif
namespace Juliet
{
#if JULIET_DEBUG
@@ -210,8 +219,25 @@ namespace Juliet
ImGuiRenderer_NewFrame();
#endif
// TODO : Move to os side as it is win32 only
static LARGE_INTEGER frequency = {};
static LARGE_INTEGER lastTime = {};
if (frequency.QuadPart == 0)
{
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&lastTime);
}
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
float deltaTime =
static_cast<float>(currentTime.QuadPart - lastTime.QuadPart) / static_cast<float>(frequency.QuadPart);
lastTime = currentTime;
Events_NewFrame(deltaTime);
// Logic tick
EngineInstance.Application->Update();
EngineInstance.Application->Update(deltaTime);
// Render tick
RenderFrame();
+1 -12
View File
@@ -225,20 +225,9 @@ void JulietApplication::Shutdown()
Log(LogLevel::Message, LogCategory::Tool, "Juliet App shutdown Completed");
}
void JulietApplication::Update()
void JulietApplication::Update(float deltaTime)
{
static LARGE_INTEGER frequency = {};
static LARGE_INTEGER lastTime = {};
if (frequency.QuadPart == 0)
{
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&lastTime);
}
LARGE_INTEGER currentTime;
QueryPerformanceCounter(&currentTime);
float deltaTime = static_cast<float>(currentTime.QuadPart - lastTime.QuadPart) / static_cast<float>(frequency.QuadPart);
lastTime = currentTime;
CameraTime += deltaTime;
+1 -1
View File
@@ -20,7 +20,7 @@ class JulietApplication : public Juliet::IApplication
protected:
void Init(Juliet::NonNullPtr<Juliet::Arena> arena) override;
void Shutdown() override;
void Update() override;
void Update(float deltaTime) override;
bool IsRunning() override;
Juliet::Window* GetPlatformWindow() override { return MainWindow; }