Files
Webcam/include/engine/ui/ui_window.cpp

366 lines
10 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#include "ui/ui_window.h"
#include "ui/widget_text.h"
#include "core/renderer_toolbox.h"
#include "core/render_resource_factory.h"
using namespace GS;
using namespace GS::S2D;
//------------------------------------------------------------------------------
iRect Window::GetRect() const
{
if (!window_flags.IsSet(Window::FlagNoDecoration))
if (skin.IsValid())
return iRect(0, 0, (int)size.x, (int)skin->top->GetHeight());
return iRect(0, 0, (int)size.x, (int)size.y);
}
iRect Window::GetClientRect() const
{
if (!window_flags.IsSet(Window::FlagNoDecoration))
if (skin.IsValid())
return iRect(skin->left->GetWidth(), skin->top_left->GetHeight(), int(size.x - skin->right->GetWidth()), int(size.y - skin->bottom_right->GetHeight()));
return iRect(0, 0, (int)size.x, (int)size.y);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::SetSize(float _w, float _h)
{
uint w = (uint)_w, h = (uint)_h;
if (cache.IsValid())
{
if (w > cache->GetWidth() || h > cache->GetHeight() || w < (cache->GetWidth() / 2) || h < (cache->GetHeight() / 2))
{
cache->AllocAs(w, h);
if (render_data && render_data->texture)
render_data->texture->Resize(w, h);
}
}
Invalidate();
Sprite::SetSize(_w, _h);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Widget *Window::GetTitleWidget() const
{ return title_widget; }
void Window::SetTitleWidget(Widget *w)
{
title_widget = w;
Invalidate();
}
Widget *Window::GetBaseWidget() const
{ return base_widget; }
void Window::SetBaseWidget(Widget *w)
{
base_widget = w;
Invalidate();
}
Widget *Window::GetWidget(uint id)
{ return base_widget ? base_widget->GetChild(id) : NULL; }
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::ComposeSkin()
{
if (skin.IsNull())
return;
cache->Fill(0, 0, 0, 0);
// Fill main area.
Rect <int> rect(GetRect());
rect.sx = skin->top_left->GetWidth();
rect.sy = skin->top_left->GetHeight();
rect.ex -= skin->bottom_right->GetWidth();
rect.ey -= skin->bottom_right->GetHeight();
Color _skin_color(skin->color);
cache->Fill(_skin_color.x, _skin_color.y, _skin_color.z, _skin_color.w, &rect);
// Blit corners.
Picture::Blit(*skin->top_left, *cache);
rect = GetRect();
rect.sx = rect.ex - skin->top_right->GetWidth();
Picture::Blit(*skin->top_right, *cache, NULL, &rect);
rect = GetRect();
rect.sy = rect.ey - skin->bottom_left->GetHeight();
Picture::Blit(*skin->bottom_left, *cache, NULL, &rect);
rect = GetRect();
rect.sx = rect.ex - skin->bottom_right->GetWidth();
rect.sy = rect.ey - skin->bottom_right->GetHeight();
Picture::Blit(*skin->bottom_right, *cache, NULL, &rect);
// Window left side.
{
int height = GetRect().GetHeight() - skin->top_left->GetHeight() - skin->bottom_left->GetHeight();
int *dst = (int *)cache->GetData();
dst += skin->top_left->GetHeight() * cache->GetWidth();
int *src = 0;
for (int s = 0, _s = 0; s < height; ++s)
{
if (!src || (++_s == (int)skin->left->GetHeight()))
{
src = (int *)skin->left->GetData();
_s = 0;
}
for (uint x = 0; x < skin->left->GetWidth(); ++x)
dst[x] = src[x];
src += skin->left->GetWidth();
dst += cache->GetWidth();
}
}
// Window right side.
{
int height = GetRect().GetHeight() - skin->top_right->GetHeight() - skin->bottom_right->GetHeight();
int *dst = (int *)cache->GetData();
dst += skin->top_right->GetHeight() * cache->GetWidth() + GetRect().ex - skin->right->GetWidth();
int *src = 0;
for (int s = 0, _s = 0; s < height; ++s)
{
if (!src || (++_s == (int)skin->right->GetHeight()))
{
src = (int *)skin->right->GetData();
_s = 0;
}
for (uint x = 0; x < skin->right->GetWidth(); ++x)
dst[x] = src[x];
src += skin->right->GetWidth();
dst += cache->GetWidth();
}
}
// Window top side.
{
int block_width = skin->top->GetWidth();
int width = GetRect().GetWidth() - skin->top_left->GetWidth() - skin->top_right->GetWidth(), height = skin->top->GetHeight();
int *src = (int *)skin->top->GetData(), *dst = (int *)cache->GetData();
dst += skin->top_left->GetWidth();
for (int y = 0; y < height; ++y)
{
for (int x = 0, _x = 0; x < width; ++x)
{
dst[x] = src[_x++];
if (_x == block_width)
_x = 0;
}
src += skin->top->GetWidth();
dst += cache->GetWidth();
}
}
// Window bottom side.
{
int block_width = skin->bottom->GetWidth();
int width = GetRect().GetWidth() - skin->bottom_left->GetWidth() - skin->bottom_right->GetWidth(), height = skin->bottom->GetHeight();
int *src = (int *)skin->bottom->GetData(), *dst = (int *)cache->GetData();
dst += skin->bottom_left->GetWidth() + (GetRect().ey - height) * cache->GetWidth();
for (int y = 0; y < height; ++y)
{
for (int x = 0, _x = 0; x < width; ++x)
{
dst[x] = src[_x++];
if (_x == block_width)
_x = 0;
}
src += skin->bottom->GetWidth();
dst += cache->GetWidth();
}
}
//
{
int height = GetRect().ey - skin->bottom_right->GetHeight() - skin->top_left->GetHeight(), width = GetRect().GetWidth();
//
uint *dst = (uint *)cache->GetData();
dst += cache->GetWidth() * skin->top_left->GetHeight();// + system.skin_left->GetWidth();
float alpha = 1.f;
int segment_height = (height * 70) / 100;
float alpha_step = (0.85f - alpha) / (float)segment_height;
for (int y = 0; y < segment_height; ++y)
{
uint int_alpha = (uint(alpha * 255.f)) & 0xff;
// uint scan_color = nColor::ARGBtoRGBA((system.skin_color & 0xffffff00) + int_alpha);
for (int x = 0; x < width; ++x)
dst[x] = (((((dst[x] >> 24) & 0xff) * int_alpha) >> 8) << 24) + (dst[x] & 0x00ffffff);//scan_color;
dst += cache->GetWidth();
alpha += alpha_step;
}
segment_height = height - segment_height;
alpha_step = (1.f - alpha) / (float)segment_height;
for (int y = 0; y < segment_height; ++y)
{
uint int_alpha = (uint(alpha * 255.f)) & 0xff;
// uint scan_color = nColor::ARGBtoRGBA((system.skin_color & 0xffffff00) + int_alpha);
for (int x = 0; x < width; ++x)
dst[x] = (((((dst[x] >> 24) & 0xff) * int_alpha) >> 8) << 24) + (dst[x] & 0x00ffffff);//scan_color;
dst += cache->GetWidth();
alpha += alpha_step;
}
}
}
void Window::Compose()
{
if (cache.IsNull())
return;
if (background_picture)
{
cache->Fill(0, 0, 0, 0);
Picture::Blit(*background_picture, *cache);
}
else
{
bool skinned = false;
if (!window_flags.IsSet(Window::FlagNoDecoration))
if (skin.IsValid())
skinned = true;
if (skinned)
ComposeSkin();
cache->Fill(background_color.x, background_color.y, background_color.z, background_color.w);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::Invalidate()
{
if (base_widget)
base_widget->Invalidate();
if (title_widget)
title_widget->Invalidate();
window_flags.Raise(FlagCacheDirty | FlagRenderDirty);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::RenderSetup(Core::ResourceFactories *f)
{
if ((render_data = new Sprite::RenderData))
if (f && f->render)
{
render_data->texture = f->render->NewTexture();
render_data->texture->Create(NULL, (int)size.x, (int)size.y, Render::Texture::FormatRGBA8, Render::Texture::NoAA, Render::Texture::Usage(Render::Texture::IsRenderTarget | Render::Texture::IsShaderResource));
window_flags.Raise(FlagRenderDirty);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::Render(Renderer &renderer, GPU::TriangleBatch *batch)
{
// Compose.
bool has_title = !(window_flags.IsSet(Window::FlagNoTitleBar) || background_picture);
if (base_widget)
{
base_widget->Refresh();
if (base_widget->IsDirty())
{
Invalidate();
// Compose window skin.
Compose();
// Compose window content.
Rect <int> compose_rect(GetRect());
if (has_title && skin)
{
compose_rect.sx = skin->top_left->GetWidth();
compose_rect.sy = skin->title_bottom + 4;
compose_rect.ex -= skin->bottom_right->GetWidth();
compose_rect.ey -= skin->bottom_right->GetHeight();
}
if (cache.IsValid())
base_widget->Compose(*cache, compose_rect);
}
}
else
if (window_flags.IsSet(FlagCacheDirty))
Compose();
// Compose the window title.
if (has_title && skin)
{
iRect title_rect(skin->top_left->GetWidth(), skin->title_top, GetRect().GetWidth() - skin->top_right->GetWidth(), skin->title_bottom);
if (cache.IsValid())
title_widget->Compose(*cache, title_rect);
}
if (window_flags.IsSet(FlagRenderDirty))
if (render_data.IsValid() && render_data->texture.IsValid())
{
render_data->texture->Blit((const char *)cache->GetData(), cache->GetWidth(), cache->GetHeight());
window_flags.Remove(FlagRenderDirty);
}
Sprite::Render(renderer, batch);
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
void Window::SetSkin(WindowSkin *s)
{
if ((skin = s))
if (title_widget->GetType() == WidgetTypeText)
if (TextWidget *t = (TextWidget *)title_widget.c_ptr())
{
Color skin_color(skin->title_color);
t->SetFont(s->title_font);
t->SetFontColor(skin_color.x, skin_color.y, skin_color.z);
t->SetFontSize(s->title_size);
t->SetTextAlignment(TextState::Center);
}
Invalidate();
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
Window::Window()
{
window_flags.Set(FlagCacheDirty);
type = Type_Window;
cache = new Picture;
background_color.Set(0.f, 0.f, 0.f, 0.f);
title_widget = new TextWidget(-1, "Window Title");
SetSize(320, 200);
}
//------------------------------------------------------------------------------