no engine anymore

This commit is contained in:
2025-07-30 23:53:26 +03:00
parent 8a29e6b86f
commit 395ced9e28
159 changed files with 2767 additions and 9484 deletions

View File

@@ -54,12 +54,12 @@ extern "C" void Preinit()
{
if (bStaticBuild)
{
IFileSystem2::MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
filesystem2->MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
} else
{
IFileSystem2::MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
filesystem2->MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
}
}
};
@@ -72,8 +72,6 @@ CUtlString client_lib;
#include "tier0/__build.cpp"
#include "tier1/__build.cpp"
#include "fgui/__build.cpp"
#include "game/server/__build.cpp"
#include "game/client/__build.cpp"

View File

@@ -5,37 +5,16 @@
#include "tier1/commandline.h"
CUtlVector<CUtlString> engine_CompiledFiles = {
"engine/interface.cpp",
"engine/console.cpp",
"engine/filesystem.cpp",
"engine/server.cpp",
"engine/engine.cpp",
"engine/physics.cpp",
"engine/gamemode.cpp",
"engine/rendering.cpp",
"engine/cvar.cpp",
"engine/filesystem.cpp",
"engine/filesystem_pak.cpp",
"engine/filesystem_libc.cpp",
/* io */
"engine/input.cpp",
"engine/networking.cpp",
/* audio */
"engine/ma_audio.cpp",
"engine/mesh.cpp",
/* entities */
"engine/baseentity.cpp",
"engine/level.cpp",
"engine/brush.cpp",
/* server entities */
"engine/sv_worldspawn.cpp",
"engine/sv_light.cpp",
"engine/sv_playerstart.cpp",
/* client entities */
"engine/cl_worldspawn.cpp",
"engine/cl_light.cpp",
"engine/gamewindow_sdl.cpp",
"engine/sv_dll.cpp",
"engine/cl_dll.cpp",
};
CUtlVector<CUtlString> engine_Libraries = {
@@ -43,56 +22,39 @@ CUtlVector<CUtlString> engine_Libraries = {
"SDL3",
};
int engine_build()
DECLARE_BUILD_STAGE(engine)
{
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS || Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
{
engine_CompiledFiles.AppendTail("engine/ml_videosdl.cpp");
engine_CompiledFiles.AppendTail("engine/ml_video.cpp");
engine_CompiledFiles.AppendTail("engine/ml_video.mm");
} else {
engine_CompiledFiles.AppendTail("engine/vk_videosdl.cpp");
engine_CompiledFiles.AppendTail("engine/vk_video.cpp");
}
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_LINUX)
{
engine_Libraries.AppendTail("vulkan");
}
CCProject compileProject = {};
CLDProject ldProject = {};
CProject_t compileProject = {};
LinkProject_t ldProject = {};
compileProject.m_szName = "engine";
compileProject.files = engine_CompiledFiles;
compileProject.includeDirectories = all_IncludeDirectories;
compileProject.bFPIC = true;
if (bStaticBuild)
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
if (bSteam)
compileProject.macros.AppendTail((C_Macro_t){"STEAM_ENABLED","1"});
ldProject = compileProject.Compile();
ldProject.libraries = engine_Libraries;
ldProject = ccompiler->Compile(&compileProject);
if (bStaticBuild)
ldProject.linkType = ELINK_STATIC_LIBRARY;
else
{
ldProject.objects.AppendTail((CObject){tier1_lib});
ldProject.objects.AppendTail((CObject){fgui_lib});
ldProject.objects.AppendTail((CObject){rapier_lib});
ldProject.objects.AppendTail((Object_t){tier1_lib});
ldProject.objects.AppendTail((Object_t){rapier_lib});
if (bSteam)
ldProject.objects.AppendTail((CObject){steam_lib});
ldProject.objects.AppendTail((Object_t){steam_lib});
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
}
CUtlString outputProject = ldProject.Link();
ldProject.libraries = engine_Libraries;
CUtlString outputProject = linker->Link(&ldProject);
if (!bStaticBuild)
{
IFileSystem2::MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
} else {
engine_lib = outputProject;
}
return 0;
};
DECLARE_BUILD_STAGE(engine, engine_build);

View File

@@ -1,81 +0,0 @@
#include "baseentity.h"
#include "tier0/platform.h"
#include "tier1/utlstring.h"
CBaseEntity::CBaseEntity()
{
glm_mat3_identity(m_matrix);
glm_vec3_zero(m_position);
glm_vec3_zero(m_scale);
};
void CBaseEntity::ReadParameter( const char *szName, const char *szValue )
{
CUtlString name = szName;
if (name == "origin")
V_sscanf(szValue, "%f %f %f", &m_position[0], &m_position[1], &m_position[2]);
}
void CBaseEntity::SetPosition( vec3 position )
{
V_memcpy(m_position, position, sizeof(vec3));
}
void CBaseEntity::SetRotationEuler( vec3 euler )
{
}
void CBaseEntity::SetRotationQuat( vec4 quaternion )
{
}
void CBaseEntity::SetRotationMatrix( mat3 matrix )
{
V_memcpy(m_matrix, matrix, sizeof(mat3));
}
void CBaseEntity::SetScale( vec3 scale )
{
V_memcpy(m_scale, scale, sizeof(vec3));
}
class CEntityManager: public IEntityManager
{
public:
virtual void Init() override {}
virtual void Frame() override {}
virtual void Deinit() override {}
};
DECLARE_ENGINE_INTERFACE(EntityManager, CEntityManager);
CEntityRegistryObject::CEntityRegistryObject(const char *szName, const char *szClass, EntityRegistryFn pfn) :
m_szName(szName), m_szClass(szClass), m_pfn(pfn), m_pClientfn(0)
{
for (auto &entity: EntityManager()->m_RegisteredEntities)
{
if (!V_strcmp(entity->m_szClass, szClass))
{
entity->m_szName = szName;
entity->m_pfn = pfn;
return;
}
}
EntityManager()->m_RegisteredEntities.AppendTail(this);
};
C_EntityRegistry::C_EntityRegistry( const char *szName, ClientEntityRegistryFn pfn )
{
for (auto &entity: EntityManager()->m_RegisteredEntities)
{
if (!V_strcmp(entity->m_szClass, szName))
{
entity->m_pClientfn = pfn;
return;
}
}
CEntityRegistryObject *pObject = new CEntityRegistryObject(0, szName, 0);
pObject->m_pClientfn = pfn;
}

View File

@@ -1,181 +0,0 @@
#include "brush.h"
#include "baseentity.h"
#include "cglm/mat4.h"
#include "physics.h"
#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlbuffer.h"
#include "tier1/utlvector.h"
#include "math3d.h"
CUtlVector<IVertexBuffer*> g_BrushVertices;
void CBrushEntity::Precache()
{
}
void CBrushEntity::Spawn()
{
/* physics don't support unindexed meshes, so generate indicies */
CUtlBuffer<uint32_t> indicies(m_mesh.GetSize()*3);
for (uint32_t i = 0;i<indicies.GetSize();i++)
{
indicies[i]=i;
}
/* copy over the triangles to a separate buffer, which will be used by physics */
CUtlBuffer<Point<float>> triangles(m_mesh.GetSize()*3);
uint32_t i = 0;
for (auto tri: m_mesh)
{
V_memcpy(&triangles[i],tri.location,36);
i+=3;
}
/* use them */
px_collider_params params = {};
params.friction = 0.0;
m_collider = px_trimesh((Point<float>*)triangles.GetMemory(), triangles.GetSize(), (uint32_t(*)[3])indicies.GetMemory(), indicies.GetSize()/3 ,params);
px_fixedbody(px, m_collider);
};
void CBrushEntity::Destroy()
{
}
void CBrushEntity::Think( float fDelta )
{
};
void CBrushEntity::SendToServer()
{
};
void CBrushEntity::RecieveFromServer( void *pData, uint32_t nDataSize )
{
};
void CBrushEntity::ReadParameter( const char *szName, const char *szValue )
{
CBaseEntity::ReadParameter(szName, szValue);
};
void C_BrushEntity::Precache()
{
CBrushEntity* pBrushEntity = dynamic_cast<CBrushEntity*>(pEntity);
if (!pBrushEntity)
Plat_FatalErrorFunc("pEntity is not a CBrushEntity");
}
void C_BrushEntity::Spawn()
{
struct Vertex_t
{
float position[3];
float uv[2];
};
CBrushEntity* pBrushEntity = (CBrushEntity*)pEntity;
uint32_t numVertices = pBrushEntity->m_mesh.GetSize();
vertexBuffer = Renderer()->CreateVertexBuffer(numVertices*60);
Vertex_t *pTriangles = (Vertex_t*)vertexBuffer->Map();
uint32_t i = 0;
for (auto &triangle: pBrushEntity->m_mesh)
{
pTriangles[i].position[0] = triangle.location[0];
pTriangles[i].position[1] = triangle.location[1];
pTriangles[i].position[2] = triangle.location[2];
pTriangles[i].uv[0] = triangle.uv[0];
pTriangles[i].uv[1] = triangle.uv[1];
pTriangles[i+1].position[0] = triangle.location[3];
pTriangles[i+1].position[1] = triangle.location[4];
pTriangles[i+1].position[2] = triangle.location[5];
pTriangles[i+1].uv[0] = triangle.uv[2];
pTriangles[i+1].uv[1] = triangle.uv[3];
pTriangles[i+2].position[0] = triangle.location[6];
pTriangles[i+2].position[1] = triangle.location[7];
pTriangles[i+2].position[2] = triangle.location[8];
pTriangles[i+2].uv[0] = triangle.uv[4];
pTriangles[i+2].uv[1] = triangle.uv[5];
i+=3;
}
vertexBuffer->Unmap();
};
void C_BrushEntity::Destroy()
{
}
void C_BrushEntity::Think( float fDelta )
{
g_BrushVertices.AppendTail(vertexBuffer);
};
class CBrushRendering: public IRenderingPipelineStep
{
public:
virtual void Init() override;
virtual void Frame( float fDelta ) override;
virtual void Deinit() override;
private:
};
DECLARE_MESH_RENDERING_STAGE(CBrushRendering, brush_rasterizer);
IGraphicsPipeline *g_BrushPipeline;
ITexture *bricks;
void CBrushRendering::Init()
{
g_BrushPipeline = Renderer()->CreateGraphicsPipeline(
{
{"gfx/mesh_vert.shader", SHADER_TYPE_VERTEX},
{"gfx/mesh_frag.shader", SHADER_TYPE_FRAGMENT},
},
{
{SHADER_INPUT_TYPE_UNIFORM_BUFFER,0},
{SHADER_INPUT_TYPE_TEXTURES,1},
},
80,
20,
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32Z32}, {12,1,EVertexFormat::VERTEX_FORMAT_X32Y32}},
{EImageFormat::IMAGE_FORMAT_R8G8B8A8},
true
);
bricks = ITextureManager::LoadTexture("textures/bricks.png");
};
void CBrushRendering::Frame( float fDelta )
{
g_BrushPipeline->BindData(0, Renderer()->GetCameraMatrix(), 0);
g_BrushPipeline->PushBindings();
Renderer()->ResetState();
Renderer()->SetDepthMode(DEPTH_MODE_LESS);
Renderer()->BindPipeline(g_BrushPipeline);
struct {
mat4 i;
uint32_t a = ITextureManager::GetTextureID(bricks);
uint32_t b = 0;
uint32_t c = 0;
} constants;
glm_mat4_identity(constants.i);
Renderer()->SetConstants(sizeof(constants), &constants);
for (auto &v: g_BrushVertices)
{
Renderer()->Draw(v, 0);
}
g_BrushVertices = {};
};
void CBrushRendering::Deinit()
{
};

1
engine/cl_dll.cpp Normal file
View File

@@ -0,0 +1 @@

View File

@@ -1,31 +0,0 @@
#include "baseentity.h"
#include "rendering.h"
class C_Light: public C_BaseEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
};
void C_Light::Precache()
{
}
void C_Light::Spawn()
{
};
void C_Light::Destroy()
{
}
void C_Light::Think( float fDelta )
{
};
LINK_CLIENT_ENTITY(C_Light, CLight)

View File

@@ -1,33 +0,0 @@
#include "brush.h"
#include "rendering.h"
class C_WorldSpawn: public C_BrushEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
};
void C_WorldSpawn::Precache()
{
C_BrushEntity::Precache();
}
void C_WorldSpawn::Spawn()
{
C_BrushEntity::Spawn();
};
void C_WorldSpawn::Destroy()
{
C_BrushEntity::Destroy();
}
void C_WorldSpawn::Think( float fDelta )
{
C_BrushEntity::Think(fDelta);
};
LINK_CLIENT_ENTITY(C_WorldSpawn, CWorldSpawn)

View File

@@ -1 +0,0 @@
#include "client.h"

View File

@@ -1,407 +0,0 @@
#include "console.h"
#include "fgui/rect.h"
#include "fgui/widget.h"
#include "fgui/label.h"
#include "filesystem.h"
#include "interface.h"
#include "rendering.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
#include "stdarg.h"
enum EConsoleMessageType
{
CONSOLE_MESSAGE_TYPE_MESSAGE,
CONSOLE_MESSAGE_TYPE_WARNING,
CONSOLE_MESSAGE_TYPE_ERROR,
};
struct ConsoleMessage_t
{
EConsoleMessageType type;
CUtlString szMessage;
};
void Msg( const char* message )
{
printf(message);
}
void Warning( const char* message )
{
}
void Error( const char* message )
{
}
interface CConsole: public IConsole
{
public:
virtual void Init() override;
virtual void Frame() override;
virtual void Deinit() override;
// Variables
virtual void RegisterVar( ConVar *cvar ) override;
virtual void UnRegisterVar( ConVar *cvar ) override;
virtual ConVar *FindVar( const char *pName ) override;
// Commands
virtual void RegisterCommand( ConCommand *cvar ) override;
virtual void UnRegisterCommand( ConCommand *cvar ) override;
virtual ConCommand *FindCommand( const char *pName ) override;
// Command buffer
virtual void Execute( void ) override;
virtual void ExecuteArguments( CUtlVector<CUtlString> &args ) override;
virtual CUtlVector<CUtlVector<CUtlString>> ParseCommandLine( CUtlString psz ) override;
virtual void AddCommand( const char *psz ) override;
virtual void InsertCommand( const char *psz ) override;
};
DECLARE_ENGINE_INTERFACE(Console, CConsole)
void CConsole::Init()
{
}
void CConsole::Frame()
{
}
void CConsole::Deinit()
{
}
void CConsole::RegisterVar( ConVar *cvar )
{
m_convars.AppendTail(cvar);
}
void CConsole::UnRegisterVar( ConVar *cvar )
{
}
ConVar *CConsole::FindVar( const char *pName )
{
for (auto &var: m_convars)
{
if (!V_strcmp(var->GetName(), pName))
return var;
}
return NULL;
}
void CConsole::RegisterCommand( ConCommand *cvar )
{
m_commands.AppendTail(cvar);
}
void CConsole::UnRegisterCommand( ConCommand *cvar )
{
}
ConCommand *CConsole::FindCommand( const char *pName )
{
for (auto &var: m_commands)
{
if (!V_strcmp(var->GetName(), pName))
return var;
}
return NULL;
}
CUtlString g_commandBuffer;
//-----------------------------------------------------------------------------
// Executes arguments from CConsole::Execute
//-----------------------------------------------------------------------------
void CConsole::ExecuteArguments( CUtlVector<CUtlString> &args )
{
if (args.GetSize()<1)
return;
ConCommand *cmd = CConsole::FindCommand(args[0]);
if (!cmd)
{
V_printf("%s not found\n", args[0].GetString());
return;
}
CUtlBuffer<char*> strbuffer(args.GetSize());
for ( size_t i = 0; i < args.GetSize(); i++)
{
strbuffer[i] = args[i].GetString();
};
(cmd->GetCallback())(args.GetSize(), strbuffer);
}
void CConsole::Execute( void )
{
CUtlVector<CUtlVector<CUtlString>> commands = ParseCommandLine(g_commandBuffer);
g_commandBuffer = 0;
for (auto &command: commands)
{
ExecuteArguments(command);
}
}
//-----------------------------------------------------------------------------
// Parses command buffer.
//-----------------------------------------------------------------------------
CUtlVector<CUtlVector<CUtlString>> CConsole::ParseCommandLine( CUtlString psz )
{
CUtlVector<CUtlString> arguments;
CUtlVector<CUtlVector<CUtlString>> commands;
CUtlString szArgument;
bool bIsQuote = false;
for ( auto &c: (CUtlVector<char>&)psz )
{
if ( c == '\"' )
{
bIsQuote = !bIsQuote;
continue;
}
if ( c == ';' || c == '\n' )
{
if (bIsQuote)
{
continue;
}
if (szArgument != 0)
arguments.AppendTail(szArgument);
if ( arguments.GetSize() > 0 )
commands.AppendTail(arguments);
szArgument = 0;
arguments = {};
continue;
}
if ( c == '\t' || c == ' ' )
{
if (bIsQuote)
{
szArgument.AppendTail(c);
continue;
}
if (szArgument != 0)
arguments.AppendTail(szArgument);
szArgument = 0;
continue;
}
szArgument.AppendTail(c);
};
if (szArgument != 0)
arguments.AppendTail(szArgument);
if ( arguments.GetSize() > 0 )
commands.AppendTail(arguments);
return commands;
}
void CConsole::AddCommand( const char *psz )
{
g_commandBuffer.AppendTail(psz);
}
void CConsole::InsertCommand( const char *psz )
{
g_commandBuffer.AppendHead(psz);
};
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags )
: ConVar(pName, pDefaultValue, flags, 0)
{
}
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString )
: ConVar(pName, pDefaultValue, flags, pHelpString, 0)
{
}
ConVar::ConVar( const char *pName, const char *pDefaultValue, int flags,
const char *pHelpString, ConCommandFn callback )
{
m_szName = pName;
m_flags = flags;
m_szValue = pDefaultValue;
m_fValue = V_atof(pDefaultValue);
m_nValue = V_atoi(pDefaultValue);
Console()->RegisterVar(this);
}
bool ConVar::IsFlagSet( int flag )
{
}
const char *ConVar::GetHelpText( void )
{
return m_szHelpString;
}
bool ConVar::IsRegistered( void )
{
}
const char *ConVar::GetName( void )
{
return m_szName;
}
void ConVar::AddFlags( int flags )
{
}
bool ConVar::IsCommand( void )
{
}
void ConVar::InstallChangeCallback( ConCommandFn )
{
}
float ConVar::GetFloat( void )
{
return m_fValue;
}
int ConVar::GetInt( void )
{
return m_nValue;
}
bool ConVar::GetBool( void )
{
return m_nValue;
}
const char *ConVar::GetString( void )
{
}
void ConVar::SetValue( const char *szValue )
{
if (!szValue)
return;
m_szValue = szValue;
m_fValue = V_atof(szValue);
m_nValue = V_atoi(szValue);
}
void ConVar::SetValue( float fValue )
{
m_fValue = fValue;
m_nValue = fValue;
m_szValue = CUtlString("%f\n",fValue);
}
void ConVar::SetValue( int iValue )
{
m_fValue = iValue;
m_nValue = iValue;
m_szValue = CUtlString("%i\n",iValue);
}
ConCommand::ConCommand(const char *pName, ConCommandFn callback,
const char *pHelpString, int flags)
{
m_szName = pName;
m_callback = callback;
m_flags = flags;
Console()->RegisterCommand(this);
};
const char *ConCommand::GetHelpText( void )
{
return m_szHelpString;
}
const char *ConCommand::GetName( void )
{
return m_szName;
}
ConCommandFn ConCommand::GetCallback( void )
{
return m_callback;
}
void IConsole_Exec( int argc, char **argv)
{
if (argc != 2)
return;
FileHandle_t f = FileSystem()->Open(argv[1], IFILE_READ);
if (!f)
return;
CUtlBuffer<char> b(FileSystem()->Size(f)+1);
FileSystem()->Read(f, b, b.GetSize());
b[FileSystem()->Size(f)] = 0;
Console()->AddCommand(b);
Console()->AddCommand(";");
Console()->Execute();
}
ConCommand IConsole_ExecCmd("exec", IConsole_Exec);
class CConsoleGUI: public CFGUI_Widget
{
public:
CConsoleGUI();
virtual void Event( FGUI_Event_t event ) override;
virtual void Draw() override;
virtual void Frame() override;
private:
CFGUI_Rect *m_pBackground = 0;
CFGUI_Label *m_pLog = 0;
};
bool console_bDrawUI = false;
CConsoleGUI::CConsoleGUI()
{
m_pBackground = new CFGUI_Rect();
m_pBackground->SetBoxColor(0.13, 0.13, 0.13, 1);
m_pBackground->SetSize(200, 200);
m_pBackground->SetPosition(0, 0);
m_pBackground->SetParent(this);
m_pLog = new CFGUI_Label();
m_pLog->SetFont("fonts/IBMPlexMono-Regular");
m_pLog->SetLabel("CONSOLE");
m_pLog->SetPosition(0, 0);
m_pLog->SetGlyphSize(24);
m_pLog->SetParent(this);
};
void CConsoleGUI::Event( FGUI_Event_t event )
{
}
void CConsoleGUI::Draw()
{
SetPosition(20, 20);
m_pBackground->SetSize(g_nWindowWidth-40, g_nWindowHeight-40);
m_pBackground->SetSize(g_nWindowWidth-40, g_nWindowHeight-40);
}
void CConsoleGUI::Frame()
{
SetVisibility(console_bDrawUI);
}
void IConsoleUI::Init()
{
new CConsoleGUI;
};
void IConsoleUI::SetVisibility( bool bIsVisisble )
{
console_bDrawUI = bIsVisisble;
}
bool IConsoleUI::IsVisibile()
{
return console_bDrawUI;
}

View File

