Commit 2da7edd9 by NTAuthority

a whole bunch of changes, including: key bindings and camera movement, changes…

a whole bunch of changes, including: key bindings and camera movement, changes in saving configuration, LODs for 'cleaner' rendering (though seemingly fairly flawed still), a minor amount of fixes
parent 5bc3a4b4
Pipeline #71 skipped
......@@ -32,6 +32,8 @@ public:
void SaveConfigurationIfNeeded(const std::string& path);
void SetVariableModifiedFlags(int flags);
inline ConsoleCommandManager* GetCommandManager()
{
return m_commandManager.get();
......@@ -50,6 +52,8 @@ public:
private:
Context* m_fallbackContext;
int m_variableModifiedFlags;
std::unique_ptr<ConsoleCommandManager> m_commandManager;
std::unique_ptr<ConsoleVariableManagerProxy> m_variableManager;
......@@ -72,5 +76,7 @@ void AddToBuffer(const std::string& text);
void ExecuteBuffer();
void SaveConfigurationIfNeeded(const std::string& path);
void SetVariableModifiedFlags(int flags);
}
}
\ No newline at end of file
......@@ -115,6 +115,8 @@ void ConsoleVariableManager::AddEntryFlags(const std::string& name, int flags)
if (it != m_entries.end())
{
it->second.flags |= flags;
m_parentContext->SetVariableModifiedFlags(it->second.flags);
}
}
......
......@@ -3,6 +3,8 @@
#include <Console.Commands.h>
#include <Console.Variables.h>
#include <KeyBinding.h>
#include <vfs/Manager.h>
#include <sstream>
......@@ -22,6 +24,8 @@ Context::Context(Context* fallbackContext)
{
m_commandManager = std::make_unique<ConsoleCommandManager>(this);
m_variableManager = std::make_unique<ConsoleVariableManager>(this);
m_variableModifiedFlags = 0;
}
void Context::ExecuteSingleCommand(const std::string& command)
......@@ -132,6 +136,7 @@ static void SaveConfiguration(const std::string& path, ConsoleVariableManager* m
writeLine("// generated by ATG, do not modify unless meow");
// save the actual configuration
g_bindings->WriteBindings(writeLine);
manager->SaveConfiguration(writeLine);
device->Close(handle);
......@@ -145,27 +150,23 @@ void Context::SaveConfigurationIfNeeded(const std::string& path)
static bool wasSavedBefore = false;
// mark a flag to see if any variables are modified (or if we haven't done our initial save)
int numModifiedVars = (wasSavedBefore) ? 0 : 1;
GetVariableManager()->ForAllVariables([&] (const std::string& name, int, const ConsoleVariableManager::THandlerPtr&)
{
// increment the counter
++numModifiedVars;
// remove the modified flag as well
GetVariableManager()->RemoveEntryFlags(name, ConVar_Modified);
}, ConVar_Modified);
if (numModifiedVars > 0)
if (!wasSavedBefore || (m_variableModifiedFlags & ConVar_Archive))
{
console::DPrintf("Saving ^1c^2o^3n^4f^5i^6g^7uration to %s...\n", path.c_str());
SaveConfiguration(path, GetVariableManager());
wasSavedBefore = true;
m_variableModifiedFlags &= ~ConVar_Archive;
}
}
void Context::SetVariableModifiedFlags(int flags)
{
m_variableModifiedFlags |= flags;
}
// default context functions
Context* GetDefaultContext()
{
......@@ -206,6 +207,11 @@ void SaveConfigurationIfNeeded(const std::string& path)
return GetDefaultContext()->SaveConfigurationIfNeeded(path);
}
void SetVariableModifiedFlags(int flags)
{
return GetDefaultContext()->SetVariableModifiedFlags(flags);
}
static inline bool IsEscapeChar(char c)
{
return (c == '"');
......
#pragma once
#include "Console.CommandHelpers.h"
#include "EventSystem.h"
namespace krt
{
class Button
{
public:
Button(const std::string& name);
inline const std::string& GetName() const
{
return m_name;
}
inline bool IsDown() const
{
return m_isDown;
}
float GetPressedFraction() const;
private:
std::string m_name;
bool m_isDown;
KeyCode m_keys[2];
uint64_t m_pressTime;
std::unique_ptr<ConsoleCommand> m_downCommand;
std::unique_ptr<ConsoleCommand> m_downCommandWithTime;
std::unique_ptr<ConsoleCommand> m_upCommand;
std::unique_ptr<ConsoleCommand> m_upCommandWithKey;
};
class BindingManager
{
public:
using TWriteLineCB = std::function<void(const std::string& line)>;
public:
BindingManager();
void WriteBindings(const TWriteLineCB& writeLineFunction);
void HandleKeyEvent(const KeyEvent* ev);
private:
std::unique_ptr<ConsoleCommand> m_bindCommand;
std::unique_ptr<ConsoleCommand> m_unbindCommand;
std::unique_ptr<ConsoleCommand> m_unbindAllCommand;
std::map<KeyCode, std::string> m_bindings;
};
extern BindingManager* g_bindings;
}
\ No newline at end of file
......@@ -5,6 +5,8 @@
#include <EventSystem.h>
#include <Game.h>
#include <windows.h>
namespace krt
......@@ -158,6 +160,8 @@ class Win32GameWindow : public GameWindow
while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) != 0)
{
m_msgTime = msg.time;
TranslateMessage(&msg);
DispatchMessage(&msg);
}
......@@ -166,17 +170,30 @@ class Win32GameWindow : public GameWindow
private:
LRESULT WindowProcedure(UINT msg, WPARAM wParam, LPARAM lParam)
{
int msgTimeDiff = (GetTickCount() - m_msgTime);
uint64_t msgTime = theGame->GetGameTime() - msgTimeDiff;
switch (msg)
{
case WM_KEYDOWN:
case WM_SYSKEYDOWN:
m_eventSystem->QueueEvent(std::make_unique<KeyEvent>(true, MapKeyCode(lParam)));
{
auto event = std::make_unique<KeyEvent>(true, MapKeyCode(lParam));
event->SetTime(msgTime);
m_eventSystem->QueueEvent(std::move(event));
break;
}
case WM_KEYUP:
case WM_SYSKEYUP:
m_eventSystem->QueueEvent(std::make_unique<KeyEvent>(false, MapKeyCode(lParam)));
{
auto event = std::make_unique<KeyEvent>(false, MapKeyCode(lParam));
event->SetTime(msgTime);
m_eventSystem->QueueEvent(std::move(event));
break;
}
case WM_CHAR:
{
......@@ -226,6 +243,8 @@ class Win32GameWindow : public GameWindow
int m_height;
bool m_fullscreen;
uint32_t m_msgTime;
};
std::map<HWND, Win32GameWindow*> Win32GameWindow::ms_windowMapping;
......
......@@ -2,7 +2,7 @@
#include "Camera.h"
#include "sys/Timer.h"
#include "Game.h"
namespace krt
{
......@@ -68,7 +68,7 @@ private:
inline void GiveVelocity( float speed )
{
timer_t cur_milli = sys::Milliseconds();
timer_t cur_milli = theGame->GetGameTime();
this->velocity_at_start_request = this->GetAtTime( cur_milli );
this->start_velocity = cur_milli;
......@@ -84,7 +84,7 @@ private:
if ( this->isMoving )
{
// Update current status.
timer_t cur_milli = sys::Milliseconds();
timer_t cur_milli = theGame->GetGameTime();
this->velocity_at_start_request = this->GetAtTime( cur_milli );
this->start_velocity = cur_milli;
......@@ -105,7 +105,7 @@ private:
inline numberType GetCurrent( void )
{
timer_t cur_milli = sys::Milliseconds();
timer_t cur_milli = theGame->GetGameTime();
numberType currentVelo = this->GetAtTime( cur_milli );
......
......@@ -56,6 +56,11 @@ struct Entity
void RemoveEntityWorldReference( EntityReference *refPtr );
inline void ResetChildrenDrawn( void ) { lodChildrenDrawn = 0; }
inline void IncrementChildrenDrawn( void ) { lodChildrenDrawn++; }
inline bool ShouldBeDrawn( void ) { return (lodChildrenCount == 0) ? true : (lodChildrenDrawn != lodChildrenCount); }
private:
Game *ourGame;
......@@ -76,6 +81,9 @@ private:
rw::Matrix matrix;
bool hasLocalMatrix;
int lodChildrenCount;
int lodChildrenDrawn;
rw::Object *rwObject;
Entity *higherQualityEntity;
......
......@@ -7,7 +7,7 @@ namespace krt
class Event abstract
{
public:
inline uint64_t GetTime() { return m_time; }
inline uint64_t GetTime() const { return m_time; }
inline void SetTime(uint64_t time) { m_time = time; }
......@@ -221,6 +221,16 @@ class KeyEvent : public Event
virtual void Handle() override;
inline bool IsDownEvent() const
{
return m_isDown;
}
inline KeyCode GetKeyCode() const
{
return m_keyCode;
}
private:
bool m_isDown;
......
......@@ -43,6 +43,8 @@ class Game
inline uint32_t GetLastFrameTime() { return lastFrameTime; }
inline uint64_t GetGameTime() { return lastGameTime; }
std::string GetDevicePathPrefix(void) { return "gta3:/"; }
GameUniversePtr AddUniverse(const GameConfiguration& configuration);
......@@ -64,6 +66,7 @@ class Game
private:
float dT;
uint32_t lastFrameTime;
uint64_t lastGameTime;
std::string gameDir;
......
......@@ -33,7 +33,10 @@ Entity::Entity( Game *ourGame )
this->onWorld = NULL; // we are not part of a world.
this->cachedBoundSphereRadius = 300.0f; // TODO: cache the real bounding sphere radius in some file so we dont need the model
this->cachedBoundSphereRadius = 400.0f; // TODO: cache the real bounding sphere radius in some file so we dont need the model
this->lodChildrenCount = 0;
this->lodChildrenDrawn = 0;
}
Entity::~Entity( void )
......@@ -388,6 +391,7 @@ void Entity::SetLODEntity( Entity *lodInst )
this->lowerQualityEntity = lodInst;
lodInst->lodChildrenCount++;
lodInst->higherQualityEntity = this;
}
}
......
......@@ -5,6 +5,8 @@
#include <Console.h>
#include <KeyBinding.h>
namespace krt
{
class NullEvent : public Event
......@@ -36,7 +38,7 @@ public:
void KeyEvent::Handle()
{
g_bindings->HandleKeyEvent(this);
}
void CharEvent::Handle()
......
......@@ -536,6 +536,12 @@ struct inst_section_manager
// I have no actual idea how things are made exactly, but lets just register it somehow.
ModelManager::ModelResource* modelInfo = theGame->GetModelManager().GetModelByID(universeModelIndex);
// HACK: ignore III island LODs some ugly way
if (modelID == 402 || modelID == 403 || modelID == 404 || modelID == 405 || modelID == 416)
{
return;
}
if (!modelInfo)
return;
......
......@@ -119,6 +119,8 @@ void Game::Run()
bool wantsToExit = false;
uint64_t lastTime = 0;
this->lastGameTime = 0;
// exit command
ConsoleCommand quitCommand("quit", [&]() {
wantsToExit = true;
......@@ -165,6 +167,8 @@ void Game::Run()
this->dT = millis / 1000.0f;
this->lastFrameTime = millis;
this->lastGameTime += millis;
lastTime = thisTime;
// execute the command buffer for the global console
......
......@@ -375,7 +375,7 @@ void ModelManager::LoadResource( streaming::ident_t localID, const void *dataBuf
if ( modelPtr == NULL )
{
throw std::exception( "invalid model file" );
//throw std::exception( "invalid model file" );
}
}
catch( ... )
......@@ -402,11 +402,12 @@ void ModelManager::UnloadResource( streaming::ident_t localID )
// Delete GPU data.
{
assert( modelEntry->modelPtr != NULL );
if (modelEntry->modelPtr != NULL)
{
rw::Object *rwobj = modelEntry->modelPtr;
rw::Object *rwobj = modelEntry->modelPtr;
ModelResource::NativeReleaseModel( rwobj );
ModelResource::NativeReleaseModel(rwobj);
}
}
modelEntry->modelPtr = NULL;
......
......@@ -10,7 +10,7 @@
#include "Camera.h"
#include "CameraControls.h"
#include "sys/Timer.h"
#include "KeyBinding.h"
namespace krt
{
......@@ -58,7 +58,7 @@ void World::PutEntitiesOnGrid( void )
LIST_FOREACH_BEGIN( Entity, this->entityList.root, worldNode )
// ignore LODs
if (item->GetModelInfo() && item->GetModelInfo()->GetLODDistance() < 300.0f)
//if (item->GetModelInfo() && item->GetModelInfo()->GetLODDistance() < 300.0f)
{
this->staticEntityGrid.PutEntity(item);
}
......@@ -110,7 +110,7 @@ void World::RenderWorld( void *gfxDevice )
if ( !hasInitializedWorldCam )
{
worldCam.SetFarClip( 1150 );
worldCam.SetFarClip( 2150 );
rw::V3d forward = rw::normalize(rw::sub(objectPosition, cameraPosition));
rw::V3d left = rw::normalize(rw::cross(rw::V3d(0.0f, 0.0f, 1.0f), forward));
......@@ -129,9 +129,9 @@ void World::RenderWorld( void *gfxDevice )
hasInitializedWorldCam = true;
}
#if 1
#if 0
// Do a little test, meow.
uint64_t cur_time = sys::Milliseconds();
uint64_t cur_time = theGame->GetGameTime();
unsigned int cur_divisor = ( ( cur_time / 500 ) % 2 );
......@@ -150,6 +150,64 @@ void World::RenderWorld( void *gfxDevice )
editorControls.OnFrame( &worldCam );
#endif
#if 1
static EditorCameraControls editorControls;
static Button forwardButton("forward");
static Button backButton("back");
static Button moveLeftButton("moveleft");
static Button moveRightButton("moveright");
static Button lookLeftButton("lookleft");
static Button lookRightButton("lookright");
static Button lookUpButton("lookup");
static Button lookDownButton("lookdown");
static std::once_flag bindingFlag;
std::call_once(bindingFlag, [] ()
{
console::ExecuteSingleCommand(ProgramArguments{ "bind", "W", "+forward" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "S", "+back" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "A", "+moveleft" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "D", "+moveright" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "Up", "+lookup" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "Down", "+lookdown" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "Left", "+lookleft" });
console::ExecuteSingleCommand(ProgramArguments{ "bind", "Right", "+lookright" });
});
auto bindButton = [&] (const Button& addButton, const Button& subButton, auto& setFunction, auto& stopFunction, float speed)
{
if (addButton.IsDown())
{
setFunction(speed * addButton.GetPressedFraction());
}
else if (subButton.IsDown())
{
setFunction(-speed * subButton.GetPressedFraction());
}
else
{
stopFunction();
}
};
#define BUTTON_MACRO(b, sb, n, s) \
bindButton(b, sb, std::bind(&EditorCameraControls::Set##n, &editorControls, std::placeholders::_1), std::bind(&EditorCameraControls::Stop##n, &editorControls), s)
BUTTON_MACRO(forwardButton, backButton, FrontVelocity, 30.0f);
BUTTON_MACRO(moveLeftButton, moveRightButton, RightVelocity, 30.0f);
BUTTON_MACRO(lookRightButton, lookLeftButton, YawVelocity, 18.0f);
BUTTON_MACRO(lookUpButton, lookDownButton, PitchVelocity, 10.0f);
#undef BUTTON_MACRO
editorControls.OnFrame(&worldCam);
#endif
}
// Begin the rendering.
......@@ -158,11 +216,22 @@ void World::RenderWorld( void *gfxDevice )
// Get its frustum.
// For now it does not matter which; both promise that things that should be visible are indeed visible.
// The difference is that the complex frustum culls away more objects than the simple frustum.
//math::Frustum frustum = worldCam.GetSimpleFrustum();
math::Quader frustum = worldCam.GetComplexFrustum();
math::Frustum frustum = worldCam.GetSimpleFrustum();
//math::Quader frustum = worldCam.GetComplexFrustum();
streaming::StreamMan& streaming = theGame->GetStreaming();
rw::V3d cameraPos = worldCam.GetRWFrame()->getLTM()->pos;
std::vector<Entity*> renderList;
renderList.reserve(5000);
LIST_FOREACH_BEGIN(Entity, this->entityList.root, worldNode)
item->ResetChildrenDrawn();
LIST_FOREACH_END
// Visit the things that are visible.
this->staticEntityGrid.VisitSectorsByFrustum( frustum,
[&]( StaticEntitySector& sector )
......@@ -172,6 +241,13 @@ void World::RenderWorld( void *gfxDevice )
{
rw::Sphere worldSphere;
rw::V3d entityPos = entity->GetMatrix().pos;
if (rw::length(rw::sub(entityPos, cameraPos)) > entity->GetModelInfo()->GetLODDistance())
{
continue;
}
bool hasEntityBounds = entity->GetWorldBoundingSphere( worldSphere );
if ( hasEntityBounds )
......@@ -203,19 +279,34 @@ void World::RenderWorld( void *gfxDevice )
// If the entity has a valid rw object, we can render it.
if ( rw::Object *rwobj = entity->GetRWObject() )
{
if ( rwobj->type == rw::Atomic::ID )
{
// We only render atomics for now.
rw::Atomic *atomic = (rw::Atomic*)rwobj;
if (entity->GetLODEntity())
{
entity->GetLODEntity()->IncrementChildrenDrawn();
}
atomic->render();
}
renderList.push_back(entity);
}
}
}
}
});
for (auto& entity : renderList)
{
if (entity->ShouldBeDrawn())
{
rw::Object* rwobj = entity->GetRWObject();
if (rwobj->type == rw::Atomic::ID)
{
// We only render atomics for now.
rw::Atomic *atomic = (rw::Atomic*)rwobj;
atomic->render();
}
}
}
// Present world scene.
worldCam.EndUpdate();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment