1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2024-12-27 03:48:21 +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 : [ #instVars : [
'currapp', 'currapp',
'txtFPS', 'txtFPS',
'event',
'running' 'running'
], ],
#category : #'Diya-Applications' #category : #'Diya-Applications'
@ -12,17 +11,17 @@ Class {
{ #category : #initialization } { #category : #initialization }
DiyaApplicationLauncher >> appNode [ DiyaApplicationLauncher >> appNode [
^root children first ^node children first
] ]
{ #category : #initialization } { #category : #initialization }
DiyaApplicationLauncher >> bindGlobalEvent [ DiyaApplicationLauncher >> bindGlobalEvent [
|pointer | |pointer |
pointer := root addNode: (DiyaCircle r: 10) at: 200@200. pointer := node addNode: (DiyaCircle r: 10) at: 200@200.
pointer styleName: #pointer. pointer styleName: #pointer.
root on: #keydown do:[:e| self stdlog: 'keydown...'. running := false.]. node on: #keydown do:[:e| self stdlog: 'keydown...'. running := false.].
root on: #quit do: [:e| running := false]. node on: #quit do: [:e| running := false].
root on: #(fingerdown fingermotion mousemotion) do:[:e| node on: #(fingerdown fingermotion mousemotion) do:[:e|
pointer position: e mapped worldPosition. pointer position: e mapped worldPosition.
DiyaRenderer mouse: (e mapped x) @ (e mapped y). DiyaRenderer mouse: (e mapped x) @ (e mapped y).
]. ].
@ -33,10 +32,15 @@ DiyaApplicationLauncher >> defaultApplication [
^DiyaExampleApp ^DiyaExampleApp
] ]
{ #category : #initialization }
DiyaApplicationLauncher >> initLoader [
]
{ #category : #initialization } { #category : #initialization }
DiyaApplicationLauncher >> initialize [ DiyaApplicationLauncher >> initialize [
super initialize. super initialize.
root := DiyaRenderer root. node := DiyaRenderer root.
currapp := nil. currapp := nil.
] ]
@ -44,42 +48,22 @@ DiyaApplicationLauncher >> initialize [
DiyaApplicationLauncher >> launch: app [ DiyaApplicationLauncher >> launch: app [
currapp ifNotNil: [ currapp ifNotNil: [
currapp quit. currapp quit.
root empty. node empty.
]. ].
currapp := app uniqueInstance. currapp := app uniqueInstance.
self context assets: currapp am. self context assets: currapp am.
[ self appNode addNode: currapp loader node.
self stdlog: 'Loading application'. currapp onloaded:[
currapp root visibility: false. self appNode empty.
currapp setup. currapp node visibility: false.
currapp root forceReload. self appNode addNode: currapp node.
self appNode addNode: currapp root. currapp node visibility: true.
currapp root visibility: true.
self stdlog: 'Application LOADED'. 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 } { #category : #initialization }
DiyaApplicationLauncher >> setup [ DiyaApplicationLauncher >> onloaded: aBlock [
event := SDL_Event new.
DiyaUIThemesManager uniqueInstance currentTheme DiyaUIThemesManager uniqueInstance currentTheme
define: #fps_text styles: { define: #fps_text styles: {
#color -> Color red. #color -> Color red.
@ -91,11 +75,27 @@ DiyaApplicationLauncher >> setup [
#bgColor -> Color orange. #bgColor -> Color orange.
#border -> 3 #border -> 3
}. }.
root addNode: (DiyaCompositeNode new) at: 0@0. node addNode: (DiyaCompositeNode new) at: 0@0.
txtFPS := root addNode:(DiyaText data: '') at: ( self context resolution x - 80)@(self context resolution y - 40). 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 extent: 80@40.
txtFPS styleName: #fps_text. txtFPS styleName: #fps_text.
self bindGlobalEvent. self bindGlobalEvent.
running := true. running := true.
self launch: self defaultApplication. 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, #name : #DiyaApplicationModel,
#superclass : #DiyaSingleton, #superclass : #DiyaSingleton,
#instVars : [ #instVars : [
'root', 'node',
'am' 'am',
'loader'
], ],
#category : #'Diya-Applications' #category : #'Diya-Applications'
} }
@ -23,13 +24,29 @@ DiyaApplicationModel >> context [
^DiyaRenderer ^DiyaRenderer
] ]
{ #category : #initialization }
DiyaApplicationModel >> initLoader [
self subclassResponsibility
]
{ #category : #initialization } { #category : #initialization }
DiyaApplicationModel >> initialize [ DiyaApplicationModel >> initialize [
super initialize. super initialize.
self initLoader.
] ]
{ #category : #accessing } { #category : #accessing }
DiyaApplicationModel >> main [ DiyaApplicationModel >> loader [
^ loader
]
{ #category : #accessing }
DiyaApplicationModel >> node [
^ node
]
{ #category : #accessing }
DiyaApplicationModel >> onloaded: aBlock [
self subclassResponsibility self subclassResponsibility
] ]
@ -37,13 +54,3 @@ DiyaApplicationModel >> main [
DiyaApplicationModel >> quit [ DiyaApplicationModel >> quit [
self cleanup self cleanup
] ]
{ #category : #accessing }
DiyaApplicationModel >> root [
^ root
]
{ #category : #accessing }
DiyaApplicationModel >> setup [
self subclassResponsibility
]

View File

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

View File

@ -96,15 +96,18 @@ DiyaBoot >> initialize [
{ #category : #events } { #category : #events }
DiyaBoot >> render [ DiyaBoot >> render [
|launcher| |launcher event|
event := SDL_Event new.
launcher := DiyaApplicationLauncher uniqueInstance. launcher := DiyaApplicationLauncher uniqueInstance.
launcher setup.
"Init the Open GL view port and enable 2D texture" "Init the Open GL view port and enable 2D texture"
OpenGL viewportX: 0 Y:0 W: display w H: display h. OpenGL viewportX: 0 Y:0 W: display w H: display h.
OpenGL enable: GL_TEXTURE_2D. OpenGL enable: GL_TEXTURE_2D.
launcher onloaded: [self stdlog: 'Launcher loaded'].
[ launcher running ] whileTrue: [ [ launcher running ] whileTrue: [
DiyaSystemClock tick. DiyaSystemClock tick.
launcher main. [(SDL2 pollEvent: event) > 0] whileTrue: [
DiyaRenderer root trigger: (DiyaEvent from: event mapped).
].
DiyaRenderer render. DiyaRenderer render.
SDL2 delay: SDL2 delay:
(0 max: (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 } { #category : #accessing }
DiyaExampleApp >> defineStyleSheet [ DiyaExampleApp >> defineStyleSheet [
|fmgr style| |fmgr style|
@ -16,7 +108,7 @@ DiyaExampleApp >> defineStyleSheet [
#(16 18 24) do:[:fontSize| #(16 18 24) do:[:fontSize|
self stdlog: 'Init font size ', fontSize asString, ' of ', fmgr defaultFamily. self stdlog: 'Init font size ', fontSize asString, ' of ', fmgr defaultFamily.
style := fmgr style: fmgr defaultStyle from: fmgr defaultFamily. style := fmgr style: fmgr defaultStyle from: fmgr defaultFamily.
style textureOf: fontSize. (style textureOf: fontSize)" genPrintableASCII" .
]. ].
DiyaUIThemesManager uniqueInstance currentTheme DiyaUIThemesManager uniqueInstance currentTheme
define: #text_icon_1 styles: { define: #text_icon_1 styles: {
@ -67,104 +159,18 @@ DiyaExampleApp >> defineStyleSheet [
} }
] ]
{ #category : #accessing } { #category : #initialization }
DiyaExampleApp >> main [ DiyaExampleApp >> initLoader [
loader := DiyaDefaultAppLoader new.
] ]
{ #category : #accessing } { #category : #accessing }
DiyaExampleApp >> setup [ DiyaExampleApp >> onloaded: aBlock [
|node node1 img ell label icon button texture loading| loader job: [ self defineStyleSheet ] name: 'Initializing themes...'.
texture := DiyaImageTex new. loader job: [
"DiyaRendererContext uniqueInstance assets self defineNodes.
addAsset: self node forceReload
((Form fromDisplay: ( Rectangle origin: 0@0 corner: 300@300 )) asDiyaTexture: 'display')." ] name: 'Initializing UI elements...'.
self defineStyleSheet.
label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@24.
label styleName:#text_icon_1.
label icon: 16rF254.
node1 := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 300 @ 40. loader onloaded: aBlock
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
] ]

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

View File

@ -135,7 +135,7 @@ DiyaRendererContext >> root [
{ #category : #rendering } { #category : #rendering }
DiyaRendererContext >> submitData: vbuffer [ 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' } { #category : #'transformation matrices' }

View File

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