@@ -1,281 +1,26 @@
#include "fgui/fgui.h"
#include "input.h"
#include "mainmenu.h"
#include "networking.h"
#include "steam/steam_api_common.h"
#include "tier0/network.h"
#include "tier0/platform.h"
#include "ifilesystem.h"
#include "igamewindow.h"
#include "tier1/interface.h"
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
#include "tier0/lib.h"
#include "console.h"
#include "filesystem.h"
#include "rendering.h"
#include "engine.h"
#include "baseentity.h"
#include "server.h"
#include "physics.h"
#include "signal.h"
#include "steam/steam_api.h"
#include "steam/isteamgameserver.h"
#include "steam/steam_gameserver.h"
#include "networking.h"
#include "tier0/mem.h"
#include "sv_dll.h"
double fPrev = 0;
double fCurrent = 0;
funnyphysics *px;
IIClient *g_localClient;
CUtlVector<IIClient*> g_clients = {};
//-----------------------------------------------------------------------------
// Purpose: Engine entry point
//-----------------------------------------------------------------------------
extern "C" void FunnyMain( int argc, char **argv ) {
ICommandLine::CreateCommandLine(argc, argv);
IEngine::Init();
for (;;)
{
fPrev = fCurrent;
fCurrent = Plat_GetTime();
IEngine::Frame(fCurrent-fPrev);
};
/* deinit is handled explicitly */
};
//-----------------------------------------------------------------------------
// Purpose: Recieves signals from the system
//-----------------------------------------------------------------------------
void IEngine_Signal(int sig)
extern "C" void FunnyMain( int argc, char **argv )
{
printf("Trapped signal %i\n",sig);
switch (sig)
{
case SIGSEGV:
case SIGILL:
case SIGABRT:
printf("Consider running app with debugger attached\n");
Plat_Backtrace();
break;
default:
break;
};
IEngine::Shutdown();
Plat_Exit(0);
};
CommandLine()->CreateCommandLine(argc, argv);
//-----------------------------------------------------------------------------
// Purpose: Initializes engine
//-----------------------------------------------------------------------------
void IEngine::Init()
{
/* trap signals */
#ifdef __linux__
signal(SIGHUP, IEngine_Signal);
signal(SIGINT, IEngine_Signal);
signal(SIGQUIT, IEngine_Signal);
signal(SIGILL, IEngine_Signal);
signal(SIGTRAP, IEngine_Signal);
signal(SIGIOT, IEngine_Signal);
signal(SIGBUS, IEngine_Signal);
signal(SIGFPE, IEngine_Signal);
signal(SIGSEGV, IEngine_Signal);
signal(SIGTERM, IEngine_Signal);
#endif
#ifdef __WIN32__
signal(SIGINT, IEngine_Signal);
signal(SIGILL, IEngine_Signal);
signal(SIGFPE, IEngine_Signal);
signal(SIGSEGV, IEngine_Signal);
signal(SIGTERM, IEngine_Signal);
#endif
filesystem = (IFileSystem*)CreateInterface(FILESYSTEM_INTERFACE_NAME, NULL);
filesystem->Init();
#ifdef STEAM_ENABLED
if(SteamAPI_RestartAppIfNecessary(480))
{
Plat_Exit(0);
}
gamewindow = (IGameWindow*)CreateInterface(GAME_WINDOW_INTERFACE_NAME, NULL);
gamewindow->Init();
SteamErrMsg err;
if (SteamAPI_InitEx(&err) != k_ESteamAPIInitResult_OK)
{
Plat_FatalErrorFunc("Failed to init Steam: %s\n", err);
}
#endif
ServerGameDLL()->Init();
FileSystem()->InitFilesystem();
px = px_init();
if (!ICommandLine::CheckParam("-dedicated"))
{
// Run local client
g_localClient = new IIClient();
IIEngine::ConnectClient(g_localClient);
// Init IO
IVideo::Init();
Input()->Init();
Input()->SetInputMode(INPUT_MODE_MENU);
IFGUI::Init();
for (;;) {
gamewindow->UpdateWindow();
};
INetworking::Init();
// load game
IServer::LoadGame("funnygame");
// create pipelines for rendering
if (!ICommandLine::CheckParam("-dedicated"))
IVideo::CreatePipelines();
// execute default config
Console()->AddCommand("exec default.cfg;");
Console()->Execute();
if (INetworking::IsClient())
{
MainMenu()->Init();
IConsoleUI::Init();
}
};
//-----------------------------------------------------------------------------
// Purpose: Updates every frame
//-----------------------------------------------------------------------------
void IEngine::Frame(float fDelta)
{
#ifdef STEAM_ENABLED
SteamAPI_RunCallbacks();
#endif
IServer::Think(fDelta);
if (INetworking::IsClient())
{
MainMenu()->Frame();
IFGUI::Frame();
IVideo::Frame(fDelta);
}
};
//-----------------------------------------------------------------------------
// Purpose: Deinitializes engine
//-----------------------------------------------------------------------------
void IEngine::Shutdown()
{
if (INetworking::IsClient())
MainMenu()->Deinit();
INetworking::Deinit();
};
//-----------------------------------------------------------------------------
// Purpose: Spawns entity in the world
//-----------------------------------------------------------------------------
uint64_t g_lastServerID = 1;
uint64_t g_lastPredictedID = 1;
CBaseEntity *IIEngine::SpawnEntity( const char *szName )
{
for (auto &entity: EntityManager()->m_RegisteredEntities)
{
if (!V_strcmp(entity->m_szName, szName))
{
CBaseEntity *pEnt = entity->m_pfn();
pEnt->m_id = g_lastPredictedID+=1;
EntityManager()->m_entities.AppendTail(pEnt);
if (ICommandLine::CheckParam("-dedicated"))
return pEnt;
if (entity->m_pClientfn)
{
pEnt->pClientEntity = entity->m_pClientfn();
pEnt->pClientEntity->pEntity = pEnt;
}
return pEnt;
}
}
return 0;
};
//-----------------------------------------------------------------------------
// Purpose: Spawns entity without any parameters
//-----------------------------------------------------------------------------
void IIEngine::InitEntity( CBaseEntity *pEntity )
{
if (!pEntity)
return;
pEntity->Spawn();
if (pEntity->pClientEntity)
pEntity->pClientEntity->Spawn();
};
//-----------------------------------------------------------------------------
// Purpose: Destroys entity
//-----------------------------------------------------------------------------
void IIEngine::DestroyEntity( CBaseEntity *pEntity )
{
uint32_t i = 0;
if (pEntity == NULL)
return;
for (auto &entity: EntityManager()->m_entities)
{
if (pEntity == entity)
{
pEntity->Destroy();
if (pEntity->pClientEntity)
pEntity->pClientEntity->Destroy();
EntityManager()->m_entities.RemoveAt(i);
return;
}
i++;
}
};
//-----------------------------------------------------------------------------
// Purpose: Connects client to the server
//-----------------------------------------------------------------------------
void IIEngine::ConnectClient( IIClient *pClient )
{
g_clients.AppendTail(pClient);
}
//-----------------------------------------------------------------------------
// Purpose: Disconnects client from the server
//-----------------------------------------------------------------------------
void IIEngine::DisconnectClient( IIClient *pClient )
{
DisconnectClient(pClient->playerID);
}
void IIEngine::DisconnectClient( uint64_t playerID )
{
uint32_t i = 0;
for (auto &client: g_clients)
{
if (client->playerID == playerID)
{
g_clients.RemoveAt(i);
break;
}
i++;
}
};
void IIEngine::DisconnectClientByHandle( uint32_t playerHandle )
{
uint32_t i = 0;
for (auto &client: g_clients)
{
if (client->playerHandle == playerHandle)
{
IIEngine::DestroyEntity((CBaseEntity*)client->pBasePlayer);
g_clients.RemoveAt(i);
break;
}
i++;
}
};

View File

@@ -1,288 +1,86 @@
#include "interface.h"
#include "tier0/platform.h"
#include "tier1/commandline.h"
#include "filesystem.h"
#include "unistd.h"
#include <cstdio>
#include "ifilesystem.h"
#include "tier1/interface.h"
#include "tier0/lib.h"
#define BASEDIR "rtt"
#define GAMEDIR "funnygame"
struct PackHeader_t
size_t IFileHandle::Write( const void *pData, size_t nDataSize )
{
char id[8];
unsigned long long offset;
unsigned long long size;
};
struct PackDirectory_t
return m_pFileSystem->Write(this, pData, nDataSize);
}
size_t IFileHandle::Read( void *pData, size_t nDataSize )
{
char name[56];
unsigned long long offset;
unsigned long long size;
};
struct Pack_t
return m_pFileSystem->Read(this, pData, nDataSize);
}
size_t IFileHandle::Seek( ESeekMode eSeekMode, size_t nOffset )
{
FILE* handle;
PackHeader_t header;
CUtlVector<PackDirectory_t> files;
};
struct FileDirectory_t
return m_pFileSystem->Seek(this, eSeekMode, nOffset);
}
size_t IFileHandle::Tell( void )
{
CUtlString path;
Pack_t pack;
};
return m_pFileSystem->Tell(this);
}
void IFileHandle::Close( void )
{
m_pFileSystem->Close(this);
}
CUtlString fs_basedir;
CUtlString fs_gamedir;
CUtlSelfReferencingVector<FileDirectory_t> fs_directories;
interface CFileSystem: public IFileSystem
class CFileSystem : public IFileSystem
{
public:
virtual void Init() override {}
virtual void Frame() override {}
virtual void Deinit() override {}
virtual void Init() override {
filesystem_backend = (IFileSystem*)CreateInterface(FILESYSTEM_BACKEND_INTERFACE_NAME, NULL);
filesystem_backend->Init();
filesystem_pak = (IFileSystem*)CreateInterface(FILESYSTEM_PAK_INTERFACE_NAME, NULL);
filesystem_pak->Init();
};
virtual void Shutdown() override {
virtual void InitFilesystem( void ) override;
virtual void AddGameDirectory( const char *psz ) override;
virtual bool LoadPackFile( const char *szFilename ) override;
virtual void CreatePath( const char *szPath ) override;
virtual FileHandle_t Open( const char *szFilename, EFileOptions options ) override;
virtual void Close( FileHandle_t file ) override;
virtual size_t Size( FileHandle_t file ) override;
virtual size_t Read( FileHandle_t file, void *pOutput, size_t nSize) override;
virtual size_t ReadLine( FileHandle_t file, void *pOutput, size_t nSize) override;
virtual size_t Write( FileHandle_t file, void *pInput, size_t nSize) override;
virtual size_t Seek( FileHandle_t file, size_t nSize) override;
virtual size_t Tell( FileHandle_t file, size_t nSize) override;
virtual size_t fprintf( FileHandle_t file, const char *szFormat, ...) override;
};
static void AddDirectory( const char *psz );
static void AddFile( const char *psz );
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
{
IFileHandle *pHandle = NULL;
pHandle = filesystem_pak->Open(szFileName, eOpCode);
if (pHandle) return pHandle;
pHandle = filesystem_backend->Open(szFileName, eOpCode);
if (pHandle) return pHandle;
return NULL;
}
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
{
return pFile->Write(pData, nDataSize);
}
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
{
return pFile->Read(pData, nDataSize);
}
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
{
return pFile->Seek(eSeekMode, nOffset);
}
virtual size_t Tell( IFileHandle *pFile ) override
{
return pFile->Tell();
}
virtual void Close( IFileHandle *pFile ) override
{
}
};
DECLARE_ENGINE_INTERFACE(FileSystem, CFileSystem);
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CFileSystem::InitFilesystem()
{
#ifdef STATIC_BUILD
fs_basedir = ICommandLine::ParamValue("-basedir");
if ( fs_basedir == 0 )
fs_basedir=BASEDIR;
if ( fs_basedir.GetString()[0] == '-' )
fs_basedir=BASEDIR;
fs_gamedir = ICommandLine::ParamValue("-gamedir");
if ( fs_gamedir == 0 )
fs_gamedir=GAMEDIR;
if ( fs_gamedir.GetString()[0] == '-' )
fs_gamedir=GAMEDIR;
AddGameDirectory(fs_gamedir);
#endif
AddGameDirectory(".");
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CFileSystem::AddFile( const char *psz )
{
CUtlString extension = Plat_GetExtension(psz);
if (extension=="pak")
{
FileSystem()->LoadPackFile(psz);
};
}
//-----------------------------------------------------------------------------
// Adds directory which can contain pack files
//-----------------------------------------------------------------------------
void CFileSystem::AddGameDirectory( const char *psz )
{
FileDirectory_t dir = {};
dir.path = psz;
fs_directories.AppendTail(dir);
Plat_ListDirRecursive(psz, CFileSystem::AddFile, 0);
for (auto &dir: fs_directories)
{
V_printf("%s\n",(char*)dir.path);
};
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CFileSystem::LoadPackFile( const char *szFilename )
{
Pack_t pack = {};
PackHeader_t header = {};
unsigned long long nNumFiles = 0;
PackDirectory_t *pDirs = NULL;
FILE* f = V_fopen(szFilename, "rb");
if (!f)
Plat_FatalErrorFunc("Failed to open %s",szFilename);
V_fread(&header,1,sizeof(header),f);
// check for rttpacku
if (
header.id[0]!='r' || header.id[1] != 't' || header.id[2] != 't' || header.id[3]!='p' ||
header.id[4]!='a' || header.id[5] != 'c' || header.id[6] != 'k' || header.id[7]!='u'
)
{
Plat_FatalErrorFunc("%s is not a pack file",szFilename);
}
nNumFiles = header.size/sizeof(PackDirectory_t);
pDirs = (PackDirectory_t*)V_malloc(header.size);
V_fseek(f, header.offset, SEEK_SET);
V_fread(pDirs, sizeof(PackDirectory_t), nNumFiles, f);
pack.header = header;
pack.handle = f;
pack.files = CUtlVector<PackDirectory_t>(nNumFiles);
V_memcpy(pack.files.GetData(),pDirs, header.size);
V_free(pDirs);
nNumFiles = header.size/sizeof(PackDirectory_t);
FileDirectory_t fd = {};
fd.path = szFilename;
fd.pack = pack;
fs_directories.AppendTail(fd);
return true;
}
//-----------------------------------------------------------------------------
// Creates path
//-----------------------------------------------------------------------------
void CFileSystem::CreatePath( const char *szPath )
{
}
//-----------------------------------------------------------------------------
// Opens file
// If it is located in a pack then it can only be read
//-----------------------------------------------------------------------------
FileHandle_t CFileSystem::Open( const char *szFilename, EFileOptions options )
{
if (options == IFILE_READ)
{
FILE *file = V_fopen(szFilename, "rb");
/* found in fs */
if ( file != NULL )
{
FileHandle_t filehandle = new FileHandle_s;
filehandle->file = file;
filehandle->nPtr = 0;
filehandle->options = IFILE_READ;
/* get size */
V_fseek(file, 0, SEEK_END);
filehandle->nSize = V_ftell(file);
V_fseek(file, 0, SEEK_SET);
return filehandle;
}
/* not found in fs, try to search in packs */
for ( auto &pak: fs_directories )
{
for ( auto &file: pak.pack.files )
{
if ( !strncmp(file.name, szFilename, 56) )
{
FileHandle_t filehandle = new FileHandle_s;
filehandle->file = 0;
filehandle->parent = pak.pack.handle;
filehandle->nSize = file.size;
filehandle->nOffset = file.offset;
filehandle->nPtr = 0;
filehandle->options = IFILE_READ;
return filehandle;
}
}
};
}
return 0;
}
//-----------------------------------------------------------------------------
// Closes file
//-----------------------------------------------------------------------------
void CFileSystem::Close( FileHandle_t file )
{
/* close only fs files */
if (file->file)
{
V_fclose(file->file);
}
delete file;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
size_t CFileSystem::Size( FileHandle_t file )
{
return file->nSize;
}
//-----------------------------------------------------------------------------
// Reads nSize bytes of file
//-----------------------------------------------------------------------------
size_t CFileSystem::Read( FileHandle_t file, void *pOutput, size_t nSize)
{
if (file->file)
{
size_t readsize = V_fread(pOutput, 1, nSize, file->file);
file->nPtr+=readsize;
return readsize;
}
size_t readsize = V_fseek(file->parent, file->nOffset, file->nPtr);
V_fread(pOutput, 1, nSize, file->parent);
return readsize;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
size_t CFileSystem::ReadLine( FileHandle_t file, void *pOutput, size_t nSize)
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
size_t CFileSystem::Write( FileHandle_t file, void *pInput, size_t nSize)
{
}
size_t CFileSystem::Seek( FileHandle_t file, size_t nSize)
{
}
size_t CFileSystem::Tell( FileHandle_t file, size_t nSize)
{
}
size_t CFileSystem::fprintf( FileHandle_t file, const char *szFormat, ...)
{
}
IFileSystem *filesystem;
IFileSystem *filesystem_backend;
IFileSystem *filesystem_pak;
EXPOSE_INTERFACE(CFileSystem, IFileSystem, FILESYSTEM_INTERFACE_NAME);

View File

@@ -0,0 +1,94 @@
#include "ifilesystem.h"
#include "tier1/interface.h"
#include "tier0/lib.h"
class CLIBCFileHandle : public IFileHandle
{
public:
FILE *m_pFile;
};
class CLIBCFileSystem : public IFileSystem
{
public:
virtual void Init() override {};
virtual void Shutdown() override {};
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
{
const char *szOperation;
FILE *pFile;
CLIBCFileHandle *pHandle = NULL;
switch (eOpCode)
{
case FILEMODE_READ:
szOperation = "r";
break;
default:
V_printf("Operation is not supported\n");
break;
}
pFile = V_fopen(szFileName, szOperation);
if (!pFile)
return NULL;
pHandle = new CLIBCFileHandle;
pHandle->m_pFileSystem = this;
pHandle->m_pFile = pFile;
return pHandle;
}
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
{
return 0;
}
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
{
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
if (!pHandle)
return 0;
return V_fread( pData, 1, nDataSize, pHandle->m_pFile );
}
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
{
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
int eLibcSeekMode = 0;
switch (eSeekMode) {
case SEEKMODE_SET:
eLibcSeekMode = SEEK_SET;
break;
case SEEKMODE_RELATIVE_END:
eLibcSeekMode = SEEK_END;
break;
case SEEKMODE_RELATIVE_START:
eLibcSeekMode = SEEK_CUR;
break;
}
if (!pHandle)
return 0;
return V_fseek( pHandle->m_pFile, eLibcSeekMode, nOffset );
}
virtual size_t Tell( IFileHandle *pFile ) override
{
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
if (!pHandle)
return 0;
return V_ftell(pHandle->m_pFile);
}
virtual void Close( IFileHandle *pFile ) override
{
CLIBCFileHandle *pHandle = (CLIBCFileHandle*)pFile;
if (!pHandle)
return;
V_fclose(pHandle->m_pFile);
delete pHandle;
}
};
EXPOSE_INTERFACE(CLIBCFileSystem, IFileSystem, FILESYSTEM_BACKEND_INTERFACE_NAME);

81
engine/filesystem_pak.cpp Normal file
View File

@@ -0,0 +1,81 @@
#include "ifilesystem.h"
#include "tier1/interface.h"
#include "tier0/lib.h"
class CPAKFileHandle : public IFileHandle
{
public:
};
class CPAKFileSystem : public IFileSystem
{
public:
virtual void Init() override {};
virtual void Shutdown() override {};
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
{
const char *szOperation;
switch (eOpCode)
{
case FILEMODE_READ:
szOperation = "r";
break;
default:
V_printf("Operation is not supported\n");
break;
}
return 0;
CPAKFileHandle *pHandle = new CPAKFileHandle;
return pHandle;
}
virtual size_t Write( IFileHandle *pFile, const void *pData, size_t nDataSize ) override
{
return 0;
}
virtual size_t Read( IFileHandle *pFile, void *pData, size_t nDataSize ) override
{
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
if (!pHandle)
return 0;
return 0;
}
virtual size_t Seek( IFileHandle *pFile, ESeekMode eSeekMode, size_t nOffset ) override
{
int eLibcSeekMode = 0;
switch (eSeekMode) {
case SEEKMODE_SET:
eLibcSeekMode = SEEK_SET;
break;
case SEEKMODE_RELATIVE_END:
eLibcSeekMode = SEEK_END;
break;
case SEEKMODE_RELATIVE_START:
eLibcSeekMode = SEEK_CUR;
break;
}
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
if (!pHandle)
return 0;
}
virtual size_t Tell( IFileHandle *pFile ) override
{
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
if (!pHandle)
return 0;
}
virtual void Close( IFileHandle *pFile ) override
{
CPAKFileHandle *pHandle = (CPAKFileHandle*)pFile;
if (!pHandle)
return;
delete pHandle;
}
};
EXPOSE_INTERFACE(CPAKFileSystem, IFileSystem, FILESYSTEM_PAK_INTERFACE_NAME);

View File

@@ -1,165 +0,0 @@
#include "gamemode.h"
#include "engine.h"
#include "interface.h"
#include "playerstart.h"
#include "networking.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
CGameMode *pCurrentMode = NULL;
CUtlString szCurrentModeName;
//-----------------------------------------------------------------------------
// Round begin handler
//-----------------------------------------------------------------------------
void CGameMode::RoundBegin( void )
{
size_t i = 0;
for (auto &start: g_PlayerStarts)
{
start->RoundEnd();
}
for (auto &player: g_clients)
{
CPlayerStart *pSelectedStart = NULL;
for (auto &start: g_PlayerStarts)
{
if (start->m_bIsRunning == false)
pSelectedStart = start;
};
if (pSelectedStart)
pSelectedStart->RoundStart(player);
i++;
}
for (auto &client: g_clients)
{
CSteamID steamID = CSteamID();
if ( client->playerID == 0)
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
else
V_printf("%s\t", SteamFriends()->GetPersonaName());
V_printf("%llu\t", client->playerID);
V_printf("%u\n", client->playerHandle);
}
}
//-----------------------------------------------------------------------------
// Round end handler
//-----------------------------------------------------------------------------
void CGameMode::RoundEnd( void )
{
}
class CGameModeManager: public IGameModeManager
{
public:
virtual void Init( void ) override;
virtual void Frame( void ) override;
virtual void Deinit( void ) override;
virtual void StartGameMode( const char *szName ) override;
virtual const char *GetCurrentGameMode( void ) override;
virtual CGameMode *GetCurrentGameModeClass( void ) override;
virtual void RestartCurrentGameMode( void ) override;
};
DECLARE_ENGINE_INTERFACE(GameModeManager, CGameModeManager);
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameModeManager::Init( void )
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameModeManager::Frame( void )
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameModeManager::Deinit( void )
{
}
//-----------------------------------------------------------------------------
// Sets gamemode
//-----------------------------------------------------------------------------
void CGameModeManager::StartGameMode( const char *szName )
{
if (pCurrentMode)
{
pCurrentMode->RoundEnd();
delete pCurrentMode;
}
for (auto &mode: m_RegisteredGameModes)
{
if (!V_strcmp(mode->m_szName, szName))
{
pCurrentMode = mode->m_pfn();
pCurrentMode->RoundBegin();
szCurrentModeName = szName;
return;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CGameModeManager::GetCurrentGameMode( void )
{
return szCurrentModeName;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGameMode *CGameModeManager::GetCurrentGameModeClass( void )
{
return pCurrentMode;
}
//-----------------------------------------------------------------------------
// Restarts the gamemode
//-----------------------------------------------------------------------------
void CGameModeManager::RestartCurrentGameMode( void )
{
if (!pCurrentMode)
return;
if (INetworking::IsServer())
{
PacketGameMode_t mode = {};
mode.type = PACKET_TYPE_GAMEMODE_START;
V_memcpy(mode.szName,szCurrentModeName, min(szCurrentModeName.GetLenght(), 255));
for (auto &client: g_clients)
{
INetworking::SendData(&mode, sizeof(mode), client, MESSAGE_MODE_RELIABLE);
};
};
pCurrentMode->RoundEnd();
pCurrentMode->RoundBegin();
}
CGameModeRegistry::CGameModeRegistry(const char *szName, GameModeRegistryFn pfn) :
m_szName(szName), m_pfn(pfn)
{
GameModeManager()->m_RegisteredGameModes.AppendTail(this);
};

60
engine/gamewindow_sdl.cpp Normal file
View File

@@ -0,0 +1,60 @@
#include "SDL3/SDL_error.h"
#include "igamewindow.h"
#include "tier1/interface.h"
#include "tier0/lib.h"
#include "tier0/platform.h"
#define SDL_MAIN_HANDLED
#include "SDL3/SDL.h"
#include "SDL3/SDL_init.h"
#include "SDL3/SDL_video.h"
#include "SDL3/SDL_vulkan.h"
#include "SDL3/SDL_events.h"
SDL_Window *g_pWindow;
IGameWindow *gamewindow;
class CSDLGameWindow: public IGameWindow
{
public:
virtual void Init() override;
virtual void Shutdown() override;
virtual void UpdateWindow() override;
};
void CSDLGameWindow::Init()
{
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD))
Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError());
g_pWindow = SDL_CreateWindow("funnygame", 1280, 720, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
if (!g_pWindow)
Plat_FatalErrorFunc("SDL_Init: %s\n", SDL_GetError());
}
void CSDLGameWindow::Shutdown()
{
}
void CSDLGameWindow::UpdateWindow()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_EVENT_QUIT:
SDL_Quit();
Plat_Exit(0);
break;
default:
break;
}
}
}
EXPOSE_INTERFACE(CSDLGameWindow, IGameWindow, GAME_WINDOW_INTERFACE_NAME);

View File

@@ -1,301 +0,0 @@
#include "input.h"
#include "console.h"
#include "interface.h"
#include "mainmenu.h"
#include "tier0/lib.h"
#include "tier1/commandline.h"
#include "math3d.h"
char g_PressedKeys[KEY_NUM_KEYS];
float g_fAxisValues[AXIS_NUM_AXIS];
float g_fAxisModifiers[AXIS_NUM_AXIS];
CUtlString g_bindings[256];
bool g_bController = false;
struct KeyName_t {
const char *szName;
EInputKey key;
};
KeyName_t keys[] = {
{"ESCAPE",KEY_ESCAPE},
{"ESC",KEY_ESCAPE},
{"TAB",KEY_TAB},
{"ENTER",KEY_ENTER},
{"CTRL",KEY_CONTROL},
{"CONTROL",KEY_CONTROL},
{"SHIFT",KEY_SHIFT},
{"ALT",KEY_ALT},
{"SPACE",KEY_SPACE},
{"BACKSPACE",KEY_BACKSPACE},
{"[",KEY_LBRACKET},
{"]",KEY_RBRACKET},
{"{",KEY_LBRACKET},
{"}",KEY_RBRACKET},
{"\\",KEY_BACKSLASH},
{";",KEY_SEMICOLON},
{":",KEY_SEMICOLON},
{"\'",KEY_APOSTROPHE},
{"\"",KEY_APOSTROPHE},
{"F1",KEY_F1},
{"F2",KEY_F2},
{"F3",KEY_F3},
{"F4",KEY_F4},
{"F5",KEY_F5},
{"F6",KEY_F6},
{"F7",KEY_F7},
{"F8",KEY_F8},
{"F9",KEY_F9},
{"F10",KEY_F10},
{"F11",KEY_F11},
{"F12",KEY_F12},
{"1",KEY_1},
{"2",KEY_2},
{"3",KEY_3},
{"4",KEY_4},
{"5",KEY_5},
{"6",KEY_6},
{"7",KEY_7},
{"8",KEY_8},
{"9",KEY_9},
{"0",KEY_0},
{"A",KEY_A},
{"B",KEY_B},
{"C",KEY_C},
{"D",KEY_D},
{"E",KEY_E},
{"F",KEY_F},
{"G",KEY_G},
{"H",KEY_H},
{"I",KEY_I},
{"J",KEY_J},
{"K",KEY_K},
{"L",KEY_L},
{"M",KEY_M},
{"N",KEY_N},
{"O",KEY_O},
{"P",KEY_P},
{"Q",KEY_Q},
{"R",KEY_R},
{"S",KEY_S},
{"T",KEY_T},
{"U",KEY_U},
{"V",KEY_V},
{"W",KEY_W},
{"X",KEY_X},
{"Y",KEY_Y},
{"Z",KEY_Z},
};
//-----------------------------------------------------------------------------
// Converts string (eg. tab, mouse0, w, 0) to keycode
//-----------------------------------------------------------------------------
EInputKey IInput_StringToKey( char *psz )
{
for (uint32_t i = 0; i<sizeof(keys)/sizeof(KeyName_t); i++)
{
if (!V_stricmp(keys[i].szName, psz))
return keys[i].key;
};
return KEY_NONE;
};
interface CInput: public IInput
{
public:
virtual void Init() override;
virtual void Frame() override;
virtual void Deinit() override;
virtual void KeyEvent( EInputKey key, EKeyEventType event ) override;
virtual void AxisEvent( EInputAxis axis, float fValue ) override;
};
DECLARE_ENGINE_INTERFACE(Input, CInput)
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CInput::Init( void )
{
}
CUtlVector<EInputMode> g_inputModeStack = {INPUT_MODE_GAME, INPUT_MODE_MENU};
//-----------------------------------------------------------------------------
// Key event may have different different effects based on current input mode.
//
// GAME:
// Generates command call when pressed the key. eg +forward; -left;
// Just to be sure we put ; in the end of the command.
// When user releases the key command event is not generated. But if the first
// command contains + as first character ( in case of example +forward ), then
// it fires -forward
//
// MENU:
// Sends all event to FGUI. KEY_ESCAPE key makes leave the menu and get back to
// the game.
//
// CONSOLE:
// Works as permanent input field.
//
// INPUT FIELD:
// Doesn't recieve any events except for KEY_ESCAPE and KEY_ENTER
//-----------------------------------------------------------------------------
void CInput::KeyEvent( EInputKey key, EKeyEventType event )
{
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_ESCAPE)
{
if (g_inputModeStack.GetSize() == 1)
{
g_inputModeStack.AppendTail(INPUT_MODE_MENU);
IInput::SetInputMode(INPUT_MODE_MENU);
MainMenu()->SetVisibility(true);
return;
}
if (IConsoleUI::IsVisibile())
IConsoleUI::SetVisibility(false);
IInput::SetInputMode(g_inputModeStack[g_inputModeStack.GetSize()-2]);
g_inputModeStack.RemoveTail();
if (g_inputModeStack[g_inputModeStack.GetSize()-1] != INPUT_MODE_MENU)
{
MainMenu()->SetVisibility(false);
}
return;
};
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_TILDE)
{
if (IConsoleUI::IsVisibile())
{
IInput::SetInputMode(g_inputModeStack[g_inputModeStack.GetSize()-2]);
g_inputModeStack.RemoveTail();
IConsoleUI::SetVisibility(false);
} else
{
g_inputModeStack.AppendTail(INPUT_MODE_CONSOLE);
IInput::SetInputMode(INPUT_MODE_CONSOLE);
IConsoleUI::SetVisibility(true);
}
return;
};
if (event == KEY_EVENT_TYPE_DOWN && key == KEY_F11)
{
Console()->AddCommand("exit;");
return;
}
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_GAME)
{
if (event == KEY_EVENT_TYPE_DOWN) {
Console()->AddCommand(g_bindings[key]);
Console()->AddCommand(";");
}
if (event == KEY_EVENT_TYPE_UP)
{
auto binding = Console()->ParseCommandLine(g_bindings[key]);
if (binding.GetSize()==0)
return;
if (binding[0].GetSize() == 0)
return;
if (binding[0][0].GetString()[0] == '+')
{
CUtlString command = binding[0][0];
command.GetString()[0] = '-';
Console()->AddCommand(command);
Console()->AddCommand(";");
}
}
}
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_MENU)
{
};
}
//-----------------------------------------------------------------------------
// Axis events for the input devices such as mouse and controller.
// Game needs to explicitly support all of the devices.
//-----------------------------------------------------------------------------
void CInput::AxisEvent( EInputAxis axis, float fValue )
{
if (g_inputModeStack[g_inputModeStack.GetSize()-1] == INPUT_MODE_GAME)
{
if (axis == AXIS_MOUSE_X || axis == AXIS_MOUSE_Y)
{
g_bController = false;
g_fAxisValues[axis] += fValue*3.09;
}
if (axis == AXIS_CONTROLLER_PITCH || axis == AXIS_CONTROLLER_YAW)
{
g_bController = true;
g_fAxisModifiers[axis] = fValue*3.09;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CInput::Frame( void )
{
g_fAxisValues[AXIS_MOUSE_X] += g_fAxisModifiers[AXIS_CONTROLLER_PITCH];
g_fAxisValues[AXIS_MOUSE_Y] += g_fAxisModifiers[AXIS_CONTROLLER_YAW];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CInput::Deinit( void )
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void IInput_Bind( int argc, char **argv )
{
if (argc == 1)
return;
if (argc == 2)
return;
EInputKey key = IInput_StringToKey(argv[1]);
if (key == KEY_NONE)
return;
g_bindings[key] = 0;
for ( int i = 2; i<argc; i++ )
{
g_bindings[key].AppendTail(argv[i]);
g_bindings[key].AppendTail(" ");
}
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void IInput_Unbind( int argc, char **argv )
{
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void IInput_UnbindAll( int argc, char **argv )
{
};
ConCommand BindCmd("bind", IInput_Bind, 0);
ConCommand UnbindCmd("unbind", IInput_Unbind, 0);
ConCommand UnbindAllcmd("unbindall", IInput_UnbindAll, 0);

View File

@@ -1,7 +0,0 @@
#include "interface.h"
#include "tier0/lib.h"
CInterfaceRegistry::CInterfaceRegistry( const char *szName, InterfaceRegistryFn pfn )
{
};

View File

@@ -1,92 +0,0 @@
#include "level.h"
#include "baseentity.h"
#include "brush.h"
#include "engine.h"
#include "filesystem.h"
#include "interface.h"
#include "tier1/utlbuffer.h"
#include "tier1/utlstring.h"
struct MapHeader_t
{
char id[8];
uint32_t nEntities;
};
struct EntityHeader_t
{
uint32_t nTriangles;
uint32_t nProperties;
};
interface CLevelManager: public ILevelManager
{
public:
virtual void Init() override {}
virtual void Frame() override {}
virtual void Deinit() override {}
virtual void LoadLevel( const char *szLevelName ) override;
};
DECLARE_ENGINE_INTERFACE(LevelManager, CLevelManager);
//-----------------------------------------------------------------------------
// Loads level from file, deserializes it and creates entities.
//-----------------------------------------------------------------------------
void CLevelManager::LoadLevel( const char *szLevelName )
{
FileHandle_t handle = FileSystem()->Open(CUtlString("%s.fmap",szLevelName), IFILE_READ);
CUtlBuffer<char> mapdata(FileSystem()->Size(handle));
FileSystem()->Read(handle, mapdata.GetMemory(), mapdata.GetSize());
FileSystem()->Close(handle);
MapHeader_t* pHeader = (MapHeader_t*)mapdata.GetMemory();
char *pData = (char*)mapdata.GetMemory()+sizeof(MapHeader_t);
for ( uint32_t i = 0; i < pHeader->nEntities; i++ )
{
CUtlBuffer<char> szEntityType(V_strlen(pData)+1);
V_strcpy(szEntityType, pData);
pData+=szEntityType.GetSize();
EntityHeader_t* pEntityHeader = (EntityHeader_t*)pData;
pData+=sizeof(EntityHeader_t);
CBaseEntity *pEntity = IIEngine::SpawnEntity(szEntityType);
if (!pEntity)
continue;
for ( uint32_t j = 0; j<pEntityHeader->nProperties; j++ )
{
CUtlBuffer<char> szParamName(V_strlen(pData)+1);
V_strcpy(szParamName, pData);
pData+=szParamName.GetSize();
CUtlBuffer<char> szParamValue(V_strlen(pData)+1);
V_strcpy(szParamValue, pData);
pData+=szParamValue.GetSize();
pEntity->ReadParameter(szParamName, szParamValue);
};
CBrushEntity *pBrush = dynamic_cast<CBrushEntity*>(pEntity);
if (!pBrush)
{
IIEngine::InitEntity(pEntity);
continue;
}
pBrush->m_mesh = CUtlVector<Triangle_t>(0);
for ( uint32_t j = 0; j<pEntityHeader->nTriangles; j++ )
{
Triangle_t triangle = {};
V_memcpy(triangle.location, pData, 4*9);
pData+=4*9;
V_memcpy(triangle.uv, pData, 4*6);
pData+=4*6;
CUtlBuffer<char> szTextureName(V_strlen(pData)+1);
V_strcpy(szTextureName, pData);
pData+=szTextureName.GetSize();
pBrush->m_mesh.AppendTail(triangle);
};
IIEngine::InitEntity(pBrush);
};
};

View File

@@ -1,49 +0,0 @@
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"
#include "audio.h"
class CMASound
{
};
class CMAAudioManager: public IAudioManager
{
virtual void Init() override;
virtual void Frame() override;
virtual void Deinit() override;
virtual ISound *CreateSound() override;
virtual I3DSound *Create3DSound() override;
};
DECLARE_ENGINE_INTERFACE(AudioManager, CMAAudioManager)
ma_engine ma_audioEngine;
void CMAAudioManager::Init()
{
ma_result r;
r = ma_engine_init(NULL, &ma_audioEngine);
}
void CMAAudioManager::Frame()
{
}
void CMAAudioManager::Deinit()
{
}
ISound *CMAAudioManager::CreateSound()
{
}
I3DSound *CMAAudioManager::Create3DSound()
{
}

View File

@@ -1,4 +0,0 @@
#define MINIAUDIO_IMPLEMENTATION
#include "miniaudio.h"

View File

@@ -1,156 +0,0 @@
#include "mesh.h"
#include "cglm/mat4.h"
#include "rendering.h"
CUtlVector<IMeshInstance*> g_meshes;
class CMeshInstance: public IMeshInstance
{
public:
virtual void SetPosition( vec3 position ) override;
virtual void SetRotationEuler( vec3 angle ) override;
virtual void SetRotationQuat( vec4 quaternion) override;
virtual void SetMatrix( mat4 matrix ) override;
virtual void SetScale( vec3 scale ) override;
virtual void Draw() override;
mat4 m_matrix;
vec3 m_position;
IVertexBuffer *m_pVertexBuffer;
IIndexBuffer *m_pIndexBuffer;
};
void CMeshInstance::SetPosition( vec3 position )
{
glm_vec3_copy(position, m_position);
}
void CMeshInstance::SetRotationEuler( vec3 angle )
{
}
void CMeshInstance::SetRotationQuat( vec4 quaternion)
{
}
void CMeshInstance::SetMatrix( mat4 matrix )
{
glm_mat4_copy(matrix, m_matrix);
}
void CMeshInstance::SetScale( vec3 scale )
{
}
void CMeshInstance::Draw()
{
g_meshes.AppendTail(this);
}
class CMesh: public IMesh
{
public:
virtual void SetVertexBuffer( IVertexBuffer *pBuffer ) override;
virtual void SetIndexBuffer( IIndexBuffer *pBuffer ) override;
virtual IMeshInstance *CreateInstance() override;
IVertexBuffer *m_pVertexBuffer = 0;
IIndexBuffer *m_pIndexBuffer = 0;
};
void CMesh::SetVertexBuffer( IVertexBuffer *pBuffer )
{
m_pVertexBuffer = pBuffer;
}
void CMesh::SetIndexBuffer( IIndexBuffer *pBuffer )
{
m_pIndexBuffer = pBuffer;
}
IMeshInstance *CMesh::CreateInstance()
{
CMeshInstance *pInstance = new CMeshInstance;
pInstance->m_pVertexBuffer = m_pVertexBuffer;
pInstance->m_pIndexBuffer = m_pIndexBuffer;
return pInstance;
};
IGraphicsPipeline *g_MeshPipeline;
class CMeshRendering: public IMeshRendering
{
virtual void Init() override;
virtual void Frame( float fDelta ) override;
virtual void Deinit() override;
};
void CMeshRendering::Init()
{
g_MeshPipeline = Renderer()->CreateGraphicsPipeline(
{
{"gfx/mesh_vert.shader", SHADER_TYPE_VERTEX},
{"gfx/mesh_frag.shader", SHADER_TYPE_FRAGMENT},
},
{
{SHADER_INPUT_TYPE_UNIFORM_BUFFER,0},
{SHADER_INPUT_TYPE_TEXTURES,1},
},
80,
20,
{{0,0,EVertexFormat::VERTEX_FORMAT_X32Y32Z32}, {12,1,EVertexFormat::VERTEX_FORMAT_X32Y32}},
{EImageFormat::IMAGE_FORMAT_R8G8B8A8},
true
);
}
void CMeshRendering::Frame( float fDelta )
{
g_MeshPipeline->BindData(0, Renderer()->GetCameraMatrix(), 0);
g_MeshPipeline->PushBindings();
Renderer()->ResetState();
Renderer()->SetDepthMode(DEPTH_MODE_LESS);
Renderer()->BindPipeline(g_MeshPipeline);
for (auto &v: g_meshes)
{
CMeshInstance *pMesh = (CMeshInstance*)v;
struct {
mat4 i;
uint32_t a = 0;
uint32_t b = 0;
uint32_t c = 0;
} constants;
glm_mat4_copy(pMesh->m_matrix,constants.i);
constants.i[3][0] = pMesh->m_position[0];
constants.i[3][1] = pMesh->m_position[1];
constants.i[3][2] = pMesh->m_position[2];
Renderer()->SetConstants(sizeof(constants), &constants);
Renderer()->Draw(pMesh->m_pVertexBuffer, pMesh->m_pIndexBuffer);
}
g_meshes = {};
}
void CMeshRendering::Deinit()
{
}
IMesh *IMeshRendering::CreateMesh()
{
CMesh *pMesh = new CMesh;
return pMesh;
};
DECLARE_MESH_RENDERING_STAGE(CMeshRendering, mesh_rendering)

View File

@@ -1,685 +0,0 @@
#include "Metal/Metal.hpp"
#include "math3d.h"
#include "filesystem.h"
#include "rendering.h"
#include "tier0/lib.h"
#include "tier1/utlvector.h"
#include "tier0/platform.h"
#include "rendering.h"
#include "ml_video.h"
#define STB_IMAGE_IMPLEMENTATION
#if defined(__APPLE__) && defined(__MACH__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
// iOS
#define STBI_NO_THREAD_LOCALS
#else
// macOS
#endif
#else
// Other platforms
#endif
#include "stb_image.h"
mat4 g_cameraView;
IImage *g_meshDepth;
IImage *g_meshDepthMSAA;
IImage *g_meshColor;
IImage *g_meshColorMSAA;
CUtlVector<ITexture*> g_textures;
IBuffer *g_cameraProperties;
struct CameraProjection {
mat4 viewprojection;
};
CameraProjection *g_cameraDataMap;
static MTL::RenderPassDescriptor *s_pRenderPass;
static MTL::RenderCommandEncoder *s_pEncoder;
static uint32_t s_nNumAttachments;
CUtlVector<MTL::Texture*> g_destroyImageBuffer;
CUtlVector<MTL::Buffer*> g_destroyBuffersBuffer;
extern MTL::PixelFormat g_swapchainFormat;
MTL::PixelFormat IRenderer_FormatToMl( EImageFormat format )
{
switch (format)
{
case IMAGE_FORMAT_R8G8B8A8: return MTL::PixelFormatRGBA8Unorm;
case IMAGE_FORMAT_R16G16B16A16: return MTL::PixelFormatRGBA16Unorm;
case IMAGE_FORMAT_DEPTH: return MTL::PixelFormatDepth32Float;
case IMAGE_FORMAT_WINDOW: return g_swapchainFormat;
default: return MTL::PixelFormatRGBA8Unorm;
}
};
MTL::VertexFormat IRenderer_VertexToMl( EVertexFormat format )
{
switch (format)
{
case VERTEX_FORMAT_X16: return MTL::VertexFormatHalf;
case VERTEX_FORMAT_X16Y16: return MTL::VertexFormatHalf2;
case VERTEX_FORMAT_X16Y16Z16: return MTL::VertexFormatHalf3;
case VERTEX_FORMAT_X16Y16Z16W16: return MTL::VertexFormatHalf4;
case VERTEX_FORMAT_X32: return MTL::VertexFormatFloat;
case VERTEX_FORMAT_X32Y32: return MTL::VertexFormatFloat2;
case VERTEX_FORMAT_X32Y32Z32: return MTL::VertexFormatFloat3;
case VERTEX_FORMAT_X32Y32Z32W32: return MTL::VertexFormatFloat4;
default: return MTL::VertexFormatFloat3;
}
};
MTL::LoadAction IRenderer_LoadOpMl( EAttachmentLoadMode mode )
{
switch (mode)
{
case ATTACHMENT_LOAD_MODE_DONT_CARE: return MTL::LoadActionDontCare;
case ATTACHMENT_LOAD_MODE_CLEAR: return MTL::LoadActionClear;
case ATTACHMENT_LOAD_MODE_LOAD: return MTL::LoadActionLoad;
default: return MTL::LoadActionDontCare;
}
}
MTL::StoreAction IRenderer_StoreOpMl( EAttachmentStoreMode mode )
{
switch (mode)
{
case ATTACHMENT_STORE_MODE_DONT_CARE: return MTL::StoreActionStore;
case ATTACHMENT_STORE_MODE_STORE: return MTL::StoreActionStore;
default: return MTL::StoreActionDontCare;
}
}
class CMlBuffer: public IBuffer
{
public:
void *Map() override;
void Unmap() override;
MTL::Buffer *m_buffer;
uint32_t m_nSize;
};
class CMlImage: public IImage
{
public:
MTL::Texture *m_image;
};
void *CMlBuffer::Map()
{
return m_buffer->contents();
}
void CMlBuffer::Unmap()
{
}
struct MLShader_t {
EShaderType shaderType;
MTL::Library *library;
MTL::Function *function;
NS::String *szMain;
};
class CMlGraphicsPipeline: public IGraphicsPipeline
{
public:
CUtlVector<MLShader_t> m_shaders;
MTL::RenderPipelineState *m_pipeline;
CUtlVector<ShaderInput_t> m_inputs;
uint32_t m_nVertexSize;
};
class CMlTexture: public ITexture
{
public:
MTL::Texture *m_texture;
};
IStorageBuffer *IRenderer::CreateStorageBuffer( uint32_t uSize )
{
CMlBuffer *pBuffer = new CMlBuffer;
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
pBuffer->m_nSize = uSize;
return pBuffer;
}
IUniformBuffer *IRenderer::CreateUniformBuffer( uint32_t uSize )
{
CMlBuffer *pBuffer = new CMlBuffer;
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
pBuffer->m_nSize = uSize;
return pBuffer;
}
IVertexBuffer *IRenderer::CreateVertexBuffer( uint32_t uSize )
{
CMlBuffer *pBuffer = new CMlBuffer;
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
pBuffer->m_nSize = uSize;
return pBuffer;
}
IIndexBuffer *IRenderer::CreateIndexBuffer( uint32_t uSize )
{
CMlBuffer *pBuffer = new CMlBuffer;
pBuffer->m_buffer = g_mlDevice->newBuffer(uSize, MTL::ResourceStorageModeShared);
pBuffer->m_nSize = uSize;
return pBuffer;
}
IImage *IRenderer::CreateImage( EImageFormat format, uint32_t usage, uint32_t nWidth, uint32_t nHeight, uint32_t nSamples )
{
CMlImage *pImage = new CMlImage;
MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init();
pCreateInfo->setPixelFormat(IRenderer_FormatToMl(format));
pCreateInfo->setWidth(nWidth);
pCreateInfo->setHeight(nHeight);
MTL::TextureUsage mlusage = 0;
if (usage&IMAGE_USAGE_COLOR_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget;
if (usage&IMAGE_USAGE_DEPTH_ATTACHMENT) mlusage |= MTL::TextureUsageRenderTarget;
mlusage |= MTL::TextureUsageShaderRead;
mlusage |= MTL::TextureUsageShaderWrite;
pCreateInfo->setUsage(mlusage);
pImage->m_image = g_mlDevice->newTexture(pCreateInfo);
pCreateInfo->release();
return pImage;
};
void IRenderer::DestroyBuffer( IBuffer *pBuffer )
{
if (!pBuffer)
return;
CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer;
g_destroyBuffersBuffer.AppendTail(pMlBuffer->m_buffer);
delete (pMlBuffer);
}
void IRenderer::DestroyImage( IImage *pImage )
{
if (!pImage)
return;
CMlImage *pMlImage = (CMlImage*)pImage;
g_destroyImageBuffer.AppendTail(pMlImage->m_image);
delete (pMlImage);
}
IPipeline *g_pCurrentPipeline;
void IRenderer::SetConstants( uint32_t nSize, void *pData )
{
if (!g_pCurrentPipeline)
return;
uint32_t nRoundedSize = nSize/8*8;
void *pTemporaryBuffer = V_malloc(nRoundedSize);
V_memcpy(pTemporaryBuffer, pData, nSize);
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
{
CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
s_pEncoder->setVertexBytes(pTemporaryBuffer, nRoundedSize, 29);
s_pEncoder->setFragmentBytes(pTemporaryBuffer, nRoundedSize, 29);
}
V_free(pTemporaryBuffer);
}
void IRenderer::Barrier( uint32_t stageIn, uint32_t stageOut, CUtlVector<BufferBarrier_t> buffers, CUtlVector<ImageBarrier_t> images )
{
}
void IRenderer::BindData( uint32_t binding, IBuffer *pBuffer, IImage* pImage)
{
if (!g_pCurrentPipeline)
return;
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
{
CMlBuffer *pMlBuffer = (CMlBuffer*)pBuffer;
CMlGraphicsPipeline *pMlPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
for (auto &input: pMlPipeline->m_inputs)
{
if (input.binding != binding)
continue;
switch (input.type)
{
case SHADER_INPUT_TYPE_STORAGE_BUFFER:
case SHADER_INPUT_TYPE_UNIFORM_BUFFER:
if (!pBuffer)
Plat_FatalErrorFunc("pBuffer is NULL\n");
s_pEncoder->setVertexBuffer(pMlBuffer->m_buffer, 0, binding);
s_pEncoder->setFragmentBuffer(pMlBuffer->m_buffer, 0, binding);
break;
case SHADER_INPUT_TYPE_IMAGE:
break;
case SHADER_INPUT_TYPE_TLAS:
break;
case SHADER_INPUT_TYPE_TEXTURES:
break;
};
}
};
}
void IRenderer::BindPipeline( IPipeline *pPipeline )
{
if (!pPipeline)
return;
if (pPipeline->type == PIPELINE_TYPE_RASTERIZATION)
{
CMlGraphicsPipeline *pVkPipeline = (CMlGraphicsPipeline*)pPipeline;
s_pEncoder->setRenderPipelineState(pVkPipeline->m_pipeline);
}
g_pCurrentPipeline = pPipeline;
}
void IRenderer::PushBindings()
{
if (!g_pCurrentPipeline)
return;
if (g_pCurrentPipeline->type == PIPELINE_TYPE_RASTERIZATION)
{
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
bool bHasTextures = false;
for ( int i = 0; i < pPipeline->m_inputs.GetSize(); i++ )
{
if (pPipeline->m_inputs[i].type == SHADER_INPUT_TYPE_TEXTURES)
{
bHasTextures = true;
break;
}
}
if (!bHasTextures)
return;
MTL::ArgumentEncoder *argumentEncoder = 0;
for (auto &shader: pPipeline->m_shaders)
{
if (shader.shaderType == SHADER_TYPE_FRAGMENT)
{
argumentEncoder = shader.function->newArgumentEncoder(21);
break;
};
}
MTL::Buffer *argumentBuffer = g_mlDevice->newBuffer(argumentEncoder->encodedLength(), MTL::ResourceStorageModeShared);
argumentEncoder->setArgumentBuffer(argumentBuffer, 0);
for ( uint32_t i = 0; i < g_textures.GetSize(); i++ )
{
CMlTexture *texture = (CMlTexture*)g_textures[i];
argumentEncoder->setTexture(texture->m_texture, i);
s_pEncoder->useResource(texture->m_texture, MTL::ResourceUsageRead);
}
s_pEncoder->useResource(argumentBuffer, MTL::ResourceUsageRead);
s_pEncoder->setFragmentBuffer(argumentBuffer, 0, 21);
g_destroyBuffersBuffer.AppendTail(argumentBuffer);
argumentEncoder->release();
}
}
void IRenderer::Begin( uint32_t nWidth, uint32_t nHeight, CUtlVector<RenderingColorAttachment_t> attachments, RenderingDepthAttachment_t depth )
{
s_pRenderPass = MTL::RenderPassDescriptor::alloc()->init();
uint32_t i = 0;
for (auto &attachment: attachments)
{
CMlImage *pImage = (CMlImage*)attachment.pOutput;
CMlImage *pTemporary = (CMlImage*)attachment.pTemporary;
auto mlattachment = s_pRenderPass->colorAttachments()->object(i);
mlattachment->setTexture(pImage->m_image);
mlattachment->setLoadAction(IRenderer_LoadOpMl(attachment.loadMode));
mlattachment->setStoreAction(IRenderer_StoreOpMl(attachment.storeMode));
mlattachment->setClearColor(MTL::ClearColor(attachment.clearColor[0],attachment.clearColor[1],attachment.clearColor[2],attachment.clearColor[3]));
i++;
};
if (depth.pOutput)
{
CMlImage *pImage = (CMlImage*)depth.pOutput;
CMlImage *pTemporary = (CMlImage*)depth.pTemporary;
s_pRenderPass->depthAttachment()->setClearDepth(depth.clearValue);
s_pRenderPass->depthAttachment()->setTexture(pImage->m_image);
s_pRenderPass->depthAttachment()->setLoadAction(IRenderer_LoadOpMl(depth.loadMode));
s_pRenderPass->depthAttachment()->setStoreAction(IRenderer_StoreOpMl(depth.storeMode));
}
s_pEncoder = g_mlCommandBuffer->renderCommandEncoder(s_pRenderPass);
}
void IRenderer::ResetState()
{
}
void IRenderer::SetDepthMode( EDepthMode mode )
{
MTL::DepthStencilDescriptor* depthStencilDesc = MTL::DepthStencilDescriptor::alloc()->init();
if (mode == DEPTH_MODE_DISABLED)
{
depthStencilDesc->setDepthWriteEnabled(false);
} else {
depthStencilDesc->setDepthWriteEnabled(true);
switch (mode)
{
case DEPTH_MODE_LESS:
depthStencilDesc->setDepthCompareFunction(MTL::CompareFunctionLess); break;
default:
break;
}
}
auto depthStencilState = g_mlDevice->newDepthStencilState(depthStencilDesc);
s_pEncoder->setDepthStencilState(depthStencilState);
depthStencilDesc->release();
}
void IRenderer::Draw( IVertexBuffer *pVertex, IIndexBuffer *pIndex )
{
CMlBuffer *pMlVertex = (CMlBuffer*)pVertex;
CMlBuffer *pMlIndex = (CMlBuffer*)pIndex;
if (pMlIndex)
{
} else {
CMlGraphicsPipeline *pPipeline = (CMlGraphicsPipeline*)g_pCurrentPipeline;
s_pEncoder->setVertexBuffer(pMlVertex->m_buffer, 0, 30);
s_pEncoder->drawPrimitives(MTL::PrimitiveTypeTriangle, NS::UInteger(0), NS::UInteger(pMlVertex->m_nSize/pPipeline->m_nVertexSize));
}
}
void IRenderer::End()
{
s_pEncoder->endEncoding();
}
IBuffer *IRenderer::GetCameraMatrix()
{
return g_cameraProperties;
}
static CMlImage *pOutputImage = new CMlImage;
IImage *IRenderer::GetOutputImage()
{
pOutputImage->m_image = g_mlDrawableTexture;
return pOutputImage;
}
IGraphicsPipeline *IRenderer::CreateGraphicsPipeline(
CUtlVector<Shader_t> shaders,
CUtlVector<ShaderInput_t> inputs,
uint32_t nConstantsSize,
uint32_t nVertexSize,
CUtlVector<VertexAttribute_t> vertexFormat,
CUtlVector<EImageFormat> outputFormats,
bool bDepth
)
{
CMlGraphicsPipeline *pPipeline = new CMlGraphicsPipeline;
CUtlVector<MLShader_t> mlshaders;
MTL::RenderPipelineDescriptor *pCreateInfo = MTL::RenderPipelineDescriptor::alloc()->init();
MTL::VertexDescriptor *vertexDescriptor = MTL::VertexDescriptor::alloc()->init();
uint32_t i = 0;
for ( auto &vertex: vertexFormat )
{
vertexDescriptor->attributes()->object(i)->setFormat(IRenderer_VertexToMl(vertex.format));
vertexDescriptor->attributes()->object(i)->setOffset(vertex.offset);
vertexDescriptor->attributes()->object(i)->setBufferIndex(30);
i++;
}
vertexDescriptor->layouts()->object(30)->setStride(nVertexSize);
vertexDescriptor->layouts()->object(30)->setStepRate(1);
vertexDescriptor->layouts()->object(30)->setStepFunction(MTL::VertexStepFunctionPerVertex);
NS::Error *error = NULL;
for ( auto &shader: shaders )
{
MLShader_t mlshader = {};
FileHandle_t f = FileSystem()->Open(shader.szPath, IFILE_READ);
if (!f)
Plat_FatalErrorFunc("Failed to open shader %s\n", shader.szPath.GetString());
CUtlBuffer<uint8_t> buffer(FileSystem()->Size(f)+1);
FileSystem()->Read(f, buffer.GetMemory(), buffer.GetSize());
buffer[FileSystem()->Size(f)] = 0;
FileSystem()->Close(f);
NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding);
MTL::CompileOptions *options = NULL;
mlshader.library = g_mlDevice->newLibrary(szSourceCode, options, &error);
if (error)
Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String());
mlshader.szMain = NS::String::string("_main", NS::StringEncoding::UTF8StringEncoding);
mlshader.function = mlshader.library->newFunction(mlshader.szMain);
if (shader.type == SHADER_TYPE_FRAGMENT)
pCreateInfo->setFragmentFunction(mlshader.function);
if (shader.type == SHADER_TYPE_VERTEX)
pCreateInfo->setVertexFunction(mlshader.function);
mlshader.shaderType = shader.type;
mlshaders.AppendTail(mlshader);
}
for ( i = 0; i < outputFormats.GetSize(); i++ )
{
pCreateInfo->colorAttachments()->object(i)->setPixelFormat(IRenderer_FormatToMl(outputFormats[i]));
};
if (bDepth)
pCreateInfo->setDepthAttachmentPixelFormat(MTL::PixelFormatDepth32Float);
pCreateInfo->setVertexDescriptor(vertexDescriptor);
pPipeline->type = PIPELINE_TYPE_RASTERIZATION;
pPipeline->m_pipeline = g_mlDevice->newRenderPipelineState(pCreateInfo, &error);
pPipeline->m_nVertexSize = nVertexSize;
pPipeline->m_inputs = inputs;
pPipeline->m_shaders = mlshaders;
if (error)
Plat_FatalErrorFunc("%s\n",error->localizedDescription()->utf8String());
return pPipeline;
};
uint32_t ITextureManager::GetTextureID(ITexture *pTexture)
{
uint32_t i = 0;
for (auto &t: g_textures)
{
if (pTexture == t)
return i;
i++;
}
return 0;
}
ITexture *ITextureManager::LoadTexture( void *pData, uint32_t X, uint32_t Y, uint32_t numChannels )
{
CMlTexture *pTexture = new CMlTexture;
*pTexture = {};
pTexture->x = X;
pTexture->y = Y;
MTL::TextureDescriptor *pCreateInfo = MTL::TextureDescriptor::alloc()->init();
pCreateInfo->setPixelFormat(MTL::PixelFormatRGBA8Unorm_sRGB);
pCreateInfo->setWidth(X);
pCreateInfo->setHeight(Y);
pCreateInfo->setUsage(MTL::TextureUsageShaderRead);
pTexture->m_texture = g_mlDevice->newTexture(pCreateInfo);
MTL::Region region = MTL::Region(0, 0, 0, X, Y, 1);
NS::UInteger bytesPerRow = 4 * X;
pTexture->m_texture->replaceRegion(region, 0, pData, bytesPerRow);
pCreateInfo->release();
g_textures.AppendTail(pTexture);
return pTexture;
};
ITexture *ITextureManager::LoadTexture( const char *szName )
{
for (ITexture *texture: g_textures)
{
if (!texture->szName)
continue;
if (!V_strcmp(texture->szName, szName))
return texture;
};
FileHandle_t file = FileSystem()->Open(szName, IFILE_READ);
if (!file)
Plat_FatalErrorFunc("Failed to load %s\n", szName);
CUtlBuffer<stbi_uc> buffer(FileSystem()->Size(file));
FileSystem()->Read(file, buffer.GetMemory(), buffer.GetSize());
int nImageX;
int nImageY;
int nImageChannels;
stbi_uc *pixels = stbi_load_from_memory((stbi_uc*)buffer.GetMemory(), buffer.GetSize(), &nImageX, &nImageY, &nImageChannels, STBI_rgb_alpha);
ITexture *pTexture = ITextureManager::LoadTexture(pixels, nImageX, nImageY, 4);
pTexture->szName = szName;
return pTexture;
};
void IMetal::Init()
{
char invalidTexture[1024] = {};
for (int i = 0; i < 16; i++) {
for (int j = 0; j < 16; j++) {
int index = i * 16 + j;
if ((i + j) % 2 == 0) {
invalidTexture[index*4] = 255;
}
}
}
g_cameraProperties = IRenderer::CreateUniformBuffer(sizeof(CameraProjection));
g_cameraDataMap = (CameraProjection*)g_cameraProperties->Map();
ITextureManager::LoadTexture(invalidTexture, 16, 16, 4);
g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 1);
g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, 1280, 720, 4);
g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 1);
g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, 1280, 720, 4);
glm_mat4_identity(g_cameraView);
}
static MTL::RenderPipelineState* s_fullScreenDraw;
void IMetal::CreatePipelines()
{
for (auto &step: Renderer()->m_StepPrepass)
step.pPipeline->Init();
for (auto &step: Renderer()->m_StepMeshRendering)
step.pPipeline->Init();
for (auto &step: Renderer()->m_StepShading)
step.pPipeline->Init();
for (auto &step: Renderer()->m_StepPostProcessing)
step.pPipeline->Init();
for (auto &step: Renderer()->m_StepUI)
step.pPipeline->Init();
NS::Error *error = 0;
FileHandle_t f = FileSystem()->Open("gfx/ml_quad.metal", IFILE_READ);
CUtlBuffer<uint8_t> buffer(FileSystem()->Size(f)+1);
FileSystem()->Read(f, buffer.GetMemory(), buffer.GetSize());
buffer[FileSystem()->Size(f)] = 0;
FileSystem()->Close(f);
NS::String *szSourceCode = NS::String::string((const char*)buffer.GetMemory(), NS::StringEncoding::UTF8StringEncoding);
MTL::CompileOptions *options = NULL;
MTL::Library *library = g_mlDevice->newLibrary(szSourceCode, options, &error);
MTL::Function *vertexFunc = library->newFunction(NS::String::string("vertex_main", NS::UTF8StringEncoding));
MTL::Function *fragmentFunc = library->newFunction(NS::String::string("fragment_main", NS::UTF8StringEncoding));
MTL::RenderPipelineDescriptor *pipelineDesc = MTL::RenderPipelineDescriptor::alloc()->init();
pipelineDesc->setVertexFunction(vertexFunc);
pipelineDesc->setFragmentFunction(fragmentFunc);
pipelineDesc->colorAttachments()->object(0)->setPixelFormat(MTL::PixelFormatBGRA8Unorm);
s_fullScreenDraw = g_mlDevice->newRenderPipelineState(pipelineDesc, &error);
}
void IMetal::Frame()
{
mat4 perspective;
glm_mat4_inv(g_cameraView, g_cameraDataMap->viewprojection);
glm_perspective(glm_rad(68),(float)g_nWindowWidth/g_nWindowHeight, 0.01, 10000, perspective);
glm_rotate(perspective, glm_rad(90), (vec4){1,0,0,0});
glm_scale(perspective, (vec4){1,-1,1,1});
glm_rotate(perspective, glm_rad(90), (vec4){0,0,1,0});
glm_mat4_mul(perspective,g_cameraDataMap->viewprojection,g_cameraDataMap->viewprojection);
if (g_bConfigNotify)
{
IRenderer::DestroyImage(g_meshDepth);
IRenderer::DestroyImage(g_meshDepthMSAA);
IRenderer::DestroyImage(g_meshColor);
IRenderer::DestroyImage(g_meshColorMSAA);
g_meshDepth = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1);
g_meshDepthMSAA = IRenderer::CreateImage(IMAGE_FORMAT_DEPTH, IMAGE_USAGE_DEPTH_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4);
g_meshColor = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 1);
g_meshColorMSAA = IRenderer::CreateImage(IMAGE_FORMAT_R8G8B8A8, IMAGE_USAGE_COLOR_ATTACHMENT, g_nWindowWidth, g_nWindowHeight, 4);
}
for (auto &step: g_StepPrepass)
step.pPipeline->Frame(0);
IRenderer::Begin(g_nWindowWidth, g_nWindowHeight,
{
{
g_meshColor,
0,
ATTACHMENT_LOAD_MODE_CLEAR,
ATTACHMENT_STORE_MODE_STORE,
}
},
{
g_meshDepth,
0,
ATTACHMENT_LOAD_MODE_CLEAR,
ATTACHMENT_STORE_MODE_STORE,
1,
});
for (auto &step: g_StepMeshRendering)
step.pPipeline->Frame(0);
IRenderer::End();
CMlImage *pInImage = (CMlImage*)g_meshColor;
MTL::RenderPassDescriptor *renderPassDesc = MTL::RenderPassDescriptor::renderPassDescriptor();
renderPassDesc->colorAttachments()->object(0)->setTexture(g_mlDrawableTexture);
renderPassDesc->colorAttachments()->object(0)->setLoadAction(MTL::LoadActionClear);
renderPassDesc->colorAttachments()->object(0)->setStoreAction(MTL::StoreActionStore);
renderPassDesc->colorAttachments()->object(0)->setClearColor(MTL::ClearColor(0.1, 0.1, 0.1, 1.0));
MTL::RenderCommandEncoder *encoder = g_mlCommandBuffer->renderCommandEncoder(renderPassDesc);
encoder->setRenderPipelineState(s_fullScreenDraw);
encoder->setFragmentTexture(pInImage->m_image, 0);
encoder->drawPrimitives(MTL::PrimitiveTypeTriangleStrip, NS::UInteger(0), NS::UInteger(4));
encoder->endEncoding();
for (auto &step: g_StepShading)
step.pPipeline->Frame(0);
for (auto &step: g_StepPostProcessing)
step.pPipeline->Frame(0);
for (auto &step: g_StepUI)
step.pPipeline->Frame(0);
}
void IMetal::Deinit()
{
}

