~didrocks/unity/launcher-bug-fix-fest

« back to all changes in this revision

Viewing changes to src/Launcher.cpp

Import the work done so far with Compiz

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#include "Nux/Nux.h"
 
2
#include "Nux/VScrollBar.h"
 
3
#include "Nux/HLayout.h"
 
4
#include "Nux/VLayout.h"
 
5
#include "Nux/MenuPage.h"
 
6
 
 
7
#include "NuxGraphics/NuxGraphics.h"
 
8
#include "NuxGraphics/GLDeviceFactory.h"
 
9
#include "NuxGraphics/GLTextureResourceManager.h"
 
10
 
 
11
#include "Nux/BaseWindow.h"
 
12
#include "Nux/WindowCompositor.h"
 
13
 
 
14
#include "Launcher.h"
 
15
#include "LauncherIcon.h"
 
16
#include "LauncherModel.h"
 
17
 
 
18
static bool USE_ARB_SHADERS = true;
 
19
/*                                                                                                       
 
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)
 
27
 
 
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.
 
31
                                                                                                                                
 
32
        */                                                                                                                    
 
33
 
 
34
nux::NString gPerspectiveCorrectShader = TEXT (
 
35
"[Vertex Shader]                                                        \n\
 
36
#version 120                                                            \n\
 
37
uniform mat4 ViewProjectionMatrix;                                      \n\
 
38
                                                                        \n\
 
39
attribute vec4 iColor;                                                  \n\
 
40
attribute vec4 iTexCoord0;                                              \n\
 
41
attribute vec4 iVertex;                                                 \n\
 
42
                                                                        \n\
 
43
varying vec4 varyTexCoord0;                                             \n\
 
44
varying vec4 varyVertexColor;                                           \n\
 
45
                                                                        \n\
 
46
void main()                                                             \n\
 
47
{                                                                       \n\
 
48
    varyTexCoord0 = iTexCoord0;                                         \n\
 
49
    varyVertexColor = iColor;                                           \n\
 
50
    gl_Position =  ViewProjectionMatrix * iVertex;                      \n\
 
51
}                                                                       \n\
 
52
                                                                        \n\
 
53
[Fragment Shader]                                                       \n\
 
54
#version 120                                                            \n\
 
55
#extension GL_ARB_texture_rectangle : enable                            \n\
 
56
                                                                        \n\
 
57
varying vec4 varyTexCoord0;                                             \n\
 
58
varying vec4 varyVertexColor;                                           \n\
 
59
                                                                        \n\
 
60
uniform sampler2D TextureObject0;                                       \n\
 
61
uniform vec4 color0;                                                     \n\
 
62
vec4 SampleTexture(sampler2D TexObject, vec4 TexCoord)                  \n\
 
63
{                                                                       \n\
 
64
  return texture2D(TexObject, TexCoord.st);                             \n\
 
65
}                                                                       \n\
 
66
                                                                        \n\
 
67
void main()                                                             \n\
 
68
{                                                                       \n\
 
69
  vec4 tex = varyTexCoord0;                                             \n\
 
70
  tex.s = tex.s/varyTexCoord0.w;                                        \n\
 
71
  tex.t = tex.t/varyTexCoord0.w;                                        \n\
 
72
                                                                              \n\
 
73
  vec4 texel = SampleTexture(TextureObject0, tex);                      \n\
 
74
  gl_FragColor = texel*varyVertexColor;                                 \n\
 
75
}                                                                       \n\
 
76
");
 
77
 
 
78
nux::NString PerspectiveCorrectVtx = TEXT (
 
79
                            "!!ARBvp1.0                                 \n\
 
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\
 
93
                            END");
 
94
 
 
95
 
 
96
 
 
97
nux::NString PerspectiveCorrectTexFrg = TEXT (
 
98
                            "!!ARBfp1.0                                 \n\
 
99
                            PARAM color0 = program.local[0];            \n\
 
100
                            TEMP temp;                                  \n\
 
101
                            TEMP pcoord;                                \n\
 
102
                            TEMP tex0;                                  \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\
 
108
                            END");
 
109
 
 
110
nux::NString PerspectiveCorrectTexRectFrg = TEXT (
 
111
                            "!!ARBfp1.0                                 \n\
 
112
                            PARAM color0 = program.local[0];            \n\
 
113
                            TEMP temp;                                  \n\
 
114
                            TEMP pcoord;                                \n\
 
115
                            TEMP tex0;                                  \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\
 
121
                            END");
 
122
 
 
123
static void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
 
124
                                       int ViewportWidth,
 
125
                                       int ViewportHeight,
 
126
                                       float NearClipPlane,
 
127
                                       float FarClipPlane,
 
128
                                       float Fovy);
 
129
 
 
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)
 
136
,   _model (0)
 
137
{
 
138
    m_Layout = new nux::HLayout(NUX_TRACKER_LOCATION);
 
139
 
 
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));
 
147
 
 
148
    m_ActiveTooltipIcon = NULL;
 
149
    m_ActiveMenuIcon = NULL;
 
150
 
 
151
    SetCompositionLayout(m_Layout);
 
152
 
 
153
    if(!USE_ARB_SHADERS)
 
154
    {
 
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();
 
158
    }
 
159
    else
 
160
    {
 
161
      _AsmShaderProg = nux::GetThreadGLDeviceFactory()->CreateAsmShaderProgram();
 
162
      _AsmShaderProg->LoadVertexShader (TCHAR_TO_ANSI (*PerspectiveCorrectVtx) );
 
163
      
 
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 ()))
 
166
      {
 
167
        // No support for non power of two textures but support for rectangle textures
 
168
        _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexRectFrg) );
 
169
      }
 
170
      else
 
171
      {
 
172
        _AsmShaderProg->LoadPixelShader (TCHAR_TO_ANSI (*PerspectiveCorrectTexFrg) );
 
173
      }
 
174
 
 
175
      _AsmShaderProg->Link();
 
176
    }
 
177
 
 
178
    _folding_functor = new nux::TimerFunctor();
 
179
    _folding_functor->OnTimerExpired.connect(sigc::mem_fun(this, &Launcher::FoldingCallback));
 
180
 
 
181
    _reveal_functor = new nux::TimerFunctor();
 
