This commit is contained in:
Antoine Pilote
2023-07-09 20:55:58 -04:00
16 changed files with 376 additions and 311 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 KiB

View File

@@ -94,7 +94,7 @@ namespace Nuake {
float needed = half - used;
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)))
if (ImGui::Button(ICON_FA_PLAY, ImVec2(30, 30)) || (Input::IsKeyPressed(GLFW_KEY_F5) && !Engine::IsPlayMode))
{
SceneSnapshot = Engine::GetCurrentScene()->Copy();
Engine::EnterPlayMode();
@@ -102,7 +102,7 @@ namespace Nuake {
ImGui::SameLine();
if (ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(297))
if (ImGui::Button(ICON_FA_STOP, ImVec2(30, 30)) || Input::IsKeyPressed(GLFW_KEY_F8))
{
Engine::ExitPlayMode();
@@ -1248,16 +1248,37 @@ namespace Nuake {
void NewProject()
{
if (Engine::GetProject())
if (Engine::GetProject() && Engine::GetProject()->FileExist())
Engine::GetProject()->Save();
std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
if (selectedProject == "") // Hit cancel
if(!String::EndsWith(selectedProject, ".project"))
selectedProject += ".project";
if (selectedProject.empty()) // Hit cancel
return;
Ref<Project> project = Project::New("Unnamed project", "no description", selectedProject + ".project");
auto backslashSplits = String::Split(selectedProject, '\\');
auto fileName = backslashSplits[backslashSplits.size() - 1];
std::string finalPath = String::Split(selectedProject, '.')[0];
// We need to create a folder
if (const auto& dirPath = finalPath;
!std::filesystem::create_directory(dirPath))
{
// Should we continue?
Logger::Log("Failed creating project directory: " + dirPath);
}
finalPath += "\\" + fileName;
Ref<Project> project = Project::New(String::Split(fileName, '.')[0], "no description", finalPath);
Engine::LoadProject(project);
Engine::LoadScene(Scene::New());
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
}

View File

@@ -9,35 +9,34 @@
#include "src/Rendering/Textures/TextureManager.h"
#include "EditorInterface.h"
const std::string TEMPLATE_SCRIPT_BEGIN = "import \"Nuake:Engine\" for Engine \
import \"Nuake:ScriptableEntity\" for ScriptableEntity \
import \"Nuake:Input\" for Input \
import \"Nuake:Scene\" for Scene \
\
class ";
const std::string TEMPLATE_SCRIPT = R"(import "Nuake:Engine" for Engine
import "Nuake:ScriptableEntity" for ScriptableEntity
import "Nuake:Input" for Input
import "Nuake:Math" for Vector3, Math
import "Nuake:Scene" for Scene
const std::string TEMPLATE_SCRIPT_END = " is ScriptableEntity {\
construct new(){\
_ReloadSpeed = 0.1\
_Intensity = 0.0\
}\
\
init() {\
}\
\
// Updates every frame\
update(ts) {\
\
}\
\
// Updates every tick\
fixedUpdate(ts) {\
\
}\
\
exit() {\
}\
}";
class MyEntityScript is ScriptableEntity {
construct new() {
}
// Called when the scene gets initialized
init() {
// Engine.Log("Hello World!")
}
// Called every update
update(ts) {
}
// Called 90 times per second
fixedUpdate(ts) {
}
// Called on shutdown
exit() {
}
}
)";
#include <src/Rendering/Textures/Material.h>
@@ -212,9 +211,29 @@ namespace Nuake {
FileSystem::BeginWriteFile(path);
FileSystem::WriteLine(jsonData.dump(4));
FileSystem::EndWriteFile();
RefreshFileBrowser();
}
}
if (ImGui::MenuItem("Wren Script"))
{
std::string path = FileDialog::SaveFile("*.wren");
if (!String::EndsWith(path, ".wren"))
{
path += ".wren";
}
if (!path.empty())
{
FileSystem::BeginWriteFile(path);
FileSystem::WriteLine(TEMPLATE_SCRIPT);
FileSystem::EndWriteFile();
RefreshFileBrowser();
}
}
ImGui::EndMenu();
}
@@ -223,6 +242,12 @@ namespace Nuake {
}
void FileSystemUI::RefreshFileBrowser()
{
FileSystem::Scan();
m_CurrentDirectory = FileSystem::RootDirectory;
}
float h = 200;
static float sz1 = 300;
static float sz2 = 300;
@@ -285,8 +310,7 @@ namespace Nuake {
{
if (ImGui::Button("Refresh"))
{
FileSystem::Scan();
m_CurrentDirectory = FileSystem::RootDirectory;
RefreshFileBrowser();
}
ImGui::SameLine();
@@ -322,7 +346,6 @@ namespace Nuake {
ImGui::TableNextColumn();
if (ImGui::Button("..", ImVec2(100, 100)))
m_CurrentDirectory = m_CurrentDirectory->Parent;
ImGui::TableNextColumn();
i++;
}
@@ -330,13 +353,12 @@ namespace Nuake {
{
for (Ref<Directory>& d : m_CurrentDirectory->Directories)
{
DrawDirectory(d);
if (i + 1 % amount != 0)
ImGui::TableNextColumn();
else
ImGui::TableNextRow();
DrawDirectory(d);
i++;
}
}
@@ -345,12 +367,12 @@ namespace Nuake {
{
for (auto f : m_CurrentDirectory->Files)
{
DrawFile(f);
if (i - 1 % amount != 0)
if (i - 1 % amount != 0 || i == 1)
ImGui::TableNextColumn();
else
ImGui::TableNextRow();
DrawFile(f);
i++;
}
}

View File

@@ -26,5 +26,6 @@ namespace Nuake {
void DrawFile(Ref<File> file);
void DrawDirectoryExplorer();
void DrawContextMenu();
void RefreshFileBrowser();
};
}

View File

@@ -3,20 +3,21 @@
#include <src/Vendors/imgui/imgui.h>
#include "../Misc/InterfaceFonts.h"
#include <Engine.h>
#include <src/Core/FileSystem.h>
#include <src/Resource/Project.h>
#include <Engine.h>
#include <src/Core/Logger.h>
#include <src/Rendering/Textures/TextureManager.h>
#include <src/Rendering/Textures/Texture.h>
#include <json/json.hpp>
#include <string>
#include <vector>
#include "EditorInterface.h"
#include "FileSystemUI.h"
#include <future>
namespace Nuake
{
ProjectPreview::ProjectPreview(const std::string& path)
@@ -33,6 +34,16 @@ namespace Nuake
nlohmann::json projectJson = nlohmann::json::parse(projectFile);
Name = projectJson["Name"];
Description = projectJson["Description"];
const std::string projectIconPath = Path + "/../icon.png";
if (FileSystem::FileExists(projectIconPath, true))
{
ProjectIcon = TextureManager::Get()->GetTexture(projectIconPath);
}
else
{
ProjectIcon = TextureManager::Get()->GetTexture("resources/Images/nuake-logo.png");
}
}
else
{
@@ -65,10 +76,14 @@ namespace Nuake
_Projects = std::vector<ProjectPreview>();
ParseRecentFile();
// Load Nuake logo
_NuakeLogo = TextureManager::Get()->GetTexture(NUAKE_LOGO_PATH);
}
void WelcomeWindow::Draw()
{
// Make viewport fullscreen
ImGuiViewport* viewport = ImGui::GetMainViewport();
ImGui::SetNextWindowPos(viewport->GetWorkPos());
ImGui::SetNextWindowSize(viewport->GetWorkSize());
@@ -78,171 +93,23 @@ namespace Nuake
ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(32.0f, 32.0f));
ImGui::Begin("Welcome Screen", 0, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize);
{
// Draw Nuake logo
{
UIFont boldfont = UIFont(Fonts::Title);
std::string text = "Nuake Engine";
auto windowWidth = ImGui::GetWindowSize().x;
auto textWidth = ImGui::CalcTextSize(text.c_str()).x;
ImGui::SetCursorPosX((windowWidth - textWidth) * 0.5f);
ImGui::Text(text.c_str());
const Vector2 logoSize = _NuakeLogo->GetSize();
const ImVec2 imguiSize = ImVec2(logoSize.x, logoSize.y);
ImGui::Image((ImTextureID)_NuakeLogo->GetID(), imguiSize, ImVec2(0, 1), ImVec2(1, 0));
}
// Add padding under logo
ImGui::Dummy(ImVec2(10, 25));
{
UIFont boldfont = UIFont(Fonts::SubTitle);
std::string text = "An IdTech inspired game engine";
auto windowWidth = ImGui::GetWindowSize().x;
auto textWidth = ImGui::CalcTextSize(text.c_str()).x;
ImGui::SetCursorPosX((windowWidth - textWidth) * 0.5f);
ImGui::Text(text.c_str());
}
ImGui::Separator();
{
UIFont boldfont = UIFont(Fonts::SubTitle);
ImGui::Text("Projects recently opened");
ImGui::Text("Open recent");
}
ImVec2 projectsWindowSize = ImGui::GetContentRegionAvail();
projectsWindowSize.x *= 0.6f;
ImGui::BeginChild("Projects", projectsWindowSize, true);
{
const uint32_t itemHeight = 120;
for (uint32_t i = 0; i < std::size(_Projects); i++)
{
ProjectPreview& project = _Projects[i];
float cursorYStart = ImGui::GetCursorPosY();
std::string selectableName = "##" + std::to_string(i);
bool isSelected = SelectedProject == i;
if (ImGui::Selectable(selectableName.c_str(), isSelected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
{
SelectedProject = i;
}
ImGui::SetCursorPosY(cursorYStart);
{
UIFont boldfont = UIFont(Fonts::LargeBold);
ImGui::Text(project.Name.c_str());
}
{
UIFont boldfont = UIFont(Fonts::Bold);
ImGui::Text(project.Description.c_str());
}
ImGui::SetCursorPosY(cursorYStart + itemHeight);
}
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
{
std::string path = FileDialog::OpenFile("*.project");
if (path != "")
{
bool alreadyContainsProject = false;
for (auto& p : _Projects)
{
if (p.Path == path)
alreadyContainsProject = true;
}
if (!alreadyContainsProject)
{
_Projects.push_back(ProjectPreview(path));
}
}
}
}
ImGui::EndChild();
DrawRecentProjectsSection();
ImGui::SameLine();
if (ImGui::BeginChild("Controls", ImGui::GetContentRegionAvail(), true))
{
ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvailWidth(), 58);
if (ImGui::Button("New Project", buttonSize))
{
std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
if (!selectedProject.empty())
{
auto backslashSplits = String::Split(selectedProject, '\\');
auto fileName = backslashSplits[backslashSplits.size() - 1];
std::string finalPath = selectedProject;
if (String::EndsWith(fileName, ".project"))
{
// We need to create a folder
if (const auto& dirPath = selectedProject;
std::filesystem::create_directory(dirPath))
{
// Should we continue?
Logger::Log("Failed creating project directory: " + dirPath);
}
finalPath += "\\" + fileName + ".project";
}
auto project = Project::New(fileName, "no description", finalPath);
Engine::LoadProject(project);
Engine::LoadScene(Scene::New());
project->Save();
auto projectPreview = ProjectPreview();
projectPreview.Name = project->Name;
projectPreview.Description = project->Description;
projectPreview.Path = project->FullPath;
_Projects.push_back(projectPreview);
}
}
ImGui::Separator();
if (SelectedProject != -1)
{
if (ImGui::Button("Load Project", buttonSize))
{
assert(SelectedProject < std::size(_Projects));
using namespace Nuake;
SaveRecentFile();
std::string projectPath = _Projects[SelectedProject].Path;
FileSystem::SetRootDirectory(projectPath + "/../");
auto project = Project::New();
auto projectFileData = FileSystem::ReadFile(projectPath, true);
try
{
project->Deserialize(projectFileData);
project->FullPath = projectPath;
Engine::LoadProject(project);
_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
}
catch (std::exception exception)
{
Logger::Log("Error loading project: " + projectPath, CRITICAL);
Logger::Log(exception.what());
}
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
}
if (ImGui::Button("Remove Project"))
{
_Projects.erase(_Projects.begin() + SelectedProject);
}
}
}
ImGui::EndChild();
DrawRightControls();
}
ImGui::End();
@@ -250,6 +117,171 @@ namespace Nuake
ImGui::PopStyleVar();
}
void WelcomeWindow::DrawRecentProjectsSection()
{
// Recent projects section takes up 80% of the width
ImVec2 projectsWindowSize = ImGui::GetContentRegionAvail();
projectsWindowSize.x *= 0.8f;
ImGui::BeginChild("Projects", projectsWindowSize, true);
{
for (uint32_t i = 0; i < std::size(_Projects); i++)
{
DrawProjectItem(i);
}
const float itemHeight = 120.0f;
if (ImGui::Button("Import an existing project", ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
{
const std::string path = FileDialog::OpenFile("Project file |*.project");
if (path != "" && String::EndsWith(path, ".project"))
{
// Prevent importing the same project twice in the list
bool alreadyContainsProject = false;
for (auto& p : _Projects)
{
if (p.Path == path)
{
alreadyContainsProject = true;
}
}
if (!alreadyContainsProject)
{
_Projects.push_back(ProjectPreview(path));
}
}
}
}
ImGui::EndChild();
}
void WelcomeWindow::DrawProjectItem(const uint32_t itemIndex)
{
const ProjectPreview& project = _Projects[itemIndex];
const uint32_t itemHeight = 120;
const float cursorYStart = ImGui::GetCursorPosY();
const std::string selectableName = "##" + std::to_string(itemIndex);
const bool isSelected = SelectedProject == itemIndex;
if (ImGui::Selectable(selectableName.c_str(), isSelected, ImGuiSelectableFlags_AllowItemOverlap, ImVec2(ImGui::GetContentRegionAvailWidth(), itemHeight)))
{
SelectedProject = itemIndex;
}
const ImVec2 padding = ImVec2(25.0f, 20.0f);
const ImVec2 iconSize = ImVec2(100, 100);
ImGui::SetCursorPos(padding / 2.0 + ImVec2(0, cursorYStart));
ImGui::Image((ImTextureID)project.ProjectIcon->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0));
ImGui::SameLine();
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
ImGui::SetCursorPosY(cursorYStart + padding.y);
{
UIFont boldfont = UIFont(Fonts::LargeBold);
ImGui::Text(project.Name.c_str());
}
ImGui::SetCursorPosY(cursorYStart + padding.y + 35.f);
{
ImGui::SetCursorPosX(padding.x + iconSize.x + padding.x);
UIFont boldfont = UIFont(Fonts::Bold);
ImGui::Text(project.Description.c_str());
}
ImGui::SetCursorPosY(cursorYStart + itemHeight);
}
void WelcomeWindow::DrawRightControls()
{
const float buttonHeight = 58.0f;
ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0));
if (ImGui::BeginChild("Controls", ImGui::GetContentRegionAvail(), false))
{
const ImVec2 buttonSize = ImVec2(ImGui::GetContentRegionAvailWidth(), buttonHeight);
if (ImGui::Button("Create a new project", buttonSize))
{
std::string selectedProject = FileDialog::SaveFile("Project file\0*.project");
if (!selectedProject.empty())
{
if(!String::EndsWith(selectedProject, ".project"))
selectedProject += ".project";
auto backslashSplits = String::Split(selectedProject, '\\');
auto fileName = backslashSplits[backslashSplits.size() - 1];
std::string finalPath = String::Split(selectedProject, '.')[0];
if (String::EndsWith(fileName, ".project"))
{
// We need to create a folder
if (const auto& dirPath = finalPath;
!std::filesystem::create_directory(dirPath))
{
// Should we continue?
Logger::Log("Failed creating project directory: " + dirPath);
}
finalPath += "\\" + fileName;
}
auto project = Project::New(String::Split(fileName, '.')[0], "no description", finalPath);
Engine::LoadProject(project);
Engine::LoadScene(Scene::New());
project->Save();
auto projectPreview = ProjectPreview();
projectPreview.Name = project->Name;
projectPreview.Description = project->Description;
projectPreview.Path = project->FullPath;
_Projects.push_back(projectPreview);
}
}
ImGui::Separator();
if (SelectedProject != -1)
{
if (ImGui::Button("Open an existing Project", buttonSize))
{
assert(SelectedProject < std::size(_Projects));
using namespace Nuake;
SaveRecentFile();
std::string projectPath = _Projects[SelectedProject].Path;
FileSystem::SetRootDirectory(projectPath + "/../");
auto project = Project::New();
auto projectFileData = FileSystem::ReadFile(projectPath, true);
try
{
project->Deserialize(projectFileData);
project->FullPath = projectPath;
Engine::LoadProject(project);
_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory;
}
catch (std::exception exception)
{
Logger::Log("Error loading project: " + projectPath, CRITICAL);
Logger::Log(exception.what());
}
Engine::GetCurrentWindow()->SetTitle("Nuake Engine - Editing " + project->Name);
}
}
}
ImGui::EndChild();
ImGui::PopStyleColor();
}
void WelcomeWindow::ParseRecentFile()
{
if (!FileSystem::FileExists(_RecentProjectFilePath, true))

View File

@@ -1,10 +1,13 @@
#pragma once
#include <src/Resource/Serializable.h>
#include <src/Core/Core.h>
#include <string>
#include <vector>
namespace Nuake
{
class Texture;
class ProjectPreview : ISerializable
{
public:
@@ -12,6 +15,7 @@ namespace Nuake
std::string Path;
std::string Description;
Ref<Texture> ProjectIcon;
ProjectPreview(const std::string& path);
ProjectPreview() = default;
@@ -19,6 +23,7 @@ namespace Nuake
json Serialize() override;
bool Deserialize(const std::string& data) override;
private:
void ReadProjectFile();
};
@@ -27,19 +32,27 @@ namespace Nuake
class WelcomeWindow
{
private:
const std::string NUAKE_LOGO_PATH = "resources/Images/logo_white.png";
Ref<Texture> _NuakeLogo;
EditorInterface* _Editor;
const std::string _RecentProjectFilePath = "recent.json";
const std::string _RecentProjectFileDefaultContent = "{ \"Projects\": [ ] }";
std::vector<ProjectPreview> _Projects;
uint32_t SelectedProject = 0;
EditorInterface* _Editor;
public:
std::vector<ProjectPreview> _Projects;
public:
WelcomeWindow(Nuake::EditorInterface* editor);
~WelcomeWindow() = default;
void Draw();
private:
void DrawRecentProjectsSection();
void DrawProjectItem(const uint32_t projectPreview);
void DrawRightControls();
void ParseRecentFile();
void SaveRecentFile();
};

View File

@@ -12,6 +12,8 @@ using Ref = std::shared_ptr<T>;
template<typename T>
using Scope = std::unique_ptr<T>;
template<typename T>
using Weak = std::weak_ptr<T>;
template<typename T, typename ... Args>
constexpr Ref<T> CreateRef(Args&& ... args)
@@ -23,4 +25,4 @@ template<typename T, typename ... Args>
constexpr Scope<T> CreateScope(Args&& ... args)
{
return std::make_unique<T>(std::forward<Args>(args)...);
}
}

View File

@@ -231,7 +231,8 @@ namespace Nuake
// You should definitely not call this every frame or when e.g. streaming in a new level section as it is an expensive operation.
// Instead insert all new objects in batches instead of 1 at a time to keep the broad phase efficient.
//_JoltPhysicsSystem->OptimizeBroadPhase();
_JoltJobSystem = new JPH::JobSystemThreadPool(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, std::thread::hardware_concurrency() - 1);
const uint32_t availableThreads = std::thread::hardware_concurrency() - 1;
_JoltJobSystem = new JPH::JobSystemThreadPool(JPH::cMaxPhysicsJobs, JPH::cMaxPhysicsBarriers, availableThreads);
}
void DynamicWorld::DrawDebug()
@@ -308,6 +309,7 @@ namespace Nuake
}
assert("Entity doesn't have a character controller component.");
return false;
}
RaycastResult DynamicWorld::Raycast(glm::vec3 from, glm::vec3 to)
@@ -408,11 +410,15 @@ namespace Nuake
// Do 1 collision step per 1 / 60th of a second (round up).
int collisionSteps = 1;
constexpr float minStepDuration = 1.0f / 90.0f;
constexpr int maxStepCount = 4;
if(ts > minStepDuration)
{
collisionSteps = static_cast<float>(ts) / minStepDuration;
}
// Prevents having too many steps and running out of jobs
collisionSteps = std::min(collisionSteps, maxStepCount);
// If you want more accurate step results you can do multiple sub steps within a collision step. Usually you would set this to 1.
constexpr int subSteps = 1;

View File

@@ -163,9 +163,16 @@ namespace Nuake
for (auto& v : j["Vertices"])
{
Vertex vertex;
try {
DESERIALIZE_VEC2(v["UV"], vertex.uv)
}
catch(std::exception& e) {
vertex.uv = { 0.0, 0.0 };
}
DESERIALIZE_VEC3(v["Position"], vertex.position)
DESERIALIZE_VEC3(v["Normal"], vertex.normal)
DESERIALIZE_VEC2(v["UV"], vertex.uv)
DESERIALIZE_VEC3(v["Tangent"], vertex.tangent)
DESERIALIZE_VEC3(v["Bitangent"], vertex.bitangent)

View File

@@ -53,6 +53,11 @@ namespace Nuake
projectFile.close();
}
bool Project::FileExist()
{
return std::filesystem::exists(this->FullPath.c_str());
}
Ref<Project> Project::New(const std::string& Name, const std::string& Description, const std::string& FullPath)
{
return CreateRef<Project>(Name, Description, FullPath);

View File

@@ -26,6 +26,7 @@ namespace Nuake
void Save();
void SaveAs(const std::string& FullPath);
bool FileExist();
static Ref<Project> New(const std::string& Name, const std::string& Description, const std::string& FullPath);
static Ref<Project> New();

View File

@@ -102,17 +102,29 @@ namespace Nuake
json ProceduralSky::Serialize()
{
BEGIN_SERIALIZE()
SERIALIZE_VAL(SurfaceRadius);
SERIALIZE_VAL(SurfaceRadius);
SERIALIZE_VAL(AtmosphereRadius);
SERIALIZE_VEC3(RayleighScattering);
SERIALIZE_VEC3(MieScattering);
SERIALIZE_VAL(SunIntensity);
SERIALIZE_VEC3(SunDirection);
SERIALIZE_VEC3(CenterPoint);
END_SERIALIZE();
}
bool ProceduralSky::Deserialize(const std::string& str)
{
return false;
BEGIN_DESERIALIZE()
DESERIALIZE_VEC3(j["SunDirection"], SunDirection)
DESERIALIZE_VEC3(j["RayleighScattering"], RayleighScattering)
DESERIALIZE_VEC3(j["MieScattering"], MieScattering)
if (j.contains("CenterPoint"))
{
DESERIALIZE_VEC3(j["CenterPoint"], CenterPoint)
}
SurfaceRadius = j["SurfaceRadius"];
AtmosphereRadius = j["AtmosphereRadius"];
SunIntensity = j["SunIntensity"];
return true;
}
}

View File

@@ -68,6 +68,11 @@ namespace Nuake {
VolumetricFog = j["VolumetricFog"];
if (j.contains("VolumetricStepCount"))
VolumetricStepCount = j["VolumetricStepCount"];
if (j.contains("ProceduralSkybox"))
{
ProceduralSkybox->Deserialize(j["ProceduralSkybox"].dump());
}
return false;
}
}