View File

@@ -1,31 +0,0 @@
#ifndef ML_VIDEO_H
#define ML_VIDEO_H
#include "tier0/platform.h"
#include "Metal/Metal.hpp"
#include "QuartzCore/QuartzCore.hpp"
extern CA::MetalLayer *g_mlLayer;
extern MTL::Device *g_mlDevice;
extern MTL::CommandQueue *g_mlCommandQueue;
extern MTL::CommandBuffer *g_mlCommandBuffer;
extern NS::AutoreleasePool *g_mlPool;
extern char g_bConfigNotify;
extern uint32_t g_nWindowWidth;
extern uint32_t g_nWindowHeight;
extern CUtlVector<MTL::Texture*> g_destroyImageBuffer;
extern CUtlVector<MTL::Buffer*> g_destroyBuffersBuffer;
extern MTL::Texture *g_mlDrawableTexture;
interface IMetal
{
public:
static void Init();
static void CreatePipelines();
static void Frame();
static void Deinit();
};
#endif

View File

@@ -1,13 +0,0 @@
#import <QuartzCore/CAMetalLayer.h>
#import <Metal/Metal.h>
namespace CA {
class MetalLayer;
}
void APPLE_ConfigureLayer(CA::MetalLayer* pMetalLayer)
{
if (!pMetalLayer) return;
CAMetalLayer* nsLayer = (__bridge CAMetalLayer*)pMetalLayer;
};

View File

@@ -1,266 +0,0 @@
#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "console.h"
#include "tier1/commandline.h"
#include "input.h"
#define NS_PRIVATE_IMPLEMENTATION
#define MTL_PRIVATE_IMPLEMENTATION
#define MTK_PRIVATE_IMPLEMENTATION
#define CA_PRIVATE_IMPLEMENTATION
#include "tier0/minmax_off.h"
#include "QuartzCore/CAMetalLayer.hpp"
#include "Metal/Metal.hpp"
#include "SDL3/SDL.h"
#include "SDL3/SDL_keycode.h"
#include "SDL3/SDL_metal.h"
#include "SDL3/SDL_events.h"
#include "tier0/minmax.h"
#include "ml_video.h"
char g_bConfigNotify = 0;
uint32_t g_nWindowWidth = 1280;
uint32_t g_nWindowHeight = 720;
SDL_Window *g_window;
SDL_MetalView g_mlView;
CA::MetalLayer *g_mlLayer;
MTL::Device *g_mlDevice;
MTL::CommandQueue *g_mlCommandQueue;
MTL::CommandBuffer *g_mlCommandBuffer;
NS::AutoreleasePool *g_mlPool;
MTL::Texture *g_mlDrawableTexture;
MTL::PixelFormat g_swapchainFormat;
#if defined(__APPLE__) && defined(__MACH__)
#include "TargetConditionals.h"
#if TARGET_OS_IPHONE
// iOS
#define SDL_METAL_VIEW UI::View
#define STBI_NO_THREAD_LOCALS
#else
// macOS
#define SDL_METAL_VIEW NS::View
#endif
#else
// Other platforms
#endif
void IInput::SetInputMode( EInputMode mode )
{
switch (mode)
{
case INPUT_MODE_GAME:
g_currentInputMode = INPUT_MODE_GAME;
SDL_SetWindowRelativeMouseMode(g_window, true);
return;
default:
g_currentInputMode = INPUT_MODE_MENU;
SDL_SetWindowRelativeMouseMode(g_window, false);
return;
}
}
EInputKey ISDL_KeyName(SDL_Keycode key)
{
switch(key)
{
case SDLK_ESCAPE: return KEY_ESCAPE;
case SDLK_TAB: return KEY_TAB;
case SDLK_RETURN: return KEY_ENTER;
case SDLK_RCTRL: return KEY_CONTROL;
case SDLK_LCTRL: return KEY_CONTROL;
case SDLK_RSHIFT: return KEY_SHIFT;
case SDLK_LSHIFT: return KEY_SHIFT;
case SDLK_RALT: return KEY_ALT;
case SDLK_LALT: return KEY_ALT;
case SDLK_SPACE: return KEY_SPACE;
case SDLK_F1: return KEY_F1;
case SDLK_F2: return KEY_F2;
case SDLK_F3: return KEY_F3;
case SDLK_F4: return KEY_F4;
case SDLK_F5: return KEY_F5;
case SDLK_F6: return KEY_F6;
case SDLK_F7: return KEY_F7;
case SDLK_F8: return KEY_F8;
case SDLK_F9: return KEY_F9;
case SDLK_F10: return KEY_F10;
case SDLK_F11: return KEY_F11;
case SDLK_F12: return KEY_F12;
case SDLK_1: return KEY_1;
case SDLK_2: return KEY_2;
case SDLK_3: return KEY_3;
case SDLK_4: return KEY_4;
case SDLK_5: return KEY_5;
case SDLK_6: return KEY_6;
case SDLK_7: return KEY_7;
case SDLK_8: return KEY_8;
case SDLK_9: return KEY_9;
case SDLK_0: return KEY_0;
case SDLK_A: return KEY_A;
case SDLK_B: return KEY_B;
case SDLK_C: return KEY_C;
case SDLK_D: return KEY_D;
case SDLK_E: return KEY_E;
case SDLK_F: return KEY_F;
case SDLK_G: return KEY_G;
case SDLK_H: return KEY_H;
case SDLK_I: return KEY_I;
case SDLK_J: return KEY_J;
case SDLK_K: return KEY_K;
case SDLK_L: return KEY_L;
case SDLK_M: return KEY_M;
case SDLK_N: return KEY_N;
case SDLK_O: return KEY_O;
case SDLK_P: return KEY_P;
case SDLK_Q: return KEY_Q;
case SDLK_R: return KEY_R;
case SDLK_S: return KEY_S;
case SDLK_T: return KEY_T;
case SDLK_U: return KEY_U;
case SDLK_V: return KEY_V;
case SDLK_W: return KEY_W;
case SDLK_X: return KEY_X;
case SDLK_Y: return KEY_Y;
case SDLK_Z: return KEY_Z;
}
return KEY_NONE;
};
void IVideo_HandleEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
SDL_KeyboardEvent *key = &event.key;
SDL_MouseMotionEvent *motion = &event.motion;
switch (event.type)
{
case SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED:
g_nWindowWidth = event.window.data1;
g_nWindowHeight = event.window.data2;
g_bConfigNotify = 2;
break;
case SDL_EVENT_KEY_DOWN:
if (!key->repeat)
IInput::KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_DOWN);
break;
case SDL_EVENT_KEY_UP:
key = &event.key;
if (!key->repeat)
IInput::KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_UP);
break;
case SDL_EVENT_MOUSE_MOTION:
IInput::AxisEvent(AXIS_MOUSE_X, motion->yrel*0.022);
IInput::AxisEvent(AXIS_MOUSE_Y, -motion->xrel*0.022);
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
{
SDL_GamepadAxis axis = (SDL_GamepadAxis)event.gaxis.axis;
float value = event.gaxis.value / 32768.0f;
if (abs(event.gaxis.value)<1000)
value = 0;
SDL_JoystickID id = event.gaxis.which;
if (axis == SDL_GAMEPAD_AXIS_RIGHTY)
{
IInput::AxisEvent(AXIS_CONTROLLER_PITCH, value);
}
if (axis == SDL_GAMEPAD_AXIS_RIGHTX)
{
IInput::AxisEvent(AXIS_CONTROLLER_YAW, -value);
}
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
break;
case SDL_EVENT_GAMEPAD_BUTTON_UP:
break;
}
};
};
void APPLE_ConfigureLayer(CA::MetalLayer* pMetalLayer);
void IVideo::Init()
{
SDL_SetHint(SDL_HINT_RENDER_VSYNC, "0");
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD);
g_window = SDL_CreateWindow("rtt", 1280, 720, SDL_WINDOW_METAL | SDL_WINDOW_HIGH_PIXEL_DENSITY);
int nNumGamepads = 0;
SDL_JoystickID *pGamepads = SDL_GetGamepads(&nNumGamepads);
for ( uint32_t i = 0; i < nNumGamepads; i++ )
{
SDL_OpenGamepad(pGamepads[i]);
}
g_mlView = SDL_Metal_CreateView(g_window);
g_mlLayer = (CA::MetalLayer*)SDL_Metal_GetLayer(g_mlView);
g_mlDevice = MTL::CreateSystemDefaultDevice();
g_mlLayer->setDevice(g_mlDevice);
g_mlLayer->setPixelFormat(MTL::PixelFormatBGRA8Unorm);
g_swapchainFormat = MTL::PixelFormatBGRA8Unorm;
g_mlCommandQueue = g_mlDevice->newCommandQueue();
g_mlLayer->setDrawableSize(CGSizeMake(1280, 720));
g_mlLayer->setFramebufferOnly(false);
IMetal::Init();
}
void IVideo::Frame( float fDelta )
{
IVideo_HandleEvents();
NS::AutoreleasePool *pool = NS::AutoreleasePool::alloc()->init();
g_mlLayer->setDrawableSize(CGSizeMake(g_nWindowWidth, g_nWindowHeight));
CA::MetalDrawable *drawable = g_mlLayer->nextDrawable();
if (!drawable)
return;
g_mlDrawableTexture = drawable->texture();
g_mlCommandBuffer = g_mlCommandQueue->commandBuffer();
IMetal::Frame();
g_mlCommandBuffer->presentDrawable(drawable);
g_mlCommandBuffer->commit();
g_mlCommandBuffer->waitUntilCompleted();
for (auto &image: g_destroyImageBuffer)
{
image->release();
}
for (auto &buffer: g_destroyBuffersBuffer)
{
buffer->release();
}
g_destroyImageBuffer = {};
g_destroyBuffersBuffer = {};
pool->release();
g_bConfigNotify = 0;
}
void IVideo::Deinit()
{
g_mlCommandQueue->release();
g_mlDevice->release();
};
void IVideo::CreatePipelines( )
{
IMetal::CreatePipelines();
}

View File