182
    _reveal_functor->OnTimerExpired.connect(sigc::mem_fun(this, &Launcher::RevealCallback));
 
183
 
 
184
    _folded_angle         = 1.0f;
 
185
    _neg_folded_angle     = -1.0f;
 
186
    _folding_angle        = _folded_angle;
 
187
    _timer_intervals      = 16;
 
188
    _angle_rate           = 0.1f;
 
189
    _space_between_icons  = 5;
 
190
    _anim_duration        = 200;
 
191
    _launcher_top_y       = 0;
 
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");
 
203
    _dnd_security           = 15;
 
204
}
 
205
 
 
206
Launcher::~Launcher()
 
207
{
 
208
 
 
209
}
 
210
 
 
211
void Launcher::SetIconSize(int tile_size, int icon_size, nux::BaseWindow *parent)
 
212
{
 
213
    nux::Geometry geo = parent->GetGeometry ();
 
214
    
 
215
    _icon_size = tile_size;
 
216
    _icon_image_size = icon_size;
 
217
    _icon_image_size_delta = tile_size - icon_size;
 
218
    
 
219
    // recreate tile textures
 
220
    
 
221
    parent->SetGeometry (nux::Geometry (geo.x, geo.y, tile_size + 12, geo.height));
 
222
}
 
223
 
 
224
void Launcher::OnIconAdded (void *icon_pointer)
 
225
{
 
226
    LauncherIcon *icon = (LauncherIcon *) icon_pointer;
 
227
 
 
228
    if (_launcher_state == LAUNCHER_UNFOLDED)
 
229
      ScheduleRevealAnimation ();
 
230
    else
 
231
      ScheduleFoldAnimation ();
 
232
 
 
233
    NeedRedraw();
 
234
    
 
235
    // needs to be disconnected
 
236
    icon->needs_redraw.connect (sigc::mem_fun(this, &Launcher::OnIconNeedsRedraw));
 
237
}
 
238
 
 
239
void Launcher::OnIconRemoved (void *icon_pointer)
 
240
{
 
241
    if (_launcher_state == LAUNCHER_UNFOLDED)
 
242
      ScheduleRevealAnimation ();
 
243
    else
 
244
      ScheduleFoldAnimation ();
 
245
    
 
246
    NeedRedraw();
 
247
}
 
248
 
 
249
void Launcher::OnOrderChanged ()
 
250
{
 
251
 
 
252
}
 
253
 
 
254
void Launcher::SetModel (LauncherModel *model)
 
255
{
 
256
    _model = 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));
 
260
}
 
261
 
 
262
void Launcher::OnIconNeedsRedraw (void *icon)
 
263
{
 
264
    NeedRedraw();
 
265
}
 
266
 
 
267
long Launcher::ProcessEvent(nux::IEvent &ievent, long TraverseInfo, long ProcessEventInfo)
 
268
{
 
269
    long ret = TraverseInfo;
 
270
    ret = PostProcessEvent2(ievent, ret, ProcessEventInfo);
 
271
    return ret;
 
272
}
 
273
 
 
274
void Launcher::Draw(nux::GraphicsContext& GfxContext, bool force_draw)
 
275
{
 
276
 
 
277
}
 
278
 
 
279
void Launcher::RenderIcon(nux::GraphicsContext& GfxContext, LauncherIcon* launcher_view)
 
280
{
 
281
  nux::Geometry geo = GetGeometry();
 
282
 
 
283
  nux::Matrix4 ObjectMatrix;
 
284
  nux::Matrix4 ViewMatrix;
 
285
  nux::Matrix4 ProjectionMatrix;
 
286
  nux::Matrix4 ViewProjectionMatrix;
 
287
  nux::BaseTexture *icon;
 
288
  
 
289
  if (launcher_view->Running ())
 
290
    icon = _icon_bkg_texture; 
 
291
  else
 
292
    icon = _icon_outline_texture;
 
293
  
 
294
  icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
 
295
 
 
296
  if(launcher_view->_folding_angle == 0.0f)
 
297
  {
 
298
    icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
 
299
  }
 
300
  else
 
301
  {
 
302
    icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
 
303
  }
 
304
 
 
305
  nux::Vector4 v0;
 
306
  nux::Vector4 v1;
 
307
  nux::Vector4 v2;
 
308
  nux::Vector4 v3;
 
309
 
 
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 ;
 
326
 
 
327
  nux::Color color;
 
328
  color = nux::Color::White;
 
329
 
 
330
  float s0, t0, s1, t1, s2, t2, s3, t3;
 
331
  
 
332
  if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
 
333
  {
 
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;
 
338
  }
 
339
  else
 
340
  {
 
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;
 
345
  }
 
346
 
 
347
  float VtxBuffer[] =
 
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(),
 
353
  };
 
354
 
 
355
  CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
 
356
  CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
 
357
 
 
358
  int TextureObjectLocation;
 
359
  int VertexLocation;
 
360
  int TextureCoord0Location;
 
361
  int VertexColorLocation;
 
362
  int FragmentColor;
 
363
 
 
364
  if(!USE_ARB_SHADERS)
 
365
  {
 
366
    _shader_program_uv_persp_correction->Begin();
 
367
 
 
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");
 
373
    
 
374
    nux::GetThreadGraphicsContext ()->SetTexture(GL_TEXTURE0, icon);
 
375
 
 
376
    if(TextureObjectLocation != -1)
 
377
      CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
 
378
 
 
379
    int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
 
380
    if(VPMatrixLocation != -1)
 
381
    {
 
382
      nux::Matrix4 mat = nux::GetThreadGraphicsContext ()->GetModelViewProjectionMatrix ();
 
383
      _shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
 
384
    }
 
385
  }
 
386
  else
 
387
  {
 
388
    _AsmShaderProg->Begin();
 
389
 
 
390
    VertexLocation        = nux::VTXATTRIB_POSITION;
 
391
    TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
 
392
    VertexColorLocation   = nux::VTXATTRIB_COLOR;
 
393
 
 
394
    nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
 
395
  }
 
396
 
 
397
  CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
 
398
  CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
 
399
 
 
400
  if(TextureCoord0Location != -1)
 
401
  {
 
402
    CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
 
403
    CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
 
404
  }
 
