From fc21bf19ca663759c47ef7b40efcc9ac79e4cf22 Mon Sep 17 00:00:00 2001 From: Nick Holland Date: Wed, 19 Oct 2016 14:34:43 +0100 Subject: [PATCH] Added support for C# operators on DALi handle objects Now have the ability to do operations such as if ( actor ) // test if the C# actor object is valid and the actor isn't just any empty handle if ( !actor ) if ( actor && anotherActor ) if ( actor || anotherActor ) Change-Id: I31dd56e89f1d4c7d056f56b52717cef469a76afb --- plugins/dali-swig/SWIG/dali-operator.i | 148 +++++++++++++++++++++++--- plugins/dali-swig/examples/dali-test.cs | 178 ++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+), 17 deletions(-) diff --git a/plugins/dali-swig/SWIG/dali-operator.i b/plugins/dali-swig/SWIG/dali-operator.i index f6bbe4d..894b34f 100644 --- a/plugins/dali-swig/SWIG/dali-operator.i +++ b/plugins/dali-swig/SWIG/dali-operator.i @@ -252,7 +252,13 @@ * This is because from C# we can't wrap the operator BooleanType() function */ %extend Dali::BaseHandle { - bool IsHandleEmpty() const { + bool HasBody() const { + + // C++ code. DALi uses Handle <-> Body design pattern. + // This function checks the Handle to see if it has a body attached ( possible to have empty handles). + // Handles in DALi can be converted into a boolean type + // to check if the handle has a valid body attached to it. + // Internally checking *$self will checks IntrusivePtr mObjectHandle in BaseHandle; if( *$self ) { return true; @@ -262,6 +268,21 @@ return false; } } + + // Check if two handles point to the same body / ref-object. + bool IsEqual( const BaseHandle& rhs ) const { + + // C++ code. Check if two handles reference the same implemtion + if( *$self == rhs) + { + return true; + } + else + { + return false; + } + } + }; /** @@ -274,21 +295,114 @@ */ %typemap(cscode) Dali::BaseHandle %{ - public static bool operator true(BaseHandle handle) - { - if( handle!= null ) - { - return handle.IsHandleEmpty(); - } - else - { - return false; - } - } - public static bool operator false(BaseHandle handle) - { - return handle.IsHandleEmpty(); - } -%} + // Returns the bool value true to indicate that an operand is true and returns false otherwise. + public static bool operator true(BaseHandle handle) + { + // if the C# object is null, return false + if( BaseHandle.ReferenceEquals( handle, null ) ) + { + return false; + } + // returns true if the handle has a body, false otherwise + return handle.HasBody(); + } + + // Returns the bool false to indicate that an operand is false and returns true otherwise. + public static bool operator false(BaseHandle handle) + { + // if the C# object is null, return true + if( BaseHandle.ReferenceEquals( handle, null ) ) + { + return true; + } + return !handle.HasBody(); + } + + // Explicit conversion from Handle to bool. + public static explicit operator bool(BaseHandle handle) + { + // if the C# object is null, return false + if( BaseHandle.ReferenceEquals( handle, null ) ) + { + return false; + } + // returns true if the handle has a body, false otherwise + return handle.HasBody(); + } + // Equality operator + public static bool operator == (BaseHandle x, BaseHandle y) + { + // if the C# objects are the same return true + if( BaseHandle.ReferenceEquals( x, y ) ) + { + return true; + } + if ( !BaseHandle.ReferenceEquals( x, null ) && !BaseHandle.ReferenceEquals( y, null ) ) + { + // drop into native code to see if both handles point to the same body + return x.IsEqual( y) ; + } + return false; + + } + + // Inequality operator. Returns Null if either operand is Null + public static bool operator !=(BaseHandle x, BaseHandle y) + { + return !(x==y); + } + + // Logical AND operator for && + // It's possible when doing a && this function (opBitwiseAnd) is never called due + // to short circuiting. E.g. + // If you perform x && y What actually is called is + // BaseHandle.op_False( x ) ? BaseHandle.op_True( x ) : BaseHandle.opTrue( BaseHandle.opBitwiseAnd(x,y) ) + // + public static BaseHandle operator &(BaseHandle x, BaseHandle y) + { + if( x == y ) + { + return x; + } + return null; + } + + // Logical OR operator for || + // It's possible when doing a || this function (opBitwiseOr) is never called due + // to short circuiting. E.g. + // If you perform x || y What actually is called is + // BaseHandle.op_True( x ) ? BaseHandle.op_True( x ) : BaseHandle.opTrue( BaseHandle.opBitwiseOr(x,y) ) + public static BaseHandle operator |(BaseHandle x, BaseHandle y) + { + if ( !BaseHandle.ReferenceEquals( x, null ) || !BaseHandle.ReferenceEquals( y, null ) ) + { + if( x.HasBody() ) + { + return x; + } + if( y.HasBody() ) + { + return y; + } + return null; + } + return null; + } + + // Logical ! operator + public static bool operator !(BaseHandle x) + { + // if the C# object is null, return true + if( BaseHandle.ReferenceEquals( x, null ) ) + { + return true; + } + if( x.HasBody() ) + { + return false; + } + return true; + } +%} \ No newline at end of file diff --git a/plugins/dali-swig/examples/dali-test.cs b/plugins/dali-swig/examples/dali-test.cs index ac4bc85..491bd95 100644 --- a/plugins/dali-swig/examples/dali-test.cs +++ b/plugins/dali-swig/examples/dali-test.cs @@ -39,6 +39,9 @@ namespace MyCSharpExample public void Initialize(object source, AUIApplicationInitEventArgs e) { + + OperatorTests(); + Handle handle = new Handle(); int myPropertyIndex = handle.RegisterProperty("myProperty", new Property.Value(10.0f), Property.AccessMode.READ_WRITE); float myProperty = 0.0f; @@ -162,6 +165,181 @@ namespace MyCSharpExample Console.WriteLine( " Vector4 r = " + vector4.r + ", g = " + vector4.g + ", b = " + vector4.b + ", a = " + vector4.a ); } + + public void OperatorTests() + { + Actor actor = new Actor(); + Actor differentActor = new Actor(); + Actor actorSame = actor; + Actor nullActor = null; + + // test the true operator + if ( actor ) + { + Console.WriteLine ("BaseHandle Operator true (actor) : test passed "); + } + else + { + Console.WriteLine ("BaseHandle Operator true (actor): test failed "); + } + + Actor parent = actor.GetParent (); + + if ( parent ) + { + Console.WriteLine ("Handle with Empty body :failed "); + } + else + { + Console.WriteLine ("Valid with Empty body :passed "); + } + + actor.Add( differentActor ); + // here we test two different C# objects, which on the native side have the same body/ ref-object + if ( actor == differentActor.GetParent() ) + { + Console.WriteLine ("actor == differentActor.GetParent() :passed "); + } + else + { + Console.WriteLine ("actor == differentActor.GetParent() :failed "); + } + + if ( differentActor == differentActor.GetParent() ) + { + Console.WriteLine ("differentActor == differentActor.GetParent() :failed "); + } + else + { + Console.WriteLine ("differentActor == differentActor.GetParent() :passed "); + } + + + if ( nullActor ) + { + Console.WriteLine ("BaseHandle Operator true (nullActor) : test failed "); + } + else + { + Console.WriteLine ("BaseHandle Operator true (nullActor): test passed "); + } + + // ! operator + if ( !actor ) + { + Console.WriteLine ("BaseHandle Operator !(actor) : test failed "); + } + else + { + Console.WriteLine ("BaseHandle Operator !(actor): test passed "); + } + + if ( !nullActor ) + { + Console.WriteLine ("BaseHandle Operator !(nullActor) : test passed "); + } + else + { + Console.WriteLine ("BaseHandle Operator !(nullActor): test failed "); + } + + // Note: operator false only used inside & operator + // test equality operator == + if ( actor == actorSame ) + { + Console.WriteLine ("BaseHandle Operator (actor == actorSame) : test passed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor == actorSame) : test failed"); + } + + if ( actor == differentActor ) + { + Console.WriteLine ("BaseHandle Operator (actor == differentActor) : test failed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor == differentActor) : test passed"); + } + + if ( actor == nullActor ) + { + Console.WriteLine ("BaseHandle Operator (actor == nullActor) : test failed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor == nullActor) : test passed"); + } + + if ( nullActor == nullActor ) + { + Console.WriteLine ("BaseHandle Operator (nullActor == nullActor) : test passed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (nullActor == nullActor) : test failed"); + } + + // test || operator + if ( actor || actorSame ) + { + Console.WriteLine ("BaseHandle Operator (actor || actorSame) : test passed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor || actorSame) : test failed"); + } + + if ( actor || nullActor ) + { + Console.WriteLine ("BaseHandle Operator (actor || nullActor) : test passed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor || nullActor) : test failed"); + } + + if ( nullActor || nullActor ) + { + Console.WriteLine ("BaseHandle Operator (nullActor || nullActor) : test failed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (nullActor || nullActor) : test passed"); + } + + + // test && operator + if ( actor && actorSame ) + { + Console.WriteLine ("BaseHandle Operator (actor && actorSame) : test passed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor && actorSame) : test failed"); + } + + if ( actor && nullActor ) + { + Console.WriteLine ("BaseHandle Operator (actor && nullActor) : test failed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (actor && nullActor) : test passed"); + } + + if ( nullActor && nullActor ) + { + Console.WriteLine ("BaseHandle Operator (nullActor && nullActor) : test failed"); + } + else + { + Console.WriteLine ("BaseHandle Operator (nullActor && nullActor) : test passed"); + } + + } + public void MainLoop() { _application.MainLoop (); -- 2.7.4