Maybe this could become some kind of pillar file...
But things are changing a lot these days with SDL2 etc.
It is converging
- SDL2 stabilisation
- Sparta integrated into Bloc
- TxText optimisation
- Bloc stabilization
Thales guys are starting to use it.
Stef
Any roadmap of these somewhere?
Phil
On Sat, Oct 8, 2016 at 7:03 PM, stepharo <steph...@free.fr
<mailto:steph...@free.fr>> wrote:
Thibault
you should talk also with Glenn and Alain to get feedback. They
will visit us in Nov.
Stef
Le 7/10/16 à 15:14, Thibault Raffaillac a écrit :
Thanks for these mails, that's actually very helpful!
I am working on a shorter syntax for animations at the moment
(than GLMAnimation, Viva, Bloc-Animation), and could not find
a proper equivalent to requestAnimationFrame (i.e. that would
be independent of any UI yet in sync with display, and as
simple as possible).
My solution was to repeatedly register to deferredUIMessages,
implementing an intermediate block to add a timestamp like
requestAnimationFrame (works wonders
http://smalltalkhub.com/#!/~ThibaultRaffaillac/Animation
<http://smalltalkhub.com/#%21/%7EThibaultRaffaillac/Animation>)
Cheers,
Thibault
ps: I'll ask Guille asap for the state of ReactiveExtensions
(lacks comments)
Also, check
MorphicUIManager>>#spawnNewProcess
UIProcess := [
[World doOneCycle. Processor yield. false] whileFalse: [].
] newProcess priority: Processor userSchedulingPriority.
UIProcess name: 'Morphic UI Process'.
UIProcess resume
digging into doOneCycle, you'll find:
#doOneCycleFor: aWorld
"Do one cycle of the interaction loop. This method is
called *repeatedly
*when
the world is running. This is a moderately private method;
a better
alternative is usually either to wait for events or to
check the state of
things from #step methods."
self interCyclePause: MinCycleLapse.
self doOneCycleNowFor: aWorld.
The interCyclePause is what make the UI timing alignment
proper (notice
serverMode) [and some Squeak remnant mention]:
interCyclePause: milliSecs
"delay enough that the previous cycle plus the amount of
delay will equal
milliSecs. If the cycle is already expensive, then no
delay occurs.
However, if the system is idly waiting for interaction
from the user, the
method will delay for a proportionally long time and cause
the overall CPU
usage of *Squeak* to be low.
If self serverMode returns true then, always do a complete
delay of 50ms,
independant of my argument. This prevents the freezing
problem described in
Mantis #6581"
| wait wait2 |
"*a very long assignment*"
wait := self serverMode
ifTrue: [ 50 ]
ifFalse:
[ wait2 := (lastCycleTime notNil and: [CanSurrenderToOS ~~
false])
ifFalse: [ 0 ]
ifTrue: [ lastCycleTime + milliSecs - Time
millisecondClockValue ].
self flag: 'Issue 14754 - wait2>millisecs is only
True for clock
rollover. Remove it once DelayScheduler based on
microsecondClock - Ben
Coman 19.01.2015'. "*<---- maybe we want this #flag: not
to be called all
the time* "
wait2 > milliSecs
ifTrue: [ 0 ]
ifFalse: [ wait2 ].
].
wait > 0 ifTrue: [ (Delay forMilliseconds: wait) wait ].
"<------- wait
is not #>>wait"
lastCycleTime := Time millisecondClockValue.
CanSurrenderToOS := true.
Now, yeah, how do get stuff to be painted on the screen?
Like this:
displayWorld: aWorld submorphs: submorphs
"Update this world's display."
| deferredUpdateMode handsToDraw allDamage |
submorphs do: [:m | m fullBounds]. "force re-layout if
needed"
self checkIfUpdateNeeded ifFalse: [^ self]. "display is
already up-to-date"
deferredUpdateMode := self doDeferredUpdatingFor: aWorld.
deferredUpdateMode ifFalse: [self assuredCanvas].
canvas roundCornersOf: aWorld during:[ | worldDamageRects
handDamageRects |
worldDamageRects := self drawWorld: aWorld submorphs:
submorphs
invalidAreasOn: canvas. "repair world's damage on canvas"
"self handsDo:[:h| h noticeDamageRects: worldDamageRects]."
handsToDraw := self selectHandsToDrawForDamage:
worldDamageRects.
handDamageRects := handsToDraw collect: [:h | h
savePatchFrom: canvas].
allDamage := worldDamageRects, handDamageRects.
handsToDraw reverseDo: [:h | canvas fullDrawMorph: h].
"draw hands onto
world canvas"
].
"*make this true to flash damaged areas for testing*"
self class debugShowDamage ifTrue: [aWorld flashRects:
allDamage color:
Color black].
canvas finish.
"quickly copy altered rects of canvas to Display:"
deferredUpdateMode
ifTrue: [self forceDamageToScreen: allDamage]
ifFalse: [canvas showAt: aWorld viewBox origin
invalidRects: allDamage].
handsToDraw do: [:h | h restoreSavedPatchOn: canvas].
"restore world
canvas under hands"
Display deferUpdates: false; forceDisplayUpdate.
The VM will take care of throwing the bits to the display
in various ways.
Interesting to look how it is done for Windows, OSX, and
Linux.
So you have about a full view now.
Timing wise, there is also some interaction with the VM
occuring elsewhere.
Pharo is still polling deep inside. epoll etc isn't there
yet, hence the
little idle CPU usage when doing nothing.
Good luck doing this UI trip with other platforms, not to
mention change or
instrument it the way you like.
Pharo is really cool for this as it helps in learning
about a lot of things.
Want to do sockets?
Do the high level stuff in Pharo and dig in the VM to see
how it is done
down under for a set of platforms.
Enjoy.
Phil