Browse Source

Finalised the easingFunctions

pull/137/head
Eugenio Parodi 3 years ago
parent
commit
e1cf4c2ff0
  1. 215
      TermTk/TTkCore/propertyanimation.py
  2. 70
      demo/showcase/animation.01.py

215
TermTk/TTkCore/propertyanimation.py

@ -77,42 +77,200 @@ class TTkEasingCurve():
__slots__ = ('_easingFunc')
def __init__(self, easingCurve=Linear):
self._easingFunc = {self.Linear : TTkEasingCurve._ecLinear,
self.InQuad : TTkEasingCurve._ecInQuad,
self.OutQuad : TTkEasingCurve._ecOutQuad,
self.InOutQuad : TTkEasingCurve._ecInOutQuad,
self.OutInQuad : TTkEasingCurve._ecOutInQuad,
self.InCubic : TTkEasingCurve._ecInCubic,
self.OutCubic : TTkEasingCurve._ecOutCubic,
self.OutBounce : TTkEasingCurve._ecOutBounce,
self.InQuad : TTkEasingCurve._ecInQuad,
self.OutQuad : TTkEasingCurve._ecOutQuad,
self.InOutQuad : TTkEasingCurve._ecInOutQuad,
self.OutInQuad : TTkEasingCurve._ecOutInQuad,
self.InCubic : TTkEasingCurve._ecInCubic,
self.OutCubic : TTkEasingCurve._ecOutCubic,
self.InOutCubic : TTkEasingCurve._ecInOutCubic,
self.OutInCubic : TTkEasingCurve._ecOutInCubic,
self.InQuart : TTkEasingCurve._ecInQuart,
self.OutQuart : TTkEasingCurve._ecOutQuart,
self.InOutQuart : TTkEasingCurve._ecInOutQuart,
self.OutInQuart : TTkEasingCurve._ecOutInQuart,
self.InQuint : TTkEasingCurve._ecInQuint,
self.OutQuint : TTkEasingCurve._ecOutQuint,
self.InOutQuint : TTkEasingCurve._ecInOutQuint,
self.OutInQuint : TTkEasingCurve._ecOutInQuint,
self.InSine : TTkEasingCurve._ecInSine,
self.OutSine : TTkEasingCurve._ecOutSine,
self.InOutSine : TTkEasingCurve._ecInOutSine,
self.OutInSine : TTkEasingCurve._ecOutInSine,
self.InExpo : TTkEasingCurve._ecInExpo,
self.OutExpo : TTkEasingCurve._ecOutExpo,
self.InOutExpo : TTkEasingCurve._ecInOutExpo,
self.OutInExpo : TTkEasingCurve._ecOutInExpo,
self.InCirc : TTkEasingCurve._ecInCirc,
self.OutCirc : TTkEasingCurve._ecOutCirc,
self.InOutCirc : TTkEasingCurve._ecInOutCirc,
self.OutInCirc : TTkEasingCurve._ecOutInCirc,
self.InElastic : TTkEasingCurve._ecInElastic,
self.OutElastic : TTkEasingCurve._ecOutElastic,
self.InOutElastic : TTkEasingCurve._ecInOutElastic,
self.OutInElastic : TTkEasingCurve._ecOutInElastic,
self.InBack : TTkEasingCurve._ecInBack,
self.OutBack : TTkEasingCurve._ecOutBack,
self.InOutBack : TTkEasingCurve._ecInOutBack,
self.OutInBack : TTkEasingCurve._ecOutInBack,
self.InBounce : TTkEasingCurve._ecInBounce,
self.OutBounce : TTkEasingCurve._ecOutBounce,
self.InOutBounce : TTkEasingCurve._ecInOutBounce,
self.OutInBounce : TTkEasingCurve._ecOutInBounce,
self.OutBounce : TTkEasingCurve._ecOutBounce,
}.get(easingCurve,TTkEasingCurve._ecLinear)
def process(self,a,b,v):
v = self._easingFunc(v)
return float(b)*v+float(a)*(1-v)
# Formulas from https://easings.net
@staticmethod
def _ecLinear(v):
return v
def _ecMixCbHelper(incb,outcb,v):
if v < 0.5: return incb(2*v)/2
return 0.5+outcb(2*v-1)/2
@staticmethod
def _ecInQuad(v):
return v*v
def _ecInOutHelper(incb,outcb,v):
if v < 0.5: return incb(2*v)/2
return 0.5+outcb(2*v-1)/2
@staticmethod
def _ecOutQuad(v):
return 1-(1-v)*(1-v)
def _ecOutInHelper(incb,outcb,v):
if v < 0.5: return outcb(2*v)/2
return 0.5+incb(2*v-1)/2
# Equations adapted from
# - https://easings.net
# - https://github.com/qt/qtbase/blob/dev/src/3rdparty/easing/easing.cpp
@staticmethod
def _ecLinear(v): return v
@staticmethod
def _ecInQuad(v): return v*v
@staticmethod
def _ecOutQuad(v): return -v*(v-2)
@staticmethod
def _ecInOutQuad(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInQuad,
TTkEasingCurve._ecOutQuad,
v)
@staticmethod
def _ecOutInQuad(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutQuad,
TTkEasingCurve._ecInQuad,
v)
@staticmethod
def _ecInCubic(v): return v*v*v
@staticmethod
def _ecOutCubic(v): v-=1 ; return 1+v*v*v
@staticmethod
def _ecInOutCubic(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInCubic,
TTkEasingCurve._ecOutCubic,
v)
@staticmethod
def _ecOutInCubic(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutCubic,
TTkEasingCurve._ecInCubic,
v)
@staticmethod
def _ecInQuart(v): return v*v*v*v
@staticmethod
def _ecOutQuart(v): v-=1 ; return 1-v*v*v*v
@staticmethod
def _ecInOutQuart(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInQuart,
TTkEasingCurve._ecOutQuart,
v)
@staticmethod
def _ecOutInQuart(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutQuart,
TTkEasingCurve._ecInQuart,
v)
@staticmethod
def _ecInQuint(v): return v*v*v*v*v
@staticmethod
def _ecOutQuint(v): v-=1 ; return 1+v*v*v*v*v
@staticmethod
def _ecInOutQuint(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInQuint,
TTkEasingCurve._ecOutQuint,
v)
@staticmethod
def _ecOutInQuint(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutQuint,
TTkEasingCurve._ecInQuint,
v)
@staticmethod
def _ecInSine(v): return 1-math.sin(math.pi*(1-v)/2)
@staticmethod
def _ecInOutQuad(v):
return v
def _ecOutSine(v): return math.sin(math.pi*v/2)
@staticmethod
def _ecOutInQuad(v):
return v
def _ecInOutSine(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInSine,
TTkEasingCurve._ecOutSine,
v)
@staticmethod
def _ecInCubic(v):
return v*v*v
def _ecOutInSine(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutSine,
TTkEasingCurve._ecInSine,
v)
@staticmethod
def _ecOutCubic(v):
return 1-(1-v)*(1-v)*(1-v)
def _ecInExpo(v): return v if v==1 or v==0 else math.pow(2,10*(v-1))-0.001
@staticmethod
def _ecOutExpo(v): return 1 if v==1 else 1.001*(1-math.pow(2,-10*v))
@staticmethod
def _ecInOutExpo(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInExpo,
TTkEasingCurve._ecOutExpo,
v)
@staticmethod
def _ecOutInExpo(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutExpo,
TTkEasingCurve._ecInExpo,
v)
@staticmethod
def _ecInCirc(v): return 1-math.sqrt(1-v*v)
@staticmethod
def _ecOutCirc(v): v-=1 ; return math.sqrt(1-v*v)
@staticmethod
def _ecInOutCirc(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInCirc,
TTkEasingCurve._ecOutCirc,
v)
@staticmethod
def _ecOutInCirc(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutCirc,
TTkEasingCurve._ecInCirc,
v)
@staticmethod
def _ecInElastic(v): return v if v in [0,1] else -math.pow(2, 10 *v-10)*math.sin((v*10-10.75)*(2*math.pi)/3)
@staticmethod
def _ecOutElastic(v): return 1-TTkEasingCurve._ecInElastic(1-v)
@staticmethod
def _ecInOutElastic(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInElastic,
TTkEasingCurve._ecOutElastic,
v)
@staticmethod
def _ecOutInElastic(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutElastic,
TTkEasingCurve._ecInElastic,
v)
@staticmethod
def _ecInBack(v,s=1.7): return v*v*((s+1)*v-s)
@staticmethod
def _ecOutBack(v,s=1.7): v-=1 ; return v*v*((s+1)*v+s)+1
@staticmethod
def _ecInOutBack(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInBack,
TTkEasingCurve._ecOutBack,
v)
@staticmethod
def _ecOutInBack(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutBack,
TTkEasingCurve._ecInBack,
v)
@staticmethod
def _ecInBounce(v): return 1-TTkEasingCurve._ecOutBounce(1-v)
@staticmethod
def _ecOutBounce(x):
n1 = 7.5625
@ -128,6 +286,17 @@ class TTkEasingCurve():
else:
x -= 2.625 / d1
return n1 * x * x + 0.984375
@staticmethod
def _ecInOutBounce(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecInBounce,
TTkEasingCurve._ecOutBounce,
v)
@staticmethod
def _ecOutInBounce(v): return TTkEasingCurve._ecMixCbHelper(
TTkEasingCurve._ecOutBounce,
TTkEasingCurve._ecInBounce,
v)
class TTkPropertyAnimation():
__slots__ = ('_target', '_propertyName', '_parent', '_cb', '_cast',

70
demo/showcase/animation.01.py

@ -33,11 +33,47 @@ import TermTk as ttk
sys.path.append(os.path.join(sys.path[0],'..'))
from showcase._showcasehelper import getUtfColoredSentence
class superSimpleHorizontalLine(ttk.TTkWidget):
class EasingShow(ttk.TTkWidget):
__slots__ = ('_easingCb')
def __init__(self, easingCb, *args, **kwargs):
super().__init__(*args, **kwargs)
self._easingCb = ttk.TTkEasingCurve(easingCb)
def paintEvent(self):
# gen w*2,h*4 pixmap
w,h = self.size()
self._canvas.drawText(pos=(0,h-1), text=''+(''*(w-2))+'',color=ttk.TTkColor.fg("#888888"))
pm = [[0]*h*4 for _ in range(w*2)]
vs = []
# populate the pixmap
for x in range(w*2):
v = float(x)/(w*2-1) # v goes from 0 -> 1
vs.append(self._easingCb.process(0,1,v))
maxv = max(vs)
minv = min(vs)
for x,v in enumerate(vs):
y = int((h*4-1)*(v-minv)/(maxv-minv))
pm[x][h*4-y-1] = 1
'''
Braille bits:
o2 o1 = 4 bits each
1 5 Braille dots
2 6
3 7
4 8
TTkTheme.braille[( o1<<4 | o2 )] = Braille UTF-8 char
'''
canvas = self.getCanvas()
gb=ttk.TTkCfg.theme.braille
color=ttk.TTkColor.fg("#FFFF00")+ttk.TTkColor.bg("#004400", modifier=ttk.TTkColorGradient(increment=-5))
for x in range(w):
for y in range(h):
o1 = pm[2*x ][4*y] | pm[2*x ][4*y+1]<<1 | pm[2*x ][4*y+2]<<2 | pm[2*x ][4*y+3]<<3
o2 = pm[2*x+1][4*y] | pm[2*x+1][4*y+1]<<1 | pm[2*x+1][4*y+2]<<2 | pm[2*x+1][4*y+3]<<3
ch = gb[( o1<<4 | o2 )]
canvas.drawChar(pos=(x,y),char=ch, color=color)
def demoTextEditRO(root=None):
easingList = (
@ -92,27 +128,36 @@ def demoTextEditRO(root=None):
animBtnScroll = ttk.TTkButton(parent=winAc, text="Anim Scroll",border=True,pos=(0,0))
animBtnWinPos = ttk.TTkButton(parent=winAc, text="Anim Pos",border=True,pos=(15,0))
animBoth = ttk.TTkButton(parent=winAc, text="Anim Both",border=True,pos=(25,0))
animHelper = ttk.TTkButton(parent=winAc, text="Anim Easing Charts",border=True,pos=(0,23))
winHelper = ttk.TTkWindow(parent=frame, title="Easing Charts", pos=(80,0), size=(50,30), layout=ttk.TTkGridLayout())
scrollArea = ttk.TTkScrollArea(parent=winHelper)
saWp = scrollArea.viewport()
for i,(easing,name) in enumerate(easingList):
ttk.TTkLabel(parent=saWp, pos=(0,i*9), size=(40,1), text=name)
EasingShow( parent=saWp, pos=( 0, 1+i*9), size=(40,8), easingCb=easing)
class PosControls(ttk.TTkFrame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs|{'border':True})
ttk.TTkLabel( parent=self,pos=(0,0),text='Starting Position (x,y)')
self.axspb = ttk.TTkSpinBox(parent=self,maximum=200, minimum=-100, pos=(0,1),size=(8,1),value=0)
self.ayspb = ttk.TTkSpinBox(parent=self,maximum=200, minimum=-100, pos=(8,1),size=(8,1),value=100)
self.axspb = ttk.TTkSpinBox(parent=self,maximum=500, minimum=-100, pos=(0,1),size=(8,1),value=0)
self.ayspb = ttk.TTkSpinBox(parent=self,maximum=500, minimum=-100, pos=(8,1),size=(8,1),value=100)
ttk.TTkLabel( parent=self,pos=(0,2),text='Ending Position (x,y)')
self.bxspb = ttk.TTkSpinBox(parent=self,maximum=200, minimum=-100, pos=(0,3),size=(8,1),value=0)
self.byspb = ttk.TTkSpinBox(parent=self,maximum=200, minimum=-100, pos=(8,3),size=(8,1),value=0)
self.bxspb = ttk.TTkSpinBox(parent=self,maximum=500, minimum=-100, pos=(0,3),size=(8,1),value=0)
self.byspb = ttk.TTkSpinBox(parent=self,maximum=500, minimum=-100, pos=(8,3),size=(8,1),value=0)
ttk.TTkLabel( parent=self,pos=(0,4),text='Duration (sec.)')
self.dursb = ttk.TTkSpinBox(parent=self,maximum=200, minimum=0, pos=(0,5),size=(12,1),value=2)
self.dursb = ttk.TTkSpinBox(parent=self,maximum=500, minimum=0, pos=(0,5),size=(12,1),value=2)
ttk.TTkLabel( parent=self,pos=(0,6),text='Easing Curve')
self.ecb = ttk.TTkComboBox(parent=self,pos=(0,7),size=(20,1),list=[v for (_,v) in easingList],index=0)
pcScroll = PosControls(parent=winAc, pos=(0,3), size=(25,10), title="Text Scroll")
pcWinPos = PosControls(parent=winAc, pos=(0,13), size=(25,10), title="Window Position")
pcHelpSc = PosControls(parent=winAc, pos=(0,26), size=(25,10), title="Helper scroll")
animScroll = ttk.TTkPropertyAnimation(te.viewport(),'viewMoveTo')
animWinPos = ttk.TTkPropertyAnimation(None, winTe.move)
animHelpSc = ttk.TTkPropertyAnimation(saWp, 'viewMoveTo')
def _startAnimScroll():
animScroll.setDuration(pcScroll.dursb.value())
@ -126,11 +171,18 @@ def demoTextEditRO(root=None):
animWinPos.setEndValue( (pcWinPos.bxspb.value(), pcWinPos.byspb.value()))
animWinPos.setEasingCurve({t:v for (v,t) in easingList}.get(pcWinPos.ecb.currentText(),easingList[0][0]))
animWinPos.start()
def _startAnimHelpSc():
animHelpSc.setDuration(pcHelpSc.dursb.value())
animHelpSc.setStartValue((pcHelpSc.axspb.value(), pcHelpSc.ayspb.value()))
animHelpSc.setEndValue( (pcHelpSc.bxspb.value(), pcHelpSc.byspb.value()))
animHelpSc.setEasingCurve({t:v for (v,t) in easingList}.get(pcHelpSc.ecb.currentText(),easingList[0][0]))
animHelpSc.start()
animBtnScroll.clicked.connect(_startAnimScroll)
animBtnWinPos.clicked.connect(_startAnimWinPos)
animBoth.clicked.connect(_startAnimScroll)
animBoth.clicked.connect(_startAnimWinPos)
animHelper.clicked.connect(_startAnimHelpSc)
# Initialize the textedit with come text

Loading…
Cancel
Save