Commit 5dca3e4f authored by Johannes Braun's avatar Johannes Braun
Browse files

Add drag+drop for render layers and improve item naming

parent e19e9e0a
......@@ -6,18 +6,26 @@
namespace dino
{
std::vector<const char*> materialNames = {"No Texture",
"Checker Board (p)",
"Grid (p)",
"Squares (p)",
"Crosses (p)",
"Flower Noise (p)",
"Wood (p)",
"Voronoi (p)",
"Cube Map",
"Hatch",
"Stippling"};
int materialID = 0;
constexpr const char* materialNames[] = {"No Texture",
"Checker Board (procedural)",
"Grid (procedural)",
"Squares (procedural)",
"Crosses (procedural)",
"Flower Noise (procedural)",
"Wood (procedural)",
"Voronoi (procedural)",
"Cube Map",
"Hatch",
"Stippling"};
constexpr const char* layerNames[] = {
"RENDERLAYER_NONE ", "Normals ", "Trace Distance ", "Object ID ",
"Step Count ", "Min Distance ", "Gradient (x) ", "Gradient (y) ",
"Material Color ", "Ambient Lighting ", "Diffuse Lighting ", "GGX Shading ",
"Ambient Occlusion ", "Shadow Mapping ", "Soft Shadows ", "Skybox ",
"Skybox Reflections", "Silhouette ", "Tone Mapping ", "FXAA "};
int materialID = 0;
Editor::Editor(std::shared_ptr<Window> window, std::shared_ptr<dino::Renderer> renderer)
: m_window(std::move(window))
......@@ -36,6 +44,18 @@ Editor::Editor(std::shared_ptr<Window> window, std::shared_ptr<dino::Renderer> r
});
glfwMakeContextCurrent(*m_window);
updateFromRenderer();
int w, h;
glfwGetFramebufferSize(*m_window, &w, &h);
m_previewFramebuffer = std::make_unique<dino::FrameBuffer>();
m_previewTexture = std::make_shared<dino::Texture>(GL_TEXTURE_2D, GL_RGBA8, glm::ivec2{w, h});
m_previewFramebuffer->addColorAttachment(0, m_previewTexture);
prepareTextures();
}
void Editor::updateFromRenderer()
{
const auto oldFields = m_renderer->packFunctions();
for(const auto& field : oldFields)
{
......@@ -47,12 +67,18 @@ Editor::Editor(std::shared_ptr<Window> window, std::shared_ptr<dino::Renderer> r
for(const auto& p : m_renderer->getLights())
m_allLightIds.push_back(p.first);
int w, h;
glfwGetFramebufferSize(*m_window, &w, &h);
m_previewFramebuffer = std::make_unique<dino::FrameBuffer>();
m_previewTexture = std::make_shared<dino::Texture>(GL_TEXTURE_2D, GL_RGBA8, glm::ivec2{w, h});
m_previewFramebuffer->addColorAttachment(0, m_previewTexture);
prepareTextures();
int erased = 0;
m_inactiveRenderLayers.resize(std::size(layerNames));
std::iota(m_inactiveRenderLayers.begin(), m_inactiveRenderLayers.end(), 0u);
for(int i = 0; i < m_renderer->getRenderLayers().size(); ++i)
{
const auto id = static_cast<uint32_t>(m_renderer->getRenderLayers()[i]->getType());
ActiveLayerInfo& info = m_activeRenderLayers.emplace_back();
info.indexInRenderer = i;
info.layerIndex = id;
m_inactiveRenderLayers.erase(m_inactiveRenderLayers.begin() + (id - erased));
++erased;
}
}
void Editor::loadField(const std::filesystem::path path)
......@@ -288,7 +314,7 @@ void Editor::drawFieldsTab()
auto mat = m_renderer->getMaterials().at(*m_allFieldIds[*m_activeFieldIndex]);
if(ImGui::BeginCombo(" ", materialNames[mat->getTextureType()]))
{
for(int i = 0; i < materialNames.size(); i++)
for(int i = 0; i < std::size(materialNames); i++)
{
if(ImGui::Selectable(materialNames[i], materialID == i))
{
......@@ -681,71 +707,186 @@ void Editor::drawLightsTab()
void Editor::drawRenderingTab()
{
const static std::vector<const char*> layerNames = {
"RENDERLAYER_NONE ", "NORMALS ", "TRACE_T ", "OBJECT_ID ",
"STEP_COUNT ", "MIN_DISTANCE ", "GRADIENT_X ", "GRADIENT_Y ",
"MATERIAL_COLOR ", "AMBIENT_LIGHTING ", "DIFFUSE_LIGHTING ", "GGX_LIGHTING ",
"AMBIENT_OCCLUSION ", "SHADOW_MAPPING ", "SOFT_SHADOWS ", "SKYBOX ",
"SKYBOX_REFLECTIONS", "SILHOUETTE ", "TONE_MAPPING ", "FXAA "};
std::vector<const char*> activeLayers;
for(const auto& rl : m_renderer->getRenderLayers())
ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));
ImGui::BeginHorizontal("Koffein", ImVec2(ImGui::GetContentRegionAvailWidth(), 0));
if(ImGui::Button(ICON_MDI_PLUS " Add"))
{
activeLayers.push_back(layerNames[static_cast<int>(rl->getType())]);
ImGui::OpenPopup("Add Layer");
}
if(ImGui::BeginCombo("##addrenderlayer", "Add Render Layer"))
if(ImGui::BeginPopup("Add Layer"))
{
for(size_t i = 0; i < layerNames.size(); i++)
for(auto it = m_inactiveRenderLayers.begin(); it != m_inactiveRenderLayers.end(); ++it)
{
auto layerType = static_cast<dino::RenderLayer::Type>(i);
bool foundRenderLayer = false;
for(auto& rl : m_renderer->getRenderLayers())
{
if(rl->getType() == layerType)
{
foundRenderLayer = true;
break;
}
}
if(!foundRenderLayer && ImGui::Selectable(layerNames[i]))
if(ImGui::Selectable(layerNames[*it]))
{
m_renderer->addRenderLayer(layerType);
m_activeRenderLayers.insert(
std::prev(m_activeRenderLayers.end()),
ActiveLayerInfo{*it,
m_renderer->addRenderLayer(
static_cast<dino::RenderLayer::Type>(*it))});
it = m_inactiveRenderLayers.erase(it);
ImGui::CloseCurrentPopup();
break;
}
}
ImGui::EndCombo();
ImGui::EndPopup();
}
ImGui::Spring();
ImGui::EndHorizontal();
// Render + dragging
for(int n = 0; n < m_renderer->getRenderLayers().size(); n++)
for(auto it = m_activeRenderLayers.begin(); it != m_activeRenderLayers.end();)
{
if(m_renderer->getRenderLayers()[n]->getType() != dino::RenderLayer::SILHOUETTE)
const ActiveLayerInfo& info = *it;
bool doIncrement = true;
const bool canDelete = static_cast<dino::RenderLayer::Type>(info.layerIndex) !=
dino::RenderLayer::SILHOUETTE;
const bool canMoveBackward = info.indexInRenderer && it > m_activeRenderLayers.begin() && canDelete;
const bool canMoveForward =
info.indexInRenderer && (m_activeRenderLayers.size() != 1 &&
it < std::prev(std::prev(m_activeRenderLayers.end())) && canDelete);
if(!canDelete)
{
if(ImGui::Button((std::string(ICON_MDI_DELETE "##") + std::to_string(n)).c_str()))
{
m_renderer->removeRenderLayer(n);
}
ImGui::SameLine();
if(ImGui::Button(
(std::string(ICON_MDI_ARROW_UP_BOLD "##") + std::to_string(n)).c_str()) &&
n > 0)
{
m_renderer->swapLayers(n, n - 1);
}
ImGui::SameLine();
if(ImGui::Button(
(std::string(ICON_MDI_ARROW_DOWN_BOLD "##") + std::to_string(n)).c_str()) &&
n < m_renderer->getRenderLayers().size() - 1)
{
m_renderer->swapLayers(n, n + 1);
}
ImGui::SameLine();
ImGui::Selectable(activeLayers[n]);
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.2f);
}
if(ImGui::Button(
(std::string(ICON_MDI_DELETE "##") + std::to_string(info.layerIndex)).c_str()) &&
canDelete)
{
if(info.indexInRenderer)
m_renderer->removeRenderLayer(*info.indexInRenderer);
const auto id = it->indexInRenderer ? *it->indexInRenderer : std::numeric_limits<uint32_t>::max();
it = m_activeRenderLayers.erase(it);
for (auto& rl : m_activeRenderLayers)
if (rl.indexInRenderer && *rl.indexInRenderer > id)
--*rl.indexInRenderer;
doIncrement = false;
}
if(!canDelete)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
ImGui::SameLine();
if(!canMoveBackward)
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.2f);
}
if(ImGui::Button(
(std::string(ICON_MDI_ARROW_UP_BOLD "##") + std::to_string(info.layerIndex))
.c_str()) &&
canMoveBackward)
{
m_renderer->swapLayers(*info.indexInRenderer, *info.indexInRenderer - 1);
std::swap(it->indexInRenderer, std::prev(it)->indexInRenderer);
std::iter_swap(it, std::prev(it));
}
if(!canMoveBackward)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
ImGui::SameLine();
if(!canMoveForward)
{
ImGui::PushItemFlag(ImGuiItemFlags_Disabled, true);
ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0.2f);
}
if(ImGui::Button(
(std::string(ICON_MDI_ARROW_DOWN_BOLD "##") + std::to_string(info.layerIndex))
.c_str()) &&
canMoveForward)
{
m_renderer->swapLayers(*info.indexInRenderer, *info.indexInRenderer + 1);
std::swap(it->indexInRenderer, std::next(it)->indexInRenderer);
std::iter_swap(it, std::next(it));
}
if(!canMoveForward)
{
ImGui::PopItemFlag();
ImGui::PopStyleVar();
}
const float btnHeight = ImGui::GetItemsLineHeightWithSpacing();
ImGui::SameLine();
ImGui::Selectable(layerNames[info.layerIndex]);
if((canMoveBackward || canMoveForward) && ImGui::IsItemHovered() && !m_layerDragState.dragging)
{
if (glfwGetMouseButton(*m_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS)
{
m_layerDragState.dragging = true;
m_layerDragState.draggedLayer = std::distance(m_activeRenderLayers.begin(), it);
m_layerDragState.lastItemDelta = 0;
m_layerDragState.dragStart = ImGui::GetMousePos();
m_layerDragState.itemHeight = btnHeight;
m_layerDragState.ydelta = m_layerDragState.dragStart.y - ImGui::GetItemRectMin().y;
}
}
if(doIncrement)
++it;
}
if (m_layerDragState.dragging)
{
const float delta = ImGui::GetMousePos().y - m_layerDragState.dragStart.y;
const int deltaItem = std::clamp<int>(m_layerDragState.draggedLayer + static_cast<int>(delta / m_layerDragState.itemHeight), 0, m_renderer->getRenderLayers().size() - 2) - m_layerDragState.draggedLayer;
std::cout << deltaItem << '\n';
if (m_layerDragState.lastItemDelta != deltaItem)
{
auto startItRot = m_activeRenderLayers.begin() + (m_layerDragState.draggedLayer + m_layerDragState.lastItemDelta);
auto endItRot = m_activeRenderLayers.begin() + (m_layerDragState.draggedLayer + deltaItem);
while (startItRot != endItRot)
{
if (startItRot > endItRot)
{
std::iter_swap(startItRot, std::prev(startItRot));
startItRot = std::prev(startItRot);
}
else
{
std::iter_swap(startItRot, std::next(startItRot));
startItRot = std::next(startItRot);
}
}
m_layerDragState.lastItemDelta = deltaItem;
}
if (glfwGetMouseButton(*m_window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_RELEASE)
{
auto startIt = m_activeRenderLayers.begin() + m_layerDragState.draggedLayer;
auto endIt = m_activeRenderLayers.begin() + (m_layerDragState.draggedLayer + deltaItem);
// Fix position;
int offset = 0;
while (startIt != endIt)
{
if (startIt > endIt)
{
std::swap(endIt->indexInRenderer, std::next(endIt)->indexInRenderer);
m_renderer->swapLayers(m_layerDragState.draggedLayer - offset, m_layerDragState.draggedLayer - offset - 1);
endIt = std::next(endIt);
}
else
{
std::swap(endIt->indexInRenderer, std::prev(endIt)->indexInRenderer);
m_renderer->swapLayers(m_layerDragState.draggedLayer + offset, m_layerDragState.draggedLayer + offset + 1);
endIt = std::prev(endIt);
}
++offset;
}
m_layerDragState.dragging = false;
m_layerDragState.draggedLayer = 0;
m_layerDragState.dragStart = ImVec2(0, 0);
m_layerDragState.itemHeight = 0;
}
}
ImGui::PopStyleColor();
}
void Editor::drawPreview()
......
......@@ -51,13 +51,14 @@ public:
void drawSettings();
void drawBlueprint();
void select(std::optional<uint32_t> id, bool showBlueprint, bool deselectOther = true);
void updateFromRenderer();
private:
void drawFieldsTab();
void drawLightsTab();
void drawRenderingTab();
void drawPreview();
void drawMenuBar();
void drawMenuBar();
void drawTimer();
void processInputsEditor();
void processInputsMain();
......@@ -74,6 +75,22 @@ private:
bool editorShown() const;
struct ActiveLayerInfo
{
uint32_t layerIndex;
std::optional<uint32_t> indexInRenderer;
};
struct DragState
{
bool dragging = false;
uint32_t draggedLayer = 0;
uint32_t lastItemDelta = 0;
float ydelta = 0;
ImVec2 dragStart = ImVec2(0, 0);
float itemHeight = 0;
};
void prepareTextures();
const dino::Texture* m_stipplingTexture;
const dino::Texture* m_hatchingTexture;
......@@ -101,6 +118,10 @@ private:
std::vector<uint32_t> m_allLightIds;
std::optional<uint32_t> m_activeFieldIndex = std::nullopt;
std::optional<uint32_t> m_activeLightIndex = std::nullopt;
DragState m_layerDragState;
std::vector<ActiveLayerInfo> m_activeRenderLayers;
std::vector<uint32_t> m_inactiveRenderLayers;
std::vector<std::unique_ptr<Blueprints>> m_blueprints;
KeyboardButton m_ctrlC = KeyboardButton(GLFW_KEY_C, GLFW_KEY_LEFT_CONTROL);
KeyboardButton m_ctrlV = KeyboardButton(GLFW_KEY_V, GLFW_KEY_LEFT_CONTROL);
......
......@@ -3,8 +3,6 @@
namespace dino
{
Renderer::Renderer(const Shader::ShaderSource& onTrace)
: m_onTrace(onTrace)
{
......@@ -640,17 +638,15 @@ void Renderer::setFramebufferSize(glm::ivec2 size)
}
}
void Renderer::addRenderLayer(RenderLayer::Type type)
uint32_t Renderer::addRenderLayer(RenderLayer::Type type)
{
m_renderLayers.insert(m_renderLayers.begin() + m_renderLayers.size() - 1,
std::make_shared<RenderLayer>(type));
m_deferredPrograms.insert(m_deferredPrograms.begin() + m_deferredPrograms.size() - 1,
Program());
m_renderLayers.insert(std::prev(m_renderLayers.end()), std::make_shared<RenderLayer>(type));
m_deferredPrograms.insert(std::prev(m_deferredPrograms.end()), Program());
m_deferredPrograms[m_deferredPrograms.size() - 2].attachNew(
GL_VERTEX_SHADER, dino::ShaderFile::load("screenFilling.vert"));
m_invalidRenderables = true;
return m_renderLayers.size() - 2;
}
void Renderer::removeRenderLayer(int layerIndex)
......@@ -668,7 +664,7 @@ void Renderer::swapLayers(int firstIndex, int secondIndex)
std::swap(m_deferredPrograms[firstIndex], m_deferredPrograms[secondIndex]);
}
std::vector<std::shared_ptr<RenderLayer>> Renderer::getRenderLayers() const
const std::vector<std::shared_ptr<RenderLayer>>& Renderer::getRenderLayers() const
{
return m_renderLayers;
}
......
......@@ -271,13 +271,13 @@ public:
/**
* @brief Returns a list with all attached render layers
*/
std::vector<std::shared_ptr<RenderLayer>> getRenderLayers() const;
const std::vector<std::shared_ptr<RenderLayer>>& getRenderLayers() const;
/**
* @brief Adds a new render layer to the list of render layers
* @param type The type of the render layer that is added
*/
void addRenderLayer(RenderLayer::Type type);
uint32_t addRenderLayer(RenderLayer::Type type);
/**
* @brief Removes a specific render layer from the list of render layers
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment