Ajout de Jolt Physics + 1ere version des factory entitecomposants - camera, transform, rigidbody, collider, renderer

This commit is contained in:
Tom Ray
2026-03-22 00:28:03 +01:00
parent 6695d46bcd
commit 48348936a8
1147 changed files with 214331 additions and 353 deletions

View File

@@ -0,0 +1,433 @@
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#include <TestFramework.h>
#include <Application/Application.h>
#include <UI/UIManager.h>
#include <Application/DebugUI.h>
#include <Utils/Log.h>
#include <Utils/CustomMemoryHook.h>
#include <Jolt/Core/Factory.h>
#include <Jolt/RegisterTypes.h>
#include <Renderer/DebugRendererImp.h>
#ifdef JPH_PLATFORM_WINDOWS
#include <crtdbg.h>
#include <Input/Win/KeyboardWin.h>
#include <Input/Win/MouseWin.h>
#include <Window/ApplicationWindowWin.h>
#elif defined(JPH_PLATFORM_LINUX)
#include <Input/Linux/KeyboardLinux.h>
#include <Input/Linux/MouseLinux.h>
#include <Window/ApplicationWindowLinux.h>
#elif defined(JPH_PLATFORM_MACOS)
#include <Input/MacOS/KeyboardMacOS.h>
#include <Input/MacOS/MouseMacOS.h>
#include <Window/ApplicationWindowMacOS.h>
#endif
JPH_GCC_SUPPRESS_WARNING("-Wswitch")
// Constructor
Application::Application(const char *inApplicationName, [[maybe_unused]] const String &inCommandLine) :
mDebugRenderer(nullptr),
mRenderer(nullptr),
mKeyboard(nullptr),
mMouse(nullptr),
mUI(nullptr),
mDebugUI(nullptr)
{
#if defined(JPH_PLATFORM_WINDOWS) && defined(_DEBUG)
// Enable leak detection
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif
// Register trace implementation
Trace = TraceImpl;
#ifdef JPH_ENABLE_ASSERTS
// Register assert failed handler
AssertFailed = [](const char *inExpression, const char *inMessage, const char *inFile, uint inLine)
{
Trace("%s (%d): Assert Failed: %s", inFile, inLine, inMessage != nullptr? inMessage : inExpression);
return true;
};
#endif // JPH_ENABLE_ASSERTS
// Create factory
Factory::sInstance = new Factory;
// Register physics types with the factory
RegisterTypes();
{
// Disable allocation checking
DisableCustomMemoryHook dcmh;
// Create window
#ifdef JPH_PLATFORM_WINDOWS
mWindow = new ApplicationWindowWin;
#elif defined(JPH_PLATFORM_LINUX)
mWindow = new ApplicationWindowLinux;
#elif defined(JPH_PLATFORM_MACOS)
mWindow = new ApplicationWindowMacOS;
#else
#error No window defined
#endif
mWindow->Initialize(inApplicationName);
// Create renderer
mRenderer = Renderer::sCreate();
mRenderer->Initialize(mWindow);
// Create font
Font *font = new Font(mRenderer);
font->Create("Roboto-Regular", 24);
mFont = font;
// Init debug renderer
mDebugRenderer = new DebugRendererImp(mRenderer, mFont);
// Init keyboard
#ifdef JPH_PLATFORM_WINDOWS
mKeyboard = new KeyboardWin;
#elif defined(JPH_PLATFORM_LINUX)
mKeyboard = new KeyboardLinux;
#elif defined(JPH_PLATFORM_MACOS)
mKeyboard = new KeyboardMacOS;
#else
#error No keyboard defined
#endif
mKeyboard->Initialize(mWindow);
// Init mouse
#ifdef JPH_PLATFORM_WINDOWS
mMouse = new MouseWin;
#elif defined(JPH_PLATFORM_LINUX)
mMouse = new MouseLinux;
#elif defined(JPH_PLATFORM_MACOS)
mMouse = new MouseMacOS;
#else
#error No mouse defined
#endif
mMouse->Initialize(mWindow);
// Init UI
mUI = new UIManager(mRenderer);
mUI->SetVisible(false);
// Init debug UI
mDebugUI = new DebugUI(mUI, mFont);
}
// Get initial time
mLastUpdateTime = chrono::high_resolution_clock::now();
}
// Destructor
Application::~Application()
{
{
// Disable allocation checking
DisableCustomMemoryHook dcmh;
delete mDebugUI;
delete mUI;
delete mMouse;
delete mKeyboard;
delete mDebugRenderer;
mFont = nullptr;
delete mRenderer;
delete mWindow;
}
// Unregisters all types with the factory and cleans up the default material
UnregisterTypes();
delete Factory::sInstance;
Factory::sInstance = nullptr;
}
String Application::sCreateCommandLine(int inArgC, char **inArgV)
{
String command_line;
for (int i = 0; i < inArgC; ++i)
{
if (i > 0)
command_line += " ";
command_line += inArgV[i];
}
return command_line;
}
// Clear debug lines / triangles / texts that have been accumulated
void Application::ClearDebugRenderer()
{
JPH_PROFILE_FUNCTION();
static_cast<DebugRendererImp *>(mDebugRenderer)->Clear();
mDebugRendererCleared = true;
}
// Main loop
void Application::Run()
{
// Set initial camera position
ResetCamera();
// Enter the main loop
mWindow->MainLoop([this]() { return RenderFrame(); });
}
bool Application::RenderFrame()
{
// Get new input
mKeyboard->Poll();
mMouse->Poll();
// Handle keyboard input
for (EKey key = mKeyboard->GetFirstKey(); key != EKey::Invalid; key = mKeyboard->GetNextKey())
switch (key)
{
case EKey::P:
mIsPaused = !mIsPaused;
break;
case EKey::O:
mSingleStep = true;
break;
case EKey::T:
// Dump timing info to file
JPH_PROFILE_DUMP();
break;
case EKey::Escape:
mDebugUI->ToggleVisibility();
break;
}
// Calculate delta time
chrono::high_resolution_clock::time_point time = chrono::high_resolution_clock::now();
chrono::microseconds delta = chrono::duration_cast<chrono::microseconds>(time - mLastUpdateTime);
mLastUpdateTime = time;
float clock_delta_time = 1.0e-6f * delta.count();
float world_delta_time = 0.0f;
if (mRequestedDeltaTime <= 0.0f)
{
// If no fixed frequency update is requested, update with variable time step
world_delta_time = !mIsPaused || mSingleStep? clock_delta_time : 0.0f;
mResidualDeltaTime = 0.0f;
}
else
{
// Else use fixed time steps
if (mSingleStep)
{
// Single step
world_delta_time = mRequestedDeltaTime;
}
else if (!mIsPaused)
{
// Calculate how much time has passed since the last render
world_delta_time = clock_delta_time + mResidualDeltaTime;
if (world_delta_time < mRequestedDeltaTime)
{
// Too soon, set the residual time and don't update
mResidualDeltaTime = world_delta_time;
world_delta_time = 0.0f;
}
else
{
// Update and clamp the residual time to a full update to avoid spiral of death
mResidualDeltaTime = min(mRequestedDeltaTime, world_delta_time - mRequestedDeltaTime);
world_delta_time = mRequestedDeltaTime;
}
}
}
mSingleStep = false;
// Clear debug lines if we're going to step
if (world_delta_time > 0.0f)
ClearDebugRenderer();
{
JPH_PROFILE("UpdateFrame");
if (!UpdateFrame(world_delta_time))
return false;
}
// Draw coordinate axis
if (mDebugRendererCleared)
mDebugRenderer->DrawCoordinateSystem(RMat44::sIdentity());
// For next frame: mark that we haven't cleared debug stuff
mDebugRendererCleared = false;
// Update the camera position
if (!mUI->IsVisible())
UpdateCamera(clock_delta_time);
// Start rendering
if (!mRenderer->BeginFrame(mWorldCamera, GetWorldScale()))
return true;
// Draw from light
static_cast<DebugRendererImp *>(mDebugRenderer)->DrawShadowPass();
// Start drawing normally
mRenderer->EndShadowPass();
// Draw debug information
static_cast<DebugRendererImp *>(mDebugRenderer)->Draw();
// Draw the frame rate counter
DrawFPS(clock_delta_time);
if (mUI->IsVisible())
{
// Send mouse input to UI
bool left_pressed = mMouse->IsLeftPressed();
if (left_pressed && !mLeftMousePressed)
mUI->MouseDown(mMouse->GetX(), mMouse->GetY());
else if (!left_pressed && mLeftMousePressed)
mUI->MouseUp(mMouse->GetX(), mMouse->GetY());
mLeftMousePressed = left_pressed;
mUI->MouseMove(mMouse->GetX(), mMouse->GetY());
{
// Disable allocation checking
DisableCustomMemoryHook dcmh;
// Update and draw the menu
mUI->Update(clock_delta_time);
mUI->Draw();
}
}
else
{
// Menu not visible, cancel any mouse operations
mUI->MouseCancel();
}
// Show the frame
mRenderer->EndFrame();
// Notify of next frame
JPH_PROFILE_NEXTFRAME();
return true;
}
void Application::GetCameraLocalHeadingAndPitch(float &outHeading, float &outPitch)
{
outHeading = ATan2(mLocalCamera.mForward.GetZ(), mLocalCamera.mForward.GetX());
outPitch = ATan2(mLocalCamera.mForward.GetY(), Vec3(mLocalCamera.mForward.GetX(), 0, mLocalCamera.mForward.GetZ()).Length());
}
void Application::ConvertCameraLocalToWorld(float inCameraHeading, float inCameraPitch)
{
// Convert local to world space using the camera pivot
RMat44 pivot = GetCameraPivot(inCameraHeading, inCameraPitch);
mWorldCamera = mLocalCamera;
mWorldCamera.mPos = pivot * mLocalCamera.mPos;
mWorldCamera.mForward = pivot.Multiply3x3(mLocalCamera.mForward);
mWorldCamera.mUp = pivot.Multiply3x3(mLocalCamera.mUp);
}
void Application::ResetCamera()
{
// Get local space camera state
mLocalCamera = CameraState();
GetInitialCamera(mLocalCamera);
// Convert to world space
float heading, pitch;
GetCameraLocalHeadingAndPitch(heading, pitch);
ConvertCameraLocalToWorld(heading, pitch);
}
// Update camera position
void Application::UpdateCamera(float inDeltaTime)
{
JPH_PROFILE_FUNCTION();
// Determine speed
float speed = 20.0f * GetWorldScale() * inDeltaTime;
bool shift = mKeyboard->IsKeyPressed(EKey::LShift) || mKeyboard->IsKeyPressed(EKey::RShift);
bool control = mKeyboard->IsKeyPressed(EKey::LControl) || mKeyboard->IsKeyPressed(EKey::RControl);
bool alt = mKeyboard->IsKeyPressed(EKey::LAlt) || mKeyboard->IsKeyPressed(EKey::RAlt);
if (shift) speed *= 10.0f;
else if (control) speed /= 25.0f;
else if (alt) speed = 0.0f;
// Position
Vec3 right = mLocalCamera.mForward.Cross(mLocalCamera.mUp);
if (mKeyboard->IsKeyPressed(EKey::A)) mLocalCamera.mPos -= speed * right;
if (mKeyboard->IsKeyPressed(EKey::D)) mLocalCamera.mPos += speed * right;
if (mKeyboard->IsKeyPressed(EKey::W)) mLocalCamera.mPos += speed * mLocalCamera.mForward;
if (mKeyboard->IsKeyPressed(EKey::S)) mLocalCamera.mPos -= speed * mLocalCamera.mForward;
// Forward
float heading, pitch;
GetCameraLocalHeadingAndPitch(heading, pitch);
heading += DegreesToRadians(mMouse->GetDX() * 0.5f);
pitch = Clamp(pitch - DegreesToRadians(mMouse->GetDY() * 0.5f), -0.49f * JPH_PI, 0.49f * JPH_PI);
mLocalCamera.mForward = Vec3(Cos(pitch) * Cos(heading), Sin(pitch), Cos(pitch) * Sin(heading));
// Convert to world space
ConvertCameraLocalToWorld(heading, pitch);
}
void Application::DrawFPS(float inDeltaTime)
{
JPH_PROFILE_FUNCTION();
// Don't divide by zero
if (inDeltaTime <= 0.0f)
return;
// Switch tho ortho mode
mRenderer->SetOrthoMode();
// Update stats
mTotalDeltaTime += inDeltaTime;
mNumFrames++;
if (mNumFrames > 10)
{
mFPS = mNumFrames / mTotalDeltaTime;
mNumFrames = 0;
mTotalDeltaTime = 0.0f;
}
// Create string
String fps = StringFormat("%.1f", (double)mFPS);
// Get size of text on screen
Float2 text_size = mFont->MeasureText(fps);
int text_w = int(text_size.x * mFont->GetCharHeight());
int text_h = int(text_size.y * mFont->GetCharHeight());
// Draw FPS counter
int x = (mWindow->GetWindowWidth() - text_w) / 2 - 20;
int y = 10;
mUI->DrawQuad(x - 5, y - 3, text_w + 10, text_h + 6, UITexturedQuad(), Color(0, 0, 0, 128));
mUI->DrawText(x, y, fps, mFont);
// Draw status string
if (!mStatusString.empty())
mUI->DrawText(5, 5, mStatusString, mFont);
// Draw paused string if the app is paused
if (mIsPaused)
{
string_view paused_str = "P: Unpause, ESC: Menu";
Float2 pause_size = mFont->MeasureText(paused_str);
mUI->DrawText(mWindow->GetWindowWidth() - 5 - int(pause_size.x * mFont->GetCharHeight()), 5, paused_str, mFont);
}
// Restore state
mRenderer->SetProjectionMode();
}

