1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-27 03:48:21 +01:00
Diya-API/Diya/DiyaNode.class.st
Dany LE f61e17de9c
Some checks reported errors
gitea-sync/Diya-API/pipeline/head Something is wrong with the build of this commit
rendering improvement
2022-08-16 00:59:35 +02:00

373 lines
7.1 KiB
Smalltalk

Class {
#name : #DiyaNode,
#superclass : #DiyaBaseObject,
#instVars : [
'translation',
'parent',
'children',
'scale',
'rotation',
'tf',
'shader',
'context',
'ehandlers',
'root',
'styleName',
'style',
'inlineStyle',
'id',
'visibility',
'pivot'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaNode class >> with: shader [
^self new shader: shader; yourself
]
{ #category : #styling }
DiyaNode >> ? styleAttr [
| value|
value := inlineStyle at: styleAttr ifAbsent:[nil].
value ifNotNil: [ ^value ].
styleName ifNotNil: [
style ifNil: [
style := DiyaUIThemesManager uniqueInstance currentTheme ? (self styleName).
].
value := style at: styleAttr ifAbsent:[nil].
value ifNotNil: [ ^value ].
].
"try to look at parent style"
parent ifNil:[self styleNotFound: styleAttr].
^ parent ? styleAttr
]
{ #category : #'add/remove' }
DiyaNode >> addNode: node [
^self addNode: node at: 0@0
]
{ #category : #'add/remove' }
DiyaNode >> addNode: node at: pos [
children ifNil: [ ^self ].
node parent: self.
children add: node.
node position: pos.
node root: self root.
node setDirtyAll.
^ node
]
{ #category : #accessing }
DiyaNode >> boundingBox [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> children [
^children
]
{ #category : #rendering }
DiyaNode >> draw [
self subclassResponsibility
]
{ #category : #requirements }
DiyaNode >> empty [
children ifNotNil: [
children do:[:c|
c root: nil.
c setClean.
c visibility: false.
]
].
children := OrderedCollection new.
]
{ #category : #accessing }
DiyaNode >> extent [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> id [
^ id
]
{ #category : #initialization }
DiyaNode >> initialize [
super initialize.
parent := nil.
shader := nil.
context := DiyaRenderer.
children := OrderedCollection new.
ehandlers := Dictionary new.
styleName := nil.
style := nil.
root := nil.
inlineStyle := Dictionary new.
visibility := true.
pivot := 0@0.
id := self className,'#',(Random new nextInt: 1e6) asString.
]
{ #category : #styling }
DiyaNode >> inlineStyle: name value: value [
inlineStyle at: name put: value
]
{ #category : #testing }
DiyaNode >> inner: aPoint [
^ self subclassResponsibility
]
{ #category : #testing }
DiyaNode >> isRoot [
^ false
]
{ #category : #convenience }
DiyaNode >> on: eventName do: aBlock [
eventName isArray ifFalse:[ ^ self register: aBlock to: eventName ].
eventName do:[:e| self register: aBlock to:e ].
]
{ #category : #accessing }
DiyaNode >> parent [
^ parent
]
{ #category : #accessing }
DiyaNode >> parent: anObject [
parent := anObject
]
{ #category : #accessing }
DiyaNode >> pivot [
^ pivot
]
{ #category : #accessing }
DiyaNode >> position [
^ translation
]
{ #category : #accessing }
DiyaNode >> position: anObject [
translation := anObject.
self updateTF.
]
{ #category : #processing }
DiyaNode >> process [
^self subclassResponsibility
]
{ #category : #convenience }
DiyaNode >> register: aBlock to: eventName [
|evtCode|
evtCode := SDL2Constants bindingOf: ('SDL_', eventName asUppercase).
evtCode ifNil: [ evtCode := eventName ].
ehandlers at: evtCode value put: aBlock.
]
{ #category : #'add/remove' }
DiyaNode >> remove [
parent ifNotNil: [ parent removeChild: self ]
]
{ #category : #'add/remove' }
DiyaNode >> removeChild: c [
c setClean.
c root: nil.
c visibility: false.
children ifNotNil: [ children remove: c ifAbsent:[ ]]
]
{ #category : #rendering }
DiyaNode >> render [
visibility ifFalse:[^self].
shader ifNotNil: [self setUpShader].
self draw.
children ifNil: [ ^self ].
root ifNil: [ ^self ].
root renderNext: children
]
{ #category : #'add/remove' }
DiyaNode >> replaceChild: aNode with: anotherNode [
|index|
children ifNil: [ ^ self ].
index := children indexOf: aNode.
index = 0 ifTrue:[^ self].
children at: index put: anotherNode.
anotherNode parent: self.
anotherNode root: self root.
anotherNode setDirtyAll.
aNode root: nil.
]
{ #category : #accessing }
DiyaNode >> root [
^ root
]
{ #category : #accessing }
DiyaNode >> root: anObject [
root = anObject ifTrue:[^self].
root := anObject.
children ifNotNil: [
children do:[:c | c root: root]
]
]
{ #category : #accessing }
DiyaNode >> rotation [
^ rotation
]
{ #category : #accessing }
DiyaNode >> rotation: anObject [
rotation := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> rotation: anObject pivot: p [
rotation := anObject.
pivot := p.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> scale [
^ scale
]
{ #category : #accessing }
DiyaNode >> scale: anObject [
scale := anObject.
self updateTF.
]
{ #category : #'changing state' }
DiyaNode >> setClean [
root ifNil: [ ^self ].
root cleanDirtyNode: self.
]
{ #category : #'changing state' }
DiyaNode >> setDirty [
root ifNil: [ ^self ].
self root enqueueDirtyNode: self.
]
{ #category : #'changing state' }
DiyaNode >> setDirtyAll [
self setDirty.
children ifNotNil: [
children do:[:c| c setDirtyAll] ]
]
{ #category : #rendering }
DiyaNode >> setUpShader [
|mem|
mem := self tf asGLBuffer.
shader use;
setUniform: #u_time value: DiyaSystemClock elapsedTime asFloat;
setUniform: #u_projection value: {GL_FALSE. context projection buffer};
setUniform: #u_resolution value: { context resolution x. context resolution y };
setUniform: #u_transform value: {GL_TRUE. mem}.
context mouse ifNotNil: [
"in shader, window origin is bottom left conor of the window
the mouse position should be transformed to this coodinate"
shader setUniform: #u_mouse value:
{ context mouse x. context mouse y }.
].
mem free.
]
{ #category : #accessing }
DiyaNode >> shader [
shader ifNil: [
parent ifNil: [ ^nil ].
^parent shader ].
^ shader
]
{ #category : #accessing }
DiyaNode >> shader: anObject [
shader := anObject
]
{ #category : #stepping }
DiyaNode >> step [
]
{ #category : #stepping }
DiyaNode >> stepDown [
self step.
children ifNotNil: [ children do:[:c | c stepDown ] ]
]
{ #category : #accessing }
DiyaNode >> styleName [
^ styleName
]
{ #category : #accessing }
DiyaNode >> styleName: anObject [
styleName := anObject.
style := nil.
self setDirty
]
{ #category : #'event handling' }
DiyaNode >> styleNotFound: styleAttr [
DiyaCoreAPIError signal: 'Query undefined style ', styleAttr, ' in', styleName.
]
{ #category : #accessing }
DiyaNode >> tf [
^ tf
]
{ #category : #'event handling' }
DiyaNode >> trigger: evt [
evt enable ifFalse:[^self].
ehandlers at: evt mapped type ifPresent:[:handler|
evt target: self.
handler value: evt].
children ifNil: [^self].
evt enable ifTrue: [
children select: [:node | evt mapped triggableOn: node ] thenDo:[:node| node trigger: evt]
].
]
{ #category : #processing }
DiyaNode >> updateTF [
self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> visibility [
^ visibility
]
{ #category : #accessing }
DiyaNode >> visibility: anObject [
visibility := anObject.
children ifNotNil: [
children do:[:c| c visibility: anObject ] ]
]