diff --git a/radiant/xyview/XYRenderer.h b/radiant/xyview/XYRenderer.h index 066363e37d..9ae77a5437 100644 --- a/radiant/xyview/XYRenderer.h +++ b/radiant/xyview/XYRenderer.h @@ -1,6 +1,7 @@ #pragma once #include "irenderable.h" +#include "imap.h" /// RenderableCollector implementation for the ortho view class XYRenderer: public RenderableCollector @@ -27,13 +28,19 @@ class XYRenderer: public RenderableCollector Shader* _selectedShader; Shader* _selectedShaderGroup; Shader* _mergeActionShader; + Shader* _nonMergeActionNodeShader; + + IMap::EditMode _editMode; public: - XYRenderer(RenderStateFlags globalstate, Shader* selected, Shader* selectedGroup, Shader* mergeActionShader) : + XYRenderer(RenderStateFlags globalstate, Shader* selected, Shader* selectedGroup, + Shader* mergeActionShader, Shader* nonMergeActionNodeShader) : _globalstate(globalstate), _selectedShader(selected), _selectedShaderGroup(selectedGroup), - _mergeActionShader(mergeActionShader) + _mergeActionShader(mergeActionShader), + _nonMergeActionNodeShader(nonMergeActionNodeShader), + _editMode(GlobalMapModule().getEditMode()) {} bool supportsFullMaterials() const override @@ -68,17 +75,33 @@ class XYRenderer: public RenderableCollector const LitObject* /* litObject */, const IRenderEntity* entity = nullptr) override { - if (_state.highlightAsMergeAction) + if (_editMode == IMap::EditMode::Merge) { - _mergeActionShader->addRenderable(renderable, localToWorld, nullptr, entity); + if (_state.highlightAsMergeAction) + { + // Merge actions get rendered in a special colour + _mergeActionShader->addRenderable(renderable, localToWorld, nullptr, entity); + } + else + { + // Everything else is using the shader for non-merge-affected nodes + _nonMergeActionNodeShader->addRenderable(renderable, localToWorld, nullptr, entity); + } + + return; } - else if (_state.highlightPrimitives) + + // Regular editing mode, add all highlighted nodes to the corresponding shader + if (_state.highlightPrimitives) { if (_state.highlightAsGroupMember) - _selectedShaderGroup->addRenderable(renderable, localToWorld, - nullptr, entity); + { + _selectedShaderGroup->addRenderable(renderable, localToWorld, nullptr, entity); + } else + { _selectedShader->addRenderable(renderable, localToWorld, nullptr, entity); + } } shader.addRenderable(renderable, localToWorld, nullptr, entity); diff --git a/radiant/xyview/XYWnd.cpp b/radiant/xyview/XYWnd.cpp index a448914598..89c01f30ee 100644 --- a/radiant/xyview/XYWnd.cpp +++ b/radiant/xyview/XYWnd.cpp @@ -223,7 +223,9 @@ void XYWnd::captureStates() { _selectedShader = GlobalRenderSystem().capture("$XY_OVERLAY"); _selectedShaderGroup = GlobalRenderSystem().capture("$XY_OVERLAY_GROUP"); - _mergeActionShader = GlobalRenderSystem().capture("$XY_OVERLAY_GROUP"); + + _mergeActionShader = GlobalRenderSystem().capture("$XY_MERGE_ACTION"); + _nonMergeActionNodeShader = GlobalRenderSystem().capture("$XY_INACTIVE_NODE"); } void XYWnd::releaseStates() @@ -231,6 +233,7 @@ void XYWnd::releaseStates() _selectedShader.reset(); _selectedShaderGroup.reset(); _mergeActionShader.reset(); + _nonMergeActionNodeShader.reset(); } void XYWnd::ensureFont() @@ -1358,9 +1361,15 @@ void XYWnd::draw() flagsMask |= RENDER_LINESTIPPLE; } + if (GlobalMapModule().getEditMode() == IMap::EditMode::Merge) + { + flagsMask |= RENDER_BLEND; + } + { // Construct the renderer and render the scene - XYRenderer renderer(flagsMask, _selectedShader.get(), _selectedShaderGroup.get(), _mergeActionShader.get()); + XYRenderer renderer(flagsMask, _selectedShader.get(), _selectedShaderGroup.get(), + _mergeActionShader.get(), _nonMergeActionNodeShader.get()); // First pass (scenegraph traversal) render::RenderableCollectionWalker::CollectRenderablesInScene(renderer, @@ -1718,5 +1727,6 @@ IInteractiveView& XYWnd::getInteractiveView() ShaderPtr XYWnd::_selectedShader; ShaderPtr XYWnd::_selectedShaderGroup; ShaderPtr XYWnd::_mergeActionShader; +ShaderPtr XYWnd::_nonMergeActionNodeShader; } // namespace diff --git a/radiant/xyview/XYWnd.h b/radiant/xyview/XYWnd.h index dcaf83329e..dd575dd68e 100644 --- a/radiant/xyview/XYWnd.h +++ b/radiant/xyview/XYWnd.h @@ -59,6 +59,7 @@ class XYWnd : static ShaderPtr _selectedShader; static ShaderPtr _selectedShaderGroup; static ShaderPtr _mergeActionShader; + static ShaderPtr _nonMergeActionNodeShader; Vector3 _mousePosition; diff --git a/radiantcore/rendersystem/backend/OpenGLShader.cpp b/radiantcore/rendersystem/backend/OpenGLShader.cpp index b46ee908b1..34d9d8a97b 100644 --- a/radiantcore/rendersystem/backend/OpenGLShader.cpp +++ b/radiantcore/rendersystem/backend/OpenGLShader.cpp @@ -826,6 +826,36 @@ void OpenGLShader::construct() state.m_linewidth = 2; state.m_linestipple_factor = 3; } + else if (_name == "$XY_MERGE_ACTION") + { + Vector3 mergeActionColour(0, 0, 1); + state.setColour(static_cast(mergeActionColour[0]), + static_cast(mergeActionColour[1]), + static_cast(mergeActionColour[2]), + static_cast(0.5)); + state.setRenderFlag(RENDER_LINESTIPPLE); + state.setSortPosition(OpenGLState::SORT_OVERLAY_FIRST); + state.m_linewidth = 2; + state.m_linestipple_factor = 2; + } + else if (_name == "$XY_INACTIVE_NODE") + { + Colour4 colour(0, 0, 0, 0.05f); + state.setColour(static_cast(colour[0]), + static_cast(colour[1]), + static_cast(colour[2]), + static_cast(colour[3])); + + state.m_blend_src = GL_SRC_ALPHA; + state.m_blend_dst = GL_ONE_MINUS_SRC_ALPHA; + + state.setRenderFlags(RENDER_DEPTHTEST | RENDER_DEPTHWRITE | RENDER_BLEND); + state.setSortPosition(OpenGLState::SORT_FULLBRIGHT); + state.setDepthFunc(GL_LESS); + + state.m_linewidth = 1; + state.m_pointsize = 1; + } else if (_name == "$DEBUG_CLIPPED") { state.setRenderFlag(RENDER_DEPTHWRITE);