View File

@@ -0,0 +1,121 @@
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#include <Renderer/Renderer.h>
#include <Renderer/Font.h>
#include <Input/Keyboard.h>
#include <Input/Mouse.h>
#include <Jolt/Core/Reference.h>
// STL includes
JPH_SUPPRESS_WARNINGS_STD_BEGIN
#include <chrono>
JPH_SUPPRESS_WARNINGS_STD_END
class UIManager;
class DebugUI;
namespace JPH {
class DebugRenderer;
}
class Application
{
private:
/// Camera state
CameraState mLocalCamera;
CameraState mWorldCamera;
protected:
/// Debug renderer module
DebugRenderer * mDebugRenderer;
/// Main window
ApplicationWindow * mWindow;
/// Render module
Renderer * mRenderer;
/// Default font
RefConst<Font> mFont;
/// Input
Keyboard * mKeyboard;
Mouse * mMouse;
/// Menu
UIManager * mUI;
DebugUI * mDebugUI;
/// A string that is shown on screen to indicate the status of the application
String mStatusString;
public:
/// Constructor
Application(const char *inApplicationName, const String &inCommandLine);
virtual ~Application();
/// Create a single string command line
static String sCreateCommandLine(int inArgC, char **inArgV);
/// Enter the main loop
void Run();
protected:
/// Update the application
virtual bool UpdateFrame(float inDeltaTime) { return false; }
/// Pause / unpause the simulation
void Pause(bool inPaused) { mIsPaused = inPaused; }
/// Programmatically single step the simulation
void SingleStep() { mIsPaused = true; mSingleStep = true; }
/// Set the frequency at which we want to render frames
void SetRenderFrequency(float inFrequency) { mRequestedDeltaTime = 1.0f / inFrequency; }
/// Will restore camera position to that returned by GetInitialCamera
void ResetCamera();
/// Override to specify the initial camera state (local to GetCameraPivot)
virtual void GetInitialCamera(CameraState &ioState) const { }
/// Override to specify a camera pivot point and orientation (world space)
virtual RMat44 GetCameraPivot(float inCameraHeading, float inCameraPitch) const { return RMat44::sIdentity(); }
/// Get scale factor for this world, used to boost camera speed and to scale detail of the shadows
virtual float GetWorldScale() const { return 1.0f; }
/// Get current state of the camera (world space)
const CameraState & GetCamera() const { return mWorldCamera; }
/// Clear debug lines / triangles / texts that have been accumulated
void ClearDebugRenderer();
private:
/// Render a frame
bool RenderFrame();
/// Extract heading and pitch from the local space (relative to the camera pivot) camera forward
void GetCameraLocalHeadingAndPitch(float &outHeading, float &outPitch);
/// Convert local space camera to world space camera
void ConvertCameraLocalToWorld(float inCameraHeading, float inCameraPitch);
/// Update the local and world space camera transform
void UpdateCamera(float inDeltaTime);
/// Draw the frame rate counter
void DrawFPS(float inDeltaTime);
chrono::high_resolution_clock::time_point mLastUpdateTime;
bool mIsPaused = false;
bool mSingleStep = false;
bool mDebugRendererCleared = true;
bool mLeftMousePressed = false;
float mFPS = 0.0f;
float mRequestedDeltaTime = 0.0f;
float mResidualDeltaTime = 0.0f;
float mTotalDeltaTime = 0.0f;
int mNumFrames = 0;
};

