Skip to content

Commit

Permalink
3D UI Feature
Browse files Browse the repository at this point in the history
  • Loading branch information
JoshEngebretson committed Jun 26, 2017
1 parent 0bac12c commit 2cb4ac0
Show file tree
Hide file tree
Showing 14 changed files with 1,183 additions and 216 deletions.
203 changes: 65 additions & 138 deletions Source/Atomic/UI/UI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ using namespace tb;

#include "UIRenderer.h"
#include "UI.h"
#include "UIView.h"
#include "UIButton.h"
#include "UITextField.h"
#include "UIEditField.h"
Expand Down Expand Up @@ -91,6 +92,7 @@ using namespace tb;
#include "UIPromptWindow.h"
#include "UIFinderWindow.h"
#include "UIPulldownMenu.h"
#include "UIComponent.h"

#include "SystemUI/SystemUI.h"
#include "SystemUI/SystemUIEvents.h"
Expand All @@ -108,12 +110,15 @@ void TBSystem::RescheduleTimer(double fire_time)

}


namespace Atomic
{

WeakPtr<Context> UI::uiContext_;
void RegisterUILibrary(Context* context)
{
UIComponent::RegisterObject(context);
}

WeakPtr<Context> UI::uiContext_;

UI::UI(Context* context) :
Object(context),
Expand All @@ -128,6 +133,8 @@ UI::UI(Context* context) :
tooltipHoverTime_ (0.0f)
{

RegisterUILibrary(context);

SubscribeToEvent(E_EXITREQUESTED, ATOMIC_HANDLER(UI, HandleExitRequested));

}
Expand Down Expand Up @@ -201,8 +208,6 @@ void UI::Initialize(const String& languageFile)
assert(graphics->IsInitialized());
graphics_ = graphics;

vertexBuffer_ = new VertexBuffer(context_);

uiContext_ = context_;

TBFile::SetReaderFunction(TBFileReader);
Expand All @@ -224,21 +229,10 @@ void UI::Initialize(const String& languageFile)
rootWidget_->SetSize(width, height);
rootWidget_->SetVisibilility(tb::WIDGET_VISIBILITY_VISIBLE);

SubscribeToEvent(E_MOUSEBUTTONDOWN, ATOMIC_HANDLER(UI, HandleMouseButtonDown));
SubscribeToEvent(E_MOUSEBUTTONUP, ATOMIC_HANDLER(UI, HandleMouseButtonUp));
SubscribeToEvent(E_MOUSEMOVE, ATOMIC_HANDLER(UI, HandleMouseMove));
SubscribeToEvent(E_MOUSEWHEEL, ATOMIC_HANDLER(UI, HandleMouseWheel));
SubscribeToEvent(E_KEYDOWN, ATOMIC_HANDLER(UI, HandleKeyDown));
SubscribeToEvent(E_KEYUP, ATOMIC_HANDLER(UI, HandleKeyUp));
SubscribeToEvent(E_TEXTINPUT, ATOMIC_HANDLER(UI, HandleTextInput));
SubscribeToEvent(E_UPDATE, ATOMIC_HANDLER(UI, HandleUpdate));
SubscribeToEvent(E_SCREENMODE, ATOMIC_HANDLER(UI, HandleScreenMode));
SubscribeToEvent(E_CONSOLECLOSED, ATOMIC_HANDLER(UI, HandleConsoleClosed));

SubscribeToEvent(E_TOUCHBEGIN, ATOMIC_HANDLER(UI, HandleTouchBegin));
SubscribeToEvent(E_TOUCHEND, ATOMIC_HANDLER(UI, HandleTouchEnd));
SubscribeToEvent(E_TOUCHMOVE, ATOMIC_HANDLER(UI, HandleTouchMove));

SubscribeToEvent(E_POSTUPDATE, ATOMIC_HANDLER(UI, HandlePostUpdate));
SubscribeToEvent(E_RENDERUPDATE, ATOMIC_HANDLER(UI, HandleRenderUpdate));

// register the UIDragDrop subsystem (after we have subscribed to events, so it is processed after)
Expand Down Expand Up @@ -316,159 +310,94 @@ void UI::AddFont(const String& fontFile, const String& name)
tb::g_font_manager->AddFontInfo(fontFile.CString(), name.CString());
}

