animations.py (6107B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\graphs\animations.py 2 import random 3 import trinity 4 import uthread2 5 from carbonui.graphs import axis 6 from carbonui.uicore import uicore 7 8 class AnimationType(object): 9 FADE = 1 10 GROW = 2 11 12 13 class AnimationDynamics(object): 14 SIMULTANEOUS = 0 15 ALONG_AXIS = 1 16 OPPOSITE_AXIS = 2 17 RANDOM = 3 18 19 20 def CreateAnimation(uiObject, categoryAxis, valueAxis, orientation, animationType, animationDynamics, duration, vertexPerDataPoint): 21 if animationType == AnimationType.FADE: 22 return CreateOpacityAnimation(uiObject, categoryAxis, orientation, animationDynamics, duration, vertexPerDataPoint) 23 if animationType == AnimationType.GROW: 24 return CreateVertexAnimation(uiObject, categoryAxis, valueAxis, orientation, animationDynamics, duration, vertexPerDataPoint) 25 raise ValueError('unsupported animation type') 26 27 28 def CreateVertexAnimation(uiObject, categoryAxis, valueAxis, orientation, animationDynamics, duration, vertexPerDataPoint): 29 startVertex = max(0, int(categoryAxis.GetVisibleRange()[0] - 1)) * vertexPerDataPoint 30 endVertex = int(min(categoryAxis.GetVisibleRange()[1] + 1, len(categoryAxis.GetDataPoints()))) * vertexPerDataPoint 31 if startVertex >= endVertex: 32 return None 33 axisZero = valueAxis.GetViewportRange()[0] 34 source = (axisZero,) * (endVertex - startVertex) 35 index = 0 if orientation == axis.AxisOrientation.HORIZONTAL else 1 36 dest = [ uiObject.renderObject.vertices[i].position[index] for i in xrange(startVertex, endVertex) ] 37 offsets = GetAnimationOffsets(animationDynamics, endVertex - startVertex, vertexPerDataPoint=vertexPerDataPoint) 38 return VertexAnimation('position', duration, offsets, source, dest, uiObject.renderObject, startVertex, index) 39 40 41 def CreateOpacityAnimation(uiObject, categoryAxis, orientation, animationDynamics, duration, vertexPerDataPoint): 42 if animationDynamics == AnimationDynamics.SIMULTANEOUS: 43 uicore.animations.MorphScalar(uiObject, 'opacity', startVal=0.0, endVal=1.0, duration=duration) 44 return None 45 startVertex = max(0, int(categoryAxis.GetVisibleRange()[0] - 1)) * vertexPerDataPoint 46 endVertex = int(min(categoryAxis.GetVisibleRange()[1] + 1, len(categoryAxis.GetDataPoints()))) * vertexPerDataPoint 47 if startVertex >= endVertex: 48 return None 49 source = (0,) * (endVertex - startVertex) 50 index = 0 if orientation == axis.AxisOrientation.HORIZONTAL else 1 51 dest = (1,) * (endVertex - startVertex) 52 offsets = GetAnimationOffsets(animationDynamics, endVertex - startVertex, vertexPerDataPoint=vertexPerDataPoint) 53 return VertexAnimation('color', duration, offsets, source, dest, uiObject.renderObject, startVertex, index) 54 55 56 class VertexAnimation(object): 57 58 def __init__(self, attribute, duration, timeOffsets, source, destination, polygon, vertexOffset, vertexAttribute): 59 self._attibute = attribute 60 self._source = source 61 self._timeOffsets = timeOffsets 62 self._destination = destination 63 self._polygon = polygon 64 self._offset = vertexOffset 65 self._startTime = trinity.device.animationTime 66 self._endTime = self._startTime + max(self._timeOffsets) + duration 67 self._duration = duration 68 self._vertexAttribute = vertexAttribute 69 self._cancelled = False 70 uthread2.StartTasklet(self._Thread) 71 72 def Cancel(self, applyLastFrame = True): 73 self._cancelled = True 74 if applyLastFrame: 75 self._Apply((self._endTime - self._startTime) / self._duration) 76 77 def _Apply(self, time): 78 if self._attibute == 'position': 79 self._ApplyPositions(time) 80 else: 81 self._ApplyColors(time) 82 83 def _ApplyPositions(self, time): 84 vertices = self._polygon.vertices 85 for i, (offset, source, dest) in enumerate(zip(self._timeOffsets, self._source, self._destination)): 86 t = time - offset 87 t = min(max(t, 0), 1) 88 t = t ** 0.3 89 v = source * (1 - t) + dest * t 90 vtx = vertices[i + self._offset] 91 if self._vertexAttribute == 0: 92 vtx.position = (v, vtx.position[1]) 93 else: 94 vtx.position = (vtx.position[0], v) 95 96 self._polygon.SetDirty() 97 98 def _ApplyColors(self, time): 99 vertices = self._polygon.vertices 100 for i, (offset, source, dest) in enumerate(zip(self._timeOffsets, self._source, self._destination)): 101 t = time - offset 102 t = min(max(t, 0), 1) 103 t = t ** 0.3 104 v = source * (1 - t) + dest * t 105 vtx = vertices[i + self._offset] 106 vtx.color = (vtx.color[0], 107 vtx.color[1], 108 vtx.color[2], 109 v) 110 111 self._polygon.SetDirty() 112 113 def _Thread(self): 114 while not self._cancelled: 115 now = trinity.device.animationTime 116 self._Apply((now - self._startTime) / self._duration) 117 if now > self._endTime: 118 break 119 uthread2.Yield() 120 121 122 def GetAnimationOffsets(animationDynamics, vertexCount, vertexPerDataPoint = 1): 123 if animationDynamics == AnimationDynamics.SIMULTANEOUS: 124 offsets = (0,) * vertexCount 125 elif animationDynamics == AnimationDynamics.ALONG_AXIS: 126 relRange = vertexPerDataPoint / float(vertexCount) 127 offsets = [ x / vertexPerDataPoint * relRange for x in xrange(vertexCount) ] 128 elif animationDynamics == AnimationDynamics.OPPOSITE_AXIS: 129 relRange = vertexPerDataPoint / float(vertexCount) 130 offsets = [ 1 - x / vertexPerDataPoint * relRange for x in xrange(vertexCount) ] 131 elif animationDynamics == AnimationDynamics.RANDOM: 132 if vertexPerDataPoint == 1: 133 offsets = [ random.random() for _ in xrange(vertexCount) ] 134 else: 135 offsets = [] 136 for each in xrange(vertexCount): 137 offsets.extend((random.random(),) * vertexPerDataPoint) 138 139 else: 140 raise ValueError('unsupported animation dynamics') 141 return offsets