405
 
 
406
  if(VertexColorLocation != -1)
 
407
  {
 
408
    CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
 
409
    CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
 
410
  }
 
411
  
 
412
  nux::Color bkg_color;
 
413
  if (launcher_view->Running ())
 
414
    bkg_color = launcher_view->BackgroundColor ();
 
415
  else    
 
416
    bkg_color = nux::Color(0xFF6D6D6D);
 
417
    
 
418
  nux::Color white = nux::Color::White;
 
419
  
 
420
  if(!USE_ARB_SHADERS)
 
421
  {
 
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) );
 
425
  }
 
426
  else
 
427
  {
 
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) );
 
431
  }
 
432
  
 
433
  if(VertexLocation != -1)
 
434
    CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
 
435
  if(TextureCoord0Location != -1)
 
436
    CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
 
437
  if(VertexColorLocation != -1)
 
438
    CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
 
439
 
 
440
  if(!USE_ARB_SHADERS)
 
441
  {
 
442
    _shader_program_uv_persp_correction->End();
 
443
  }
 
444
  else
 
445
  {
 
446
    _AsmShaderProg->End();
 
447
  }
 
448
}
 
449
 
 
450
void Launcher::RenderIconImage(nux::GraphicsContext& GfxContext, LauncherIcon* launcher_view)
 
451
{
 
452
  nux::Geometry geo = GetGeometry();
 
453
 
 
454
  nux::Matrix4 ObjectMatrix;
 
455
  nux::Matrix4 ViewMatrix;
 
456
  nux::Matrix4 ProjectionMatrix;
 
457
  nux::Matrix4 ViewProjectionMatrix;
 
458
  nux::BaseTexture *icon;
 
459
 
 
460
  icon = launcher_view->TextureForSize (_icon_image_size);
 
461
  
 
462
  if(launcher_view->_folding_angle == 0.0f)
 
463
  {
 
464
    icon->GetDeviceTexture()->SetFiltering(GL_NEAREST, GL_NEAREST);
 
465
  }
 
466
  else
 
467
  {
 
468
    icon->GetDeviceTexture()->SetFiltering(GL_LINEAR, GL_LINEAR);
 
469
  }
 
470
 
 
471
  nux::Vector4 v0;
 
472
  nux::Vector4 v1;
 
473
  nux::Vector4 v2;
 
474
  nux::Vector4 v3;
 
475
 
 
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);
 
493
 
 
494
  nux::Color color;
 
495
  if(inside)
 
496
    color = nux::Color::Red;
 
497
  else
 
498
    color = nux::Color::White;
 
499
 
 
500
  float s0, t0, s1, t1, s2, t2, s3, t3;
 
501
  
 
502
  if (icon->Type ().IsDerivedFromType(nux::TextureRectangle::StaticObjectType))
 
503
  {
 
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;
 
508
  }
 
509
  else
 
510
  {
 
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;
 
515
  }
 
516
 
 
517
  float VtxBuffer[] =
 
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(),
 
523
  };
 
524
 
 
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,
 
531
  //         };
 
532
 
 
533
  CHECKGL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0));
 
534
  CHECKGL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
 
535
 
 
536
  int TextureObjectLocation;
 
537
  int VertexLocation;
 
538
  int TextureCoord0Location;
 
539
  int VertexColorLocation;
 
540
  int FragmentColor;
 
541
 
 
542
  if(!USE_ARB_SHADERS)
 
543
  {
 
544
    _shader_program_uv_persp_correction->Begin();
 
545
 
 
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");
 
551
    
 
552
    nux::GetThreadGraphicsContext ()->SetTexture(GL_TEXTURE0, icon);
 
553
 
 
554
    if(TextureObjectLocation != -1)
 
555
      CHECKGL( glUniform1iARB (TextureObjectLocation, 0) );
 
556
 
 
557
    int VPMatrixLocation = _shader_program_uv_persp_correction->GetUniformLocationARB("ViewProjectionMatrix");
 
558
    if(VPMatrixLocation != -1)
 
559
    {
 
560
      nux::Matrix4 mat = nux::GetThreadGraphicsContext ()->GetModelViewProjectionMatrix ();
 
561
      _shader_program_uv_persp_correction->SetUniformLocMatrix4fv ((GLint)VPMatrixLocation, 1, false, (GLfloat*)&(mat.m));
 
562
    }
 
563
  }
 
564
  else
 
565
  {
 
566
    _AsmShaderProg->Begin();
 
567
 
 
568
    VertexLocation        = nux::VTXATTRIB_POSITION;
 
569
    TextureCoord0Location = nux::VTXATTRIB_TEXCOORD0;
 
570
    VertexColorLocation   = nux::VTXATTRIB_COLOR;
 
571
 
 
572
    nux::GetThreadGraphicsContext()->SetTexture(GL_TEXTURE0, icon);
 
573
  }
 
574
 
 
575
  CHECKGL( glEnableVertexAttribArrayARB(VertexLocation) );
 
576
  CHECKGL( glVertexAttribPointerARB((GLuint)VertexLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer) );
 
577
 
 
578
  if(TextureCoord0Location != -1)
 
579
  {
 
580
    CHECKGL( glEnableVertexAttribArrayARB(TextureCoord0Location) );
 
581
    CHECKGL( glVertexAttribPointerARB((GLuint)TextureCoord0Location, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 4) );
 
582
  }
 
583
 
 
584
  if(VertexColorLocation != -1)
 
585
  {
 
586
    CHECKGL( glEnableVertexAttribArrayARB(VertexColorLocation) );
 
587
    CHECKGL( glVertexAttribPointerARB((GLuint)VertexColorLocation, 4, GL_FLOAT, GL_FALSE, 48, VtxBuffer + 8) );
 
588
  }
 
589
 
 
590
  nux::Color bkg_color = nux::Color::White;
 
591
  nux::Color white = nux::Color::White;
 
592
  
 
593
  if(!USE_ARB_SHADERS)
 
594
  {
 
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) );
 
598
  }
 
599
  else
 
600
  {
 
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) );
 
604
  }
 
605
  
 
606
  if(VertexLocation != -1)
 
607
    CHECKGL( glDisableVertexAttribArrayARB(VertexLocation) );
 