View File

@@ -0,0 +1,215 @@
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#include <TestFramework.h>
#include <Application/DebugUI.h>
#include <Renderer/Texture.h>
#include <UI/UIManager.h>
#include <UI/UIImage.h>
#include <UI/UIStaticText.h>
#include <UI/UICheckBox.h>
#include <UI/UIHorizontalStack.h>
#include <UI/UIVerticalStack.h>
#include <UI/UITextButton.h>
#include <Image/LoadTGA.h>
#include <Utils/Log.h>
#include <Utils/AssetStream.h>
JPH_SUPPRESS_WARNINGS_STD_BEGIN
#include <fstream>
JPH_SUPPRESS_WARNINGS_STD_END
DebugUI::DebugUI(UIManager *inUIManager, const Font *inFont) :
mUI(inUIManager),
mFont(inFont)
{
// Load UI texture with commonly used UI elements
AssetStream texture_stream("UI.tga", std::ios::in | std::ios::binary);
Ref<Surface> texture_surface = LoadTGA(texture_stream.Get());
if (texture_surface == nullptr)
FatalError("Failed to load UI.tga");
mUITexture = mUI->GetRenderer()->CreateTexture(texture_surface);
// Install callback that pops a layer when the deactivate animation finishes
mUI->SetDeactivatedAction([this]() {
mUI->PopLayer();
});
// Don't want to draw any layers that are not active
mUI->SetDrawInactiveLayers(false);
}
UIElement *DebugUI::CreateMenu()
{
mUI->PushLayer();
UIImage *background = new UIImage();
background->SetRelativeX(10);
background->SetRelativeY(10);
background->SetImage(UITexturedQuad(mUITexture, 0, 0, 33, 30, 4, 4, 24, 21));
mUI->Add(background);
UIVerticalStack *stack = new UIVerticalStack();
stack->SetRelativeX(10);
stack->SetRelativeY(10);
stack->SetPaddingRight(10);
stack->SetPaddingBottom(10);
background->Add(stack);
return stack;
}
UIStaticText *DebugUI::CreateStaticText(UIElement *inMenu, const string_view &inText)
{
UIStaticText *text = new UIStaticText();
text->SetText(inText);
text->SetFont(mFont);
inMenu->Add(text);
return text;
}
UITextButton *DebugUI::CreateTextButton(UIElement *inMenu, const string_view &inName, UITextButton::ClickAction inAction)
{
UITextButton *button = new UITextButton();
button->SetText(inName);
button->SetFont(mFont);
button->SetClickAction(inAction);
button->SetTextPadding(0, 24, 0, 0);
button->SetPaddingRight(24);
inMenu->Add(button);
return button;
}
UICheckBox *DebugUI::CreateCheckBox(UIElement *inMenu, const string_view &inName, bool inInitiallyChecked, UICheckBox::ClickAction inAction)
{
UICheckBox *check_box = new UICheckBox();
check_box->SetUncheckedStateQuad(UITexturedQuad(mUITexture, 48, 0, 16, 16));
check_box->SetCheckedStateQuad(UITexturedQuad(mUITexture, 65, 0, 16, 16));
check_box->SetFont(mFont);
check_box->SetText(inName);
check_box->SetClickAction(inAction);
check_box->SetState(inInitiallyChecked? UICheckBox::STATE_CHECKED : UICheckBox::STATE_UNCHECKED);
check_box->SetPaddingRight(24);
inMenu->Add(check_box);
return check_box;
}
UISlider *DebugUI::CreateSlider(UIElement *inMenu, const string_view &inName, float inInitialValue, float inMinValue, float inMaxValue, float inStepValue, UISlider::ValueChangedAction inAction)
{
UIHorizontalStack *horiz = new UIHorizontalStack();
horiz->SetPaddingRight(24);
inMenu->Add(horiz);
UIStaticText *text = new UIStaticText();
text->SetFont(mFont);
text->SetTextPadding(0, 24, 0, 0);
text->SetText(inName);
text->SetPaddingRight(20);
horiz->Add(text);
UISlider *slider = new UISlider();
slider->SetHeight(24);
slider->SetWidth(250);
slider->SetPaddingRight(20);
slider->SetValue(inInitialValue);
slider->SetRange(inMinValue, inMaxValue, inStepValue);
slider->SetValueChangedAction(inAction);
slider->SetSlider(UITexturedQuad(mUITexture, 44, 37, 1, 9));
slider->SetThumb(UITexturedQuad(mUITexture, 31, 32, 11, 19));
horiz->Add(slider);
UIButton *decr_button = new UIButton();
decr_button->SetRepeat(0.5f, 0.2f);
decr_button->SetButtonQuad(UITexturedQuad(mUITexture, 0, 31, 17, 21));
slider->Add(decr_button);
slider->SetDecreaseButton(decr_button);
UIButton *incr_button = new UIButton();
incr_button->SetRepeat(0.5f, 0.2f);
incr_button->SetButtonQuad(UITexturedQuad(mUITexture, 13, 31, 17, 21));
slider->Add(incr_button);
slider->SetIncreaseButton(incr_button);
UIImage *image = new UIImage();
image->SetImage(UITexturedQuad(mUITexture, 34, 0, 13, 24, 36, 2, 9, 20));
horiz->Add(image);
UIStaticText *value = new UIStaticText();
value->SetWidth(75);
value->SetTextPadding(0, 5, 0, 5);
value->SetWrap(true);
value->SetTextAlignment(UIElement::RIGHT);
value->SetFont(mFont);
image->Add(value);
slider->SetStaticText(value);
return slider;
}
UIComboBox *DebugUI::CreateComboBox(UIElement *inMenu, const string_view &inName, const Array<String> &inItems, int inInitialItem, UIComboBox::ItemChangedAction inAction)
{
UIHorizontalStack *horiz = new UIHorizontalStack();
horiz->SetPaddingRight(24);
inMenu->Add(horiz);
UIStaticText *text = new UIStaticText();
text->SetFont(mFont);
text->SetTextPadding(0, 24, 0, 0);
text->SetText(inName);
text->SetPaddingRight(20);
horiz->Add(text);
UIComboBox *combo = new UIComboBox();
combo->SetHeight(24);
combo->SetWidth(250);
combo->SetPaddingRight(20);
combo->SetItems(inItems);
combo->SetCurrentItem(inInitialItem);
combo->SetItemChangedAction(inAction);
horiz->Add(combo);
UIButton *prev_button = new UIButton();
prev_button->SetRepeat(0.5f, 0.2f);
prev_button->SetButtonQuad(UITexturedQuad(mUITexture, 0, 31, 17, 21));
combo->Add(prev_button);
combo->SetPreviousButton(prev_button);
UIButton *next_button = new UIButton();
next_button->SetRepeat(0.5f, 0.2f);
next_button->SetButtonQuad(UITexturedQuad(mUITexture, 13, 31, 17, 21));
combo->Add(next_button);
combo->SetNextButton(next_button);
UIStaticText *value = new UIStaticText();
value->SetTextPadding(0, 5, 0, 5);
value->SetWrap(false);
value->SetTextAlignment(UIElement::CENTER);
value->SetFont(mFont);
combo->Add(value);
combo->SetStaticText(value);
return combo;
}
void DebugUI::ShowMenu(UIElement *inMenu)
{
UIHorizontalStack::sUniformChildWidth(inMenu);
mUI->AutoLayout();
mUI->SwitchToState(UIManager::STATE_ACTIVATING);
}
void DebugUI::BackToMain()
{
while (mUI->GetNumLayers() > 2)
mUI->PopLayer();
}
void DebugUI::ToggleVisibility()
{
if (mUI->GetNumLayers() > 2)
mUI->SwitchToState(UIManager::STATE_DEACTIVATING);
else
mUI->SetVisible(!mUI->IsVisible());
}

