Skip to content

Commit a90142f

Browse files
ggcrunchyzero-meta
authored andcommitted
Hit-test-only masks. Merged from (ggcrunchy:MaskFromBitmap2).
See more details in this [pull request](coronalabs#543).
1 parent dfee929 commit a90142f

14 files changed

+249
-33
lines changed

librtt/Display/Rtt_BitmapMask.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,41 +23,50 @@ namespace Rtt
2323
// ----------------------------------------------------------------------------
2424

2525
BitmapMask*
26-
BitmapMask::Create( Runtime& runtime, const FilePath& maskData )
26+
BitmapMask::Create( Runtime& runtime, const FilePath& maskData, bool onlyForHitTests )
2727
{
28-
BitmapPaint *paint = BitmapPaint::NewBitmap( runtime, maskData, PlatformBitmap::kIsBitsFullResolution, true );
28+
BitmapPaint *paint = BitmapPaint::NewBitmap( runtime, maskData, PlatformBitmap::kIsBitsFullResolution, true, onlyForHitTests );
2929
BitmapMask *result = NULL;
3030

31-
if ( Rtt_VERIFY( paint ) )
31+
if ( Rtt_VERIFY( paint || onlyForHitTests ) )
3232
{
33-
result = Rtt_NEW( runtime.GetAllocator(), BitmapMask( paint ) );
33+
result = Rtt_NEW( runtime.GetAllocator(), BitmapMask( paint, onlyForHitTests ) );
3434
}
3535

3636
return result;
3737
}
3838

39-
BitmapMask::BitmapMask( BitmapPaint *paint )
39+
BitmapMask::BitmapMask( BitmapPaint *paint, bool onlyForHitTests, bool isTemporary )
4040
: fPaint( paint ),
4141
fTransform(),
4242
fContentWidth( Rtt_REAL_NEG_1 ),
43-
fContentHeight( Rtt_REAL_NEG_1 )
43+
fContentHeight( Rtt_REAL_NEG_1 ),
44+
fOnlyForHitTests( onlyForHitTests ),
45+
fIsTemporary( isTemporary )
4446
{
45-
Rtt_ASSERT( paint );
47+
Rtt_ASSERT( paint || onlyForHitTests );
4648
}
4749

4850
BitmapMask::BitmapMask( BitmapPaint *paint, Real contentW, Real contentH )
4951
: fPaint( paint ),
5052
fTransform(),
5153
fContentWidth( contentW > Rtt_REAL_0 ? contentW : Rtt_REAL_NEG_1 ),
52-
fContentHeight( contentH > Rtt_REAL_0 ? contentH : Rtt_REAL_NEG_1 )
54+
fContentHeight( contentH > Rtt_REAL_0 ? contentH : Rtt_REAL_NEG_1 ),
55+
fOnlyForHitTests( false ),
56+
fIsTemporary( false )
5357
{
5458
}
5559

5660
BitmapMask::~BitmapMask()
5761
{
58-
Rtt_DELETE( fPaint );
62+
if ( !fIsTemporary )
63+
{
64+
Rtt_DELETE( fPaint );
65+
}
5966
}
6067

68+
const char BitmapMask::kHitTestOnlyTable[] = "hitTestOnlyTableKey";
69+
6170
void
6271
BitmapMask::GetSelfBounds( Rect& rect ) const
6372
{

librtt/Display/Rtt_BitmapMask.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,24 @@ class UserdataWrapper;
2828
class BitmapMask
2929
{
3030
public:
31-
static BitmapMask* Create( Runtime& runtime, const FilePath& maskData );
31+
static BitmapMask* Create( Runtime& runtime, const FilePath& maskData, bool onlyForHitTests );
3232

3333
public:
34-
BitmapMask( BitmapPaint *paint );
34+
BitmapMask( BitmapPaint *paint, bool onlyForHitTests, bool isTemporary = false );
3535
BitmapMask( BitmapPaint *paint, Real contentW, Real contentH );
3636

3737
public:
3838
~BitmapMask();
3939

40+
public:
41+
static const char kHitTestOnlyTable[];
42+
4043
public:
4144
const BitmapPaint* GetPaint() const { return fPaint; }
4245
BitmapPaint* GetPaint() { return fPaint; }
46+
47+
public:
48+
bool GetOnlyForHitTests() const { return fOnlyForHitTests; }
4349

4450
public:
4551
const Transform& GetTransform() const { return fTransform; }
@@ -58,6 +64,8 @@ class BitmapMask
5864
Transform fTransform;
5965
Real fContentWidth;
6066
Real fContentHeight;
67+
bool fOnlyForHitTests;
68+
bool fIsTemporary;
6169
};
6270

6371
// ----------------------------------------------------------------------------

librtt/Display/Rtt_BitmapPaint.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,16 +66,21 @@ BitmapPaint::NewBitmap( Runtime& runtime, const char* filename, MPlatform::Direc
6666
}
6767

6868
BitmapPaint*
69-
BitmapPaint::NewBitmap( Runtime& runtime, const FilePath& data, U32 flags, bool isMask )
69+
BitmapPaint::NewBitmap( Runtime& runtime, const FilePath& data, U32 flags, bool isMask, bool onlyForHitTests )
7070
{
7171
BitmapPaint *result = NULL;
7272

7373
const char *filename = data.GetFilename();
7474
MPlatform::Directory baseDir = data.GetBaseDir();
75+
76+
if ( onlyForHitTests && '\0' == *filename )
77+
{
78+
return NULL;
79+
}
7580

7681
TextureFactory& factory = runtime.GetDisplay().GetTextureFactory();
7782
SharedPtr< TextureResource > pTexture =
78-
factory.FindOrCreate( filename, baseDir, flags, isMask );
83+
factory.FindOrCreate( filename, baseDir, flags, isMask, onlyForHitTests );
7984

8085
if ( pTexture.NotNull() )
8186
{

librtt/Display/Rtt_BitmapPaint.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class BitmapPaint : public Paint
4040
static BitmapPaint* NewBitmap( Runtime& runtime, const char* filename, MPlatform::Directory baseDir, U32 flags );
4141

4242
// Load bitmap mask from file or reuse bitmap from image cache
43-
static BitmapPaint* NewBitmap( Runtime& runtime, const FilePath& data, U32 flags, bool isMask );
43+
static BitmapPaint* NewBitmap( Runtime& runtime, const FilePath& data, U32 flags, bool isMask, bool onlyForHitTests = false );
4444

4545
// Wrap platform bitmap in Paint-compatible interface. Typically used
4646
// in conjunction with PlatformImageProvider

librtt/Display/Rtt_DisplayObject.cpp

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Display/Rtt_BitmapPaint.h"
2020
#include "Display/Rtt_Scene.h"
2121
#include "Display/Rtt_StageObject.h"
22+
#include "Display/Rtt_ShapeObject.h"
2223
#include "Rtt_Event.h"
2324
#include "Rtt_LuaContext.h"
2425
#include "Rtt_LuaProxy.h"
@@ -320,7 +321,32 @@ DisplayObject::UpdateSelfBounds( Rect& rRect ) const
320321
if ( IsHitTestMasked() )
321322
{
322323
Rect maskBounds;
323-
fMask->GetSelfBounds( maskBounds );
324+
325+
if ( fMask->GetOnlyForHitTests() && !fMask->GetPaint() )
326+
{
327+
if ( !ShapeObject::IsShapeObject( *this ) )
328+
{
329+
return;
330+
}
331+
332+
const ShapeObject &o = static_cast<const ShapeObject&>( *this );
333+
const BitmapPaint* tempPaint = o.GetBitmapPaint();
334+
335+
if ( !tempPaint )
336+
{
337+
return;
338+
}
339+
340+
BitmapMask temp( const_cast<BitmapPaint*>( tempPaint ), true, true );
341+
342+
temp.GetSelfBounds( maskBounds );
343+
}
344+
345+
else
346+
{
347+
fMask->GetSelfBounds( maskBounds );
348+
}
349+
324350
rRect.Intersect( maskBounds );
325351
}
326352
}
@@ -1318,7 +1344,7 @@ DisplayObject::UpdateMask()
13181344
{
13191345
Rtt_ASSERT( ! IsValid( kMaskFlag ) );
13201346

1321-
if ( fMask )
1347+
if ( fMask && !fMask->GetOnlyForHitTests() )
13221348
{
13231349
/*
13241350
Matrix xform = GetSrcToDstMatrix();
@@ -1349,7 +1375,7 @@ DisplayObject::SetMask( Rtt_Allocator *allocator, BitmapMask *mask )
13491375

13501376
if ( mask )
13511377
{
1352-
if( ! fMaskUniform )
1378+
if( ! fMaskUniform && !fMask->GetOnlyForHitTests() )
13531379
{
13541380
fMaskUniform = Rtt_NEW( allocator, Uniform( allocator, Uniform::kMat3 ) );
13551381
}

librtt/Display/Rtt_GroupObject.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ GroupObject::Draw( Renderer& renderer ) const
220220

221221
const BitmapMask *mask = GetMask();
222222

223-
if ( mask )
223+
if ( mask && !fMask->GetOnlyForHitTests() )
224224
{
225225
Texture *texture = const_cast< BitmapPaint * >( mask->GetPaint() )->GetTexture();
226226
Uniform *uniform = const_cast< Self * >( this )->GetMaskUniform();
@@ -239,7 +239,7 @@ GroupObject::Draw( Renderer& renderer ) const
239239
}
240240
}
241241

242-
if ( mask )
242+
if ( mask && !fMask->GetOnlyForHitTests() )
243243
{
244244
renderer.PopMask();
245245
}

librtt/Display/Rtt_LuaLibGraphics.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ class GraphicsLibrary
7272

7373
public:
7474
static int newMask( lua_State *L );
75+
static int newHitTestOnlyMask( lua_State *L );
76+
static int newHitTestOnlyMaskFromPaint( lua_State *L );
7577
static int newGradient( lua_State *L );
7678
static int newImageSheet( lua_State *L );
7779
static int defineEffect( lua_State *L );
@@ -114,6 +116,8 @@ GraphicsLibrary::Open( lua_State *L )
114116
const luaL_Reg kVTable[] =
115117
{
116118
{ "newMask", newMask },
119+
{ "newHitTestOnlyMask", newHitTestOnlyMask },
120+
{ "newHitTestOnlyMaskFromPaint", newHitTestOnlyMaskFromPaint },
117121
// { "newVertexArray", newVertexArray },
118122
{ "newGradient", newGradient },
119123
{ "newImageSheet", newImageSheet },
@@ -203,6 +207,43 @@ GraphicsLibrary::newMask( lua_State *L )
203207
return result;
204208
}
205209

210+
// graphics.newHitTestOnlyMask( filename [, baseDir] )
211+
int
212+
GraphicsLibrary::newHitTestOnlyMask( lua_State *L )
213+
{
214+
int result = GraphicsLibrary::newMask( L );
215+
216+
if ( result )
217+
{
218+
lua_getfield( L, LUA_REGISTRYINDEX, BitmapMask::kHitTestOnlyTable );
219+
220+
if ( lua_istable( L, -1 ) )
221+
{
222+
lua_pushvalue( L, -2 );
223+
lua_pushboolean( L, 1 );
224+
lua_rawset( L, -3 );
225+
lua_pop( L, 1 );
226+
}
227+
228+
else
229+
{
230+
result = 0;
231+
}
232+
}
233+
234+
return result;
235+
}
236+
237+
// graphics.newHitTestOnlyMaskFromPaint( [opts] )
238+
int
239+
GraphicsLibrary::newHitTestOnlyMaskFromPaint( lua_State *L )
240+
{
241+
lua_settop( L, 0 ); // TODO: any options?
242+
lua_pushliteral( L, "" );
243+
244+
return newHitTestOnlyMask( L );
245+
}
246+
206247
// graphics.newVertexArray( x1, y1 [,x2, y2, ... ] )
207248
/*
208249
static int
@@ -921,6 +962,13 @@ LuaLibGraphics::Initialize( lua_State *L, Display& display )
921962

922963
CoronaLuaPushModule( L, GraphicsLibrary::kName );
923964
lua_setglobal( L, GraphicsLibrary::kName ); // graphics = library
965+
966+
lua_newtable( L );
967+
lua_createtable( L, 0, 1 );
968+
lua_pushliteral( L, "k" );
969+
lua_setfield( L, -2, "__mode" );
970+
lua_setmetatable( L, -2 );
971+
lua_setfield( L, LUA_REGISTRYINDEX, BitmapMask::kHitTestOnlyTable );
924972
}
925973

926974
// ----------------------------------------------------------------------------

librtt/Display/Rtt_PlatformBitmap.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,17 @@ PlatformBitmap::HitTest( Rtt_Allocator *context, int i, int j, U8 threshold ) co
6161
break;
6262

6363
default:
64-
// TODO: Use GetColorByteIndexesFor()
65-
Rtt_ASSERT_NOT_IMPLEMENTED();
64+
{
65+
int alphaIndex, redIndex, greenIndex, blueIndex;
66+
GetColorByteIndexesFor( format, &alphaIndex, &redIndex, &greenIndex, &blueIndex );
67+
#ifdef Rtt_ANDROID_ENV // cf. GraphicsLibrary::newOutline et al.
68+
alphaIndex = 3;
69+
#endif
70+
const U8 *pixels = ((const U8*)data);
71+
U8 alpha = pixels[index + alphaIndex];
72+
/* TODO? use r,g,b...*/
73+
result = alpha > threshold;
74+
}
6675
break;
6776
}
6877
}

librtt/Display/Rtt_ShapeObject.cpp

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,37 @@ ShapeObject::~ShapeObject()
5656
Rtt_DELETE( fPath );
5757
}
5858

59+
bool
60+
ShapeObject::IsShapeObject( const DisplayObject &object )
61+
{
62+
const LuaProxyVTable* t = &object.ProxyVTable(), * shapeVTable = &LuaShapeObjectProxyVTable::Constant();
63+
64+
while ( shapeVTable != t )
65+
{
66+
const LuaProxyVTable* parent = &t->Parent();
67+
68+
if ( parent == t )
69+
{
70+
return false;
71+
}
72+
73+
else
74+
{
75+
t = parent;
76+
}
77+
}
78+
79+
return true;
80+
}
81+
82+
const BitmapPaint*
83+
ShapeObject::GetBitmapPaint() const
84+
{
85+
Rtt_ASSERT( fPath );
86+
87+
return (BitmapPaint*)fPath->GetFill()->AsPaint( Paint::kBitmap );
88+
}
89+
5990
bool
6091
ShapeObject::UpdateTransform( const Matrix& parentToDstSpace )
6192
{
@@ -278,12 +309,25 @@ ShapeObject::SetSelfBounds( Real width, Real height )
278309
void
279310
ShapeObject::DidSetMask( BitmapMask *mask, Uniform *uniform )
280311
{
281-
Texture *maskTexture = ( mask ? mask->GetPaint()->GetTexture() : NULL );
312+
Rtt_ASSERT( !mask || mask->GetPaint() || mask->GetOnlyForHitTests() );
313+
314+
Texture *maskTexture = ( mask && !mask->GetOnlyForHitTests() ? mask->GetPaint()->GetTexture() : NULL );
282315

283316
fFillData.fMaskTexture = maskTexture;
284317
fFillData.fMaskUniform = uniform;
285318
fStrokeData.fMaskTexture = maskTexture;
286319
fStrokeData.fMaskUniform = uniform;
320+
321+
if ( mask && !mask->GetPaint() )
322+
{
323+
const BitmapPaint *bitmapPaint = GetBitmapPaint();
324+
325+
if ( bitmapPaint )
326+
{
327+
SetMaskGeometricProperty( kScaleX, GetGeometricProperty( kWidth ) / bitmapPaint->GetBitmap()->Width() );
328+
SetMaskGeometricProperty( kScaleY, GetGeometricProperty( kHeight ) / bitmapPaint->GetBitmap()->Height() );
329+
}
330+
}
287331
}
288332

289333
void
@@ -322,6 +366,21 @@ ShapeObject::SetFill( Paint* newValue )
322366
fPath->SetFill( newValue );
323367

324368
DidChangePaint( fFillData );
369+
370+
BitmapMask *mask = GetMask();
371+
372+
if ( mask && !mask->GetPaint() )
373+
{
374+
Rtt_ASSERT( mask->GetOnlyForHitTests() );
375+
376+
const BitmapPaint *paint = GetBitmapPaint();
377+
378+
if ( paint )
379+
{
380+
SetMaskGeometricProperty( kScaleX, GetGeometricProperty( kWidth ) / paint->GetBitmap()->Width() );
381+
SetMaskGeometricProperty( kScaleY, GetGeometricProperty( kHeight ) / paint->GetBitmap()->Height() );
382+
}
383+
}
325384
}
326385

327386
void

0 commit comments

Comments
 (0)