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