608
  if(TextureCoord0Location != -1)
 
609
    CHECKGL( glDisableVertexAttribArrayARB(TextureCoord0Location) );
 
610
  if(VertexColorLocation != -1)
 
611
    CHECKGL( glDisableVertexAttribArrayARB(VertexColorLocation) );
 
612
 
 
613
  if(!USE_ARB_SHADERS)
 
614
  {
 
615
    _shader_program_uv_persp_correction->End();
 
616
  }
 
617
  else
 
618
  {
 
619
    _AsmShaderProg->End();
 
620
  }
 
621
  
 
622
  int markerCenter = (v1.y + v0.y) / 2;
 
623
  
 
624
  if (launcher_view->Active ())
 
625
  {
 
626
    if (!m_ActiveIndicator)
 
627
    {
 
628
      GdkPixbuf *pbuf = gdk_pixbuf_new_from_file (PKGDATADIR"/focused_indicator.png", NULL);
 
629
      m_ActiveIndicator = nux::CreateTextureFromPixbuf (pbuf);
 
630
      g_object_unref (pbuf);
 
631
    }
 
632
    gPainter.Draw2DTexture (GfxContext, m_ActiveIndicator, geo.width - m_ActiveIndicator->GetWidth (), markerCenter - (m_ActiveIndicator->GetHeight () / 2));
 
633
  }
 
634
}
 
635
 
 
636
void Launcher::DrawContent(nux::GraphicsContext& GfxContext, bool force_draw)
 
637
{
 
638
    nux::Geometry base = GetGeometry();
 
639
    GfxContext.PushClippingRectangle(base);
 
640
 
 
641
    nux::ROPConfig ROP;
 
642
    ROP.Blend = true;
 
643
    ROP.SrcBlend = GL_SRC_ALPHA;
 
644
    ROP.DstBlend = GL_ONE_MINUS_SRC_ALPHA;
 
645
 
 
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);
 
648
    
 
649
    LauncherModel::reverse_iterator rev_it;
 
650
    for (rev_it = _model->rbegin (); rev_it != _model->rend (); rev_it++)
 
651
    {
 
652
      if ((*rev_it)->_folding_angle >= 0.0f)
 
653
        continue;
 
654
    
 
655
      GfxContext.GetRenderStates ().SetSeparateBlend (true,
 
656
                                                    GL_SRC_ALPHA,
 
657
                                                    GL_ONE_MINUS_SRC_ALPHA,
 
658
                                                    GL_ONE_MINUS_DST_ALPHA,
 
659
                                                    GL_ONE);
 
660
 
 
661
      GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
 
662
      RenderIcon(GfxContext, *rev_it);
 
663
 
 
664
      GfxContext.GetRenderStates ().SetSeparateBlend (true,
 
665
                                                    GL_SRC_ALPHA,
 
666
                                                    GL_ONE_MINUS_SRC_ALPHA,
 
667
                                                    GL_ONE_MINUS_DST_ALPHA,
 
668
                                                    GL_ONE);
 
669
      GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
 
670
      RenderIconImage (GfxContext, *rev_it);
 
671
    }
 
672
    
 
673
    LauncherModel::iterator it;
 
674
    for (it = _model->begin(); it != _model->end(); it++)
 
675
    {
 
676
      if ((*it)->_folding_angle < 0.0f)
 
677
        continue;
 
678
      GfxContext.GetRenderStates ().SetSeparateBlend (true,
 
679
                                                    GL_SRC_ALPHA,
 
680
                                                    GL_ONE_MINUS_SRC_ALPHA,
 
681
                                                    GL_ONE_MINUS_DST_ALPHA,
 
682
                                                    GL_ONE);
 
683
 
 
684
      GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
 
685
      RenderIcon(GfxContext, *it);
 
686
 
 
687
      GfxContext.GetRenderStates ().SetSeparateBlend (true,
 
688
                                                    GL_SRC_ALPHA,
 
689
                                                    GL_ONE_MINUS_SRC_ALPHA,
 
690
                                                    GL_ONE_MINUS_DST_ALPHA,
 
691
                                                    GL_ONE);
 
692
      GfxContext.GetRenderStates ().SetColorMask (true, true, true, true);
 
693
      RenderIconImage (GfxContext, *it);
 
694
    }
 
695
    
 
696
    GfxContext.GetRenderStates().SetColorMask (true, true, true, true);
 
697
    GfxContext.GetRenderStates().SetBlend(false);
 
698
    gPainter.PopBackground();
 
699
    GfxContext.PopClippingRectangle();
 
700
}
 
701
 
 
702
void Launcher::PostDraw(nux::GraphicsContext& GfxContext, bool force_draw)
 
703
{
 
704
 
 
705
}
 
706
 
 
707
void Launcher::OrderRevealedIcons()
 
708
{
 
709
  nux::Geometry geo = GetGeometry();
 
710
  int x = geo.x + (geo.width - _icon_size) / 2;
 
711
  int y = geo.y + _launcher_top_y;
 
712
 
 
713
  LauncherModel::iterator it;
 
714
  for(it = _model->begin(); it != _model->end(); it++)
 
715
  {
 
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;
 
720
 
 
721
    y += _icon_size + _space_between_icons;
 
722
  }
 
723
 
 
724
  _launcher_bottom_y = y - _space_between_icons;
 
725
}
 
726
 
 
727
void Launcher::OrderFoldedIcons(int focus_icon_index)
 
728
{
 
729
  nux::Geometry geo = GetGeometry();
 
730
  int total_height = geo.GetHeight();
 
731
 
 
732
  int x = geo.x + (geo.width - _icon_size) / 2;
 
733
  int y = geo.y;
 
734
 
 
735
  int num_icons = _model->Size();
 
736
 
 
737
  if (num_icons == 0)
 
738
    return;
 
739
 
 
740
  focus_icon_index = 0;
 
741
 
 
742
  if (focus_icon_index > num_icons - 1)
 
743
    focus_icon_index = num_icons - 1;
 
744
  
 
745
  if (focus_icon_index < 0)
 
746
    focus_icon_index = 0;
 
747
 
 
748
  int icons_revealed;      // a block of consecutive, totally expanded icons. Should be odd number.
 
749
 
 
750
  if (total_height > num_icons * (_icon_size + _space_between_icons))
 
751
  {
 
752
    // all icons will be expanded
 
753
    icons_revealed = num_icons;
 
754
  }
 
755
  else
 
756
  {
 
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)
 
761
      icons_revealed = 1;
 
762
  }
 
