1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     lyt_DrawerUniform.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include "precompiled.h"
19 #include <nw/lyt/lyt_Layout.h>
20 #include <nw/lyt/lyt_Pane.h>
21 #include <nw/lyt/lyt_Drawer.h>
22 
23 #ifdef NW_LYT_DRAWER_ENABLE
24 
25 // MakeUniformDataSelf実装のため
26 #include <nw/lyt/lyt_Picture.h>
27 #include <nw/lyt/lyt_Window.h>
28 #include <nw/lyt/lyt_TextBox.h>
29 
30 namespace nw { namespace lyt {
31 
32 namespace local { namespace {
33 
Transform(const nw::math::MTX22 & mtx,const nw::math::VEC2 & vec)34 const nw::math::VEC2 Transform(
35     const nw::math::MTX22& mtx,
36     const nw::math::VEC2& vec)
37 {
38     return nw::math::VEC2(
39         mtx.f._00 * vec.x + mtx.f._01 * vec.y,
40         mtx.f._10 * vec.x + mtx.f._11 * vec.y);
41 }
42 
43 }}
44 
45 void
SetUniformDataEnd()46 Drawer::SetUniformDataEnd()
47 {
48     m_UniformAddr[ m_UniformAddrIndex ] = m_UniformAddress;
49 
50     ++m_UniformAddrIndex;
51 
52 #ifdef NW_FONT_RECTDRAWER_USE_DRAW_BUFFER
53 
54     if ( m_UniformAddrIndex + 1                    > UNIFORM_ADDR_NUM
55       || m_UniformMtxIndex  + UNIFORM_MTX_USE_MAX  > UNIFORM_MTX_NUM
56       || m_UniformDataIndex + UNIFORM_DATA_USE_MAX > UNIFORM_DATA_NUM
57     )
58     {
59         UniformAndDraw();
60     }
61 
62 #else
63 
64     UniformAndDraw();
65 
66 #endif
67 }
68 
69 u8
CalcTextureCoords(const Material * pMaterial,const TexCoordQuad * pTexCoordQuad,nw::math::VEC4 texCoords[TexMapMax * 2]) const70 Drawer::CalcTextureCoords( const Material* pMaterial,
71                                 const TexCoordQuad* pTexCoordQuad,
72                                 nw::math::VEC4 texCoords[ TexMapMax * 2 ] ) const
73 {
74     // テクスチャ座標の設定
75     const u32 num = ut::Min( (u32)pMaterial->GetTexCoordGenNum(), (u32)TexMapMax );
76 
77     if ( 0 == num ) return 0;
78 
79     // TODO: 中心固定... エディターで編集できて、Materialから取得するようにしたい
80     static const nw::math::VEC2 center( 0.5f, 0.5f );
81 
82     for ( int i = 0; i < num; ++i )
83     {
84         const int src = pMaterial->GetTexCoordGen( i ).GetTexGenSrc();
85 
86         const TexMap& texMap = pMaterial->GetTexMap( i );
87         const f32 adjust_x = static_cast<f32>(texMap.GetWidth()) / texMap.GetRealWidth();
88         const f32 adjust_y = static_cast<f32>(texMap.GetHeight()) / texMap.GetRealHeight();
89 
90         const TexSRT& texSRT = pMaterial->GetTexSRT( i );
91         register const f32 rotate = texSRT.rotate;
92         register const f32 scalex = texSRT.scale.x;
93         register const f32 scaley = texSRT.scale.y;
94 
95         if ( rotate != 0.f || scalex != 1.f || scaley != 1.f )
96         {
97             f32 cos, sin;
98             nw::math::SinCosDeg( &sin, &cos, rotate );
99 
100             register nw::math::MTX22 srMtx(
101                 cos * scalex * adjust_x, -sin * scaley * adjust_x,
102                 sin * scalex * adjust_y,  cos * scaley * adjust_y );
103 
104             register nw::math::VEC2 ctrans( ( center.x + texSRT.translate.x ) * adjust_x,
105                                             ( center.y + texSRT.translate.y ) * adjust_y );
106 
107             { // 左上、右下
108                 nw::math::VEC4* pTexCoord = &texCoords[ i ];
109 
110                 register nw::math::VEC2 lt( pTexCoordQuad[ src ][ VERTEX_LT ].x,
111                                             pTexCoordQuad[ src ][ VERTEX_LT ].y);
112                 register nw::math::VEC2 rb( pTexCoordQuad[ src ][ VERTEX_RB ].x,
113                                             pTexCoordQuad[ src ][ VERTEX_RB ].y );
114 
115                 lt = local::Transform(srMtx, lt - center) + ctrans;
116                 rb = local::Transform(srMtx, rb - center) + ctrans;
117 
118                 pTexCoord->x = lt.x ;
119                 pTexCoord->y = 1.f - lt.y;
120                 pTexCoord->z = rb.x ;
121                 pTexCoord->w = 1.f - rb.y;
122             }
123 
124             { // 左下、右上は、下のほうに詰める
125                 nw::math::VEC4* pTexCoord = &texCoords[ i + TexMapMax ];
126 
127                 register nw::math::VEC2 lb( pTexCoordQuad[ src ][ VERTEX_LB ].x,
128                                             pTexCoordQuad[ src ][ VERTEX_LB ].y );
129                 register nw::math::VEC2 rt( pTexCoordQuad[ src ][ VERTEX_RT ].x,
130                                             pTexCoordQuad[ src ][ VERTEX_RT ].y );
131 
132                 lb = local::Transform(srMtx, lb - center) + ctrans;
133                 rt = local::Transform(srMtx, rt - center) + ctrans;
134 
135                 pTexCoord->x = lb.x;
136                 pTexCoord->y = 1.f - lb.y;
137                 pTexCoord->z = rt.x;
138                 pTexCoord->w = 1.f - rt.y;
139             }
140         }
141         else
142         {
143             register const nw::math::VEC2 trans( texSRT.translate.x, texSRT.translate.y );
144 
145             { // 左上、右下
146                 nw::math::VEC4* pTexCoord = &texCoords[ i ];
147 
148                 pTexCoord->x = ( pTexCoordQuad[ src ][ VERTEX_LT ].x + trans.x ) * adjust_x;
149                 pTexCoord->y = 1.f - ( pTexCoordQuad[ src ][ VERTEX_LT ].y + trans.y ) * adjust_y;
150                 pTexCoord->z = ( pTexCoordQuad[ src ][ VERTEX_RB ].x + trans.x ) * adjust_x;
151                 pTexCoord->w = 1.f - ( pTexCoordQuad[ src ][ VERTEX_RB ].y + trans.y ) * adjust_y;
152             }
153 
154             { // 左下、右上は、下のほうに詰める
155                 nw::math::VEC4* pTexCoord = &texCoords[ i + TexMapMax ];
156 
157                 pTexCoord->x = ( pTexCoordQuad[ src ][ VERTEX_LB ].x + trans.x) * adjust_x;
158                 pTexCoord->y = 1.f - ( pTexCoordQuad[ src ][ VERTEX_LB ].y + trans.y ) * adjust_y;
159                 pTexCoord->z = ( pTexCoordQuad[ src ][ VERTEX_RT ].x + trans.x) * adjust_x;
160                 pTexCoord->w = 1.f - ( pTexCoordQuad[ src ][ VERTEX_RT ].y + trans.y ) * adjust_y;
161             }
162         }
163     }
164 
165     // テクスチャ座標を省略できない場合、6レジスタ使用する
166     for ( int i = 0; i < num; ++i )
167     {
168         if ( texCoords[ i ].x != texCoords[ i + TexMapMax ].x || // 左辺がそろっているかを判定
169              texCoords[ i ].z != texCoords[ i + TexMapMax ].z || // 右辺がそろっているかを判定
170              texCoords[ i ].y != texCoords[ i + TexMapMax ].w || // 上辺がそろっているかを判定
171              texCoords[ i ].w != texCoords[ i + TexMapMax ].y )  // 下辺がそろっているかを判定
172         {
173             return TexMapMax * 2;
174         }
175     }
176 
177     return num;
178 }
179 
180 
181 void
SetUpTextureCoords(const nw::math::VEC4 texCoords[TexMapMax * 2],const int texCoordNum)182 Drawer::SetUpTextureCoords( const nw::math::VEC4 texCoords[ TexMapMax * 2 ],
183                                  const int texCoordNum )
184 {
185     if ( texCoordNum != m_TexCoordNum )
186     {
187         FlushBuffer();
188         m_TexCoordNum = texCoordNum;
189     }
190 
191     if ( texCoordNum != 0 )
192     {
193         if ( 2 <= texCoordNum )
194         {
195             FlushBuffer();
196         }
197 
198         m_UniformAddress.addrTexCoord = m_UniformDataIndex;
199         nw::math::VEC4* pTexCoord = &m_UniformData[ m_UniformDataIndex ];
200 
201         std::memcpy( &m_UniformData[ m_UniformDataIndex ],
202                      texCoords,
203                      sizeof( nw::math::VEC4 ) * texCoordNum );
204 
205         m_UniformDataIndex += texCoordNum;
206     }
207 }
208 
209 
210 void
SetCurrentUniformAlpha(const f32 alpha)211 Drawer::SetCurrentUniformAlpha( const f32 alpha )
212 {
213     m_UniformAddress.addrColor = alpha;
214 }
215 
216 void
SetUpMtx(const nw::math::MTX34 & __restrict mtx)217 Drawer::SetUpMtx( const nw::math::MTX34& __restrict mtx )
218 {
219     // std::memcpy( &m_UniformMtx[ m_UniformMtxIndex ], &mtx, sizeof(nw::math::MTX34) );
220     MTX34Copy( ( nw::math::MTX34* )&m_UniformMtx[ m_UniformMtxIndex ], &mtx );
221 
222     m_UniformAddress.addrMtx = m_UniformMtxIndex;
223     m_UniformMtxIndex += 3;
224 }
225 
226 void
SetUpQuad(const nw::lyt::Size & __restrict size,const nw::math::VEC2 & __restrict basePt)227 Drawer::SetUpQuad( const nw::lyt::Size&  __restrict size,
228                         const nw::math::VEC2& __restrict basePt )
229 {
230     nw::math::VEC4* __restrict pQuadInfo = &m_UniformData[ m_UniformDataIndex ];
231     pQuadInfo->x = size.width;
232     pQuadInfo->y = size.height;
233     pQuadInfo->z = basePt.x;
234     pQuadInfo->w = basePt.y;
235 
236     m_UniformAddress.addrSizeAndVtx = m_UniformDataIndex;
237     ++m_UniformDataIndex;
238 }
239 
240 void
SetUpVtxColors(const nw::ut::Color8 vtxColors[VERTEX_MAX],const u8 globalAlpha)241 Drawer::SetUpVtxColors( const nw::ut::Color8 vtxColors[ VERTEX_MAX ], const u8 globalAlpha )
242 {
243     register f32 d = 1.f / 255.f;
244     register f32 colors[ VERTEX_MAX ][ 4 ];
245     bool isWhite = true;
246     register f32 alpha = globalAlpha * d;
247 
248     for ( int i = 0; i < VERTEX_MAX; ++i )
249     {
250         if ( nw::ut::Color8::WHITE != vtxColors[i] )
251         {
252             colors[ i ][ 0 ] = vtxColors[ i ].r * d;
253             colors[ i ][ 1 ] = vtxColors[ i ].g * d;
254             colors[ i ][ 2 ] = vtxColors[ i ].b * d;
255             colors[ i ][ 3 ] = vtxColors[ i ].a * d;
256 
257             for ( int j = 0; isWhite && j < i; ++j )
258             {
259                 colors[ j ][ 0 ] = 1.f;
260                 colors[ j ][ 1 ] = 1.f;
261                 colors[ j ][ 2 ] = 1.f;
262                 colors[ j ][ 3 ] = alpha;
263             }
264 
265             isWhite = false;
266 
267             // アルファをかける
268             colors[ i ][ 3 ] *= alpha;
269         }
270         else if ( !isWhite )
271         {
272             colors[ i ][ 0 ] = 1.f;
273             colors[ i ][ 1 ] = 1.f;
274             colors[ i ][ 2 ] = 1.f;
275             colors[ i ][ 3 ] = alpha;
276         }
277     }
278 
279     if ( isWhite )
280     {
281         m_UniformAddress.addrColor = alpha;
282     }
283     else
284     {
285         m_UniformAddress.addrColor = m_UniformMtxIndex;
286 
287         for ( int i = 0; i < VERTEX_MAX; ++i )
288         {
289             m_UniformMtx[ m_UniformMtxIndex + i ].x = colors[ i ][ 0 ];
290             m_UniformMtx[ m_UniformMtxIndex + i ].y = colors[ i ][ 1 ];
291             m_UniformMtx[ m_UniformMtxIndex + i ].z = colors[ i ][ 2 ];
292             m_UniformMtx[ m_UniformMtxIndex + i ].w = colors[ i ][ 3 ];
293         }
294         m_UniformMtxIndex += VERTEX_MAX;
295     }
296 }
297 
298 
299 //----------------------------------------------------------
300 // TextBox
301 void
MakeUniformDataSelf(DrawInfo * pDrawInfo,Drawer * __restrict pDrawer) const302 TextBox::MakeUniformDataSelf( DrawInfo* pDrawInfo,
303                               Drawer* __restrict pDrawer ) const
304 {
305 #ifdef NW_LYT_DRAWER_DISABLE_DRAW_TEXTBOX
306     return;
307 #endif
308 
309     if ( m_TextLen <= 0 || !m_pFont || !m_pMaterial )
310     {
311         return;
312     }
313 
314     pDrawer->FlushBuffer();
315 
316     const_cast<TextBox*>(this)->UpdateDrawCharDataImpl(pDrawer);
317 
318     pDrawer->SetUpTextBox( this, m_pMaterial, *pDrawInfo );
319 }
320 
321 //----------------------------------------------------------
322 // Picture
323 void
MakeUniformDataSelf(DrawInfo * pDrawInfo,Drawer * __restrict pDrawer) const324 Picture::MakeUniformDataSelf( DrawInfo* pDrawInfo,
325                               Drawer* __restrict pDrawer ) const
326 {
327     NW_UNUSED_VARIABLE( pDrawInfo );
328 
329 #ifdef NW_LYT_DRAWER_DISABLE_DRAW_PICTURE
330     return;
331 #endif
332 
333     { // TexEnvの設定
334         pDrawer->SetUpTexEnv( m_pMaterial );
335     }
336 
337     { // テクスチャの設定
338         pDrawer->SetUpTextures( m_pMaterial );
339     }
340 
341     { // テクスチャ座標の設定
342         if ( !m_IsTexCoordInited || m_pMaterial->IsTextureDirty() )
343         {
344             m_UniformTexCoordNum = pDrawer->CalcTextureCoords( m_pMaterial,
345                                                                     m_TexCoordAry.GetArray(),
346                                                                     m_UniformTexCoords );
347             m_IsTexCoordInited = true;
348             m_pMaterial->SetTextureDirty( false );
349         }
350 
351         pDrawer->SetUpTextureCoords( m_UniformTexCoords, m_UniformTexCoordNum );
352     }
353 
354     { // 頂点座標の計算に必要な情報の設定
355         pDrawer->SetUpMtx( GetGlobalMtx() );
356         pDrawer->SetUpQuad( GetSize(), GetVtxPos() );
357     }
358 
359     { // 頂点カラーの設定
360         pDrawer->SetUpVtxColors( m_VtxColors, GetGlobalAlpha() );
361     }
362 
363     { // UniformDataの設定終了
364         pDrawer->SetUniformDataEnd();
365     }
366 }
367 
368 
369 //----------------------------------------------------------
370 // Pane
371 void
MakeUniformData(DrawInfo * pDrawInfo,Drawer * __restrict pDrawer) const372 Pane::MakeUniformData( DrawInfo* pDrawInfo,
373                        Drawer* __restrict pDrawer ) const
374 {
375     NW_UNUSED_VARIABLE( pDrawInfo );
376 
377     // 自身の描画
378     MakeUniformDataSelf( pDrawInfo, pDrawer );
379 
380     // TODO: 再帰やめたい
381 
382     // 子供の描画
383     for ( PaneList::ConstIterator child = m_ChildList.begin(); child != m_ChildList.end(); ++child )
384     {
385         if ( child->IsVisible() )
386         {
387             child->MakeUniformData( pDrawInfo, pDrawer );
388         }
389     }
390 }
391 
392 void
MakeUniformDataSelf(DrawInfo *,Drawer *) const393 Pane::MakeUniformDataSelf( DrawInfo* /*pDrawInfo*/,
394                            Drawer* /*pDrawer*/ ) const
395 {
396 }
397 
398 }}
399 #endif
400