1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-26 11:28:22 +01:00

refactory code, support inline style, improve text rendering

This commit is contained in:
Dany LE 2022-08-15 12:28:09 +02:00
parent 0b7396242a
commit 3c00e1d181
10 changed files with 265 additions and 158 deletions

View File

@ -4,7 +4,6 @@ Class {
#instVars : [
'currapp',
'txtFPS',
'event',
'running'
],
#category : #'Diya-Applications'
@ -12,17 +11,17 @@ Class {
{ #category : #initialization }
DiyaApplicationLauncher >> appNode [
^root children first
^node children first
]
{ #category : #initialization }
DiyaApplicationLauncher >> bindGlobalEvent [
|pointer |
pointer := root addNode: (DiyaCircle r: 10) at: 200@200.
pointer := node addNode: (DiyaCircle r: 10) at: 200@200.
pointer styleName: #pointer.
root on: #keydown do:[:e| self stdlog: 'keydown...'. running := false.].
root on: #quit do: [:e| running := false].
root on: #(fingerdown fingermotion mousemotion) do:[:e|
node on: #keydown do:[:e| self stdlog: 'keydown...'. running := false.].
node on: #quit do: [:e| running := false].
node on: #(fingerdown fingermotion mousemotion) do:[:e|
pointer position: e mapped worldPosition.
DiyaRenderer mouse: (e mapped x) @ (e mapped y).
].
@ -33,10 +32,15 @@ DiyaApplicationLauncher >> defaultApplication [
^DiyaExampleApp
]
{ #category : #initialization }
DiyaApplicationLauncher >> initLoader [
]
{ #category : #initialization }
DiyaApplicationLauncher >> initialize [
super initialize.
root := DiyaRenderer root.
node := DiyaRenderer root.
currapp := nil.
]
@ -44,42 +48,22 @@ DiyaApplicationLauncher >> initialize [
DiyaApplicationLauncher >> launch: app [
currapp ifNotNil: [
currapp quit.
root empty.
node empty.
].
currapp := app uniqueInstance.
self context assets: currapp am.
[
self stdlog: 'Loading application'.
currapp root visibility: false.
currapp setup.
currapp root forceReload.
self appNode addNode: currapp root.
currapp root visibility: true.
self appNode addNode: currapp loader node.
currapp onloaded:[
self appNode empty.
currapp node visibility: false.
self appNode addNode: currapp node.
currapp node visibility: true.
self stdlog: 'Application LOADED'.
] fork.
]
{ #category : #initialization }
DiyaApplicationLauncher >> main [
| fps delta|
delta := DiyaSystemClock delta.
fps := DiyaSystemSettings maxFPS.
delta = 0 ifFalse:[ fps := (1000/ delta) asInteger].
txtFPS data: ('FPS:', fps asString).
[(SDL2 pollEvent: event) > 0] whileTrue: [
root trigger: (DiyaEvent from: event mapped).
].
currapp ifNotNil: [currapp main.].
]
{ #category : #accessing }
DiyaApplicationLauncher >> running [
^ running
]
{ #category : #initialization }
DiyaApplicationLauncher >> setup [
event := SDL_Event new.
DiyaApplicationLauncher >> onloaded: aBlock [
DiyaUIThemesManager uniqueInstance currentTheme
define: #fps_text styles: {
#color -> Color red.
@ -91,11 +75,27 @@ DiyaApplicationLauncher >> setup [
#bgColor -> Color orange.
#border -> 3
}.
root addNode: (DiyaCompositeNode new) at: 0@0.
txtFPS := root addNode:(DiyaText data: '') at: ( self context resolution x - 80)@(self context resolution y - 40).
node addNode: (DiyaCompositeNode new) at: 0@0.
txtFPS := node addNode:(DiyaText data: '') at: ( self context resolution x - 80)@(self context resolution y - 40).
node addNode: (DiyaTimerNode timeout: 0 do: [:n| self updateFPS ] ).
txtFPS extent: 80@40.
txtFPS styleName: #fps_text.
self bindGlobalEvent.
running := true.
self launch: self defaultApplication.
aBlock value.
]
{ #category : #accessing }
DiyaApplicationLauncher >> running [
^ running
]
{ #category : #initialization }
DiyaApplicationLauncher >> updateFPS [
| fps delta|
delta := DiyaSystemClock delta.
fps := DiyaSystemSettings maxFPS.
delta = 0 ifFalse:[ fps := (1000/ delta) asInteger].
txtFPS data: ('FPS:', fps asString).
]

View File

@ -2,8 +2,9 @@ Class {
#name : #DiyaApplicationModel,
#superclass : #DiyaSingleton,
#instVars : [
'root',
'am'
'node',
'am',
'loader'
],
#category : #'Diya-Applications'
}
@ -23,13 +24,29 @@ DiyaApplicationModel >> context [
^DiyaRenderer
]
{ #category : #initialization }
DiyaApplicationModel >> initLoader [
self subclassResponsibility
]
{ #category : #initialization }
DiyaApplicationModel >> initialize [
super initialize.
self initLoader.
]
{ #category : #accessing }
DiyaApplicationModel >> main [
DiyaApplicationModel >> loader [
^ loader
]
{ #category : #accessing }
DiyaApplicationModel >> node [
^ node
]
{ #category : #accessing }
DiyaApplicationModel >> onloaded: aBlock [
self subclassResponsibility
]
@ -37,13 +54,3 @@ DiyaApplicationModel >> main [
DiyaApplicationModel >> quit [
self cleanup
]
{ #category : #accessing }
DiyaApplicationModel >> root [
^ root
]
{ #category : #accessing }
DiyaApplicationModel >> setup [
self subclassResponsibility
]

View File

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

View File

@ -96,15 +96,18 @@ DiyaBoot >> initialize [
{ #category : #events }
DiyaBoot >> render [
|launcher|
|launcher event|
event := SDL_Event new.
launcher := DiyaApplicationLauncher uniqueInstance.
launcher setup.
"Init the Open GL view port and enable 2D texture"
OpenGL viewportX: 0 Y:0 W: display w H: display h.
OpenGL enable: GL_TEXTURE_2D.
launcher onloaded: [self stdlog: 'Launcher loaded'].
[ launcher running ] whileTrue: [
DiyaSystemClock tick.
launcher main.
[(SDL2 pollEvent: event) > 0] whileTrue: [
DiyaRenderer root trigger: (DiyaEvent from: event mapped).
].
DiyaRenderer render.
SDL2 delay:
(0 max:

View File

@ -0,0 +1,24 @@
Class {
#name : #DiyaDefaultAppLoader,
#superclass : #DiyaLoader,
#instVars : [
'progress',
'label'
],
#category : #'Diya-Applications'
}
{ #category : #initialization }
DiyaDefaultAppLoader >> init [
progress := node addNode: (DiyaLoadingBar new) at: 20@50.
progress extent: 420 @ 20.
label := node addNode: (DiyaText new) at: 20@80.
label extent: 420 @ 20.
label inlineStyle: #xAlign value: #center
]
{ #category : #scheduling }
DiyaDefaultAppLoader >> updateProgress: name percent: p [
label data: name.
progress percent: p
]

View File

@ -9,6 +9,98 @@ DiyaExampleApp >> cleanup [
]
{ #category : #accessing }
DiyaExampleApp >> defineNodes [
|node2 node1 img ell label icon button texture loading|
texture := DiyaImageTex new.
label := node addNode: (DiyaLabel new) at: 10@40.
label extent: 250@24.
label styleName:#text_icon_1.
label icon: 16rF254.
node1 := node addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 300 @ 40.
node1 rotation: 45.
node1 scale: 2.0@2.0.
node1 on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'RECT ', (node1 local: e mapped worldPosition) asIntegerPoint asString].
img := node addNode: (DiyaImageView from:'mrsang.png') at: 10 @ 400.
img styleName: #image_view.
img extent:200@200.
node on: #(mousebuttondown fingerdown) do:[:e|
"change texture"
|p|
p := e mapped worldPosition.
label txt: 'Mouse ', p asIntegerPoint asString.
DiyaRenderer assets
addAsset:(texture fromDisplay: (Rectangle origin: ((p x - 100) @ (p y - 100)) extent: 200@200 ) as: 'capture').
img textureNamed: 'capture'.
].
node2 := node addNode: (DiyaRectangle new) at: 10@80.
node2 styleName: #rect_view.
node2 extent: 240@320.
node2 := node addNode: (DiyaText data: String loremIpsum) at: 10@80.
node2 extent: 240@320.
node2 wordWrap: true.
node2 styleName: #text_view.
node2 := node addNode: (DiyaLine from: 10@10 to: 200@200).
node2 styleName: #line_view.
ell := node addNode: (DiyaEllipse rx:100 ry: 70) at: 120@300.
ell scale: 1.2 @ 1.2.
ell styleName: #ell_view.
"ell rotation: 30."
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|
label txt: 'Ellipse clicked', (ell local:e mapped worldPosition) asIntegerPoint asString].
node2 := node addNode: (DiyaConvexPolygon points:{0@40. 150@190. 200@20. 100@0}) at: 250@60.
node2 textureNamed: 'mrsang.png'.
node2 styleName: #poly_view.
icon := node addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 240@500.
icon styleName: #text_icon_2.
button := node 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 icon: icon "'mrsang.png'".
"button rotation: Float pi / 2.0."
button styleName: #button_view.
loading := node addNode: (DiyaLoadingBar new) at: 240@550.
loading extent: 200 @ 20.
loading addNode: (DiyaTimerNode timeout: 2000 do:[:n |
|p|
p := (n parent percent + 10).
p > 100 ifTrue:[ p := 0].
n parent percent: p.
] ).
loading := node addNode: (DiyaLoadingBar new) at: 240@580.
loading extent: 200 @ 20.
loading addNode: (DiyaTimerNode timeout: 1000 do:[:n |
|p|
p := (n parent percent + 10).
p > 100 ifTrue:[ p := 0].
n parent percent: p.
] ).
]
{ #category : #accessing }
DiyaExampleApp >> defineStyleSheet [
|fmgr style|
@ -16,7 +108,7 @@ DiyaExampleApp >> defineStyleSheet [
#(16 18 24) do:[:fontSize|
self stdlog: 'Init font size ', fontSize asString, ' of ', fmgr defaultFamily.
style := fmgr style: fmgr defaultStyle from: fmgr defaultFamily.
style textureOf: fontSize.
(style textureOf: fontSize)" genPrintableASCII" .
].
DiyaUIThemesManager uniqueInstance currentTheme
define: #text_icon_1 styles: {
@ -67,104 +159,18 @@ DiyaExampleApp >> defineStyleSheet [
}
]
{ #category : #accessing }
DiyaExampleApp >> main [
{ #category : #initialization }
DiyaExampleApp >> initLoader [
loader := DiyaDefaultAppLoader new.
]
{ #category : #accessing }
DiyaExampleApp >> setup [
|node node1 img ell label icon button texture loading|
texture := DiyaImageTex new.
"DiyaRendererContext uniqueInstance assets
addAsset:
((Form fromDisplay: ( Rectangle origin: 0@0 corner: 300@300 )) asDiyaTexture: 'display')."
self defineStyleSheet.
label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@24.
label styleName:#text_icon_1.
label icon: 16rF254.
DiyaExampleApp >> onloaded: aBlock [
loader job: [ self defineStyleSheet ] name: 'Initializing themes...'.
loader job: [
self defineNodes.
self node forceReload
] name: 'Initializing UI elements...'.
node1 := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 300 @ 40.
node1 rotation: 45.
node1 scale: 2.0@2.0.
node1 on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'RECT ', (node1 local: e mapped worldPosition) asIntegerPoint asString].
img := root addNode: (DiyaImageView from:'mrsang.png') at: 10 @ 400.
img styleName: #image_view.
img extent:200@200.
root on: #(mousebuttondown fingerdown) do:[:e|
"change texture"
|p|
p := e mapped worldPosition.
label txt: 'Mouse ', p asIntegerPoint asString.
DiyaRenderer assets
addAsset:(texture fromDisplay: (Rectangle origin: ((p x - 100) @ (p y - 100)) extent: 200@200 ) as: 'capture').
img textureNamed: 'capture'.
].
node := root addNode: (DiyaRectangle new) at: 10@80.
node styleName: #rect_view.
node extent: 240@320.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@80.
node extent: 240@320.
node wordWrap: true.
node styleName: #text_view.
node := root addNode: (DiyaLine from: 10@10 to: 200@200).
node styleName: #line_view.
ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 120@300.
ell scale: 1.2 @ 1.2.
ell styleName: #ell_view.
"ell rotation: 30."
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|
label txt: 'Ellipse clicked', (ell local:e mapped worldPosition) asIntegerPoint asString].
node := root addNode: (DiyaConvexPolygon points:{0@40. 150@190. 200@20. 100@0}) at: 250@60.
node textureNamed: 'mrsang.png'.
node styleName: #poly_view.
icon := root addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 240@500.
icon styleName: #text_icon_2.
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 icon: icon "'mrsang.png'".
"button rotation: Float pi / 2.0."
button styleName: #button_view.
loading := root addNode: (DiyaLoadingBar new) at: 240@550.
loading extent: 200 @ 20.
loading addNode: (DiyaTimerNode timeout: 2000 do:[:n |
|p|
p := (n parent percent + 10).
p > 100 ifTrue:[ p := 0].
n parent percent: p.
] ).
loading := root addNode: (DiyaLoadingBar new) at: 240@580.
loading extent: 200 @ 20.
loading addNode: (DiyaTimerNode timeout: 1000 do:[:n |
|p|
p := (n parent percent + 10).
p > 100 ifTrue:[ p := 0].
n parent percent: p.
] ).
^ root
loader onloaded: aBlock
]

54
Diya/DiyaLoader.class.st Normal file
View File

@ -0,0 +1,54 @@
Class {
#name : #DiyaLoader,
#superclass : #DiyaBaseObject,
#instVars : [
'node',
'jobs'
],
#category : #'Diya-Applications'
}
{ #category : #scheduling }
DiyaLoader >> executeJobs: callback [
jobs withIndexDo: [ :job :i|
self updateProgress: job key percent: ((i - 1) * 100 / (jobs size)) asInteger.
job value value.
].
jobs := OrderedCollection new.
self updateProgress: 'Finishing...' percent: 100.
500 milliSeconds wait.
callback value.
]
{ #category : #initialization }
DiyaLoader >> init [
self subclassResponsibility
]
{ #category : #initialization }
DiyaLoader >> initialize [
super initialize.
node := DiyaCompositeNode new.
jobs := OrderedCollection new.
self init.
]
{ #category : #scheduling }
DiyaLoader >> job: aBlock name: aName [
jobs add: (aName -> aBlock)
]
{ #category : #accessing }
DiyaLoader >> node [
^ node
]
{ #category : #scheduling }
DiyaLoader >> onloaded: aBlock [
[ self executeJobs: aBlock ] fork"At: Processor userBackgroundPriority".
]
{ #category : #scheduling }
DiyaLoader >> updateProgress: name percent: p [
self subclassResponsibility
]

View File

@ -14,6 +14,7 @@ Class {
'root',
'styleName',
'style',
'inlineStyle',
'id',
'visibility',
'pivot'
@ -31,9 +32,11 @@ DiyaNode class >> with: shader [
^self new shader: shader; yourself
]
{ #category : #accessing }
{ #category : #styling }
DiyaNode >> ? styleAttr [
| value|
value := inlineStyle at: styleAttr ifAbsent:[nil].
value ifNotNil: [ ^value ].
styleName ifNotNil: [
style ifNil: [
style := DiyaUIThemesManager uniqueInstance currentTheme ? (self styleName).
@ -90,7 +93,6 @@ DiyaNode >> extent [
{ #category : #processing }
DiyaNode >> forceReload [
self process.
self setClean.
children ifNotNil: [
children do:[:c|
c forceReload
@ -113,11 +115,17 @@ DiyaNode >> initialize [
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

View File

@ -135,7 +135,7 @@ DiyaRendererContext >> root [
{ #category : #rendering }
DiyaRendererContext >> submitData: vbuffer [
vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_DYNAMIC_DRAW.
vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
]
{ #category : #'transformation matrices' }

View File

@ -206,9 +206,6 @@ DiyaText >> process [
data ifNil:[^true].
data ifEmpty:[^true].
texture ifNil: [ self initTexture ].
texheight = texture height ifFalse: [
texheight := texture height.
].
vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease.
@ -230,6 +227,14 @@ DiyaText >> splitLines [
] whileTrue.
]
{ #category : #stepping }
DiyaText >> step [
texture ifNil: [ ^self ].
texheight = texture height ifTrue: [ ^self].
texheight := texture height.
self setDirty
]
{ #category : #accessing }
DiyaText >> styleName: aName [
super styleName: aName.