@@ -1,448 +0,0 @@
#include "networking.h"
#include "console.h"
#include "engine.h"
#include "gamemode.h"
#include "server.h"
#include "steam/isteamfriends.h"
#include "steam/isteamnetworking.h"
#include "steam/isteamnetworkingsockets.h"
#include "steam/steam_api_common.h"
#include "steam/steamnetworkingtypes.h"
#include "tier0/platform.h"
#include "tier0/lib.h"
#include "tier1/commandline.h"
#include "tier0/network.h"
#include "tier1/utlvector.h"
#include "baseplayer.h"
#include "steam/steam_api.h"
#include "steam/steam_gameserver.h"
#include "steam/steamnetworkingsockets.h"
#include "steam/isteamgameserver.h"
#include "steam/isteamnetworkingutils.h"
#ifndef STEAMNETWORKINGSOCKETS_OPENSOURCE
#include "steam/steam_api.h"
#endif
HSteamNetConnection net_connection = 0;
HSteamNetConnection net_server = 0;
HSteamListenSocket net_listenSocket = -1;
CUtlVector<IIClient*> net_clients;
bool net_bIsServer = false;
static int net_nMaxPlayers = 0;
static uint64_t net_nLastSteamID = 90071992547409920;
class CClientNetworkingCallbacks
{
STEAM_CALLBACK(CClientNetworkingCallbacks, RelayNetworkStatusChanged, SteamRelayNetworkStatus_t);
};
void CClientNetworkingCallbacks::RelayNetworkStatusChanged( SteamRelayNetworkStatus_t *pCallback )
{
};
class CServerNetworkingCallbacks
{
STEAM_GAMESERVER_CALLBACK(CServerNetworkingCallbacks, ClientConnected, SteamNetConnectionStatusChangedCallback_t);
STEAM_GAMESERVER_CALLBACK(CServerNetworkingCallbacks, SteamNetAuthenticated, SteamNetAuthenticationStatus_t);
};
void CServerNetworkingCallbacks::ClientConnected( SteamNetConnectionStatusChangedCallback_t *pCallback )
{
INetworking::ClientConnectedCallback(pCallback);
};
void CServerNetworkingCallbacks::SteamNetAuthenticated( SteamNetAuthenticationStatus_t *pCallback )
{
if (net_nLastSteamID == SteamGameServer()->GetSteamID().ConvertToUint64())
return;
net_nLastSteamID = SteamGameServer()->GetSteamID().ConvertToUint64();
V_printf("-------------- SERVER INFO ----------------\n");
V_printf(" STEAMID64:\t%llu\n", net_nLastSteamID);
V_printf(" MAX PLAYERS:\t%i\n", net_nMaxPlayers);
V_printf("-------------- TIPS -----------------------\n");
V_printf(" players can join by using connect <STEAMID64>\n");
V_printf("-------------------------------------------\n");
};
static CServerNetworkingCallbacks *net_pServerCallbacks;
static CClientNetworkingCallbacks *net_pClientCallbacks;
void INetworking::Init()
{
Net_Init();
#ifdef STEAMNETWORKINGSOCKETS_OPENSOURCE
GameNetworkingSockets_Init(NULL, &errMsg)
#endif
V_printf("Cool\n");
if (ICommandLine::CheckParam("-steamdebug"))
{
SteamNetworkingUtils()->SetDebugOutputFunction(k_ESteamNetworkingSocketsDebugOutputType_Msg,
[](ESteamNetworkingSocketsDebugOutputType severity, const char *szMessage) {
V_printf("Steam: %s\n", szMessage);
});
}
if (ICommandLine::CheckParam("-dedicated"))
{
net_pServerCallbacks = new CServerNetworkingCallbacks;
// Run dedicated server with steam
SteamGameServer_Init(0, 27015, 27016, eServerModeAuthentication, "0.0.0.0");
SteamGameServer()->SetProduct("funnygame");
SteamGameServer()->SetGameDescription("not that funny but ok");
SteamGameServer()->SetModDir("funnygame");
SteamGameServer()->SetDedicatedServer(true);
SteamGameServer()->LogOnAnonymous();
net_nMaxPlayers = atoi(ICommandLine::ParamValue("-maxplayers", "128"));
SteamGameServer()->SetMaxPlayerCount(net_nMaxPlayers);
SteamGameServer()->SetAdvertiseServerActive(true);
} else {
net_pClientCallbacks = new CClientNetworkingCallbacks;
}
SteamDatagramErrMsg errMsg = {};
SteamNetworkingUtils()->InitRelayNetworkAccess();
if (ICommandLine::CheckParam("-dedicated"))
{
net_listenSocket = SteamGameServerNetworkingSockets()->CreateListenSocketP2P(0, 0, NULL);
net_bIsServer = true;
} else {
if (ICommandLine::ParamValue("-connect"))
{
Console()->AddCommand(CUtlString("connect %s;", ICommandLine::ParamValue("-connect")));
};
}
}
void INetworking::Deinit()
{
if (net_listenSocket == -1)
return;
if (ICommandLine::CheckParam("-dedicated"))
SteamGameServerNetworkingSockets()->CloseListenSocket(net_listenSocket);
else
SteamNetworkingSockets()->CloseConnection(net_listenSocket, 0, NULL, false);
}
bool INetworking::IsServer()
{
return net_bIsServer;
}
bool INetworking::IsClient()
{
return !net_bIsServer;
}
bool INetworking::IsConnected()
{
return (bool)net_server;
}
void INetworking::Frame()
{
if (IsServer())
{
SteamGameServer_RunCallbacks();
for (auto &client: g_clients)
{
SteamNetworkingMessage_t *pMessages[64];
while (true)
{
int nMessages = SteamGameServerNetworkingSockets()->ReceiveMessagesOnConnection(client->playerHandle, pMessages, 64);
if ( nMessages <= 0 )
break;
for ( int i = 0; i < nMessages; i++ )
{
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), client);
}
}
}
} else {
SteamNetworkingMessage_t *pMessages[64];
while (true)
{
int nMessages = SteamNetworkingSockets()->ReceiveMessagesOnConnection(net_connection, pMessages, 64);
if ( nMessages <= 0 )
break;
for ( int i = 0; i < nMessages; i++ )
{
ProcessPacket((void*)pMessages[i]->GetData(), pMessages[i]->GetSize(), NULL);
pMessages[i]->Release();
}
}
}
}
void INetworking::SendData( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
{
if (!IsConnected() && IsClient())
return;
int nSendFlags = 0;
switch ( messageMode )
{
case MESSAGE_MODE_UNRELIABLE:
nSendFlags |= k_nSteamNetworkingSend_Unreliable;
break;
case MESSAGE_MODE_RELIABLE:
nSendFlags |= k_nSteamNetworkingSend_Reliable;
break;
};
/* Send to server if client is NULL */
EResult r = k_EResultNone;
if (pClient == NULL)
r = SteamNetworkingSockets()->SendMessageToConnection(net_server, pData, nSize, nSendFlags, NULL);
else
r = SteamGameServerNetworkingSockets()->SendMessageToConnection(pClient->playerHandle, pData, nSize, nSendFlags, NULL);
}
void INetworking::SendDataEverybody( void *pData, uint32_t nSize, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, IIClient *pClient, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
if (client == pClient)
continue;
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::SendDataEverybodyExcept( void *pData, uint32_t nSize, CBasePlayer *pPlayer, EMessageMode messageMode )
{
for (auto &client: g_clients)
{
if (client->pBasePlayer == pPlayer)
continue;
SendData(pData, nSize, client, messageMode);
}
}
void INetworking::ProcessPacket( void *pData, uint32_t nSize, IIClient *pClient )
{
Packet_t *pPacketHeader = (Packet_t*)pData;
if (IsServer() && pPacketHeader->type != PACKET_TYPE_PLAYER_MOVEMENT)
return;
if (nSize < sizeof(Packet_t))
return;
PacketPlayer_t *pPlayerPacket = (PacketPlayer_t*)pData;
PacketGameMode_t *pGameModePacket = (PacketGameMode_t*)pData;
IIClient *pNewClient;
switch(pPacketHeader->type)
{
case PACKET_TYPE_PLAYER_MOVEMENT:
if (nSize < sizeof(PacketPlayer_t))
return;
if (IsServer())
{
if (pClient->pBasePlayer)
pClient->pBasePlayer->RecieveFromServer(pData, nSize);
}
for (auto &client: g_clients)
{
if (client->playerHandle == pPlayerPacket->playerHandle)
{
if (!client->pBasePlayer)
return;
client->pBasePlayer->RecieveFromServer(pData, nSize);
return;
}
}
return;
case PACKET_TYPE_PLAYER_JOIN:
if (nSize != sizeof(PacketPlayer_t))
return;
// Player join and leave can be processed only by the clients
pNewClient = new IIClient;
*pNewClient = {
.playerID = pPlayerPacket->playerID,
.playerHandle = pPlayerPacket->playerHandle,
};
V_printf("%i\n",g_clients.GetSize());
IIEngine::ConnectClient(pNewClient);
for (auto &client: g_clients)
{
CSteamID steamID = CSteamID();
if ( client->playerID == 0)
V_printf("%s\t", SteamFriends()->GetPlayerNickname((uint64)client->playerID));
else
V_printf("%s\t", SteamFriends()->GetPersonaName());
V_printf("%llu\t", client->playerID);
V_printf("%u\n", client->playerHandle);
if (client->playerHandle == 0)
g_localClient = client;
}
return;
case PACKET_TYPE_PLAYER_LEAVE:
IIEngine::DisconnectClientByHandle(pPlayerPacket->playerHandle);
return;
case PACKET_TYPE_GAMEMODE_START:
V_printf("PacketGameMode\n");
if (nSize != sizeof(PacketGameMode_t))
return;
GameModeManager()->StartGameMode(pGameModePacket->szName);
return;
default:
return;
}
}
void INetworking::GetServerInfo()
{
}
uint32_t INetworking_IPv4ToUint(const char *szIP) {
if (CUtlString(szIP) == "localhost")
return 0x7F000001;
struct in_addr ipAdress;
if (inet_pton(AF_INET, szIP, &ipAdress) != 1) {
V_printf("Invalid IPv4 address: %s\n", szIP);
return 0;
}
return ntohl(ipAdress.s_addr);
}
void INetworking::JoinServer( const char *szIP )
{
g_clients = {};
if (net_connection)
{
SteamNetworkingSockets()->CloseConnection(net_connection, 0, NULL, false);
}
SteamNetworkingIPAddr localAddress = {};
localAddress.Clear();
localAddress.SetIPv4(INetworking_IPv4ToUint(szIP), 27015);
net_connection = SteamNetworkingSockets()->ConnectByIPAddress(localAddress, 0, NULL);
net_server = net_connection;
}
void INetworking::JoinServer( uint64_t nSteamID )
{
g_clients = {};
if (net_connection)
{
SteamNetworkingSockets()->CloseConnection(net_connection, 0, NULL, false);
}
SteamNetworkingIdentity remoteIdentity = {};
remoteIdentity.Clear();
remoteIdentity.SetSteamID64(nSteamID);
net_connection = SteamNetworkingSockets()->ConnectP2P(remoteIdentity, 0, 0, 0);
net_server = net_connection;
}
void INetworking::ClientConnectedCallback( SteamNetConnectionStatusChangedCallback_t *pCallback )
{
IIClient *pClient = new IIClient;
switch (pCallback->m_info.m_eState)
{
case k_ESteamNetworkingConnectionState_Connecting:
V_printf("Awaiting connection: %llu\n",pCallback->m_info.m_identityRemote.GetSteamID64());
SteamNetworkingSockets()->AcceptConnection(pCallback->m_hConn);
break;
case k_ESteamNetworkingConnectionState_Connected:
V_printf("Connected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
*pClient = {
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
.playerHandle = pCallback->m_hConn,
};
// send out to all clients
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = pClient->playerID,
.playerHandle = pClient->playerHandle,
};
packet.type = PACKET_TYPE_PLAYER_JOIN;
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
};
IIEngine::ConnectClient(pClient);
// register all clients on connected one
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = client->playerID,
.playerHandle = client->playerHandle,
};
if (client == pClient)
{
packet.playerID = 0;
packet.playerHandle = 0;
}
packet.type = PACKET_TYPE_PLAYER_JOIN;
SendData(&packet, sizeof(packet), pClient, MESSAGE_MODE_RELIABLE);
};
GameModeManager()->RestartCurrentGameMode();
break;
case k_ESteamNetworkingConnectionState_ClosedByPeer:
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
SteamNetworkingSockets()->CloseConnection(pCallback->m_hConn, 0, NULL, false);
V_printf("Disconnected: %llu %u\n",pCallback->m_info.m_identityRemote.GetSteamID64(), pCallback->m_hConn);
IIEngine::DisconnectClientByHandle(pCallback->m_hConn);
// send out to all clients
for (auto &client: g_clients)
{
PacketPlayer_t packet = {
.playerID = pCallback->m_info.m_identityRemote.GetSteamID64(),
.playerHandle = pCallback->m_hConn,
};
packet.type = PACKET_TYPE_PLAYER_LEAVE;
SendData(&packet, sizeof(packet), client, MESSAGE_MODE_RELIABLE);
};
break;
default:
break;
}
}
void INetworking_Connect( int argc, char **argv )
{
if (ICommandLine::CheckParam("-dedicated"))
return;
if (argc != 2)
{
V_printf("connect <IPv4>\n");
return;
}
INetworking::JoinServer(argv[1]);
};
void INetworking_ConnectFriend( int argc, char **argv )
{
if (ICommandLine::CheckParam("-dedicated"))
return;
if (argc != 2)
{
V_printf("connect_friend <steamid>\n");
return;
}
uint64_t nFriendID = 0;
V_sscanf(argv[1], "%llu\n", &nFriendID);
V_printf("Connecting to %llu\n",nFriendID);
INetworking::JoinServer(nFriendID);
};
ConCommand ConnectCmd("connect", INetworking_ConnectFriend);

View File

@@ -1,160 +0,0 @@
#include "physics.h"
#include "math3d.h"
PxCastResult_t IPxWorld::BoxCast( vec3 size, vec3 origin, vec3 destination, vec3 rotation )
{
vec3 velocity;
PxCastResult_t result = {};
px_cast_result r = {};
for ( int i = 0; i < 3; i++ )
velocity[i] = destination[i] - origin[i];
r = px_box_cast(px, size[0], size[1], size[2], PX_GLM_VEC3(origin), PX_GLM_VEC3(rotation), PX_GLM_VEC3(velocity), 1);
result.bHit = r.hit;
result.fTime = r.time;
for ( int i = 0; i < 3; i++ )
{
result.position[i] = origin[i] + velocity[i] * result.fTime;
result.normal[i] = r.normal1.m[i];
result.normal2[i] = r.normal2.m[i];
}
return result;
}
void CPxCollider::Spawn( float fFriction )
{
};
void CPxCollider::Destroy()
{
};
void CPxBallMesh::Spawn( float fFriction )
{
m_pCollider = px_ball(m_fRadius, {.friction = fFriction});
};
void CPxBallMesh::Destroy()
{
};
void CPxBoxMesh::Spawn( float fFriction )
{
m_pCollider = px_box(m_fRadius[0], m_fRadius[1], m_fRadius[2], {.friction = fFriction});
};
void CPxBoxMesh::Destroy()
{
};
void CPxTriangleMesh::Spawn( float fFriction )
{
};
void CPxTriangleMesh::Destroy()
{
};
void CPxRigidKinematicPosition::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
{
m_pRigidBody = px_kinematic_position_body(px, pCollider->m_pCollider, matrix, params);
};
void CPxRigidKinematicPosition::SetPosition( px_vec3 position )
{
px_setposition(px, m_pRigidBody, position);
};
px_vec3 CPxRigidKinematicPosition::GetPosition( void )
{
return px_getposition(px, m_pRigidBody);
};
px_matrix CPxRigidKinematicPosition::GetMatrix ( void )
{
return px_getmatrix(px, m_pRigidBody);
};
void CPxRigidKinematicPosition::Destroy()
{
};
void CPxRigidBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
{
m_pRigidBody = px_rigidbody(px, pCollider->m_pCollider, matrix, params);
};
void CPxRigidBody::SetPosition( px_vec3 position )
{
px_setposition(px, m_pRigidBody, position);
}
void CPxRigidBody::SetVelocity( px_vec3 velocity )
{
px_setvelocity(px, m_pRigidBody, velocity);
}
px_vec3 CPxRigidBody::GetPosition( void )
{
return px_getposition(px, m_pRigidBody);
};
px_vec3 CPxRigidBody::GetVelocity( void )
{
return px_getvelocity(px, m_pRigidBody);
};
px_matrix CPxRigidBody::GetMatrix ( void )
{
return px_getmatrix(px, m_pRigidBody);
};
void CPxRigidBody::Destroy()
{
};
void CPxStaticBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
{
px_staticbody(px, pCollider->m_pCollider, matrix);
};
px_vec3 CPxStaticBody::GetPosition( void )
{
return px_getposition(px, m_pCollider);
};
px_matrix CPxStaticBody::GetMatrix ( void )
{
return px_getmatrix(px, m_pCollider);
};
void CPxStaticBody::Destroy()
{
}
;
void CPxFixedBody::Spawn( CPxCollider *pCollider, px_matrix matrix, px_rigidbody_params params )
{
px_fixedbody(px, pCollider->m_pCollider);
};
px_vec3 CPxFixedBody::GetPosition( void )
{
return px_getposition(px, m_pCollider);
};
px_matrix CPxFixedBody::GetMatrix ( void )
{
return px_getmatrix(px, m_pCollider);
};
void CPxFixedBody::Destroy()
{
};

View File

@@ -1,37 +0,0 @@
#include "rendering.h"
CRenderingStep::CRenderingStep()
{
}
CRenderingStep::CRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
}
CPrepassRenderingStep::CPrepassRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
Renderer()->m_StepPrepass.AppendTail({pfn(), szStepName});
}
CMeshRenderingStep::CMeshRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
Renderer()->m_StepMeshRendering.AppendTail({pfn(), szStepName});
}
CShadingRenderingStep::CShadingRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
Renderer()->m_StepShading.AppendTail({pfn(), szStepName});
}
CPostProcessingRenderingStep::CPostProcessingRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
Renderer()->m_StepPostProcessing.AppendTail({pfn(), szStepName});
}
CUIRenderingStep::CUIRenderingStep(const char *szStepName, CreateRenderStepFn pfn)
{
Renderer()->m_StepUI.AppendTail({pfn(), szStepName});
}

View File

@@ -1,80 +0,0 @@
#include "server.h"
#include "engine.h"
#include "input.h"
#include "steam/steam_api_common.h"
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
#include "baseentity.h"
#include "console.h"
#include "physics.h"
#include "input.h"
#include "networking.h"
void *g_serverdll;
ConVar g_tickrate("tickrate","64",FCVAR_PROTECTED);
float g_fAccumulator = 0;
extern "C" void IGame_Load(void);
//-----------------------------------------------------------------------------
// Loads game and client libraries if linking dynamically, otherwise it runs
// IGame_Load compiled statically.
//-----------------------------------------------------------------------------
void IServer::LoadGame( const char *psz )
{
#ifndef STATIC_BUILD
#ifdef __linux__
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.so", psz));
if (!ICommandLine::CheckParam("-dedicated"))
Plat_LoadLibrary(CUtlString("%s/bin/libclient.so", psz));
#endif
#ifdef __APPLE__
g_serverdll = Plat_LoadLibrary(CUtlString("%s/bin/libserver.dylib", psz));
if (!ICommandLine::CheckParam("-dedicated"))
Plat_LoadLibrary(CUtlString("%s/bin/libclient.dylib", psz));
#endif
void (*GameLoadfn)() = (void(*)())Plat_GetProc(g_serverdll, "IGame_Load");
if (!GameLoadfn)
Plat_FatalErrorFunc("IGame_Load not found in libserver.so\n");
GameLoadfn();
#else
IGame_Load();
#endif
};
//-----------------------------------------------------------------------------
// Updates server and client state.
//-----------------------------------------------------------------------------
void IServer::Think( float fDelta )
{
g_fAccumulator += fDelta;
float fTickrate = 1.0/g_tickrate.GetFloat();
/* tickrate */
while(g_fAccumulator>=fTickrate)
{
if (INetworking::IsClient())
Input()->Frame();
Console()->Execute();
g_fAccumulator-=fTickrate;
for (auto &entity: EntityManager()->m_entities)
{
entity->Think(fTickrate);
entity->SendToServer();
}
px_frame(px, fTickrate);
INetworking::Frame();
}
for (auto &entity: EntityManager()->m_entities)
{
if (entity->pClientEntity)
entity->pClientEntity->Think(fDelta);
}
};
void IGame_Exit( int argc, char **argv ) {
IEngine::Shutdown();
Plat_Exit(0);
}
ConCommand ExitCmd("exit", IGame_Exit, 0);

21
engine/sv_dll.cpp Normal file
View File

@@ -0,0 +1,21 @@
#include "sv_dll.h"
#include "tier1/interface.h"
#include "tier0/platform.h"
void CServerGameDLL::Init()
{
#if defined(__linux__)
#endif
}
void CServerGameDLL::Shutdown()
{
}
CServerGameDLL *ServerGameDLL()
{
static CServerGameDLL s_serverdll;
return &s_serverdll;
}

View File

@@ -1,49 +0,0 @@
#include "baseentity.h"
#include "physics.h"
class CLight: public CBaseEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
virtual void SendToServer() override;
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
};
void CLight::Precache()
{
}
void CLight::Spawn()
{
};
void CLight::ReadParameter( const char *szName, const char *szValue )
{
CBaseEntity::ReadParameter(szName, szValue);
}
void CLight::Destroy()
{
}
void CLight::Think( float fDelta )
{
};
void CLight::SendToServer()
{
}
void CLight::RecieveFromServer( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(light, CLight)

View File

@@ -1,74 +0,0 @@
#include "baseentity.h"
#include "baseplayer.h"
#include "engine.h"
#include "tier1/utlvector.h"
CUtlVector<CPlayerStart*> g_PlayerStarts = {};
void CPlayerStart::Precache()
{
}
void CPlayerStart::Spawn()
{
g_PlayerStarts.AppendTail(this);
};
void CPlayerStart::ReadParameter( const char *szName, const char *szValue )
{
CBaseEntity::ReadParameter(szName, szValue);
}
void CPlayerStart::Destroy()
{
uint32_t i = 0;
for (auto &start: g_PlayerStarts)
{
if (start == this)
{
g_PlayerStarts.RemoveAt(i);
break;
}
i++;
}
}
void CPlayerStart::Think( float fDelta )
{
}
void CPlayerStart::RoundEnd( void )
{
m_bIsRunning = false;
}
void CPlayerStart::RoundStart(IIClient *pClient)
{
IIEngine::DestroyEntity(pOwningPlayer);
if (!pClient)
return;
m_bIsRunning = true;
pOwningPlayer = (CBasePlayer*)IIEngine::SpawnEntity("player");
if (pOwningPlayer)
{
pOwningPlayer->pOwningSpawn = this;
pOwningPlayer->SetPosition(m_position);
}
else
V_printf("Failed to spawn player\n");
IIEngine::InitEntity(pOwningPlayer);
pClient->pBasePlayer = pOwningPlayer;
};
void CPlayerStart::SendToServer()
{
};
void CPlayerStart::RecieveFromServer( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(info_player_start, CPlayerStart);

View File

@@ -1,51 +0,0 @@
#include "brush.h"
class CWorldSpawn: public CBrushEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
virtual void SendToServer() override;
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
};
void CWorldSpawn::Precache()
{
CBrushEntity::Precache();
}
void CWorldSpawn::Spawn()
{
CBrushEntity::Spawn();
};
void CWorldSpawn::ReadParameter( const char *szName, const char *szValue )
{
CBrushEntity::ReadParameter(szName, szValue);
}
void CWorldSpawn::Destroy()
{
CBrushEntity::Destroy();
}
void CWorldSpawn::Think( float fDelta )
{
CBrushEntity::Think(fDelta);
}
void CWorldSpawn::SendToServer()
{
}
void CWorldSpawn::RecieveFromServer( void *pData, uint32_t nDataSize )
{
};
DECLARE_ENTITY(worldspawn, CWorldSpawn)

View File

@@ -1,16 +0,0 @@
VK_DEVICE_FUNCTION(vkCmdSetPolygonModeEXT);
VK_DEVICE_FUNCTION(vkCmdSetRasterizationSamplesEXT);
VK_DEVICE_FUNCTION(vkCmdSetVertexInputEXT);
VK_DEVICE_FUNCTION(vkCmdSetSampleMaskEXT);
VK_DEVICE_FUNCTION(vkCmdSetAlphaToCoverageEnableEXT);
VK_DEVICE_FUNCTION(vkCmdSetViewportWithCount);
VK_DEVICE_FUNCTION(vkCmdSetColorBlendEnableEXT);
VK_DEVICE_FUNCTION(vkCmdSetColorBlendEquationEXT);
VK_DEVICE_FUNCTION(vkCmdSetColorWriteMaskEXT);
VK_DEVICE_FUNCTION(vkCmdSetLogicOpEXT);
VK_DEVICE_FUNCTION(vkCmdTraceRaysKHR);
VK_DEVICE_FUNCTION(vkCreateAccelerationStructureKHR);
VK_DEVICE_FUNCTION(vkDestroyAccelerationStructureKHR);
VK_DEVICE_FUNCTION(vkGetAccelerationStructureBuildSizesKHR);
VK_DEVICE_FUNCTION(vkCmdBuildAccelerationStructuresKHR);
VK_DEVICE_FUNCTION(vkCreateRayTracingPipelinesKHR);

View File

@@ -1,74 +0,0 @@
#include "filesystem.h"
#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "console.h"
#include "tier1/commandline.h"
#include "vulkan/vulkan.h"
#define VULKAN_RENDERING_IMPL
#include "vk_video.h"
#define VK_DEVICE_FUNCTION(name) extern PFN_##name _##name
#include "vk_external_functions.cpp"
#undef VK_DEVICE_FUNCTION
class CVkBuffer: public IBuffer
{
public:
void *Map() override;
void Unmap() override;
vk_buffer_t m_buffer;
void *m_pAllocated = NULL;
};
class CVkImage: public IImage
{
public:
vk_image2d_t m_image = {};
uint32_t m_usage;
VkImageLayout m_currentLayout;
};
class CVkTexture: public ITexture
{
public:
vk_image2d_t image;
};
extern VkInstance g_vkInstance;
extern VkPhysicalDevice g_vkPhysicalDevice;
extern VkDevice g_vkDevice;
extern uint32_t g_drawfamily;
extern VkQueue g_drawQueue;
extern uint32_t g_presentfamily;
extern VkQueue g_presentQueue;
extern VmaAllocator g_allocator;
extern VkSurfaceKHR g_surface;
extern VkSwapchainKHR g_swapchain;
extern VkCommandPool g_vkCommandPool;
extern VkCommandBuffer g_vkCommandBuffer;
extern VkImageView g_swapchainImageView;
extern VkImage g_swapchainImage;
extern VkFormat g_swapchainFormat;
extern char g_bConfigNotify;
extern uint32_t g_nWindowWidth;
extern uint32_t g_nWindowHeight;
extern VkSampler g_invalidTextureSampler;
extern CUtlVector<ITexture*> g_textures;
extern IBuffer *g_cameraProperties;
extern IImage *g_meshDepth;
extern IImage *g_meshDepthMSAA;
extern IImage *g_meshColor;
extern IImage *g_meshColorMSAA;

File diff suppressed because it is too large Load Diff

View File

@@ -1,107 +0,0 @@
#ifndef VK_VIDEO_H
#define VK_VIDEO_H
#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "vulkan/vulkan.h"
#include "vulkan/vulkan_core.h"
#ifndef VULKAN_RENDERING_IMPL
#error "Not a vulkan rendering implementation. Do not use this file!"
#endif
#include "vk_mem_alloc.h"
struct vk_framedata_t {
VkSemaphore draw;
VkSemaphore present;
VkFence fence;
};
struct vk_shader_t
{
void Create( const char *szPath, VkShaderStageFlagBits shaderStage );
void Create( CUtlBuffer<uint8_t> &spirv, VkShaderStageFlagBits shaderStage );
void Destroy( void );
VkShaderModule m_shaderModule = NULL;
VkPipelineShaderStageCreateInfo m_stageCreateInfo;
};
struct vk_tripipeline_t
{
void Create(
CUtlVector<vk_shader_t> &shaders,
CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
uint32_t pushConstantsSize,
uint32_t nVertexSize,
CUtlVector<VertexAttribute_t> vertexFormat,
CUtlVector<VkFormat> formats
/* the rest of the stuff is set by the dynamic state */
/* literally */
);
void Destroy();
CUtlVector<vk_shader_t> m_shaders;
VkDescriptorSetLayout m_descriptorSetLayout;
VkPipelineLayout m_layout;
VkPipeline m_pipeline;
};
struct vk_comppipeline_t
{
void Create(
vk_shader_t &shader,
CUtlVector<VkDescriptorSetLayoutBinding> &bindings,
uint32_t pushConstantsSize
);
void Destroy();
VkDescriptorSetLayout m_descriptorSetLayout;
VkPipelineLayout m_layout;
VkPipeline m_pipeline;
};
struct vk_buffer_t
{
void Create(size_t size, VkBufferUsageFlags usage);
void Destroy();
void *Map(size_t offset, size_t size);
void Unmap();
void CopyTo(struct vk_image2d_t *image);
void CopyTo(struct vk_buffer_t *buffer);
size_t m_nSize;
VkBuffer m_buffer;
VmaAllocation m_memory;
VkDeviceAddress m_address;
};
struct vk_image2d_t
{
void Create(size_t x, size_t y, VkFormat format, VkImageUsageFlags usage, VkSampleCountFlagBits samples);
void Destroy();
void CopyTo(struct vk_image2d_t *image);
void CopyTo(struct vk_buffer_t *buffer);
uint32_t m_X;
uint32_t m_Y;
VkFormat m_format;
VkImage m_image;
VkImageView m_imageView;
VmaAllocation m_memory;
};
interface IVulkan
{
public:
static void Init();
static void CreatePipelines();
static void Frame();
static void Deinit();
};
#endif

View File

@@ -1,452 +0,0 @@
#include "rendering.h"
#include "tier1/utlvector.h"
#include "console.h"
#include "tier1/commandline.h"
#include "X11/X.h"
#include "X11/Xlib.h"
#include "vulkan/vulkan.h"
#include "vulkan/vulkan_core.h"
#include "vulkan/vulkan_xlib.h"
#define VULKAN_RENDERING_IMPL
#include "vk_video.h"
#define VMA_VULKAN_VERSION 1004000
#define VMA_IMPLEMENTATION
#include "vk_mem_alloc.h"
Display* g_xdisplay;
int g_xscreen;
Window g_xroot;
Window g_xwin;
VkInstance g_vkInstance = NULL;
VkPhysicalDevice g_vkPhysicalDevice = NULL;
VkDevice g_vkDevice = NULL;
uint32_t g_drawfamily = 0;
VkQueue g_drawQueue;
uint32_t g_presentfamily = 0;
VkQueue g_presentQueue;
VmaAllocator g_allocator = NULL;
VkSurfaceKHR g_surface;
VkSwapchainKHR g_swapchain;
ConVar vulkan_gpu("vk_gpu", "0", FCVAR_ARCHIVE);
VkCommandPool g_vkCommandPool;
/* more efficient */
CUtlVector<VkCommandBuffer> g_commandBuffers;
VkCommandBuffer g_vkCommandBuffer;
CUtlVector<vk_framedata_t> g_frameData;
CUtlVector<VkImage> g_swapchainImages;
CUtlVector<VkImageView> g_swapchainImageViews;
VkImageView g_swapchainImageView;
VkImage g_swapchainImage;
uint32_t g_nNumSwapchainImages = 0;
#define VK_DEVICE_FUNCTION(name) PFN_##name _##name
#include "vk_external_functions.cpp"
#undef VK_DEVICE_FUNCTION
char g_bConfigNotify = 0;
uint32_t g_nWindowWidth = 1280;
uint32_t g_nWindowHeight = 720;
void IVideo_SwapchainInit()
{
/* swapchain */
VkXlibSurfaceCreateInfoKHR surfaceCreateInfo = {};
surfaceCreateInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
surfaceCreateInfo.dpy = g_xdisplay;
surfaceCreateInfo.window = g_xwin;
vkCreateXlibSurfaceKHR(g_vkInstance, &surfaceCreateInfo, NULL, &g_surface);
VkSurfaceCapabilitiesKHR surfaceCapatibilities = {};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, g_surface, &surfaceCapatibilities);
const VkFormat preferedSurfaceFormats[] = {
VK_FORMAT_R8G8B8A8_UNORM,
VK_FORMAT_B8G8R8A8_UNORM,
};
uint32_t numSurfaceFormats = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, NULL);
CUtlVector<VkSurfaceFormatKHR> surfaceFormats(numSurfaceFormats);
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, surfaceFormats.GetData());
VkSurfaceFormatKHR selectedFormat = surfaceFormats[0];
for (auto &format: surfaceFormats)
{
for (int i = 0; i < sizeof(preferedSurfaceFormats)/sizeof(VkFormat); i++)
{
selectedFormat = surfaceFormats[i];
}
}
uint32_t numSurfacePresentModes = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, NULL);
CUtlVector<VkPresentModeKHR> surfacePresentModes(numSurfacePresentModes);
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, surfacePresentModes.GetData());
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = g_surface;
swapchainCreateInfo.imageFormat = selectedFormat.format;
swapchainCreateInfo.imageColorSpace = selectedFormat.colorSpace;
swapchainCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
swapchainCreateInfo.preTransform = surfaceCapatibilities.currentTransform;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageExtent = surfaceCapatibilities.minImageExtent;
swapchainCreateInfo.minImageCount = surfaceCapatibilities.minImageCount;
vkCreateSwapchainKHR(g_vkDevice, &swapchainCreateInfo, NULL, &g_swapchain);
vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, NULL);
g_swapchainImages = CUtlVector<VkImage>(g_nNumSwapchainImages);
g_swapchainImageViews = CUtlVector<VkImageView>(g_nNumSwapchainImages);
g_commandBuffers = CUtlVector<VkCommandBuffer>(g_nNumSwapchainImages);
g_frameData = CUtlVector<vk_framedata_t>(g_nNumSwapchainImages);
vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, g_swapchainImages.GetData());
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = g_swapchainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = selectedFormat.format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(g_vkDevice, &createInfo, NULL, &g_swapchainImageViews[i]);
}
/* command buffers */
VkCommandPoolCreateInfo commandPoolCreateInfo = {};
commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
commandPoolCreateInfo.queueFamilyIndex = g_drawfamily;
commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(g_vkDevice, &commandPoolCreateInfo, NULL, &g_vkCommandPool);
VkCommandBufferAllocateInfo commandBufferAllocInfo = {};
commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
commandBufferAllocInfo.commandPool = g_vkCommandPool;
commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
commandBufferAllocInfo.commandBufferCount = g_nNumSwapchainImages;
vkAllocateCommandBuffers(g_vkDevice, &commandBufferAllocInfo, g_commandBuffers.GetData());
/* sync */
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
vkCreateFence(g_vkDevice,&fenceCreateInfo, NULL, &g_frameData[i].fence);
vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].draw);
vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].present);
}
};
void IVideo_SwapchainDestroy()
{
vkDestroySwapchainKHR(g_vkDevice, g_swapchain, NULL);
vkDestroySurfaceKHR(g_vkInstance, g_surface, NULL);
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
vkDestroyImageView(g_vkDevice, g_swapchainImageViews[i], NULL);
vkDestroySemaphore(g_vkDevice, g_frameData[i].draw, NULL);
vkDestroySemaphore(g_vkDevice, g_frameData[i].present, NULL);
vkDestroyFence(g_vkDevice, g_frameData[i].fence, NULL);
}
};
void IVideo::Init()
{
g_xdisplay = XOpenDisplay(NULL);
g_xscreen = DefaultScreen(g_xdisplay);
g_xroot = RootWindow(g_xdisplay, g_xscreen);
g_xwin = XCreateSimpleWindow(g_xdisplay, g_xroot, 0, 0, 1280, 720, 0, 0, 0);
XSelectInput(g_xdisplay, g_xwin, StructureNotifyMask);
vulkan_gpu.SetValue(ICommandLine::ParamValue("-gpu"));
VkResult r = VK_SUCCESS;
uint32_t i = 0;
/* Instance */
VkApplicationInfo applicationInfo = {};
applicationInfo.apiVersion = VK_API_VERSION_1_4;
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &applicationInfo;
const char *szEnabledExtensions[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
};
instanceCreateInfo.enabledExtensionCount = 2;
instanceCreateInfo.ppEnabledExtensionNames = szEnabledExtensions;
r = vkCreateInstance(&instanceCreateInfo, NULL, &g_vkInstance);
if ( r != VK_SUCCESS )
Plat_FatalErrorFunc("Failed to create VkInstance!");
/* Physical Devices */
uint32_t nNumPhysicalDevices = 0;
vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, NULL);
if ( nNumPhysicalDevices == 0 )
Plat_FatalErrorFunc("No GPU drivers available!");
CUtlVector<VkPhysicalDevice> PhysicalDevices(nNumPhysicalDevices);
vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, PhysicalDevices.GetData());
/* enumerate them for the user */
for (auto &device: PhysicalDevices)
{
VkPhysicalDeviceProperties Properties = {};
vkGetPhysicalDeviceProperties(device, &Properties);
V_printf("GPU%i available: %s\n", i, Properties.deviceName);
i++;
}
/* select one in vk_gpu */
g_vkPhysicalDevice = PhysicalDevices[vulkan_gpu.GetInt()];
VkPhysicalDeviceProperties Properties = {};
vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &Properties);
V_printf("Using %s\n", Properties.deviceName);
/* queue family */
uint32_t nNumQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
CUtlVector<VkQueueFamilyProperties> queueFamilyProperties(nNumQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, queueFamilyProperties.GetData());
i = 0;
for (auto &family: queueFamilyProperties)
{
if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
g_drawfamily = i;
g_presentfamily = i;
}
i++;
}
/* create device */
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = g_drawfamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
VkPhysicalDeviceVertexInputDynamicStateFeaturesEXT pdvidsfe = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_INPUT_DYNAMIC_STATE_FEATURES_EXT,
.vertexInputDynamicState = VK_TRUE,
};
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT pdeds3fe = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT,
.pNext = &pdvidsfe,
.extendedDynamicState3DepthClampEnable = VK_TRUE,
.extendedDynamicState3PolygonMode = VK_TRUE,
.extendedDynamicState3RasterizationSamples = VK_TRUE,
.extendedDynamicState3SampleMask = VK_TRUE,
.extendedDynamicState3AlphaToCoverageEnable = VK_TRUE,
.extendedDynamicState3LogicOpEnable = VK_TRUE,
.extendedDynamicState3ColorBlendEnable = VK_TRUE,
.extendedDynamicState3ColorBlendEquation = VK_TRUE,
.extendedDynamicState3ColorWriteMask = VK_TRUE,
};
VkPhysicalDeviceExtendedDynamicState2FeaturesEXT pdeds2fe = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_2_FEATURES_EXT,
.pNext = &pdeds3fe,
.extendedDynamicState2LogicOp = VK_TRUE,
.extendedDynamicState2PatchControlPoints = VK_TRUE,
};
VkPhysicalDeviceVulkan13Features pdv13f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.pNext = &pdeds2fe,
.dynamicRendering = VK_TRUE,
};
VkPhysicalDeviceVulkan12Features pdv12f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = &pdv13f,
.runtimeDescriptorArray = VK_TRUE,
.bufferDeviceAddress = VK_TRUE,
};
VkPhysicalDeviceVulkan11Features pdv11f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
.pNext = &pdv12f,
};
const char *szEnabledGPUExtensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME,
};
VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.enabledExtensionCount = sizeof(szEnabledGPUExtensions)/(sizeof(const char*));
deviceCreateInfo.ppEnabledExtensionNames = szEnabledGPUExtensions;
deviceCreateInfo.pNext = &pdv11f;
r = vkCreateDevice(g_vkPhysicalDevice, &deviceCreateInfo, NULL, &g_vkDevice);
if ( r != VK_SUCCESS )
Plat_FatalErrorFunc("Failed to create VkDevice!");
vkGetDeviceQueue(g_vkDevice, g_drawfamily, 0, &g_drawQueue);
vkGetDeviceQueue(g_vkDevice, g_presentfamily, 0, &g_presentQueue);
VmaVulkanFunctions vulkanFunctions = {};
vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
VmaAllocatorCreateInfo allocatorCreateInfo = {};
allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_4;
allocatorCreateInfo.physicalDevice = g_vkPhysicalDevice;
allocatorCreateInfo.device = g_vkDevice;
allocatorCreateInfo.instance = g_vkInstance;
vmaCreateAllocator(&allocatorCreateInfo, &g_allocator);
#define VK_DEVICE_FUNCTION(name) _##name = (PFN_##name)vkGetDeviceProcAddr(g_vkDevice, #name)
#include "vk_external_functions.cpp"
#undef VK_DEVICE_FUNCTION
IVideo_SwapchainInit();
XMapWindow(g_xdisplay, g_xwin);
XFlush(g_xdisplay);
IVulkan::Init();
}
void IVideo_HandleX11()
{
XEvent event;
while(XPending(g_xdisplay))
{
XNextEvent(g_xdisplay, &event);
switch (event.type)
{
case KeyPress:
case KeyRelease:
break;
case MotionNotify:
break;
case ButtonPress:
break;
case ButtonRelease:
break;
case CreateNotify:
break;
case ConfigureNotify:
g_nWindowWidth = event.xconfigure.width;
g_nWindowHeight = event.xconfigure.height;
g_bConfigNotify = 2;
break;
}
}
};
void IVideo::Frame( float fDelta )
{
static uint32_t s_frameID = 0;
IVideo_HandleX11();
vk_framedata_t frame = g_frameData[s_frameID];
vkDeviceWaitIdle(g_vkDevice);
vkWaitForFences(g_vkDevice, 1, &frame.fence, VK_TRUE, UINT64_MAX);
uint32_t imageIndex = 0;
VkResult r = vkAcquireNextImageKHR(g_vkDevice, g_swapchain, UINT64_MAX, frame.draw, VK_NULL_HANDLE, &imageIndex);
if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR || g_bConfigNotify == 2)
{
g_bConfigNotify=1;
vkDeviceWaitIdle(g_vkDevice);
IVideo_SwapchainDestroy();
IVideo_SwapchainInit();
return;
}
vk_framedata_t frameindex = g_frameData[imageIndex];
vkResetFences(g_vkDevice, 1, &frame.fence);
g_vkCommandBuffer = g_commandBuffers[s_frameID];
g_swapchainImageView = g_swapchainImageViews[imageIndex];
g_swapchainImage = g_swapchainImages[imageIndex];
vkResetCommandBuffer(g_vkCommandBuffer, 0);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(g_vkCommandBuffer, &beginInfo);
IVulkan::Frame();
vkEndCommandBuffer(g_vkCommandBuffer);
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &frame.draw;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &g_vkCommandBuffer;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &frameindex.present;
vkQueueSubmit(g_drawQueue, 1, &submitInfo, frame.fence);
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &frameindex.present;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &g_swapchain;
presentInfo.pImageIndices = &imageIndex;
r = vkQueuePresentKHR(g_presentQueue, &presentInfo);
if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR)
{
vkDeviceWaitIdle(g_vkDevice);
IVideo_SwapchainDestroy();
IVideo_SwapchainInit();
return;
}
g_bConfigNotify = 0;
s_frameID=(s_frameID+1)%g_nNumSwapchainImages;
};

