Files
WickedEngine/WickedEngine/wiGUI.cpp
T
Turánszki János 180ddc3586 0.49 (#160)
* renderer updates: material shadertype, customshaders

* custom shader updates

* hologram fix

* editor windows refactor

* major gui update:
- gui no longer lifetime manager
- window no longer needs gui to construct
- removed gui constructors/destructors
- rewritten every editor window

* renderer update

* gui hasfocus fix

* editor fix

* renderpath upgrades: hybrid forward-deferred

* fix

* water ripple refactor

* cmake fix

* cmake fix

* renderer fix

* volumetric light fix

* customshader stencilref

* cmake fix

* rtdeferred fix

* editor update

* raytraced shadows denoise

* anisotropic shader

* sss stencil greater

* added cartoon shader

* using precomputed tangents

* added unlit object shader

* importer update

* editor update

* editor fix

* vulkan envmap rendering fix

* terrain shader simplification (normal texture mapping instead of triplanar)

* added subsurface profiles, reduced gbuffer

* denoise disocclusion fallback

* editor fix

* more sorting priority for blend than instancing

* hairparticle culling

* particle updates; font update instancing instead of index buffer; vulkan/dx12 fixes;

* shader fixes

* hairparticle trianglestrip and no cross section

* editor fix

* cam wnd update

* terrain shader fix
2020-10-17 13:17:07 +02:00

224 lines
4.9 KiB
C++

#include "wiGUI.h"
#include "wiWidget.h"
#include "wiRenderer.h"
#include "wiInput.h"
using namespace std;
using namespace wiGraphics;
void wiGUIElement::AttachTo(wiGUIElement* parent)
{
this->parent = parent;
this->parent->UpdateTransform();
XMMATRIX B = XMMatrixInverse(nullptr, XMLoadFloat4x4(&parent->world));
MatrixTransform(B);
UpdateTransform();
UpdateTransform_Parented(*parent);
}
void wiGUIElement::Detach()
{
this->parent = nullptr;
ApplyTransform();
}
void wiGUIElement::ApplyScissor(const Rect rect, CommandList cmd, bool constrain_to_parent) const
{
Rect scissor = rect;
if (constrain_to_parent && parent != nullptr)
{
wiGUIElement* recurse_parent = parent;
while (recurse_parent != nullptr)
{
scissor.bottom = std::min(scissor.bottom, recurse_parent->scissorRect.bottom);
scissor.top = std::max(scissor.top, recurse_parent->scissorRect.top);
scissor.left = std::max(scissor.left, recurse_parent->scissorRect.left);
scissor.right = std::min(scissor.right, recurse_parent->scissorRect.right);
recurse_parent = recurse_parent->parent;
}
}
if (scissor.left > scissor.right)
{
scissor.left = scissor.right;
}
if (scissor.top > scissor.bottom)
{
scissor.top = scissor.bottom;
}
GraphicsDevice* device = wiRenderer::GetDevice();
float scale_x = (float)device->GetResolutionWidth() / (float)device->GetScreenWidth();
float scale_y = (float)device->GetResolutionHeight() / (float)device->GetScreenHeight();
scissor.bottom = int32_t((float)scissor.bottom * scale_y);
scissor.top = int32_t((float)scissor.top * scale_y);
scissor.left = int32_t((float)scissor.left * scale_x);
scissor.right = int32_t((float)scissor.right * scale_x);
device->BindScissorRects(1, &scissor, cmd);
}
void wiGUI::Update(float dt)
{
if (!visible)
{
return;
}
XMFLOAT4 _p = wiInput::GetPointer();
pointerpos.x = _p.x;
pointerpos.y = _p.y;
pointerhitbox = Hitbox2D(pointerpos, XMFLOAT2(1, 1));
if (activeWidget != nullptr)
{
if (!activeWidget->IsEnabled() || !activeWidget->IsVisible())
{
// deactivate active widget if it became invisible or disabled
DeactivateWidget(activeWidget);
}
}
focus = false;
for (auto& widget : widgets)
{
// the contained child widgets will be updated by the containers
widget->Update(this, dt);
if (widget->IsVisible() && widget->hitBox.intersects(pointerhitbox))
{
// hitbox can only intersect with one element (avoid detecting multiple overlapping elements)
pointerhitbox.pos = XMFLOAT2(-FLT_MAX, -FLT_MAX);
pointerhitbox.siz = XMFLOAT2(0, 0);
focus = true;
}
if (widget->priority_change)
{
widget->priority_change = false;
priorityChangeQueue.push_back(widget);
}
}
for (auto& widget : priorityChangeQueue)
{
if (std::find(widgets.begin(), widgets.end(), widget) != widgets.end()) // only add back to widgets if it's still there!
{
widgets.remove(widget);
widgets.push_front(widget);
}
}
priorityChangeQueue.clear();
scissorRect.bottom = (int32_t)(wiRenderer::GetDevice()->GetScreenHeight());
scissorRect.left = (int32_t)(0);
scissorRect.right = (int32_t)(wiRenderer::GetDevice()->GetScreenWidth());
scissorRect.top = (int32_t)(0);
}
void wiGUI::Render(CommandList cmd) const
{
if (!visible)
{
return;
}
wiRenderer::GetDevice()->EventBegin("GUI", cmd);
for (auto it = widgets.rbegin(); it != widgets.rend(); ++it)
{
const wiWidget* widget = (*it);
if (widget != activeWidget)
{
ApplyScissor(scissorRect, cmd);
widget->Render(this, cmd);
}
}
if (activeWidget != nullptr)
{
// Active widget is always on top!
ApplyScissor(scissorRect, cmd);
activeWidget->Render(this, cmd);
}
ApplyScissor(scissorRect, cmd);
if (activeWidget == nullptr)
{
for (auto& x : widgets)
{
x->RenderTooltip(this, cmd);
}
}
wiRenderer::GetDevice()->EventEnd(cmd);
}
void wiGUI::AddWidget(wiWidget* widget)
{
if (widget != nullptr)
{
assert(std::find(widgets.begin(), widgets.end(), widget) == widgets.end()); // don't attach one widget twice!
widget->AttachTo(this);
widgets.push_back(widget);
}
}
void wiGUI::RemoveWidget(wiWidget* widget)
{
if (widget != nullptr)
{
widget->Detach();
widgets.remove(widget);
}
}
wiWidget* wiGUI::GetWidget(const std::string& name)
{
for (auto& x : widgets)
{
if (x->GetName() == name)
{
return x;
}
}
return nullptr;
}
void wiGUI::ActivateWidget(wiWidget* widget)
{
widget->priority_change = false;
priorityChangeQueue.push_back(widget);
if (activeWidget == nullptr)
{
activeWidget = widget;
activeWidget->Activate();
}
}
void wiGUI::DeactivateWidget(wiWidget* widget)
{
widget->Deactivate();
if (activeWidget == widget)
{
activeWidget = nullptr;
}
}
const wiWidget* wiGUI::GetActiveWidget() const
{
return activeWidget;
}
bool wiGUI::IsWidgetDisabled(wiWidget* widget)
{
return (activeWidget != nullptr && activeWidget != widget);
}
bool wiGUI::HasFocus()
{
if (!visible)
{
return false;
}
return focus;
}