#include "NewProjectWindow.h" #include "imgui/imgui.h" #include "../Misc/InterfaceFonts.h" #include #include #include #include #include #include "Nuake/FileSystem/FileSystem.h" #include #include #include #include #include "EditorInterface.h" #include "FileSystemUI.h" namespace Nuake { NewProjectWindow::NewProjectWindow(EditorInterface* editor) : m_Editor(editor) { } void NewProjectWindow::Draw() { ImGuiViewport* viewport = ImGui::GetMainViewport(); ImGui::SetNextWindowPos(viewport->Pos); ImGui::SetNextWindowSize(viewport->Size); ImGui::SetNextWindowViewport(viewport->ID); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0.0f); ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, ImVec2(32.0f, 32.0f)); if (ImGui::Begin("NewProjectScreen", 0, ImGuiWindowFlags_NoDecoration | ImGuiWindowFlags_NoResize)) { { ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 16.0f); bool opened = ImGui::BeginChild("TemplatesView", ImVec2(ImGui::GetContentRegionAvail().x * 0.5f, ImGui::GetContentRegionAvail().y), false, ImGuiChildFlags_AlwaysUseWindowPadding); if (opened) { ImGui::PopStyleVar(); UIFont boldFont(Fonts::SubTitle); ImGui::Text("Templates"); ImGui::Dummy(ImVec2(32, 16)); } if (!opened) { ImGui::PopStyleVar(); } ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0.1f, 0.1f, 0.1f, 0.2f)); ImGui::BeginChild("TemplateContainer", { ImGui::GetContentRegionAvail().x - 64.0f, ImGui::GetContentRegionAvail().y }, true, ImGuiChildFlags_AlwaysUseWindowPadding); { ImGui::Dummy({ 4, 4 }); DrawProjectTemplate(0, "Minimal", "The bare minimum required to get started in Nuake."); ImGui::Dummy({ 4, 2 }); DrawProjectTemplate(1, "Shooter", "A Simple first person shooter game."); ImGui::Dummy({ 4, 2 }); DrawProjectTemplate(2, "Demo", "The Nuake demo project."); } ImGui::EndChild(); ImGui::PopStyleColor(); ImGui::EndChild(); ImGui::PopStyleColor(); } ImGui::SameLine(); { ImGui::PushStyleColor(ImGuiCol_ChildBg, ImVec4(0, 0, 0, 0)); ImGui::PushStyleVar(ImGuiStyleVar_ChildRounding, 16.0f); bool opened = ImGui::BeginChild("ProjectSetupView", ImVec2(ImGui::GetContentRegionAvail().x, ImGui::GetContentRegionAvail().y), false); if (opened) { ImGui::PopStyleVar(); { UIFont boldFont(Fonts::SubTitle); ImGui::Text("Project Setup"); } ImGui::Dummy(ImVec2(32, 16)); static std::string projectTitle = ""; static bool showTitleEmptyWarning = false; static bool showPathWarning = false; ImGui::Text("Title"); if (showTitleEmptyWarning && projectTitle.empty()) { ImGui::SameLine(); ImGui::TextColored({ 1.0f, 0.1f, 0.1f, 1.0f }, ICON_FA_EXCLAMATION_TRIANGLE); Nuake::UI::Tooltip("Title required"); } ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputText("##ProjectTitle", &projectTitle); ImGui::Dummy(ImVec2(32, 16)); ImGui::Text("Description"); ImGui::TextColored(ImVec4(1, 1, 1, 0.4), "A description for your new project"); static std::string description = ""; ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x); ImGui::InputText("##ProjectDescription", &description); ImGui::Dummy(ImVec2(32, 16)); ImGui::Text("Location"); static std::string location = ""; static bool isPathValid = Nuake::FileSystem::DirectoryExists(location, true); if ((showPathWarning && location.empty()) || (!location.empty() && !Nuake::FileSystem::DirectoryExists(location, true))) { ImGui::SameLine(); ImGui::TextColored({ 1.0, 0.1, 0.1, 1.0 }, ICON_FA_EXCLAMATION_TRIANGLE); if (location.empty()) { Nuake::UI::Tooltip("Path required"); } else if (!isPathValid) { Nuake::UI::Tooltip("Path doesn't exist"); } } ImGui::TextColored(ImVec4(1, 1, 1, 0.4), "A folder in which to create your new project"); std::string finalLocation = ""; static std::string projectFileName = ""; ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x - 40.0f); ImGui::InputText("##Location", &location); ImGui::SameLine(); if (ImGui::Button((ICON_FA_FOLDER + std::string("##folderOpen")).c_str())) { std::string folderPath = Nuake::FileDialog::OpenFolder(); folderPath = Nuake::String::ReplaceSlash(folderPath); if (!folderPath.empty()) { auto splits = Nuake::String::Split(folderPath, '/'); location = ""; for (int i = 0; i < splits.size(); i++) { location += splits[i] + "/"; } } } projectFileName = Nuake::String::RemoveWhiteSpace(projectTitle) + ".project"; finalLocation = location; static std::string projectParentPath = location; projectParentPath = location; static bool placeInFolder = false; if (placeInFolder) { projectParentPath += projectTitle + "/"; } finalLocation = projectParentPath + projectFileName; if (!location.empty()) { ImGui::TextColored(ImVec4(1, 1, 1, 0.4), "Project will be created at under:"); ImGui::TextColored(ImVec4(1, 1, 1, 0.4), (finalLocation).c_str()); } ImGui::Dummy(ImVec2(32, 16)); ImGui::Text("Other"); ImGui::Checkbox("Place in empty folder", &placeInFolder); static bool generateCsharpProject = true; ImGui::Checkbox("Generate C# project", &generateCsharpProject); static ImVec4 primaryColor = { 97.0f / 255.0f, 0.0f, 1.0f, 1.0f}; ImGui::PushStyleVar(ImGuiStyleVar_WindowPadding, { 8, 8 }); ImGui::ColorEdit3("Accent color", &primaryColor.x, ImGuiColorEditFlags_NoInputs); ImGui::PopStyleVar(); ImGui::Dummy({ 1, ImGui::GetContentRegionAvail().y - 42 }); ImGui::Dummy({ ImGui::GetContentRegionAvail().x - 230 - 16, 38}); ImGui::SameLine(); if (Nuake::UI::SecondaryButton("Cancel", { 100, 38 })) { m_Editor->isCreatingNewProject = false; } ImGui::SameLine(); if (Nuake::UI::PrimaryButton((ICON_FA_PLUS + std::string(" Create")).c_str(), Nuake::Vector2{ 120, 38 }, Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w))) { if (projectTitle.empty()) { showTitleEmptyWarning = true; } else { showTitleEmptyWarning = false; } if (location.empty()) { showPathWarning = true; } else if (Nuake::FileSystem::DirectoryExists(location, true)) { showPathWarning = false; } if (!showTitleEmptyWarning && !showPathWarning) { // Create project if (Nuake::String::EndsWith(finalLocation, ".project")) { // We need to create a folder if (const auto& dirPath = projectParentPath; !std::filesystem::create_directory(dirPath)) { // Should we continue? Nuake::Logger::Log("Failed creating project directory: " + dirPath); } } Nuake::FileSystem::SetRootDirectory(projectParentPath); auto project = Nuake::Project::New(projectTitle, description, finalLocation); Nuake::Engine::LoadProject(project); Nuake::Engine::SetCurrentScene(Nuake::Scene::New()); project->Settings.PrimaryColor = Nuake::Color(primaryColor.x, primaryColor.y, primaryColor.z, primaryColor.w); project->Save(); auto window = Nuake::Window::Get(); window->SetDecorated(true); window->Maximize(); m_Editor->filesystem->m_CurrentDirectory = Nuake::FileSystem::RootDirectory; m_Editor->isNewProject = true; m_HasCreatedProject = true; } } } if (!opened) { ImGui::PopStyleVar(); } ImGui::EndChild(); ImGui::PopStyleColor(); } ImGui::End(); } ImGui::PopStyleVar(2); } bool opened = true; void NewProjectWindow::DrawProjectTemplate(uint32_t i, const std::string& title, const std::string& description) { opened = true; ImGui::Dummy({ 4, 4 }); ImGui::SameLine(); opened = true; const uint32_t itemHeight = 50; const float cursorYStart = ImGui::GetCursorPosY(); const std::string selectableName = "##" + title; const bool isSelected = m_SelectedTemplate == i; //ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(10.0f / 255.f, 182.0f / 255.f, 255.f / 255.f, 1.0f)); ImDrawList* draw_list = ImGui::GetWindowDrawList(); draw_list->ChannelsSplit(2); // Channel number is like z-order. Widgets in higher channels are rendered above widgets in lower channels. draw_list->ChannelsSetCurrent(1); ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 8.0f); ImGui::PushStyleColor(ImGuiCol_Header, ImVec4(0.25, 0.25, 0.5, 0.0)); ImGui::PushStyleColor(ImGuiCol_HeaderActive, ImVec4(0.25, 0.25, 0.5, 0.0)); ImGui::PushStyleColor(ImGuiCol_HeaderHovered, ImVec4(0.25, 0.25, 0.5, 0.0)); bool result = ImGui::Selectable(selectableName.c_str(), m_SelectedTemplate == i, ImGuiSelectableFlags_AllowOverlap | ImGuiSelectableFlags_AllowDoubleClick, ImVec2(ImGui::GetContentRegionAvail().x - 12, itemHeight)); ImGui::PopStyleVar(); if (result) { m_SelectedTemplate == i; } ImU32 color = IM_COL32(63, 63, 66, 128); if (isSelected) { color = IM_COL32(63, 69, 79, 255); } else if (ImGui::IsItemHovered()) { color = IM_COL32(20, 20, 20, 128); } draw_list->ChannelsSetCurrent(0); ImVec2 p_min = ImGui::GetItemRectMin(); ImVec2 p_max = ImGui::GetItemRectMax(); ImGui::GetWindowDrawList()->AddRectFilled(p_min, p_max, color, 4.0f); draw_list->ChannelsMerge(); ImGui::PopStyleColor(3); if (result) { m_SelectedTemplate = i; } //ImGui::PopStyleColor(); const ImVec2 padding = ImVec2(16.0f, 0.0f); const ImVec2 iconSize = ImVec2(50, 50.0f); ImGui::SetCursorPos(ImVec2(padding.x / 2.0, padding.y / 2.0) + ImVec2(4, cursorYStart)); //ImGui::Image((void*)Nuake::TextureManager::Get()->GetTexture("Resources/Images/cube.png")->GetID(), iconSize, ImVec2(0, 1), ImVec2(1, 0)); ImGui::SameLine(); ImGui::SetCursorPosX(padding.x + iconSize.x); ImGui::SetCursorPosY(cursorYStart + 8.0f); { UIFont boldfont = UIFont(Fonts::Normal); if (isSelected) { ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), title.c_str()); } else { ImGui::Text(title.c_str()); } } ImGui::SetCursorPosY(cursorYStart + 28.f); { ImGui::SetCursorPosX(padding.x + iconSize.x); UIFont boldfont = UIFont(Fonts::Normal); if (isSelected) { ImGui::TextColored(ImVec4(119.0f / 255.0f, 187.0f / 255.0f, 1, 255.0f), (ICON_FA_INFO_CIRCLE + std::string(" ") + description).c_str()); } else { ImGui::TextColored(ImVec4(1, 1, 1, 0.4), (ICON_FA_INFO_CIRCLE + std::string(" ") + description).c_str()); } } ImGui::SetCursorPosY(cursorYStart + itemHeight + 4.0f); } }