View File

@@ -1,566 +0,0 @@
#include "SDL3/SDL_gamepad.h"
#include "SDL3/SDL_joystick.h"
#include "rendering.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "console.h"
#include "tier1/commandline.h"
#include "input.h"
#include "vulkan/vulkan.h"
#include "SDL3/SDL.h"
#include "vulkan/vulkan_core.h"
#include "SDL3/SDL_keycode.h"
#include "SDL3/SDL_vulkan.h"
#include "SDL3/SDL_events.h"
#define VULKAN_RENDERING_IMPL
#include "vk_video.h"
#define VMA_VULKAN_VERSION 1004000
#define VMA_IMPLEMENTATION
#include "tier0/minmax_off.h"
#include "vk_mem_alloc.h"
#include "tier0/minmax.h"
SDL_Window *g_window;
VkInstance g_vkInstance = NULL;
VkPhysicalDevice g_vkPhysicalDevice = NULL;
VkDevice g_vkDevice = NULL;
uint32_t g_drawfamily = 0;
VkQueue g_drawQueue;
uint32_t g_presentfamily = 0;
VkQueue g_presentQueue;
VmaAllocator g_allocator = NULL;
VkSurfaceKHR g_surface;
VkSwapchainKHR g_swapchain;
ConVar vulkan_gpu("vk_gpu", "0", FCVAR_ARCHIVE);
VkCommandPool g_vkCommandPool;
/* more efficient */
CUtlVector<VkCommandBuffer> g_commandBuffers;
VkCommandBuffer g_vkCommandBuffer;
CUtlVector<vk_framedata_t> g_frameData;
CUtlVector<VkImage> g_swapchainImages;
CUtlVector<VkImageView> g_swapchainImageViews;
VkImageView g_swapchainImageView;
VkImage g_swapchainImage;
VkFormat g_swapchainFormat;
uint32_t g_nNumSwapchainImages = 0;
char g_bConfigNotify = 0;
uint32_t g_nWindowWidth = 1280;
uint32_t g_nWindowHeight = 720;
#define VK_DEVICE_FUNCTION(name) PFN_##name _##name
#include "vk_external_functions.cpp"
#undef VK_DEVICE_FUNCTION
void IVideo_SwapchainInit()
{
/* swapchain */
SDL_Vulkan_CreateSurface(g_window, g_vkInstance, NULL, &g_surface);
VkSurfaceCapabilitiesKHR surfaceCapatibilities = {};
vkGetPhysicalDeviceSurfaceCapabilitiesKHR(g_vkPhysicalDevice, g_surface, &surfaceCapatibilities);
const VkFormat preferedSurfaceFormats[] = {
VK_FORMAT_B8G8R8A8_UNORM,
VK_FORMAT_R8G8B8A8_UNORM,
};
uint32_t numSurfaceFormats = 0;
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, NULL);
CUtlVector<VkSurfaceFormatKHR> surfaceFormats(numSurfaceFormats);
vkGetPhysicalDeviceSurfaceFormatsKHR(g_vkPhysicalDevice, g_surface, &numSurfaceFormats, surfaceFormats.GetData());
VkSurfaceFormatKHR selectedFormat = surfaceFormats[0];
for (auto &format: surfaceFormats)
{
for (int i = 0; i < sizeof(preferedSurfaceFormats)/sizeof(VkFormat); i++)
{
if (format.format == preferedSurfaceFormats[i])
{
selectedFormat = format;
goto formatPicked;
}
}
}
formatPicked:
uint32_t numSurfacePresentModes = 0;
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, NULL);
CUtlVector<VkPresentModeKHR> surfacePresentModes(numSurfacePresentModes);
vkGetPhysicalDeviceSurfacePresentModesKHR(g_vkPhysicalDevice, g_surface, &numSurfacePresentModes, surfacePresentModes.GetData());
VkSwapchainCreateInfoKHR swapchainCreateInfo = {};
swapchainCreateInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
swapchainCreateInfo.surface = g_surface;
swapchainCreateInfo.imageFormat = selectedFormat.format;
swapchainCreateInfo.imageColorSpace = selectedFormat.colorSpace;
swapchainCreateInfo.presentMode = VK_PRESENT_MODE_IMMEDIATE_KHR;
swapchainCreateInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
swapchainCreateInfo.preTransform = surfaceCapatibilities.currentTransform;
swapchainCreateInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
swapchainCreateInfo.imageArrayLayers = 1;
swapchainCreateInfo.imageExtent = surfaceCapatibilities.minImageExtent;
swapchainCreateInfo.minImageCount = surfaceCapatibilities.minImageCount;
vkCreateSwapchainKHR(g_vkDevice, &swapchainCreateInfo, NULL, &g_swapchain);
vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, NULL);
g_swapchainImages = CUtlVector<VkImage>(g_nNumSwapchainImages);
g_swapchainImageViews = CUtlVector<VkImageView>(g_nNumSwapchainImages);
g_commandBuffers = CUtlVector<VkCommandBuffer>(g_nNumSwapchainImages);
g_frameData = CUtlVector<vk_framedata_t>(g_nNumSwapchainImages);
vkGetSwapchainImagesKHR(g_vkDevice, g_swapchain, &g_nNumSwapchainImages, g_swapchainImages.GetData());
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
VkImageViewCreateInfo createInfo = {};
createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
createInfo.image = g_swapchainImages[i];
createInfo.viewType = VK_IMAGE_VIEW_TYPE_2D;
createInfo.format = selectedFormat.format;
createInfo.components.r = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.g = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.b = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.components.a = VK_COMPONENT_SWIZZLE_IDENTITY;
createInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
createInfo.subresourceRange.baseMipLevel = 0;
createInfo.subresourceRange.levelCount = 1;
createInfo.subresourceRange.baseArrayLayer = 0;
createInfo.subresourceRange.layerCount = 1;
vkCreateImageView(g_vkDevice, &createInfo, NULL, &g_swapchainImageViews[i]);
}
g_swapchainFormat = selectedFormat.format;
/* command buffers */
VkCommandPoolCreateInfo commandPoolCreateInfo = {};
commandPoolCreateInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
commandPoolCreateInfo.queueFamilyIndex = g_drawfamily;
commandPoolCreateInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
vkCreateCommandPool(g_vkDevice, &commandPoolCreateInfo, NULL, &g_vkCommandPool);
VkCommandBufferAllocateInfo commandBufferAllocInfo = {};
commandBufferAllocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
commandBufferAllocInfo.commandPool = g_vkCommandPool;
commandBufferAllocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
commandBufferAllocInfo.commandBufferCount = g_nNumSwapchainImages;
vkAllocateCommandBuffers(g_vkDevice, &commandBufferAllocInfo, g_commandBuffers.GetData());
/* sync */
VkFenceCreateInfo fenceCreateInfo = {};
fenceCreateInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
fenceCreateInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT;
VkSemaphoreCreateInfo semaphoreCreateInfo = {};
semaphoreCreateInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
vkCreateFence(g_vkDevice,&fenceCreateInfo, NULL, &g_frameData[i].fence);
vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].draw);
vkCreateSemaphore(g_vkDevice, &semaphoreCreateInfo, NULL, &g_frameData[i].present);
}
};
void IVideo_SwapchainDestroy()
{
vkDestroySwapchainKHR(g_vkDevice, g_swapchain, NULL);
vkDestroySurfaceKHR(g_vkInstance, g_surface, NULL);
for (int i = 0; i < g_nNumSwapchainImages; i++)
{
vkDestroyImageView(g_vkDevice, g_swapchainImageViews[i], NULL);
vkDestroySemaphore(g_vkDevice, g_frameData[i].draw, NULL);
vkDestroySemaphore(g_vkDevice, g_frameData[i].present, NULL);
vkDestroyFence(g_vkDevice, g_frameData[i].fence, NULL);
}
};
EInputKey ISDL_KeyName(SDL_Keycode key)
{
switch(key)
{
case SDLK_ESCAPE: return KEY_ESCAPE;
case SDLK_TAB: return KEY_TAB;
case SDLK_RETURN: return KEY_ENTER;
case SDLK_RCTRL: return KEY_CONTROL;
case SDLK_LCTRL: return KEY_CONTROL;
case SDLK_RSHIFT: return KEY_SHIFT;
case SDLK_LSHIFT: return KEY_SHIFT;
case SDLK_RALT: return KEY_ALT;
case SDLK_LALT: return KEY_ALT;
case SDLK_SPACE: return KEY_SPACE;
case SDLK_GRAVE: return KEY_TILDE;
case SDLK_F1: return KEY_F1;
case SDLK_F2: return KEY_F2;
case SDLK_F3: return KEY_F3;
case SDLK_F4: return KEY_F4;
case SDLK_F5: return KEY_F5;
case SDLK_F6: return KEY_F6;
case SDLK_F7: return KEY_F7;
case SDLK_F8: return KEY_F8;
case SDLK_F9: return KEY_F9;
case SDLK_F10: return KEY_F10;
case SDLK_F11: return KEY_F11;
case SDLK_F12: return KEY_F12;
case SDLK_1: return KEY_1;
case SDLK_2: return KEY_2;
case SDLK_3: return KEY_3;
case SDLK_4: return KEY_4;
case SDLK_5: return KEY_5;
case SDLK_6: return KEY_6;
case SDLK_7: return KEY_7;
case SDLK_8: return KEY_8;
case SDLK_9: return KEY_9;
case SDLK_0: return KEY_0;
case SDLK_A: return KEY_A;
case SDLK_B: return KEY_B;
case SDLK_C: return KEY_C;
case SDLK_D: return KEY_D;
case SDLK_E: return KEY_E;
case SDLK_F: return KEY_F;
case SDLK_G: return KEY_G;
case SDLK_H: return KEY_H;
case SDLK_I: return KEY_I;
case SDLK_J: return KEY_J;
case SDLK_K: return KEY_K;
case SDLK_L: return KEY_L;
case SDLK_M: return KEY_M;
case SDLK_N: return KEY_N;
case SDLK_O: return KEY_O;
case SDLK_P: return KEY_P;
case SDLK_Q: return KEY_Q;
case SDLK_R: return KEY_R;
case SDLK_S: return KEY_S;
case SDLK_T: return KEY_T;
case SDLK_U: return KEY_U;
case SDLK_V: return KEY_V;
case SDLK_W: return KEY_W;
case SDLK_X: return KEY_X;
case SDLK_Y: return KEY_Y;
case SDLK_Z: return KEY_Z;
}
return KEY_NONE;
};
void IVideo::Init()
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_GAMEPAD);
g_window = SDL_CreateWindow("rtt", 1280, 720, SDL_WINDOW_VULKAN);
int nNumGamepads = 0;
SDL_JoystickID *pGamepads = SDL_GetGamepads(&nNumGamepads);
for ( uint32_t i = 0; i < nNumGamepads; i++ )
{
SDL_OpenGamepad(pGamepads[i]);
}
unsigned int nExtensionCount = 0;
const char* const* szExtensions = SDL_Vulkan_GetInstanceExtensions(&nExtensionCount);
vulkan_gpu.SetValue(ICommandLine::ParamValue("-gpu"));
VkResult r = VK_SUCCESS;
uint32_t i = 0;
/* Instance */
VkApplicationInfo applicationInfo = {};
applicationInfo.apiVersion = VK_API_VERSION_1_4;
VkInstanceCreateInfo instanceCreateInfo = {};
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &applicationInfo;
instanceCreateInfo.enabledExtensionCount = nExtensionCount;
instanceCreateInfo.ppEnabledExtensionNames = szExtensions;
r = vkCreateInstance(&instanceCreateInfo, NULL, &g_vkInstance);
if ( r != VK_SUCCESS )
Plat_FatalErrorFunc("Failed to create VkInstance!");
/* Physical Devices */
uint32_t nNumPhysicalDevices = 0;
vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, NULL);
if ( nNumPhysicalDevices == 0 )
Plat_FatalErrorFunc("No GPU drivers available!");
CUtlVector<VkPhysicalDevice> PhysicalDevices(nNumPhysicalDevices);
vkEnumeratePhysicalDevices(g_vkInstance, &nNumPhysicalDevices, PhysicalDevices.GetData());
/* enumerate them for the user */
for (auto &device: PhysicalDevices)
{
VkPhysicalDeviceProperties Properties = {};
vkGetPhysicalDeviceProperties(device, &Properties);
V_printf("GPU%i available: %s\n", i, Properties.deviceName);
i++;
}
/* select one in vk_gpu */
g_vkPhysicalDevice = PhysicalDevices[vulkan_gpu.GetInt()];
VkPhysicalDeviceProperties Properties = {};
vkGetPhysicalDeviceProperties(g_vkPhysicalDevice, &Properties);
V_printf("Using %s\n", Properties.deviceName);
/* queue family */
uint32_t nNumQueueFamilies = 0;
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, NULL);
CUtlVector<VkQueueFamilyProperties> queueFamilyProperties(nNumQueueFamilies);
vkGetPhysicalDeviceQueueFamilyProperties(g_vkPhysicalDevice, &nNumQueueFamilies, queueFamilyProperties.GetData());
i = 0;
for (auto &family: queueFamilyProperties)
{
if (family.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
g_drawfamily = i;
g_presentfamily = i;
}
i++;
}
/* create device */
float queuePriority = 1.0f;
VkDeviceQueueCreateInfo queueCreateInfo = {};
queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queueCreateInfo.queueFamilyIndex = g_drawfamily;
queueCreateInfo.queueCount = 1;
queueCreateInfo.pQueuePriorities = &queuePriority;
VkPhysicalDeviceShaderObjectFeaturesEXT pdsofe = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_FEATURES_EXT,
.pNext = 0,
.shaderObject = VK_TRUE,
};
VkPhysicalDeviceExtendedDynamicState3FeaturesEXT pdeds3fe = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_FEATURES_EXT,
.pNext = &pdsofe,
.extendedDynamicState3DepthClampEnable = VK_TRUE,
.extendedDynamicState3PolygonMode = VK_TRUE,
.extendedDynamicState3RasterizationSamples = VK_TRUE,
.extendedDynamicState3SampleMask = VK_TRUE,
.extendedDynamicState3AlphaToCoverageEnable = VK_TRUE,
};
VkPhysicalDeviceVulkan13Features pdv13f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_FEATURES,
.pNext = &pdeds3fe,
.synchronization2 = VK_TRUE,
.dynamicRendering = VK_TRUE,
};
VkPhysicalDeviceVulkan12Features pdv12f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES,
.pNext = &pdv13f,
.runtimeDescriptorArray = VK_TRUE,
.bufferDeviceAddress = VK_TRUE,
};
VkPhysicalDeviceVulkan11Features pdv11f = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_FEATURES,
.pNext = &pdv12f,
};
const char *szEnabledGPUExtensions[] = {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
VK_EXT_EXTENDED_DYNAMIC_STATE_3_EXTENSION_NAME,
};
VkDeviceCreateInfo deviceCreateInfo = {};
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
deviceCreateInfo.pQueueCreateInfos = &queueCreateInfo;
deviceCreateInfo.queueCreateInfoCount = 1;
deviceCreateInfo.enabledExtensionCount = sizeof(szEnabledGPUExtensions)/(sizeof(const char*));
deviceCreateInfo.ppEnabledExtensionNames = szEnabledGPUExtensions;
deviceCreateInfo.pNext = &pdv11f;
r = vkCreateDevice(g_vkPhysicalDevice, &deviceCreateInfo, NULL, &g_vkDevice);
if ( r != VK_SUCCESS )
Plat_FatalErrorFunc("Failed to create VkDevice!");
vkGetDeviceQueue(g_vkDevice, g_drawfamily, 0, &g_drawQueue);
vkGetDeviceQueue(g_vkDevice, g_presentfamily, 0, &g_presentQueue);
VmaVulkanFunctions vulkanFunctions = {};
vulkanFunctions.vkGetInstanceProcAddr = &vkGetInstanceProcAddr;
vulkanFunctions.vkGetDeviceProcAddr = &vkGetDeviceProcAddr;
VmaAllocatorCreateInfo allocatorCreateInfo = {};
allocatorCreateInfo.flags = VMA_ALLOCATOR_CREATE_BUFFER_DEVICE_ADDRESS_BIT;
allocatorCreateInfo.vulkanApiVersion = VK_API_VERSION_1_4;
allocatorCreateInfo.physicalDevice = g_vkPhysicalDevice;
allocatorCreateInfo.device = g_vkDevice;
allocatorCreateInfo.instance = g_vkInstance;
vmaCreateAllocator(&allocatorCreateInfo, &g_allocator);
#define VK_DEVICE_FUNCTION(name) _##name = (PFN_##name)vkGetDeviceProcAddr(g_vkDevice, #name)
#include "vk_external_functions.cpp"
#undef VK_DEVICE_FUNCTION
IVideo_SwapchainInit();
IVulkan::Init();
}
void IInput::SetInputMode( EInputMode mode )
{
switch (mode)
{
case INPUT_MODE_GAME:
SDL_SetWindowRelativeMouseMode(g_window, true);
return;
case INPUT_MODE_MENU:
SDL_SetWindowRelativeMouseMode(g_window, false);
return;
case INPUT_MODE_CONSOLE:
SDL_SetWindowRelativeMouseMode(g_window, true);
return;
default:
return;
}
}
ConVar m_pitch("m_pitch", "0.022", FCVAR_ARCHIVE);
ConVar m_yaw("m_yaw", "0.022", FCVAR_ARCHIVE);
void IVideo_HandleEvents()
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
SDL_KeyboardEvent *key = &event.key;
SDL_MouseMotionEvent *motion = &event.motion;
switch (event.type)
{
case SDL_EVENT_WINDOW_RESIZED:
g_nWindowWidth = event.window.data1;
g_nWindowHeight = event.window.data2;
g_bConfigNotify = 2;
break;
case SDL_EVENT_KEY_DOWN:
if (!key->repeat)
Input()->KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_DOWN);
break;
case SDL_EVENT_KEY_UP:
key = &event.key;
if (!key->repeat)
Input()->KeyEvent(ISDL_KeyName(key->key),KEY_EVENT_TYPE_UP);
break;
case SDL_EVENT_MOUSE_MOTION:
Input()->AxisEvent(AXIS_MOUSE_X, motion->yrel*m_pitch.GetFloat());
Input()->AxisEvent(AXIS_MOUSE_Y, -motion->xrel*m_yaw.GetFloat());
break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
{
SDL_GamepadAxis axis = (SDL_GamepadAxis)event.gaxis.axis;
float value = event.gaxis.value / 32768.0f;
if (abs(event.gaxis.value)<1000)
value = 0;
SDL_JoystickID id = event.gaxis.which;
if (axis == SDL_GAMEPAD_AXIS_RIGHTY)
{
Input()->AxisEvent(AXIS_CONTROLLER_PITCH, value);
}
if (axis == SDL_GAMEPAD_AXIS_RIGHTX)
{
Input()->AxisEvent(AXIS_CONTROLLER_YAW, -value);
}
}
break;
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
break;
case SDL_EVENT_GAMEPAD_BUTTON_UP:
break;
}
};
};
void IVideo::CreatePipelines( )
{
IVulkan::CreatePipelines();
};
void IVideo::Frame( float fDelta )
{
static uint32_t s_frameID = 0;
IVideo_HandleEvents();
vk_framedata_t frame = g_frameData[s_frameID];
vkDeviceWaitIdle(g_vkDevice);
vkWaitForFences(g_vkDevice, 1, &frame.fence, VK_TRUE, UINT64_MAX);
uint32_t imageIndex = 0;
VkResult r = vkAcquireNextImageKHR(g_vkDevice, g_swapchain, UINT64_MAX, frame.draw, VK_NULL_HANDLE, &imageIndex);
if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR || g_bConfigNotify == 2)
{
g_bConfigNotify=1;
vkDeviceWaitIdle(g_vkDevice);
IVideo_SwapchainDestroy();
IVideo_SwapchainInit();
return;
}
vk_framedata_t frameindex = g_frameData[imageIndex];
vkResetFences(g_vkDevice, 1, &frame.fence);
g_vkCommandBuffer = g_commandBuffers[s_frameID];
g_swapchainImageView = g_swapchainImageViews[imageIndex];
g_swapchainImage = g_swapchainImages[imageIndex];
vkResetCommandBuffer(g_vkCommandBuffer, 0);
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
vkBeginCommandBuffer(g_vkCommandBuffer, &beginInfo);
IVulkan::Frame();
vkEndCommandBuffer(g_vkCommandBuffer);
VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT};
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.waitSemaphoreCount = 1;
submitInfo.pWaitSemaphores = &frame.draw;
submitInfo.pWaitDstStageMask = waitStages;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &g_vkCommandBuffer;
submitInfo.signalSemaphoreCount = 1;
submitInfo.pSignalSemaphores = &frameindex.present;
vkQueueSubmit(g_drawQueue, 1, &submitInfo, frame.fence);
VkPresentInfoKHR presentInfo = {};
presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
presentInfo.waitSemaphoreCount = 1;
presentInfo.pWaitSemaphores = &frameindex.present;
presentInfo.swapchainCount = 1;
presentInfo.pSwapchains = &g_swapchain;
presentInfo.pImageIndices = &imageIndex;
r = vkQueuePresentKHR(g_presentQueue, &presentInfo);
if (r == VK_ERROR_OUT_OF_DATE_KHR || r == VK_SUBOPTIMAL_KHR)
{
vkDeviceWaitIdle(g_vkDevice);
IVideo_SwapchainDestroy();
IVideo_SwapchainInit();
return;
}
g_bConfigNotify = 0;
s_frameID=(s_frameID+1)%g_nNumSwapchainImages;
};

View File

@@ -1,32 +0,0 @@
#include "helper.h"
#include "c.h"
#include "ld.h"
#include "tier1/utlstring.h"
#include "tier1/commandline.h"
CUtlVector<CUtlString> fgui_CompiledFiles = {
"fgui/fgui.cpp",
"fgui/widget.cpp",
"fgui/rect.cpp",
"fgui/label.cpp",
};
CUtlString fgui_lib;
int fgui_build()
{
CCProject compileProject = {};
CLDProject ldProject = {};
compileProject.m_szName = "fgui";
compileProject.files = fgui_CompiledFiles;
compileProject.includeDirectories = all_IncludeDirectories;
compileProject.bFPIC = true;
ldProject = compileProject.Compile();
ldProject.linkType = ELINK_STATIC_LIBRARY;
CUtlString outputProject = ldProject.Link();
fgui_lib = outputProject;
return 0;
};
DECLARE_BUILD_STAGE(fgui, fgui_build);

View File

@@ -1,330 +0,0 @@
#include "fgui/fgui.h"
#include "filesystem.h"
#include "rendering.h"
#include "tier1/utlvector.h"
#include "fgui/widget.h"
#include "ctype.h"
float fgui_fRectColor[4];
float fgui_fTextColor[4];
float fgui_fTextPosition[2];
float fgui_fGlyphScale[2];
CFont *fgui_pTextFont;
float fgui_fOffset[2];
IGraphicsPipeline *fgui_RectPipeline;
IGraphicsPipeline *fgui_TextPipeline;
IVertexBuffer *fgui_pRectangleBuffer;
IVertexBuffer *fgui_pUVRectangleBuffer;
CUtlVector<CFGUI_Widget*> fgui_widgets;
void IFGUI::Init( void )
{
}
void IFGUI::Frame( void )
{
for (auto &widget: fgui_widgets)
{
widget->Frame();
}
}
//----------------------------------------------------------------------------
// Sets offset of the drawn widget
//----------------------------------------------------------------------------
void IFGUI::AddOffset( float x, float y)
{
fgui_fOffset[0] += x;
fgui_fOffset[1] += y;
}
//----------------------------------------------------------------------------
// Reset offset of the drawn widget
//----------------------------------------------------------------------------
void IFGUI::ResetOffset()
{
fgui_fOffset[0] = 0;
fgui_fOffset[1] = 0;
}
//----------------------------------------------------------------------------
// Creates new widget in the world
//----------------------------------------------------------------------------
void IFGUI::AppendWidget( CFGUI_Widget *pWidget )
{
fgui_widgets.AppendTail(pWidget);
}
//----------------------------------------------------------------------------
// Destroys widget
//----------------------------------------------------------------------------
void IFGUI::DestroyWidget( CFGUI_Widget *pWidget )
{
size_t i = 0;
for (auto &widget: fgui_widgets)
{
if (widget == pWidget)
{
fgui_widgets.RemoveAt(i);
return;
}
i++;
}
}
//----------------------------------------------------------------------------
//
//----------------------------------------------------------------------------
void IFGUI::SetRectColor( float r, float g, float b, float a )
{
fgui_fRectColor[0] = r;
fgui_fRectColor[1] = g;
fgui_fRectColor[2] = b;
fgui_fRectColor[3] = a;
}
//----------------------------------------------------------------------------
// Draws rectangle on the screen
//----------------------------------------------------------------------------
void IFGUI::DrawRect( int32_t iPosX, int32_t iPosY, uint32_t uSizeX, uint32_t uSizeY )
{
Renderer()->BindPipeline(fgui_RectPipeline);
struct RectConstants_t
{
uint32_t nResolution[2];
uint32_t nSize[2];
int32_t nPosition[2];
float offest0[2];
float fColor[4];
} constants;
constants.nResolution[0] = g_nWindowWidth;
constants.nResolution[1] = g_nWindowHeight;
constants.nPosition[0] = fgui_fOffset[0] + iPosX;
constants.nPosition[1] = fgui_fOffset[1] + iPosY;
constants.nSize[0] = uSizeX;
constants.nSize[1] = uSizeY;
for ( int i = 0; i < 4; i++ )
constants.fColor[i] = fgui_fRectColor[i];
Renderer()->SetConstants(sizeof(RectConstants_t), &constants);
Renderer()->Draw(fgui_pRectangleBuffer, NULL);
}
CUtlVector<CFont*> fgui_fonts;
CFont *fgui_pCurrentFont;
//----------------------------------------------------------------------------
// Loads new font
//----------------------------------------------------------------------------
CFont *IFGUI::LoadFont( CUtlString szFontPath )
{
for (auto &font: fgui_fonts)
{
if (font->szName == szFontPath)
return font;
};
CFont *pFont = new CFont;
pFont->szName = szFontPath;
pFont->pTexture = ITextureManager::LoadTexture(CUtlString("%s.png", szFontPath.GetString()));
FileHandle_t f = FileSystem()->Open(CUtlString("%s.fontdata", szFontPath.GetString()), IFILE_READ);
CUtlBuffer<char> b = FileSystem()->Size(f)+1;
FileSystem()->Read(f, b.GetMemory(), FileSystem()->Size(f));
FileSystem()->Close(f);
char cCharacterSet[256] = {};
V_memset(cCharacterSet, 0, 256);
uint32_t nElementsWidth;
uint32_t nElementsHeight;
V_sscanf(b, "%u %u %255s", &nElementsWidth, &nElementsHeight, cCharacterSet);
uint32_t nGlyphWidth = pFont->pTexture->x / nElementsWidth;
uint32_t nGlyphHeight = pFont->pTexture->y / nElementsHeight;
for ( int i = 0; i < 255; i++ )
{
if (isprint(cCharacterSet[i]) && !isspace(cCharacterSet[i]))
pFont->cCharacterSet[cCharacterSet[i]] = i;
else
pFont->cCharacterSet[cCharacterSet[i]] = -1;
}
pFont->glyphWidth = nGlyphWidth;
pFont->glyphHeight = nGlyphHeight;
pFont->nGlyphsPerRow = nElementsWidth;
pFont->nGlyphsPerColumn = nElementsHeight;
return pFont;
}
void IFGUI::SetGlyphScale( float x, float y )
{
fgui_fGlyphScale[0] = x;
fgui_fGlyphScale[1] = y;
};
void IFGUI::SetTextFont( CFont *pFont )
{
fgui_pTextFont = pFont;
}
void IFGUI::SetTextPos( float x, float y )
{
fgui_fTextPosition[0] = x;
fgui_fTextPosition[1] = y;
}
void IFGUI::SetTextColor( float r, float g, float b, float a )
{
fgui_fRectColor[0] = r;
fgui_fRectColor[1] = g;
fgui_fRectColor[2] = b;
fgui_fRectColor[3] = a;
}
void IFGUI::DrawText( CUtlString psz )
{
if (fgui_pTextFont == NULL)
{
V_printf("Forgot to call IFGUI::SetTextFont()?\n");
return;
}
Renderer()->BindPipeline(fgui_TextPipeline);
struct RectConstants_t
{
uint32_t nResolution[2];
uint32_t nSize[2];
int32_t nPosition[2];
float offest0[2];
float fColor[4];
float fGlyphPos[2];
float fGlyphSize[2];
uint32_t nFont;
} constants;
constants.nResolution[0] = g_nWindowWidth;
constants.nResolution[1] = g_nWindowHeight;
constants.nPosition[0] = fgui_fOffset[0] + fgui_fTextPosition[0];
constants.nPosition[1] = fgui_fOffset[1] + fgui_fTextPosition[1];
constants.nSize[0] = fgui_pTextFont->glyphWidth * fgui_fGlyphScale[0];
constants.nSize[1] = fgui_pTextFont->glyphHeight * fgui_fGlyphScale[1];
constants.fGlyphSize[0] = 1.0 / fgui_pTextFont->nGlyphsPerRow;
constants.fGlyphSize[1] = 1.0 / fgui_pTextFont->nGlyphsPerColumn;
constants.nFont = ITextureManager::GetTextureID(fgui_pTextFont->pTexture);
for ( int i = 0; i < 4; i++ )
constants.fColor[i] = fgui_fRectColor[i];
for ( int i = 0; psz[i]; i++)
{
constants.fGlyphPos[0] = fgui_pTextFont->cCharacterSet[psz[i]] % fgui_pTextFont->nGlyphsPerRow;
constants.fGlyphPos[1] = fgui_pTextFont->cCharacterSet[psz[i]] / fgui_pTextFont->nGlyphsPerRow;
if (isprint(psz[i]) && !isspace(psz[i]))
{
Renderer()->SetConstants(sizeof(RectConstants_t), &constants);
Renderer()->Draw(fgui_pUVRectangleBuffer, NULL);
}
constants.nPosition[0] += constants.nSize[0];
}
}
class CFGUI_Rendering: public IRenderingPipelineStep
{
public:
virtual void Init() override;
virtual void Frame( float fDelta ) override;
virtual void Deinit() override;
};
DECLARE_UI_RENDERING_STAGE(CFGUI_Rendering, fgui_rendering);
void CFGUI_Rendering::Init()
{
fgui_RectPipeline = Renderer()->CreateGraphicsPipeline(
{
{"gfx/fgui_rect_vert.shader", SHADER_TYPE_VERTEX},
{"gfx/fgui_rect_frag.shader", SHADER_TYPE_FRAGMENT},
},
{},
48,
8,
{{0,0,VERTEX_FORMAT_X32Y32}},
{IMAGE_FORMAT_WINDOW},
true
);
fgui_TextPipeline = Renderer()->CreateGraphicsPipeline(
{
{"gfx/fgui_text_vert.shader", SHADER_TYPE_VERTEX},
{"gfx/fgui_text_frag.shader", SHADER_TYPE_FRAGMENT},
},
{
{SHADER_INPUT_TYPE_TEXTURES, 29},
},
80,
16,
{{0,0, VERTEX_FORMAT_X32Y32},{8,1, VERTEX_FORMAT_X32Y32}},
{IMAGE_FORMAT_WINDOW},
true
);
{
float vertices[6*2] = {
0,0,
0,1,
1,0,
1,0,
0,1,
1,1,
};
fgui_pRectangleBuffer = Renderer()->CreateVertexBuffer(sizeof(vertices));
void *pMapping = fgui_pRectangleBuffer->Map();
V_memcpy(pMapping, vertices, sizeof(vertices));
fgui_pRectangleBuffer->Unmap();
}
{
float vertices[6*4] = {
0,0, 0,0,
0,1, 0,1,
1,0, 1,0,
1,0, 1,0,
0,1, 0,1,
1,1, 1,1,
};
fgui_pUVRectangleBuffer = Renderer()->CreateVertexBuffer(sizeof(vertices));
void *pMapping = fgui_pUVRectangleBuffer->Map();
V_memcpy(pMapping, vertices, sizeof(vertices));
fgui_pUVRectangleBuffer->Unmap();
}
};
void CFGUI_Rendering::Frame( float fDelta )
{
fgui_TextPipeline->PushBindings();
Renderer()->Begin(g_nWindowWidth, g_nWindowHeight, {
{
Renderer()->GetOutputImage(),
NULL,
ATTACHMENT_LOAD_MODE_LOAD,
ATTACHMENT_STORE_MODE_STORE,
}
}, {});
Renderer()->ResetState();
Renderer()->SetDepthMode(DEPTH_MODE_LESS);
for (auto &widget: fgui_widgets)
{
if (!widget->IsVisible())
{
continue;
}
IFGUI::ResetOffset();
widget->ComputeOffset();
widget->Draw();
}
Renderer()->End();
};
void CFGUI_Rendering::Deinit()
{
};

