1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-27 03:48:21 +01:00

API improvements:

- fix: TF update bug on scale
- fix: Use local coordiate for Polygon points
- Add timer node for basic animation
- Dirty processing nodes are monitored by rootnode
- refactory code
This commit is contained in:
Dany LE 2022-08-12 22:19:54 +02:00
parent 2ee103191c
commit 2e4c73f8cf
14 changed files with 267 additions and 67 deletions

View File

@ -77,11 +77,22 @@ Diya2DNode >> recFromBuffer [
Diya2DNode >> updateTF [ Diya2DNode >> updateTF [
tf := MatrixTransform2x3 identity. tf := MatrixTransform2x3 identity.
"translation" "translation"
tf setOffset: translation. tf setOffset: translation + pivot.
"rotation" "rotation"
rotation = 0 ifFalse:[tf setAngle: rotation ]. rotation = 0 ifFalse:[tf setAngle: rotation ].
"scale" "translate back to pivot"
tf setScale: scale. pivot isZero ifFalse:[
tf := tf composedWithLocal:
(MatrixTransform2x3 identity
setOffset: pivot negated;
yourself)
].
scale isZero ifFalse: [
tf := tf composedWithLocal:
(MatrixTransform2x3 identity
setScale: scale;
yourself)
].
self parent ifNil: [ ^self ]. self parent ifNil: [ ^self ].
self parent isRoot ifFalse: [tf := self parent tf composedWithLocal: tf ]. self parent isRoot ifFalse: [tf := self parent tf composedWithLocal: tf ].
children ifNotNil: [children do:[:c| c updateTF ]]. children ifNotNil: [children do:[:c| c updateTF ]].

View File

@ -75,7 +75,6 @@ Diya2DPrimShape >> extent [
Diya2DPrimShape >> initialize [ Diya2DPrimShape >> initialize [
super initialize. super initialize.
texture := nil. texture := nil.
children := nil.
type := GL_TRIANGLES. type := GL_TRIANGLES.
bbox := Rectangle origin: 0@0 corner: 0@0. bbox := Rectangle origin: 0@0 corner: 0@0.
] ]

View File

@ -47,9 +47,11 @@ DiyaApplicationLauncher >> launch: app [
root empty. root empty.
]. ].
currapp := app uniqueInstance. currapp := app uniqueInstance.
self appNode addNode: currapp root. currapp setup.
currapp root forceReload.
Transcript show: 'APPLICATION INIT'; cr.
self context assets: currapp am. self context assets: currapp am.
currapp setup self appNode addNode: currapp root.
] ]
{ #category : #initialization } { #category : #initialization }
@ -64,7 +66,7 @@ DiyaApplicationLauncher >> main [
]. ].
currapp ifNotNil: [currapp main.]. currapp ifNotNil: [currapp main.].
"root render." "root render."
[ root stepDown ] fork. root stepDown.
self process. self process.
root render. root render.
] ]
@ -73,11 +75,12 @@ DiyaApplicationLauncher >> main [
DiyaApplicationLauncher >> process [ DiyaApplicationLauncher >> process [
|Q node maxProcessingTime| |Q node maxProcessingTime|
maxProcessingTime := 1000 / DiyaBoot maxFPS - 100. maxProcessingTime := 1000 / DiyaBoot maxFPS - 100.
Q := DiyaRendererContext uniqueInstance processQueue. Q := root processingQueue select:[:e| e visibility].
Q ifEmpty:[^ self]. Q ifEmpty:[^ self].
[ [
node := Q removeFirst. node := Q removeFirst.
node process. node process.
root cleanDirtyNode: node.
Q isNotEmpty and: DiyaClock uniqueInstance lapDelta asMilliSeconds < maxProcessingTime Q isNotEmpty and: DiyaClock uniqueInstance lapDelta asMilliSeconds < maxProcessingTime
] whileTrue ] whileTrue
@ -102,7 +105,7 @@ DiyaApplicationLauncher >> setup [
#bgColor -> Color orange. #bgColor -> Color orange.
#border -> 3 #border -> 3
}. }.
root addNode: (Diya2DNode new) at: 0@0. root addNode: (DiyaCompositeNode new) at: 0@0.
txtFPS := root addNode:(DiyaText data: '') at: ( self context resolution x - 80)@(self context resolution y - 40). txtFPS := root addNode:(DiyaText data: '') at: ( self context resolution x - 80)@(self context resolution y - 40).
txtFPS extent: 80@40. txtFPS extent: 80@40.
txtFPS styleName: #fps_text. txtFPS styleName: #fps_text.

View File

@ -7,6 +7,7 @@ Class {
{ #category : #initialization } { #category : #initialization }
DiyaBaseApplication >> initialize [ DiyaBaseApplication >> initialize [
super initialize. super initialize.
root := Diya2DNode new. root := DiyaCompositeNode new.
root styleName: #global.
am := AssetManager new. am := AssetManager new.
] ]

View File

@ -0,0 +1,22 @@
Class {
#name : #DiyaCompositeNode,
#superclass : #Diya2DNode,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaCompositeNode >> process [
]
{ #category : #accessing }
DiyaCompositeNode >> setClean [
]
{ #category : #accessing }
DiyaCompositeNode >> setDirty [
]

View File

@ -92,6 +92,6 @@ DiyaEllipse >> setUpShader [
self shader self shader
setUniform: #u_border value: (self ? #border); setUniform: #u_border value: (self ? #border);
setUniform: #u_border_color value: ( self ? #borderColor) asGL4FArray; setUniform: #u_border_color value: ( self ? #borderColor) asGL4FArray;
setUniform: #u_rx value: rx; setUniform: #u_rx value: (rx * (scale x)) ;
setUniform: #u_ry value: ry. setUniform: #u_ry value: (ry * (scale y)) .
] ]

View File

@ -89,7 +89,7 @@ DiyaExampleApp >> setup [
node1 rotation: 45. node1 rotation: 45.
node1 scale: 2.0@2.0. node1 scale: 2.0@2.0.
node1 on: #(mousebuttondown fingerdown) do:[:e| node1 on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'Mouse ', (node1 local: e mapped worldPosition) asIntegerPoint asString]. label txt: 'RECT ', (node1 local: e mapped worldPosition) asIntegerPoint asString].
img := root addNode: (DiyaImageView from:'mrsang.png') at: 10 @ 400. img := root addNode: (DiyaImageView from:'mrsang.png') at: 10 @ 400.
img styleName: #image_view. img styleName: #image_view.
@ -117,15 +117,17 @@ DiyaExampleApp >> setup [
node := root addNode: (DiyaLine from: 10@10 to: 200@200). node := root addNode: (DiyaLine from: 10@10 to: 200@200).
node styleName: #line_view. node styleName: #line_view.
ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 100@300. ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 120@300.
ell rotation: 30. ell scale: 1.2 @ 1.2.
ell styleName: #ell_view. ell styleName: #ell_view.
"node rotation: Float pi / 2.0."
ell textureNamed:'mrsang.png'. ell textureNamed:'mrsang.png'.
ell addNode: (DiyaTimerNode timeout: 1000 / 6 do:[:n |
n parent rotation: n parent rotation + 10.
] ).
ell on: #(mousebuttondown fingerdown) do:[:e| ell on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'Ellipse clicked', (ell local:e mapped worldPosition) asIntegerPoint asString]. label txt: 'Ellipse clicked', (ell local:e mapped worldPosition) asIntegerPoint asString].
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}). node := root addNode: (DiyaConvexPolygon points:{0@40. 150@190. 200@20. 100@0}) at: 250@60.
node textureNamed: 'mrsang.png'. node textureNamed: 'mrsang.png'.
node styleName: #poly_view. node styleName: #poly_view.
@ -133,8 +135,13 @@ DiyaExampleApp >> setup [
icon styleName: #text_icon_2. icon styleName: #text_icon_2.
button := root addNode: (DiyaButton text: 'Click me !') at: 240@460. button := root addNode: (DiyaButton text: 'Click me !') at: 240@460.
icon := DiyaFontIcon data: 16rF130.
"icon := DiyaImageIcon from: 'mrsang.png'."
icon addNode:(DiyaTimerNode timeout: 1000 / 12 do:[:n |
n parent rotation: n parent rotation + 10 pivot: n parent extent / 2.
] ).
button extent: 200@40. button extent: 200@40.
button icon:16rF185"'mrsang.png'". button icon: icon "'mrsang.png'".
"button rotation: Float pi / 2.0." "button rotation: Float pi / 2.0."
button styleName: #button_view. button styleName: #button_view.
Transcript show: 'Application setup';cr. Transcript show: 'Application setup';cr.

View File

@ -32,7 +32,7 @@ DiyaLabel >> icon: anObject [
anObject isString ifTrue: [ anObject isString ifTrue: [
icon := self addNode: (DiyaImageIcon from: anObject). icon := self addNode: (DiyaImageIcon from: anObject).
]. ].
icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification']. icon ifNil: [ icon := self addNode: anObject ].
self setDirty self setDirty
] ]

View File

@ -0,0 +1,40 @@
Class {
#name : #DiyaMetaNode,
#superclass : #DiyaNode,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaMetaNode >> addNode: node at: pos [
self shouldNotBeCalled
]
{ #category : #accessing }
DiyaMetaNode >> boundingBox [
^ 0@0
]
{ #category : #rendering }
DiyaMetaNode >> draw [
]
{ #category : #accessing }
DiyaMetaNode >> extent [
^ 0@0
]
{ #category : #testing }
DiyaMetaNode >> inner: aPoint [
^ false
]
{ #category : #processing }
DiyaMetaNode >> process [
]
{ #category : #processing }
DiyaMetaNode >> updateTF [
]

View File

@ -14,7 +14,9 @@ Class {
'root', 'root',
'styleName', 'styleName',
'style', 'style',
'id' 'id',
'visibility',
'pivot'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -53,25 +55,13 @@ DiyaNode >> addNode: node [
DiyaNode >> addNode: node at: pos [ DiyaNode >> addNode: node at: pos [
children ifNil: [ ^self ]. children ifNil: [ ^self ].
node parent: self. node parent: self.
node position: pos.
children add: node. children add: node.
node position: pos.
node root: self root. node root: self root.
node setDirtyAll.
^ node ^ node
] ]
{ #category : #accessing }
DiyaNode >> allChildren [
|nodes|
nodes := OrderedCollection new.
children ifNil: [ ^ nodes ].
children do:[:c|
nodes add: c.
c allChildren do:[:e| nodes add:e].
].
^nodes
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> boundingBox [ DiyaNode >> boundingBox [
^ self subclassResponsibility ^ self subclassResponsibility
@ -82,7 +72,7 @@ DiyaNode >> children [
^children ^children
] ]
{ #category : #accessing } { #category : #rendering }
DiyaNode >> draw [ DiyaNode >> draw [
self subclassResponsibility self subclassResponsibility
] ]
@ -97,6 +87,15 @@ DiyaNode >> extent [
^ self subclassResponsibility ^ self subclassResponsibility
] ]
{ #category : #processing }
DiyaNode >> forceReload [
self process.
children ifNotNil: [
children do:[:c|
c forceReload
]]
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> id [ DiyaNode >> id [
^ id ^ id
@ -113,10 +112,12 @@ DiyaNode >> initialize [
styleName := nil. styleName := nil.
style := nil. style := nil.
root := nil. root := nil.
visibility := true.
pivot := 0@0.
id := self className,'#',(Random new nextInt: 1e6) asString. id := self className,'#',(Random new nextInt: 1e6) asString.
] ]
{ #category : #accessing } { #category : #testing }
DiyaNode >> inner: aPoint [ DiyaNode >> inner: aPoint [
^ self subclassResponsibility ^ self subclassResponsibility
] ]
@ -143,6 +144,11 @@ DiyaNode >> parent: anObject [
parent := anObject parent := anObject
] ]
{ #category : #accessing }
DiyaNode >> pivot [
^ pivot
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> position [ DiyaNode >> position [
^ translation ^ translation
@ -154,7 +160,7 @@ DiyaNode >> position: anObject [
self updateTF. self updateTF.
] ]
{ #category : #accessing } { #category : #processing }
DiyaNode >> process [ DiyaNode >> process [
^self subclassResponsibility ^self subclassResponsibility
] ]
@ -163,13 +169,26 @@ DiyaNode >> process [
DiyaNode >> register: aBlock to: eventName [ DiyaNode >> register: aBlock to: eventName [
|evtCode| |evtCode|
evtCode := SDL2Constants bindingOf: ('SDL_', eventName asUppercase). evtCode := SDL2Constants bindingOf: ('SDL_', eventName asUppercase).
evtCode ifNil: [ ^DiyaCoreAPIError signal: 'Unknow event ', eventName ]. evtCode ifNil: [ evtCode := eventName ].
ehandlers at: evtCode value put: aBlock. ehandlers at: evtCode value put: aBlock.
] ]
{ #category : #accessing } { #category : #removing }
DiyaNode >> remove [
self setClean.
root := nil.
parent ifNotNil: [ parent removeChild: self ]
]
{ #category : #removing }
DiyaNode >> removeChild: c [
children ifNotNil: [ children remove: c ifAbsent:[ ]]
]
{ #category : #rendering }
DiyaNode >> render [ DiyaNode >> render [
visibility ifFalse:[^self].
shader ifNotNil: [self setUpShader]. shader ifNotNil: [self setUpShader].
self draw. self draw.
children ifNil: [ ^self ]. children ifNil: [ ^self ].
@ -201,6 +220,13 @@ DiyaNode >> rotation: anObject [
self updateTF. self updateTF.
] ]
{ #category : #accessing }
DiyaNode >> rotation: anObject pivot: p [
rotation := anObject.
pivot := p.
self updateTF.
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> scale [ DiyaNode >> scale [
^ scale ^ scale
@ -212,21 +238,26 @@ DiyaNode >> scale: anObject [
self updateTF. self updateTF.
] ]
{ #category : #initialization } { #category : #'changing state' }
DiyaNode >> setClean [ DiyaNode >> setClean [
|Q| root ifNil: [ ^self ].
Q := DiyaRendererContext uniqueInstance processQueue. root cleanDirtyNode: self.
Q remove: self ifAbsent: [ ]
] ]
{ #category : #initialization } { #category : #'changing state' }
DiyaNode >> setDirty [ DiyaNode >> setDirty [
|Q| root ifNil: [ ^self ].
Q := DiyaRendererContext uniqueInstance processQueue. self root enqueueDirtyNode: self.
(Q includes: self ) ifFalse:[ Q add: self].
] ]
{ #category : #accessing } { #category : #'changing state' }
DiyaNode >> setDirtyAll [
self setDirty.
children ifNotNil: [
children do:[:c| c setDirtyAll] ]
]
{ #category : #rendering }
DiyaNode >> setUpShader [ DiyaNode >> setUpShader [
|mem| |mem|
mem := self tf asGLBuffer. mem := self tf asGLBuffer.
@ -264,7 +295,7 @@ DiyaNode >> step [
{ #category : #stepping } { #category : #stepping }
DiyaNode >> stepDown [ DiyaNode >> stepDown [
self step self step.
children ifNotNil: [ children do:[:c | c stepDown ] ] children ifNotNil: [ children do:[:c | c stepDown ] ]
] ]
@ -303,7 +334,17 @@ DiyaNode >> trigger: evt [
]. ].
] ]
{ #category : #accessing } { #category : #processing }
DiyaNode >> updateTF [ DiyaNode >> updateTF [
self subclassResponsibility self subclassResponsibility
] ]
{ #category : #accessing }
DiyaNode >> visibility [
^ visibility
]
{ #category : #accessing }
DiyaNode >> visibility: anObject [
visibility := anObject
]

View File

@ -42,9 +42,6 @@ DiyaPolygon >> points: anObject [
{ #category : #accessing } { #category : #accessing }
DiyaPolygon >> process [ DiyaPolygon >> process [
bbox := self recFromPoints.
translation = bbox origin ifFalse:[ self position: bbox origin].
points := points collect:[:e | e - bbox origin].
bbox := self recFromPoints. bbox := self recFromPoints.
self calculateVertices. self calculateVertices.
^true ^true

View File

@ -9,8 +9,7 @@ Class {
'texture0', 'texture0',
'projection', 'projection',
'assets', 'assets',
'window', 'window'
'rqueue'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -67,7 +66,6 @@ DiyaRendererContext >> initialize [
vbo bind: GL_ARRAY_BUFFER. vbo bind: GL_ARRAY_BUFFER.
projection := Array2D identity: 4. projection := Array2D identity: 4.
assets := AssetManager new. assets := AssetManager new.
rqueue := OrderedCollection new.
] ]
{ #category : #accessing } { #category : #accessing }
@ -80,11 +78,6 @@ DiyaRendererContext >> mouse: anObject [
mouse := anObject mouse := anObject
] ]
{ #category : #accessing }
DiyaRendererContext >> processQueue [
^ rqueue
]
{ #category : #accessing } { #category : #accessing }
DiyaRendererContext >> projection [ DiyaRendererContext >> projection [
^ projection ^ projection

View File

@ -12,16 +12,16 @@ DiyaRootNode >> Q [
^ Q ^ Q
] ]
{ #category : #accessing }
DiyaRootNode >> Q: v [
Q := v
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> boundingBox [ DiyaRootNode >> boundingBox [
^ Rectangle origin: 0@0 corner: context resolution ^ Rectangle origin: 0@0 corner: context resolution
] ]
{ #category : #'add/remove' }
DiyaRootNode >> cleanDirtyNode: aNode [
Q remove: aNode ifAbsent:[]
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> draw [ DiyaRootNode >> draw [
|c| |c|
@ -31,6 +31,11 @@ DiyaRootNode >> draw [
context vbo bind: GL_ARRAY_BUFFER. context vbo bind: GL_ARRAY_BUFFER.
] ]
{ #category : #'add/remove' }
DiyaRootNode >> enqueueDirtyNode: aNode [
(Q includes: aNode ) ifFalse:[ Q add: aNode].
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> extent [ DiyaRootNode >> extent [
^ context resolution ^ context resolution
@ -58,7 +63,7 @@ DiyaRootNode >> isRoot [
{ #category : #initialization } { #category : #initialization }
DiyaRootNode >> process [ DiyaRootNode >> process [
^true
] ]
{ #category : #accessing } { #category : #accessing }
@ -66,6 +71,19 @@ DiyaRootNode >> processingQueue [
^ Q ^ Q
] ]
{ #category : #initialization }
DiyaRootNode >> setClean [
]
{ #category : #initialization }
DiyaRootNode >> setDirty [
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> updateTF [ DiyaRootNode >> updateTF [
"donothing" "donothing"

View File

@ -0,0 +1,68 @@
Class {
#name : #DiyaTimerNode,
#superclass : #DiyaMetaNode,
#instVars : [
'timeout',
'elapsedTime',
'handlers'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaTimerNode class >> timeout: ms [
^ self new timeout: ms; yourself
]
{ #category : #accessing }
DiyaTimerNode class >> timeout: ms do: aBlock [
^ (self timeout: ms) onTimeout: aBlock;yourself
]
{ #category : #accessing }
DiyaTimerNode class >> timeout: ms doOnce: aBlock [
^ (self timeout: ms) onceTimeout: aBlock;yourself
]
{ #category : #accessing }
DiyaTimerNode >> delta [
^ DiyaClock uniqueInstance delta asMilliSeconds
]
{ #category : #accessing }
DiyaTimerNode >> initialize [
super initialize.
elapsedTime := 0.
handlers := OrderedCollection new.
]
{ #category : #'as yet unclassified' }
DiyaTimerNode >> onTimeout: aBlock [
handlers add: aBlock
]
{ #category : #'as yet unclassified' }
DiyaTimerNode >> onceTimeout: aBlock [
|newBlock|
handlers := OrderedCollection new.
newBlock := [ :node | aBlock value: node. self remove ].
handlers add: newBlock
]
{ #category : #stepping }
DiyaTimerNode >> step [
elapsedTime := elapsedTime + self delta.
elapsedTime >= timeout ifFalse:[^ self].
handlers do:[:e| e value: self ].
elapsedTime := 0
]
{ #category : #accessing }
DiyaTimerNode >> timeout [
^ timeout
]
{ #category : #accessing }
DiyaTimerNode >> timeout: anObject [
timeout := anObject
]