[dali_1.0.20] Merge branch 'tizen' 87/31287/1
authorLee Morgan <Lee.morgan@partner.samsung.com>
Wed, 3 Dec 2014 12:37:51 +0000 (12:37 +0000)
committerLee Morgan <Lee.morgan@partner.samsung.com>
Wed, 3 Dec 2014 12:44:29 +0000 (12:44 +0000)
Change-Id: I02366faeffe824b809a8a2fb21a80eb50abcd224

13 files changed:
automated-tests/build.sh
automated-tests/execute.sh
automated-tests/src/dali-toolkit-internal/tct-dali-toolkit-internal-core.cpp
automated-tests/src/dali-toolkit-unmanaged/tct-dali-toolkit-unmanaged-core.cpp
automated-tests/src/dali-toolkit/tct-dali-toolkit-core.cpp
base/dali-toolkit/internal/builder/builder-animations.cpp
base/dali-toolkit/internal/builder/builder-impl.cpp
base/dali-toolkit/internal/builder/builder-impl.h
base/dali-toolkit/internal/builder/builder-signals.cpp
base/dali-toolkit/public-api/builder/builder.cpp
base/dali-toolkit/public-api/builder/builder.h
optional/dali-toolkit/public-api/dali-toolkit-version.cpp
packaging/dali-toolkit.spec

index 6c817ae..7c7584b 100755 (executable)
@@ -1,5 +1,6 @@
 #!/bin/bash
 
+
 TEMP=`getopt -o rn --long rebuild,no-gen \
      -n 'genmake' -- "$@"`
 
@@ -43,6 +44,7 @@ else
     if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
         echo BUILDING $mod
         build $mod
+        if [ $? -ne 0 ]; then echo "Build failed" ; exit 1; fi
     fi
   done
 fi
index aedd933..1c77009 100755 (executable)
@@ -1,5 +1,23 @@
 #!/bin/bash
 