View File

@@ -1,49 +0,0 @@
#include "fgui/label.h"
#include "fgui/fgui.h"
CFGUI_Label::CFGUI_Label()
{
}
void CFGUI_Label::SetFont( CUtlString font )
{
m_pFont = IFGUI::LoadFont(font);
}
void CFGUI_Label::SetLabel( CUtlString text )
{
m_szText = text;
}
void CFGUI_Label::SetGlyphSize( uint32_t nSize )
{
if (!m_pFont)
return;
m_fGlyphScale[1] = (float)nSize/m_pFont->glyphHeight;
m_fGlyphScale[0] = m_fGlyphScale[1];
}
void CFGUI_Label::Event( FGUI_Event_t event )
{
}
void CFGUI_Label::Draw()
{
IFGUI::SetTextFont(m_pFont);
IFGUI::SetTextColor(1, 1, 1, 1);
IFGUI::SetGlyphScale(m_fGlyphScale[0], m_fGlyphScale[1]);
IFGUI::SetTextPos(m_iPosition[0], m_iPosition[1]);
IFGUI::DrawText(m_szText);
}
void CFGUI_Label::Frame()
{
}
CFGUI_Label::~CFGUI_Label()
{
}

View File

@@ -1,25 +0,0 @@
#include "fgui/rect.h"
void CFGUI_Rect::SetBoxColor( float r, float g, float b, float a )
{
m_fBoxColor[0] = r;
m_fBoxColor[1] = g;
m_fBoxColor[2] = b;
m_fBoxColor[3] = a;
};
void CFGUI_Rect::Event( FGUI_Event_t event )
{
}
void CFGUI_Rect::Draw()
{
IFGUI::SetRectColor(m_fBoxColor[0],m_fBoxColor[1],m_fBoxColor[2],m_fBoxColor[3]);
IFGUI::DrawRect(m_iPosition[0],m_iPosition[1],m_iSize[0],m_iSize[1]);
}
void CFGUI_Rect::Frame()
{
};

View File

@@ -1,55 +0,0 @@
#include "fgui/widget.h"
#include "fgui/fgui.h"
CFGUI_Widget::CFGUI_Widget()
{
IFGUI::AppendWidget(this);
}
CFGUI_Widget::~CFGUI_Widget()
{
}
void CFGUI_Widget::SetPosition( int32_t nX, int32_t nY )
{
m_iPosition[0] = nX;
m_iPosition[1] = nY;
}
void CFGUI_Widget::SetSize( uint32_t nX, uint32_t nY )
{
m_iSize[0] = nX;
m_iSize[1] = nY;
}
void CFGUI_Widget::SetParent( CFGUI_Widget *pParent )
{
m_pParent = pParent;
}
void CFGUI_Widget::ComputeOffset( void )
{
CFGUI_Widget *pParent = m_pParent;
while (pParent)
{
IFGUI::AddOffset(pParent->m_iPosition[0], pParent->m_iPosition[1]);
pParent = pParent->m_pParent;
};
}
bool CFGUI_Widget::IsVisible( )
{
CFGUI_Widget *pWidget = this;
while (pWidget)
{
if (!pWidget->m_bIsVisible)
return false;
pWidget = pWidget->m_pParent;
};
return true;
};
void CFGUI_Widget::SetVisibility( bool bValue )
{
m_bIsVisible = bValue;
}

View File

@@ -1,5 +1,6 @@
TIER_FILES := ../tier0/lib.cpp ../tier0/mem.cpp ../tier0/platform.cpp ../tier1/utlbuffer.cpp ../tier1/utlstring.cpp ../tier1/utlvector.cpp ../tier1/utlmap.cpp ../tier1/commandline.cpp
FPC_FILES := main.cpp library/runner.cpp library/helper.cpp library/c.cpp library/ld.cpp library/target.cpp
# We want to build just enough to use other stuff
TIER_FILES := ../tier0/lib.cpp ../tier0/mem.cpp ../tier0/platform.cpp ../tier1/utlbuffer.cpp ../tier1/interface.cpp ../tier1/utlstring.cpp ../tier1/utlvector.cpp ../tier1/utlmap.cpp ../tier1/commandline.cpp
FPC_FILES := main.cpp library/runner.cpp library/helper.cpp library/c.cpp library/ld.cpp library/clang/c.cpp library/clang/ld.cpp library/target.cpp
CC = clang
OUTPUT_DIR = fpc
CCFLAGS = -I../public -Ipublic -lc -lstdc++

34
fpc/README Normal file
View File

@@ -0,0 +1,34 @@
funny project compiler
fpc is a simple project manager written in C++ without usage of STL.
Instead it uses C++ files for building stuff with quite simple API.
It also generates compile_commands.json.
basics cheat sheet
With this toolset it should be sufficient enough to build any simple application.
DECLARE_BUILD_STAGE( stage_name, function ) - Declares build stage
CProject - compiler output base;
CShaderProject - shader compiler output base (NOT IMPLEMENTED)
CCProject - C, C++, Objective-C, Objective-C++ compiler
CLDProject - linker
IFileSystem2 - simple filesystem for creating, deleting and copying stuff
usage parameters cheat sheet
-os - sets target kernel
windows
linux
macos
ios
android
-arch - sets target arch
x86_64
aarch64
-fpcdebug - shows shell command used to run the command

View File

@@ -5,20 +5,28 @@
#include "signal.h"
CUtlVector<CUtlString> g_CompiledFiles = {
"../tier0/lib.cpp",
"../tier0/mem.cpp",
"../tier0/platform.cpp",
"../tier1/interface.cpp",
"../tier1/utlbuffer.cpp",
"../tier1/utlstring.cpp",
"../tier1/utlvector.cpp",
"../tier1/utlmap.cpp",
"../tier1/commandline.cpp",
"main.cpp",
"library/runner.cpp",
"library/helper.cpp",
"library/c.cpp",
"library/ld.cpp",
"library/target.cpp",
"../tier0/lib.cpp",
"../tier0/mem.cpp",
"../tier0/platform.cpp",
"../tier1/utlbuffer.cpp",
"../tier1/utlstring.cpp",
"../tier1/utlvector.cpp",
"../tier1/utlmap.cpp",
"../tier1/commandline.cpp",
"library/android/apktool.cpp",
"library/clang/c.cpp",
"library/clang/ld.cpp",
};
CUtlVector<CUtlString> g_IncludeDirectories = {
@@ -27,21 +35,20 @@ CUtlVector<CUtlString> g_IncludeDirectories = {
};
int build_fpc()
DECLARE_BUILD_STAGE(fpc)
{
CCProject compileProject = {};
CLDProject ldProject = {};
CProject_t compileProject = {};
LinkProject_t ldProject = {};
compileProject.m_szName = "fpc";
compileProject.files = g_CompiledFiles;
compileProject.includeDirectories = g_IncludeDirectories;
ldProject = compileProject.Compile();
ldProject = ccompiler->Compile(&compileProject);
CUtlString outputProject = ldProject.Link();
CUtlString outputProject = linker->Link(&ldProject);
IFileSystem2::MakeDirectory("../build/tools");
IFileSystem2::CopyFile("fpc_temp", outputProject);
filesystem2->MakeDirectory("../build/tools");
filesystem2->CopyFile("fpc_temp", outputProject);
return 0;
};
DECLARE_BUILD_STAGE(fpc, build_fpc);

View File

@@ -0,0 +1,139 @@
#include "apktool.h"
#include "helper.h"
#include "tier0/lib.h"
#include "tier0/platform.h"
#include "tier1/commandline.h"
#include "tier1/interface.h"
#include "runner.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
void AndroidManifest_t::SetPackageVersion( CUtlString szVersion )
{
m_szVersion = szVersion;
}
void AndroidManifest_t::SetPackageBuild( uint64_t nBuild )
{
m_nBuild = nBuild;
}
void AndroidManifest_t::SetPackageID( CUtlString szPackageID )
{
m_szPackageID = szPackageID;
}
void AndroidManifest_t::SetPackageName( CUtlString szPackageName )
{
m_szPackageName = szPackageName;
}
void AndroidManifest_t::SetTargetSDKVersion( uint64_t nTargetVersion )
{
m_nTargetVersion = nTargetVersion;
}
void AndroidManifest_t::SetMinSDKVersion( uint64_t nMinVersion )
{
m_nMinVersion = nMinVersion;
}
void AndroidManifest_t::AddUserFeature( CUtlString szName, bool bIsRequired, uint64_t nVersion )
{
}
void AndroidManifest_t::AddUserLibrary( CUtlString szPath )
{
}
CUtlString AndroidManifest_t::BuildManifest()
{
CPUProject_t project = {};
project.m_szName = m_szPackageName;
unsigned int hash = project.GenerateProjectHash();
CUtlString szOutputDir = CUtlString("%s/%s/android/%u_%s/",FPC_TEMPORAL_DIRNAME, project.m_target.GetTriplet().GetString(), hash, m_szPackageID.GetString());
filesystem2->MakeDirectory(szOutputDir);
filesystem2->MakeDirectory(CUtlString("%s/res", szOutputDir.GetString()));
CUtlString szAndroidManifestPath = CUtlString("%s/AndroidManifest.xml", szOutputDir.GetString());
FILE *pAndroidManifest = V_fopen(szAndroidManifestPath, "wb");
V_fprintf(pAndroidManifest, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
V_fprintf(pAndroidManifest, "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" package=\"%s\">\n", m_szPackageID.GetString());
V_fprintf(pAndroidManifest, "<uses-sdk android:minSdkVersion=\"%lu\" android:targetSdkVersion=\"%lu\" />\n",m_nMinVersion, m_nTargetVersion);
V_fprintf(pAndroidManifest, "<application android:label=\"%s\" android:hasCode=\"false\" android:debuggable=\"true\">\n", m_szPackageName.GetString());
V_fprintf(pAndroidManifest, "<activity android:name=\"android.app.NativeActivity\" android:label=\"%s\" android:exported=\"true\">\n", m_szPackageName.GetString());
V_fprintf(pAndroidManifest, "<meta-data android:name=\"android.app.lib_name\" android:value=\"native-app\" />\n");
V_fprintf(pAndroidManifest, "<intent-filter>\n");
V_fprintf(pAndroidManifest, "<action android:name=\"android.intent.action.MAIN\" />\n");
V_fprintf(pAndroidManifest, "<category android:name=\"android.intent.category.LAUNCHER\" />\n");
V_fprintf(pAndroidManifest, "</intent-filter>\n");
V_fprintf(pAndroidManifest, "</activity>\n");
V_fprintf(pAndroidManifest, "</application>\n");
V_fprintf(pAndroidManifest, "</manifest>\n");
V_fclose(pAndroidManifest);
return szOutputDir;
};
class CAPKTool : public IAPKTool
{
public:
virtual CUtlString BuildPackage( AndroidManifest_t manifest, CUtlString szManifestDir ) override;
private:
};
CUtlString CAPKTool::BuildPackage( AndroidManifest_t manifest, CUtlString szManifestDir )
{
V_printf(" APKTOOL %s\n", manifest.m_szPackageID.GetString());
if (CommandLine()->ParamValue("-android_build_tools"))
{
CUtlVector<CUtlString> args = {
"package",
"-f",
"-M",
"AndroidManifest.xml",
"-S",
"res",
"-I",
CUtlString("%s/../../platforms/android-%lu/android.jar", CommandLine()->ParamValue("-android_build_tools"), manifest.m_nTargetVersion),
"-F",
CUtlString("%s.unaligned.apk", manifest.m_szPackageID.GetString()),
};
CUtlString szAndroidSDK = CommandLine()->ParamValue("-android_build_tools");
runner->Run(CUtlString("%s/aapt",szAndroidSDK.GetString()),szManifestDir,args);
runner->Wait();
args = {
"-u",
CUtlString("%s.unaligned.apk", manifest.m_szPackageID.GetString()),
"lib/x86_64/libnative-app.so",
};
runner->Run("zip",szManifestDir, args);
runner->Wait();
args = {
"-f",
"-v",
"4",
CUtlString("%s.unaligned.apk", manifest.m_szPackageID.GetString()),
CUtlString("%s.apk", manifest.m_szPackageID.GetString()),
};
runner->Run(CUtlString("%s/zipalign",szAndroidSDK.GetString()),szManifestDir,args);
} else
Plat_FatalErrorFunc("-android_build_tools was not specified.");
return 0;
}
IAPKTool *APKTool()
{
static CAPKTool s_apktool = {};
return &s_apktool;
}

View File

@@ -0,0 +1,23 @@
#include "signtool.h"
#include "tier0/platform.h"
#include "tier1/interface.h"
class CAndroidSignTool : public ISignTool
{
public:
virtual void SignFile( CUtlString szFile ) override;
virtual void SignDirectory( CUtlString szDirectory ) override;
};
EXPOSE_INTERFACE(CAndroidSignTool, ISignTool, ANDROID_SIGN_TOOL_INTERFACE_NAME);
void CAndroidSignTool::SignFile( CUtlString szFile )
{
}
void CAndroidSignTool::SignDirectory( CUtlString szDirectory )
{
V_printf("Android doesn't support signing of directories\n");
}

View File

@@ -1,123 +1,3 @@
#include "c.h"
#include "filesystem.h"
#include "helper.h"
#include "target.h"
#include "tier0/lib.h"
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "libgen.h"
#include "ctype.h"
struct ClangFile_t
{
CUtlString m_szName;
CUtlVector<CUtlString> m_szArguments;
};
CUtlVector<ClangFile_t> g_clangFiles;
CLDProject CCProject::Compile()
{
CLDProject proj = {};
proj.m_szName = m_szName;
unsigned int hash = GenerateProjectHash();
for (auto &file: files)
{
CUtlString szTarget = m_target.GetTriplet();
CUtlString szOutputFile = CUtlString("%s/%s/cc/%u_%s/%s/%s.o",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, m_szName.GetString(), IFileSystem2::BuildDirectory(), file.GetString());
CUtlString szOutputDir = szOutputFile;
szOutputDir = dirname(szOutputDir);
IFileSystem2::MakeDirectory(szOutputDir);
}
for (auto &file: files)
{
CUtlVector<CUtlString> args;
V_printf(" CC %s\n", file.GetString());
CUtlString szTarget = m_target.GetTriplet();
CUtlString szOutputFile = CUtlString("%s/%s/cc/%u_%s/%s/%s.o",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, m_szName.GetString(), IFileSystem2::BuildDirectory(), file.GetString());
args = {
"-target",
szTarget,
"-g",
"-c",
"-o",
szOutputFile,
file,
};
if (!strcmp(Plat_GetExtension(file),"cpp"))
args.AppendTail("-std=c++17");
else if (!strcmp(Plat_GetExtension(file),"mm"))
;
else
args.AppendTail("-std=c99");
if (m_target.kernel == TARGET_KERNEL_DARWIN)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk");
}
if (m_target.kernel == TARGET_KERNEL_IOS)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk");
args.AppendTail("-miphoneos-version-min=18.0 ");
args.AppendTail("-fembed-bitcode");
}
if (bFPIC)
args.AppendTail("-fPIC");
if (bFPIE)
args.AppendTail("-fPIE");
for (auto &macro: macros)
{
args.AppendTail("-D");
args.AppendTail(CUtlString("%s=%s", (char*)macro.szName, (char*)macro.szValue));
}
for (auto &include: includeDirectories)
{
args.AppendTail("-I");
args.AppendTail(include);
}
for (auto &include: includeFiles)
{
args.AppendTail("-include");
args.AppendTail(include);
}
if (!IFileSystem2::ShouldRecompile(file, szOutputFile))
goto skipcompile;
IRunner::Run("clang", args);
skipcompile:
proj.objects.AppendTail((CObject){szOutputFile});
ClangFile_t cfile = {};
cfile.m_szName = file;
cfile.m_szArguments = args;
g_clangFiles.AppendTail(cfile);
}
return proj;
}
void CCProject::GenerateCompileCommands()
{
FILE* f = V_fopen("compile_commands.json", "w");
V_fprintf(f, "[\n");
uint32_t i = 0;
for (auto &file: g_clangFiles)
{
V_fprintf(f, "\t{\n");
V_fprintf(f, "\t\t\"arguments\": [\n");
V_fprintf(f, "\t\t\t\"clang\",\n");
for (auto &arg: file.m_szArguments)
V_fprintf(f, "\t\t\t\"%s\",\n",arg.GetString());
V_fseek(f, -2, SEEK_CUR);
V_fprintf(f, "\n\t\t],\n");
V_fprintf(f, "\t\t\"file\": \"%s\",\n", file.m_szName.GetString());
V_fprintf(f, "\t\t\"directory\": \"%s\"\n", IFileSystem2::BuildDirectory());
V_fprintf(f, "\t},\n");
};
V_fseek(f, -2, SEEK_CUR);
V_fprintf(f, "\n]\n");
V_fclose(f);
};
ICCompiler *ccompiler;

164
fpc/library/clang/c.cpp Normal file
View File

@@ -0,0 +1,164 @@
#include "c.h"
#include "helper.h"
#include "obj.h"
#include "target.h"
#include "tier0/lib.h"
#include "tier0/platform.h"
#include "tier1/interface.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
#include "libgen.h"
#include "ctype.h"
struct ClangFile_t
{
CUtlString m_szName;
CUtlVector<CUtlString> m_szArguments;
};
class CClangCompiler : public ICCompiler
{
public:
virtual LinkProject_t Compile( CProject_t *pProject ) override;
virtual void GenerateLinterData( void ) override;
};
EXPOSE_INTERFACE(CClangCompiler, ICCompiler, CLANG_C_COMPILER_INTERFACE_NAME);
CUtlVector<ClangFile_t> g_clangFiles;
LinkProject_t CClangCompiler::Compile( CProject_t *pProject )
{
LinkProject_t proj = {};
proj.m_szName = pProject->m_szName;
proj.m_target = pProject->m_target;
proj.m_androidmanifest = pProject->m_androidmanifest;
unsigned int hash = pProject->GenerateProjectHash();
for (auto &file: pProject->files)
{
CUtlString szTarget = pProject->m_target.GetTriplet();
CUtlString szOutputFile = CUtlString("%s/%s/cc/%u_%s/%s/%s.o",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, pProject->m_szName.GetString(), filesystem2->BuildDirectory(), file.GetString());
CUtlString szOutputDir = szOutputFile;
szOutputDir = dirname(szOutputDir);
filesystem2->MakeDirectory(szOutputDir);
}
for (auto &file: pProject->files)
{
CUtlVector<CUtlString> args;
V_printf(" CC %s\n", file.GetString());
CUtlString szTarget = pProject->m_target.GetTriplet();
CUtlString szCompiledTarget = szTarget;
if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
szCompiledTarget = CUtlString("%s%u", szTarget.GetString(), pProject->m_androidmanifest.m_nTargetVersion);
}
CUtlString szOutputFile = CUtlString("%s/%s/cc/%u_%s/%s/%s.o",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, pProject->m_szName.GetString(), filesystem2->BuildDirectory(), file.GetString());
args = {
"-target",
szCompiledTarget,
"-g",
"-c",
"-o",
szOutputFile,
file,
};
if (!strcmp(Plat_GetExtension(file),"cpp"))
args.AppendTail("-std=c++17");
else if (!strcmp(Plat_GetExtension(file),"mm"))
;
else
args.AppendTail("-std=c99");
if (pProject->m_target.kernel == TARGET_KERNEL_DARWIN)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk");
} else if (pProject->m_target.kernel == TARGET_KERNEL_IOS)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk");
args.AppendTail("-miphoneos-version-min=18.0 ");
args.AppendTail("-fembed-bitcode");
}
if (pProject->m_target.szSysroot)
{
args.AppendTail(CUtlString("--sysroot=%s", pProject->m_target.szSysroot));
}
if (pProject->bFPIC)
args.AppendTail("-fPIC");
if (pProject->bFPIE)
args.AppendTail("-fPIE");
for (auto &macro: pProject->macros)
{
args.AppendTail("-D");
args.AppendTail(CUtlString("%s=%s", (char*)macro.szName, (char*)macro.szValue));
}
for (auto &include: pProject->includeDirectories)
{
args.AppendTail("-I");
args.AppendTail(include);
}
for (auto &include: pProject->includeFiles)
{
args.AppendTail("-include");
args.AppendTail(include);
}
if (!filesystem2->ShouldRecompile(file, szOutputFile))
goto skipcompile;
if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
if (!pProject->m_target.szSysroot)
Plat_FatalErrorFunc("-sysroot must be specified for android\n");
runner->Run(CUtlString("%s/bin/clang",pProject->m_target.szSysroot), args);
}
else
{
runner->Run("clang", args);
}
skipcompile:
proj.objects.AppendTail((Object_t){szOutputFile});
ClangFile_t cfile = {};
cfile.m_szName = file;
cfile.m_szArguments = args;
if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
if (!pProject->m_target.szSysroot)
Plat_FatalErrorFunc("-sysroot must be specified for android\n");
cfile.m_szArguments.AppendHead(CUtlString("%s/bin/clang",pProject->m_target.szSysroot));
}
else
cfile.m_szArguments.AppendHead("clang");
g_clangFiles.AppendTail(cfile);
}
return proj;
}
void CClangCompiler::GenerateLinterData()
{
FILE* f = V_fopen("compile_commands.json", "wb");
V_fprintf(f, "[\n");
uint32_t i = 0;
for (auto &file: g_clangFiles)
{
V_fprintf(f, "\t{\n");
V_fprintf(f, "\t\t\"arguments\": [\n");
for (auto &arg: file.m_szArguments)
V_fprintf(f, "\t\t\t\"%s\",\n",arg.GetString());
V_fseek(f, -2, SEEK_CUR);
V_fprintf(f, "\n\t\t],\n");
V_fprintf(f, "\t\t\"file\": \"%s\",\n", file.m_szName.GetString());
V_fprintf(f, "\t\t\"directory\": \"%s\"\n", filesystem2->BuildDirectory());
V_fprintf(f, "\t},\n");
};
V_fseek(f, -2, SEEK_CUR);
V_fprintf(f, "\n]\n");
V_fclose(f);
};

175
fpc/library/clang/ld.cpp Normal file
View File

@@ -0,0 +1,175 @@
#include "ld.h"
#include "helper.h"
#include "libgen.h"
#include "target.h"
#include "tier0/platform.h"
#include "tier1/interface.h"
#include "tier1/utlstring.h"
class CClangLinker : public ILinker
{
public:
virtual CUtlString Link( LinkProject_t *pProject ) override;
};
EXPOSE_INTERFACE(CClangLinker, ILinker, CLANG_LINKER_INTERFACE_NAME);
CUtlString CClangLinker::Link( LinkProject_t *pProject )
{
CUtlString szFileName;
unsigned int hash = pProject->GenerateProjectHash();
switch(pProject->linkType)
{
case ELINK_EXECUTABLE:
if (pProject->m_target.kernel == TARGET_KERNEL_WINDOWS)
szFileName = CUtlString("%s.exe", pProject->m_szName.GetString());
else if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
szFileName = CUtlString("lib%s.so", pProject->m_szName.GetString());
else
szFileName = CUtlString("%s", pProject->m_szName.GetString());
break;
case ELINK_STATIC_LIBRARY:
szFileName = CUtlString("lib%s.a", pProject->m_szName.GetString());
break;
case ELINK_DYNAMIC_LIBRARY:
if (pProject->m_target.kernel == TARGET_KERNEL_DARWIN)
szFileName = CUtlString("lib%s.dylib", pProject->m_szName.GetString());
if (pProject->m_target.kernel == TARGET_KERNEL_LINUX)
szFileName = CUtlString("lib%s.so", pProject->m_szName.GetString());
break;
}
CUtlString szTarget = pProject->m_target.GetTriplet();
CUtlString szOutputFile = CUtlString("%s/%s/ld/%u_%s/%s",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, pProject->m_szName.GetString(), szFileName.GetString());
CUtlString szOutputDir = szOutputFile;
szOutputDir = dirname(szOutputDir);
filesystem2->MakeDirectory(szOutputDir);
if (pProject->linkType == ELINK_STATIC_LIBRARY)
{
V_printf(" AR %s\n", pProject->m_szName.GetString());
bool shouldRecompile = false;
CUtlVector<CUtlString> args;
for (auto object: pProject->objects)
{
if (filesystem2->ShouldRecompile(object.m_szObjectFile,szOutputFile))
{
shouldRecompile = true;
break;
}
}
if (!shouldRecompile)
goto compiled;
args = {
"rcs",
szOutputFile
};
for (auto object: pProject->objects)
args.AppendTail(object.m_szObjectFile);
runner->Run("ar", args);
runner->Wait();
} else {
V_printf(" LINK %s\n", pProject->m_szName.GetString());
bool shouldRecompile = false;
CUtlVector<CUtlString> args;
for (auto object: pProject->objects)
{
if (filesystem2->ShouldRecompile(object.m_szObjectFile,szOutputFile))
{
shouldRecompile = true;
break;
}
}
if (!shouldRecompile)
goto compiled;
CUtlString szTarget = pProject->m_target.GetTriplet();
CUtlString szCompiledTarget = szTarget;
if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
szCompiledTarget = CUtlString("%s%u", szTarget.GetString(), pProject->m_androidmanifest.m_nTargetVersion);
}
args = {
"-o",
szOutputFile,
"-target",
szCompiledTarget,
};
if (pProject->bNoStdLib)
{
args.AppendTail("-nostdlib");
}
if (pProject->m_target.kernel == TARGET_KERNEL_DARWIN)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk");
args.AppendTail("-Wl,-export_dynamic");
args.AppendTail("-undefined");
args.AppendTail("dynamic_lookup");
}
else if (pProject->m_target.kernel == TARGET_KERNEL_IOS)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk");
args.AppendTail("-miphoneos-version-min=18.0 ");
args.AppendTail("-fembed-bitcode");
args.AppendTail("-Wl,-rpath,@executable_path");
args.AppendTail("-Wl,-all_load");
args.AppendTail("-w");
}
else if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
args.AppendTail(CUtlString("--sysroot=%s/sysroot", pProject->m_target.szSysroot));
args.AppendTail("-static-libstdc++");
}
else if (pProject->m_target.szSysroot)
{
args.AppendTail(CUtlString("--sysroot=%s", pProject->m_target.szSysroot));
}
if (pProject->m_target.kernel == TARGET_KERNEL_WINDOWS)
{
args.AppendTail("-fuse-ld=ld");
}
if (pProject->m_target.kernel == TARGET_KERNEL_LINUX || pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
args.AppendTail("-rdynamic");
}
if (pProject->linkType == ELINK_DYNAMIC_LIBRARY || pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
args.AppendTail("-shared");
}
if (pProject->m_target.kernel == TARGET_KERNEL_WINDOWS || pProject->m_target.kernel == TARGET_KERNEL_LINUX || pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
args.AppendTail("-Wl,--whole-archive");
for (auto object: pProject->objects)
args.AppendTail(object.m_szObjectFile);
if (pProject->m_target.kernel == TARGET_KERNEL_WINDOWS || pProject->m_target.kernel == TARGET_KERNEL_LINUX || pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
args.AppendTail("-Wl,--no-whole-archive");
for (auto lib: pProject->libraries)
{
args.AppendTail("-l");
args.AppendTail(lib);
}
for (auto &directory: pProject->frameworkDirectories)
{
args.AppendTail("-F");
args.AppendTail(directory);
}
for (auto &framework: pProject->frameworks)
{
args.AppendTail("-framework");
args.AppendTail(framework);
}
if (pProject->m_target.kernel == TARGET_KERNEL_ANDROID)
{
if (!pProject->m_target.szSysroot)
Plat_FatalErrorFunc("-sysroot must be specified for android\n");
runner->Run(CUtlString("%s/bin/clang++",pProject->m_target.szSysroot), args);
}
else
{
runner->Run("clang++", args);
}
runner->Wait();
}
compiled:
return szOutputFile;
};

View File