View File

@@ -1,44 +1,47 @@
![Nuake](http://antoinepilote.com/assets/NUAKE.png)
# Nuake
Feel free to join the discord server for updates:
![Nuake](Editor/resources/Images/logo.png)
[![Support Server](https://img.shields.io/discord/852625335236558868.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge)](https://discord.gg/kuF4efPK7Y)
# What is it
Nuake is a game engine written from scratch by myself. It is not meant to be a end-all be-all engine and it is not a quakespasm type engine. This is a game engine that focuses on fast level design iteration that integrates with quake level editing software. If you can create quake maps, you can create Nuake levels.
`Warning: It is still very early in development and I dont recommend anyone using this to make their games *yet*. `
## Quake inspired game engine
Nuake is a game engine currently in developement that focuses on fast level design iteration time that integrates with quake level editing software.
> It is currently in developement and is not feature complete. We are currently aiming for an alpha release with basic features and a demo level.
# How to build
![Nuake](Editor/resources/Images/screenshot.png)
You can join the discord server for updates and screenshots or if you want to contribute:
[![Join Server](https://img.shields.io/discord/852625335236558868.svg?label=Discord&logo=Discord&colorB=7289da&style=for-the-badge)](https://discord.gg/kuF4efPK7Y)
## Current Features
- ECS system
- Modern physic engine (Jolt physic)
- PBR Renderer
- Post processing effects(Bloom, SSAO, SSR, Volumetrics, Procedural Sky)
- Wren Scripting
- Trenchbroom integration
## Planned features
- C# Scripting
- Custom Shaders
- Spatialized audio
- NuakeUI integration
- Dynamic global illumination
- Asset packing
- Terrain editor
- WAD converter
## Contributing
We are currently looking for contributors, feel free to join the discord if you are looking to help the project.
## Compiling the engine
1. Clone the repos using `git clone --recurse-submodules https://github.com/antopilo/Nuake.git`
2. Run the `generate.bat` to generate the sln files.
3. Open `Nuake.sln`
4. Build and run
# Contributing
Feel free to make pull requests and I will look over them myself.
# Documentation and demos
> The current documentation is not up to date.
# Documentation
You can access the current documentation at [here](https://nuake.readthedocs.io/en/latest/index.html)
You can access the current documentation [here](https://nuake.readthedocs.io/en/latest/index.html).
# Features
- Trenchbroom integration with live reload
- fast ECS & Scene tree system
- Jolt physics
- PBR rendering
- Volumetric lighting
- Parallax mapping
- Game in editor
- Procedural & HDR skies
- Modern UI system
- Wren scripting api and module system
- Triggers and entity editing in TB
# Planned
- Advanced physics features
- Soft bodies, Joints, etc.
- Demo level
- Cross platform
- Optimization
- Water simulation
- Terrain editing
- Exporting
- Custom shaders

View File

@@ -1,65 +0,0 @@
version(1);
project_name = "4coder custom";
patterns = {
"*.c",
"*.cpp",
"*.h",
"*.m",
"*.mm",
"*.bat",
"*.sh",
"*.4coder",
"*.txt",
};
blacklist_patterns = {
".*",
};
load_paths_custom = {
{"."},
};
load_paths = {
{ load_paths_custom, .os = "win" },
{ load_paths_custom, .os = "linux"},
{ load_paths_custom, .os = "mac" },
};
build_super_x64_win32 = "custom\\bin\\buildsuper_x64-win.bat";
build_super_x86_win32 = "custom\\bin\\buildsuper_x86-win.bat";
build_super_x64_linux = "custom/bin/buildsuper_x64-linux.sh";
build_super_x86_linux = "custom/bin/buildsuper_x86-linux.sh";
build_super_x64_mac = "custom/bin/buildsuper_x64-mac.sh";
command_list = {
{ .name = "build super x64",
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
.cmd = { {build_super_x64_win32, .os ="win" },
{build_super_x64_linux , .os ="linux"},
{build_super_x64_mac , .os ="mac" }, }, },
{ .name = "build super x86",
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
.cmd = { {build_super_x86_win32, .os ="win" },
{build_super_x86_linux, .os ="linux" }, }, },
{ .name = "build C++ lexer generator",
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
.cmd = { {"custom\\bin\\build_one_time custom\\languages\\4coder_cpp_lexer_gen.cpp ..\\build", .os ="win" },
}, },
{ .name = "build token tester",
.out = "*compilation*", .footer_panel = true, .save_dirty_files = true,
.cmd = { {"custom\\bin\\build_one_time custom\\languages\\4coder_cpp_lexer_test.cpp ..\\build", .os = "win" },
}, },
{ .name = "run one time",
.out = "*run*", .footer_panel = false, .save_dirty_files = false,
.cmd = { {"pushd ..\\build & one_time", .os = "win" },
}, },
};
fkey_command[1] = "build super x64";
fkey_command[2] = "build C++ lexer generator";
fkey_command[3] = "build token tester";
fkey_command[4] = "run one time";
fkey_command[5] = "build super x86";