View File

@@ -0,0 +1,48 @@
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
#include <Jolt/Core/Reference.h>
#include <UI/UICheckBox.h>
#include <UI/UITextButton.h>
#include <UI/UISlider.h>
#include <UI/UIComboBox.h>
#include <UI/UIStaticText.h>
class UIManager;
class Texture;
class Font;
class Keyboard;
class DebugUI
{
public:
/// Constructor
DebugUI(UIManager *inUIManager, const Font *inFont);
/// Create a new (sub) menu
UIElement * CreateMenu();
/// Add items to the menu
UIStaticText * CreateStaticText(UIElement *inMenu, const string_view &inText);
UITextButton * CreateTextButton(UIElement *inMenu, const string_view &inName, UITextButton::ClickAction inAction);
UICheckBox * CreateCheckBox(UIElement *inMenu, const string_view &inName, bool inInitiallyChecked, UICheckBox::ClickAction inAction);
UISlider * CreateSlider(UIElement *inMenu, const string_view &inName, float inInitialValue, float inMinValue, float inMaxValue, float inStepValue, UISlider::ValueChangedAction inAction);
UIComboBox * CreateComboBox(UIElement *inMenu, const string_view &inName, const Array<String> &inItems, int inInitialItem, UIComboBox::ItemChangedAction inAction);
/// Show it
void ShowMenu(UIElement *inMenu);
/// Go back to the main menu
void BackToMain();
/// Show or hide the entire menu
void ToggleVisibility();
private:
UIManager * mUI;
RefConst<Font> mFont;
RefConst<Texture> mUITexture;
};