763
 
 
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.
 
767
 
 
768
  if ((icons_revealed % 2) == 0)
 
769
  {
 
770
    icons_top_center = half - 1;
 
771
    icons_bottom_center = half;
 
772
  }
 
773
  else
 
774
  {
 
775
    icons_top_center = half;
 
776
    icons_bottom_center = half;
 
777
  }
 
778
 
 
779
  if (focus_icon_index - icons_top_center < 0)
 
780
  {
 
781
    icons_bottom_center += icons_top_center - (focus_icon_index);
 
782
    icons_top_center = focus_icon_index;
 
783
  }
 
784
 
 
785
  if (focus_icon_index + icons_bottom_center > num_icons - 1)
 
786
  {
 
787
    icons_bottom_center = (num_icons - 1) - focus_icon_index;
 
788
    icons_top_center += focus_icon_index + half - (num_icons - 1);
 
789
  }
 
790
 
 
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));
 
793
 
 
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);
 
797
 
 
798
  int index = 0;
 
799
 
 
800
  LauncherModel::iterator it;
 
801
  for(it = _model->begin(), index = 0; it != _model->end(); it++, index++)
 
802
  {
 
803
    if (index < icons_above)
 
804
    {
 
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;
 
810
    }
 
811
 
 
812
    if ((index >= focus_icon_index - icons_top_center) && (index <= focus_icon_index + icons_bottom_center))
 
813
    {
 
814
      if(index == focus_icon_index)
 
815
        _launcher_top_y = y - (icons_top_center + icons_above) * (_icon_size + _space_between_icons);
 
816
 
 
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;
 
822
    }
 
823
 
 
824
 
 
825
    if ((index > focus_icon_index + icons_bottom_center))
 
826
    {
 
827
      if(index == focus_icon_index + icons_bottom_center + 1)
 
828
        y -= 16;
 
829
 
 
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;
 
835
    }
 
836
  }
 
837
 
 
838
  _launcher_bottom_y = y;
 
839
}
 
840
 
 
841
void Launcher::ScheduleRevealAnimation ()
 
842
{
 
843
  _launcher_state = LAUNCHER_UNFOLDED;
 
844
  OrderRevealedIcons();
 
845
 
 
846
  if(nux::GetThreadTimer().FindTimerHandle(_folding_timer_handle))
 
847
  {
 
848
    nux::GetThreadTimer().RemoveTimerHandler(_folding_timer_handle);
 
849
  }
 
850
  _folding_timer_handle = 0;
 
851
 
 
852
  if(!nux::GetThreadTimer().FindTimerHandle(_reveal_timer_handle))
 
853
  {
 
854
    _reveal_timer_handle = nux::GetThreadTimer().AddPeriodicTimerHandler(_timer_intervals, _anim_duration, _reveal_functor, this);
 
855
  }
 
856
}
 
857
 
 
858
void Launcher::ScheduleFoldAnimation ()
 
859
{
 
860
  _launcher_state = LAUNCHER_FOLDED;
 
861
  OrderFoldedIcons(0);
 
862
 
 
863
  if(nux::GetThreadTimer().FindTimerHandle(_reveal_timer_handle))
 
864
  {
 
865
    nux::GetThreadTimer().RemoveTimerHandler(_reveal_timer_handle);
 
866
  }
 
867
  _reveal_timer_handle = 0;
 
868
 
 
869
  if(!nux::GetThreadTimer().FindTimerHandle(_folding_timer_handle))
 
870
  {
 
871
    _folding_timer_handle = nux::GetThreadTimer().AddPeriodicTimerHandler(_timer_intervals, _anim_duration, _folding_functor, this);
 
872
  }
 
873
}
 
874
 
 
875
void Launcher::PreLayoutManagement()
 
876
{
 
877
    View::PreLayoutManagement();
 
878
    if(m_CompositionLayout)
 
879
    {
 
880
        m_CompositionLayout->SetGeometry(GetGeometry());
 
881
    }
 
882
}
 
883
 
 
884
long Launcher::PostLayoutManagement(long LayoutResult)
 
885
{
 
886
  View::PostLayoutManagement(LayoutResult);
 
887
 
 
888
  _mouse_position = nux::Point2 (0, 0);
 
889
  ScheduleFoldAnimation ();
 
890
  
 
891
  return nux::eCompliantHeight | nux::eCompliantWidth;
 
892
}
 
893
 
 
894
void Launcher::PositionChildLayout(float offsetX, float offsetY)
 
895
{
 
896
}
 
897
 
 
898
void Launcher::SlideDown(float stepy, int mousedy)
 
899
{
 
900
    NeedRedraw();
 
901
}
 
902
 
 
903
void Launcher::SlideUp(float stepy, int mousedy)
 
904
{
 
905
    NeedRedraw();
 
906
}
 
907
 
 
908
bool Launcher::TooltipNotify(LauncherIcon* Icon)
 
909
{
 
910
    if(GetActiveMenuIcon())
 
911
        return false;
 
912
    return true;
 
913
}
 
914
 
 
915
bool Launcher::MenuNotify(LauncherIcon* Icon)
 
916
{
 
917
//     if(GetActiveMenuIcon())
 
918
//         return false;
 
919
// 
 
920
//     m_ActiveMenuIcon = Icon;
 
921
    return true;
 
922
}
 
923
 
 
924
void Launcher::NotifyMenuTermination(LauncherIcon* Icon)
 
925
{
 
926
//     if(Icon == GetActiveMenuIcon())
 
927
//         m_ActiveMenuIcon = NULL;
 
928
}
 
929
 
 
930
void Launcher::RecvMouseDown(int x, int y, unsigned long button_flags, unsigned long key_flags)
 
931
{
 
932
  _mouse_position = nux::Point2 (x, y);
 
933
  _dnd_delta = 0;
 
934
  
 
935
  UpdateIconXForm ();
 
936
  MouseDownLogic ();
 
937
  NeedRedraw ();
 
938
}
 
