Quartic ease in/out in Applescript?

Discussion in 'Mac Programming' started by Puonti, Mar 15, 2014.

  1. Puonti macrumors 6502a

    Joined:
    Mar 14, 2011
    #1
    I'm trying to write an Applescript that would dim Philips Hue bulbs based on a quartic ease in/out (speed up until halfway point, then slow down towards the end). The script would run every 10 minutes and calculate what the brightness should be at that time, based on the quartic ease in/out.

    I've found the quartic ease in/out formula in other programming languages but unfortunately my attempts to convert it into Applescript have resulted in values that don't make sense. Since programming and Applescript aren't my strong suites I was hoping someone could help me sort this out.

    Here's what I have for the calculation:

    Code:
    set b to 0 as integer -- starting brightness
    set c to 255 as integer -- target brightness
    set t to 10 as integer -- elapsed time in minutes
    set d to 60 as integer -- fade duration in minutes
    
    t ≠ d / 2
    
    if t < 1 then
    	set hueBrightness to c / 2 * t * t * t * t + b as real
    else
    	set t to t - 2
    	set hueBrightness to -c / 2 * (t * t * t * t - 2) + b as real
    end if
    In the sample script above 10 minutes would have passed since the fade began (t = 10).
     
  2. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #2
    Where did you find it?

    Post the URL where you found the formula you're using.

    If there's more than one language on the web page, also tell us exactly which language you used as your example.
     
  3. Puonti thread starter macrumors 6502a

    Joined:
    Mar 14, 2011
    #3
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    The quartic ease-in/out in ActionScript is this:
    Code:
    // quartic easing in/out - acceleration until halfway, then deceleration
    Math.easeInOutQuart = function (t, b, c, d) {
    [COLOR="Red"]	t /= d/2;
    [/COLOR]	if (t < 1) return c/2*t*t*t*t + b;
    	t -= 2;
    	return -c/2 * (t*t*t*t - 2) + b;
    };
    
    I've hilited in red the line that doesn't correpond to AppleScript.

    The correct AppleScript calculation for that line would be:
    Code:
    set t to t / (d/2)
    
    The /= operator is a divide-and-assign operator, which is completely different from , an inequality comparison.

    If this still doesn't produce the desired results, change all your as integer clauses to as real. The calculation may need intermediate floating-point values, not integers.


    I should also point out that dividing a 60-minute duration into 10-minute intervals is only going to yield 7 points, counting both end-points. The dimming or brightening at each 10-minute point is probably going to be noticeable.
     
  5. Puonti thread starter macrumors 6502a

    Joined:
    Mar 14, 2011
    #5
    Thank you so much! I suspected that particular line might have been the cause, but lack of understanding combined with a Google search lead me astray. Your correction gives me the kind of values I was expecting; problem solved! (and more importantly, I hope, lesson learned)

    Setting bulb brightness to the resulting value would indeed be visible. My plan is to make use of Hue's transitiontime function which makes the bulbs change brightness (and other values, too) over a given time – in this case 10 minutes.

    Thanks again, I appreciate your help.
     
  6. hhas macrumors regular

    Joined:
    Oct 15, 2007
    #6
    Yep. A much better approach would be to step down the brightness by a fixed amount each time, and just use a precalculated list of times to sleep between each step. To illustrate:

    Code:
    -- save as a stay-open applet
    
    global gDelays, gBrightness
    
    on run
       set gDelays to {1, 2, 4, 8, 16, 32, 64, ..., 8, 4, 2, 1} -- whatever
       set gBrightness to 100 -- percentage
    end
    
    on idle
       set gBrightness to gBrightness - 5
       if gDelays is {} -- done
          -- tell applet to terminate as soon as idle handler returns
          quit
          return 0
       else
          set nextDelay to first item of gDelays
          set gDelays to rest of gDelays
          return nextDelay
       end
    end
    
     

Share This Page