Issue with Screen Transition Animation Not Playing Before Screen Change in Crank Storyboard

I am trying to implement a screen transition effect in Crank Storyboard using Lua. The goal is to play an animation first and then switch to the target screen. However, when I run my script, the animation does not play—it directly switches to the next screen.

Current Implementation:

Here's the code I am using:

luaCopyEditfunction hide_info_layer(screen)if screen then        gre.set_layer_attrs_global(screen, { hidden = 1 })
    elseprint("Error: screen is nil in hide_info_layer")
    end endfunction screen_transition(target_screen)if target_screen thenprint("Transitioning to:", target_screen)
        gre.set_value("target_sc", target_screen)
        gre.send_event("gre.load_screen", target_screen) -- Directly load the screenelseprint("Error: target_screen is nil in screen_transition")
    end endfunction cb_presstart_button(mapargs)local current_screen = mapargs.context_screen
    local control = mapargs.context_control

    -- Fetch correct screen namelocal target_screen = gre.get_value(string.format("%s.screen_name1", control))

    print("Current Screen:", current_screen)
    print("Target Screen:", target_screen)

    if current_screen == target_screen thenprint("Already on target screen, no transition needed")
        returnend
    hide_info_layer(current_screen)

    if current_screen == "start" then        gre.set_value("target_sc", target_screen)
        print("Triggering animation: punch_NewAnimation")
        gre.animation_trigger("punch_NewAnimation")
    elseprint("Calling screen_transition")
        screen_transition(target_screen)
    end end

Observed Behavior:

  • The animation punch_NewAnimation does not play when transitioning between screens.
  • The screen changes immediately after calling gre.animation_trigger(), skipping the animation effect.
  • The console prints the expected logs but does not execute the animation before the screen transition.

Attempts to Resolve:

  1. Delaying Screen Change Until Animation Ends
    • I tried adding a delay after triggering the animation but didn't find a direct way to ensure the transition happens only after the animation completes.
  2. Using Animation Callbacks
    • I attempted to listen for an animation event before triggering the screen change but couldn't find a working solution.

Expected Behavior:

  • The animation (punch_NewAnimation) should play completely.
  • After the animation finishes, the screen should transition to target_screen.

Question:

How can I ensure that the animation plays fully before transitioning to the next screen? Is there a way to use animation callbacks or events to handle this properly in Crank Storyboard?

Any guidance or example code or any video if there is any video related to it would be greatly appreciated!

0

Comments