939
 
 
940
void Launcher::RecvMouseUp(int x, int y, unsigned long button_flags, unsigned long key_flags)
 
941
{
 
942
  _mouse_position = nux::Point2 (x, y);
 
943
  nux::Geometry geo = GetGeometry ();
 
944
 
 
945
  if (!geo.IsInside(nux::Point(x, y)))
 
946
    ScheduleFoldAnimation ();
 
947
  else if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
 
948
  {
 
949
    if (_launcher_top_y > 0)
 
950
    {
 
951
      _launcher_top_y = 0;
 
952
    }
 
953
    else if ((_launcher_bottom_y < geo.height))
 
954
    {
 
955
      _launcher_top_y += geo.height - _launcher_bottom_y;
 
956
      if (_launcher_top_y > 0)
 
957
        _launcher_top_y = 0;
 
958
    }
 
959
    ScheduleRevealAnimation ();
 
960
  }
 
961
 
 
962
  UpdateIconXForm ();
 
963
  MouseUpLogic ();
 
964
  _launcher_action_state = ACTION_NONE;
 
965
  NeedRedraw ();
 
966
}
 
967
 
 
968
void Launcher::RecvMouseDrag(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
969
{
 
970
  _mouse_position = nux::Point2 (x, y);
 
971
  nux::Geometry geo = GetGeometry ();
 
972
  float dampening_factor;
 
973
  
 
974
  if (nux::Abs (_dnd_delta) < 15)
 
975
  {
 
976
    _dnd_delta += dy;
 
977
    if (nux::Abs (_dnd_delta) < 15)
 
978
      return;
 
979
  }
 
980
 
 
981
  int DY = 0;
 
982
  if ((nux::Abs (_dnd_delta) >= _dnd_security) && (_launcher_action_state != ACTION_DRAG_LAUNCHER))
 
983
  {
 
984
    _launcher_action_state = ACTION_DRAG_LAUNCHER;
 
985
    DY = _dnd_delta;
 
986
    LauncherModel::iterator it;
 
987
    for(it = _model->begin(); it != _model->end(); it++)
 
988
    {
 
989
      (*it)->HideTooltip ();
 
990
    }
 
991
  }
 
992
  else
 
993
  {
 
994
    DY = dy;
 
995
  }
 
996
 
 
997
  {
 
998
    if (DY > 0)
 
999
    {
 
1000
      dampening_factor = 1.0f;
 
1001
 
 
1002
      _launcher_top_y += dampening_factor * DY;
 
1003
      _launcher_bottom_y += dampening_factor * DY;
 
1004
 
 
1005
      LauncherModel::iterator it;
 
1006
      for(it = _model->begin(); it != _model->end(); it++)
 
1007
      {
 
1008
        (*it)->_position.y += DY * dampening_factor;
 
1009
      }
 
1010
    }
 
1011
    else
 
1012
    {
 
1013
      dampening_factor = 1.0f;
 
1014
 
 
1015
      _launcher_top_y += dampening_factor * DY;
 
1016
      _launcher_bottom_y += dampening_factor * DY;
 
1017
 
 
1018
 
 
1019
      LauncherModel::iterator it;
 
1020
      for(it = _model->begin(); it != _model->end(); it++)
 
1021
      {
 
1022
        (*it)->_position.y += DY * dampening_factor;
 
1023
      }
 
1024
    }
 
1025
  }
 
1026
  
 
1027
  UpdateIconXForm ();
 
1028
  EventLogic ();
 
1029
  NeedRedraw ();
 
1030
}
 
1031
 
 
1032
void Launcher::RecvMouseEnter(int x, int y, unsigned long button_flags, unsigned long key_flags)
 
1033
{
 
1034
  _mouse_position = nux::Point2 (x, y);
 
1035
  if  (_launcher_action_state == ACTION_NONE)
 
1036
    ScheduleRevealAnimation ();
 
1037
 
 
1038
  UpdateIconXForm ();
 
1039
  EventLogic ();
 
1040
  NeedRedraw ();
 
1041
}
 
1042
 
 
1043
void Launcher::RecvMouseLeave(int x, int y, unsigned long button_flags, unsigned long key_flags)
 
1044
{
 
1045
  _mouse_position = nux::Point2 (x, y);
 
1046
  if  (_launcher_action_state == ACTION_NONE)
 
1047
    ScheduleFoldAnimation ();
 
1048
 
 
1049
  UpdateIconXForm ();
 
1050
  EventLogic ();
 
1051
  NeedRedraw ();
 
1052
}
 
1053
 
 
1054
void Launcher::RecvMouseMove(int x, int y, int dx, int dy, unsigned long button_flags, unsigned long key_flags)
 
1055
{
 
1056
  _mouse_position = nux::Point2 (x, y);
 
1057
 
 
1058
  // Every time the mouse moves, we check if it is inside an icon...
 
1059
 
 
1060
  UpdateIconXForm ();
 
1061
  EventLogic ();
 
1062
  NeedRedraw ();
 
1063
}
 
1064
 
 
1065
void Launcher::RecvMouseWheel(int x, int y, int wheel_delta, unsigned long button_flags, unsigned long key_flags)
 
1066
{
 
1067
  nux::Geometry geo = GetGeometry ();
 
1068
  float dampening_factor;
 
1069
  if (!geo.IsInside(nux::Point(x, y)))
 
1070
    return;
 
1071
 
 
1072
  if (wheel_delta > 0)
 
1073
  {
 
1074
    if(_launcher_top_y >= 200.0f)
 
1075
      return;
 
1076
 
 
1077
    dampening_factor = nux::Min<float> (1.0f, float (200.0f - _launcher_top_y) / 200.0f);
 
1078
 
 
1079
    _launcher_top_y += dampening_factor * wheel_delta;
 
1080
    _launcher_bottom_y += dampening_factor * wheel_delta;
 
1081
 
 
1082
    if(_launcher_top_y >= 200.0f)
 
1083
      _launcher_top_y = 200;
 
1084
 
 
1085
    LauncherModel::iterator it;
 
1086
    for(it = _model->begin(); it != _model->end(); it++)
 
1087
    {
 
1088
      (*it)->_position.y += wheel_delta * dampening_factor;
 
1089
    }
 
1090
  }
 
1091
  else
 
1092
  {
 
1093
    if(_launcher_bottom_y <= geo.height - 200.0f)
 
1094
      return;
 
1095
 
 
1096
    dampening_factor = nux::Min<float> (1.0f, float (_launcher_bottom_y - (geo.height - 200.0f)) / 200.0f);
 
1097
 
 
1098
    _launcher_top_y += dampening_factor * wheel_delta;
 
1099
    _launcher_bottom_y += dampening_factor * wheel_delta;
 
1100
 
 
1101
    if(_launcher_bottom_y <= geo.height - 200.0f)
 
1102
      _launcher_bottom_y = geo.height - 200.0f;
 
1103
 
 
1104
    LauncherModel::iterator it;
 
1105
    for(it = _model->begin(); it != _model->end(); it++)
 
1106
    {
 
1107
      (*it)->_position.y += wheel_delta * dampening_factor;
 
1108
    }
 
1109
  }
 
1110
 
 
1111
  UpdateIconXForm ();
 
1112
  EventLogic ();
 
1113
  NeedRedraw ();
 
1114
}
 
1115
 
 
1116
void Launcher::FoldingCallback(void* v)
 
1117
{
 
1118
  LauncherModel::iterator it;
 
1119
  for(it = _model->begin(); it != _model->end(); it++)
 
1120
  {
 
1121
    (*it)->_folding_angle += _folding_timer_handle.GetProgressDelta() * (*it)->_folding_angle_delta;
 
1122
 
 
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;
 
1126
  }
 
1127
 
 
1128
  UpdateIconXForm ();
 
1129
  EventLogic ();
 
1130
  NeedRedraw ();
 
1131
}
 
1132
 
 
1133
void Launcher::RevealCallback(void* v)
 
1134
{
 
1135
  LauncherModel::iterator it;
 
1136
  for(it = _model->begin(); it != _model->end(); it++)
 
1137
  {
 
1138
    (*it)->_folding_angle += _reveal_timer_handle.GetProgressDelta() * (*it)->_folding_angle_delta;
 
1139
 
 
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;
 
1143
  }
 
1144
 
 
1145
  UpdateIconXForm ();
 
1146
  EventLogic ();
 
1147
  NeedRedraw ();
 
1148
}
 
1149
 
 
1150
void Launcher::EventLogic ()
 
1151
 
1152
  if (_launcher_action_state == ACTION_DRAG_LAUNCHER)
 
1153
    return;
 
1154
  
 
1155
  LauncherIcon* launcher_icon = 0;
 
1156
  launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
 
1157
 
 
1158
  if (_icon_under_mouse && (_icon_under_mouse != launcher_icon))
 
1159
  {
 
1160
    _icon_under_mouse->MouseLeave.emit ();
 
1161
    _icon_under_mouse->_mouse_inside = false;
 
1162
    _icon_under_mouse = 0;
 
1163
  }
 
1164
 
 
1165
  if (launcher_icon && (_icon_under_mouse != launcher_icon))
 
1166
  {
 
1167
    launcher_icon->MouseEnter.emit ();
 
1168
    launcher_icon->_mouse_inside = true;
 
1169
    _icon_under_mouse = launcher_icon;
 
1170
  }
 
1171
}
 
