python - 是否可以在 Shady 中共享动画回调?
问题描述
我正在尝试使用 Shady 来呈现一系列图像帧。在过去,我通过为stimulus.page 属性分配一个动画回调来做到这一点。在 Shady 为每个监视器帧调用一次的回调中,我首先检查一个全局变量,该变量跟踪应该显示哪个刺激帧。如果是肯定的,我将刺激的可见性设置为 True 并返回帧号;否则我将其设置为 False 并返回 0。就像一个魅力。
现在我需要扩展它,因为我需要从多个序列中选择一个来显示。由于加载序列可能需要一些时间,因此我在程序开始时将它们全部加载,并将每个序列与一个 Stimulus 对象相关联。现在,这是我的问题。我是否必须为每个序列(其数量可变,并且可能很高)创建不同的动画回调函数。或者有没有更优雅的方法来调用单个动画回调(或类似的东西),并在那里我确定要显示哪个序列的哪个帧(再次,基于全局变量的当前值)?
解决方案
首先,我想确定“动画回调”和“动态属性值”在术语上的区别。Shady 文档和此答案并未将您使用的东西称为“动画回调”。但我认为,对您的问题的最佳答案可能是使用实际的动画回调。
动态属性值或“动态”:
World
和Stimulus
实例的某些属性可以分配给它们的可调用对象。如果是这样,它们会在每一帧上被调用。你stimulus.page
就是一个例子(即使page
它不是一个成熟的“托管属性”,即具有与另一个实例的相应属性共享内存的能力,它确实支持这种方式的“动态分配”)。如果您希望一次只更改几个刺激的几个方面,和/或您希望一个属性的更改完全独立于另一个属性的更改,则动态属性是很好的。t
s
(或实际上任何其他实例)具有原型blah(self, t)
,因为self
当您访问它时将被烘焙。该函数还必须返回一个值——应该分配给此帧上的属性的静态值。动画回调:每个
Stimulus
实例s
(以及另外的World
实例)都有一个“动画回调”,它占据属性槽s.Animate
,并且可以通过s.SetAnimationCallback
方法或其等效函数装饰器进行更改@s.AnimationCallback
。在每一帧上,每一个World
或Stimulus
实例都会检查它是否有一个.Animate
属性,如果有,就调用它。如果您希望对多个属性(例如s.visible
和s.page
)的更改相互协调,那么附加到的动画回调s
可能是最好的选择。与动态不同,动画回调可以是一个(未绑定的)方法,它接收对s
as的引用self
,因此 的属性self
可以用作“全局”(但特定于刺激实例)的暂存器。(实际上,对于动画回调,您可以选择使用类似方法的原型blah(self, t)
或单参数原型来定义它们blah(t)
,类似于动态。)动态是功能性的,动画回调是程序性的:动画回调的任何返回参数被忽略。
在任何一种情况下,确实(正如您所担心的那样)您附加回调的所有刺激都会调用它,并且所有刺激都会在每一帧上调用它们的动态,而不检查相同的可调用对象是否也被使用其他情况。如果您想确保代码不会被不必要地调用,您的选择包括:
如果一次只
Stimulus
应该看到一个:让每个都Stimulus
遵循自己的逻辑,在自己的动画回调和/或动态属性中(以您最有意义的为准)。但是当它应该在屏幕外时,不要只设置s.visible = False
: 相反,实际上让Stimulus
实例s.Leave()
出现在舞台上,并s.Enter()
在必要时再次设置。当你在舞台上时,即使你是隐形的,你的动画回调和动态也会在每一帧上被调用。当你不在舞台上时,他们不会被召唤。这在年底得到证明python -m Shady demo sharing
或者,您可以选择在一个地方执行大部分或全部动画逻辑。最好的地方可能是
World
动画回调,它肯定每帧只调用一次,因为只有一个World
. 对单个刺激的引用始终可以作为全局变量检索,或者通过self.stimuli
容器中的名称检索:import Shady cmdline = Shady.WorldConstructorCommandLine() cmdline.Help().Finalize() w = Shady.World( **cmdline.opts ) w.Stimulus( name='bill', x=-100, size=100, color=[1,0,0] ) w.Stimulus( name='ben', x=+100, size=100, color=[0,0,1] ) @w.AnimationCallback def Animate( self, t ): # top-down control of multiple stimuli: if self.framesCompleted % 2: # self.stimuli is a dict, with all the expected dict capabilities... self.stimuli['bill'].visible = True self.stimuli['ben'].visible = False else: # ...but it supports lazier syntax too: self.stimuli.bill.visible = False self.stimuli.ben.visible = True Shady.AutoFinish( w )
推荐阅读
- flutter - 行错误集
不能分配给列表类型“小部件” - oracle-adf - 我需要访问 ADF viewObject 的旧值
- reactjs - 防止事件传播给孩子
- android - 如果不使用 sqlite 中的 row_number() 函数,如何提供相同的函数?
- javascript - 如何用相应的图表显示 Highcharts 图例?
- node.js - 猫鼬子查询中子文档的计数值
- windows - 当 curl http://localhost:1337/parse 响应显示 curl: (7) 无法连接到 127.0.0.1 端口 50497: Connection refused
- javascript - NodeJs 如何处理微任务?
- spring-boot - 使用 groovy @AnnotationCollector 时获取 java.lang.IncompatibleClassChangeError
- python - 在 Win10 中为 Python 安装 Netfaces 时出错