void UI::Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigned batchStart, unsigned batchEnd)
void UI::AddUIView(UIView* uiView)
{
rootWidget_->AddChild(uiView->GetInternalWidget());
uiViews_.Push(SharedPtr<UIView>(uiView));

if (batches.Empty())
return;

Vector2 invScreenSize(1.0f / (float)graphics_->GetWidth(), 1.0f / (float)graphics_->GetHeight());
Vector2 scale(2.0f * invScreenSize.x_, -2.0f * invScreenSize.y_);
Vector2 offset(-1.0f, 1.0f);

Matrix4 projection(Matrix4::IDENTITY);
projection.m00_ = scale.x_;
projection.m03_ = offset.x_;
projection.m11_ = scale.y_;
projection.m13_ = offset.y_;
projection.m22_ = 1.0f;
projection.m23_ = 0.0f;
projection.m33_ = 1.0f;

graphics_->ClearParameterSources();
graphics_->SetColorWrite(true);
graphics_->SetCullMode(CULL_NONE);
graphics_->SetDepthTest(CMP_ALWAYS);
graphics_->SetDepthWrite(false);
graphics_->SetFillMode(FILL_SOLID);
graphics_->SetStencilTest(false);

graphics_->ResetRenderTargets();

graphics_->SetVertexBuffer(buffer);

ShaderVariation* noTextureVS = graphics_->GetShader(VS, "Basic", "VERTEXCOLOR");
ShaderVariation* diffTextureVS = graphics_->GetShader(VS, "Basic", "DIFFMAP VERTEXCOLOR");
ShaderVariation* noTexturePS = graphics_->GetShader(PS, "Basic", "VERTEXCOLOR");
ShaderVariation* diffTexturePS = graphics_->GetShader(PS, "Basic", "DIFFMAP VERTEXCOLOR");
ShaderVariation* diffMaskTexturePS = graphics_->GetShader(PS, "Basic", "DIFFMAP ALPHAMASK VERTEXCOLOR");
ShaderVariation* alphaTexturePS = graphics_->GetShader(PS, "Basic", "ALPHAMAP VERTEXCOLOR");

unsigned alphaFormat = Graphics::GetAlphaFormat();

for (unsigned i = batchStart; i < batchEnd; ++i)
if (!focusedView_ && uiView)
{
const UIBatch& batch = batches[i];
if (batch.vertexStart_ == batch.vertexEnd_)
continue;

ShaderVariation* ps;
ShaderVariation* vs;

if (!batch.texture_)
{
ps = noTexturePS;
vs = noTextureVS;
}
else
{
// If texture contains only an alpha channel, use alpha shader (for fonts)
vs = diffTextureVS;

if (batch.texture_->GetFormat() == alphaFormat)
ps = alphaTexturePS;
else if (batch.blendMode_ != BLEND_ALPHA && batch.blendMode_ != BLEND_ADDALPHA && batch.blendMode_ != BLEND_PREMULALPHA)
ps = diffMaskTexturePS;
else
ps = diffTexturePS;
}
uiView->SetFocus();
}
}

graphics_->SetShaders(vs, ps);
if (graphics_->NeedParameterUpdate(SP_OBJECT, this))
graphics_->SetShaderParameter(VSP_MODEL, Matrix3x4::IDENTITY);
if (graphics_->NeedParameterUpdate(SP_CAMERA, this))
graphics_->SetShaderParameter(VSP_VIEWPROJ, projection);
if (graphics_->NeedParameterUpdate(SP_MATERIAL, this))
graphics_->SetShaderParameter(PSP_MATDIFFCOLOR, Color(1.0f, 1.0f, 1.0f, 1.0f));