5 comments
  • Hi Sahil,

    It should be fairly simple to do this using the animation completion event. Each animation generates a unique event on both completion and when it's stopped. The completion event has the prefix 'gre.animate.complete.' plus the animation name. You could easily setup an event listener on this unique event, and when the listener is invoked you can trigger your screen transition. See in the below code snippet:

    ---
    -- Transition to a new screen by setting a app level variable and
    -- trigger a screen transition action with the load_screen event
    local function screen_transition(target_screen)
        gre.set_value('target_sc', target_screen)
        gre.send_event('load_screen')
    end

    -- variable to store our event listener in
    local transition_animation_listener = nil
    ---
    -- Chain an animation and screen transition back to back using gre.add_event_listener()
    -- @param target_screen - the next screen to transition to
    -- @param animation_id - the name or id of the animation to trigger first
    local function screen_transition_animation(target_screen, animation_id)
        local current_screen = gre.env('active_screen')
        if (current_screen == target_screen) then
            return
        end

        if (transition_animation_listener ~= nil) then
            -- don't trigger twice in a row
            return
        end

        local animation_complete_ev = string.format('gre.animate.complete.%s', animation_id)
        transition_animation_listener =
            gre.add_event_listener(animation_complete_ev, '',
            function()
                transition_animation_listener = nil
                screen_transition(target_screen)
            end)
        gre.animation_trigger(animation_id)
    end

    ---
    -- Trigger an animation created using the animation timeline and
    -- then transition to the second screen on complete
    function cb_transition_to_second_sc(mapargs)
        screen_transition_animation('second_sc', 'first_screen_btn_press')
    end

    ---
    -- Create/trigger an animation created in Lua, and
    -- then transition to the first screen on completion
    function cb_transition_to_first_sc(mapargs)
        local animation_id = gre.animation_create(30,1)
        local data = {}
        data.rate = 'ease out'
        data.duration = 500
        data.offset = 0
        data.to = 370
        data.key = 'second_content_layer.next_btn.grd_y'
        gre.animation_add_step(animation_id, data)

        screen_transition_animation('first_sc', animation_id)
    end

    As you can see above, I created a function called screen_transition_animation that take two variables, the next screen name and the animation to trigger. It first determines if we are on the target screen using gre.env('active_screen') to query the current screen, adds an event listener for the animation completion event, and then triggers the animation. The anonymous function used in the gre.add_event_listener function will be triggered once the animation is complete, and it will be what calls screen_transition(target_screen). I used this function to transition back and forth between two screens in this quick example. The animation for the transition to second_sc was created using the animation timeline, while the animation for the transition to first_sc was generated in Lua at runtime. But both can use the same technique for chain the animation and subsequent screen transition.

    I hope this helps you in your current work.

    - Matt

    0
  • Hey thanks Matt for the solution i am having some doubts in one more please can you guide me through........

    Problem Description

    I have implemented a password authentication system in Storyboard using Lua. The functionality of entering a password and checking its correctness is working fine. However, the screen transition is not happening as expected when the correct password is entered.

    Expected Behavior

    • The screen should remain stable and not transition unless the correct password is entered.

    • Upon entering the correct password and pressing enter, the screen should transition to another screen.

    •  

    Current Issue

    • The password entry works correctly.

    • When entering the correct password, the transition (gre.set_value("target_sc", "Start") and gre.send_event("load_screen")) does not occur.

    • I have tried different methods but cannot get the screen to transition properly.

    • I used the screen transition then only i can achieve but i want it through lua code.                                                     

      -- Password Configuration

      local PASSCODE_LENGTH = 4

      local CORRECT_PASSCODE = "1234"

      local current_password = ""

      local is_authenticated = false

       

      -- Function to update password display

      local function UpdatePasswordDisplay()

      local display_text = string.rep("•", #current_password) .. string.rep("-", PASSCODE_LENGTH - #current_password)

      print("DEBUG: Display updated to:", display_text)

      gre.set_value("ready2.Background3.text", display_text)

      end

       

      -- Number button handler (keep this name if your buttons use it)

      function cb_change_pwd(mapargs)

      if is_authenticated then

      print("DEBUG: Already authenticated, ignoring input")

      return

      end

       

      if #current_password >= PASSCODE_LENGTH then

      print("DEBUG: Maximum length reached")

      return

      end

       

      local button_name = mapargs.context_control:match("[^.]+$")

      local button_values = {

      ["1"] = "1", ["2"] = "2", ["3"] = "3", ["4"] = "4",

      ["5"] = "5", ["6"] = "6", ["7"] = "7", ["8"] = "8",

      ["9"] = "9", ["0"] = "0", ["star"] = "*", ["hash"] = "#"

      }

       

      local value = button_values[button_name]

      if not value then

      print("DEBUG: Unknown button pressed:", button_name)

      return

      end

       

      current_password = current_password .. value

      print("DEBUG: Added character. Current input:", current_password)

      UpdatePasswordDisplay()

       

      if #current_password == PASSCODE_LENGTH then

      CheckPassword()

      end

      end

       

      -- Password verification

      function CheckPassword()

      print("DEBUG: Checking password:", current_password)

       

      if current_password == CORRECT_PASSCODE then

      is_authenticated = true

      print("SUCCESS: Correct password! Transitioning...")

      gre.set_value("target_sc", "Start")

      gre.send_event("load_screen")

      else

      print("FAIL: Incorrect password!")

      gre.set_value("ready2.Background3.text", "WRONG!")

       

      gre.timer_set_timeout(function()

      print("DEBUG: Resetting after incorrect attempt")

      current_password = ""

      UpdatePasswordDisplay()

      end, 1000)

      end

      end

       

      -- Backspace handler (FIXED NAME - must match what buttons call)

      function CBBackspacePress(mapargs) -- Changed to match your button callback

      if is_authenticated then return end

      if #current_password > 0 then

      current_password = current_password:sub(1, -2)

      print("DEBUG: Backspace pressed. Current input:", current_password)

      UpdatePasswordDisplay()

      end

      end

       

      -- Enter button handler

      function CB_enter_pressed(mapargs)

      print("DEBUG: Enter button pressed")

      CheckPassword()

      end

     

    0
  • Hi Sahil,

    What does your event handler in your model do when triggered by the 'load_screen'  event?

    gre.set_value("target_sc", "Start")
    gre.send_event("load_screen")

    As mentioned in the support ticket this article may help:

     How to trigger a Screen Transition from Lua – Crank Software

    I suggest that you get a simple model together that demonstrated the correct screen transition  behaviour that you are looking for then apply it to your password application.

    Garry

    0
  • The thing I need is to transfer on the page when I hit enter I did all the things told in this discussion but still its showing error  
    WARN [0.762074]:Transition to invalid screen
    And I am unable to transfer to the screen. Please can you tell me how to do it.Also please tell me where i am Lacking......
    https://support.cranksoftware.com/hc/en-us/community/posts/6856257294356-How-to-trigger-a-Screen-Transition-from-Lua                                                                                                                        
    -- =============================================
    -- PASSWORD SYSTEM WITH VERBOSE CONSOLE LOGGING
    -- =============================================
    local PASSCODE_LENGTH = 4
    local CORRECT_PASSCODE = "1234"
    local current_password = ""
    local is_authenticated = false
    local nav_screen_list = {}
    local current_screen = "lock" -- Start on lock screen
    local transition_in_progress = false
    print("[SYSTEM] **************************************")
    print("[SYSTEM] Initializing Password System")
    print("[SYSTEM] Target Screen: Start")
    print("[SYSTEM] Current Screen:", current_screen)
    print("[SYSTEM] **************************************")
    -- =============================================
    -- SCREEN TRANSITION FUNCTION (WORKING VERSION)
    -- =============================================
    function cb_test_func(target_screen)
    if transition_in_progress then
    print("[NAV] XXXX Transition blocked - already in progress")
    return false
    end
    print("\n[NAV] === STARTING TRANSITION ===")
    print("[NAV] From:", current_screen)
    print("[NAV] To:", target_screen)
    -- Set the target screen and send the event
    gre.set_value("screen_target", "Start")
    gre.send_event("change_screen")
    -- Update current screen state
    transition_in_progress = true
    current_screen = target_screen
    print("[NAV] ---> Transition event sent successfully")
    return true
    end
    -- =============================================
    -- ENHANCED NAVIGATION SYSTEM
    -- =============================================
    function cb_request_screen_transition(mapargs)
    local target_screen = mapargs.target_screen or "Start"
    print("\n[NAV] === NEW TRANSITION REQUEST ===")
    print("[NAV] Requested screen:", target_screen)
    print("[NAV] Current screen:", current_screen)
    print("[NAV] Auth status:", is_authenticated and "AUTHENTICATED" or "LOCKED")
    -- Authentication check
    if target_screen ~= "Lock" and not is_authenticated then
    print("[SECURITY] !!! Blocked unauthorized access to", target_screen)
    target_screen = "Lock"
    end
    -- Process transition using the working function
    cb_test_func(target_screen)
    end
    function cb_check_screen_list(mapargs)
    local arrived_screen = mapargs.context_screen
    print("\n[NAV] === TRANSITION COMPLETE ===")
    print("[NAV] Arrived at screen:", arrived_screen)
    -- Ensure the transition is marked as complete
    transition_in_progress = false
    current_screen = arrived_screen
    -- Process the next screen in the queue if any
    if #nav_screen_list > 0 then
    local next_screen = table.remove(nav_screen_list, 1)
    print("[NAV] Processing next in queue:", next_screen)
    cb_test_func(next_screen)
    else
    print("[NAV] Queue is empty - no pending transitions")
    end
    end
    -- =============================================
    -- PASSWORD SYSTEM WITH DETAILED LOGGING
    -- =============================================
    function UpdatePasswordDisplay()
    local display_text = string.rep("•", #current_password) .. string.rep("-", PASSCODE_LENGTH - #current_password)
    gre.set_value("ready2.Background3.text", display_text)
    print("[PASSWORD] Display updated:", display_text, "| Input:", current_password)
    end
    function cb_change_pwd(mapargs)
    if is_authenticated then
    print("[INPUT] XXXX Ignored - already authenticated")
    return
    end
    if #current_password >= PASSCODE_LENGTH then
    print("[INPUT] XXXX Ignored - max length reached")
    return
    end
    local button_name = mapargs.context_control:match("[^.]+$")
    print("[INPUT] Button pressed:", button_name)
    local button_values = {
    ["1"]="1", ["2"]="2", ["3"]="3", ["4"]="4",
    ["5"]="5", ["6"]="6", ["7"]="7", ["8"]="8",
    ["9"]="9", ["0"]="0", ["star"]="*", ["hash"]="#"
    }
    local value = button_values[button_name]
    if value then
    current_password = current_password .. value
    UpdatePasswordDisplay()
    if #current_password == PASSCODE_LENGTH then
    print("[SYSTEM] >>> Auto-submitting password...")
    CheckPassword()
    end
    else
    print("[INPUT] XXXX Unknown button ignored")
    end
    end
    function CheckPassword()
    print("\n[AUTH] === PASSWORD CHECK ===")
    print("[AUTH] Comparing:", current_password, "vs", CORRECT_PASSCODE)
    if current_password == CORRECT_PASSCODE then
    is_authenticated = true
    print("[AUTH] !!! SUCCESS - ACCESS GRANTED !!!")
    current_password = ""
    UpdatePasswordDisplay()
    -- Initiate transition using working function
    print("[AUTH] Initiating transition to Start screen")
    cb_test_func("Start")
    else
    print("[AUTH] XXXX FAILED - INCORRECT PASSWORD")
    gre.set_value("ready2.Background3.text", "WRONG!")
    gre.timer_set_timeout(function()
    print("[AUTH] Resetting password input")
    current_password = ""
    UpdatePasswordDisplay()
    end, 1000)
    end
    end
    function CBBackspacePress(mapargs)
    if is_authenticated then
    print("[INPUT] XXXX Backspace ignored - authenticated")
    return
    end
    if #current_password > 0 then
    current_password = current_password:sub(1, -2)
    UpdatePasswordDisplay()
    print("[INPUT] Backspace - New input:", current_password)
    else
    print("[INPUT] XXXX Backspace ignored - empty input")
    end
    end
    function CB_enter_pressed(mapargs)
    print("[INPUT] >>> Enter button pressed - validating")
    CheckPassword()
    end
    -- =============================================
    -- INITIALIZATION
    -- =============================================
    print("\n[INIT] ===== SYSTEM STARTUP =====")
    print("[INIT] Loading initial screen: lock")
    cb_test_func("lock")
    print("\n[SYSTEM] **************************************")
    print("[SYSTEM] READY FOR USER INPUT")
    print("[SYSTEM] **************************************")
     
    0
  • Hi Sahil,

    Are you able to share your Storyboard application project so we can take a look at what you have done and maybe debug it for you to figure where it is going wrong.  I suspect that it may be in the binding of the screen name variable to the screen transition action:

    AMfQADnw2sD7IJMtwUBLqw.png (975×600)

    You can zip it up and reply on the existing support ticket or just create a new ticket and attach the archive if possible.

    Regards,

    Garry

    0

Please sign in to leave a comment.

Didn't find what you were looking for?

New post