View File

@@ -0,0 +1,74 @@
// Jolt Physics Library (https://github.com/jrouwe/JoltPhysics)
// SPDX-FileCopyrightText: 2021 Jorrit Rouwe
// SPDX-License-Identifier: MIT
#pragma once
#include <Jolt/Core/FPException.h>
#if defined(JPH_PLATFORM_WINDOWS)
#define ENTRY_POINT(AppName, RegisterAllocator) \
\
int WINAPI wWinMain(_In_ HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) \
{ \
RegisterAllocator(); \
\
JPH_PROFILE_START("Main"); \
\
FPExceptionsEnable enable_exceptions; \
JPH_UNUSED(enable_exceptions); \
\
{ \
AppName app(GetCommandLineA()); \
app.Run(); \
} \
\
JPH_PROFILE_END(); \
\
return 0; \
} \
\
int __cdecl main(int inArgC, char **inArgV) \
{ \
RegisterAllocator(); \
\
JPH_PROFILE_START("Main"); \
\
FPExceptionsEnable enable_exceptions; \
JPH_UNUSED(enable_exceptions); \
\
{ \
AppName app(Application::sCreateCommandLine(inArgC, inArgV)); \
app.Run(); \
} \
\
JPH_PROFILE_END(); \
\
return 0; \
}
#else
#define ENTRY_POINT(AppName, RegisterAllocator) \
\
int main(int inArgC, char **inArgV) \
{ \
RegisterAllocator(); \
\
JPH_PROFILE_START("Main"); \
\
FPExceptionsEnable enable_exceptions; \
JPH_UNUSED(enable_exceptions); \
\
{ \
AppName app(Application::sCreateCommandLine(inArgC, inArgV)); \
app.Run(); \
} \
\
JPH_PROFILE_END(); \
\
return 0; \
}
#endif