graphics_->SetBlendMode(batch.blendMode_);
graphics_->SetScissorTest(true, batch.scissor_);
graphics_->SetTexture(0, batch.texture_);
graphics_->Draw(TRIANGLE_LIST, batch.vertexStart_ / UI_VERTEX_SIZE, (batch.vertexEnd_ - batch.vertexStart_) /
UI_VERTEX_SIZE);
void UI::RemoveUIView(UIView* uiView)
{
if (focusedView_ == uiView)
{
SetFocusedView(0);
}

rootWidget_->RemoveChild(uiView->GetInternalWidget());
uiViews_.Remove(SharedPtr<UIView>(uiView));
}

void UI::SetVertexData(VertexBuffer* dest, const PODVector<float>& vertexData)
void UI::SetFocusedView(UIView* uiView)
{
if (vertexData.Empty())
if (focusedView_ == uiView)
{
return;
}

// Update quad geometry into the vertex buffer
// Resize the vertex buffer first if too small or much too large
unsigned numVertices = vertexData.Size() / UI_VERTEX_SIZE;
if (dest->GetVertexCount() < numVertices || dest->GetVertexCount() > numVertices * 2)
dest->SetSize(numVertices, MASK_POSITION | MASK_COLOR | MASK_TEXCOORD1, true);
focusedView_ = uiView;

dest->SetData(&vertexData[0]);
}
if (focusedView_)
{
focusedView_->BecomeFocused();
}
else
{
focusedView_ = 0;

// look for first auto activated UIView, and recurse
Vector<SharedPtr<UIView>>::Iterator itr = uiViews_.Begin();

void UI::Render(bool resetRenderTargets)
{
SetVertexData(vertexBuffer_, vertexData_);
Render(vertexBuffer_, batches_, 0, batches_.Size());
while (itr != uiViews_.End())
{
if ((*itr)->GetAutoFocus())
{
SetFocusedView(*itr);
return;
}

itr++;
}

}
}

void UI::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
void UI::Render(bool resetRenderTargets)
{
// Get rendering batches from the non-modal UI elements
batches_.Clear();
vertexData_.Clear();
Vector<SharedPtr<UIView>>::Iterator itr = uiViews_.Begin();

tb::TBRect rect = rootWidget_->GetRect();
while (itr != uiViews_.End())
{
(*itr)->Render(resetRenderTargets);

IntRect currentScissor = IntRect(0, 0, rect.w, rect.h);
GetBatches(batches_, vertexData_, currentScissor);
itr++;
}

}

void UI::GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor)
{
//if (!initialized_)
// return;

void UI::HandlePostUpdate(StringHash eventType, VariantMap& eventData)
{
TBAnimationManager::Update();

rootWidget_->InvokeProcessStates();
rootWidget_->InvokeProcess();

tb::g_renderer->BeginPaint(rootWidget_->GetRect().w, rootWidget_->GetRect().h);

renderer_->currentScissor_ = currentScissor;
renderer_->batches_ = &batches;
renderer_->vertexData_ = &vertexData;
rootWidget_->InvokePaint(tb::TBWidget::PaintProps());

tb::g_renderer->EndPaint();
}

void UI::SubmitBatchVertexData(Texture* texture, const PODVector<float>& vertexData)
void UI::HandleRenderUpdate(StringHash eventType, VariantMap& eventData)
{
UIBatch b(BLEND_ALPHA , renderer_->currentScissor_, texture, &vertexData_);

unsigned begin = b.vertexData_->Size();
b.vertexData_->Resize(begin + vertexData.Size());
float* dest = &(b.vertexData_->At(begin));
b.vertexEnd_ = b.vertexData_->Size();
Vector<SharedPtr<UIView>>::Iterator itr = uiViews_.Begin();

for (unsigned i = 0; i < vertexData.Size(); i++, dest++)
while (itr != uiViews_.End())
{
*dest = vertexData[i];
(*itr)->UpdateUIBatches();
itr++;
}

UIBatch::AddOrMerge(b, batches_);

}

void UI::TBFileReader(const char* filename, void** data, unsigned* length)
Expand Down Expand Up @@ -1034,6 +963,4 @@ void UI::DebugShowSettingsWindow(UIWidget* parent)

}



}
40 changes: 17 additions & 23 deletions Source/Atomic/UI/UI.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,14 @@ namespace Atomic
class VertexBuffer;
class UIRenderer;
class UIWidget;
class UIView;
class UIPopupWindow;
class MessageBox;