1172
 
 
1173
void Launcher::MouseDownLogic ()
 
1174
{
 
1175
  LauncherIcon* launcher_icon = 0;
 
1176
  launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
 
1177
 
 
1178
  if (launcher_icon)
 
1179
  {
 
1180
    _icon_mouse_down = launcher_icon;
 
1181
    launcher_icon->MouseDown.emit ();
 
1182
  }
 
1183
}
 
1184
 
 
1185
void Launcher::MouseUpLogic ()
 
1186
{
 
1187
  LauncherIcon* launcher_icon = 0;
 
1188
  launcher_icon = MouseIconIntersection (_mouse_position.x, _mouse_position.y);
 
1189
 
 
1190
  if (_icon_mouse_down && (_icon_mouse_down == launcher_icon))
 
1191
  {
 
1192
    _icon_mouse_down->MouseUp.emit ();
 
1193
    
 
1194
    if (_launcher_action_state != ACTION_DRAG_LAUNCHER)
 
1195
      _icon_mouse_down->MouseClick.emit ();
 
1196
  }
 
1197
 
 
1198
  if (launcher_icon && (_icon_mouse_down != launcher_icon))
 
1199
  {
 
1200
    launcher_icon->MouseUp.emit ();
 
1201
  }
 
1202
  
 
1203
  _icon_mouse_down = 0;
 
1204
}
 
1205
 
 
1206
LauncherIcon* Launcher::MouseIconIntersection (int x, int y)
 
1207
{
 
1208
  // We are looking for the icon at screen coordinates x, y;
 
1209
  nux::Point2 mouse_position(x, y);
 
1210
  int inside = 0;
 
1211
 
 
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++)
 
1215
  {
 
1216
    if ((*rev_it)->_folding_angle < 0.0f)
 
1217
      continue;
 
1218
 
 
1219
    nux::Point2 screen_coord [4];
 
1220
    for (int i = 0; i < 4; i++)
 
1221
    {
 
1222
      screen_coord [i].x = (*rev_it)->_xform_screen_coord [i].x;
 
1223
      screen_coord [i].y = (*rev_it)->_xform_screen_coord [i].y;
 
1224
    }
 
1225
    inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
 
1226
    if (inside)
 
1227
      return (*rev_it);
 
1228
  }
 
1229
 
 
1230
  LauncherModel::iterator it;
 
1231
  for (it = _model->begin(); it != _model->end (); it++)
 
1232
  {
 
1233
    if ((*it)->_folding_angle >= 0.0f)
 
1234
      continue;
 
1235
 
 
1236
    nux::Point2 screen_coord [4];
 
1237
    for (int i = 0; i < 4; i++)
 
1238
    {
 
1239
      screen_coord [i].x = (*it)->_xform_screen_coord [i].x;
 
1240
      screen_coord [i].y = (*it)->_xform_screen_coord [i].y;
 
1241
    }
 
1242
    inside = PointInside2DPolygon (screen_coord, 4, mouse_position, 1);
 
1243
    if (inside)
 
1244
      return (*it);
 
1245
  }
 