@@ -6,12 +6,13 @@
#include "unistd.h"
#include "libgen.h"
#include "sys/stat.h"
#include "tier1/interface.h"
#ifdef __APPLE__
#include <mach-o/dyld.h>
#endif
unsigned int g_hashState = 102851263;
unsigned int CProject::GenerateProjectHash( void )
unsigned int BaseProject_t::GenerateProjectHash( void )
{
unsigned int hash = 5381+g_hashState;
int c;
@@ -31,50 +32,65 @@ static ssize_t pathSize = readlink("/proc/self/exe", path, sizeof(path) - 1);
#endif
#ifdef __APPLE__
static uint32_t pathSize = sizeof(path);
int pathResult = _NSGetExecutablePath(path, &pathSize);
static int pathResult = _NSGetExecutablePath(path, &pathSize);
#endif
char *szPathDir = dirname(path);
char *szBuildDir = 0;
char *IFileSystem2::OwnDirectory()
static char *szPathDir = dirname(path);
char *g_szBuildDir = 0;
class CPOSIXFileSystem2: public IFileSystem2
{
public:
virtual char *OwnDirectory() override;
virtual char *BuildDirectory() override;
virtual void MakeDirectory( const char *psz ) override;
virtual void CopyFile( const char *szDestination, const char *szOrigin ) override;
virtual void CopyDirectory( const char *szDestination, const char *szOrigin ) override;
virtual bool ShouldRecompile( const char *szSource, const char *szOutput ) override;
};
EXPOSE_INTERFACE(CPOSIXFileSystem2, IFileSystem2, FILE_SYSTEM_2_INTERFACE_NAME);
IFileSystem2 *filesystem2;
char *CPOSIXFileSystem2::OwnDirectory()
{
return szPathDir;
};
char *IFileSystem2::BuildDirectory()
char *CPOSIXFileSystem2::BuildDirectory()
{
return szBuildDir;
return g_szBuildDir;
};
void IFileSystem2::CopyFile( const char *szDestination, const char *szOrigin )
void CPOSIXFileSystem2::CopyFile( const char *szDestination, const char *szOrigin )
{
CUtlVector<CUtlString> args = {
CUtlString(szOrigin),
CUtlString(szDestination),
};
IRunner::Run("cp", args);
IRunner::Wait();
runner->Run("cp", args);
runner->Wait();
}
void IFileSystem2::CopyDirectory( const char *szDestination, const char *szOrigin )
void CPOSIXFileSystem2::CopyDirectory( const char *szDestination, const char *szOrigin )
{
CUtlVector<CUtlString> args = {
"-r",
CUtlString(szOrigin),
CUtlString(szDestination),
};
IRunner::Run("cp", args);
IRunner::Wait();
runner->Run("cp", args);
runner->Wait();
}
void IFileSystem2::MakeDirectory( const char *psz )
void CPOSIXFileSystem2::MakeDirectory( const char *psz )
{
CUtlVector<CUtlString> args = {
"-p",
CUtlString(psz),
};
IRunner::Run("mkdir", args);
IRunner::Wait();
runner->Run("mkdir", args);
runner->Wait();
};
bool IFileSystem2::ShouldRecompile(const char *szSource, const char *szOutput)
bool CPOSIXFileSystem2::ShouldRecompile(const char *szSource, const char *szOutput)
{
struct stat srcbuf;
struct stat outbuf;

View File

@@ -1,134 +1,3 @@
#include "ld.h"
#include "helper.h"
#include "libgen.h"
#include "target.h"
CUtlString CLDProject::Link( void )
{
CUtlString szFileName;
unsigned int hash = GenerateProjectHash();
switch(linkType)
{
case ELINK_EXECUTABLE:
if (m_target.kernel == TARGET_KERNEL_WINDOWS)
szFileName = CUtlString("%s.exe", m_szName.GetString());
else
szFileName = CUtlString("%s", m_szName.GetString());
break;
case ELINK_STATIC_LIBRARY:
szFileName = CUtlString("lib%s.a", m_szName.GetString());
break;
case ELINK_DYNAMIC_LIBRARY:
if (m_target.kernel == TARGET_KERNEL_DARWIN)
szFileName = CUtlString("lib%s.dylib", m_szName.GetString());
if (m_target.kernel == TARGET_KERNEL_LINUX)
szFileName = CUtlString("lib%s.so", m_szName.GetString());
break;
}
CUtlString szTarget = m_target.GetTriplet();
CUtlString szOutputFile = CUtlString("%s/%s/ld/%u_%s/%s",FPC_TEMPORAL_DIRNAME, szTarget.GetString(), hash, m_szName.GetString(), szFileName.GetString());
CUtlString szOutputDir = szOutputFile;
szOutputDir = dirname(szOutputDir);
IFileSystem2::MakeDirectory(szOutputDir);
if (linkType == ELINK_STATIC_LIBRARY)
{
V_printf(" AR %s\n", m_szName.GetString());
bool shouldRecompile = false;
CUtlVector<CUtlString> args;
for (auto object: objects)
{
if (IFileSystem2::ShouldRecompile(object.m_szObjectFile,szOutputFile))
{
shouldRecompile = true;
break;
}
}
if (!shouldRecompile)
goto compiled;
args = {
"rcs",
szOutputFile
};
for (auto object: objects)
args.AppendTail(object.m_szObjectFile);
IRunner::Run("ar", args);
IRunner::Wait();
} else {
V_printf(" LINK %s\n", m_szName.GetString());
bool shouldRecompile = false;
CUtlVector<CUtlString> args;
for (auto object: objects)
{
if (IFileSystem2::ShouldRecompile(object.m_szObjectFile,szOutputFile))
{
shouldRecompile = true;
break;
}
}
if (!shouldRecompile)
goto compiled;
args = {
"-o",
szOutputFile,
"-target",
m_target.GetTriplet(),
};
if (m_target.kernel == TARGET_KERNEL_DARWIN)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk");
args.AppendTail("-Wl,-export_dynamic");
args.AppendTail("-undefined");
args.AppendTail("dynamic_lookup");
}
if (m_target.kernel == TARGET_KERNEL_IOS)
{
args.AppendTail("-isysroot");
args.AppendTail("/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk");
args.AppendTail("-miphoneos-version-min=18.0 ");
args.AppendTail("-fembed-bitcode");
args.AppendTail("-Wl,-rpath,@executable_path");
args.AppendTail("-Wl,-all_load");
args.AppendTail("-w");
}
if (m_target.kernel == TARGET_KERNEL_WINDOWS)
{
args.AppendTail("-fuse-ld=ld");
}
if (m_target.kernel == TARGET_KERNEL_LINUX)
{
args.AppendTail("-rdynamic");
}
if (linkType == ELINK_DYNAMIC_LIBRARY)
{
args.AppendTail("-shared");
}
if (m_target.kernel == TARGET_KERNEL_WINDOWS || m_target.kernel == TARGET_KERNEL_LINUX)
args.AppendTail("-Wl,--whole-archive");
for (auto object: objects)
args.AppendTail(object.m_szObjectFile);
if (m_target.kernel == TARGET_KERNEL_WINDOWS || m_target.kernel == TARGET_KERNEL_LINUX)
args.AppendTail("-Wl,--no-whole-archive");
for (auto lib: libraries)
{
args.AppendTail("-l");
args.AppendTail(lib);
}
for (auto &directory: frameworkDirectories)
{
args.AppendTail("-F");
args.AppendTail(directory);
}
for (auto &framework: frameworks)
{
args.AppendTail("-framework");
args.AppendTail(framework);
}
IRunner::Run("clang++", args);
IRunner::Wait();
}
compiled:
return szOutputFile;
};
ILinker *linker;

View File

@@ -1,5 +1,6 @@
#include "runner.h"
#include "tier0/platform.h"
#include "tier1/interface.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
#include "unistd.h"
@@ -7,7 +8,20 @@
#include "tier1/commandline.h"
CUtlVector<pid_t> g_processes;
int IRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
class CPOSIXRunner: public IRunner
{
public:
virtual int Run( CUtlString szName, CUtlVector<CUtlString>& args ) override;
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args ) override;
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment ) override;
virtual int Wait( void ) override;
};
EXPOSE_INTERFACE(CPOSIXRunner, IRunner, RUNNER_INTERFACE_NAME);
IRunner *runner;
int CPOSIXRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
{
pid_t pid = fork();
if (pid < 0)
@@ -17,15 +31,15 @@ int IRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
{
CUtlVector<const char*> execargs;
execargs.AppendTail(szName);
if (ICommandLine::CheckParam("-fpcdebug"))
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf("%s",szName.GetString());
for (auto &arg: args)
{
execargs.AppendTail(arg);
if (ICommandLine::CheckParam("-fpcdebug"))
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf(" %s",arg.GetString());
}
if (ICommandLine::CheckParam("-fpcdebug"))
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf("\n");
execargs.AppendTail(0);
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
@@ -38,7 +52,7 @@ int IRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
return 0;
}
int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args)
int CPOSIXRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args)
{
pid_t pid = fork();
if (pid < 0)
@@ -48,10 +62,16 @@ int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlStrin
{
CUtlVector<const char*> execargs;
execargs.AppendTail(szName);
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf("%s",szName.GetString());
for (auto &arg: args)
{
execargs.AppendTail(arg);
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf(" %s",arg.GetString());
}
if (CommandLine()->CheckParam("-fpcdebug"))
V_printf("\n");
execargs.AppendTail(0);
chdir(szDirectory.GetString());
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
@@ -65,12 +85,12 @@ int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlStrin
return 0;
}
int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment)
int CPOSIXRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment)
{
}
int IRunner::Wait( void )
int CPOSIXRunner::Wait( void )
{
for (auto &process: g_processes)
{

View File

@@ -2,7 +2,9 @@
#include "tier1/commandline.h"
#include "tier1/utlstring.h"
//-----------------------------------------------------------------------------
// Generates triplet suitable for most compilers.
//-----------------------------------------------------------------------------
CUtlString Target_t::GetTriplet()
{
CUtlString triplet = "";
@@ -11,15 +13,25 @@ CUtlString Target_t::GetTriplet()
triplet.AppendTail("x86_64");
if ( cpu == TARGET_CPU_AARCH64 )
triplet.AppendTail("aarch64");
if ( cpu == TARGET_CPU_WASM32 )
triplet.AppendTail("wasm32");
triplet.AppendTail("-");
if ( kernel == TARGET_KERNEL_WINDOWS )
triplet.AppendTail("pc-windows-gnu");
if ( kernel == TARGET_KERNEL_UNKNOWN )
triplet.AppendTail("unknown-unknown");
if ( kernel == TARGET_KERNEL_LINUX )
triplet.AppendTail("unknown-linux-gnu");
if ( kernel == TARGET_KERNEL_WINDOWS )
triplet.AppendTail("pc-windows-gnu");
if ( kernel == TARGET_KERNEL_DARWIN )
triplet.AppendTail("apple-darwin");
if ( kernel == TARGET_KERNEL_IOS )
triplet.AppendTail("apple-ios");
if ( kernel == TARGET_KERNEL_ANDROID )
triplet.AppendTail("linux-android");
if ( kernel == TARGET_KERNEL_WASI )
triplet.AppendTail("unknown-wasi");
if ( kernel == TARGET_KERNEL_EMSCRIPTEN )
triplet.AppendTail("unknown-emscripten");
return triplet;
@@ -40,11 +52,15 @@ Target_t Target_t::HostTarget()
.optimization = TARGET_DEBUG,
};
};
//-----------------------------------------------------------------------------
// Returns default target for build
//-----------------------------------------------------------------------------
Target_t Target_t::DefaultTarget()
{
CUtlString szDevice = ICommandLine::ParamValue("-device");
CUtlString szOS = ICommandLine::ParamValue("-os");
CUtlString szArch = ICommandLine::ParamValue("-arch");
CUtlString szDevice = CommandLine()->ParamValue("-device");
CUtlString szOS = CommandLine()->ParamValue("-os");
CUtlString szArch = CommandLine()->ParamValue("-arch");
ETargetKernel kernel =
#if defined(__linux__)
@@ -58,8 +74,12 @@ Target_t Target_t::DefaultTarget()
cpu = TARGET_CPU_AMD64;
else if ( szArch == "aarch64" )
cpu = TARGET_CPU_AARCH64;
else if ( szArch == "wasm32" )
cpu = TARGET_CPU_WASM32;
if ( szOS == "windows" )
if ( szOS == "unknown" )
kernel = TARGET_KERNEL_UNKNOWN;
else if ( szOS == "windows" )
kernel = TARGET_KERNEL_WINDOWS;
else if ( szOS == "linux" )
kernel = TARGET_KERNEL_LINUX;
@@ -67,6 +87,8 @@ Target_t Target_t::DefaultTarget()
kernel = TARGET_KERNEL_DARWIN;
else if ( szOS == "ios" )
kernel = TARGET_KERNEL_IOS;
else if ( szOS == "android" )
kernel = TARGET_KERNEL_ANDROID;
else if ( szOS != 0 )
V_printf("Unknown OS: %s\n", szOS.GetString());

View File

@@ -2,34 +2,43 @@
#include "public/helper.h"
#include "public/ld.h"
#include "public/target.h"
#include "runner.h"
#include "tier0/platform.h"
#include "tier1/commandline.h"
#include "c.h"
#include "tier1/interface.h"
#include "tier1/utlvector.h"
#include "signal.h"
#include "libgen.h"
#include <unistd.h>
CUtlString owndir;
extern char *g_szBuildDir;
int build()
{
extern char *szBuildDir;
CCProject compileScriptProject = {};
runner = (IRunner*)CreateInterface(RUNNER_INTERFACE_NAME, NULL);
filesystem2 = (IFileSystem2*)CreateInterface(FILE_SYSTEM_2_INTERFACE_NAME, NULL);
ccompiler = (ICCompiler*)CreateInterface(CLANG_C_COMPILER_INTERFACE_NAME, NULL);
linker = (ILinker*)CreateInterface(CLANG_LINKER_INTERFACE_NAME, NULL);
CProject_t compileScriptProject = {};
compileScriptProject.m_szName = "build";
compileScriptProject.files = {"build.cpp"};
compileScriptProject.includeDirectories = {CUtlString("%s/public",IFileSystem2::OwnDirectory()),CUtlString("%s/public", IFileSystem2::BuildDirectory()), CUtlString("%s/../public",IFileSystem2::OwnDirectory()),CUtlString("%s/../public", IFileSystem2::BuildDirectory())};
compileScriptProject.includeDirectories = {CUtlString("%s/public",filesystem2->OwnDirectory()),CUtlString("%s/public", filesystem2->BuildDirectory()), CUtlString("%s/../public",filesystem2->OwnDirectory()),CUtlString("%s/../public", filesystem2->BuildDirectory())};
compileScriptProject.bFPIC = true;
compileScriptProject.m_target = Target_t::HostTarget();
CLDProject linkScriptProject = compileScriptProject.Compile();
LinkProject_t linkScriptProject = ccompiler->Compile(&compileScriptProject);
linkScriptProject.linkType = ELINK_DYNAMIC_LIBRARY;
linkScriptProject.m_target = Target_t::HostTarget();
CUtlString script = linkScriptProject.Link();
CUtlString script = linker->Link(&linkScriptProject);
void *scriptDLL = Plat_LoadLibrary(script);
auto PreinitFn = (void(*)())Plat_GetProc(scriptDLL, "Preinit");
V_printf("%p\n",PreinitFn);
if (PreinitFn)
PreinitFn();
@@ -38,7 +47,8 @@ int build()
build->m_pMainFn();
};
Plat_UnloadLibrary(scriptDLL);
CCProject::GenerateCompileCommands();
ccompiler->GenerateLinterData();
return 0;
};
@@ -80,8 +90,7 @@ findbuild:
} else {
V_fclose(file);
}
extern char *szBuildDir;
szBuildDir = szBuildcppDir;
g_szBuildDir = szBuildcppDir;
#ifdef __linux
signal(SIGHUP, IEngine_Signal);
@@ -95,8 +104,8 @@ findbuild:
signal(SIGSEGV, IEngine_Signal);
signal(SIGTERM, IEngine_Signal);
#endif
ICommandLine::CreateCommandLine(c, v);
if (ICommandLine::CheckParam("build"))
CommandLine()->CreateCommandLine(c, v);
if (CommandLine()->CheckParam("build"))
return build();
return 0;
};

39
fpc/public/apktool.h Normal file
View File

@@ -0,0 +1,39 @@
#ifndef APK_TOOL_H
#define APK_TOOL_H
#include "tier0/platform.h"
#include "tier1/utlstring.h"
struct AndroidManifest_t
{
public:
void SetPackageVersion( CUtlString szVersion );
void SetPackageBuild( uint64_t nBuild );
void SetPackageID( CUtlString szPackageID );
void SetPackageName( CUtlString szPackageName );
void SetTargetSDKVersion( uint64_t nTargetVersion );
void SetMinSDKVersion( uint64_t nMinVersion );
void AddUserFeature( CUtlString szName, bool bIsRequired, uint64_t nVersion );
void AddUserLibrary( CUtlString szPath );
CUtlString BuildManifest();
CUtlString m_szPackageName;
CUtlString m_szPackageID;
uint64_t m_nBuild;
CUtlString m_szVersion;
uint64_t m_nTargetVersion;
uint64_t m_nMinVersion;
};
abstract_class IAPKTool
{
public:
virtual CUtlString BuildPackage( AndroidManifest_t manifest, CUtlString szManifestDir ) = 0;
};
IAPKTool *APKTool();
#endif

View File

@@ -1,6 +1,7 @@
#ifndef C_H
#define C_H
#include "tier0/platform.h"
#include "tier1/utlstring.h"
#include "tier1/utlvector.h"
#include "runner.h"
@@ -35,20 +36,35 @@ enum ECPPVersion
CPPVERSION_2C = 6,
};
class CCProject : public CProject
struct CProject_t : public CPUProject_t
{
public:
CUtlVector<CUtlString> files = {};
CUtlVector<C_Macro_t> macros = {};
CUtlVector<CUtlString> includeDirectories = {};
CUtlVector<CUtlString> includeFiles = {};
CUtlVector<C_Macro_t> macros = {};
bool bFPIE = false;
bool bFPIC = false;
bool bDebug = m_target.optimization == TARGET_DEBUG;
ECVersion cVersion;
ECPPVersion cppVersion;
CLDProject Compile();
static void GenerateCompileCommands();
AndroidManifest_t m_androidmanifest;
};
#define C_COMPILER_INTERFACE_NAME "CCompiler001"
#define CLANG_C_COMPILER_INTERFACE_NAME "ClangCCompiler001"
#define GCC_C_COMPILER_INTERFACE_NAME "GCCCCompiler001"
#define MSVC_C_COMPILER_INTERFACE_NAME "MSVCCCompiler001"
abstract_class ICCompiler
{
public:
virtual LinkProject_t Compile( CProject_t *pProject ) = 0;
virtual void GenerateLinterData( void ) = 0;
};
extern ICCompiler *ccompiler;
#endif

View File

@@ -1,30 +1,62 @@
#ifndef HELPER_H
#define HELPER_H
#include "apktool.h"
#include "tier1/utlstring.h"
#include "target.h"
#define FPC_TEMPORAL_DIRNAME ".fpc"
class CProject
struct BaseProject_t
{
public:
Target_t m_target = Target_t::DefaultTarget();
CUtlString m_szName;
unsigned int GenerateProjectHash( void );
};
interface IFileSystem2
struct CPUProject_t : public BaseProject_t
{
public:
static char *OwnDirectory();
static char *BuildDirectory();
static void MakeDirectory( const char *psz );
static void CopyFile( const char *szDestination, const char *szOrigin );
static void CopyDirectory( const char *szDestination, const char *szOrigin );
static bool ShouldRecompile( const char *szSource, const char *szOutput );
Target_t m_target = Target_t::DefaultTarget();
};
struct ShaderProject_t : public BaseProject_t
{
public:
EShaderTarget m_eTarget;
};
//-----------------------------------------------------------------------------
// File system.
//-----------------------------------------------------------------------------
#define FILE_SYSTEM_2_INTERFACE_NAME "FileSystem2_001"
abstract_class IFileSystem2
{
public:
// Returns a directory of fpc executable
virtual char *OwnDirectory() = 0;
// Returns directory of build.cpp
virtual char *BuildDirectory() = 0;
virtual void MakeDirectory( const char *psz ) = 0;
virtual void CopyFile( const char *szDestination, const char *szOrigin ) = 0;
virtual void CopyDirectory( const char *szDestination, const char *szOrigin ) = 0;
virtual bool ShouldRecompile( const char *szSource, const char *szOutput ) = 0;
};
extern IFileSystem2 *filesystem2;
//-----------------------------------------------------------------------------
// Build stage.
//-----------------------------------------------------------------------------
class CBuildStage
{
public:
@@ -33,8 +65,10 @@ public:
int(*m_pMainFn)();
};
#define DECLARE_BUILD_STAGE(sz, fn) \
CBuildStage __##sz##_build_stage(#sz, fn);
#define DECLARE_BUILD_STAGE(sz) \
int __build_stage_##sz(); \
CBuildStage __##sz##_build_stage(#sz, __build_stage_##sz); \
int __build_stage_##sz()
CUtlVector<CBuildStage*>& BuildStages();

View File

@@ -5,6 +5,7 @@
#include "runner.h"
#include "helper.h"
#include "obj.h"
#include "tier0/platform.h"
#include "tier1/utlstring.h"
enum ELinkType
@@ -14,22 +15,32 @@ enum ELinkType
ELINK_STATIC_LIBRARY,
};
class CLDProject: public CProject
struct LinkProject_t: public CPUProject_t
{
public:
void AddObject( CObject& object );
void AddLibrary( CUtlString psz );
void AddLibraryByPath( CUtlString szPath );
void AddLibraryDirectory( CUtlString szPath );
CUtlString Link( void );
void AddObject( Object_t& object );
ELinkType linkType;
CUtlVector<CObject> objects = {};
CUtlVector<Object_t> objects = {};
CUtlVector<CUtlString> libraries ={};
CUtlVector<CUtlString> libraryDirectories = {};
CUtlVector<CUtlString> libraryObjects = {};
CUtlVector<CUtlString> frameworkDirectories = {};
CUtlVector<CUtlString> frameworks = {};
AndroidManifest_t m_androidmanifest;
bool bNoStdLib;
};
#define LINKER_INTERFACE_NAME "Linker001"
#define CLANG_LINKER_INTERFACE_NAME "ClangLinker001"
abstract_class ILinker
{
public:
virtual CUtlString Link( LinkProject_t *pProject ) = 0;
};
extern ILinker *linker;
#endif

View File

@@ -3,7 +3,7 @@
#include "tier1/utlstring.h"
class CObject
struct Object_t
{
public:
CUtlString m_szObjectFile;

View File

@@ -1,16 +1,21 @@
#ifndef RUNNER_H
#define RUNNER_H
#include "tier0/platform.h"
#include "tier1/utlvector.h"
#include "tier1/utlstring.h"
interface IRunner
#define RUNNER_INTERFACE_NAME "Runner001"
abstract_class IRunner
{
public:
static int Run( CUtlString szName, CUtlVector<CUtlString>& args );
static int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args );
static int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment );
static int Wait( void );
virtual int Run( CUtlString szName, CUtlVector<CUtlString>& args ) = 0;
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args ) = 0;
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment ) = 0;
virtual int Wait( void ) = 0;
};
extern IRunner *runner;
#endif

21
fpc/public/signtool.h Normal file
View File

@@ -0,0 +1,21 @@
#ifndef SIGN_TOOL_H
#define SIGN_TOOL_H
#include "tier0/platform.h"
#include "tier1/utlstring.h"
#define APPLE_SIGN_TOOL_INTERFACE_NAME "SignToolApple001"
#define ANDROID_SIGN_TOOL_INTERFACE_NAME "SignToolAndroid001"
abstract_class ISignTool
{
public:
virtual void SetSignPassword( CUtlString szPassword ) = 0;
virtual void SignFile( CUtlString szFile ) = 0;
virtual void SignDirectory( CUtlString szDirectory ) = 0;
};
extern ISignTool *signtool_android;
extern ISignTool *signtool_apple;
#endif

0
fpc/public/slang.h Normal file
View File

View File

@@ -2,20 +2,30 @@
#define TARGET_T
#include "tier1/utlstring.h"
#include "tier1/commandline.h"
enum ETargetKernel
{
TARGET_KERNEL_UNKNOWN,
TARGET_KERNEL_LINUX,
TARGET_KERNEL_WINDOWS,
TARGET_KERNEL_DARWIN,
TARGET_KERNEL_IOS,
TARGET_KERNEL_ANDROID,
TARGET_KERNEL_WASI,
TARGET_KERNEL_EMSCRIPTEN,
};
enum ETargetCPU
{
TARGET_CPU_AMD64,
TARGET_CPU_I286,
TARGET_CPU_I386,
TARGET_CPU_I486,
TARGET_CPU_I586,
TARGET_CPU_I686,
TARGET_CPU_AARCH64,
TARGET_CPU_WASM32,
};
enum ETargetOptimization
@@ -30,9 +40,21 @@ struct Target_t
ETargetKernel kernel;
ETargetCPU cpu;
ETargetOptimization optimization;
const char *szSysroot = CommandLine()->ParamValue("-sysroot");
CUtlString GetTriplet();
static Target_t HostTarget();
static Target_t DefaultTarget();
};
enum EShaderTarget
{
SHADER_TARGET_VULKAN_SPIRV,
SHADER_TARGET_OPENGL_SPIRV,
SHADER_TARGET_GLSL,
SHADER_TARGET_HLSL,
SHADER_TARGET_MSL,
};
#endif

0
fpc/public/windres.h Normal file
View File

View File

@@ -0,0 +1,443 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <jni.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/resource.h>
#include <stdlib.h>
#include "android_native_app_glue.h"
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "threaded_app", __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, "threaded_app", __VA_ARGS__))
/* For debug builds, always enable the debug traces in this library */
#ifndef NDEBUG
# define LOGV(...) ((void)__android_log_print(ANDROID_LOG_VERBOSE, "threaded_app", __VA_ARGS__))
#else
# define LOGV(...) ((void)0)
#endif
static void free_saved_state(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->savedState != NULL) {
free(android_app->savedState);
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
}
int8_t android_app_read_cmd(struct android_app* android_app) {
int8_t cmd;
if (read(android_app->msgread, &cmd, sizeof(cmd)) == sizeof(cmd)) {
switch (cmd) {
case APP_CMD_SAVE_STATE:
free_saved_state(android_app);
break;
}
return cmd;
} else {
LOGE("No data on command pipe!");
}
return -1;
}
static void print_cur_config(struct android_app* android_app) {
char lang[2], country[2];
AConfiguration_getLanguage(android_app->config, lang);
AConfiguration_getCountry(android_app->config, country);
LOGV("Config: mcc=%d mnc=%d lang=%c%c cnt=%c%c orien=%d touch=%d dens=%d "
"keys=%d nav=%d keysHid=%d navHid=%d sdk=%d size=%d long=%d "
"modetype=%d modenight=%d",
AConfiguration_getMcc(android_app->config),
AConfiguration_getMnc(android_app->config),
lang[0], lang[1], country[0], country[1],
AConfiguration_getOrientation(android_app->config),
AConfiguration_getTouchscreen(android_app->config),
AConfiguration_getDensity(android_app->config),
AConfiguration_getKeyboard(android_app->config),
AConfiguration_getNavigation(android_app->config),
AConfiguration_getKeysHidden(android_app->config),
AConfiguration_getNavHidden(android_app->config),
AConfiguration_getSdkVersion(android_app->config),
AConfiguration_getScreenSize(android_app->config),
AConfiguration_getScreenLong(android_app->config),
AConfiguration_getUiModeType(android_app->config),
AConfiguration_getUiModeNight(android_app->config));
}
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_INPUT_CHANGED:
LOGV("APP_CMD_INPUT_CHANGED\n");
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
android_app->inputQueue = android_app->pendingInputQueue;
if (android_app->inputQueue != NULL) {
LOGV("Attaching input queue to looper");
AInputQueue_attachLooper(android_app->inputQueue,
android_app->looper, LOOPER_ID_INPUT, NULL,
&android_app->inputPollSource);
}
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_INIT_WINDOW:
LOGV("APP_CMD_INIT_WINDOW\n");
pthread_mutex_lock(&android_app->mutex);
android_app->window = android_app->pendingWindow;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW\n");
pthread_cond_broadcast(&android_app->cond);
break;
case APP_CMD_RESUME:
case APP_CMD_START:
case APP_CMD_PAUSE:
case APP_CMD_STOP:
LOGV("activityState=%d\n", cmd);
pthread_mutex_lock(&android_app->mutex);
android_app->activityState = cmd;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_CONFIG_CHANGED:
LOGV("APP_CMD_CONFIG_CHANGED\n");
AConfiguration_fromAssetManager(android_app->config,
android_app->activity->assetManager);
print_cur_config(android_app);
break;
case APP_CMD_DESTROY:
LOGV("APP_CMD_DESTROY\n");
android_app->destroyRequested = 1;
break;
}
}
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd) {
switch (cmd) {
case APP_CMD_TERM_WINDOW:
LOGV("APP_CMD_TERM_WINDOW\n");
pthread_mutex_lock(&android_app->mutex);
android_app->window = NULL;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_SAVE_STATE:
LOGV("APP_CMD_SAVE_STATE\n");
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
break;
case APP_CMD_RESUME:
free_saved_state(android_app);
break;
}
}
void app_dummy() {
}
static void android_app_destroy(struct android_app* android_app) {
LOGV("android_app_destroy!");
free_saved_state(android_app);
pthread_mutex_lock(&android_app->mutex);
if (android_app->inputQueue != NULL) {
AInputQueue_detachLooper(android_app->inputQueue);
}
AConfiguration_delete(android_app->config);
android_app->destroyed = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
// Can't touch android_app object after this.
}
static void process_input(struct android_app* app, struct android_poll_source* source) {
AInputEvent* event = NULL;
if (AInputQueue_getEvent(app->inputQueue, &event) >= 0) {
LOGV("New input event: type=%d\n", AInputEvent_getType(event));
if (AInputQueue_preDispatchEvent(app->inputQueue, event)) {
return;
}
int32_t handled = 0;
if (app->onInputEvent != NULL) handled = app->onInputEvent(app, event);
AInputQueue_finishEvent(app->inputQueue, event, handled);
} else {
LOGE("Failure reading next input event: %s\n", strerror(errno));
}
}
static void process_cmd(struct android_app* app, struct android_poll_source* source) {
int8_t cmd = android_app_read_cmd(app);
android_app_pre_exec_cmd(app, cmd);
if (app->onAppCmd != NULL) app->onAppCmd(app, cmd);
android_app_post_exec_cmd(app, cmd);
}
static void* android_app_entry(void* param) {
struct android_app* android_app = (struct android_app*)param;
android_app->config = AConfiguration_new();
AConfiguration_fromAssetManager(android_app->config, android_app->activity->assetManager);
print_cur_config(android_app);
android_app->cmdPollSource.id = LOOPER_ID_MAIN;
android_app->cmdPollSource.app = android_app;
android_app->cmdPollSource.process = process_cmd;
android_app->inputPollSource.id = LOOPER_ID_INPUT;
android_app->inputPollSource.app = android_app;
android_app->inputPollSource.process = process_input;
ALooper* looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);
ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL,
&android_app->cmdPollSource);
android_app->looper = looper;
pthread_mutex_lock(&android_app->mutex);
android_app->running = 1;
pthread_cond_broadcast(&android_app->cond);
pthread_mutex_unlock(&android_app->mutex);
android_main(android_app);
android_app_destroy(android_app);
return NULL;
}
// --------------------------------------------------------------------
// Native activity interaction (called from main thread)
// --------------------------------------------------------------------
static struct android_app* android_app_create(ANativeActivity* activity,
void* savedState, size_t savedStateSize) {
struct android_app* android_app = (struct android_app*)malloc(sizeof(struct android_app));
memset(android_app, 0, sizeof(struct android_app));
android_app->activity = activity;
pthread_mutex_init(&android_app->mutex, NULL);
pthread_cond_init(&android_app->cond, NULL);
if (savedState != NULL) {
android_app->savedState = malloc(savedStateSize);
android_app->savedStateSize = savedStateSize;
memcpy(android_app->savedState, savedState, savedStateSize);
}
int msgpipe[2];
if (pipe(msgpipe)) {
LOGE("could not create pipe: %s", strerror(errno));
return NULL;
}
android_app->msgread = msgpipe[0];
android_app->msgwrite = msgpipe[1];
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
// Wait for thread to start.
pthread_mutex_lock(&android_app->mutex);
while (!android_app->running) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
return android_app;
}
static void android_app_write_cmd(struct android_app* android_app, int8_t cmd) {
if (write(android_app->msgwrite, &cmd, sizeof(cmd)) != sizeof(cmd)) {
LOGE("Failure writing android_app cmd: %s\n", strerror(errno));
}
}
static void android_app_set_input(struct android_app* android_app, AInputQueue* inputQueue) {
pthread_mutex_lock(&android_app->mutex);
android_app->pendingInputQueue = inputQueue;
android_app_write_cmd(android_app, APP_CMD_INPUT_CHANGED);
while (android_app->inputQueue != android_app->pendingInputQueue) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
static void android_app_set_window(struct android_app* android_app, ANativeWindow* window) {
pthread_mutex_lock(&android_app->mutex);
if (android_app->pendingWindow != NULL) {
android_app_write_cmd(android_app, APP_CMD_TERM_WINDOW);
}
android_app->pendingWindow = window;
if (window != NULL) {
android_app_write_cmd(android_app, APP_CMD_INIT_WINDOW);
}
while (android_app->window != android_app->pendingWindow) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
static void android_app_set_activity_state(struct android_app* android_app, int8_t cmd) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, cmd);
while (android_app->activityState != cmd) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
}
static void android_app_free(struct android_app* android_app) {
pthread_mutex_lock(&android_app->mutex);
android_app_write_cmd(android_app, APP_CMD_DESTROY);
while (!android_app->destroyed) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
pthread_mutex_unlock(&android_app->mutex);
close(android_app->msgread);
close(android_app->msgwrite);
pthread_cond_destroy(&android_app->cond);
pthread_mutex_destroy(&android_app->mutex);
free(android_app);
}
static void onDestroy(ANativeActivity* activity) {
LOGV("Destroy: %p\n", activity);
android_app_free((struct android_app*)activity->instance);
}
static void onStart(ANativeActivity* activity) {
LOGV("Start: %p\n", activity);
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_START);
}
static void onResume(ANativeActivity* activity) {
LOGV("Resume: %p\n", activity);
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_RESUME);
}
static void* onSaveInstanceState(ANativeActivity* activity, size_t* outLen) {
struct android_app* android_app = (struct android_app*)activity->instance;
void* savedState = NULL;
LOGV("SaveInstanceState: %p\n", activity);
pthread_mutex_lock(&android_app->mutex);
android_app->stateSaved = 0;
android_app_write_cmd(android_app, APP_CMD_SAVE_STATE);
while (!android_app->stateSaved) {
pthread_cond_wait(&android_app->cond, &android_app->mutex);
}
if (android_app->savedState != NULL) {
savedState = android_app->savedState;
*outLen = android_app->savedStateSize;
android_app->savedState = NULL;
android_app->savedStateSize = 0;
}
pthread_mutex_unlock(&android_app->mutex);
return savedState;
}
static void onPause(ANativeActivity* activity) {
LOGV("Pause: %p\n", activity);
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_PAUSE);
}
static void onStop(ANativeActivity* activity) {
LOGV("Stop: %p\n", activity);
android_app_set_activity_state((struct android_app*)activity->instance, APP_CMD_STOP);
}
static void onConfigurationChanged(ANativeActivity* activity) {
struct android_app* android_app = (struct android_app*)activity->instance;
LOGV("ConfigurationChanged: %p\n", activity);
android_app_write_cmd(android_app, APP_CMD_CONFIG_CHANGED);
}
static void onLowMemory(ANativeActivity* activity) {
struct android_app* android_app = (struct android_app*)activity->instance;
LOGV("LowMemory: %p\n", activity);
android_app_write_cmd(android_app, APP_CMD_LOW_MEMORY);
}
static void onWindowFocusChanged(ANativeActivity* activity, int focused) {
LOGV("WindowFocusChanged: %p -- %d\n", activity, focused);
android_app_write_cmd((struct android_app*)activity->instance,
focused ? APP_CMD_GAINED_FOCUS : APP_CMD_LOST_FOCUS);
}
static void onNativeWindowCreated(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowCreated: %p -- %p\n", activity, window);
android_app_set_window((struct android_app*)activity->instance, window);
}
static void onNativeWindowDestroyed(ANativeActivity* activity, ANativeWindow* window) {
LOGV("NativeWindowDestroyed: %p -- %p\n", activity, window);
android_app_set_window((struct android_app*)activity->instance, NULL);
}
static void onInputQueueCreated(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueCreated: %p -- %p\n", activity, queue);
android_app_set_input((struct android_app*)activity->instance, queue);
}
static void onInputQueueDestroyed(ANativeActivity* activity, AInputQueue* queue) {
LOGV("InputQueueDestroyed: %p -- %p\n", activity, queue);
android_app_set_input((struct android_app*)activity->instance, NULL);
}
void ANativeActivity_onCreate(ANativeActivity* activity,
void* savedState, size_t savedStateSize) {
LOGV("Creating: %p\n", activity);
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onStart = onStart;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onPause = onPause;
activity->callbacks->onStop = onStop;
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onLowMemory = onLowMemory;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->instance = android_app_create(activity, savedState, savedStateSize);
}

View File

