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