366 lines
10 KiB
C++
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);
|
|
}
|
|
//------------------------------------------------------------------------------
|