class ATOMIC_API UI : public Object, private tb::TBWidgetListener
{
friend class UIView;

ATOMIC_OBJECT(UI, Object)

public:
Expand All @@ -55,8 +58,6 @@ class ATOMIC_API UI : public Object, private tb::TBWidgetListener
void SetInputDisabled(bool disabled) { inputDisabled_ = disabled; }

void Render(bool resetRenderTargets = true);
void GetBatches(PODVector<UIBatch>& batches, PODVector<float>& vertexData, const IntRect& currentScissor);
void SubmitBatchVertexData(Texture* texture, const PODVector<float>& vertexData);

void Initialize(const String& languageFile);

Expand Down Expand Up @@ -130,35 +131,36 @@ class ATOMIC_API UI : public Object, private tb::TBWidgetListener
// Debugging
static void DebugShowSettingsWindow(UIWidget* parent);

/// Get the currently focused view
UIView* GetFocusedView() const { return focusedView_; }

private:

static WeakPtr<Context> uiContext_;
static void TBFileReader(const char* filename, void** data, unsigned* length);
static void TBIDRegisterStringCallback(unsigned id, const char* value);

void HandlePostUpdate(StringHash eventType, VariantMap& eventData);
void HandleRenderUpdate(StringHash eventType, VariantMap& eventData);
void HandleExitRequested(StringHash eventType, VariantMap& eventData);

void Render(VertexBuffer* buffer, const PODVector<UIBatch>& batches, unsigned batchStart, unsigned batchEnd);
void SetVertexData(VertexBuffer* dest, const PODVector<float>& vertexData);

// TBWidgetListener
void OnWidgetDelete(tb::TBWidget *widget);
bool OnWidgetDying(tb::TBWidget *widget);
void OnWidgetFocusChanged(tb::TBWidget *widget, bool focused);
bool OnWidgetInvokeEvent(tb::TBWidget *widget, const tb::TBWidgetEvent &ev);
void OnWindowClose(tb::TBWindow *window);

/// Add a UIView to UI subsystem, happens immediately at UIView creation
void AddUIView(UIView* uiView);
/// Set the currently focused view
void SetFocusedView(UIView* uiView);
/// Removes a UIView from the UI subsystem, readding a view is not encouraged
void RemoveUIView(UIView* uiView);

tb::TBWidget* rootWidget_;
UIRenderer* renderer_;

/// UI rendering batches.
PODVector<UIBatch> batches_;
/// UI rendering vertex data.
PODVector<float> vertexData_;
SharedPtr<VertexBuffer> vertexBuffer_;

WeakPtr<Graphics> graphics_;

HashMap<tb::TBWidget*, SharedPtr<UIWidget> > widgetWrap_;
Expand All @@ -177,22 +179,14 @@ class ATOMIC_API UI : public Object, private tb::TBWidgetListener

float tooltipHoverTime_;

Vector<SharedPtr<UIView>> uiViews_;

WeakPtr<UIView> focusedView_;

// Events
void HandleScreenMode(StringHash eventType, VariantMap& eventData);
void HandleMouseButtonDown(StringHash eventType, VariantMap& eventData);
void HandleMouseButtonUp(StringHash eventType, VariantMap& eventData);
void HandleMouseMove(StringHash eventType, VariantMap& eventData);
void HandleMouseWheel(StringHash eventType, VariantMap& eventData);
void HandleKeyDown(StringHash eventType, VariantMap& eventData);
void HandleKeyUp(StringHash eventType, VariantMap& eventData);
void HandleKey(bool keydown, int keycode, int scancode);
void HandleTextInput(StringHash eventType, VariantMap& eventData);
void HandleUpdate(StringHash eventType, VariantMap& eventData);
void HandleConsoleClosed(StringHash eventType, VariantMap& eventData);
//Touch Input
void HandleTouchBegin(StringHash eventType, VariantMap& eventData);
void HandleTouchMove(StringHash eventType, VariantMap& eventData);
void HandleTouchEnd(StringHash eventType, VariantMap& eventData);
};

}
Loading

0 comments on commit 2cb4ac0

Please sign in to comment.