@@ -0,0 +1,349 @@
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#ifndef _ANDROID_NATIVE_APP_GLUE_H
#define _ANDROID_NATIVE_APP_GLUE_H
#include <poll.h>
#include <pthread.h>
#include <sched.h>
#include <android/configuration.h>
#include <android/looper.h>
#include <android/native_activity.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* The native activity interface provided by <android/native_activity.h>
* is based on a set of application-provided callbacks that will be called
* by the Activity's main thread when certain events occur.
*
* This means that each one of this callbacks _should_ _not_ block, or they
* risk having the system force-close the application. This programming
* model is direct, lightweight, but constraining.
*
* The 'threaded_native_app' static library is used to provide a different
* execution model where the application can implement its own main event
* loop in a different thread instead. Here's how it works:
*
* 1/ The application must provide a function named "android_main()" that
* will be called when the activity is created, in a new thread that is
* distinct from the activity's main thread.
*
* 2/ android_main() receives a pointer to a valid "android_app" structure
* that contains references to other important objects, e.g. the
* ANativeActivity obejct instance the application is running in.
*
* 3/ the "android_app" object holds an ALooper instance that already
* listens to two important things:
*
* - activity lifecycle events (e.g. "pause", "resume"). See APP_CMD_XXX
* declarations below.
*
* - input events coming from the AInputQueue attached to the activity.
*
* Each of these correspond to an ALooper identifier returned by
* ALooper_pollOnce with values of LOOPER_ID_MAIN and LOOPER_ID_INPUT,
* respectively.
*
* Your application can use the same ALooper to listen to additional
* file-descriptors. They can either be callback based, or with return
* identifiers starting with LOOPER_ID_USER.
*
* 4/ Whenever you receive a LOOPER_ID_MAIN or LOOPER_ID_INPUT event,
* the returned data will point to an android_poll_source structure. You
* can call the process() function on it, and fill in android_app->onAppCmd
* and android_app->onInputEvent to be called for your own processing
* of the event.
*
* Alternatively, you can call the low-level functions to read and process
* the data directly... look at the process_cmd() and process_input()
* implementations in the glue to see how to do this.
*
* See the sample named "native-activity" that comes with the NDK with a
* full usage example. Also look at the JavaDoc of NativeActivity.
*/
struct android_app;
/**
* Data associated with an ALooper fd that will be returned as the "outData"
* when that source has data ready.
*/
struct android_poll_source {
// The identifier of this source. May be LOOPER_ID_MAIN or
// LOOPER_ID_INPUT.
int32_t id;
// The android_app this ident is associated with.
struct android_app* app;
// Function to call to perform the standard processing of data from
// this source.
void (*process)(struct android_app* app, struct android_poll_source* source);
};
/**
* This is the interface for the standard glue code of a threaded
* application. In this model, the application's code is running
* in its own thread separate from the main thread of the process.
* It is not required that this thread be associated with the Java
* VM, although it will need to be in order to make JNI calls any
* Java objects.
*/
struct android_app {
// The application can place a pointer to its own state object
// here if it likes.
void* userData;
// Fill this in with the function to process main app commands (APP_CMD_*)
void (*onAppCmd)(struct android_app* app, int32_t cmd);
// Fill this in with the function to process input events. At this point
// the event has already been pre-dispatched, and it will be finished upon
// return. Return 1 if you have handled the event, 0 for any default
// dispatching.
int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event);
// The ANativeActivity object instance that this app is running in.
ANativeActivity* activity;
// The current configuration the app is running in.
AConfiguration* config;
// This is the last instance's saved state, as provided at creation time.
// It is NULL if there was no state. You can use this as you need; the
// memory will remain around until you call android_app_exec_cmd() for
// APP_CMD_RESUME, at which point it will be freed and savedState set to NULL.
// These variables should only be changed when processing a APP_CMD_SAVE_STATE,
// at which point they will be initialized to NULL and you can malloc your
// state and place the information here. In that case the memory will be
// freed for you later.
void* savedState;
size_t savedStateSize;
// The ALooper associated with the app's thread.
ALooper* looper;
// When non-NULL, this is the input queue from which the app will
// receive user input events.
AInputQueue* inputQueue;
// When non-NULL, this is the window surface that the app can draw in.
ANativeWindow* window;
// Current content rectangle of the window; this is the area where the
// window's content should be placed to be seen by the user.
ARect contentRect;
// Current state of the app's activity. May be either APP_CMD_START,
// APP_CMD_RESUME, APP_CMD_PAUSE, or APP_CMD_STOP; see below.
int activityState;
// This is non-zero when the application's NativeActivity is being
// destroyed and waiting for the app thread to complete.
int destroyRequested;
// -------------------------------------------------
// Below are "private" implementation of the glue code.
pthread_mutex_t mutex;
pthread_cond_t cond;
int msgread;
int msgwrite;
pthread_t thread;
struct android_poll_source cmdPollSource;
struct android_poll_source inputPollSource;
int running;
int stateSaved;
int destroyed;
int redrawNeeded;
AInputQueue* pendingInputQueue;
ANativeWindow* pendingWindow;
ARect pendingContentRect;
};
enum {
/**
* Looper data ID of commands coming from the app's main thread, which
* is returned as an identifier from ALooper_pollOnce(). The data for this
* identifier is a pointer to an android_poll_source structure.
* These can be retrieved and processed with android_app_read_cmd()
* and android_app_exec_cmd().
*/
LOOPER_ID_MAIN = 1,
/**
* Looper data ID of events coming from the AInputQueue of the
* application's window, which is returned as an identifier from
* ALooper_pollOnce(). The data for this identifier is a pointer to an
* android_poll_source structure. These can be read via the inputQueue
* object of android_app.
*/
LOOPER_ID_INPUT = 2,
/**
* Start of user-defined ALooper identifiers.
*/
LOOPER_ID_USER = 3,
};
enum {
/**
* Command from main thread: the AInputQueue has changed. Upon processing
* this command, android_app->inputQueue will be updated to the new queue
* (or NULL).
*/
APP_CMD_INPUT_CHANGED,
/**
* Command from main thread: a new ANativeWindow is ready for use. Upon
* receiving this command, android_app->window will contain the new window
* surface.
*/
APP_CMD_INIT_WINDOW,
/**
* Command from main thread: the existing ANativeWindow needs to be
* terminated. Upon receiving this command, android_app->window still
* contains the existing window; after calling android_app_exec_cmd
* it will be set to NULL.
*/
APP_CMD_TERM_WINDOW,
/**
* Command from main thread: the current ANativeWindow has been resized.
* Please redraw with its new size.
*/
APP_CMD_WINDOW_RESIZED,
/**
* Command from main thread: the system needs that the current ANativeWindow
* be redrawn. You should redraw the window before handing this to
* android_app_exec_cmd() in order to avoid transient drawing glitches.
*/
APP_CMD_WINDOW_REDRAW_NEEDED,
/**
* Command from main thread: the content area of the window has changed,
* such as from the soft input window being shown or hidden. You can
* find the new content rect in android_app::contentRect.
*/
APP_CMD_CONTENT_RECT_CHANGED,
/**
* Command from main thread: the app's activity window has gained
* input focus.
*/
APP_CMD_GAINED_FOCUS,
/**
* Command from main thread: the app's activity window has lost
* input focus.
*/
APP_CMD_LOST_FOCUS,
/**
* Command from main thread: the current device configuration has changed.
*/
APP_CMD_CONFIG_CHANGED,
/**
* Command from main thread: the system is running low on memory.
* Try to reduce your memory use.
*/
APP_CMD_LOW_MEMORY,
/**
* Command from main thread: the app's activity has been started.
*/
APP_CMD_START,
/**
* Command from main thread: the app's activity has been resumed.
*/
APP_CMD_RESUME,
/**
* Command from main thread: the app should generate a new saved state
* for itself, to restore from later if needed. If you have saved state,
* allocate it with malloc and place it in android_app.savedState with
* the size in android_app.savedStateSize. The will be freed for you
* later.
*/
APP_CMD_SAVE_STATE,
/**
* Command from main thread: the app's activity has been paused.
*/
APP_CMD_PAUSE,
/**
* Command from main thread: the app's activity has been stopped.
*/
APP_CMD_STOP,
/**
* Command from main thread: the app's activity is being destroyed,
* and waiting for the app thread to clean up and exit before proceeding.
*/
APP_CMD_DESTROY,
};
/**
* Call when ALooper_pollAll() returns LOOPER_ID_MAIN, reading the next
* app command message.
*/
int8_t android_app_read_cmd(struct android_app* android_app);
/**
* Call with the command returned by android_app_read_cmd() to do the
* initial pre-processing of the given command. You can perform your own
* actions for the command after calling this function.
*/
void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Call with the command returned by android_app_read_cmd() to do the
* final post-processing of the given command. You must have done your own
* actions for the command before calling this function.
*/
void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd);
/**
* Dummy function you can call to ensure glue code isn't stripped.
*/
void app_dummy();
/**
* This is the function that application code must implement, representing
* the main entry to the app.
*/
extern void android_main(struct android_app* app);
#ifdef __cplusplus
}
#endif
#endif /* _ANDROID_NATIVE_APP_GLUE_H */

View File

@@ -0,0 +1,35 @@
#include "helper.h"
#include "c.h"
#include "ld.h"
#include "tier1/utlstring.h"
DECLARE_BUILD_STAGE(android_build)
{
AndroidManifest_t manifest = {};
manifest.SetMinSDKVersion(21);
manifest.SetTargetSDKVersion(35);
manifest.SetPackageName("FPC Testing facility");
manifest.SetPackageID("com.example.testfpc");
CUtlString szManifestDir = manifest.BuildManifest();
CProject_t compileProject = {};
compileProject.m_szName = "android_app";
compileProject.m_androidmanifest = manifest;
compileProject.bFPIC = true;
compileProject.files = {
"main.c",
};
LinkProject_t ldProject = ccompiler->Compile(&compileProject);
ldProject.libraries = {
"android",
"log",
};
CUtlString szOutputDir = linker->Link(&ldProject);
filesystem2->MakeDirectory(CUtlString("%s/lib/x86_64",szManifestDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/lib/x86_64/libnative-app.so",szManifestDir.GetString()), szOutputDir);
APKTool()->BuildPackage(manifest, szManifestDir);
return 0;
}

Binary file not shown.

View File

@@ -0,0 +1,42 @@
#include "android_native_app_glue.h"
#include <android/log.h>
#define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "NativeApp", __VA_ARGS__))
// Handle lifecycle events
static void handle_cmd(struct android_app* app, int32_t cmd) {
switch (cmd) {
case APP_CMD_INIT_WINDOW:
LOGI("Window created");
// You could init OpenGL/Vulkan here
break;
case APP_CMD_TERM_WINDOW:
LOGI("Window destroyed");
break;
}
}
// Entry point for native app
void android_main(struct android_app* app) {
app->onAppCmd = handle_cmd;
LOGI("Native app started");
int events;
struct android_poll_source* source;
// Main event loop
while (1) {
int ident;
while ((ident = ALooper_pollOnce(0, NULL, &events, (void**)&source)) >= 0) {
if (source) source->process(app, source);
if (app->destroyRequested) {
LOGI("App destroy requested");
return;
}
}
// Here you can update your game/render loop
}
}

View File

View File

@@ -8,8 +8,8 @@
void build_shader( const char *szName )
{
IFileSystem2::MakeDirectory(CUtlString("build/funnygame/metal/gfx"));
IFileSystem2::MakeDirectory(CUtlString("build/funnygame/vulkan/gfx"));
filesystem2->MakeDirectory(CUtlString("build/funnygame/metal/gfx"));
filesystem2->MakeDirectory(CUtlString("build/funnygame/vulkan/gfx"));
CUtlVector<CUtlString> slang_args = {
CUtlString("funnyassets/gfx_shaders/%s.slang", szName),
@@ -22,23 +22,25 @@ void build_shader( const char *szName )
CUtlString("build/funnygame/vulkan/gfx/%s.shader", szName),
};
IRunner::Run("slangc", slang_args);
runner->Run("slangc", slang_args);
slang_args[3] = "metal";
slang_args[5] = "__METAL__=1";
slang_args[7] = CUtlString("build/funnygame/metal/gfx/%s.shader", szName);
IRunner::Run("slangc", slang_args);
IRunner::Wait();
runner->Run("slangc", slang_args);
runner->Wait();
};
int assets_build()
DECLARE_BUILD_STAGE(assets)
{
IFileSystem2::CopyDirectory("build", "tools");
if (CommandLine()->CheckParam("-noassets"))
return 0;
filesystem2->CopyDirectory("build", "tools");
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/maps");
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/gfx");
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts");
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures");
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/maps");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/gfx");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures");
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials");
build_shader("mesh_frag");
build_shader("mesh_vert");
build_shader("fgui_rect_frag");
@@ -50,7 +52,7 @@ int assets_build()
CUtlString("build/funnygame/assets"),
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "rtt") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "rtt"),
};
IRunner::Run("python3", python_args);
runner->Run("python3", python_args);
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS ||Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
{
python_args = {
@@ -58,21 +60,20 @@ int assets_build()
CUtlString("build/funnygame/metal"),
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "metal") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "metal"),
};
IRunner::Run("python3", python_args);
runner->Run("python3", python_args);
} else {
python_args = {
"build/tools/makepak64.py",
CUtlString("build/funnygame/vulkan"),
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "vulkan") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "vulkan"),
};
IRunner::Run("python3", python_args);
runner->Run("python3", python_args);
}
IRunner::Wait();
runner->Wait();
if (bStaticBuild)
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "funnyassets/default.cfg");
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "funnyassets/default.cfg");
else
IFileSystem2::CopyFile(szOutputDir.GetString(), "funnyassets/default.cfg");
filesystem2->CopyFile(szOutputDir.GetString(), "funnyassets/default.cfg");
return 0;
};
DECLARE_BUILD_STAGE(assets, assets_build);

View File

@@ -0,0 +1,16 @@
#include "mesh_raytracer_shared.slang"
[shader("raygeneration")]
void _main()
{
uint2 launchIndex = DispatchRaysIndex().xy;
uint8_t edgemask = inputMask.Load(uint3(launchIndex, 0));
uint8_t edgemask1 = inputMask.Load(uint3(launchIndex, 1));
uint8_t edgemask2 = inputMask.Load(uint3(launchIndex, 2));
uint8_t edgemask3 = inputMask.Load(uint3(launchIndex, 3));
uint8_t nBits = (countbits(edgemask) + countbits(edgemask1) + countbits(edgemask2) + countbits(edgemask3));
if ( nBits != 16 && nBits != 0 )
outputTest[launchIndex] = float4(1,0,0,0);
}

View File

@@ -0,0 +1,18 @@
struct RayPayload
{
bool bHit;
float fDistance;
};
#include "shader_base.slang"
DECLARE_CBUFFER(0)
{
float4x4 projection;
}
DECLARE_DATA(1, Texture2DMS<float> inputDepth;);
DECLARE_DATA(2, Texture2DMS<uint8_t> inputMask;);
DECLARE_DATA(3, RWTexture2D<float4> outputTest;);
DECLARE_TEXTURES(29)

View File

@@ -0,0 +1,25 @@
#ifndef SHADER_BASE_SLANG
#define SHADER_BASE_SLANG
/*
* I hope you are not looking at these war crimes.
* They are truly horrible crimes.
* Don't even try to understand what the fuck is happening here.
*/
#define DECLARE_TEXTURES(n) \
[[vk::binding(n)]] \
Sampler2D g_textures[]; \
float4 SampleTexture(uint32_t binding, float2 uv) { return g_textures[binding].Sample(uv); };
#define DECLARE_CBUFFER(b) [[vk::binding(b)]] cbuffer cbuffer_##b
#define DECLARE_DATA(b, r) [[vk::binding(b)]] r
#define DECLARE_CONSTANTS [[vk::push_constant]] cbuffer cbuffer_constants
#define FIX_VERTEX_POSITION(x)
#endif

View File

@@ -5,35 +5,32 @@
#include "tier1/commandline.h"
CUtlVector<CUtlString> client_CompiledFiles = {
"game/client/milmoba/player.cpp",
"game/client/milmoba/mainmenu.cpp",
};
int client_build()
DECLARE_BUILD_STAGE(client)
{
CCProject compileProject = {};
CLDProject ldProject = {};
CProject_t compileProject = {};
LinkProject_t ldProject = {};
compileProject.m_szName = "client";
compileProject.files = client_CompiledFiles;
compileProject.includeDirectories = all_IncludeDirectories;
compileProject.bFPIC = true;
ldProject = compileProject.Compile();
ldProject = ccompiler->Compile(&compileProject);
if (bStaticBuild)
ldProject.linkType = ELINK_STATIC_LIBRARY;
else
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
CUtlString outputProject = ldProject.Link();
CUtlString outputProject = linker->Link(&ldProject);
if (!bStaticBuild)
{
IFileSystem2::MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
IFileSystem2::CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
filesystem2->MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
} else {
client_lib = outputProject;
}
return 0;
};
DECLARE_BUILD_STAGE(client, client_build);

View File

@@ -2,7 +2,7 @@
#include "fgui/label.h"
#include "fgui/rect.h"
#include "fgui/widget.h"
#include "interface.h"
#include "tier1/interface.h"
class CMOBAMainMenuGUI: public CFGUI_Widget
{

View File

@@ -9,31 +9,30 @@ CUtlVector<CUtlString> server_CompiledFiles = {
"game/server/milmoba/player.cpp",
};
int server_build()
DECLARE_BUILD_STAGE(server)
{
CCProject compileProject = {};
CLDProject ldProject = {};
CProject_t compileProject = {};
LinkProject_t ldProject = {};
compileProject.m_szName = "server";
compileProject.files = server_CompiledFiles;
compileProject.includeDirectories = all_IncludeDirectories;
compileProject.bFPIC = true;
ldProject = compileProject.Compile();
ldProject = ccompiler->Compile(&compileProject);
if (bStaticBuild)
ldProject.linkType = ELINK_STATIC_LIBRARY;
else
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
CUtlString outputProject = ldProject.Link();
CUtlString outputProject = linker->Link(&ldProject);
if (!bStaticBuild)
{
IFileSystem2::MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
IFileSystem2::CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
filesystem2->MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
filesystem2->CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
} else {
server_lib = outputProject;
}
return 0;
};
DECLARE_BUILD_STAGE(server, server_build);

View File

@@ -1,21 +1 @@
#include "console.h"
#include "gamemode.h"
#include "tier0/platform.h"
#include "engine.h"
#include "level.h"
#include "stdio.h"
#include "tier0/lib.h"
class CTestGameMode: public CGameMode
{
};
DECLARE_GAME_MODE(CTestGameMode, test_gamemode)
DLL_EXPORT void IGame_Load()
{
LevelManager()->LoadLevel("maps/test_map");
GameModeManager()->StartGameMode("test_gamemode");
return;
};

View File

@@ -1,254 +1 @@
#include "baseentity.h"
#include "baseplayer.h"
#include "cglm/io.h"
#include "cglm/vec2.h"
#include "cglm/vec3.h"
#include "console.h"
#include "engine.h"
#include "input.h"
#include "math3d.h"
#include "networking.h"
#include "physics.h"
#include "physics_gen.h"
#define STEP_SIZE 0.3f
#define PLAYER_WIDTH 0.5f
#define PLAYER_HEIGHT 1.8f
#define EPSILON 0.0005f
class CMOBAPlayer: public CBasePlayer
{
public:
virtual void Precache() override;
virtual void Spawn( void ) override;
virtual void Destroy( void ) override;
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Think( float fDelta ) override;
virtual void SendToServer() override;
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
void Accelerate( void );
void AirAccelerate( void );
int ClipVelocity( vec3 in, vec3 normal, vec3 &out, float fOverbounce );
void FlyMove( void );
void GroundMove( void );
void AirMove( void );
void CategorizePosition( void );
void Friction( void );
void PlayerMove( void );
bool bIsForward = 0;
bool bIsBack = 0;
bool bIsLeft = 0;
bool bIsRight = 0;
bool bIsJumping = 0;
bool bIsCrouching = 0;
bool bIsProning = 0;
bool bIsFiring = 0;
bool bIsFiring2 = 0;
float fStamina;
float m_fDelta = 0;
float fPitch = 0;
float fYaw = 0;
enum {
PLAYER_GROUNDED,
PLAYER_FLYING,
} m_playerState;
vec3 m_velocity = {0,0,0};
vec3 m_prevVelocity = {0,0,0};
vec2 forward = {};
vec2 right = {};
CPxBoxMesh mesh;
CPxRigidKinematicPosition rigidbody;
};
void CMOBAPlayer::Precache()
{
}
void CMOBAPlayer::Spawn()
{
};
void CMOBAPlayer::ReadParameter( const char *szName, const char *szValue )
{
CBaseEntity::ReadParameter(szName, szValue);
}
void CMOBAPlayer::Destroy()
{
}
void CMOBAPlayer::AirAccelerate( void )
{
m_velocity[2] -= 9.8 * m_fDelta;
}
void CMOBAPlayer::Accelerate( void )
{
vec2 wishdir = {(float)bIsForward-bIsBack, (float)bIsLeft-bIsRight};
vec3 velocityDifference;
vec3 acceleration;
glm_vec2_rotate(wishdir, fYaw, wishdir);
glm_vec2_normalize(wishdir);
for ( int i = 0; i < 2; i++ )
m_velocity[i] += (wishdir[i]*6 - m_velocity[i]) * m_fDelta/0.25;
}
void CMOBAPlayer::Friction( void )
{
};
void CMOBAPlayer::FlyMove( void )
{
}
void CMOBAPlayer::GroundMove( void )
{
m_velocity[2] = 0;
Accelerate();
}
void CMOBAPlayer::CategorizePosition( void )
{
px_vec3 p;
px_cast_result r;
p.m[0] = m_position[0];
p.m[1] = m_position[1];
p.m[2] = m_position[2];
r = px_box_cast(px, PLAYER_WIDTH/2, PLAYER_WIDTH/2, PLAYER_HEIGHT/2, p, (px_vec3){}, (px_vec3){0,0,-0.01}, 1);
if (r.hit)
{
m_playerState = PLAYER_GROUNDED;
} else {
m_playerState = PLAYER_FLYING;
}
}
void CMOBAPlayer::PlayerMove( void )
{
CategorizePosition();
GroundMove();
vec3 velocity;
for ( int i = 0; i < 3; i++ )
velocity[i] = (m_prevVelocity[i] + m_velocity[i]) * 0.5;
for ( int i = 0; i < 3; i++ )
m_position[i] += velocity[i] * m_fDelta;
for ( int i = 0; i < 3; i++ )
m_prevVelocity[i] = m_velocity[i];
CategorizePosition();
}
struct PlayerMovement_t: public PacketPlayer_t
{
bool bIsForward;
bool bIsBack;
bool bIsLeft;
bool bIsRight;
float fPitch;
float fYaw;
};
void CMOBAPlayer::Think( float fDelta )
{
if (INetworking::IsClient())
{
if (g_localClient->pBasePlayer == this) {
float x = g_fAxisValues[AXIS_MOUSE_X];
float y = g_fAxisValues[AXIS_MOUSE_Y];
fPitch = glm_rad(x);
fYaw = glm_rad(y);
}
}
m_fDelta = fDelta;
PlayerMove();
};
void CMOBAPlayer::SendToServer()
{
PlayerMovement_t movement = {
.bIsForward = bIsForward,
.bIsBack = bIsBack,
.bIsLeft = bIsLeft,
.bIsRight = bIsRight,
.fPitch = fPitch,
.fYaw = fYaw,
};
movement.type = PACKET_TYPE_PLAYER_MOVEMENT;
if (INetworking::IsClient())
{
if (g_localClient->pBasePlayer != this)
return;
INetworking::SendData(&movement, sizeof(PlayerMovement_t), 0, MESSAGE_MODE_RELIABLE);
} else {
for (auto &client: g_clients)
{
if (client->pBasePlayer == this)
{
movement.playerHandle = client->playerHandle;
break;
}
}
INetworking::SendDataEverybodyExcept(&movement, sizeof(PlayerMovement_t), this, MESSAGE_MODE_RELIABLE);
}
return;
}
void CMOBAPlayer::RecieveFromServer( void *pData, uint32_t nDataSize )
{
Packet_t *pPacket = (Packet_t*)pData;
if (pPacket->type == PACKET_TYPE_PLAYER_MOVEMENT)
{
if (nDataSize != sizeof(PlayerMovement_t))
return;
PlayerMovement_t *pMovement = (PlayerMovement_t*)pPacket;
bIsForward = pMovement->bIsForward;
bIsBack = pMovement->bIsBack;
bIsLeft = pMovement->bIsLeft;
bIsRight = pMovement->bIsRight;
fPitch = pMovement->fPitch;
fYaw = pMovement->fYaw;
};
};
void PlayerForward(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsForward = true;};
void PlayerForwardUp(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsForward = false;};
void PlayerBack(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsBack = true;};
void PlayerBackUp(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsBack = false;};
void PlayerLeft(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsLeft = true;};
void PlayerLeftUp(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsLeft = false;};
void PlayerRight(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsRight = true;};
void PlayerRightUp(int argc, char **argv) {if (g_localClient->pBasePlayer) ((CMOBAPlayer*)g_localClient->pBasePlayer)->bIsRight = false;};
ConCommand moveForwardCmd("+forward", PlayerForward, 0);
ConCommand moveForwardUpCmd("-forward", PlayerForwardUp, 0);
ConCommand moveBackwardCmd("+back", PlayerBack, 0);
ConCommand moveBackwardUpCmd("-back", PlayerBackUp, 0);
ConCommand moveLeftCmd("+left", PlayerLeft, 0);
ConCommand moveLeftUpCmd("-left", PlayerLeftUp, 0);
ConCommand moveRightCmd("+right", PlayerRight, 0);
ConCommand moveRightUpCmd("-right", PlayerRightUp, 0);
DECLARE_ENTITY(player, CMOBAPlayer);

View File

@@ -7,11 +7,11 @@ CUtlVector<CUtlString> launcher_CompiledFiles = {
"launcher/launcher.cpp",
};
int launcher_build()
DECLARE_BUILD_STAGE(launcher)
{
IFileSystem2::MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
CCProject compileProject = {};
CLDProject ldProject = {};
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
CProject_t compileProject = {};
LinkProject_t ldProject = {};
compileProject.m_szName = "launcher";
compileProject.files = launcher_CompiledFiles;
@@ -21,19 +21,18 @@ int launcher_build()
{
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
}
ldProject = compileProject.Compile();
ldProject = ccompiler->Compile(&compileProject);
ldProject.linkType = ELINK_EXECUTABLE;
CUtlString szBinaryOutput = CUtlString("%s/bin/funnygame", szOutputDir.GetString());
if (bStaticBuild)
{
ldProject.objects.AppendTail((CObject){tier0_lib});
ldProject.objects.AppendTail((CObject){tier1_lib});
ldProject.objects.AppendTail((CObject){rapier_lib});
ldProject.objects.AppendTail((CObject){engine_lib});
ldProject.objects.AppendTail((CObject){server_lib});
ldProject.objects.AppendTail((CObject){fgui_lib});
ldProject.objects.AppendTail((CObject){client_lib});
ldProject.objects.AppendTail((Object_t){tier0_lib});
ldProject.objects.AppendTail((Object_t){tier1_lib});
ldProject.objects.AppendTail((Object_t){rapier_lib});
ldProject.objects.AppendTail((Object_t){engine_lib});
ldProject.objects.AppendTail((Object_t){server_lib});
ldProject.objects.AppendTail((Object_t){client_lib});
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS)
{
ldProject.frameworks.AppendTail("SDL3");
@@ -45,16 +44,16 @@ int launcher_build()
ldProject.frameworks.AppendTail("QuartzCore");
ldProject.frameworks.AppendTail("UIKit");
ldProject.frameworkDirectories.AppendTail("external/ios");
IFileSystem2::CopyDirectory(CUtlString("%s/bin", szOutputDir.GetString()), "external/ios/SDL3.framework");
filesystem2->CopyDirectory(CUtlString("%s/bin", szOutputDir.GetString()), "external/ios/SDL3.framework");
};
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_WINDOWS)
{
ldProject.objects.AppendTail((CObject){"external/windows/vulkan-1.dll"});
ldProject.objects.AppendTail((CObject){"external/windows/libSDL3.a"});
ldProject.objects.AppendTail((CObject){"external/windows/libpthread.a"});
ldProject.objects.AppendTail((CObject){"external/windows/libstdc++.a"});
ldProject.objects.AppendTail((Object_t){"external/windows/vulkan-1.dll"});
ldProject.objects.AppendTail((Object_t){"external/windows/libSDL3.a"});
ldProject.objects.AppendTail((Object_t){"external/windows/libpthread.a"});
ldProject.objects.AppendTail((Object_t){"external/windows/libstdc++.a"});
if (bSteam)
ldProject.objects.AppendTail((CObject){"external/steamworks/redistributable_bin/win64/steam_api64.dll"});
ldProject.objects.AppendTail((Object_t){"external/steamworks/redistributable_bin/win64/steam_api64.dll"});
ldProject.libraries.AppendTail("ws2_32");
ldProject.libraries.AppendTail("ntdll");
ldProject.libraries.AppendTail("userenv");
@@ -67,15 +66,14 @@ int launcher_build()
ldProject.libraries.AppendTail("imm32");
ldProject.libraries.AppendTail("version");
ldProject.libraries.AppendTail("oleaut32");
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "external/windows/libgcc_s_seh-1.dll");
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "external/windows/libwinpthread-1.dll");
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "external/windows/libgcc_s_seh-1.dll");
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "external/windows/libwinpthread-1.dll");
szBinaryOutput = CUtlString("%s/bin/funnygame.exe", szOutputDir.GetString());
}
};
CUtlString outputProject = ldProject.Link();
IFileSystem2::CopyFile(szBinaryOutput, outputProject);
CUtlString outputProject = linker->Link(&ldProject);
filesystem2->CopyFile(szBinaryOutput, outputProject);
return 0;
};
DECLARE_BUILD_STAGE(launcher, launcher_build);

View File

View File

View File

View File

View File

@@ -1,24 +0,0 @@
#ifndef AUDIO_H
#define AUDIO_H
#include "interface.h"
#include "tier0/platform.h"
abstract_class ISound
{
virtual void SetVolume() = 0;
};
abstract_class I3DSound: public ISound
{
virtual void SetPosition() = 0;
virtual void SetVelocity() = 0;
};
interface IAudioManager: public IInterface
{
virtual ISound *CreateSound() = 0;
virtual I3DSound *Create3DSound() = 0;
};
#endif

View File

@@ -1,140 +0,0 @@
#ifndef ENTITY_H
#define ENTITY_H
#include "engine.h"
#include "interface.h"
#include "tier1/utlvector.h"
#include "math3d.h"
class CBaseEntity;
class C_BaseEntity;
enum EPredictionMode {
PREDICTION_MODE_CREATED,
PREDICTION_MODE_DESTROYED,
PREDICTION_MODE_NONE,
};
//-----------------------------------------------------------------------------
// Base server entity class.
// It is updated every 1/tickrate (64) of a second. Does not require special
// classes to exist.
//-----------------------------------------------------------------------------
class CBaseEntity
{
public:
CBaseEntity();
virtual void Precache() = 0;
virtual void Spawn( void ) = 0;
//---------------------------------------------------------------------
//
//---------------------------------------------------------------------
virtual void Destroy( void ) = 0;
//---------------------------------------------------------------------
// Reads the parameter from the level file. szName indicates of the
// parameter that is sent to be deserialized. szValue is value encoded
// as a string.
//---------------------------------------------------------------------
virtual void ReadParameter( const char *szName, const char *szValue );
//---------------------------------------------------------------------
// Update at constant rate (+-tickrate times a second).
//---------------------------------------------------------------------
virtual void Think( float fDelta ) = 0;
//---------------------------------------------------------------------
// Used to send data from an actual server.
//---------------------------------------------------------------------
virtual void SendToServer() = 0;
//---------------------------------------------------------------------
// Used to recieve data from an actual server.
//---------------------------------------------------------------------
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) = 0;
void SetPosition( vec3 position );
void SetRotationEuler( vec3 euler );
void SetRotationQuat( vec4 quaternion );
void SetRotationMatrix( mat3 matrix );
void SetScale( vec3 scale );
C_BaseEntity *pClientEntity = NULL;
mat3 m_matrix;
vec3 m_position;
vec3 m_scale;
uint64_t m_id;
EPredictionMode m_prediction;
};
typedef CBaseEntity*(*EntityRegistryFn)( void );
typedef C_BaseEntity*(*ClientEntityRegistryFn)( void );
class CEntityRegistryObject
{
public:
CEntityRegistryObject( const char *szName, const char *szClass, EntityRegistryFn pfn );
const char *m_szName;
const char *m_szClass;
EntityRegistryFn m_pfn;
ClientEntityRegistryFn m_pClientfn = 0;
};
interface IEntityManager: public IInterface
{
public:
CUtlVector<CBaseEntity*> m_entities;
CUtlVector<CEntityRegistryObject*> m_RegisteredEntities;
};
IEntityManager *EntityManager();
#define DECLARE_ENTITY(name, class) \
CBaseEntity *__entity_alloc_##name() \
{ \
return new class; \
}; \
CEntityRegistryObject __entity_##name##_registry(#name, #class, __entity_alloc_##name); \
//-----------------------------------------------------------------------------
// Base client entity class.
// It uses server data directly.
//-----------------------------------------------------------------------------
class C_BaseEntity
{
public:
CBaseEntity *pEntity;
virtual void Precache() = 0;
virtual void Spawn( void ) = 0;
virtual void Destroy( void ) = 0;
virtual void Think( float fDelta ) = 0;
private:
};
interface C_EntityRegistry
{
public:
C_EntityRegistry( const char *pName, ClientEntityRegistryFn pfn );
};
//-----------------------------------------------------------------------------
// Server-Client sync for entities. When new server entity is created, client
// entity gets created as well.
//-----------------------------------------------------------------------------
#define LINK_CLIENT_ENTITY(client, server) \
C_BaseEntity *__c_entity_alloc_##server() \
{ \
return new client; \
}; \
C_EntityRegistry __c_entity_##server##_registry(#server, __c_entity_alloc_##server); \
#endif

View File

@@ -1,14 +0,0 @@
#ifndef BASE_PLAYER_H
#define BASE_PLAYER_H
#include "baseentity.h"
#include "playerstart.h"
class CBaseEntity;
class CBasePlayer: public CBaseEntity
{
public:
CPlayerStart *pOwningSpawn;
};
#endif

View File

@@ -1,59 +0,0 @@
#ifndef BRUSH_H
#define BRUSH_H
#include "tier1/utlvector.h"
#include "rendering.h"
#include "baseentity.h"
#include "physics.h"
#include "mesh.h"
//-----------------------------------------------------------------------------
// Basic triangle structure which is used in brush entities.
//-----------------------------------------------------------------------------
struct Triangle_t
{
float location[9];
float uv[6];
float normal[9];
uint32_t texture;
};
//-----------------------------------------------------------------------------
// Basic brush entity which has its own geometry defined.
// They have constant position, shape, and rotation, so it makes them
// non-interactable with the game world in terms of ability to modify it at
// runtime. Collisions are precise.
//-----------------------------------------------------------------------------
class CBrushEntity: public CBaseEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void ReadParameter( const char *szName, const char *szValue ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
virtual void SendToServer() override;
virtual void RecieveFromServer( void *pData, uint32_t nDataSize ) override;
CUtlVector<Triangle_t> m_mesh;
Collider *m_collider;
RigidBodyHandle *m_body;
};
//-----------------------------------------------------------------------------
// Client rendering for brush entitites.
//-----------------------------------------------------------------------------
class C_BrushEntity: public C_BaseEntity
{
public:
virtual void Precache ( void ) override;
virtual void Spawn( void ) override;
virtual void Destroy( void ) override;
virtual void Think( float fDelta ) override;
IVertexBuffer *vertexBuffer;
IIndexBuffer *indexBuffer;
IMesh *mesh;
};
#endif

0
public/cl_dll.h Normal file
View File

View File

@@ -1,13 +0,0 @@
#ifndef CLIENT_H
#define CLIENT_H
#include "tier0/platform.h"
interface IClient
{
void LoadGame( const char *psz );
void Frame( float flDelta );
void UnloadGame( const char *psz );
};
#endif

Some files were not shown because too many files have changed in this diff Show More