+TEMP=`getopt -o sr --long serial,rerun -n 'execute.sh' -- "$@"`
+
+if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
+
+# Note the quotes around `$TEMP': they are essential!
+eval set -- "$TEMP"
+
+opt_parallel=1
+opt_rerun=""
+while true ; do
+    case "$1" in
+        -s|--serial)   opt_parallel=0 ; shift ;;
+        -r|--rerun)    opt_rerun="-r" ; shift ;;
+        --) shift; break;;
+       *) echo "Internal error $1!" ; exit 1 ;;
+    esac
+done
+
 function execute
 {
     scripts/tctestsgen.sh $1 `pwd` desktop $2
@@ -15,20 +33,36 @@ if [ -d ../build/tizen ] ; then
     rm -f ../build/tizen/dali-core/.libs/*.gcda
 fi
 
-find build -name "*.gcda" -exec rm '{}' \;
+find build \( -name "*.gcda" \) -exec rm '{}' \;
 
-if [ -n "$1" ] ; then
-  echo EXECUTING ONLY $1
-  execute $*
+if [ $opt_parallel = 1 ] ; then
+
+    if [ -n "$1" ] ; then
+        if [ -f "build/src/$1/tct-$1-core" ] ; then
+            build/src/$1/tct-$1-core -p $opt_rerun
+        fi
+    else
+        for mod in `ls -1 src/ | grep -v CMakeList `
+        do
+            if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+                echo EXECUTING $mod
+                build/src/$mod/tct-$mod-core -p $opt_rerun
+            fi
+        done
+    fi
 
 else
-  for mod in `ls -1 src/ | grep -v CMakeList `
-  do
-    if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
-        echo EXECUTING $mod
-        execute $mod $*
+    if [ -n "$1" ] ; then
+        execute $1 $*
+    else
+        for mod in `ls -1 src/ | grep -v CMakeList `
+        do
+            if [ $mod != 'common' ] && [ $mod != 'manual' ]; then
+                echo EXECUTING $mod
+                execute $mod $*
+            fi
+        done
     fi
-  done
-fi
 
-scripts/summarize.pl
+    scripts/summarize.pl
+fi
index 2bbd960..c80af33 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-internal-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }
index b871625..9036241 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-unmanaged-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }
index d9c39e1..195627e 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "tct-dali-toolkit-core.h"
+#include <stdlib.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <unistd.h>
+#include <vector>
+#include <map>
 
-int main(int argc, const char *argv[])
+int RunTestCase( struct testcase_s& testCase )
 {
-    int result = -1;
-    int i;
+  int result = 1;
+  if( testCase.startup )
+  {
+    testCase.startup();
+  }
+  result = testCase.function();
+  if( testCase.cleanup )
+  {
+    testCase.cleanup();
+  }
+  return result;
+}
 
-    if (argc != 2) {
-        printf("Usage: %s <testcase name>\n", argv[0]);
-        return 2;
-    }
+#define MAX_NUM_CHILDREN 16
+
+struct TestCase
+{
+  int testCase;
+  const char* testCaseName;
+
+  TestCase()
+  : testCase(0),
+    testCaseName(NULL)
+  {
+  }
 
-    for (i = 0; tc_array[i].name; i++) {
-        if (!strcmp(argv[1], tc_array[i].name)) {
-            if (tc_array[i].startup)
-                tc_array[i].startup();
+  TestCase(int tc, const char* name)
+  : testCase(tc),
+    testCaseName(name)
+  {
+  }
+  TestCase(const TestCase& rhs)
+  : testCase(rhs.testCase),
+    testCaseName(rhs.testCaseName)
+  {
+  }
+  TestCase& operator=(const TestCase& rhs)
+  {
+    testCase = rhs.testCase;
+    testCaseName = rhs.testCaseName;
+    return *this;
+
+  }
+};
+
+
+typedef std::map<int, TestCase> RunningTestCases;
+
+// Constantly runs up to MAX_NUM_CHILDREN processes
+int RunAllInParallel(const char* processName, bool reRunFailed)
+{
+  int numFailures = 0;
+  int numPasses = 0;
+  int numTestCases = sizeof(tc_array)/sizeof(struct testcase_s) - 1;
 
-            result = tc_array[i].function();
+  RunningTestCases children;
+  std::vector<int> failedTestCases;
 
-            if (tc_array[i].cleanup)
-                tc_array[i].cleanup();
+  // Fork up to MAX_NUM_CHILDREN processes, then
+  // wait. As soon as a proc completes, fork the next.
+
+  int nextTestCase = 0;
+  int numRunningChildren = 0;
+  while( nextTestCase < numTestCases || numRunningChildren > 0)
+  {
+    if( nextTestCase < numTestCases )
+    {
+      while( numRunningChildren < MAX_NUM_CHILDREN )
+      {
+        int pid = fork();
+        if( pid == 0 ) // Child process
+        {
+          close(STDOUT_FILENO);
+          close(STDERR_FILENO);
+          exit( RunTestCase( tc_array[nextTestCase] ) );
+        }
+        else if(pid == -1)
+        {
+          perror("fork");
+          exit(2);
+        }
+        else // Parent process
+        {
+          TestCase tc(nextTestCase, tc_array[nextTestCase].name);
+          children[pid] = tc;
+          nextTestCase++;
+          numRunningChildren++;
+        }
+      }
+    }
+
+    int status=0;
+    int childPid = waitpid(-1, &status, 0);
+    if( childPid == -1 )
+    {
+      perror("waitpid");
+      exit(2);
+    }
+
+    if( WIFEXITED(status) )
+    {
+      if( childPid > 0 )
+      {
+        int testResult = WEXITSTATUS(status);
+        if( testResult )
+        {
+          printf("Test case %s failed: %d\n", children[childPid].testCaseName, testResult);
+          failedTestCases.push_back(children[childPid].testCase);
+          numFailures++;
+        }
+        else
+        {
+          numPasses++;
+        }
+        numRunningChildren--;
+      }
+    }
 
-            return result;
+    else if( WIFSIGNALED(status) )
+    {
+      if( childPid > 0 )
+      {
+        RunningTestCases::iterator iter = children.find(childPid);
+        if( iter != children.end() )
+        {
+          printf("Test case %s exited with signal %d\n", iter->second.testCaseName, WTERMSIG(status));
+          failedTestCases.push_back(iter->second.testCase);
+        }
+        else
+        {
+          printf("Unknown child process: %d signaled %d\n", childPid, WTERMSIG(status));
         }
+
+        numFailures++;
+        numRunningChildren--;
+      }
+    }
+  }
+
+  printf("\rNumber of test passes: %d                                        \n", numPasses);
+  printf("Number of test failures: %d\n", numFailures);
+
+  if( reRunFailed )
+  {
+    for( unsigned int i=0; i<failedTestCases.size(); i++)
+    {
+      printf("Running test case %s:\n", tc_array[failedTestCases[i]].name );
+      RunTestCase( tc_array[failedTestCases[i] ] );
     }
+  }
 
-    printf("Unknown testcase name: \"%s\"\n", argv[1]);
-    return 2;
+  return numFailures;
+}
+
+int FindAndRunTestCase(const char* testCaseName)
+{
+  int result = 2;
+
+  for( int i = 0; tc_array[i].name; i++ )
+  {
+    if( !strcmp(testCaseName, tc_array[i].name) )
+    {
+      return RunTestCase( tc_array[i] );
+    }
+  }
+
+  printf("Unknown testcase name: \"%s\"\n", testCaseName);
+  return result;
+}
+
+int main(int argc, char * const argv[])
+{
+  int result = -1;
+
+  const char* optString = "pr";
+  bool optParallel(false);
+  bool optRerunFailed(false);
+
+  int nextOpt = 0;
+  do
+  {
+    nextOpt = getopt( argc, argv, optString );
+    switch(nextOpt)
+    {
+      case 'p':
+        optParallel = true;
+        break;
+      case 'r':
+        optRerunFailed = true;
+        break;
+    }
+  } while( nextOpt != -1 );
+
+  if( optParallel )
+  {
+    result = RunAllInParallel(argv[0], optRerunFailed);
+  }
+  else
+  {
+    if (argc != 2) {
+      printf("Usage: %s <testcase name>\n", argv[0]);
+      return 2;
+    }
+    result = FindAndRunTestCase(argv[1]);
+  }
+  return result;
 }
index 7714541..c1c8921 100644 (file)
@@ -163,7 +163,7 @@ namespace Toolkit
 namespace Internal
 {
 
-Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot )
+Animation CreateAnimation( const TreeNode& child, const Replacement& constant, Dali::Actor searchRoot, Builder* const builder )
 {
   float durationSum = 0.f;
 
@@ -227,53 +227,54 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D
       OptionalString actorName( constant.IsString( IsChild(pKeyChild.second, "actor" ) ) );
       OptionalString property(  constant.IsString( IsChild(pKeyChild.second, "property" ) ) );
       DALI_ASSERT_ALWAYS( actorName && "Animation must specify actor name" );
-      DALI_ASSERT_ALWAYS( property  && "Animation must specify a property name" );
 
       Handle targetHandle = searchActor.FindChildByName( *actorName );
       DALI_ASSERT_ALWAYS( targetHandle && "Actor must exist for property" );
 
-      Property::Index idx( targetHandle.GetPropertyIndex( *property ) );
-
-      // if the property is not found from the (actor) handle, try to downcast it to renderable actor
-      // to allow animating shader uniforms
-      if( idx == Property::INVALID_INDEX )
+      Property::Value propValue;
+      Property::Index propIndex = Property::INVALID_INDEX;
+      if( property )
       {
-        RenderableActor renderable = RenderableActor::DownCast( targetHandle );
-        if( renderable )
+        propIndex = targetHandle.GetPropertyIndex( *property );
+
+        // if the property is not found from the (actor) handle, try to downcast it to renderable actor
+        // to allow animating shader uniforms
+        if( propIndex == Property::INVALID_INDEX )
         {
-          // A limitation here is that its possible that between creation of animation
-          // and running it the ShaderEffect of the actor has been changed.
-          // However this is a unlikely use case especially when using scripts.
-          if( ShaderEffect effect = renderable.GetShaderEffect() )
+          RenderableActor renderable = RenderableActor::DownCast( targetHandle );
+          if( renderable )
           {
-            idx = effect.GetPropertyIndex( *property );
-            if(idx != Property::INVALID_INDEX)
+            // A limitation here is that its possible that between creation of animation
+            // and running it the ShaderEffect of the actor has been changed.
+            // However this is a unlikely use case especially when using scripts.
+            if( ShaderEffect effect = renderable.GetShaderEffect() )
             {
-              targetHandle = effect;
-            }
-            else
-            {
-              DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
-              continue;
+              propIndex = effect.GetPropertyIndex( *property );
+              if(propIndex != Property::INVALID_INDEX)
+              {
+                targetHandle = effect;
+              }
+              else
+              {
+                DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
+                continue;
+              }
             }
           }
+          else
+          {
+            DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
+            continue;
+          }
         }
-        else
+
+        if( propIndex == Property::INVALID_INDEX)
         {
-          DALI_SCRIPT_WARNING( "Cannot find property on object or ShaderEffect\n" );
+          DALI_ASSERT_ALWAYS( propIndex != Property::INVALID_INDEX && "Animation must specify a valid property" );
           continue;
         }
       }
 
-      if( idx == Property::INVALID_INDEX)
-      {
-        DALI_ASSERT_ALWAYS( idx != Property::INVALID_INDEX && "Animation must specify a valid property" );
-        continue;
-      }
-
-      Property prop( Property( targetHandle, idx ) );
-      Property::Value propValue;
-
       // these are the defaults
       AlphaFunction alphaFunction( AlphaFunctions::Default );
       TimePeriod timePeriod( 0.f );
@@ -294,6 +295,9 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D
 
       if( OptionalChild keyFrameChild = IsChild(pKeyChild.second, "key-frames") )
       {
+        DALI_ASSERT_ALWAYS( property  && "Animation must specify a property name" );
+        Property prop = Property( targetHandle, propIndex );
+
         KeyFrames keyframes = KeyFrames::New();
 
         const TreeNode::ConstIterator endIter = (*keyFrameChild).CEnd();
@@ -338,8 +342,45 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D
           animation.AnimateBetween( prop, keyframes, alphaFunction );
         }
       }
+      else if( OptionalString pathChild = IsString(pKeyChild.second, "path") )
+      {
+        //Get path
+        Path path = builder->GetPath(*pathChild);
+        if( path )
+        {
+          //Get forward vector if specified
+          Vector3 forward( 0.0f, 0.0f, 0.0f );
+          OptionalVector3 forwardProperty = constant.IsVector3( IsChild(pKeyChild.second, "forward" ) );
+          if( forwardProperty )
+          {
+            forward = *forwardProperty;
+          }
+
+          Actor actor = Actor::DownCast( targetHandle );
+          if( actor )
+          {
+            if( timeChild )
+            {
+              animation.Animate( actor, path, forward, alphaFunction, timePeriod );
+            }
+            else
+            {
+              animation.Animate( actor, path, forward, alphaFunction );
+            }
+
+          }
+        }
+        else
+        {
+          //Path not found
+          DALI_SCRIPT_WARNING( "Cannot find animation path '%s'\n", (*pathChild).c_str() );
+        }
+      }
       else
       {
+        DALI_ASSERT_ALWAYS( property  && "Animation must specify a property name" );
+
+        Property prop = Property( targetHandle, propIndex );
         try
         {
           propValue = GetPropertyValue( prop.object.GetPropertyType(prop.propertyIndex), *IsChild(pKeyChild.second, "value") );
@@ -386,10 +427,10 @@ Animation CreateAnimation( const TreeNode& child, const Replacement& constant, D
   return animation;
 }
 
-Animation CreateAnimation( const TreeNode& child )
+Animation CreateAnimation( const TreeNode& child, Builder* const builder )
 {
   Replacement replacement;
-  return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer() );
+  return CreateAnimation( child, replacement, Stage::GetCurrent().GetRootLayer(), builder );
 }
 
 } // namespace Internal
index ba3678b..ab40d18 100644 (file)
@@ -44,13 +44,13 @@ namespace Internal
 {
 class Replacement;
 
-extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot );
+extern Animation CreateAnimation(const TreeNode& child, const Replacement& replacements, const Dali::Actor searchRoot, Builder* const builder );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value, const Replacement& replacements );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Type type, Property::Value& value, const Replacement& replacements );
-extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction);
-extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction);
+extern Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder);
+extern Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder);
 extern Actor SetupActor( const TreeNode& node, Actor& actor, const Replacement& constant );
 
 #if defined(DEBUG_ENABLED)
@@ -355,8 +355,8 @@ void Builder::ApplyProperties( const TreeNode& root, const TreeNode& node,
 
       // add signals
       QuitAction quitAction( *this );
-      SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction );
-      SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction );
+      SetupSignalAction( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this );
+      SetupPropertyNotification( mSlotDelegate.GetConnectionTracker(), root, node, actor, quitAction, this );
    }
   }
   else
@@ -745,6 +745,69 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name, const Re
   return ret;
 }
 
+Path Builder::GetPath( const std::string& name )
+{
+  DALI_ASSERT_ALWAYS(mParser.GetRoot() && "Builder script not loaded");
+
+  Path ret;
+
+  PathLut::const_iterator iter( mPathLut.find( name ) );
+  if( iter != mPathLut.end() )
+  {
+    ret = iter->second;
+  }
+  else
+  {
+    if( OptionalChild paths = IsChild( *mParser.GetRoot(), "paths") )
+    {
+      if( OptionalChild path = IsChild( *paths, name ) )
+      {
+        //points property
+        if( OptionalChild pointsProperty = IsChild( *path, "points") )
+        {
+          Dali::Property::Value points(Property::ARRAY);
+          if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+          {
+            ret = Path::New();
+            ret.SetProperty( Path::POINTS, points);
+
+            //control-points property
+            if( OptionalChild pointsProperty = IsChild( *path, "control-points") )
+            {
+              Dali::Property::Value points(Property::ARRAY);
+              if( SetPropertyFromNode( *pointsProperty, Property::ARRAY, points ) )
+              {
+                ret.SetProperty( Path::CONTROL_POINTS, points);
+              }
+            }
+            else
+            {
+              //Curvature
+              float curvature(0.25f);
+              if( OptionalFloat pointsProperty = IsFloat( *path, "curvature") )
+              {
+                curvature = *pointsProperty;
+              }
+              ret.GenerateControlPoints(curvature);
+            }
+
+            //Add the new path to the hash table for paths
+            mPathLut[ name ] = ret;
+          }
+        }
+        else
+        {
+          //Interpolation points not specified
+          DALI_SCRIPT_WARNING("Interpolation points not specified for path '%s'\n", name.c_str() );
+        }
+      }
+
+    }
+  }
+
+  return ret;
+}
+
 Toolkit::Builder::Signal& Builder::QuitSignal()
 {
   return mQuitSignal;
@@ -808,7 +871,7 @@ Animation Builder::CreateAnimation( const std::string& animationName, const Repl
   {
     if( OptionalChild animation = IsChild(*animations, animationName) )
     {
-      anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor );
+      anim = Dali::Toolkit::Internal::CreateAnimation( *animation, replacement, sourceActor, this );
     }
     else
     {
index 477f1aa..a51a350 100644 (file)
@@ -180,6 +180,10 @@ public:
   FrameBufferImage GetFrameBufferImage( const std::string &name, const Replacement& constant );
 
   /**
+   * @copydoc Toolkit::Builder::GetPath
+   */
+  Path GetPath( const std::string &name );
+  /**
    * @copydoc Toolkit::Builder::QuitSignal
    */
   Toolkit::Builder::Signal& QuitSignal();
@@ -209,6 +213,9 @@ private:
   typedef std::map<const std::string, ShaderEffect> ShaderEffectLut;
   ShaderEffectLut mShaderEffectLut;
 
+  typedef std::map<const std::string, Path> PathLut;
+  PathLut mPathLut;
+
   SlotDelegate<Builder> mSlotDelegate;
 
   Property::Map mReplacementMap;
index c323fab..40428e3 100644 (file)
@@ -29,7 +29,7 @@ namespace Toolkit
 {
 namespace Internal
 {
-extern Animation CreateAnimation( const TreeNode& child );
+extern Animation CreateAnimation( const TreeNode& child, Dali::Toolkit::Internal::Builder* const builder  );
 extern bool SetPropertyFromNode( const TreeNode& node, Property::Value& value );
 }
 }
@@ -126,11 +126,12 @@ struct GenericAction
 // Delay an animation play; ie wait as its not on stage yet
 struct DelayedAnimationPlay
 {
-  Toolkit::JsonParser memento;
+  OptionalChild                                         animNode;
+  Dali::IntrusivePtr<Dali::Toolkit::Internal::Builder>  builder;
 
   void operator()(void)
   {
-    Animation anim = Toolkit::Internal::CreateAnimation(*memento.GetRoot());
+    Animation anim = Toolkit::Internal::CreateAnimation(*animNode, builder.Get() );
     if(anim)
     {
       anim.Play();
@@ -222,7 +223,7 @@ void DoNothing(void) {};
 /**
  * Get an action as boost function callback
  */
-boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction)
+boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder)
 {
   OptionalString childActorName(IsString( IsChild(&child, "child-actor")) );
   OptionalString actorName(IsString( IsChild(&child, "actor")) );
@@ -279,7 +280,8 @@ boost::function<void (void)> GetAction(const TreeNode &root, const TreeNode &chi
       if( OptionalChild animNode = IsChild(*animations, *animationName) )
       {
         DelayedAnimationPlay action;
-        action.memento = Toolkit::JsonParser::New(*animNode);
+        action.animNode = animNode;
+        action.builder = builder;
         // @todo; put constants into the map
         callback = action;
       }
@@ -356,13 +358,13 @@ namespace Toolkit
 namespace Internal
 {
 
-Actor SetupSignalAction(const TreeNode &child, Actor actor);
-Actor SetupPropertyNotification(const TreeNode &child, Actor actor);
+Actor SetupSignalAction(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
+Actor SetupPropertyNotification(const TreeNode &child, Actor actor, Dali::Toolkit::Internal::Builder* const builder );
 
 /**
  * Setup signals and actions on an actor
  */
-Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction)
+Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -379,7 +381,7 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const
       OptionalString name( IsString( IsChild( key_child.second, "name")) );
       DALI_ASSERT_ALWAYS(name && "Signal must have a name");
 
-      boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction);
+      boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction, builder );
 
       actor.ConnectSignal(tracker, *name, callback);
     }
@@ -391,7 +393,7 @@ Actor SetupSignalAction(ConnectionTracker* tracker, const TreeNode &root, const
 /**
  * Setup Property notifications for an actor
  */
-Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction)
+Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root, const TreeNode &child, Actor actor, boost::function<void (void)> quitAction, Dali::Toolkit::Internal::Builder* const builder )
 {
   DALI_ASSERT_ALWAYS(actor);
 
@@ -405,7 +407,7 @@ Actor SetupPropertyNotification(ConnectionTracker* tracker, const TreeNode &root
 
       // Actor actions reference by pointer because of circular reference actor->signal
       // So this callback should only go onto the actor maintained list.
-      boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction);
+      boost::function<void (void)> callback = GetAction(root, key_child.second, actor, quitAction, builder );
 
       OptionalString prop(IsString( IsChild(key_child.second, "property")) );
       DALI_ASSERT_ALWAYS(prop && "Notification signal must specify a property");
index 3f531a3..bd85719 100644 (file)
@@ -144,6 +144,11 @@ FrameBufferImage Builder::GetFrameBufferImage( const std::string &name )
   return GetImpl(*this).GetFrameBufferImage( name );
 }
 
+Path Builder::GetPath( const std::string &name )
+{
+  return GetImpl(*this).GetPath( name );
+}
+
 Builder::Signal& Builder::QuitSignal()
 {
   return GetImpl( *this ).QuitSignal();
index 65ece45..98d3d8c 100644 (file)
@@ -399,6 +399,15 @@ class DALI_IMPORT_API Builder : public BaseHandle
    */
   FrameBufferImage GetFrameBufferImage( const std::string &name );
 
+  /**
+   * Get or create Path from the Path instance library.
+   * An empty handle is returned otherwise.
+   * @pre The Builder has been initialized.
+   * @param name The name of a Path in the loaded representation
+   * @return A handle to a Path if found, otherwise empty
+   */
+  Path GetPath( const std::string &name );
+
   // Signals
 
   /**
index 7de9ea8..12efc07 100644 (file)
@@ -31,7 +31,7 @@ namespace Toolkit
 
 const unsigned int TOOLKIT_MAJOR_VERSION = 1;
 const unsigned int TOOLKIT_MINOR_VERSION = 0;
-const unsigned int TOOLKIT_MICRO_VERSION = 19;
+const unsigned int TOOLKIT_MICRO_VERSION = 20;
 const char * const TOOLKIT_BUILD_DATE    = __DATE__ " " __TIME__;
 
 #ifdef DEBUG_ENABLED
index 2d1fffa..137f9fd 100644 (file)
@@ -1,6 +1,6 @@
 Name:       dali-toolkit
 Summary:    The OpenGLES Canvas Core Library Toolkit
-Version:    1.0.19
+Version:    1.0.20
 Release:    1
 Group:      System/Libraries
 License:    Apache-2.0