1246
 
 
1247
  return 0;
 
1248
}
 
1249
 
 
1250
void Launcher::UpdateIconXForm ()
 
1251
{
 
1252
 
 
1253
  nux::Geometry geo = GetGeometry ();
 
1254
  nux::Matrix4 ObjectMatrix;
 
1255
  nux::Matrix4 ViewMatrix;
 
1256
  nux::Matrix4 ProjectionMatrix;
 
1257
  nux::Matrix4 ViewProjectionMatrix;
 
1258
 
 
1259
  GetInverseScreenPerspectiveMatrix(ViewMatrix, ProjectionMatrix, geo.width, geo.height, 0.1f, 1000.0f, DEGTORAD(90));
 
1260
 
 
1261
  LauncherModel::iterator it;
 
1262
  for(it = _model->begin(); it != _model->end(); it++)
 
1263
  {
 
1264
    LauncherIcon* launcher_icon = *it;
 
1265
 
 
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;
 
1271
 
 
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)
 
1275
 
 
1276
    ViewProjectionMatrix = ProjectionMatrix*ViewMatrix*ObjectMatrix;
 
1277
 
 
1278
    // Icon 
 
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);
 
1283
    
 
1284
    v0 = ViewProjectionMatrix * v0;
 
1285
    v1 = ViewProjectionMatrix * v1;
 
1286
    v2 = ViewProjectionMatrix * v2;
 
1287
    v3 = ViewProjectionMatrix * v3;
 
1288
 
 
1289
    v0.divide_xyz_by_w();
 
1290
    v1.divide_xyz_by_w();
 
1291
    v2.divide_xyz_by_w();
 
1292
    v3.divide_xyz_by_w();
 
1293
 
 
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;
 
1303
 
 
1304
 
 
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;
 
1321
    
 
1322
    
 
1323
    //// icon image
 
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;
 
1329
    
 
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);
 
1334
    
 
1335
    v0 = ViewProjectionMatrix * v0;
 
1336
    v1 = ViewProjectionMatrix * v1;
 
1337
    v2 = ViewProjectionMatrix * v2;
 
1338
    v3 = ViewProjectionMatrix * v3;
 
1339
 
 
1340
    v0.divide_xyz_by_w();
 
1341
    v1.divide_xyz_by_w();
 
1342
    v2.divide_xyz_by_w();
 
1343
    v3.divide_xyz_by_w();
 
1344
 
 
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;
 
1354
 
 
1355
 
 
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;    
 
1372
  }
 
1373
}
 
1374
 
 
1375
void GetInverseScreenPerspectiveMatrix(nux::Matrix4& ViewMatrix, nux::Matrix4& PerspectiveMatrix,
 
1376
                                       int ViewportWidth,
 
1377
                                       int ViewportHeight,
 
1378
                                       float NearClipPlane,
 
1379
                                       float FarClipPlane,
 
1380
                                       float Fovy)
 
1381
{
 
1382
/*
 
1383
  Objective:
 
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).
 
1394
 
 
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.
 
1398
 
 
1399
    (-x_cs, y_cs)          Camera Space
 
1400
                 ^
 
1401
       __________|__________
 
1402
      |          |          |
 
1403
      |          |          |
 
1404
      |          |(0, 0)    |
 
1405
      |----------|----------|->
 
1406
      |          |          |
 
1407
      |          |          |
 
1408
      |__________|__________|
 
1409
                         (x_cs, -y_cs)
 
1410
 
 
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.
 
1414
 
 
1415
    (0, 0)            Screen Space
 
1416
       _____________________->
 
1417
      |          |          |
 
1418
      |          |          |
 
1419
      |          |          |
 
1420
      |----------|----------|
 
1421
      |          |          |
 
1422
      |          |          |
 
1423
      |__________|__________|
 
1424
      v                   (WindowWidth, WindowHeight)
 
1425
 
 
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)
 
1428
 
 
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
 
1434
 
 
1435
  If the following is the projection matrix:
 
1436
 
 
1437
  (a, 0,  0, 0)     a = 1/(AspectRatio*tan(Fovy/2))
 
1438
  (0, b,  0, 0)     b = 1/tan(Fovy/2)
 
1439
  (0, 0,  c, d)
 
1440
  (0, 0, -1, 0)
 
1441
 
 
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
 
1444
                         |  ==>                     ==>
 
1445
    y_cs*b/(-z_cs) = +1; |        z_cs = -y_cs*b          z_cs = -y_cs*1/tanf(Fovy/2)
 
1446
*/
 
1447
 
 
1448
 
 
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*/));
 
1454
 
 
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*/ );
 
1457
 
 
1458
  PerspectiveMatrix.Perspective(Fovy, AspectRatio, NearClipPlane, FarClipPlane);
 
1459
 
 
1460
//   // Example usage with the matrices above:
 
1461
//   float W = 300;
 
1462
//   float H = 300;
 
1463
//   // centered quad
 
1464
//   float X = (ViewportWidth - W)/2.0;
 
1465
//   float Y = (ViewportHeight - H)/2.0;
 
1466
//   float Z = 0.0f;
 
1467
// 
 
1468
//   {
 
1469
//     glPushMatrix();
 
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);
 
1476
// 
 
1477
//     glBegin(GL_QUADS);
 
1478
//     {
 
1479
//       glNormal3f(0.0f, 0.0f, 1.0f);
 
1480
// 
 
1481
//       glColor4f(1.0f, 0.0f, 0.0f, 1.0f);
 
1482
//       glVertex4f(X, Y, Z, 1.0f);
 
1483
// 
 
1484
//       glColor4f(0.0f, 1.0f, 0.0f, 1.0f);
 
1485
//       glVertex4f(X, Y+H, Z, 1.0f);
 
1486
// 
 
1487
//       glColor4f(0.0f, 0.0f, 1.0f, 1.0f);
 
1488
//       glVertex4f(X+W, Y+H, Z, 1.0f);
 
1489
// 
 
1490
//       glColor4f(0.0f, 1.0f, 1.0f, 1.0f);
 
1491
//       glVertex4f(X+W, Y, Z, 1.0f);
 
1492
//     }
 
1493
//     glEnd();
 
1494
}