no engine anymore
This commit is contained in:
10
build.cpp
10
build.cpp
@@ -54,12 +54,12 @@ extern "C" void Preinit()
|
|||||||
{
|
{
|
||||||
if (bStaticBuild)
|
if (bStaticBuild)
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
|
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/bin", szOutputDir.GetString()));
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
|
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), steam_lib);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -72,8 +72,6 @@ CUtlString client_lib;
|
|||||||
#include "tier0/__build.cpp"
|
#include "tier0/__build.cpp"
|
||||||
#include "tier1/__build.cpp"
|
#include "tier1/__build.cpp"
|
||||||
|
|
||||||
#include "fgui/__build.cpp"
|
|
||||||
|
|
||||||
#include "game/server/__build.cpp"
|
#include "game/server/__build.cpp"
|
||||||
#include "game/client/__build.cpp"
|
#include "game/client/__build.cpp"
|
||||||
|
|
||||||
|
|||||||
@@ -5,37 +5,16 @@
|
|||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
|
|
||||||
CUtlVector<CUtlString> engine_CompiledFiles = {
|
CUtlVector<CUtlString> engine_CompiledFiles = {
|
||||||
"engine/interface.cpp",
|
|
||||||
"engine/console.cpp",
|
|
||||||
"engine/filesystem.cpp",
|
|
||||||
"engine/server.cpp",
|
|
||||||
"engine/engine.cpp",
|
"engine/engine.cpp",
|
||||||
"engine/physics.cpp",
|
"engine/cvar.cpp",
|
||||||
"engine/gamemode.cpp",
|
"engine/filesystem.cpp",
|
||||||
"engine/rendering.cpp",
|
"engine/filesystem_pak.cpp",
|
||||||
|
"engine/filesystem_libc.cpp",
|
||||||
|
|
||||||
/* io */
|
"engine/gamewindow_sdl.cpp",
|
||||||
"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/sv_dll.cpp",
|
||||||
|
"engine/cl_dll.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
CUtlVector<CUtlString> engine_Libraries = {
|
CUtlVector<CUtlString> engine_Libraries = {
|
||||||
@@ -43,56 +22,39 @@ CUtlVector<CUtlString> engine_Libraries = {
|
|||||||
"SDL3",
|
"SDL3",
|
||||||
};
|
};
|
||||||
|
|
||||||
int engine_build()
|
DECLARE_BUILD_STAGE(engine)
|
||||||
{
|
{
|
||||||
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS || Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
|
CProject_t compileProject = {};
|
||||||
{
|
LinkProject_t ldProject = {};
|
||||||
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 = {};
|
|
||||||
|
|
||||||
compileProject.m_szName = "engine";
|
compileProject.m_szName = "engine";
|
||||||
compileProject.files = engine_CompiledFiles;
|
compileProject.files = engine_CompiledFiles;
|
||||||
compileProject.includeDirectories = all_IncludeDirectories;
|
compileProject.includeDirectories = all_IncludeDirectories;
|
||||||
compileProject.bFPIC = true;
|
compileProject.bFPIC = true;
|
||||||
if (bStaticBuild)
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
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;
|
|
||||||
if (bStaticBuild)
|
if (bStaticBuild)
|
||||||
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ldProject.objects.AppendTail((CObject){tier1_lib});
|
ldProject.objects.AppendTail((Object_t){tier1_lib});
|
||||||
ldProject.objects.AppendTail((CObject){fgui_lib});
|
ldProject.objects.AppendTail((Object_t){rapier_lib});
|
||||||
ldProject.objects.AppendTail((CObject){rapier_lib});
|
|
||||||
if (bSteam)
|
if (bSteam)
|
||||||
ldProject.objects.AppendTail((CObject){steam_lib});
|
ldProject.objects.AppendTail((Object_t){steam_lib});
|
||||||
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||||
}
|
}
|
||||||
|
|
||||||
CUtlString outputProject = ldProject.Link();
|
|
||||||
|
ldProject.libraries = engine_Libraries;
|
||||||
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
if (!bStaticBuild)
|
if (!bStaticBuild)
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
|
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), outputProject);
|
||||||
} else {
|
} else {
|
||||||
engine_lib = outputProject;
|
engine_lib = outputProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(engine, engine_build);
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
181
engine/brush.cpp
181
engine/brush.cpp
@@ -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
1
engine/cl_dll.cpp
Normal file
@@ -0,0 +1 @@
|
|||||||
|
|
||||||
@@ -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)
|
|
||||||
@@ -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)
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
#include "client.h"
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,281 +1,26 @@
|
|||||||
|
|
||||||
#include "fgui/fgui.h"
|
#include "ifilesystem.h"
|
||||||
#include "input.h"
|
#include "igamewindow.h"
|
||||||
#include "mainmenu.h"
|
#include "tier1/interface.h"
|
||||||
#include "networking.h"
|
|
||||||
#include "steam/steam_api_common.h"
|
|
||||||
#include "tier0/network.h"
|
|
||||||
#include "tier0/platform.h"
|
|
||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier0/mem.h"
|
||||||
#include "tier0/lib.h"
|
#include "sv_dll.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"
|
|
||||||
|
|
||||||
double fPrev = 0;
|
extern "C" void FunnyMain( int argc, char **argv )
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
printf("Trapped signal %i\n",sig);
|
CommandLine()->CreateCommandLine(argc, argv);
|
||||||
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);
|
|
||||||
};
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
filesystem = (IFileSystem*)CreateInterface(FILESYSTEM_INTERFACE_NAME, NULL);
|
||||||
// Purpose: Initializes engine
|
filesystem->Init();
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
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
|
|
||||||
|
|
||||||
#ifdef STEAM_ENABLED
|
gamewindow = (IGameWindow*)CreateInterface(GAME_WINDOW_INTERFACE_NAME, NULL);
|
||||||
if(SteamAPI_RestartAppIfNecessary(480))
|
gamewindow->Init();
|
||||||
{
|
|
||||||
Plat_Exit(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
SteamErrMsg err;
|
ServerGameDLL()->Init();
|
||||||
if (SteamAPI_InitEx(&err) != k_ESteamAPIInitResult_OK)
|
|
||||||
{
|
|
||||||
Plat_FatalErrorFunc("Failed to init Steam: %s\n", err);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
FileSystem()->InitFilesystem();
|
|
||||||
px = px_init();
|
|
||||||
|
|
||||||
if (!ICommandLine::CheckParam("-dedicated"))
|
for (;;) {
|
||||||
{
|
gamewindow->UpdateWindow();
|
||||||
// Run local client
|
|
||||||
g_localClient = new IIClient();
|
|
||||||
IIEngine::ConnectClient(g_localClient);
|
|
||||||
|
|
||||||
// Init IO
|
|
||||||
IVideo::Init();
|
|
||||||
Input()->Init();
|
|
||||||
Input()->SetInputMode(INPUT_MODE_MENU);
|
|
||||||
IFGUI::Init();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
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++;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,288 +1,86 @@
|
|||||||
#include "interface.h"
|
#include "ifilesystem.h"
|
||||||
#include "tier0/platform.h"
|
#include "tier1/interface.h"
|
||||||
#include "tier1/commandline.h"
|
#include "tier0/lib.h"
|
||||||
#include "filesystem.h"
|
|
||||||
#include "unistd.h"
|
|
||||||
#include <cstdio>
|
|
||||||
|
|
||||||
#define BASEDIR "rtt"
|
size_t IFileHandle::Write( const void *pData, size_t nDataSize )
|
||||||
#define GAMEDIR "funnygame"
|
|
||||||
|
|
||||||
|
|
||||||
struct PackHeader_t
|
|
||||||
{
|
{
|
||||||
char id[8];
|
return m_pFileSystem->Write(this, pData, nDataSize);
|
||||||
unsigned long long offset;
|
}
|
||||||
unsigned long long size;
|
|
||||||
};
|
size_t IFileHandle::Read( void *pData, size_t nDataSize )
|
||||||
struct PackDirectory_t
|
|
||||||
{
|
{
|
||||||
char name[56];
|
return m_pFileSystem->Read(this, pData, nDataSize);
|
||||||
unsigned long long offset;
|
}
|
||||||
unsigned long long size;
|
|
||||||
};
|
size_t IFileHandle::Seek( ESeekMode eSeekMode, size_t nOffset )
|
||||||
struct Pack_t
|
|
||||||
{
|
{
|
||||||
FILE* handle;
|
return m_pFileSystem->Seek(this, eSeekMode, nOffset);
|
||||||
PackHeader_t header;
|
}
|
||||||
CUtlVector<PackDirectory_t> files;
|
|
||||||
};
|
size_t IFileHandle::Tell( void )
|
||||||
struct FileDirectory_t
|
|
||||||
{
|
{
|
||||||
CUtlString path;
|
return m_pFileSystem->Tell(this);
|
||||||
Pack_t pack;
|
}
|
||||||
};
|
|
||||||
|
void IFileHandle::Close( void )
|
||||||
|
{
|
||||||
|
m_pFileSystem->Close(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CUtlString fs_basedir;
|
class CFileSystem : public IFileSystem
|
||||||
CUtlString fs_gamedir;
|
|
||||||
CUtlSelfReferencingVector<FileDirectory_t> fs_directories;
|
|
||||||
|
|
||||||
interface CFileSystem: public IFileSystem
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual void Init() override {}
|
virtual void Init() override {
|
||||||
virtual void Frame() override {}
|
filesystem_backend = (IFileSystem*)CreateInterface(FILESYSTEM_BACKEND_INTERFACE_NAME, NULL);
|
||||||
virtual void Deinit() override {}
|
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 );
|
virtual IFileHandle *Open( const char *szFileName, int eOpCode ) override
|
||||||
static void AddFile( const char *psz );
|
{
|
||||||
|
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);
|
IFileSystem *filesystem;
|
||||||
|
IFileSystem *filesystem_backend;
|
||||||
//-----------------------------------------------------------------------------
|
IFileSystem *filesystem_pak;
|
||||||
//
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
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, ...)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
EXPOSE_INTERFACE(CFileSystem, IFileSystem, FILESYSTEM_INTERFACE_NAME);
|
||||||
|
|||||||
94
engine/filesystem_libc.cpp
Normal file
94
engine/filesystem_libc.cpp
Normal 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
81
engine/filesystem_pak.cpp
Normal 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);
|
||||||
@@ -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
60
engine/gamewindow_sdl.cpp
Normal 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);
|
||||||
301
engine/input.cpp
301
engine/input.cpp
@@ -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);
|
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#include "interface.h"
|
|
||||||
#include "tier0/lib.h"
|
|
||||||
|
|
||||||
|
|
||||||
CInterfaceRegistry::CInterfaceRegistry( const char *szName, InterfaceRegistryFn pfn )
|
|
||||||
{
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
#define MINIAUDIO_IMPLEMENTATION
|
|
||||||
#include "miniaudio.h"
|
|
||||||
|
|
||||||
|
|
||||||
156
engine/mesh.cpp
156
engine/mesh.cpp
@@ -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)
|
|
||||||
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -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();
|
|
||||||
}
|
|
||||||
@@ -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);
|
|
||||||
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -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});
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -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
21
engine/sv_dll.cpp
Normal 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;
|
||||||
|
}
|
||||||
@@ -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)
|
|
||||||
@@ -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);
|
|
||||||
@@ -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)
|
|
||||||
@@ -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);
|
|
||||||
@@ -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;
|
|
||||||
1410
engine/vk_video.cpp
1410
engine/vk_video.cpp
File diff suppressed because it is too large
Load Diff
@@ -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
|
|
||||||
@@ -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;
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -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);
|
|
||||||
330
fgui/fgui.cpp
330
fgui/fgui.cpp
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -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()
|
|
||||||
{
|
|
||||||
|
|
||||||
};
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -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
|
# We want to build just enough to use other stuff
|
||||||
FPC_FILES := main.cpp library/runner.cpp library/helper.cpp library/c.cpp library/ld.cpp library/target.cpp
|
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
|
CC = clang
|
||||||
OUTPUT_DIR = fpc
|
OUTPUT_DIR = fpc
|
||||||
CCFLAGS = -I../public -Ipublic -lc -lstdc++
|
CCFLAGS = -I../public -Ipublic -lc -lstdc++
|
||||||
|
|||||||
34
fpc/README
Normal file
34
fpc/README
Normal 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
|
||||||
@@ -5,20 +5,28 @@
|
|||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
|
|
||||||
CUtlVector<CUtlString> g_CompiledFiles = {
|
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",
|
"main.cpp",
|
||||||
"library/runner.cpp",
|
"library/runner.cpp",
|
||||||
"library/helper.cpp",
|
"library/helper.cpp",
|
||||||
"library/c.cpp",
|
"library/c.cpp",
|
||||||
"library/ld.cpp",
|
"library/ld.cpp",
|
||||||
"library/target.cpp",
|
"library/target.cpp",
|
||||||
"../tier0/lib.cpp",
|
|
||||||
"../tier0/mem.cpp",
|
"library/android/apktool.cpp",
|
||||||
"../tier0/platform.cpp",
|
|
||||||
"../tier1/utlbuffer.cpp",
|
"library/clang/c.cpp",
|
||||||
"../tier1/utlstring.cpp",
|
"library/clang/ld.cpp",
|
||||||
"../tier1/utlvector.cpp",
|
|
||||||
"../tier1/utlmap.cpp",
|
|
||||||
"../tier1/commandline.cpp",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
CUtlVector<CUtlString> g_IncludeDirectories = {
|
CUtlVector<CUtlString> g_IncludeDirectories = {
|
||||||
@@ -27,21 +35,20 @@ CUtlVector<CUtlString> g_IncludeDirectories = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
int build_fpc()
|
DECLARE_BUILD_STAGE(fpc)
|
||||||
{
|
{
|
||||||
CCProject compileProject = {};
|
CProject_t compileProject = {};
|
||||||
CLDProject ldProject = {};
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
compileProject.m_szName = "fpc";
|
compileProject.m_szName = "fpc";
|
||||||
compileProject.files = g_CompiledFiles;
|
compileProject.files = g_CompiledFiles;
|
||||||
compileProject.includeDirectories = g_IncludeDirectories;
|
compileProject.includeDirectories = g_IncludeDirectories;
|
||||||
ldProject = compileProject.Compile();
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
|
|
||||||
CUtlString outputProject = ldProject.Link();
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
IFileSystem2::MakeDirectory("../build/tools");
|
filesystem2->MakeDirectory("../build/tools");
|
||||||
IFileSystem2::CopyFile("fpc_temp", outputProject);
|
filesystem2->CopyFile("fpc_temp", outputProject);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(fpc, build_fpc);
|
|
||||||
|
|||||||
139
fpc/library/android/apktool.cpp
Normal file
139
fpc/library/android/apktool.cpp
Normal 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;
|
||||||
|
}
|
||||||
23
fpc/library/android/signtool.cpp
Normal file
23
fpc/library/android/signtool.cpp
Normal 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");
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,123 +1,3 @@
|
|||||||
#include "c.h"
|
#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
|
ICCompiler *ccompiler;
|
||||||
{
|
|
||||||
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 ¯o: 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);
|
|
||||||
};
|
|
||||||
|
|||||||
164
fpc/library/clang/c.cpp
Normal file
164
fpc/library/clang/c.cpp
Normal 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 ¯o: 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
175
fpc/library/clang/ld.cpp
Normal 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;
|
||||||
|
};
|
||||||
@@ -6,12 +6,13 @@
|
|||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
#include "libgen.h"
|
#include "libgen.h"
|
||||||
#include "sys/stat.h"
|
#include "sys/stat.h"
|
||||||
|
#include "tier1/interface.h"
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned int g_hashState = 102851263;
|
unsigned int g_hashState = 102851263;
|
||||||
unsigned int CProject::GenerateProjectHash( void )
|
unsigned int BaseProject_t::GenerateProjectHash( void )
|
||||||
{
|
{
|
||||||
unsigned int hash = 5381+g_hashState;
|
unsigned int hash = 5381+g_hashState;
|
||||||
int c;
|
int c;
|
||||||
@@ -31,50 +32,65 @@ static ssize_t pathSize = readlink("/proc/self/exe", path, sizeof(path) - 1);
|
|||||||
#endif
|
#endif
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
static uint32_t pathSize = sizeof(path);
|
static uint32_t pathSize = sizeof(path);
|
||||||
int pathResult = _NSGetExecutablePath(path, &pathSize);
|
static int pathResult = _NSGetExecutablePath(path, &pathSize);
|
||||||
#endif
|
#endif
|
||||||
char *szPathDir = dirname(path);
|
static char *szPathDir = dirname(path);
|
||||||
char *szBuildDir = 0;
|
char *g_szBuildDir = 0;
|
||||||
char *IFileSystem2::OwnDirectory()
|
|
||||||
|
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;
|
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 = {
|
CUtlVector<CUtlString> args = {
|
||||||
CUtlString(szOrigin),
|
CUtlString(szOrigin),
|
||||||
CUtlString(szDestination),
|
CUtlString(szDestination),
|
||||||
};
|
};
|
||||||
IRunner::Run("cp", args);
|
runner->Run("cp", args);
|
||||||
IRunner::Wait();
|
runner->Wait();
|
||||||
}
|
}
|
||||||
void IFileSystem2::CopyDirectory( const char *szDestination, const char *szOrigin )
|
void CPOSIXFileSystem2::CopyDirectory( const char *szDestination, const char *szOrigin )
|
||||||
{
|
{
|
||||||
CUtlVector<CUtlString> args = {
|
CUtlVector<CUtlString> args = {
|
||||||
"-r",
|
"-r",
|
||||||
CUtlString(szOrigin),
|
CUtlString(szOrigin),
|
||||||
CUtlString(szDestination),
|
CUtlString(szDestination),
|
||||||
};
|
};
|
||||||
IRunner::Run("cp", args);
|
runner->Run("cp", args);
|
||||||
IRunner::Wait();
|
runner->Wait();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IFileSystem2::MakeDirectory( const char *psz )
|
void CPOSIXFileSystem2::MakeDirectory( const char *psz )
|
||||||
{
|
{
|
||||||
CUtlVector<CUtlString> args = {
|
CUtlVector<CUtlString> args = {
|
||||||
"-p",
|
"-p",
|
||||||
CUtlString(psz),
|
CUtlString(psz),
|
||||||
};
|
};
|
||||||
IRunner::Run("mkdir", args);
|
runner->Run("mkdir", args);
|
||||||
IRunner::Wait();
|
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 srcbuf;
|
||||||
struct stat outbuf;
|
struct stat outbuf;
|
||||||
|
|||||||
@@ -1,134 +1,3 @@
|
|||||||
#include "ld.h"
|
#include "ld.h"
|
||||||
#include "helper.h"
|
|
||||||
#include "libgen.h"
|
|
||||||
#include "target.h"
|
|
||||||
|
|
||||||
CUtlString CLDProject::Link( void )
|
ILinker *linker;
|
||||||
{
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "runner.h"
|
#include "runner.h"
|
||||||
#include "tier0/platform.h"
|
#include "tier0/platform.h"
|
||||||
|
#include "tier1/interface.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
#include "tier1/utlvector.h"
|
#include "tier1/utlvector.h"
|
||||||
#include "unistd.h"
|
#include "unistd.h"
|
||||||
@@ -7,7 +8,20 @@
|
|||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
|
|
||||||
CUtlVector<pid_t> g_processes;
|
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();
|
pid_t pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
@@ -17,15 +31,15 @@ int IRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
|
|||||||
{
|
{
|
||||||
CUtlVector<const char*> execargs;
|
CUtlVector<const char*> execargs;
|
||||||
execargs.AppendTail(szName);
|
execargs.AppendTail(szName);
|
||||||
if (ICommandLine::CheckParam("-fpcdebug"))
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
V_printf("%s",szName.GetString());
|
V_printf("%s",szName.GetString());
|
||||||
for (auto &arg: args)
|
for (auto &arg: args)
|
||||||
{
|
{
|
||||||
execargs.AppendTail(arg);
|
execargs.AppendTail(arg);
|
||||||
if (ICommandLine::CheckParam("-fpcdebug"))
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
V_printf(" %s",arg.GetString());
|
V_printf(" %s",arg.GetString());
|
||||||
}
|
}
|
||||||
if (ICommandLine::CheckParam("-fpcdebug"))
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
V_printf("\n");
|
V_printf("\n");
|
||||||
execargs.AppendTail(0);
|
execargs.AppendTail(0);
|
||||||
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
|
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
|
||||||
@@ -38,7 +52,7 @@ int IRunner::Run(CUtlString szName, CUtlVector<CUtlString>& args)
|
|||||||
return 0;
|
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();
|
pid_t pid = fork();
|
||||||
if (pid < 0)
|
if (pid < 0)
|
||||||
@@ -48,10 +62,16 @@ int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlStrin
|
|||||||
{
|
{
|
||||||
CUtlVector<const char*> execargs;
|
CUtlVector<const char*> execargs;
|
||||||
execargs.AppendTail(szName);
|
execargs.AppendTail(szName);
|
||||||
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
|
V_printf("%s",szName.GetString());
|
||||||
for (auto &arg: args)
|
for (auto &arg: args)
|
||||||
{
|
{
|
||||||
execargs.AppendTail(arg);
|
execargs.AppendTail(arg);
|
||||||
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
|
V_printf(" %s",arg.GetString());
|
||||||
}
|
}
|
||||||
|
if (CommandLine()->CheckParam("-fpcdebug"))
|
||||||
|
V_printf("\n");
|
||||||
execargs.AppendTail(0);
|
execargs.AppendTail(0);
|
||||||
chdir(szDirectory.GetString());
|
chdir(szDirectory.GetString());
|
||||||
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
|
if ( execvp(szName, (char *const*)execargs.GetData()) == -1 )
|
||||||
@@ -65,12 +85,12 @@ int IRunner::Run(CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlStrin
|
|||||||
return 0;
|
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)
|
for (auto &process: g_processes)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Generates triplet suitable for most compilers.
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
CUtlString Target_t::GetTriplet()
|
CUtlString Target_t::GetTriplet()
|
||||||
{
|
{
|
||||||
CUtlString triplet = "";
|
CUtlString triplet = "";
|
||||||
@@ -11,15 +13,25 @@ CUtlString Target_t::GetTriplet()
|
|||||||
triplet.AppendTail("x86_64");
|
triplet.AppendTail("x86_64");
|
||||||
if ( cpu == TARGET_CPU_AARCH64 )
|
if ( cpu == TARGET_CPU_AARCH64 )
|
||||||
triplet.AppendTail("aarch64");
|
triplet.AppendTail("aarch64");
|
||||||
|
if ( cpu == TARGET_CPU_WASM32 )
|
||||||
|
triplet.AppendTail("wasm32");
|
||||||
triplet.AppendTail("-");
|
triplet.AppendTail("-");
|
||||||
if ( kernel == TARGET_KERNEL_WINDOWS )
|
if ( kernel == TARGET_KERNEL_UNKNOWN )
|
||||||
triplet.AppendTail("pc-windows-gnu");
|
triplet.AppendTail("unknown-unknown");
|
||||||
if ( kernel == TARGET_KERNEL_LINUX )
|
if ( kernel == TARGET_KERNEL_LINUX )
|
||||||
triplet.AppendTail("unknown-linux-gnu");
|
triplet.AppendTail("unknown-linux-gnu");
|
||||||
|
if ( kernel == TARGET_KERNEL_WINDOWS )
|
||||||
|
triplet.AppendTail("pc-windows-gnu");
|
||||||
if ( kernel == TARGET_KERNEL_DARWIN )
|
if ( kernel == TARGET_KERNEL_DARWIN )
|
||||||
triplet.AppendTail("apple-darwin");
|
triplet.AppendTail("apple-darwin");
|
||||||
if ( kernel == TARGET_KERNEL_IOS )
|
if ( kernel == TARGET_KERNEL_IOS )
|
||||||
triplet.AppendTail("apple-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;
|
return triplet;
|
||||||
@@ -40,11 +52,15 @@ Target_t Target_t::HostTarget()
|
|||||||
.optimization = TARGET_DEBUG,
|
.optimization = TARGET_DEBUG,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Returns default target for build
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
Target_t Target_t::DefaultTarget()
|
Target_t Target_t::DefaultTarget()
|
||||||
{
|
{
|
||||||
CUtlString szDevice = ICommandLine::ParamValue("-device");
|
CUtlString szDevice = CommandLine()->ParamValue("-device");
|
||||||
CUtlString szOS = ICommandLine::ParamValue("-os");
|
CUtlString szOS = CommandLine()->ParamValue("-os");
|
||||||
CUtlString szArch = ICommandLine::ParamValue("-arch");
|
CUtlString szArch = CommandLine()->ParamValue("-arch");
|
||||||
|
|
||||||
ETargetKernel kernel =
|
ETargetKernel kernel =
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
@@ -58,8 +74,12 @@ Target_t Target_t::DefaultTarget()
|
|||||||
cpu = TARGET_CPU_AMD64;
|
cpu = TARGET_CPU_AMD64;
|
||||||
else if ( szArch == "aarch64" )
|
else if ( szArch == "aarch64" )
|
||||||
cpu = TARGET_CPU_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;
|
kernel = TARGET_KERNEL_WINDOWS;
|
||||||
else if ( szOS == "linux" )
|
else if ( szOS == "linux" )
|
||||||
kernel = TARGET_KERNEL_LINUX;
|
kernel = TARGET_KERNEL_LINUX;
|
||||||
@@ -67,6 +87,8 @@ Target_t Target_t::DefaultTarget()
|
|||||||
kernel = TARGET_KERNEL_DARWIN;
|
kernel = TARGET_KERNEL_DARWIN;
|
||||||
else if ( szOS == "ios" )
|
else if ( szOS == "ios" )
|
||||||
kernel = TARGET_KERNEL_IOS;
|
kernel = TARGET_KERNEL_IOS;
|
||||||
|
else if ( szOS == "android" )
|
||||||
|
kernel = TARGET_KERNEL_ANDROID;
|
||||||
else if ( szOS != 0 )
|
else if ( szOS != 0 )
|
||||||
V_printf("Unknown OS: %s\n", szOS.GetString());
|
V_printf("Unknown OS: %s\n", szOS.GetString());
|
||||||
|
|
||||||
|
|||||||
31
fpc/main.cpp
31
fpc/main.cpp
@@ -2,34 +2,43 @@
|
|||||||
#include "public/helper.h"
|
#include "public/helper.h"
|
||||||
#include "public/ld.h"
|
#include "public/ld.h"
|
||||||
#include "public/target.h"
|
#include "public/target.h"
|
||||||
|
#include "runner.h"
|
||||||
#include "tier0/platform.h"
|
#include "tier0/platform.h"
|
||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
#include "c.h"
|
#include "c.h"
|
||||||
|
#include "tier1/interface.h"
|
||||||
#include "tier1/utlvector.h"
|
#include "tier1/utlvector.h"
|
||||||
#include "signal.h"
|
#include "signal.h"
|
||||||
#include "libgen.h"
|
#include "libgen.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
CUtlString owndir;
|
CUtlString owndir;
|
||||||
|
extern char *g_szBuildDir;
|
||||||
int build()
|
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.m_szName = "build";
|
||||||
compileScriptProject.files = {"build.cpp"};
|
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.bFPIC = true;
|
||||||
compileScriptProject.m_target = Target_t::HostTarget();
|
compileScriptProject.m_target = Target_t::HostTarget();
|
||||||
CLDProject linkScriptProject = compileScriptProject.Compile();
|
|
||||||
|
LinkProject_t linkScriptProject = ccompiler->Compile(&compileScriptProject);
|
||||||
linkScriptProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
linkScriptProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||||
linkScriptProject.m_target = Target_t::HostTarget();
|
linkScriptProject.m_target = Target_t::HostTarget();
|
||||||
CUtlString script = linkScriptProject.Link();
|
|
||||||
|
CUtlString script = linker->Link(&linkScriptProject);
|
||||||
|
|
||||||
void *scriptDLL = Plat_LoadLibrary(script);
|
void *scriptDLL = Plat_LoadLibrary(script);
|
||||||
|
|
||||||
auto PreinitFn = (void(*)())Plat_GetProc(scriptDLL, "Preinit");
|
auto PreinitFn = (void(*)())Plat_GetProc(scriptDLL, "Preinit");
|
||||||
V_printf("%p\n",PreinitFn);
|
|
||||||
if (PreinitFn)
|
if (PreinitFn)
|
||||||
PreinitFn();
|
PreinitFn();
|
||||||
|
|
||||||
@@ -38,7 +47,8 @@ int build()
|
|||||||
build->m_pMainFn();
|
build->m_pMainFn();
|
||||||
};
|
};
|
||||||
Plat_UnloadLibrary(scriptDLL);
|
Plat_UnloadLibrary(scriptDLL);
|
||||||
CCProject::GenerateCompileCommands();
|
|
||||||
|
ccompiler->GenerateLinterData();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
@@ -80,8 +90,7 @@ findbuild:
|
|||||||
} else {
|
} else {
|
||||||
V_fclose(file);
|
V_fclose(file);
|
||||||
}
|
}
|
||||||
extern char *szBuildDir;
|
g_szBuildDir = szBuildcppDir;
|
||||||
szBuildDir = szBuildcppDir;
|
|
||||||
|
|
||||||
#ifdef __linux
|
#ifdef __linux
|
||||||
signal(SIGHUP, IEngine_Signal);
|
signal(SIGHUP, IEngine_Signal);
|
||||||
@@ -95,8 +104,8 @@ findbuild:
|
|||||||
signal(SIGSEGV, IEngine_Signal);
|
signal(SIGSEGV, IEngine_Signal);
|
||||||
signal(SIGTERM, IEngine_Signal);
|
signal(SIGTERM, IEngine_Signal);
|
||||||
#endif
|
#endif
|
||||||
ICommandLine::CreateCommandLine(c, v);
|
CommandLine()->CreateCommandLine(c, v);
|
||||||
if (ICommandLine::CheckParam("build"))
|
if (CommandLine()->CheckParam("build"))
|
||||||
return build();
|
return build();
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
|
|||||||
39
fpc/public/apktool.h
Normal file
39
fpc/public/apktool.h
Normal 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
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#ifndef C_H
|
#ifndef C_H
|
||||||
#define C_H
|
#define C_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
#include "tier1/utlvector.h"
|
#include "tier1/utlvector.h"
|
||||||
#include "runner.h"
|
#include "runner.h"
|
||||||
@@ -35,20 +36,35 @@ enum ECPPVersion
|
|||||||
CPPVERSION_2C = 6,
|
CPPVERSION_2C = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CCProject : public CProject
|
struct CProject_t : public CPUProject_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CUtlVector<CUtlString> files = {};
|
CUtlVector<CUtlString> files = {};
|
||||||
CUtlVector<C_Macro_t> macros = {};
|
|
||||||
CUtlVector<CUtlString> includeDirectories = {};
|
CUtlVector<CUtlString> includeDirectories = {};
|
||||||
CUtlVector<CUtlString> includeFiles = {};
|
CUtlVector<CUtlString> includeFiles = {};
|
||||||
|
CUtlVector<C_Macro_t> macros = {};
|
||||||
|
|
||||||
bool bFPIE = false;
|
bool bFPIE = false;
|
||||||
bool bFPIC = false;
|
bool bFPIC = false;
|
||||||
bool bDebug = m_target.optimization == TARGET_DEBUG;
|
|
||||||
ECVersion cVersion;
|
ECVersion cVersion;
|
||||||
ECPPVersion cppVersion;
|
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
|
#endif
|
||||||
|
|||||||
@@ -1,30 +1,62 @@
|
|||||||
#ifndef HELPER_H
|
#ifndef HELPER_H
|
||||||
#define HELPER_H
|
#define HELPER_H
|
||||||
|
|
||||||
|
#include "apktool.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
|
|
||||||
#define FPC_TEMPORAL_DIRNAME ".fpc"
|
#define FPC_TEMPORAL_DIRNAME ".fpc"
|
||||||
|
|
||||||
class CProject
|
|
||||||
|
struct BaseProject_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Target_t m_target = Target_t::DefaultTarget();
|
|
||||||
CUtlString m_szName;
|
CUtlString m_szName;
|
||||||
unsigned int GenerateProjectHash( void );
|
unsigned int GenerateProjectHash( void );
|
||||||
};
|
};
|
||||||
|
|
||||||
interface IFileSystem2
|
|
||||||
|
struct CPUProject_t : public BaseProject_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static char *OwnDirectory();
|
Target_t m_target = Target_t::DefaultTarget();
|
||||||
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 );
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
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
|
class CBuildStage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -33,8 +65,10 @@ public:
|
|||||||
int(*m_pMainFn)();
|
int(*m_pMainFn)();
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DECLARE_BUILD_STAGE(sz, fn) \
|
#define DECLARE_BUILD_STAGE(sz) \
|
||||||
CBuildStage __##sz##_build_stage(#sz, fn);
|
int __build_stage_##sz(); \
|
||||||
|
CBuildStage __##sz##_build_stage(#sz, __build_stage_##sz); \
|
||||||
|
int __build_stage_##sz()
|
||||||
|
|
||||||
CUtlVector<CBuildStage*>& BuildStages();
|
CUtlVector<CBuildStage*>& BuildStages();
|
||||||
|
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "runner.h"
|
#include "runner.h"
|
||||||
#include "helper.h"
|
#include "helper.h"
|
||||||
#include "obj.h"
|
#include "obj.h"
|
||||||
|
#include "tier0/platform.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
enum ELinkType
|
enum ELinkType
|
||||||
@@ -14,22 +15,32 @@ enum ELinkType
|
|||||||
ELINK_STATIC_LIBRARY,
|
ELINK_STATIC_LIBRARY,
|
||||||
};
|
};
|
||||||
|
|
||||||
class CLDProject: public CProject
|
struct LinkProject_t: public CPUProject_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
void AddObject( CObject& object );
|
void AddObject( Object_t& object );
|
||||||
void AddLibrary( CUtlString psz );
|
|
||||||
void AddLibraryByPath( CUtlString szPath );
|
|
||||||
void AddLibraryDirectory( CUtlString szPath );
|
|
||||||
CUtlString Link( void );
|
|
||||||
|
|
||||||
ELinkType linkType;
|
ELinkType linkType;
|
||||||
CUtlVector<CObject> objects = {};
|
CUtlVector<Object_t> objects = {};
|
||||||
CUtlVector<CUtlString> libraries ={};
|
CUtlVector<CUtlString> libraries ={};
|
||||||
CUtlVector<CUtlString> libraryDirectories = {};
|
CUtlVector<CUtlString> libraryDirectories = {};
|
||||||
CUtlVector<CUtlString> libraryObjects = {};
|
CUtlVector<CUtlString> libraryObjects = {};
|
||||||
CUtlVector<CUtlString> frameworkDirectories = {};
|
CUtlVector<CUtlString> frameworkDirectories = {};
|
||||||
CUtlVector<CUtlString> frameworks = {};
|
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
|
#endif
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
class CObject
|
struct Object_t
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CUtlString m_szObjectFile;
|
CUtlString m_szObjectFile;
|
||||||
|
|||||||
@@ -1,16 +1,21 @@
|
|||||||
#ifndef RUNNER_H
|
#ifndef RUNNER_H
|
||||||
#define RUNNER_H
|
#define RUNNER_H
|
||||||
|
|
||||||
|
#include "tier0/platform.h"
|
||||||
#include "tier1/utlvector.h"
|
#include "tier1/utlvector.h"
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
|
|
||||||
interface IRunner
|
#define RUNNER_INTERFACE_NAME "Runner001"
|
||||||
|
|
||||||
|
abstract_class IRunner
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static int Run( CUtlString szName, CUtlVector<CUtlString>& args );
|
virtual int Run( CUtlString szName, CUtlVector<CUtlString>& args ) = 0;
|
||||||
static int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args );
|
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args ) = 0;
|
||||||
static int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment );
|
virtual int Run( CUtlString szName, CUtlString szDirectory, CUtlVector<CUtlString>& args, CUtlVector<CUtlString>& environment ) = 0;
|
||||||
static int Wait( void );
|
virtual int Wait( void ) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern IRunner *runner;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
21
fpc/public/signtool.h
Normal file
21
fpc/public/signtool.h
Normal 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
0
fpc/public/slang.h
Normal file
@@ -2,20 +2,30 @@
|
|||||||
#define TARGET_T
|
#define TARGET_T
|
||||||
|
|
||||||
#include "tier1/utlstring.h"
|
#include "tier1/utlstring.h"
|
||||||
|
#include "tier1/commandline.h"
|
||||||
|
|
||||||
enum ETargetKernel
|
enum ETargetKernel
|
||||||
{
|
{
|
||||||
|
TARGET_KERNEL_UNKNOWN,
|
||||||
TARGET_KERNEL_LINUX,
|
TARGET_KERNEL_LINUX,
|
||||||
TARGET_KERNEL_WINDOWS,
|
TARGET_KERNEL_WINDOWS,
|
||||||
TARGET_KERNEL_DARWIN,
|
TARGET_KERNEL_DARWIN,
|
||||||
TARGET_KERNEL_IOS,
|
TARGET_KERNEL_IOS,
|
||||||
|
TARGET_KERNEL_ANDROID,
|
||||||
|
TARGET_KERNEL_WASI,
|
||||||
|
TARGET_KERNEL_EMSCRIPTEN,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ETargetCPU
|
enum ETargetCPU
|
||||||
{
|
{
|
||||||
TARGET_CPU_AMD64,
|
TARGET_CPU_AMD64,
|
||||||
|
TARGET_CPU_I286,
|
||||||
TARGET_CPU_I386,
|
TARGET_CPU_I386,
|
||||||
|
TARGET_CPU_I486,
|
||||||
|
TARGET_CPU_I586,
|
||||||
|
TARGET_CPU_I686,
|
||||||
TARGET_CPU_AARCH64,
|
TARGET_CPU_AARCH64,
|
||||||
|
TARGET_CPU_WASM32,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum ETargetOptimization
|
enum ETargetOptimization
|
||||||
@@ -30,9 +40,21 @@ struct Target_t
|
|||||||
ETargetKernel kernel;
|
ETargetKernel kernel;
|
||||||
ETargetCPU cpu;
|
ETargetCPU cpu;
|
||||||
ETargetOptimization optimization;
|
ETargetOptimization optimization;
|
||||||
|
const char *szSysroot = CommandLine()->ParamValue("-sysroot");
|
||||||
|
|
||||||
CUtlString GetTriplet();
|
CUtlString GetTriplet();
|
||||||
static Target_t HostTarget();
|
static Target_t HostTarget();
|
||||||
static Target_t DefaultTarget();
|
static Target_t DefaultTarget();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum EShaderTarget
|
||||||
|
{
|
||||||
|
SHADER_TARGET_VULKAN_SPIRV,
|
||||||
|
SHADER_TARGET_OPENGL_SPIRV,
|
||||||
|
SHADER_TARGET_GLSL,
|
||||||
|
SHADER_TARGET_HLSL,
|
||||||
|
SHADER_TARGET_MSL,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
0
fpc/public/windres.h
Normal file
0
fpc/public/windres.h
Normal file
443
fpc/tests/android_build/android_native_app_glue.c
Normal file
443
fpc/tests/android_build/android_native_app_glue.c
Normal 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);
|
||||||
|
}
|
||||||
349
fpc/tests/android_build/android_native_app_glue.h
Normal file
349
fpc/tests/android_build/android_native_app_glue.h
Normal 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 */
|
||||||
35
fpc/tests/android_build/build.cpp
Normal file
35
fpc/tests/android_build/build.cpp
Normal 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;
|
||||||
|
}
|
||||||
|
|
||||||
BIN
fpc/tests/android_build/com.example.testfpc.signed.apk
Normal file
BIN
fpc/tests/android_build/com.example.testfpc.signed.apk
Normal file
Binary file not shown.
BIN
fpc/tests/android_build/com.example.testfpc.signed.apk.idsig
Normal file
BIN
fpc/tests/android_build/com.example.testfpc.signed.apk.idsig
Normal file
Binary file not shown.
42
fpc/tests/android_build/main.c
Normal file
42
fpc/tests/android_build/main.c
Normal 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
|
||||||
|
}
|
||||||
|
}
|
||||||
0
fpc/tests/ios_build/build.cpp
Normal file
0
fpc/tests/ios_build/build.cpp
Normal file
@@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
void build_shader( const char *szName )
|
void build_shader( const char *szName )
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("build/funnygame/metal/gfx"));
|
filesystem2->MakeDirectory(CUtlString("build/funnygame/metal/gfx"));
|
||||||
IFileSystem2::MakeDirectory(CUtlString("build/funnygame/vulkan/gfx"));
|
filesystem2->MakeDirectory(CUtlString("build/funnygame/vulkan/gfx"));
|
||||||
|
|
||||||
CUtlVector<CUtlString> slang_args = {
|
CUtlVector<CUtlString> slang_args = {
|
||||||
CUtlString("funnyassets/gfx_shaders/%s.slang", szName),
|
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),
|
CUtlString("build/funnygame/vulkan/gfx/%s.shader", szName),
|
||||||
};
|
};
|
||||||
|
|
||||||
IRunner::Run("slangc", slang_args);
|
runner->Run("slangc", slang_args);
|
||||||
slang_args[3] = "metal";
|
slang_args[3] = "metal";
|
||||||
slang_args[5] = "__METAL__=1";
|
slang_args[5] = "__METAL__=1";
|
||||||
slang_args[7] = CUtlString("build/funnygame/metal/gfx/%s.shader", szName);
|
slang_args[7] = CUtlString("build/funnygame/metal/gfx/%s.shader", szName);
|
||||||
IRunner::Run("slangc", slang_args);
|
runner->Run("slangc", slang_args);
|
||||||
IRunner::Wait();
|
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");
|
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/maps");
|
||||||
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/gfx");
|
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/gfx");
|
||||||
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts");
|
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/fonts");
|
||||||
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures");
|
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/textures");
|
||||||
IFileSystem2::CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials");
|
filesystem2->CopyDirectory(CUtlString("build/funnygame/assets"), "funnyassets/materials");
|
||||||
build_shader("mesh_frag");
|
build_shader("mesh_frag");
|
||||||
build_shader("mesh_vert");
|
build_shader("mesh_vert");
|
||||||
build_shader("fgui_rect_frag");
|
build_shader("fgui_rect_frag");
|
||||||
@@ -50,7 +52,7 @@ int assets_build()
|
|||||||
CUtlString("build/funnygame/assets"),
|
CUtlString("build/funnygame/assets"),
|
||||||
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "rtt") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "rtt"),
|
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)
|
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS ||Target_t::DefaultTarget().kernel == TARGET_KERNEL_DARWIN)
|
||||||
{
|
{
|
||||||
python_args = {
|
python_args = {
|
||||||
@@ -58,21 +60,20 @@ int assets_build()
|
|||||||
CUtlString("build/funnygame/metal"),
|
CUtlString("build/funnygame/metal"),
|
||||||
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "metal") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "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 {
|
} else {
|
||||||
python_args = {
|
python_args = {
|
||||||
"build/tools/makepak64.py",
|
"build/tools/makepak64.py",
|
||||||
CUtlString("build/funnygame/vulkan"),
|
CUtlString("build/funnygame/vulkan"),
|
||||||
bStaticBuild ? CUtlString("%s/bin/%s.pak", szOutputDir.GetString(), "vulkan") : CUtlString("%s/funnygame/%s.pak", szOutputDir.GetString(), "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)
|
if (bStaticBuild)
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "funnyassets/default.cfg");
|
filesystem2->CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "funnyassets/default.cfg");
|
||||||
else
|
else
|
||||||
IFileSystem2::CopyFile(szOutputDir.GetString(), "funnyassets/default.cfg");
|
filesystem2->CopyFile(szOutputDir.GetString(), "funnyassets/default.cfg");
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(assets, assets_build);
|
|
||||||
|
|||||||
0
funnyassets/gfx_shaders/mesh_raytracer_hit.slang
Normal file
0
funnyassets/gfx_shaders/mesh_raytracer_hit.slang
Normal file
0
funnyassets/gfx_shaders/mesh_raytracer_miss.slang
Normal file
0
funnyassets/gfx_shaders/mesh_raytracer_miss.slang
Normal file
16
funnyassets/gfx_shaders/mesh_raytracer_raygen.slang
Normal file
16
funnyassets/gfx_shaders/mesh_raytracer_raygen.slang
Normal 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);
|
||||||
|
|
||||||
|
}
|
||||||
18
funnyassets/gfx_shaders/mesh_raytracer_shared.slang
Normal file
18
funnyassets/gfx_shaders/mesh_raytracer_shared.slang
Normal 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)
|
||||||
25
funnyassets/gfx_shaders/shader_base.slang
Normal file
25
funnyassets/gfx_shaders/shader_base.slang
Normal 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
|
||||||
|
|
||||||
|
|
||||||
@@ -5,35 +5,32 @@
|
|||||||
#include "tier1/commandline.h"
|
#include "tier1/commandline.h"
|
||||||
|
|
||||||
CUtlVector<CUtlString> client_CompiledFiles = {
|
CUtlVector<CUtlString> client_CompiledFiles = {
|
||||||
"game/client/milmoba/player.cpp",
|
|
||||||
"game/client/milmoba/mainmenu.cpp",
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int client_build()
|
DECLARE_BUILD_STAGE(client)
|
||||||
{
|
{
|
||||||
CCProject compileProject = {};
|
CProject_t compileProject = {};
|
||||||
CLDProject ldProject = {};
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
compileProject.m_szName = "client";
|
compileProject.m_szName = "client";
|
||||||
compileProject.files = client_CompiledFiles;
|
compileProject.files = client_CompiledFiles;
|
||||||
compileProject.includeDirectories = all_IncludeDirectories;
|
compileProject.includeDirectories = all_IncludeDirectories;
|
||||||
compileProject.bFPIC = true;
|
compileProject.bFPIC = true;
|
||||||
ldProject = compileProject.Compile();
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
if (bStaticBuild)
|
if (bStaticBuild)
|
||||||
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
||||||
else
|
else
|
||||||
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||||
|
|
||||||
CUtlString outputProject = ldProject.Link();
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
if (!bStaticBuild)
|
if (!bStaticBuild)
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
|
filesystem2->CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
|
||||||
} else {
|
} else {
|
||||||
client_lib = outputProject;
|
client_lib = outputProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(client, client_build);
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "fgui/label.h"
|
#include "fgui/label.h"
|
||||||
#include "fgui/rect.h"
|
#include "fgui/rect.h"
|
||||||
#include "fgui/widget.h"
|
#include "fgui/widget.h"
|
||||||
#include "interface.h"
|
#include "tier1/interface.h"
|
||||||
|
|
||||||
class CMOBAMainMenuGUI: public CFGUI_Widget
|
class CMOBAMainMenuGUI: public CFGUI_Widget
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,31 +9,30 @@ CUtlVector<CUtlString> server_CompiledFiles = {
|
|||||||
"game/server/milmoba/player.cpp",
|
"game/server/milmoba/player.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
int server_build()
|
DECLARE_BUILD_STAGE(server)
|
||||||
{
|
{
|
||||||
CCProject compileProject = {};
|
CProject_t compileProject = {};
|
||||||
CLDProject ldProject = {};
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
compileProject.m_szName = "server";
|
compileProject.m_szName = "server";
|
||||||
compileProject.files = server_CompiledFiles;
|
compileProject.files = server_CompiledFiles;
|
||||||
compileProject.includeDirectories = all_IncludeDirectories;
|
compileProject.includeDirectories = all_IncludeDirectories;
|
||||||
compileProject.bFPIC = true;
|
compileProject.bFPIC = true;
|
||||||
ldProject = compileProject.Compile();
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
if (bStaticBuild)
|
if (bStaticBuild)
|
||||||
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
ldProject.linkType = ELINK_STATIC_LIBRARY;
|
||||||
else
|
else
|
||||||
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
ldProject.linkType = ELINK_DYNAMIC_LIBRARY;
|
||||||
|
|
||||||
CUtlString outputProject = ldProject.Link();
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
|
|
||||||
if (!bStaticBuild)
|
if (!bStaticBuild)
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/funnygame/bin",szOutputDir.GetString()));
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
|
filesystem2->CopyFile(CUtlString("%s/funnygame/bin", szOutputDir.GetString()), outputProject);
|
||||||
} else {
|
} else {
|
||||||
server_lib = outputProject;
|
server_lib = outputProject;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(server, server_build);
|
|
||||||
|
|||||||
@@ -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;
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -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);
|
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ CUtlVector<CUtlString> launcher_CompiledFiles = {
|
|||||||
"launcher/launcher.cpp",
|
"launcher/launcher.cpp",
|
||||||
};
|
};
|
||||||
|
|
||||||
int launcher_build()
|
DECLARE_BUILD_STAGE(launcher)
|
||||||
{
|
{
|
||||||
IFileSystem2::MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
filesystem2->MakeDirectory(CUtlString("%s/bin",szOutputDir.GetString()));
|
||||||
CCProject compileProject = {};
|
CProject_t compileProject = {};
|
||||||
CLDProject ldProject = {};
|
LinkProject_t ldProject = {};
|
||||||
|
|
||||||
compileProject.m_szName = "launcher";
|
compileProject.m_szName = "launcher";
|
||||||
compileProject.files = launcher_CompiledFiles;
|
compileProject.files = launcher_CompiledFiles;
|
||||||
@@ -21,19 +21,18 @@ int launcher_build()
|
|||||||
{
|
{
|
||||||
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
|
compileProject.macros.AppendTail((C_Macro_t){"STATIC_BUILD","1"});
|
||||||
}
|
}
|
||||||
ldProject = compileProject.Compile();
|
ldProject = ccompiler->Compile(&compileProject);
|
||||||
ldProject.linkType = ELINK_EXECUTABLE;
|
ldProject.linkType = ELINK_EXECUTABLE;
|
||||||
CUtlString szBinaryOutput = CUtlString("%s/bin/funnygame", szOutputDir.GetString());
|
CUtlString szBinaryOutput = CUtlString("%s/bin/funnygame", szOutputDir.GetString());
|
||||||
|
|
||||||
if (bStaticBuild)
|
if (bStaticBuild)
|
||||||
{
|
{
|
||||||
ldProject.objects.AppendTail((CObject){tier0_lib});
|
ldProject.objects.AppendTail((Object_t){tier0_lib});
|
||||||
ldProject.objects.AppendTail((CObject){tier1_lib});
|
ldProject.objects.AppendTail((Object_t){tier1_lib});
|
||||||
ldProject.objects.AppendTail((CObject){rapier_lib});
|
ldProject.objects.AppendTail((Object_t){rapier_lib});
|
||||||
ldProject.objects.AppendTail((CObject){engine_lib});
|
ldProject.objects.AppendTail((Object_t){engine_lib});
|
||||||
ldProject.objects.AppendTail((CObject){server_lib});
|
ldProject.objects.AppendTail((Object_t){server_lib});
|
||||||
ldProject.objects.AppendTail((CObject){fgui_lib});
|
ldProject.objects.AppendTail((Object_t){client_lib});
|
||||||
ldProject.objects.AppendTail((CObject){client_lib});
|
|
||||||
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS)
|
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_IOS)
|
||||||
{
|
{
|
||||||
ldProject.frameworks.AppendTail("SDL3");
|
ldProject.frameworks.AppendTail("SDL3");
|
||||||
@@ -45,16 +44,16 @@ int launcher_build()
|
|||||||
ldProject.frameworks.AppendTail("QuartzCore");
|
ldProject.frameworks.AppendTail("QuartzCore");
|
||||||
ldProject.frameworks.AppendTail("UIKit");
|
ldProject.frameworks.AppendTail("UIKit");
|
||||||
ldProject.frameworkDirectories.AppendTail("external/ios");
|
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)
|
if (Target_t::DefaultTarget().kernel == TARGET_KERNEL_WINDOWS)
|
||||||
{
|
{
|
||||||
ldProject.objects.AppendTail((CObject){"external/windows/vulkan-1.dll"});
|
ldProject.objects.AppendTail((Object_t){"external/windows/vulkan-1.dll"});
|
||||||
ldProject.objects.AppendTail((CObject){"external/windows/libSDL3.a"});
|
ldProject.objects.AppendTail((Object_t){"external/windows/libSDL3.a"});
|
||||||
ldProject.objects.AppendTail((CObject){"external/windows/libpthread.a"});
|
ldProject.objects.AppendTail((Object_t){"external/windows/libpthread.a"});
|
||||||
ldProject.objects.AppendTail((CObject){"external/windows/libstdc++.a"});
|
ldProject.objects.AppendTail((Object_t){"external/windows/libstdc++.a"});
|
||||||
if (bSteam)
|
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("ws2_32");
|
||||||
ldProject.libraries.AppendTail("ntdll");
|
ldProject.libraries.AppendTail("ntdll");
|
||||||
ldProject.libraries.AppendTail("userenv");
|
ldProject.libraries.AppendTail("userenv");
|
||||||
@@ -67,15 +66,14 @@ int launcher_build()
|
|||||||
ldProject.libraries.AppendTail("imm32");
|
ldProject.libraries.AppendTail("imm32");
|
||||||
ldProject.libraries.AppendTail("version");
|
ldProject.libraries.AppendTail("version");
|
||||||
ldProject.libraries.AppendTail("oleaut32");
|
ldProject.libraries.AppendTail("oleaut32");
|
||||||
IFileSystem2::CopyFile(CUtlString("%s/bin", szOutputDir.GetString()), "external/windows/libgcc_s_seh-1.dll");
|
filesystem2->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/libwinpthread-1.dll");
|
||||||
szBinaryOutput = CUtlString("%s/bin/funnygame.exe", szOutputDir.GetString());
|
szBinaryOutput = CUtlString("%s/bin/funnygame.exe", szOutputDir.GetString());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CUtlString outputProject = ldProject.Link();
|
CUtlString outputProject = linker->Link(&ldProject);
|
||||||
IFileSystem2::CopyFile(szBinaryOutput, outputProject);
|
filesystem2->CopyFile(szBinaryOutput, outputProject);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
};
|
};
|
||||||
DECLARE_BUILD_STAGE(launcher, launcher_build);
|
|
||||||
|
|||||||
0
materialsystem/vulkan/material.cpp
Normal file
0
materialsystem/vulkan/material.cpp
Normal file
0
materialsystem/vulkan/materialsystem.cpp
Normal file
0
materialsystem/vulkan/materialsystem.cpp
Normal file
0
materialsystem/vulkan/shader.cpp
Normal file
0
materialsystem/vulkan/shader.cpp
Normal file
0
materialsystem/vulkan/vulkan_machine.h
Normal file
0
materialsystem/vulkan/vulkan_machine.h
Normal 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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -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
0
public/cl_dll.h
Normal 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
Reference in New Issue
Block a user