2
#include "Nux/VScrollBar.h"
3
#include "Nux/HLayout.h"
4
#include "Nux/VLayout.h"
5
#include "Nux/MenuPage.h"
7
#include "NuxGraphics/NuxGraphics.h"
8
#include "NuxGraphics/GLDeviceFactory.h"
9
#include "NuxGraphics/GLTextureResourceManager.h"
11
#include "Nux/BaseWindow.h"
12
#include "Nux/WindowCompositor.h"
15
#include "LauncherIcon.h"
16
#include "LauncherModel.h"
18
static bool USE_ARB_SHADERS = true;
20
Use this shader to pass vertices in screen coordinates in the C++ code and compute use
21
the fragment shader to perform the texture perspective correct division.
22
This shader assume the following:
23
- the projection matrix is orthogonal: glOrtho(0, ScreenWidth, ScreenWidth, 0, Near, Far)
24
- vertices x and y are in screen coordinates: Vertex(x_screen, y_screen, 0, 1.0)
25
- the vertices w coordinates has been computed 'manually'
26
- vertices uv textture coordinates are passed to the shader as: (u/w, v/w, 0, 1/w)
28
The texture coordinates s=u/w, t=v/w and q=1w are interpolated linearly in screen coordinates.
29
In the fragment shader we get the texture coordinates used for the sampling by dividing
30
s and t resulting from the interpolation by q.
34
nux::NString gPerspectiveCorrectShader = TEXT (
37
uniform mat4 ViewProjectionMatrix; \n\
39
attribute vec4 iColor; \n\
40
attribute vec4 iTexCoord0; \n\
41
attribute vec4 iVertex; \n\
43
varying vec4 varyTexCoord0; \n\
44
varying vec4 varyVertexColor; \n\
48
varyTexCoord0 = iTexCoord0; \n\
49
varyVertexColor = iColor; \n\
50
gl_Position = ViewProjectionMatrix * iVertex; \n\
55
#extension GL_ARB_texture_rectangle : enable \n\
57
varying vec4 varyTexCoord0; \n\
58
varying vec4 varyVertexColor; \n\
60
uniform sampler2D TextureObject0; \n\
61
uniform vec4 color0; \n\
62
vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord) \n\
64
return texture2D(TexObject, TexCoord.st); \n\
69
vec4 tex = varyTexCoord0; \n\
70
tex.s = tex.s/varyTexCoord0.w; \n\
71
tex.t = tex.t/varyTexCoord0.w; \n\
73
vec4 texel = SampleTexture(TextureObject0, tex); \n\
74
gl_FragColor = texel*varyVertexColor; \n\
78
nux::NString PerspectiveCorrectVtx = TEXT (
80
ATTRIB iPos = vertex.position; \n\
81
ATTRIB iColor = vertex.attrib[3]; \n\
82
PARAM mvp[4] = {state.matrix.mvp}; \n\
83
OUTPUT oPos = result.position; \n\
84
OUTPUT oColor = result.color; \n\
85
OUTPUT oTexCoord0 = result.texcoord[0]; \n\
86
# Transform the vertex to clip coordinates. \n\
87
DP4 oPos.x, mvp[0], iPos; \n\
88
DP4 oPos.y, mvp[1], iPos; \n\
89
DP4 oPos.z, mvp[2], iPos; \n\
90
DP4 oPos.w, mvp[3], iPos; \n\
91
MOV oColor, iColor; \n\
92
MOV oTexCoord0, vertex.attrib[8]; \n\
97
nux::NString PerspectiveCorrectTexFrg = TEXT (
99
PARAM color0 = program.local[0]; \n\
103
MOV pcoord, fragment.texcoord[0].w; \n\
104
RCP temp, fragment.texcoord[0].w; \n\
105
MUL pcoord.xy, fragment.texcoord[0], temp; \n\
106
TEX tex0, pcoord, texture[0], 2D; \n\
107
MUL result.color, color0, tex0; \n\
110
nux::NString PerspectiveCorrectTexRectFrg = TEXT (
112
PARAM color0 = program.local[0]; \n\
116
MOV pcoord, fragment.texcoord[0].w; \n\
117
RCP temp, fragment.texcoord[0].w; \n\
118
MUL pcoord.xy, fragment.texcoord[0], temp; \n\
119
TEX tex0, pcoord, texture[0], RECT; \n\
120
MUL result.color, color0, tex0; \n\
123
static void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
130
Launcher::Launcher(NUX_FILE_LINE_DECL)
131
: View(NUX_FILE_LINE_PARAM)
132
, m_ContentOffsetY(0)
133
, m_RunningIndicator(0)
134
, m_ActiveIndicator(0)
135
, m_BackgroundLayer(0)
138
m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
140
OnMouseDown.connect(sigc::mem_fun(this, &Launcher::RecvMouseDown));
141
OnMouseUp.connect(sigc::mem_fun(this, &Launcher::RecvMouseUp));
142
OnMouseDrag.connect(sigc::mem_fun(this, &Launcher::RecvMouseDrag));
143
OnMouseEnter.connect(sigc::mem_fun(this, &Launcher::RecvMouseEnter));
144
OnMouseLeave.connect(sigc::mem_fun(this, &Launcher::RecvMouseLeave));
145
OnMouseMove.connect(sigc::mem_fun(this, &Launcher::RecvMouseMove));
146
OnMouseWheel.connect(sigc::mem_fun(this, &Launcher::RecvMouseWheel));
148
m_ActiveTooltipIcon = NULL;
149
m_ActiveMenuIcon = NULL;
151
SetCompositionLayout(m_Layout);
155
_shader_program_uv_persp_correction = nux::GetThreadGLDeviceFactory()->CreateShaderProgram();
156
_shader_program_uv_persp_correction->LoadIShader(gPerspectiveCorrectShader.GetTCharPtr());
157
_shader_program_uv_persp_correction->Link();
161
_AsmShaderProg = nux::GetThreadGLDeviceFactory()->CreateAsmShaderProgram();
162
_AsmShaderProg->LoadVertexShader (TCHAR_TO_ANSI (*PerspectiveCorrectVtx) );
164
if ((nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_NON_POWER_OF_TWO() == false) &&
165
(nux::GetThreadGLDeviceFactory()->SUPPORT_GL_EXT_TEXTURE_RECTANGLE () || nux::GetThreadGLDeviceFactory()->SUPPORT_GL_ARB_TEXTURE_RECTANGLE ()))
167
// No support for non power of two textures but support for rectangle textures
168
_AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexRectFrg) );
172
_AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexFrg) );
175
_AsmShaderProg->Link();
178
_folding_functor = new nux::TimerFunctor();
179
_folding_functor->OnTimerExpired.connect(sigc::mem_fun(this, &Launcher::FoldingCallback));
181
_reveal_functor = new nux::TimerFunctor();
182
_reveal_functor->OnTimerExpired.connect(sigc::mem_fun(this, &Launcher::RevealCallback));
184
_folded_angle = 1.0f;
185
_neg_folded_angle = -1.0f;
186
_folding_angle = _folded_angle;
187
_timer_intervals = 16;
189
_space_between_icons = 5;
190
_anim_duration = 200;
192
_launcher_bottom_y = 0;
193
_folded_z_distance = 10.0f;
194
_launcher_state = LAUNCHER_FOLDED;
195
_launcher_action_state = ACTION_NONE;
196
_icon_under_mouse = NULL;
197
_icon_mouse_down = NULL;
198
_icon_image_size = 48;
199
_icon_image_size_delta = 6;
200
_icon_size = _icon_image_size + _icon_image_size_delta;
201
_icon_bkg_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_corner_54x54.png");
202
_icon_outline_texture = nux::CreateTextureFromFile (PKGDATADIR"/round_outline_54x54.png");
206
Launcher::~Launcher()
211
void Launcher::SetIconSize(int tile_size, int icon_size, nux::BaseWindow *parent)
213
nux::Geometry geo = parent->GetGeometry ();
215
_icon_size = tile_size;
216
_icon_image_size = icon_size;
217
_icon_image_size_delta = tile_size - icon_size;
219
// recreate tile textures
221
parent->SetGeometry (nux::Geometry (geo.x, geo.y, tile_size + 12, geo.height));
224
void Launcher::OnIconAdded (void *icon_pointer)
226
LauncherIcon *icon = (LauncherIcon *) icon_pointer;
228
if (_launcher_state == LAUNCHER_UNFOLDED)
229
ScheduleRevealAnimation ();
231
ScheduleFoldAnimation ();
235
// needs to be disconnected
236
icon->needs_redraw.connect (sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
239
void Launcher::OnIconRemoved (void *icon_pointer)
241
if (_launcher_state == LAUNCHER_UNFOLDED)
242
ScheduleRevealAnimation ();
244
ScheduleFoldAnimation ();
249
void Launcher::OnOrderChanged ()
254
void Launcher::SetModel (LauncherModel *model)
257
_model->icon_added.connect (sigc::mem_fun (this, &Launcher::OnIconAdded));
258
_model->icon_removed.connect (sigc::mem_fun (this, &Launcher::OnIconRemoved));
259
_model->order_changed.connect (sigc::mem_fun (this, &Launcher::OnOrderChanged));
262
void Launcher::OnIconNeedsRedraw (void *icon)
267
long Launcher::ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
269
long ret = TraverseInfo;
270
ret = PostProcessEvent2(ievent, ret, ProcessEventInfo);
274
void Launcher::Draw(nux::GraphicsContext& GfxContext, bool force_draw)
279
void Launcher::RenderIcon(nux::GraphicsContext& GfxContext, LauncherIcon* launcher_view)
281
nux::Geometry geo = GetGeometry();
283
nux::Matrix4 ObjectMatrix;
284
nux::Matrix4 ViewMatrix;
285
nux::Matrix4 ProjectionMatrix;
286
nux::Matrix4 ViewProjectionMatrix;
287
nux::BaseTexture *icon;
289
if (launcher_view->Running ())
290
icon = _icon_bkg_texture;
292
icon = _icon_outline_texture;
294
icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
296
if(launcher_view->_folding_angle == 0.0f)
298
icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
302
icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
310
v0.x = launcher_view->_xform_screen_coord[0].x ;
311
v0.y = launcher_view->_xform_screen_coord[0].y ;
312
v0.z = launcher_view->_xform_screen_coord[0].z ;
313
v0.w = launcher_view->_xform_screen_coord[0].w ;
314
v1.x = launcher_view->_xform_screen_coord[1].x ;
315
v1.y = launcher_view->_xform_screen_coord[1].y ;
316
v1.z = launcher_view->_xform_screen_coord[1].z ;
317
v1.w = launcher_view->_xform_screen_coord[1].w ;
318
v2.x = launcher_view->_xform_screen_coord[2].x ;
319
v2.y = launcher_view->_xform_screen_coord[2].y ;
320
v2.z = launcher_view->_xform_screen_coord[2].z ;
321
v2.w = launcher_view->_xform_screen_coord[2].w ;
322
v3.x = launcher_view->_xform_screen_coord[3].x ;
323
v3.y = launcher_view->_xform_screen_coord[3].y ;
324
v3.z = launcher_view->_xform_screen_coord[3].z ;
325
v3.w = launcher_view->_xform_screen_coord[3].w ;
328
color = nux::Color::White;
330
float s0, t0, s1, t1, s2, t2, s3, t3;
332
if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
334
s0 = 0.0f; t0 = 0.0f;
335
s1 = 0.0f; t1 = icon->GetHeight();
336
s2 = icon->GetWidth(); t2 = icon->GetHeight();
337
s3 = icon->GetWidth(); t3 = 0.0f;
341
s0 = 0.0f; t0 = 0.0f;
342
s1 = 0.0f; t1 = 1.0f;
343
s2 = 1.0f; t2 = 1.0f;
344
s3 = 1.0f; t3 = 0.0f;
348
{// Perspective correct
349
v0.x, v0.y, 0.0f, 1.0f, s0/v0.w, t0/v0.w, 0.0f, 1.0f/v0.w, color.R(), color.G(), color.B(), color.A(),
350
v1.x, v1.y, 0.0f, 1.0f, s1/v1.w, t1/v1.w, 0.0f, 1.0f/v1.w, color.R(), color.G(), color.B(), color.A(),
351
v2.x, v2.y, 0.0f, 1.0f, s2/v2.w, t2/v2.w, 0.0f, 1.0f/v2.w, color.R(), color.G(), color.B(), color.A(),
352
v3.x, v3.y, 0.0f, 1.0f, s3/v3.w, t3/v3.w, 0.0f, 1.0f/v3.w, color.R(), color.G(), color.B(), color.A(),
355
CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
356
CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
358
int TextureObjectLocation;
360
int TextureCoord0Location;
361
int VertexColorLocation;
366
_shader_program_uv_persp_correction->Begin();
368
TextureObjectLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0");
369
VertexLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iVertex");
370
TextureCoord0Location = _shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0");
371
VertexColorLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iColor");
372
FragmentColor = _shader_program_uv_persp_correction->GetUniformLocationARB ("color");
374
nux::GetThreadGraphicsContext ()->SetTexture(GL_TEXTURE0, icon);
376
if(TextureObjectLocation != -1)
377
CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
379
int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
380
if(VPMatrixLocation != -1)
382
nux::Matrix4 mat = nux::GetThreadGraphicsContext ()->GetModelViewProjectionMatrix ();
383
_shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
388
_AsmShaderProg->Begin();
390
VertexLocation = nux::VTXATTRIB_POSITION;
391
TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
392
VertexColorLocation = nux::VTXATTRIB_COLOR;
394
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
397
CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
398
CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
400
if(TextureCoord0Location != -1)
402
CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
403
CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
406
if(VertexColorLocation != -1)
408
CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
409
CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
412
nux::Color bkg_color;
413
if (launcher_view->Running ())
414
bkg_color = launcher_view->BackgroundColor ();
416
bkg_color = nux::Color(0xFF6D6D6D);
418
nux::Color white = nux::Color::White;
422
CHECKGL ( glUniform4fARB (FragmentColor, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
423
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
424
CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
428
CHECKGL ( glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, bkg_color.R(), bkg_color.G(), bkg_color.B(), bkg_color.A() ) );
429
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
430
CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
433
if(VertexLocation != -1)
434
CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
435
if(TextureCoord0Location != -1)
436
CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
437
if(VertexColorLocation != -1)
438
CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
442
_shader_program_uv_persp_correction->End();
446
_AsmShaderProg->End();
450
void Launcher::RenderIconImage(nux::GraphicsContext& GfxContext, LauncherIcon* launcher_view)
452
nux::Geometry geo = GetGeometry();
454
nux::Matrix4 ObjectMatrix;
455
nux::Matrix4 ViewMatrix;
456
nux::Matrix4 ProjectionMatrix;
457
nux::Matrix4 ViewProjectionMatrix;
458
nux::BaseTexture *icon;
460
icon = launcher_view->TextureForSize (_icon_image_size);
462
if(launcher_view->_folding_angle == 0.0f)
464
icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
468
icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
476
v0.x = launcher_view->_xform_icon_screen_coord[0].x;
477
v0.y = launcher_view->_xform_icon_screen_coord[0].y;
478
v0.z = launcher_view->_xform_icon_screen_coord[0].z;
479
v0.w = launcher_view->_xform_icon_screen_coord[0].w;
480
v1.x = launcher_view->_xform_icon_screen_coord[1].x;
481
v1.y = launcher_view->_xform_icon_screen_coord[1].y;
482
v1.z = launcher_view->_xform_icon_screen_coord[1].z;
483
v1.w = launcher_view->_xform_icon_screen_coord[1].w;
484
v2.x = launcher_view->_xform_icon_screen_coord[2].x;
485
v2.y = launcher_view->_xform_icon_screen_coord[2].y;
486
v2.z = launcher_view->_xform_icon_screen_coord[2].z;
487
v2.w = launcher_view->_xform_icon_screen_coord[2].w;
488
v3.x = launcher_view->_xform_icon_screen_coord[3].x;
489
v3.y = launcher_view->_xform_icon_screen_coord[3].y;
490
v3.z = launcher_view->_xform_icon_screen_coord[3].z;
491
v3.w = launcher_view->_xform_icon_screen_coord[3].w;
492
int inside = launcher_view->_mouse_inside; //PointInside2DPolygon(launcher_view->_xform_screen_coord, 4, _mouse_position, 1);
496
color = nux::Color::Red;
498
color = nux::Color::White;
500
float s0, t0, s1, t1, s2, t2, s3, t3;
502
if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
504
s0 = 0.0f; t0 = 0.0f;
505
s1 = 0.0f; t1 = icon->GetHeight();
506
s2 = icon->GetWidth(); t2 = icon->GetHeight();
507
s3 = icon->GetWidth(); t3 = 0.0f;
511
s0 = 0.0f; t0 = 0.0f;
512
s1 = 0.0f; t1 = 1.0f;
513
s2 = 1.0f; t2 = 1.0f;
514
s3 = 1.0f; t3 = 0.0f;
518
{// Perspective correct
519
v0.x, v0.y, 0.0f, 1.0f, s0/v0.w, t0/v0.w, 0.0f, 1.0f/v0.w, color.R(), color.G(), color.B(), color.A(),
520
v1.x, v1.y, 0.0f, 1.0f, s1/v1.w, t1/v1.w, 0.0f, 1.0f/v1.w, color.R(), color.G(), color.B(), color.A(),
521
v2.x, v2.y, 0.0f, 1.0f, s2/v2.w, t2/v2.w, 0.0f, 1.0f/v2.w, color.R(), color.G(), color.B(), color.A(),
522
v3.x, v3.y, 0.0f, 1.0f, s3/v3.w, t3/v3.w, 0.0f, 1.0f/v3.w, color.R(), color.G(), color.B(), color.A(),
525
// float VtxBuffer[] =
526
// {// Not perspective correct
527
// v0.x, v0.y, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
528
// v1.x, v1.y, 0.0f, 1.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
529
// v2.x, v2.y, 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
530
// v3.x, v3.y, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f,
533
CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
534
CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
536
int TextureObjectLocation;
538
int TextureCoord0Location;
539
int VertexColorLocation;
544
_shader_program_uv_persp_correction->Begin();
546
TextureObjectLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("TextureObject0");
547
VertexLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iVertex");
548
TextureCoord0Location = _shader_program_uv_persp_correction->GetAttributeLocation("iTexCoord0");
549
VertexColorLocation = _shader_program_uv_persp_correction->GetAttributeLocation("iColor");
550
FragmentColor = _shader_program_uv_persp_correction->GetUniformLocationARB ("color");
552
nux::GetThreadGraphicsContext ()->SetTexture(GL_TEXTURE0, icon);
554
if(TextureObjectLocation != -1)
555
CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
557
int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
558
if(VPMatrixLocation != -1)
560
nux::Matrix4 mat = nux::GetThreadGraphicsContext ()->GetModelViewProjectionMatrix ();
561
_shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
566
_AsmShaderProg->Begin();
568
VertexLocation = nux::VTXATTRIB_POSITION;
569
TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
570
VertexColorLocation = nux::VTXATTRIB_COLOR;
572
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
575
CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
576
CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
578
if(TextureCoord0Location != -1)
580
CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
581
CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
584
if(VertexColorLocation != -1)
586
CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
587
CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
590
nux::Color bkg_color = nux::Color::White;
591
nux::Color white = nux::Color::White;
595
CHECKGL ( glUniform4fARB (FragmentColor, white.R(), white.G(), white.B(), white.A() ) );
596
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
597
CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
601
CHECKGL ( glProgramLocalParameter4fARB (GL_FRAGMENT_PROGRAM_ARB, 0, white.R(), white.G(), white.B(), white.A() ) );
602
nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
603
CHECKGL( glDrawArrays(GL_QUADS, 0, 4) );
606
if(VertexLocation != -1)
607
CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
608
if(TextureCoord0Location != -1)
609
CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
610
if(VertexColorLocation != -1)
611
CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
615
_shader_program_uv_persp_correction->End();
619
_AsmShaderProg->End();
622
int markerCenter = (v1.y + v0.y) / 2;
624
if (launcher_view->Active ())
626
if (!m_ActiveIndicator)
628
GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/focused_indicator.png", NULL);
629
m_ActiveIndicator = nux::CreateTextureFromPixbuf (pbuf);
630
g_object_unref (pbuf);
632
gPainter.Draw2DTexture (GfxContext, m_ActiveIndicator, geo.width - m_ActiveIndicator->GetWidth (), markerCenter - (m_ActiveIndicator->GetHeight () / 2));
636
void Launcher::DrawContent(nux::GraphicsContext& GfxContext, bool force_draw)
638
nux::Geometry base = GetGeometry();
639
GfxContext.PushClippingRectangle(base);
643
ROP.SrcBlend = GL_SRC_ALPHA;
644
ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
646
gPainter.PushDrawColorLayer(GfxContext, base, nux::Color(0x99000000), true, ROP);
647
gPainter.PushDrawColorLayer(GfxContext, nux::Geometry (base.x + base.width - 1, base.y, 1, base.height), nux::Color(0x60FFFFFF), true, ROP);
649
LauncherModel::reverse_iterator rev_it;
650
for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
652
if ((*rev_it)->_folding_angle >= 0.0f)
655
GfxContext.GetRenderStates ().SetSeparateBlend (true,
657
GL_ONE_MINUS_SRC_ALPHA,
658
GL_ONE_MINUS_DST_ALPHA,
661
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
662
RenderIcon(GfxContext, *rev_it);
664
GfxContext.GetRenderStates ().SetSeparateBlend (true,
666
GL_ONE_MINUS_SRC_ALPHA,
667
GL_ONE_MINUS_DST_ALPHA,
669
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
670
RenderIconImage (GfxContext, *rev_it);
673
LauncherModel::iterator it;
674
for (it = _model->begin(); it != _model->end(); it++)
676
if ((*it)->_folding_angle < 0.0f)
678
GfxContext.GetRenderStates ().SetSeparateBlend (true,
680
GL_ONE_MINUS_SRC_ALPHA,
681
GL_ONE_MINUS_DST_ALPHA,
684
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
685
RenderIcon(GfxContext, *it);
687
GfxContext.GetRenderStates ().SetSeparateBlend (true,
689
GL_ONE_MINUS_SRC_ALPHA,
690
GL_ONE_MINUS_DST_ALPHA,
692
GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
693
RenderIconImage (GfxContext, *it);
696
GfxContext.GetRenderStates().SetColorMask (true, true, true, true);
697
GfxContext.GetRenderStates().SetBlend(false);
698
gPainter.PopBackground();
699
GfxContext.PopClippingRectangle();
702
void Launcher::PostDraw(nux::GraphicsContext& GfxContext, bool force_draw)
707
void Launcher::OrderRevealedIcons()
709
nux::Geometry geo = GetGeometry();
710
int x = geo.x + (geo.width - _icon_size) / 2;
711
int y = geo.y + _launcher_top_y;
713
LauncherModel::iterator it;
714
for(it = _model->begin(); it != _model->end(); it++)
716
(*it)->_folding_angle_delta = 0.0f - (*it)->_folding_angle;
717
(*it)->_position_delta.x = x - (*it)->_position.x;
718
(*it)->_position_delta.y = y - (*it)->_position.y;
719
(*it)->_position_delta.z = 0 - (*it)->_position.z;
721
y += _icon_size + _space_between_icons;
724
_launcher_bottom_y = y - _space_between_icons;
727
void Launcher::OrderFoldedIcons(int focus_icon_index)
729
nux::Geometry geo = GetGeometry();
730
int total_height = geo.GetHeight();
732
int x = geo.x + (geo.width - _icon_size) / 2;
735
int num_icons = _model->Size();
740
focus_icon_index = 0;
742
if (focus_icon_index > num_icons - 1)
743
focus_icon_index = num_icons - 1;
745
if (focus_icon_index < 0)
746
focus_icon_index = 0;
748
int icons_revealed; // a block of consecutive, totally expanded icons. Should be odd number.
750
if (total_height > num_icons * (_icon_size + _space_between_icons))
752
// all icons will be expanded
753
icons_revealed = num_icons;
757
icons_revealed = total_height / (_icon_size + _space_between_icons);
758
if (icons_revealed > num_icons)
759
icons_revealed = num_icons;
760
if (icons_revealed <= 0)
764
int half = (icons_revealed)/2;
765
int icons_top_center = half; // number of icons around the middle icon in the block of expanded icons.
766
int icons_bottom_center = half; // number of icons around the middle icon in the block of expanded icons.
768
if ((icons_revealed % 2) == 0)
770
icons_top_center = half - 1;
771
icons_bottom_center = half;
775
icons_top_center = half;
776
icons_bottom_center = half;
779
if (focus_icon_index - icons_top_center < 0)
781
icons_bottom_center += icons_top_center - (focus_icon_index);
782
icons_top_center = focus_icon_index;
785
if (focus_icon_index + icons_bottom_center > num_icons - 1)
787
icons_bottom_center = (num_icons - 1) - focus_icon_index;
788
icons_top_center += focus_icon_index + half - (num_icons - 1);
791
int icons_above = nux::Max<int> (0, focus_icon_index - icons_top_center);
792
int icons_below = nux::Max<int> (0, (num_icons - 1) - (focus_icon_index + icons_bottom_center));
794
int box_height = icons_revealed * (_icon_size + _space_between_icons);
795
int space_above = icons_above * float (total_height - box_height) / float (icons_above + icons_below);
796
int space_below = icons_below * float (total_height - box_height) / float (icons_above + icons_below);
800
LauncherModel::iterator it;
801
for(it = _model->begin(), index = 0; it != _model->end(); it++, index++)
803
if (index < icons_above)
805
(*it)->_folding_angle_delta = _folded_angle - (*it)->_folding_angle;
806
(*it)->_position_delta.x = x - (*it)->_position.x;
807
(*it)->_position_delta.y = y - (*it)->_position.y;
808
(*it)->_position_delta.z = _folded_z_distance - (*it)->_position.z;
809
y += space_above / icons_above;
812
if ((index >= focus_icon_index - icons_top_center) && (index <= focus_icon_index + icons_bottom_center))
814
if(index == focus_icon_index)
815
_launcher_top_y = y - (icons_top_center + icons_above) * (_icon_size + _space_between_icons);
817
(*it)->_folding_angle_delta = 0.0f - (*it)->_folding_angle;
818
(*it)->_position_delta.x = x - (*it)->_position.x;
819
(*it)->_position_delta.y = y - (*it)->_position.y;
820
(*it)->_position_delta.z = 0.0f - (*it)->_position.z;
821
y += _icon_size + _space_between_icons;
825
if ((index > focus_icon_index + icons_bottom_center))
827
if(index == focus_icon_index + icons_bottom_center + 1)
830
(*it)->_folding_angle_delta = _neg_folded_angle - (*it)->_folding_angle;
831
(*it)->_position_delta.x = x - (*it)->_position.x;
832
(*it)->_position_delta.y = y - (*it)->_position.y;
833
(*it)->_position_delta.z = _folded_z_distance - (*it)->_position.z;
834
y += space_below / icons_below;
838
_launcher_bottom_y = y;
841
void Launcher::ScheduleRevealAnimation ()
843
_launcher_state = LAUNCHER_UNFOLDED;
844
OrderRevealedIcons();
846
if(nux::GetThreadTimer().FindTimerHandle(_folding_timer_handle))
848
nux::GetThreadTimer().RemoveTimerHandler(_folding_timer_handle);
850
_folding_timer_handle = 0;
852
if(!nux::GetThreadTimer().FindTimerHandle(_reveal_timer_handle))
854
_reveal_timer_handle = nux::GetThreadTimer().AddPeriodicTimerHandler(_timer_intervals, _anim_duration, _reveal_functor, this);
858
void Launcher::ScheduleFoldAnimation ()
860
_launcher_state = LAUNCHER_FOLDED;
863
if(nux::GetThreadTimer().FindTimerHandle(_reveal_timer_handle))
865
nux::GetThreadTimer().RemoveTimerHandler(_reveal_timer_handle);
867
_reveal_timer_handle = 0;
869
if(!nux::GetThreadTimer().FindTimerHandle(_folding_timer_handle))
871
_folding_timer_handle = nux::GetThreadTimer().AddPeriodicTimerHandler(_timer_intervals, _anim_duration, _folding_functor, this);
875
void Launcher::PreLayoutManagement()
877
View::PreLayoutManagement();
878
if(m_CompositionLayout)
880
m_CompositionLayout->SetGeometry(GetGeometry());
884
long Launcher::PostLayoutManagement(long LayoutResult)
886
View::PostLayoutManagement(LayoutResult);
888
_mouse_position = nux::Point2 (0, 0);
889
ScheduleFoldAnimation ();
891
return nux::eCompliantHeight | nux::eCompliantWidth;
894
void Launcher::PositionChildLayout(float offsetX, float offsetY)
898
void Launcher::SlideDown(float stepy, int mousedy)
903
void Launcher::SlideUp(float stepy, int mousedy)
908
bool Launcher::TooltipNotify(LauncherIcon* Icon)
910
if(GetActiveMenuIcon())
915
bool Launcher::MenuNotify(LauncherIcon* Icon)
917
// if(GetActiveMenuIcon())
920
// m_ActiveMenuIcon = Icon;
924
void Launcher::NotifyMenuTermination(LauncherIcon* Icon)
926
// if(Icon == GetActiveMenuIcon())
927
// m_ActiveMenuIcon = NULL;
930
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
932
_mouse_position = nux::Point2 (x, y);
940
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
942
_mouse_position = nux::Point2 (x, y);
943
nux::Geometry geo = GetGeometry ();
945
if (!geo.IsInside(nux::Point(x, y)))
946
ScheduleFoldAnimation ();
947
else if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
949
if (_launcher_top_y > 0)
953
else if ((_launcher_bottom_y < geo.height))
955
_launcher_top_y += geo.height - _launcher_bottom_y;
956
if (_launcher_top_y > 0)
959
ScheduleRevealAnimation ();
964
_launcher_action_state = ACTION_NONE;
968
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
970
_mouse_position = nux::Point2 (x, y);
971
nux::Geometry geo = GetGeometry ();
972
float dampening_factor;
974
if (nux::Abs (_dnd_delta) < 15)
977
if (nux::Abs (_dnd_delta) < 15)
982
if ((nux::Abs (_dnd_delta) >= _dnd_security) && (_launcher_action_state != ACTION_DRAG_LAUNCHER))
984
_launcher_action_state = ACTION_DRAG_LAUNCHER;
986
LauncherModel::iterator it;
987
for(it = _model->begin(); it != _model->end(); it++)
989
(*it)->HideTooltip ();
1000
dampening_factor = 1.0f;
1002
_launcher_top_y += dampening_factor * DY;
1003
_launcher_bottom_y += dampening_factor * DY;
1005
LauncherModel::iterator it;
1006
for(it = _model->begin(); it != _model->end(); it++)
1008
(*it)->_position.y += DY * dampening_factor;
1013
dampening_factor = 1.0f;
1015
_launcher_top_y += dampening_factor * DY;
1016
_launcher_bottom_y += dampening_factor * DY;
1019
LauncherModel::iterator it;
1020
for(it = _model->begin(); it != _model->end(); it++)
1022
(*it)->_position.y += DY * dampening_factor;
1032
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
1034
_mouse_position = nux::Point2 (x, y);
1035
if (_launcher_action_state == ACTION_NONE)
1036
ScheduleRevealAnimation ();
1043
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
1045
_mouse_position = nux::Point2 (x, y);
1046
if (_launcher_action_state == ACTION_NONE)
1047
ScheduleFoldAnimation ();
1054
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
1056
_mouse_position = nux::Point2 (x, y);
1058
// Every time the mouse moves, we check if it is inside an icon...
1065
void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
1067
nux::Geometry geo = GetGeometry ();
1068
float dampening_factor;
1069
if (!geo.IsInside(nux::Point(x, y)))
1072
if (wheel_delta > 0)
1074
if(_launcher_top_y >= 200.0f)
1077
dampening_factor = nux::Min<float> (1.0f, float (200.0f - _launcher_top_y) / 200.0f);
1079
_launcher_top_y += dampening_factor * wheel_delta;
1080
_launcher_bottom_y += dampening_factor * wheel_delta;
1082
if(_launcher_top_y >= 200.0f)
1083
_launcher_top_y = 200;
1085
LauncherModel::iterator it;
1086
for(it = _model->begin(); it != _model->end(); it++)
1088
(*it)->_position.y += wheel_delta * dampening_factor;
1093
if(_launcher_bottom_y <= geo.height - 200.0f)
1096
dampening_factor = nux::Min<float> (1.0f, float (_launcher_bottom_y - (geo.height - 200.0f)) / 200.0f);
1098
_launcher_top_y += dampening_factor * wheel_delta;
1099
_launcher_bottom_y += dampening_factor * wheel_delta;
1101
if(_launcher_bottom_y <= geo.height - 200.0f)
1102
_launcher_bottom_y = geo.height - 200.0f;
1104
LauncherModel::iterator it;
1105
for(it = _model->begin(); it != _model->end(); it++)
1107
(*it)->_position.y += wheel_delta * dampening_factor;
1116
void Launcher::FoldingCallback(void* v)
1118
LauncherModel::iterator it;
1119
for(it = _model->begin(); it != _model->end(); it++)
1121
(*it)->_folding_angle += _folding_timer_handle.GetProgressDelta() * (*it)->_folding_angle_delta;
1123
(*it)->_position.x += _folding_timer_handle.GetProgressDelta() * (*it)->_position_delta.x;
1124
(*it)->_position.y += _folding_timer_handle.GetProgressDelta() * (*it)->_position_delta.y;
1125
(*it)->_position.z += _folding_timer_handle.GetProgressDelta() * (*it)->_position_delta.z;
1133
void Launcher::RevealCallback(void* v)
1135
LauncherModel::iterator it;
1136
for(it = _model->begin(); it != _model->end(); it++)
1138
(*it)->_folding_angle += _reveal_timer_handle.GetProgressDelta() * (*it)->_folding_angle_delta;
1140
(*it)->_position.x += _reveal_timer_handle.GetProgressDelta() * (*it)->_position_delta.x;
1141
(*it)->_position.y += _reveal_timer_handle.GetProgressDelta() * (*it)->_position_delta.y;
1142
(*it)->_position.z += _reveal_timer_handle.GetProgressDelta() * (*it)->_position_delta.z;
1150
void Launcher::EventLogic ()
1152
if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
1155
LauncherIcon* launcher_icon = 0;
1156
launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
1158
if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
1160
_icon_under_mouse->MouseLeave.emit ();
1161
_icon_under_mouse->_mouse_inside = false;
1162
_icon_under_mouse = 0;
1165
if (launcher_icon && (_icon_under_mouse != launcher_icon))
1167
launcher_icon->MouseEnter.emit ();
1168
launcher_icon->_mouse_inside = true;
1169
_icon_under_mouse = launcher_icon;
1173
void Launcher::MouseDownLogic ()
1175
LauncherIcon* launcher_icon = 0;
1176
launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
1180
_icon_mouse_down = launcher_icon;
1181
launcher_icon->MouseDown.emit ();
1185
void Launcher::MouseUpLogic ()
1187
LauncherIcon* launcher_icon = 0;
1188
launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
1190
if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
1192
_icon_mouse_down->MouseUp.emit ();
1194
if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
1195
_icon_mouse_down->MouseClick.emit ();
1198
if (launcher_icon && (_icon_mouse_down != launcher_icon))
1200
launcher_icon->MouseUp.emit ();
1203
_icon_mouse_down = 0;
1206
LauncherIcon* Launcher::MouseIconIntersection (int x, int y)
1208
// We are looking for the icon at screen coordinates x, y;
1209
nux::Point2 mouse_position(x, y);
1212
// Because of the way icons fold and stack on one another, we must proceed in 2 steps.
1213
LauncherModel::reverse_iterator rev_it;
1214
for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
1216
if ((*rev_it)->_folding_angle < 0.0f)
1219
nux::Point2 screen_coord [4];
1220
for (int i = 0; i < 4; i++)
1222
screen_coord [i].x = (*rev_it)->_xform_screen_coord [i].x;
1223
screen_coord [i].y = (*rev_it)->_xform_screen_coord [i].y;
1225
inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
1230
LauncherModel::iterator it;
1231
for (it = _model->begin(); it != _model->end (); it++)
1233
if ((*it)->_folding_angle >= 0.0f)
1236
nux::Point2 screen_coord [4];
1237
for (int i = 0; i < 4; i++)
1239
screen_coord [i].x = (*it)->_xform_screen_coord [i].x;
1240
screen_coord [i].y = (*it)->_xform_screen_coord [i].y;
1242
inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
1250
void Launcher::UpdateIconXForm ()
1253
nux::Geometry geo = GetGeometry ();
1254
nux::Matrix4 ObjectMatrix;
1255
nux::Matrix4 ViewMatrix;
1256
nux::Matrix4 ProjectionMatrix;
1257
nux::Matrix4 ViewProjectionMatrix;
1259
GetInverseScreenPerspectiveMatrix(ViewMatrix, ProjectionMatrix, geo.width, geo.height, 0.1f, 1000.0f, DEGTORAD(90));
1261
LauncherModel::iterator it;
1262
for(it = _model->begin(); it != _model->end(); it++)
1264
LauncherIcon* launcher_icon = *it;
1266
float w = _icon_size;
1267
float h = _icon_size;
1268
float x = launcher_icon->_position.x;
1269
float y = launcher_icon->_position.y;
1270
float z = launcher_icon->_position.z;
1272
ObjectMatrix = nux::Matrix4::TRANSLATE(geo.width/2.0f, geo.height/2.0f, z) * // Translate the icon to the center of the viewport
1273
nux::Matrix4::ROTATEX(launcher_icon->_folding_angle) * // rotate the icon
1274
nux::Matrix4::TRANSLATE(-x - w/2.0f, -y - h/2.0f, -z); // Put the center the icon to (0, 0)
1276
ViewProjectionMatrix = ProjectionMatrix*ViewMatrix*ObjectMatrix;
1279
nux::Vector4 v0 = nux::Vector4(x, y, z, 1.0f);
1280
nux::Vector4 v1 = nux::Vector4(x, y+h, z, 1.0f);
1281
nux::Vector4 v2 = nux::Vector4(x+w, y+h, z, 1.0f);
1282
nux::Vector4 v3 = nux::Vector4(x+w, y, z, 1.0f);
1284
v0 = ViewProjectionMatrix * v0;
1285
v1 = ViewProjectionMatrix * v1;
1286
v2 = ViewProjectionMatrix * v2;
1287
v3 = ViewProjectionMatrix * v3;
1289
v0.divide_xyz_by_w();
1290
v1.divide_xyz_by_w();
1291
v2.divide_xyz_by_w();
1292
v3.divide_xyz_by_w();
1294
// normalize to the viewport coordinates and translate to the correct location
1295
v0.x = geo.width *(v0.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1296
v0.y = -geo.height*(v0.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1297
v1.x = geo.width *(v1.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;;
1298
v1.y = -geo.height*(v1.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1299
v2.x = geo.width *(v2.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1300
v2.y = -geo.height*(v2.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1301
v3.x = geo.width *(v3.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1302
v3.y = -geo.height*(v3.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1305
launcher_icon->_xform_screen_coord[0].x = v0.x;
1306
launcher_icon->_xform_screen_coord[0].y = v0.y;
1307
launcher_icon->_xform_screen_coord[0].z = v0.z;
1308
launcher_icon->_xform_screen_coord[0].w = v0.w;
1309
launcher_icon->_xform_screen_coord[1].x = v1.x;
1310
launcher_icon->_xform_screen_coord[1].y = v1.y;
1311
launcher_icon->_xform_screen_coord[1].z = v1.z;
1312
launcher_icon->_xform_screen_coord[1].w = v1.w;
1313
launcher_icon->_xform_screen_coord[2].x = v2.x;
1314
launcher_icon->_xform_screen_coord[2].y = v2.y;
1315
launcher_icon->_xform_screen_coord[2].z = v2.z;
1316
launcher_icon->_xform_screen_coord[2].w = v2.w;
1317
launcher_icon->_xform_screen_coord[3].x = v3.x;
1318
launcher_icon->_xform_screen_coord[3].y = v3.y;
1319
launcher_icon->_xform_screen_coord[3].z = v3.z;
1320
launcher_icon->_xform_screen_coord[3].w = v3.w;
1324
w = _icon_image_size;
1325
h = _icon_image_size;
1326
x = launcher_icon->_position.x + _icon_image_size_delta/2;
1327
y = launcher_icon->_position.y + _icon_image_size_delta/2;
1328
z = launcher_icon->_position.z;
1330
v0 = nux::Vector4(x, y, z, 1.0f);
1331
v1 = nux::Vector4(x, y+h, z, 1.0f);
1332
v2 = nux::Vector4(x+w, y+h, z, 1.0f);
1333
v3 = nux::Vector4(x+w, y, z, 1.0f);
1335
v0 = ViewProjectionMatrix * v0;
1336
v1 = ViewProjectionMatrix * v1;
1337
v2 = ViewProjectionMatrix * v2;
1338
v3 = ViewProjectionMatrix * v3;
1340
v0.divide_xyz_by_w();
1341
v1.divide_xyz_by_w();
1342
v2.divide_xyz_by_w();
1343
v3.divide_xyz_by_w();
1345
// normalize to the viewport coordinates and translate to the correct location
1346
v0.x = geo.width *(v0.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1347
v0.y = -geo.height*(v0.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1348
v1.x = geo.width *(v1.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;;
1349
v1.y = -geo.height*(v1.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1350
v2.x = geo.width *(v2.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1351
v2.y = -geo.height*(v2.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1352
v3.x = geo.width *(v3.x + 1.0f)/2.0f - geo.width/2.0f + x + w/2.0f;
1353
v3.y = -geo.height*(v3.y - 1.0f)/2.0f - geo.height/2.0f + y + h/2.0f;
1356
launcher_icon->_xform_icon_screen_coord[0].x = v0.x;
1357
launcher_icon->_xform_icon_screen_coord[0].y = v0.y;
1358
launcher_icon->_xform_icon_screen_coord[0].z = v0.z;
1359
launcher_icon->_xform_icon_screen_coord[0].w = v0.w;
1360
launcher_icon->_xform_icon_screen_coord[1].x = v1.x;
1361
launcher_icon->_xform_icon_screen_coord[1].y = v1.y;
1362
launcher_icon->_xform_icon_screen_coord[1].z = v1.z;
1363
launcher_icon->_xform_icon_screen_coord[1].w = v1.w;
1364
launcher_icon->_xform_icon_screen_coord[2].x = v2.x;
1365
launcher_icon->_xform_icon_screen_coord[2].y = v2.y;
1366
launcher_icon->_xform_icon_screen_coord[2].z = v2.z;
1367
launcher_icon->_xform_icon_screen_coord[2].w = v2.w;
1368
launcher_icon->_xform_icon_screen_coord[3].x = v3.x;
1369
launcher_icon->_xform_icon_screen_coord[3].y = v3.y;
1370
launcher_icon->_xform_icon_screen_coord[3].z = v3.z;
1371
launcher_icon->_xform_icon_screen_coord[3].w = v3.w;
1375
void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
1378
float NearClipPlane,
1384
Given a perspective matrix defined by (Fovy, AspectRatio, NearPlane, FarPlane), we want to compute
1385
the ModelView matrix that transform a quad defined by its top-left coord (0, 0) and its
1386
bottom-right coord (WindowWidth, WindowHeight) into a full screen quad that covers the entire viewport (one to one).
1387
Any quad that is facing the camera and whose 4 points are on the 4 guiding line of the view frustum (pyramid)
1388
will always cover the entire viewport one to one (when projected on the screen).
1389
So all we have to do is to define a quad with x:[-x_cs, x_cs] and y:[-y_cs, y_cs] and find the z distance in eye space (z_cs) so that
1390
the quad touches the 4 guiding lines of the view frustum.
1391
We consider a well centered projection view (no skewing, no oblique clipping plane, ...) and derive the following equations:
1392
x_cs = AspectRatio*y_cs
1393
y_cs/z_cs = tanf(Fovy/2) ==> z_cs = y_cs*1/tanf(Fovy/2) (this is the absolute value the quad depth value will be -z_cs since we are using OpenGL right hand coord system).
1395
The quad (in camera space) facing the camera and centered around the camera view axis is defined by the points (-x_cs, y_cs) (top-left)
1396
and the point (x_cs, -y_cs) (bottom-right). If we move that quad along the camera view axis and place it at a distance z_cs of the camera,
1397
then its 4 corners are each on the 4 lines of the view frustum.
1399
(-x_cs, y_cs) Camera Space
1401
__________|__________
1405
|----------|----------|->
1408
|__________|__________|
1411
The full-screen quad (in screen space) is defined by the point (0, 0) (top-left) and (WindowWidth, WindowHeight) (bottom-right).
1412
We can choose and arbitrary value y_cs and compute the z_cs position in camera space that will produce a quad in camera space that projects into
1413
the full-screen space.
1416
_____________________->
1420
|----------|----------|
1423
|__________|__________|
1424
v (WindowWidth, WindowHeight)
1426
The model view matrix is the succession of transformation that convert the quad (0, 0, WindowWidth, WindowHeight) into
1427
the quad (-x_cs, y_cs, x_cs, -y_cs)
1429
Screen Space Camera Space
1430
x ----> x_ = x*2*x_cs/WindowWidth - x_cs
1431
y ----> y_ = -y*2*y_cs/WindowHeight + y_cs
1432
z ----> z_ = A*z -y_cs*1/tanf(Fovy/2)
1433
where A is a coefficient that can attenuate the rate of change in depth when the quad moves along the camera axis
1435
If the following is the projection matrix:
1437
(a, 0, 0, 0) a = 1/(AspectRatio*tan(Fovy/2))
1438
(0, b, 0, 0) b = 1/tan(Fovy/2)
1442
and the camera space vertex is (x_cs, y_cs, z_cs, w_cs) projects to the top left corner of the view port on the screen ((-1, 1) in clip space), then
1443
x_cs*a/(-z_cs) = -1; | z_cs = x_cs*a x_cs*a = -y_cs*b ==> x_cs = y_cs*AspectRatio
1445
y_cs*b/(-z_cs) = +1; | z_cs = -y_cs*b z_cs = -y_cs*1/tanf(Fovy/2)
1449
float AspectRatio = (float)ViewportWidth/(float)ViewportHeight;
1450
float CameraToScreenDistance = -1.0f;
1451
float y_cs = -CameraToScreenDistance*tanf(0.5f*Fovy/* *3.1415926/180.0f*/);
1452
float x_cs = y_cs*AspectRatio;
1453
//float CameraToScreenDistance = -y_cs*1.0f/(tanf(0.5f*Fovy/* *3.1415926/180.0f*/));
1455
ViewMatrix = nux::Matrix4::TRANSLATE(-x_cs, y_cs, CameraToScreenDistance) *
1456
nux::Matrix4::SCALE(2.0f*x_cs/ViewportWidth, -2.0f*y_cs/ViewportHeight, -2.0f * 3 * y_cs/ViewportHeight /* or -2.0f * x_cs/ViewportWidth*/ );
1458
PerspectiveMatrix.Perspective(Fovy, AspectRatio, NearClipPlane, FarClipPlane);
1460
// // Example usage with the matrices above:
1464
// float X = (ViewportWidth - W)/2.0;
1465
// float Y = (ViewportHeight - H)/2.0;
1470
// // Local Transformation of the object
1471
// glTranslatef(0.0f, 0.0f, ObjectDistanceToCamera);
1472
// glTranslatef(X + W/2.0f, Y + H/2.0f, 0.0f);
1473
// glRotatef(cameraAngleY, 1, 0, 0);
1474
// glRotatef(cameraAngleX, 0, 1, 0);
1475
// glTranslatef(-X - W/2.0f, -Y - H/2.0f, 0.0f);
1477
// glBegin(GL_QUADS);
1479
// glNormal3f(0.0f, 0.0f, 1.0f);
1481
// glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
1482
// glVertex4f(X, Y, Z, 1.0f);
1484
// glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
1485
// glVertex4f(X, Y+H, Z, 1.0f);
1487
// glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
1488
// glVertex4f(X+W, Y+H, Z, 1.0f);
1490
// glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
1491
// glVertex4f(X+W, Y, Z, 1.0f);