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