mirror of
https://github.com/lxsang/Diya-API.git
synced 2025-07-17 14:29:52 +02:00
Compare commits
36 Commits
conflict
...
single_buf
Author | SHA1 | Date | |
---|---|---|---|
d99d6f3604 | |||
c1f2de2896 | |||
766ae23f8e | |||
f3ef0c1aa0 | |||
2e4c73f8cf | |||
2ee103191c | |||
a3d00d52ef | |||
133ddb0380 | |||
598e252b9e | |||
664e2169f3 | |||
9442050825 | |||
6f5c6b8551 | |||
141bf2e226 | |||
676113a697 | |||
4a95c7d6df | |||
7a7665430d | |||
8b6a7927f4 | |||
007d99804f | |||
c249c2e381 | |||
6d7ab2dcd6 | |||
b8257f7011 | |||
fcaadbc185 | |||
4467f61f32 | |||
396fd9909d | |||
5915d86219 | |||
a8b89f19c5 | |||
5058d62876 | |||
d70df41681 | |||
e2adc4f733 | |||
e99500acca | |||
91cfa95ef7 | |||
42aeb49947 | |||
eba462b9c0 | |||
ac764da076 | |||
e2a8bc046c | |||
f215eb054f |
@ -1,5 +1,15 @@
|
||||
Extension { #name : #Array }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
Array >> asDiyaStyle [
|
||||
|style|
|
||||
style := DiyaStyle new.
|
||||
self do:[:v |
|
||||
style at: v key put: v value
|
||||
].
|
||||
^style
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
Array >> asPoint [
|
||||
^ (self at: 1 ifAbsent:[0]) @ (self at: 2 ifAbsent:[0])
|
||||
|
@ -1,14 +0,0 @@
|
||||
Extension { #name : #Array2D }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
Array2D >> asGLBuffer [
|
||||
|buffer i|
|
||||
i := 1.
|
||||
buffer := FFIExternalArray externalNewType: #float size: self size.
|
||||
self asArray do:[:e|
|
||||
buffer at:i put:e.
|
||||
i := i+1
|
||||
].
|
||||
buffer autoRelease.
|
||||
^buffer
|
||||
]
|
58
Diya/AssetManager.class.st
Normal file
58
Diya/AssetManager.class.st
Normal file
@ -0,0 +1,58 @@
|
||||
Class {
|
||||
#name : #AssetManager,
|
||||
#superclass : #DiyaBaseObject,
|
||||
#instVars : [
|
||||
'assets',
|
||||
'base'
|
||||
],
|
||||
#category : #'Diya-Core'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
AssetManager class >> defaultAssetLocation [
|
||||
^Smalltalk imageDirectory / 'assets'
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
AssetManager class >> fromLocation: loc [
|
||||
^self new from: loc; yourself
|
||||
]
|
||||
|
||||
{ #category : #adding }
|
||||
AssetManager >> addAsset: value [
|
||||
assets at: value name put: value
|
||||
]
|
||||
|
||||
{ #category : #adding }
|
||||
AssetManager >> addAssetName: name value: value [
|
||||
assets at: name put: value
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
AssetManager >> from: location [
|
||||
base := location
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
AssetManager >> initialize [
|
||||
super initialize.
|
||||
assets := Dictionary new.
|
||||
base := self class defaultAssetLocation
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
AssetManager >> name: name [
|
||||
^assets at: name.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
AssetManager >> name: name of: type [
|
||||
^assets at: name ifAbsentPut: [
|
||||
(type fromFile: (base / name))].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
AssetManager >> texture: name [
|
||||
^self name: name of: DiyaImageTex
|
||||
]
|
6
Diya/DiskStore.extension.st
Normal file
6
Diya/DiskStore.extension.st
Normal file
@ -0,0 +1,6 @@
|
||||
Extension { #name : #DiskStore }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
DiskStore class >> inform: string [
|
||||
Transcript show: string; cr.
|
||||
]
|
@ -2,31 +2,32 @@ Class {
|
||||
#name : #Diya2DNode,
|
||||
#superclass : #DiyaNode,
|
||||
#instVars : [
|
||||
'color',
|
||||
'vbuffer',
|
||||
'bbox'
|
||||
'voffset'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> boundingBox [
|
||||
^ bbox
|
||||
|rec|
|
||||
children ifEmpty: [ ^ Rectangle origin: 0@0 corner: 0@0 ].
|
||||
rec := children first boundingBox.
|
||||
children do:[:c|
|
||||
rec = c ifFalse:[
|
||||
rec := rec merge: c boundingBox]
|
||||
].
|
||||
^rec
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> color [
|
||||
^ color
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> color: anObject [
|
||||
color := anObject
|
||||
Diya2DNode >> draw [
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> extent [
|
||||
^ bbox extent
|
||||
^ self boundingBox extent
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -38,15 +39,26 @@ Diya2DNode >> height [
|
||||
Diya2DNode >> initialize [
|
||||
super initialize.
|
||||
translation := 0@0.
|
||||
scale := 1.0@1.0.
|
||||
rotation := 0.0.
|
||||
tf := Array2D identity: 3.
|
||||
scale := 1@1.
|
||||
rotation := 0.
|
||||
tf := MatrixTransform2x3 identity .
|
||||
shader := Diya2DShader uniqueInstance.
|
||||
color := Color white.
|
||||
vbuffer := nil.
|
||||
voffset := 0.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> inner: aPoint [
|
||||
^ self boundingBox containsPoint: (self local: aPoint)
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> local: aPoint [
|
||||
^ self tf globalPointToLocal: aPoint
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> recFromBuffer [
|
||||
|maxX maxY minX minY x y|
|
||||
maxX := minX := vbuffer at: 1.
|
||||
@ -62,36 +74,29 @@ Diya2DNode >> recFromBuffer [
|
||||
^ Rectangle origin: minX@minY corner: maxX @ maxY
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
Diya2DNode >> setUpShader [
|
||||
super setUpShader.
|
||||
shader setUniform: #u_color value: self color asGL4FArray.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DNode >> updateTF [
|
||||
tf := Array2D identity:3.
|
||||
tf := MatrixTransform2x3 identity.
|
||||
"translation"
|
||||
tf := tf +* (Array2D rows: 3 columns: 3 contents: {
|
||||
1.0. 0.0. translation x.
|
||||
0.0. 1.0. translation y.
|
||||
0.0. 0.0. 1.0
|
||||
}).
|
||||
tf setOffset: translation + pivot.
|
||||
"rotation"
|
||||
tf := tf +* (Array2D rows: 3 columns: 3 contents:{
|
||||
rotation cos. (rotation sin) negated. 0.0.
|
||||
rotation sin. rotation cos. 0.0.
|
||||
0.0. 0.0. 1.0
|
||||
}).
|
||||
"scale"
|
||||
tf := tf +* (Array2D rows: 3 columns: 3 contents:{
|
||||
scale x. 0.0. 0.0.
|
||||
0.0. scale y. 0.0.
|
||||
0.0. 0.0. 1.0
|
||||
}).
|
||||
self parent isRoot ifFalse: [ tf := self parent tf +* tf ].
|
||||
children ifNotNil: [
|
||||
children do:[:c| c updateTF ]].
|
||||
rotation = 0 ifFalse:[tf setAngle: rotation ].
|
||||
"translate back to pivot"
|
||||
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 isRoot ifFalse: [tf := self parent tf composedWithLocal: tf ].
|
||||
children ifNotNil: [children do:[:c| c updateTF ]].
|
||||
|
||||
]
|
||||
|
||||
|
@ -4,50 +4,49 @@ Class {
|
||||
#instVars : [
|
||||
'texture',
|
||||
'type',
|
||||
'border',
|
||||
'bcolor'
|
||||
'bbox'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DPrimShape >> borderColor: c [
|
||||
bcolor := c
|
||||
Diya2DPrimShape >> borderWidth [
|
||||
^ self ? #border
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DPrimShape >> borderWidth: w [
|
||||
border := w
|
||||
Diya2DPrimShape >> boundingBox [
|
||||
^ self tf localBoundsToGlobal: bbox.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
Diya2DPrimShape >> draw [
|
||||
vbuffer ifNil: [ ^self ].
|
||||
OpenGL
|
||||
enable: GL_CULL_FACE;
|
||||
enable: GL_BLEND;
|
||||
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
|
||||
"configure vao vbo for texture QUAD"
|
||||
self texture ifNotNil: [
|
||||
self texture setup.
|
||||
context texture0 setImage2D: self texture.
|
||||
context texture0 active.
|
||||
context setTexture: self texture.
|
||||
].
|
||||
context vao enableAttribute: 0.
|
||||
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
|
||||
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
|
||||
OpenGL drawArrays: type first:0 count:((vbuffer size )>> 2 ).
|
||||
voffset := context submitData: vbuffer.
|
||||
OpenGL drawArrays: type first: voffset count:((vbuffer size )>> 2 ).
|
||||
"reset value"
|
||||
self texture ifNotNil: [self texture drop.].
|
||||
border > 0 ifTrue: [ self drawBorder ].
|
||||
context vao disableAttribute: 0.
|
||||
self borderWidth > 0 ifTrue: [ self drawBorder ].
|
||||
OpenGL
|
||||
disable: GL_CULL_FACE;
|
||||
disable: GL_BLEND.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
Diya2DPrimShape >> drawBorder [
|
||||
"Diya2DShader uniqueInstance use."
|
||||
color = bcolor ifFalse:[
|
||||
shader setUniform: #u_color value: bcolor asGL4FArray;
|
||||
setUniform: #u_texture_type value: 0.
|
||||
].
|
||||
shader setUniform: #u_color value: (self ? #borderColor) asGL4FArray;
|
||||
setUniform: #u_texture_type value: 1.
|
||||
OpenGL
|
||||
lineWidth: border.
|
||||
lineWidth: self borderWidth.
|
||||
self drawLines.
|
||||
OpenGL lineWidth: 1.0.
|
||||
]
|
||||
@ -62,23 +61,33 @@ Diya2DPrimShape >> drawLines [
|
||||
self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DPrimShape >> extent [
|
||||
^ bbox extent
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
Diya2DPrimShape >> initialize [
|
||||
super initialize.
|
||||
texture := nil.
|
||||
children := nil.
|
||||
type := GL_TRIANGLES.
|
||||
border := 0.
|
||||
bcolor := Color white.
|
||||
bbox := Rectangle origin: 0@0 corner: 0@0.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DPrimShape >> inner: aPoint [
|
||||
bbox ifNil: [ ^false ].
|
||||
^ bbox containsPoint: (self local: aPoint)
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
Diya2DPrimShape >> setUpShader [
|
||||
super setUpShader
|
||||
texture ifNotNil:[
|
||||
self shader
|
||||
setUniform: #u_texture_type value: texture format.
|
||||
].
|
||||
super setUpShader.
|
||||
self shader
|
||||
setUniform: #u_color value: (self ? #color) asGL4FArray;
|
||||
setUniform: #u_bg_color value: (self ? #bgColor) asGL4FArray;
|
||||
setUniform: #u_texture_type value:
|
||||
(self texture ifNil: [ 0 ] ifNotNil:[self texture format]).
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -90,3 +99,8 @@ Diya2DPrimShape >> texture [
|
||||
Diya2DPrimShape >> texture: anObject [
|
||||
texture := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
Diya2DPrimShape >> textureNamed: name [
|
||||
self texture: (context assets texture: name)
|
||||
]
|
||||
|
@ -10,17 +10,23 @@ Diya2DShader class >> fragmentShader [
|
||||
#ifdef GL_ES
|
||||
precision highp float;
|
||||
#endif
|
||||
|
||||
uniform vec2 u_resolution;
|
||||
uniform vec2 u_mouse;
|
||||
uniform float u_time;
|
||||
// 2D uniforms
|
||||
uniform int u_texture_type;
|
||||
uniform vec4 u_color;
|
||||
uniform vec4 u_bg_color;
|
||||
uniform sampler2D u_texture;
|
||||
varying vec2 texcoord;
|
||||
void main(void) {
|
||||
vec4 texcolor = vec4(1,1,1,1);
|
||||
if(u_texture_type == 1)
|
||||
{
|
||||
// draw border
|
||||
gl_FragColor = u_color;
|
||||
return;
|
||||
}
|
||||
vec4 texcolor = u_bg_color;
|
||||
// alpha
|
||||
if(u_texture_type == 0x1906) {
|
||||
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
|
||||
@ -28,8 +34,16 @@ void main(void) {
|
||||
// rgba
|
||||
else if (u_texture_type == 0x1908){
|
||||
texcolor = texture2D(u_texture, texcoord);
|
||||
}
|
||||
vec4 pxcolor = texcolor * u_color;
|
||||
if(pxcolor.a > 0.0)
|
||||
{
|
||||
gl_FragColor = pxcolor;
|
||||
}
|
||||
else
|
||||
{
|
||||
gl_FragColor = u_bg_color;
|
||||
}
|
||||
gl_FragColor = texcolor * u_color;
|
||||
}'
|
||||
]
|
||||
|
||||
@ -55,6 +69,7 @@ Diya2DShader >> setUpUniforms [
|
||||
self addUniform: #u_texture of: Uniform1i.
|
||||
self addUniform: #u_texture_type of: Uniform1i.
|
||||
self addUniform: #u_color of: Uniform4F.
|
||||
self addUniform: #u_bg_color of: Uniform4F.
|
||||
self addUniform: #u_border_color of: Uniform4F.
|
||||
self addUniform: #u_border of: Uniform1F.
|
||||
]
|
||||
|
119
Diya/DiyaApplicationLauncher.class.st
Normal file
119
Diya/DiyaApplicationLauncher.class.st
Normal file
@ -0,0 +1,119 @@
|
||||
Class {
|
||||
#name : #DiyaApplicationLauncher,
|
||||
#superclass : #DiyaApplicationModel,
|
||||
#instVars : [
|
||||
'currapp',
|
||||
'txtFPS',
|
||||
'event',
|
||||
'running'
|
||||
],
|
||||
#category : #'Diya-Applications'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> appNode [
|
||||
^root children first
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> bindGlobalEvent [
|
||||
|pointer |
|
||||
pointer := root 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|
|
||||
pointer position: e mapped worldPosition.
|
||||
DiyaRendererContext uniqueInstance mouse: (e mapped x) @ (e mapped y).
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> defaultApplication [
|
||||
^DiyaExampleApp
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> initialize [
|
||||
super initialize.
|
||||
root := DiyaRootNode new.
|
||||
currapp := nil.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> launch: app [
|
||||
currapp ifNotNil: [
|
||||
currapp quit.
|
||||
root empty.
|
||||
].
|
||||
currapp := app uniqueInstance.
|
||||
self context assets: currapp am.
|
||||
[
|
||||
self stdlog: 'Loading application'.
|
||||
currapp root visibility: false.
|
||||
currapp setup.
|
||||
self appNode addNode: currapp root.
|
||||
self process: true.
|
||||
currapp root visibility: true.
|
||||
self stdlog: 'Application LOADED'.
|
||||
] fork.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> main [
|
||||
| fps delta|
|
||||
delta := DiyaClock uniqueInstance delta asMilliSeconds.
|
||||
fps := DiyaBoot 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.].
|
||||
root stepDown.
|
||||
self process: false.
|
||||
root render.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> process: force [
|
||||
|Q node maxProcessingTime|
|
||||
maxProcessingTime := (1000 / DiyaBoot maxFPS) asInteger >> 1.
|
||||
Q := root processingQueue.
|
||||
Q ifEmpty:[^ self].
|
||||
[
|
||||
node := Q removeFirst.
|
||||
node process.
|
||||
Q isNotEmpty and: (
|
||||
(DiyaClock uniqueInstance lapDelta asMilliSeconds < maxProcessingTime) or: force)
|
||||
] whileTrue
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationLauncher >> running [
|
||||
^ running
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationLauncher >> setup [
|
||||
event := SDL_Event new.
|
||||
DiyaUIThemesManager uniqueInstance currentTheme
|
||||
define: #fps_text styles: {
|
||||
#color -> Color red.
|
||||
#fontSize -> 18.
|
||||
#bgColor -> Color transparent.
|
||||
};
|
||||
define: #pointer styles: {
|
||||
#borderColor -> Color red.
|
||||
#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).
|
||||
txtFPS extent: 80@40.
|
||||
txtFPS styleName: #fps_text.
|
||||
self bindGlobalEvent.
|
||||
running := true.
|
||||
self launch: self defaultApplication.
|
||||
]
|
49
Diya/DiyaApplicationModel.class.st
Normal file
49
Diya/DiyaApplicationModel.class.st
Normal file
@ -0,0 +1,49 @@
|
||||
Class {
|
||||
#name : #DiyaApplicationModel,
|
||||
#superclass : #DiyaSingleton,
|
||||
#instVars : [
|
||||
'root',
|
||||
'am'
|
||||
],
|
||||
#category : #'Diya-Applications'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> am [
|
||||
^ am
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> cleanup [
|
||||
self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> context [
|
||||
^DiyaRendererContext uniqueInstance
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaApplicationModel >> initialize [
|
||||
super initialize.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> main [
|
||||
self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> quit [
|
||||
self cleanup
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> root [
|
||||
^ root
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaApplicationModel >> setup [
|
||||
self subclassResponsibility
|
||||
]
|
13
Diya/DiyaBaseApplication.class.st
Normal file
13
Diya/DiyaBaseApplication.class.st
Normal file
@ -0,0 +1,13 @@
|
||||
Class {
|
||||
#name : #DiyaBaseApplication,
|
||||
#superclass : #DiyaApplicationModel,
|
||||
#category : #'Diya-Applications'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaBaseApplication >> initialize [
|
||||
super initialize.
|
||||
root := DiyaCompositeNode new.
|
||||
root styleName: #global.
|
||||
am := AssetManager new.
|
||||
]
|
@ -13,9 +13,9 @@ DiyaBaseObject >> checkGLError: mark [
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaBaseObject >> logError: string [
|
||||
self stderr nextPutAll: string; cr
|
||||
{ #category : #asserting }
|
||||
DiyaBaseObject >> shouldNotBeCalled [
|
||||
^DiyaCoreAPIError signal: 'Should not be called'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -25,12 +25,19 @@ DiyaBaseObject >> stderr [
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaBaseObject >> stderror: string [
|
||||
self stderr nextPutAll: string; nextPutAll: Character cr asString.
|
||||
self stderr
|
||||
nextPutAll: DateAndTime now asString;
|
||||
nextPutAll: ': ';
|
||||
nextPutAll: string;
|
||||
nextPutAll: Character cr asString.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaBaseObject >> stdlog: string [
|
||||
self stdout nextPutAll: string;
|
||||
self stdout
|
||||
nextPutAll: DateAndTime now asString;
|
||||
nextPutAll: ': ';
|
||||
nextPutAll: string;
|
||||
nextPutAll: Character cr asString.
|
||||
]
|
||||
|
||||
|
@ -2,7 +2,6 @@ Class {
|
||||
#name : #DiyaBoot,
|
||||
#superclass : #DiyaSingleton,
|
||||
#instVars : [
|
||||
'running',
|
||||
'window',
|
||||
'context',
|
||||
'display',
|
||||
@ -17,6 +16,11 @@ Class {
|
||||
#category : #'Diya-Runtime'
|
||||
}
|
||||
|
||||
{ #category : #'class initialization' }
|
||||
DiyaBoot class >> initialize [
|
||||
Smalltalk globals at: #DiyaDisplay put: nil
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaBoot class >> maxFPS [
|
||||
^60
|
||||
@ -41,7 +45,7 @@ DiyaBoot >> GLinit. [
|
||||
{ #category : #events }
|
||||
DiyaBoot >> createGLContext [
|
||||
context := SDL2 glCreateContext: window.
|
||||
context ifNil: [ ^self error: SDL2 getErrorMessage ].
|
||||
context ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
|
||||
^context
|
||||
|
||||
]
|
||||
@ -60,7 +64,7 @@ DiyaBoot >> createWindow [
|
||||
width: display w
|
||||
height: display h
|
||||
flags: SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL.
|
||||
window ifNil: [ ^self error: SDL2 getErrorMessage ].
|
||||
window ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
|
||||
"handle fullscreen: SDL_WINDOW_FULLSCREEN."
|
||||
"SDL2 glSetAttribute: SDL_GL_CONTEXT_PROFILE_MASK value: SDL_GL_CONTEXT_PROFILE_ES.
|
||||
SDL2 glSetAttribute: SDL_GL_CONTEXT_MAJOR_VERSION value: 2.
|
||||
@ -72,130 +76,66 @@ DiyaBoot >> createWindow [
|
||||
^window
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> exampleNodes [
|
||||
|root node style tex|
|
||||
root := DiyaRootNode new.
|
||||
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
|
||||
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
|
||||
node texture: tex.
|
||||
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
|
||||
node borderColor: Color red.
|
||||
node borderWidth: 3.0.
|
||||
|
||||
style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'.
|
||||
"style := DiyaFontManager uniqueInstance style: 'Regular' from: 'bootstrap-icons'."
|
||||
node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
|
||||
node color: (Color orange).
|
||||
node texture: (style textureOf: 48).
|
||||
node borderColor: Color red.
|
||||
node borderWidth: 3.0.
|
||||
|
||||
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
|
||||
node rotation: (Float pi / -8.0).
|
||||
node scale: 1.5@1.5.
|
||||
|
||||
node := root addNode: (DiyaText data: String loremIpsum) at: 10@340.
|
||||
node extent: 250@320.
|
||||
node wordWrap: true.
|
||||
|
||||
node := root addNode: (DiyaLine from: 10@620 to: 200@635).
|
||||
node color: (Color red).
|
||||
node borderWidth: 2.0.
|
||||
|
||||
|
||||
node := root addNode: (DiyaCircle r: 100) at: 200@200.
|
||||
node borderColor: Color red.
|
||||
node color: Color white.
|
||||
node borderWidth: 3.0.
|
||||
node texture: tex.
|
||||
|
||||
|
||||
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}).
|
||||
node color: Color green.
|
||||
node borderColor: Color red.
|
||||
node texture: tex.
|
||||
node borderWidth: 3.0.
|
||||
^ root
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> init [
|
||||
| status |
|
||||
SDL2 setHint: 'SDL_RENDER_DRIVER' value: 'opengles2'.
|
||||
status := SDL2 init: SDL_INIT_EVERYTHING.
|
||||
status = 0
|
||||
ifFalse: [ ^ self error: SDL2 getErrorMessage ].
|
||||
ifFalse: [ ^ DiyaCoreAPIError signal: SDL2 getErrorMessage ].
|
||||
display := SDL_DisplayMode externalNew autoRelease.
|
||||
SDL2 SDLGetCurrentDisplayMode: display from:0.
|
||||
DiyaRendererContext reset.
|
||||
DiyaFontManager reset.
|
||||
OpenGLSL resetShaders.
|
||||
SDL2 showCursor: 0.
|
||||
Smalltalk globals at: #Display ifAbsentPut:display.
|
||||
Smalltalk globals at: #DiyaDisplay put:display.
|
||||
DiyaSingleton resetAll.
|
||||
DiyaFontManager uniqueInstance loadFonts.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> initialize [
|
||||
running := true.
|
||||
display := nil.
|
||||
window := nil.
|
||||
context := nil.
|
||||
clock := DiyaClock uniqueInstance.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> processEvent: event [
|
||||
|mappedEvt|
|
||||
mappedEvt := event mapped.
|
||||
mappedEvt type = SDL_KEYDOWN ifTrue: [ Transcript show: 'keydown...';cr. ^running := false. ].
|
||||
mappedEvt type = SDL_QUIT ifTrue:[ ^running:= false ].
|
||||
mappedEvt type = SDL_FINGERDOWN ifTrue:[^self setCursorPosition: mappedEvt ].
|
||||
mappedEvt type = SDL_FINGERMOTION ifTrue:[^self setCursorPosition: mappedEvt ].
|
||||
mappedEvt type = SDL_MOUSEMOTION ifTrue:[DiyaRendererContext uniqueInstance mouse: (mappedEvt x) @ (mappedEvt y)].
|
||||
mappedEvt free.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> randomColorChannel [
|
||||
| rand |
|
||||
rand := Random new.
|
||||
rand := (rand next) * 255.
|
||||
rand := rand asInteger.
|
||||
^ rand
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> render [
|
||||
|event root text delta fps|
|
||||
event := SDL_Event new.
|
||||
root := self exampleNodes.
|
||||
DiyaRenderer uniqueInstance root: root.
|
||||
text := root addNode:(DiyaText data: 'tick') at: (display w - 80)@40.
|
||||
text extent: 80@40.
|
||||
text fontSize: 18.
|
||||
text color: Color red.
|
||||
|launcher|
|
||||
DiyaRendererContext uniqueInstance.
|
||||
launcher := DiyaApplicationLauncher uniqueInstance.
|
||||
launcher setup.
|
||||
self GLinit.
|
||||
[ running ] whileTrue: [
|
||||
delta := DiyaClock uniqueInstance delta asMilliSeconds.
|
||||
fps := ((1000/delta) asInteger).
|
||||
text data: ('FPS:', fps asString).
|
||||
[ launcher running ] whileTrue: [
|
||||
DiyaClock uniqueInstance tick.
|
||||
[(SDL2 pollEvent: event) > 0] whileTrue: [
|
||||
self processEvent: event
|
||||
].
|
||||
DiyaRenderer uniqueInstance render.
|
||||
|
||||
launcher main.
|
||||
SDL2 glSwapWindow: window.
|
||||
delta := DiyaClock uniqueInstance delta asMilliSeconds.
|
||||
SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta).
|
||||
SDL2 delay:
|
||||
(0 max:
|
||||
(1000/ self class maxFPS) asInteger - (DiyaClock uniqueInstance lapDelta asMilliSeconds)).
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> run [
|
||||
self init.
|
||||
self startx.
|
||||
|envar arr|
|
||||
envar := Smalltalk getenv:'DIYA_RES'.
|
||||
arr := nil.
|
||||
envar ifNotNil: [
|
||||
arr := (envar splitOn: 'x') collect: [ :e| e asInteger ] .
|
||||
arr size = 2 ifFalse:[
|
||||
arr := nil.
|
||||
]
|
||||
].
|
||||
arr
|
||||
ifNil: [
|
||||
self init.
|
||||
self startx.
|
||||
]
|
||||
ifNotNil: [
|
||||
self run: (arr at:1) @ (arr at: 2)
|
||||
]
|
||||
]
|
||||
|
||||
{ #category : #running }
|
||||
@ -223,12 +163,6 @@ DiyaBoot >> run: screenSize app: application [
|
||||
Smalltalk garbageCollect.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> setCursorPosition: mappedEvt [
|
||||
window warpMouseX:((mappedEvt x)* (display w) )
|
||||
Y: ((mappedEvt y) * (display h))
|
||||
]
|
||||
|
||||
{ #category : #logging }
|
||||
DiyaBoot >> showSystemInfo [
|
||||
|stream numdriver rinfo|
|
||||
@ -253,43 +187,27 @@ DiyaBoot >> showSystemInfo [
|
||||
stream nextPutAll: rinfo name readString; nextPutAll:' '.
|
||||
].
|
||||
stream cr.
|
||||
stream nextPutAll:'Display resolution: ';
|
||||
nextPutAll:display w asString;
|
||||
nextPutAll: 'x';
|
||||
nextPutAll: display h asString; cr.
|
||||
stream nextPutAll: DiyaDisplay asString; cr.
|
||||
stream cr.
|
||||
self stdout nextPutAll: stream contents
|
||||
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> startx [
|
||||
display ifNil: [ ^self error: 'Please run #init before this method' ].
|
||||
display ifNil: [ ^DiyaCoreAPIError signal: 'Please run #init before this method' ].
|
||||
self createWindow.
|
||||
self createGLContext.
|
||||
"SDL2 glMakeCurrent: window context: context."
|
||||
self showSystemInfo.
|
||||
DiyaRendererContext
|
||||
uniqueInstance display: display;
|
||||
useProjection: OrthoProjectionMatrix.
|
||||
uniqueInstance
|
||||
display: display;
|
||||
window: window;
|
||||
useProjection: OrthoProjectionMatrix.
|
||||
self render.
|
||||
context delete.
|
||||
window destroy.
|
||||
DiyaFontManager reset.
|
||||
DiyaRendererContext reset.
|
||||
DiyaSingleton resetAll.
|
||||
SDL2 quit.
|
||||
]
|
||||
|
||||
{ #category : #events }
|
||||
DiyaBoot >> step [
|
||||
"renderer drawColorR: 0
|
||||
g: 0
|
||||
b: 0
|
||||
a: 255."
|
||||
OpenGL begin: GL_TRIANGLES.
|
||||
"draw a simple triangle here"
|
||||
OpenGL color3fR: 0.1 G:0.2 B: 0.3.
|
||||
OpenGL vertex3fX: 0 Y: 0 Z: 0.
|
||||
OpenGL vertex3fX: 1 Y: 0 Z: 0.
|
||||
OpenGL vertex3fX: 0 Y: 1 Z: 0.
|
||||
OpenGL end.
|
||||
]
|
||||
|
@ -1,5 +1,51 @@
|
||||
Class {
|
||||
#name : #DiyaButton,
|
||||
#superclass : #DiyaWidget,
|
||||
#instVars : [
|
||||
'label',
|
||||
'rec'
|
||||
],
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton class >> text: string [
|
||||
^ self new text: string; yourself
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton >> icon: ico [
|
||||
label icon: ico.
|
||||
label setDirty.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton >> iconSize: size [
|
||||
label iconSize: size.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaButton >> initialize [
|
||||
super initialize.
|
||||
rec := self addNode: (DiyaRectangle new).
|
||||
label := self addNode: (DiyaLabel new).
|
||||
label txt
|
||||
wordWrap: false.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton >> label [
|
||||
^ label
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton >> process [
|
||||
rec extent: self extent.
|
||||
label extent: self extent.
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaButton >> text: string [
|
||||
label txt: string.
|
||||
]
|
||||
|
@ -3,14 +3,15 @@ Class {
|
||||
#superclass : #DiyaSingleton,
|
||||
#instVars : [
|
||||
'monotonic',
|
||||
'lastTick'
|
||||
'lastTick',
|
||||
'lapTime'
|
||||
],
|
||||
#category : #'Diya-Runtime'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaClock >> delta [
|
||||
^(DateAndTime now) - lastTick
|
||||
^ self lapDelta + self lapTime
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -22,9 +23,21 @@ DiyaClock >> elapsedTime [
|
||||
DiyaClock >> initialize [
|
||||
monotonic := DateAndTime now.
|
||||
lastTick := monotonic.
|
||||
lapTime := 0 asDuration.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaClock >> lapDelta [
|
||||
^ ((DateAndTime now) - lastTick)
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaClock >> lapTime [
|
||||
^ lapTime
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaClock >> tick [
|
||||
lapTime := (DateAndTime now) - lastTick.
|
||||
lastTick := DateAndTime now.
|
||||
]
|
||||
|
22
Diya/DiyaCompositeNode.class.st
Normal file
22
Diya/DiyaCompositeNode.class.st
Normal 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 [
|
||||
|
||||
|
||||
]
|
@ -11,7 +11,7 @@ DiyaConvexPolygon >> calculateVertices [
|
||||
vbuffer ifNotNil: [ vbuffer free ].
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size:size.
|
||||
vbuffer autoRelease.
|
||||
points sort:[:a :b| a angle < b angle].
|
||||
points sort:[:a :b| a angle > b angle].
|
||||
index := 1.
|
||||
points do:[:point|
|
||||
texcoord := self texcoordOf: point.
|
||||
@ -19,7 +19,7 @@ DiyaConvexPolygon >> calculateVertices [
|
||||
at: index put: point x;
|
||||
at: index + 1 put: point y;
|
||||
at: index + 2 put: texcoord x;
|
||||
at: index + 3 put: 1.0 - texcoord y.
|
||||
at: index + 3 put: texcoord y.
|
||||
index := index + 4.
|
||||
].
|
||||
p := points at: 2.
|
||||
@ -28,12 +28,12 @@ DiyaConvexPolygon >> calculateVertices [
|
||||
at: index put: p x;
|
||||
at: index + 1 put: p y;
|
||||
at: index + 2 put: texcoord x;
|
||||
at: index + 3 put: 1.0 - texcoord y.
|
||||
at: index + 3 put: texcoord y.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaConvexPolygon >> drawLines [
|
||||
OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2) - 1.
|
||||
OpenGL drawArrays: GL_LINE_LOOP first:voffset count: (vbuffer size >> 2) - 1.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
|
5
Diya/DiyaCoreAPIError.class.st
Normal file
5
Diya/DiyaCoreAPIError.class.st
Normal file
@ -0,0 +1,5 @@
|
||||
Class {
|
||||
#name : #DiyaCoreAPIError,
|
||||
#superclass : #DiyaError,
|
||||
#category : #'Diya-Events'
|
||||
}
|
41
Diya/DiyaDefaultTheme.class.st
Normal file
41
Diya/DiyaDefaultTheme.class.st
Normal file
@ -0,0 +1,41 @@
|
||||
Class {
|
||||
#name : #DiyaDefaultTheme,
|
||||
#superclass : #DiyaStyleSheet,
|
||||
#category : #'Diya-UIThemes'
|
||||
}
|
||||
|
||||
{ #category : #define }
|
||||
DiyaDefaultTheme >> defineGlobal [
|
||||
self define: #global styles: {
|
||||
#bgColor -> (Color r: 0.2118 g: 0.2118 b: 0.2118).
|
||||
#color -> Color white.
|
||||
#border -> 0.
|
||||
#fontSize -> 18.
|
||||
#fontFamily -> DiyaFontManager uniqueInstance defaultFamily.
|
||||
#textIconFamily -> 'bootstrap-icons'.
|
||||
#fontStyle -> DiyaFontManager uniqueInstance defaultStyle.
|
||||
#borderColor -> Color transparent.
|
||||
#xAlign -> #left.
|
||||
#yAlign -> #middle.
|
||||
#iconSize -> 24.
|
||||
}
|
||||
]
|
||||
|
||||
{ #category : #define }
|
||||
DiyaDefaultTheme >> defineLoadingBar [
|
||||
self define: #loadingBar styles: {
|
||||
#bgColor -> Color red.
|
||||
#border -> 1.
|
||||
#borderColor -> Color white.
|
||||
};
|
||||
define: #loadingProgress styles: {
|
||||
#bgColor -> Color white.
|
||||
}
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaDefaultTheme >> initialize [
|
||||
super initialize.
|
||||
self defineGlobal.
|
||||
self defineLoadingBar.
|
||||
]
|
@ -24,18 +24,13 @@ DiyaEllipse class >> rx: rx ry: ry shader: s [
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEllipse >> draw [
|
||||
OpenGL
|
||||
enable: GL_BLEND;
|
||||
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
|
||||
super draw.
|
||||
OpenGL
|
||||
disable: GL_BLEND
|
||||
DiyaEllipse >> drawBorder [
|
||||
"do nothing"
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEllipse >> drawBorder [
|
||||
"do nothing"
|
||||
DiyaEllipse >> drawLines [
|
||||
self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -47,6 +42,28 @@ DiyaEllipse >> initialize [
|
||||
shader := DiyaEllipseShader uniqueInstance.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEllipse >> inner: aPoint [
|
||||
|dxy|
|
||||
dxy := self local: aPoint.
|
||||
^ ((((dxy x) ** 2)/(rx**2)) + (((dxy y) ** 2) / (ry**2))) < 1.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEllipse >> process [
|
||||
bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
|
||||
{
|
||||
bbox origin x. bbox origin y. 0.0. 0.0.
|
||||
bbox origin x. bbox corner y. 0.0. 1.0.
|
||||
bbox corner x. bbox corner y. 1.0. 1.0.
|
||||
|
||||
bbox corner x. bbox corner y. 1.0. 1.0.
|
||||
bbox corner x. bbox origin y. 1.0. 0.0.
|
||||
bbox origin x. bbox origin y. 0.0. 0.0.
|
||||
} doWithIndex: [:e :i| vbuffer at: i put: e].
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEllipse >> rx [
|
||||
^ rx
|
||||
@ -55,7 +72,7 @@ DiyaEllipse >> rx [
|
||||
{ #category : #accessing }
|
||||
DiyaEllipse >> rx: anObject [
|
||||
rx := anObject.
|
||||
dirty := true.
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -66,30 +83,15 @@ DiyaEllipse >> ry [
|
||||
{ #category : #accessing }
|
||||
DiyaEllipse >> ry: anObject [
|
||||
ry := anObject.
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEllipse >> setUpShader [
|
||||
super setUpShader.
|
||||
self shader
|
||||
setUniform: #u_border value: border;
|
||||
setUniform: #u_border_color value: bcolor asGL4FArray;
|
||||
setUniform: #u_rx value: rx;
|
||||
setUniform: #u_ry value: ry.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEllipse >> update [
|
||||
bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
|
||||
{
|
||||
bbox origin x. bbox corner y. 0.0. 0.0.
|
||||
bbox origin x. bbox origin y. 0.0. 1.0.
|
||||
bbox corner x. bbox origin y. 1.0. 1.0.
|
||||
|
||||
bbox corner x. bbox origin y. 1.0. 1.0.
|
||||
bbox corner x. bbox corner y. 1.0. 0.0.
|
||||
bbox origin x. bbox corner y. 0.0. 0.0.
|
||||
} doWithIndex: [:e :i| vbuffer at: i put: e].
|
||||
^true
|
||||
setUniform: #u_border value: (self ? #border);
|
||||
setUniform: #u_border_color value: ( self ? #borderColor) asGL4FArray;
|
||||
setUniform: #u_rx value: (rx * (scale x)) ;
|
||||
setUniform: #u_ry value: (ry * (scale y)) .
|
||||
]
|
||||
|
@ -89,8 +89,8 @@ void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border)
|
||||
|
||||
vec2 rotate_point(vec2 center, vec2 p,float angle)
|
||||
{
|
||||
float s = sin(angle);
|
||||
float c = cos(angle);
|
||||
float s = sin(-angle);
|
||||
float c = cos(-angle);
|
||||
|
||||
// translate point back to origin:
|
||||
p.x -= center.x;
|
||||
@ -110,7 +110,7 @@ void main() {
|
||||
vec4 color = vec4(0);
|
||||
//defining ellipse
|
||||
Ellipse e = create_ellipse(middle, u_ry, u_rx);
|
||||
draw_ellipse(color, rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border);
|
||||
draw_ellipse(color,rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border);
|
||||
// Output to screen
|
||||
gl_FragColor = color;
|
||||
}
|
||||
@ -125,6 +125,7 @@ precision mediump float;
|
||||
#endif
|
||||
uniform mat4 u_projection;
|
||||
uniform mat3 u_transform;
|
||||
uniform vec2 u_resolution;
|
||||
varying float rotation;
|
||||
varying vec2 middle;
|
||||
varying vec2 texcoord;
|
||||
@ -133,7 +134,8 @@ void main()
|
||||
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
|
||||
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
|
||||
rotation = atan(u_transform[1][0], u_transform[0][0]);
|
||||
middle = (u_transform * vec3(0.0,0.0,1.0)).xy;
|
||||
vec2 org = (u_transform * vec3(0.0,0.0,1.0)).xy;
|
||||
middle = vec2(org.x, u_resolution.y - org.y);
|
||||
texcoord = gl_Vertex.zw;
|
||||
}'
|
||||
]
|
||||
|
5
Diya/DiyaError.class.st
Normal file
5
Diya/DiyaError.class.st
Normal file
@ -0,0 +1,5 @@
|
||||
Class {
|
||||
#name : #DiyaError,
|
||||
#superclass : #Error,
|
||||
#category : #'Diya-Events'
|
||||
}
|
51
Diya/DiyaEvent.class.st
Normal file
51
Diya/DiyaEvent.class.st
Normal file
@ -0,0 +1,51 @@
|
||||
Class {
|
||||
#name : #DiyaEvent,
|
||||
#superclass : #DiyaBaseObject,
|
||||
#instVars : [
|
||||
'enable',
|
||||
'mapped',
|
||||
'target'
|
||||
],
|
||||
#category : #'Diya-Events'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaEvent class >> from: mappedEvt [
|
||||
^ self new mapped: mappedEvt; yourself
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEvent >> enable [
|
||||
^ enable
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEvent >> initialize [
|
||||
super initialize.
|
||||
enable := true.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEvent >> mapped [
|
||||
^ mapped
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEvent >> mapped: anObject [
|
||||
mapped := anObject
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaEvent >> preventDefault [
|
||||
enable := false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEvent >> target [
|
||||
^ target
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaEvent >> target: anObject [
|
||||
target := anObject
|
||||
]
|
170
Diya/DiyaExampleApp.class.st
Normal file
170
Diya/DiyaExampleApp.class.st
Normal file
@ -0,0 +1,170 @@
|
||||
Class {
|
||||
#name : #DiyaExampleApp,
|
||||
#superclass : #DiyaBaseApplication,
|
||||
#category : #'Diya-Applications'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaExampleApp >> cleanup [
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaExampleApp >> defineStyleSheet [
|
||||
|fmgr style|
|
||||
fmgr := DiyaFontManager uniqueInstance.
|
||||
#(16 24) do:[:fontSize|
|
||||
self stdlog: 'Init font size ', fontSize asString, ' of ', fmgr defaultFamily.
|
||||
style := fmgr style: fmgr defaultStyle from: fmgr defaultFamily.
|
||||
style textureOf: fontSize.
|
||||
].
|
||||
DiyaUIThemesManager uniqueInstance currentTheme
|
||||
define: #text_icon_1 styles: {
|
||||
#color -> Color orange.
|
||||
#fontSize -> 24.
|
||||
#bgColor -> Color transparent.
|
||||
};
|
||||
define: #text_icon_2 extend:#text_icon_1 styles: {
|
||||
#fontSize -> 16.
|
||||
};
|
||||
define: #image_view styles: {
|
||||
#color -> Color white.
|
||||
#border -> 1.
|
||||
#bgColor -> Color cyan.
|
||||
#borderColor -> Color red
|
||||
};
|
||||
define: #rect_view extend: #image_view styles: {
|
||||
#bgColor -> Color transparent.
|
||||
};
|
||||
define: #text_view styles: {
|
||||
#color -> Color orange.
|
||||
#fontSize -> 16.
|
||||
#bgColor -> Color transparent.
|
||||
#xAlign -> #center
|
||||
};
|
||||
define: #line_view styles: {
|
||||
#color -> Color red.
|
||||
#border -> 4
|
||||
};
|
||||
define: #ell_view styles: {
|
||||
#borderColor -> Color red.
|
||||
#color -> Color white.
|
||||
#border -> 2.
|
||||
};
|
||||
define: #poly_view styles: {
|
||||
#borderColor -> Color red.
|
||||
#color -> Color green.
|
||||
#border -> 1.
|
||||
#bgColor -> Color transparent.
|
||||
};
|
||||
define: #button_view styles: {
|
||||
#borderColor -> (Color r: 0.051 g: 0.051 b: 0.051).
|
||||
#color -> Color white.
|
||||
#bgColor -> (Color r: 0.1529 g: 0.1529 b: 0.1529).
|
||||
#border -> 1.
|
||||
#yAlign -> #middle.
|
||||
#xAlign -> #center
|
||||
}
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaExampleApp >> main [
|
||||
|
||||
]
|
||||
|
||||
{ #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.
|
||||
|
||||
"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.
|
||||
DiyaRendererContext uniqueInstance 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
|
||||
]
|
@ -22,11 +22,13 @@ DiyaFFIBase class >> libNames [
|
||||
{ #category : #accessing }
|
||||
DiyaFFIBase class >> moduleName [
|
||||
self libNames do:[:aName|
|
||||
(ExternalAddress loadSymbol: self checkSymbol from: aName) ifNotNil: [
|
||||
^ aName
|
||||
].
|
||||
[
|
||||
(ExternalAddress loadSymbol: self checkSymbol from: aName) ifNotNil: [
|
||||
^ aName
|
||||
]
|
||||
] on: Error do: [ ]
|
||||
].
|
||||
self error: 'Unable to find FFI library (', self checkSymbol, ')'.
|
||||
DiyaFFILibNotFound signal: 'Unable to find FFI library (', self checkSymbol, ')'.
|
||||
]
|
||||
|
||||
{ #category : #'library path' }
|
||||
|
5
Diya/DiyaFFILibNotFound.class.st
Normal file
5
Diya/DiyaFFILibNotFound.class.st
Normal file
@ -0,0 +1,5 @@
|
||||
Class {
|
||||
#name : #DiyaFFILibNotFound,
|
||||
#superclass : #DiyaError,
|
||||
#category : #'Diya-Events'
|
||||
}
|
@ -4,7 +4,7 @@ Class {
|
||||
#instVars : [
|
||||
'advance',
|
||||
'bearing',
|
||||
'texcoord'
|
||||
'tex'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
@ -34,11 +34,16 @@ DiyaFontGlyph >> bearing: anObject [
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontGlyph >> texcoord [
|
||||
^ texcoord
|
||||
DiyaFontGlyph >> tex [
|
||||
^ tex
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontGlyph >> texcoord: anObject [
|
||||
texcoord := anObject
|
||||
DiyaFontGlyph >> tex: anObject [
|
||||
tex := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontGlyph >> texcoord [
|
||||
^ (Rectangle origin: (self origin/ (tex extent) ) asFloatPoint corner: ((self corner) / (tex extent)) asFloatPoint ).
|
||||
]
|
||||
|
66
Diya/DiyaFontIcon.class.st
Normal file
66
Diya/DiyaFontIcon.class.st
Normal file
@ -0,0 +1,66 @@
|
||||
Class {
|
||||
#name : #DiyaFontIcon,
|
||||
#superclass : #DiyaText,
|
||||
#pools : [
|
||||
'FT2Types'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> data: code [
|
||||
super data:(code isArray ifTrue: [ code ] ifFalse:[{code}]).
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> drawText [
|
||||
|index offset tex glyph |
|
||||
index := 1.
|
||||
tex := self texture.
|
||||
offset := (self alignLine: self fontSize)@(self valignText: self fontSize).
|
||||
data do: [ :c|
|
||||
glyph := tex getGlyph: c asInteger.
|
||||
(self getCharsVerticesFrom: glyph offset: offset cellh: tex cellh) do: [
|
||||
:e| vbuffer at: index put:e.
|
||||
index := index + 1
|
||||
].
|
||||
"offset setX: offset x + tex spacing setY: offset y"
|
||||
].
|
||||
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontIcon >> fontName [
|
||||
^ self ? #textIconFamily
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> getLinebreakIndices: delta [
|
||||
self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaFontIcon >> iconSize [
|
||||
^ self fontSize
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> initialize [
|
||||
super initialize.
|
||||
data := { }.
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
|
||||
vbuffer autoRelease.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> lastSeparatorFrom: i [
|
||||
self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontIcon >> process [
|
||||
data ifNil: [ ^self ].
|
||||
bbox := Rectangle origin: 0@0 corner: ((data size) * (self fontSize) ) @ self fontSize.
|
||||
^ super process.
|
||||
]
|
@ -22,7 +22,19 @@ DiyaFontManager class >> searchPaths [
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontManager >> defaultFamily [
|
||||
^self error: 'No font found'
|
||||
^'Ubuntu'
|
||||
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontManager >> defaultIconSet [
|
||||
^ self style: 'Regular' from: 'bootstrap-icons'
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaFontManager >> defaultStyle [
|
||||
^'Regular'
|
||||
|
||||
|
||||
]
|
||||
@ -62,11 +74,11 @@ DiyaFontManager >> loadFile: aFile [
|
||||
index: i.
|
||||
face newFaceFromFile: path index: i.
|
||||
face loadFields.
|
||||
Transcript show: 'Loaded font face ', face styleName;cr.
|
||||
self stdlog: 'Loaded font face ', face styleName.
|
||||
numfaces ifNil: [ numfaces := face numFaces ].
|
||||
self loadFace: face.
|
||||
i := i + 1.
|
||||
i < numfaces ] whileTrue: [ ]
|
||||
i < numfaces ] whileTrue
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -97,7 +109,7 @@ DiyaFontManager >> reset [
|
||||
{ #category : #initialization }
|
||||
DiyaFontManager >> style: styleName from: familyName [
|
||||
|family|
|
||||
family := families at: familyName ifAbsent: [ self defaultFamily ].
|
||||
family := families at: familyName ifAbsent: [ families at: self defaultFamily ].
|
||||
^family style: styleName
|
||||
|
||||
]
|
||||
|
@ -1,5 +0,0 @@
|
||||
Class {
|
||||
#name : #DiyaIcon,
|
||||
#superclass : #DiyaImageView,
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
28
Diya/DiyaImageIcon.class.st
Normal file
28
Diya/DiyaImageIcon.class.st
Normal file
@ -0,0 +1,28 @@
|
||||
Class {
|
||||
#name : #DiyaImageIcon,
|
||||
#superclass : #DiyaImageView,
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageIcon >> borderWidth [
|
||||
^0
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageIcon >> iconSize [
|
||||
^ self ? #iconSize
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageIcon >> initialize [
|
||||
super initialize.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageIcon >> process [
|
||||
|v|
|
||||
v := self iconSize.
|
||||
self extent: (v@v).
|
||||
^super process
|
||||
]
|
@ -1,6 +1,9 @@
|
||||
Class {
|
||||
#name : #DiyaImageTex,
|
||||
#superclass : #OpenGLTexImage2D,
|
||||
#instVars : [
|
||||
'name'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
'OpenGLTypes'
|
||||
@ -8,6 +11,16 @@ Class {
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex class >> fromDisplay: aRect as: assetName [
|
||||
^ self new fromDisplay: aRect as: assetName; yourself
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex class >> fromDisplayAs: assetName [
|
||||
^ self new fromDisplayAs: assetName; yourself
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex class >> fromFile: path [
|
||||
^ self new fromFile: path; yourself
|
||||
@ -15,34 +28,84 @@ DiyaImageTex class >> fromFile: path [
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageTex >> drop [
|
||||
OpenGL
|
||||
"OpenGL
|
||||
disable: GL_CULL_FACE;
|
||||
disable: GL_BLEND.
|
||||
disable: GL_BLEND."
|
||||
]
|
||||
|
||||
{ #category : #conversion }
|
||||
DiyaImageTex >> flipY [
|
||||
|buffer size linesize top bottom|
|
||||
size := self bytesSize.
|
||||
linesize := width << 2.
|
||||
buffer := FFIExternalArray externalNewType: GLubyte size: linesize.
|
||||
LibC memset: buffer getHandle value: 0 size: buffer size.
|
||||
0 to: (height >> 1) -1 do: [ :line|
|
||||
top := line * linesize.
|
||||
bottom := (size - (linesize * (line + 1))).
|
||||
LibC memCopy: (data getHandle) + top to: buffer getHandle size: linesize.
|
||||
LibC memCopy: (data getHandle) + bottom to: (data getHandle) + top size: linesize.
|
||||
LibC memCopy: buffer getHandle to: (data getHandle) + bottom size: linesize.
|
||||
].
|
||||
buffer free
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex >> fromFile: path [
|
||||
|form color index|
|
||||
Transcript show: 'Loading texture from ', path fullName;cr.
|
||||
form := ImageReadWriter formFromFileNamed: path.
|
||||
data := FFIExternalArray externalNewType: GLubyte size:(form width) * (form height) * 4.
|
||||
DiyaImageTex >> fromDisplay: aRect as: assetName [
|
||||
data ifNotNil: [data free].
|
||||
width := aRect extent x asInteger.
|
||||
height := aRect extent y asInteger.
|
||||
data := FFIExternalArray externalNewType: GLubyte size: self bytesSize.
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
data autoRelease.
|
||||
width := form width.
|
||||
height := form height.
|
||||
index := 1.
|
||||
0 to: height -1 do:[:y|
|
||||
0 to: width - 1 do:[:x|
|
||||
color := (form colorAt: x@y) as4bytesRGB.
|
||||
data
|
||||
at: index put: color first;
|
||||
at: index + 1 put: (color at: 2);
|
||||
at: index +2 put: (color at: 3);
|
||||
at: index + 3 put: color last.
|
||||
index := index + 4.
|
||||
]
|
||||
].
|
||||
|
||||
OpenGL readPixelsOn: data getHandle
|
||||
x: aRect origin x
|
||||
y: (DiyaDisplay height) - (aRect origin y) - (aRect extent y)
|
||||
w: aRect extent x
|
||||
h: aRect extent y
|
||||
format:GL_RGBA
|
||||
type: GL_UNSIGNED_BYTE.
|
||||
name := assetName.
|
||||
self flipY.
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex >> fromDisplayAs: assetName [
|
||||
self fromDisplay: (Rectangle origin: 0@0 extent: DiyaDisplay extent ) as: assetName
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex >> fromFile: aPath [
|
||||
|surface|
|
||||
self stdlog: 'Loading texture from ', aPath fullName.
|
||||
data ifNotNil: [ data free ].
|
||||
name := aPath fullName.
|
||||
surface := self surfaceFromFile: aPath.
|
||||
width := surface w.
|
||||
height := surface h.
|
||||
data := FFIExternalArray externalNewType: GLubyte size: self bytesSize.
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
data autoRelease.
|
||||
LibC memCopy: surface pixels getHandle to: data getHandle size: data size.
|
||||
SDL2
|
||||
freeSurface: surface.
|
||||
self stdlog: 'Loaded ', aPath fullName.
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageTex >> fromForm: aForm name: aName [
|
||||
|surface|
|
||||
name := aName.
|
||||
data ifNotNil: [ data free ].
|
||||
surface := self surfaceFromForm: aForm.
|
||||
width := surface w.
|
||||
height := surface h.
|
||||
data := FFIExternalArray externalNewType: GLubyte size: self bytesSize.
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
data autoRelease.
|
||||
LibC memCopy: surface pixels getHandle to: data getHandle size: data size.
|
||||
SDL2
|
||||
freeSurface: surface.
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
@ -61,15 +124,50 @@ DiyaImageTex >> mipmap [
|
||||
^false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageTex >> name [
|
||||
^ name
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaImageTex >> setup [
|
||||
OpenGL
|
||||
enable: GL_CULL_FACE;
|
||||
enable: GL_BLEND;
|
||||
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
|
||||
OpenGLTexture
|
||||
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE;
|
||||
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE;
|
||||
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR;
|
||||
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
|
||||
]
|
||||
|
||||
{ #category : #conversion }
|
||||
DiyaImageTex >> surfaceFromFile: aPath [
|
||||
aPath exists ifFalse: [ ^DiyaCoreAPIError signal:'File not found ', aPath fullName ].
|
||||
[^ SDL2Image SDLImgLoad: aPath fullName] on: Error do: [
|
||||
^ self surfaceFromForm: (ImageReadWriter formFromFileNamed: aPath)
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #conversion }
|
||||
DiyaImageTex >> surfaceFromForm: aForm [
|
||||
|srcSurface destSurface form|
|
||||
form := aForm asFormOfDepth: 32.
|
||||
srcSurface :=
|
||||
SDL2 createRGBSurfaceFromPixels: form bits
|
||||
width: form width height: form height
|
||||
depth: 32 pitch: (form width << 2)
|
||||
rmask: 16r00ff0000
|
||||
gmask: 16r000ff00
|
||||
bmask: 16r00000ff
|
||||
amask: 16rff000000.
|
||||
destSurface :=
|
||||
SDL2 createRGBSurfaceFromPixels: srcSurface pixels getHandle
|
||||
width: form width height: form height
|
||||
depth: 32 pitch: (form width << 2)
|
||||
rmask: 16r000000ff
|
||||
gmask: 16r0000ff00
|
||||
bmask: 16r00ff0000
|
||||
amask: 16rff000000.
|
||||
SDL2 SDLBlitSurface: srcSurface srcRect: nil dest: destSurface dstRect: nil.
|
||||
SDL2
|
||||
freeSurface: srcSurface.
|
||||
^ destSurface
|
||||
]
|
||||
|
@ -1,5 +1,16 @@
|
||||
Class {
|
||||
#name : #DiyaImageView,
|
||||
#superclass : #DiyaRectangle,
|
||||
#category : #'Diya-Widgets'
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageView class >> from: assetName [
|
||||
^self new from: assetName ; yourself
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaImageView >> from: name [
|
||||
texture := context assets texture: name.
|
||||
self extent: texture extent
|
||||
]
|
||||
|
@ -1,5 +1,85 @@
|
||||
Class {
|
||||
#name : #DiyaLabel,
|
||||
#superclass : #DiyaWidget,
|
||||
#instVars : [
|
||||
'txt',
|
||||
'icon'
|
||||
],
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> fontSize [
|
||||
^txt fontSize.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> getHAlign: offset [
|
||||
^ 0 max: (txt alignLine: ( txt maxLineWidth)).
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> icon [
|
||||
^ icon
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> icon: anObject [
|
||||
icon := nil.
|
||||
anObject isNumber ifTrue: [
|
||||
icon := self addNode: (DiyaFontIcon data: anObject).].
|
||||
anObject isString ifTrue: [
|
||||
icon := self addNode: (DiyaImageIcon from: anObject).
|
||||
].
|
||||
icon ifNil: [ icon := self addNode: anObject ].
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> iconSize [
|
||||
icon ifNil: [ ^0 ].
|
||||
^ icon iconSize
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaLabel >> initialize [
|
||||
super initialize.
|
||||
txt := self addNode:(DiyaText data: '').
|
||||
icon := nil.
|
||||
self extent: 0@0.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> process [
|
||||
|offset isize align|
|
||||
offset := 0.
|
||||
icon ifNotNil: [
|
||||
isize := self iconSize.
|
||||
offset := isize + (isize >> 2).
|
||||
"icon extent:offset @ (extent y)."
|
||||
].
|
||||
txt extent: (extent x - offset) @ (extent y).
|
||||
"lookahead update"
|
||||
txt process.
|
||||
align := self getHAlign: offset.
|
||||
txt position: offset @ ( (self extent y - txt extent y ) >> 1).
|
||||
|
||||
icon ifNil: [ ^self ].
|
||||
"{ offset. txt extent. txt maxLineWidth. align } inspect."
|
||||
icon position: (align @( (self extent y - self iconSize ) >> 1)).
|
||||
^ true
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> txt [
|
||||
^ txt
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLabel >> txt: anObject [
|
||||
txt data: anObject.
|
||||
self setDirty
|
||||
]
|
||||
|
@ -32,17 +32,13 @@ DiyaLine class >> points: points [
|
||||
yourself
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> borderColor: c [
|
||||
color := c
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaLine >> draw [
|
||||
shader setUniform: #u_texture_type value: 1.
|
||||
OpenGL
|
||||
"enable: GL_LINE_SMOOTH;
|
||||
hint: GL_LINE_SMOOTH_HINT mode: GL_NICEST;"
|
||||
lineWidth: border.
|
||||
lineWidth: self borderWidth.
|
||||
super draw.
|
||||
OpenGL lineWidth: 1.0";
|
||||
disable: GL_LINE_SMOOTH".
|
||||
@ -53,6 +49,11 @@ DiyaLine >> drawBorder [
|
||||
"do nothing"
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaLine >> drawLines [
|
||||
self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> from [
|
||||
^ from
|
||||
@ -61,7 +62,7 @@ DiyaLine >> from [
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> from: anObject [
|
||||
from := anObject.
|
||||
dirty := true.
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -73,7 +74,31 @@ DiyaLine >> initialize [
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size:8.
|
||||
vbuffer autoRelease.
|
||||
type := GL_LINES.
|
||||
border := 1.0
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> inner: aPoint [
|
||||
^false
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> process [
|
||||
|extent|
|
||||
bbox := (Rectangle origin: from corner: to ).
|
||||
self position: bbox origin.
|
||||
extent := bbox extent.
|
||||
bbox := (Rectangle origin: 0@0 corner: extent ).
|
||||
vbuffer
|
||||
at: 1 put: 0.0;
|
||||
at: 2 put: 0.0;
|
||||
at: 3 put: 0.0;
|
||||
at: 4 put: 0.0;
|
||||
|
||||
at: 5 put: extent x;
|
||||
at: 6 put: extent y;
|
||||
at: 7 put: 0.0;
|
||||
at: 8 put: 0.0.
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -84,22 +109,5 @@ DiyaLine >> to [
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> to: anObject [
|
||||
to := anObject.
|
||||
dirty := true.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLine >> update [
|
||||
|extent|
|
||||
bbox := (Rectangle origin: from corner: to ).
|
||||
bbox origin = translation ifFalse:[self position: bbox origin].
|
||||
from := from - bbox origin.
|
||||
to := to - bbox origin.
|
||||
extent := bbox extent.
|
||||
bbox := (Rectangle origin: 0@0 corner: extent ).
|
||||
|
||||
{
|
||||
0.0. 0.0. 0.0. 0.0.
|
||||
extent x. extent y. 0.0. 0.0.
|
||||
} doWithIndex: [:e :i| vbuffer at: i put: e].
|
||||
^true
|
||||
self setDirty
|
||||
]
|
||||
|
55
Diya/DiyaLoadingBar.class.st
Normal file
55
Diya/DiyaLoadingBar.class.st
Normal file
@ -0,0 +1,55 @@
|
||||
Class {
|
||||
#name : #DiyaLoadingBar,
|
||||
#superclass : #DiyaWidget,
|
||||
#instVars : [
|
||||
'label',
|
||||
'bar',
|
||||
'progress',
|
||||
'percent'
|
||||
],
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLoadingBar >> bar [
|
||||
^ bar
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaLoadingBar >> initialize [
|
||||
super initialize.
|
||||
bar := self addNode: (DiyaRectangle new).
|
||||
progress := self addNode: (DiyaRectangle new).
|
||||
bar styleName: #loadingBar.
|
||||
progress styleName: #loadingProgress.
|
||||
"label := self addNode: (DiyaLabel new).
|
||||
label wordWrap: false."
|
||||
percent := 0.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLoadingBar >> label [
|
||||
^ label
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLoadingBar >> percent [
|
||||
^ percent
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLoadingBar >> percent: anObject [
|
||||
percent := anObject.
|
||||
self setDirty.
|
||||
]
|
||||
|
||||
{ #category : #processing }
|
||||
DiyaLoadingBar >> process [
|
||||
bar extent: self extent.
|
||||
progress extent: ((self percent) * (self extent x) / 100) @ (self extent y).
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaLoadingBar >> progress [
|
||||
^ progress
|
||||
]
|
40
Diya/DiyaMetaNode.class.st
Normal file
40
Diya/DiyaMetaNode.class.st
Normal 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 [
|
||||
^ Rectangle origin: 0@0 extent: 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 [
|
||||
|
||||
]
|
@ -10,11 +10,18 @@ Class {
|
||||
'tf',
|
||||
'shader',
|
||||
'context',
|
||||
'dirty'
|
||||
'ehandlers',
|
||||
'root',
|
||||
'styleName',
|
||||
'style',
|
||||
'id',
|
||||
'visibility',
|
||||
'pivot'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
'OpenGLTypes'
|
||||
'OpenGLTypes',
|
||||
'SDL2Constants'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
@ -24,6 +31,21 @@ DiyaNode class >> with: shader [
|
||||
^self new shader: shader; yourself
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> ? styleAttr [
|
||||
| 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 : #accessing }
|
||||
DiyaNode >> addNode: node [
|
||||
^self addNode: node at: 0@0
|
||||
@ -33,9 +55,11 @@ DiyaNode >> addNode: node [
|
||||
DiyaNode >> addNode: node at: pos [
|
||||
children ifNil: [ ^self ].
|
||||
node parent: self.
|
||||
node position: pos.
|
||||
children add: node.
|
||||
^ node
|
||||
node position: pos.
|
||||
node root: self root.
|
||||
node setDirtyAll.
|
||||
^ node
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -48,16 +72,35 @@ DiyaNode >> children [
|
||||
^children
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : #rendering }
|
||||
DiyaNode >> draw [
|
||||
self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #requirements }
|
||||
DiyaNode >> empty [
|
||||
children := OrderedCollection new.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> extent [
|
||||
^ self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #processing }
|
||||
DiyaNode >> forceReload [
|
||||
self process.
|
||||
children ifNotNil: [
|
||||
children do:[:c|
|
||||
c forceReload
|
||||
]]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> id [
|
||||
^ id
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaNode >> initialize [
|
||||
super initialize.
|
||||
@ -65,12 +108,30 @@ DiyaNode >> initialize [
|
||||
shader := nil.
|
||||
context := DiyaRendererContext uniqueInstance.
|
||||
children := OrderedCollection new.
|
||||
dirty := false
|
||||
ehandlers := Dictionary new.
|
||||
styleName := nil.
|
||||
style := nil.
|
||||
root := nil.
|
||||
visibility := true.
|
||||
pivot := 0@0.
|
||||
id := self className,'#',(Random new nextInt: 1e6) asString.
|
||||
]
|
||||
|
||||
{ #category : #testing }
|
||||
DiyaNode >> inner: aPoint [
|
||||
^ self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #testing }
|
||||
DiyaNode >> isRoot [
|
||||
^false
|
||||
^ 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 }
|
||||
@ -83,6 +144,11 @@ DiyaNode >> parent: anObject [
|
||||
parent := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> pivot [
|
||||
^ pivot
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> position [
|
||||
^ translation
|
||||
@ -94,13 +160,53 @@ DiyaNode >> position: anObject [
|
||||
self updateTF.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #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 : #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 [
|
||||
dirty ifTrue:[dirty := self update not].
|
||||
shader ifNotNil: [ self setUpShader ].
|
||||
visibility ifFalse:[^self].
|
||||
shader ifNotNil: [self setUpShader].
|
||||
self draw.
|
||||
children ifNil: [ ^self ].
|
||||
children do: [:c | c render ].
|
||||
children do: [:c| c render ].
|
||||
]
|
||||
|
||||
{ #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 }
|
||||
@ -114,6 +220,13 @@ DiyaNode >> rotation: anObject [
|
||||
self updateTF.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> rotation: anObject pivot: p [
|
||||
rotation := anObject.
|
||||
pivot := p.
|
||||
self updateTF.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> scale [
|
||||
^ scale
|
||||
@ -125,7 +238,26 @@ DiyaNode >> scale: anObject [
|
||||
self updateTF.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #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.
|
||||
@ -139,7 +271,7 @@ DiyaNode >> setUpShader [
|
||||
"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 resolution y - context mouse y }.
|
||||
{ context mouse x. context mouse y }.
|
||||
].
|
||||
mem free.
|
||||
]
|
||||
@ -157,18 +289,62 @@ 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 [
|
||||
parent ifNil: [ self error: 'TF: This node is not attached to the main tree' ].
|
||||
^ tf
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> update [
|
||||
^self subclassResponsibility
|
||||
{ #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: [
|
||||
"evt mapped triggableOn: children first."
|
||||
children select: [:node | evt mapped triggableOn: node ] thenDo:[:node| node trigger: evt]
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
{ #category : #processing }
|
||||
DiyaNode >> updateTF [
|
||||
self subclassResponsibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> visibility [
|
||||
^ visibility
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaNode >> visibility: anObject [
|
||||
visibility := anObject
|
||||
]
|
||||
|
@ -37,31 +37,12 @@ DiyaPolygon >> points [
|
||||
{ #category : #accessing }
|
||||
DiyaPolygon >> points: anObject [
|
||||
points := anObject.
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaPolygon >> recFromPoints [
|
||||
|maxX maxY minX minY x y|
|
||||
maxX := minX := (points at: 1) x.
|
||||
maxY := minY := (points at: 1) y.
|
||||
points do: [ :p|
|
||||
x := p x.
|
||||
y := p y.
|
||||
maxX := maxX max: x.
|
||||
maxY := maxY max: y.
|
||||
minX := minX min: x.
|
||||
minY := minY min: y.
|
||||
].
|
||||
^ Rectangle origin: minX@minY corner: maxX @ maxY
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaPolygon >> update [
|
||||
bbox := self recFromPoints.
|
||||
translation = bbox origin ifFalse:[ self position: bbox origin].
|
||||
points := points collect:[:e | e - bbox origin].
|
||||
bbox := self recFromPoints.
|
||||
DiyaPolygon >> process [
|
||||
bbox := Rectangle encompassing: points.
|
||||
self calculateVertices.
|
||||
^true
|
||||
]
|
||||
|
@ -16,17 +16,14 @@ DiyaRectangle class >> size: size shader:s [
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaRectangle >> drawLines [
|
||||
self drawLineAt: 0.
|
||||
self drawLineAt: 1.
|
||||
self drawLineAt: 3.
|
||||
self drawLineAt: 4.
|
||||
OpenGL drawArrays: GL_LINE_LOOP first:voffset count: (vbuffer size >> 2).
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRectangle >> extent: v [
|
||||
bbox := Rectangle origin:0@0 corner: v.
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -34,22 +31,34 @@ DiyaRectangle >> initialize [
|
||||
super initialize.
|
||||
self extent:10@10.
|
||||
translation := nil.
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size:16.
|
||||
vbuffer autoRelease.
|
||||
type := GL_QUADS.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRectangle >> update [
|
||||
DiyaRectangle >> process [
|
||||
|extent|
|
||||
extent := self extent.
|
||||
{
|
||||
0.0. extent y. 0.0. 0.0.
|
||||
0. 0. 0.0. 1.0.
|
||||
extent x. 0.0. 1.0. 1.0.
|
||||
|
||||
extent x. 0.0. 1.0. 1.0.
|
||||
extent x. extent y. 1.0. 0.0.
|
||||
0.0. extent y. 0.0. 0.0.
|
||||
} doWithIndex: [:e :i| vbuffer at: i put: e].
|
||||
vbuffer
|
||||
at: 1 put: 0.0;
|
||||
at: 2 put: 0.0;
|
||||
at: 3 put: 0.0;
|
||||
at: 4 put: 0.0;
|
||||
|
||||
at: 5 put: 0.0;
|
||||
at: 6 put: extent y;
|
||||
at: 7 put: 0.0;
|
||||
at: 8 put: 1.0;
|
||||
|
||||
at: 9 put: extent x;
|
||||
at: 10 put: extent y;
|
||||
at: 11 put: 1.0;
|
||||
at: 12 put: 1.0;
|
||||
|
||||
at: 13 put: extent x;
|
||||
at: 14 put: 0.0;
|
||||
at: 15 put: 1.0;
|
||||
at: 16 put: 0.0.
|
||||
^true
|
||||
]
|
||||
|
@ -1,37 +0,0 @@
|
||||
Class {
|
||||
#name : #DiyaRenderer,
|
||||
#superclass : #DiyaSingleton,
|
||||
#instVars : [
|
||||
'root'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
'OpenGLTypes'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaRenderer class >> fromContext: ctx [
|
||||
^self new context: ctx; yourself
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaRenderer >> initialize [
|
||||
super initialize.
|
||||
]
|
||||
|
||||
{ #category : #deleting }
|
||||
DiyaRenderer >> render [
|
||||
root render.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRenderer >> root [
|
||||
^ root
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRenderer >> root: anObject [
|
||||
root := anObject
|
||||
]
|
@ -7,7 +7,11 @@ Class {
|
||||
'vbo',
|
||||
'vao',
|
||||
'texture0',
|
||||
'projection'
|
||||
'projection',
|
||||
'assets',
|
||||
'window',
|
||||
'vbuffer',
|
||||
'voffset'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
@ -16,6 +20,11 @@ Class {
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext class >> bufferSize [
|
||||
^ 524288 "512Kb"
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaRendererContext class >> cleanUpInstance: singleton [
|
||||
singleton ifNil:[^self].
|
||||
@ -28,12 +37,29 @@ DiyaRendererContext class >> maxFloatBufferSize [
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> destroy [
|
||||
DiyaRendererContext >> assets [
|
||||
^ assets
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> assets: anObject [
|
||||
assets := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> destroy [
|
||||
self disableGLAttribute: 0.
|
||||
vbuffer free.
|
||||
vao delete.
|
||||
vbo delete.
|
||||
texture0 delete.
|
||||
]
|
||||
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> disableGLAttribute: attribute [
|
||||
vao disableAttribute: attribute
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> display [
|
||||
^ display
|
||||
@ -44,6 +70,11 @@ DiyaRendererContext >> display: anObject [
|
||||
display := anObject
|
||||
]
|
||||
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> enableGLAttribute: attribute [
|
||||
vao enableAttribute: attribute.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> initialize [
|
||||
super initialize.
|
||||
@ -53,6 +84,15 @@ DiyaRendererContext >> initialize [
|
||||
vao bind.
|
||||
vbo bind: GL_ARRAY_BUFFER.
|
||||
projection := Array2D identity: 4.
|
||||
assets := AssetManager new.
|
||||
"allocate vbuffer"
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size: self class bufferSize.
|
||||
vbuffer autoRelease.
|
||||
voffset := 0.
|
||||
vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STREAM_DRAW.
|
||||
self enableGLAttribute: 0.
|
||||
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -70,17 +110,42 @@ DiyaRendererContext >> projection [
|
||||
^ projection
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> resetBuffer [
|
||||
voffset := 0
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> resolution [
|
||||
^ (display w) @ (display h)
|
||||
]
|
||||
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> setTexture: texture [
|
||||
texture setup.
|
||||
texture0 setImage2D: texture.
|
||||
texture0 active.
|
||||
]
|
||||
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> submitData: data [
|
||||
|n|
|
||||
n := self voffset.
|
||||
voffset := voffset + (data size << 2).
|
||||
voffset > self class bufferSize ifTrue:[
|
||||
^ DiyaCoreAPIError signal: 'Out of video buffer memory'
|
||||
].
|
||||
vbo subData: GL_ARRAY_BUFFER offset: n data: data.
|
||||
^ (n >> 4)
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> texture0 [
|
||||
^ texture0
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
{ #category : #registration }
|
||||
DiyaRendererContext >> useProjection: aClass [
|
||||
projection := aClass fromDisplay: self display
|
||||
]
|
||||
@ -94,3 +159,23 @@ DiyaRendererContext >> vao [
|
||||
DiyaRendererContext >> vbo [
|
||||
^ vbo
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> vbuffer [
|
||||
^ vbuffer
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> voffset [
|
||||
^ voffset
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> window [
|
||||
^ window
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRendererContext >> window: anObject [
|
||||
window := anObject
|
||||
]
|
||||
|
@ -1,14 +1,45 @@
|
||||
Class {
|
||||
#name : #DiyaRootNode,
|
||||
#superclass : #DiyaNode,
|
||||
#instVars : [
|
||||
'Q'
|
||||
],
|
||||
#category : #'Diya-Graphics'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> Q [
|
||||
^ Q
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> boundingBox [
|
||||
^ Rectangle origin: 0@0 corner: context resolution
|
||||
]
|
||||
|
||||
{ #category : #'add/remove' }
|
||||
DiyaRootNode >> cleanDirtyNode: aNode [
|
||||
Q remove: aNode ifAbsent:[]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> draw [
|
||||
OpenGL clearColorR: 0.0 G: 0.0 B: 0.0 A:0.
|
||||
|c|
|
||||
context resetBuffer.
|
||||
c := self ? #bgColor.
|
||||
OpenGL clearColorR: c red G: c green B: c blue A: c alpha.
|
||||
OpenGL clear: GL_COLOR_BUFFER_BIT.
|
||||
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 }
|
||||
DiyaRootNode >> extent [
|
||||
^ context resolution
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -16,16 +47,42 @@ DiyaRootNode >> initialize [
|
||||
super initialize.
|
||||
parent := self.
|
||||
shader := nil.
|
||||
root := self.
|
||||
styleName := #global.
|
||||
Q := OrderedCollection new
|
||||
]
|
||||
|
||||
{ #category : #testing }
|
||||
DiyaRootNode >> isRoot [
|
||||
^ true
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> inner: aPoint [
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> isRoot [
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaRootNode >> update [
|
||||
^true
|
||||
DiyaRootNode >> process [
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaRootNode >> processingQueue [
|
||||
^ Q
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaRootNode >> setClean [
|
||||
|
||||
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaRootNode >> setDirty [
|
||||
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
5
Diya/DiyaRuntimeError.class.st
Normal file
5
Diya/DiyaRuntimeError.class.st
Normal file
@ -0,0 +1,5 @@
|
||||
Class {
|
||||
#name : #DiyaRuntimeError,
|
||||
#superclass : #DiyaError,
|
||||
#category : #'Diya-Events'
|
||||
}
|
@ -19,7 +19,7 @@ DiyaSingleton class >> initialize [
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaSingleton class >> new [
|
||||
self error: 'Use #uniqueInstance'
|
||||
^ DiyaCoreAPIError signal: 'Use #uniqueInstance'
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
@ -31,6 +31,11 @@ DiyaSingleton class >> reset [
|
||||
singletons removeKey: key
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaSingleton class >> resetAll [
|
||||
self allSubclasses do:[:e| e reset]
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaSingleton class >> uniqueInstance [
|
||||
^singletons at: self class asString asSymbol ifAbsentPut: [ super new ].
|
||||
@ -39,5 +44,5 @@ DiyaSingleton class >> uniqueInstance [
|
||||
{ #category : #initialization }
|
||||
DiyaSingleton >> initialize [
|
||||
super initialize.
|
||||
Transcript show: 'Initialise unique instance of ', self className; cr.
|
||||
self stdlog: 'Initialise unique instance of ', self className.
|
||||
]
|
||||
|
41
Diya/DiyaStyle.class.st
Normal file
41
Diya/DiyaStyle.class.st
Normal file
@ -0,0 +1,41 @@
|
||||
Class {
|
||||
#name : #DiyaStyle,
|
||||
#superclass : #DiyaBaseObject,
|
||||
#instVars : [
|
||||
'parent',
|
||||
'style'
|
||||
],
|
||||
#category : #'Diya-UIThemes'
|
||||
}
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaStyle >> at: name ifAbsent: aBlock [
|
||||
|value|
|
||||
value := style at: name ifAbsent:[nil].
|
||||
value ifNotNil: [ ^value ].
|
||||
parent ifNil: [ ^aBlock value ].
|
||||
^ parent at:name ifAbsent: aBlock.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaStyle >> at: name put: value [
|
||||
style at: name put: value
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaStyle >> initialize [
|
||||
super initialize.
|
||||
style := Dictionary new.
|
||||
parent := nil
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaStyle >> parent [
|
||||
^ parent
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaStyle >> parent: anObject [
|
||||
parent := anObject
|
||||
]
|
45
Diya/DiyaStyleSheet.class.st
Normal file
45
Diya/DiyaStyleSheet.class.st
Normal file
@ -0,0 +1,45 @@
|
||||
Class {
|
||||
#name : #DiyaStyleSheet,
|
||||
#superclass : #DiyaBaseObject,
|
||||
#instVars : [
|
||||
'stylesheet'
|
||||
],
|
||||
#category : #'Diya-UIThemes'
|
||||
}
|
||||
|
||||
{ #category : #convenience }
|
||||
DiyaStyleSheet >> ? styleName [
|
||||
^stylesheet at: styleName ifAbsent:[
|
||||
DiyaCoreAPIError signal: 'Unable to query stylesheet ', styleName
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaStyleSheet >> define: styName extend: parentStyName styles: rules [
|
||||
|parentSheet style|
|
||||
parentSheet := self ? parentStyName.
|
||||
style := self define: styName styles: rules.
|
||||
style parent: parentSheet.
|
||||
^style
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaStyleSheet >> define: name styles: rules [
|
||||
|style|
|
||||
style := rules asDiyaStyle.
|
||||
stylesheet at: name put: style.
|
||||
^style
|
||||
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaStyleSheet >> initialize [
|
||||
super initialize.
|
||||
stylesheet := Dictionary new.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaStyleSheet >> stylesheet [
|
||||
^ stylesheet
|
||||
]
|
@ -1,5 +1,5 @@
|
||||
Class {
|
||||
#name : #DiyaTableLayout,
|
||||
#superclass : #DiyaWidget,
|
||||
#superclass : #DiyaLayout,
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
||||
|
@ -1,13 +1,13 @@
|
||||
Class {
|
||||
#name : #DiyaText,
|
||||
#superclass : #Diya2DNode,
|
||||
#superclass : #Diya2DPrimShape,
|
||||
#instVars : [
|
||||
'fontStyle',
|
||||
'fontSize',
|
||||
'fontName',
|
||||
'data',
|
||||
'style',
|
||||
'wrap'
|
||||
'wrap',
|
||||
'texheight',
|
||||
'font',
|
||||
'lines',
|
||||
'maxLineWidth'
|
||||
],
|
||||
#pools : [
|
||||
'FT2Types'
|
||||
@ -25,6 +25,34 @@ DiyaText class >> data: string shader: s [
|
||||
^ (self with:s) data: string; yourself
|
||||
]
|
||||
|
||||
{ #category : #'menu messages' }
|
||||
DiyaText >> align [
|
||||
^ self ? #xAlign
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> alignLine:w [
|
||||
self align = #center ifTrue:[^ 0 max:((self extent x - w) / 2.0 ) asFloat].
|
||||
self align = #right ifTrue:[^ 0 max: self extent x - w].
|
||||
^0
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> allocMemory [
|
||||
vbuffer ifNotNil: [
|
||||
vbuffer size >= data size
|
||||
ifTrue: [^self]
|
||||
ifFalse:[vbuffer free]
|
||||
].
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
|
||||
vbuffer autoRelease.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> borderWidth [
|
||||
^0
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> data [
|
||||
^ data
|
||||
@ -33,146 +61,200 @@ DiyaText >> data [
|
||||
{ #category : #accessing }
|
||||
DiyaText >> data: anObject [
|
||||
data := anObject.
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> draw [
|
||||
data ifNil: [ ^self ].
|
||||
self shader
|
||||
setUniform: #u_texture_type value: self texture format.
|
||||
"configure vao vbo for texture QUAD"
|
||||
self texture setup.
|
||||
context texture0 setImage2D: self texture.
|
||||
context texture0 active.
|
||||
context vao enableAttribute: 0.
|
||||
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
|
||||
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
|
||||
OpenGL drawArrays: GL_TRIANGLES first:0 count: ((vbuffer size) >> 2).
|
||||
context vao disableAttribute: 0.
|
||||
"reset value"
|
||||
self texture drop.
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> drawBorder [
|
||||
self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> drawLines [
|
||||
^ self shouldNotBeCalled
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> drawText [
|
||||
|vertices index tex2D offset|
|
||||
index := 1.
|
||||
offset := 0@0.
|
||||
tex2D := self texture.
|
||||
1 to: data size do: [ :i|
|
||||
vertices := self getCharsVerticesAt:i offset: offset on: tex2D.
|
||||
vertices do: [
|
||||
:e| vbuffer at: index put:e.
|
||||
index := index + 1.
|
||||
].
|
||||
(offset x > self extent x and: wrap not) ifTrue: [ ^self ].
|
||||
(offset y negated > self extent y) ifTrue: [ ^self ].
|
||||
].
|
||||
self splitLines.
|
||||
self formatText .
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> extent: v [
|
||||
bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ).
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> fontName [
|
||||
^ fontName
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> fontName: name style: face size: size [
|
||||
name ifNotNil: [ fontName := name ].
|
||||
face ifNotNil: [ fontStyle := face ].
|
||||
fontSize := size.
|
||||
style := DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
|
||||
dirty := true.
|
||||
^ self ? #fontFamily
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> fontSize [
|
||||
^ fontSize
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> fontSize: size [
|
||||
self fontName: nil style:nil size: size
|
||||
^ self ? #fontSize
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> fontStyle [
|
||||
^ fontStyle
|
||||
^ self ? #fontStyle
|
||||
]
|
||||
|
||||
{ #category : #'text-processing' }
|
||||
DiyaText >> formatText [
|
||||
|offset index line|
|
||||
lines ifNil: [^self].
|
||||
offset := 0@(self valignText: (texture linespace) * (lines size)).
|
||||
index := 1.
|
||||
lines do:[:assoc|
|
||||
line := assoc value.
|
||||
offset setX: (self alignLine: assoc key) setY: offset y.
|
||||
line do:[:g|
|
||||
(self getCharsVerticesFrom: g offset: offset cellh: texture cellh) do:[:v|
|
||||
vbuffer at: index put:v.
|
||||
index := index + 1.
|
||||
]
|
||||
].
|
||||
offset setX: 0.0 setY: (offset y ) + (texture linespace)
|
||||
].
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [
|
||||
|x y w h glyph gsize c |
|
||||
c := (data at:i) asciiValue.
|
||||
c = (Character space asciiValue) ifTrue:[
|
||||
offset setX: (offset x + (tex2D spacing ) ) setY: offset y.
|
||||
wrap ifTrue: [
|
||||
(offset x + ((self nextSpaceFrom: i + 1) * (tex2D fontSize))) > (self extent x) ifTrue: [
|
||||
offset setX: 0.0 setY: (offset y )- (tex2D linespace)].
|
||||
].
|
||||
^ {}.
|
||||
].
|
||||
glyph := tex2D getGlyph: c.
|
||||
DiyaText >> getCharsVerticesFrom:glyph offset: offset cellh: cellh [
|
||||
|x y w h gsize texcoord|
|
||||
gsize := glyph extent.
|
||||
((offset x > self extent x) and: (gsize x > 0)) ifTrue:[
|
||||
wrap ifFalse: [ ^ { } ].
|
||||
offset setX: 0.0 setY: (offset y )- (tex2D linespace).
|
||||
offset y negated > self extent y ifTrue:[^{}].
|
||||
].
|
||||
x := offset x + (glyph bearing x).
|
||||
y := offset y - (tex2D cellh).
|
||||
y := offset y "- cellh".
|
||||
w := (gsize x).
|
||||
h := (gsize y).
|
||||
texcoord := glyph texcoord.
|
||||
offset setX: (offset x + (glyph advance x)) setY: offset y.
|
||||
^{x. y + h. glyph texcoord origin x. glyph texcoord origin y.
|
||||
x. y. glyph texcoord origin x. glyph texcoord corner y.
|
||||
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
|
||||
x. y + h. glyph texcoord origin x. glyph texcoord origin y.
|
||||
x + w. y. glyph texcoord corner x. glyph texcoord corner y.
|
||||
x + w. y + h. glyph texcoord corner x. glyph texcoord origin y. }.
|
||||
^{x. y. texcoord origin x. texcoord origin y.
|
||||
x. y + h. texcoord origin x. texcoord corner y.
|
||||
x + w. y + h. texcoord corner x. texcoord corner y.
|
||||
"x. y + h. texcoord origin x. texcoord origin y.
|
||||
x + w. y. texcoord corner x. texcoord corner y."
|
||||
x + w. y. texcoord corner x. texcoord origin y. }.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> getLineAt: index to: line with: tex2D [
|
||||
| glyph ret w |
|
||||
w := 0.
|
||||
index to: data size do:[ :i|
|
||||
glyph := tex2D getGlyph: (data at:i) asInteger.
|
||||
(w + (glyph advance x)) >= (self extent x) ifTrue:[
|
||||
wrap ifFalse: [ ^ i @ w].
|
||||
ret := self lastSeparatorFrom: i.
|
||||
ret to: i - 1 do:[:j|
|
||||
w := w - (line removeLast advance x)].
|
||||
^ (ret+1)@w
|
||||
] ifFalse:[
|
||||
w := w + (glyph advance x).
|
||||
line add: glyph.
|
||||
].
|
||||
].
|
||||
maxLineWidth := maxLineWidth max: w.
|
||||
^ (data size + 1) @ w
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> initTexture [
|
||||
font:= DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
|
||||
texture := font textureOf: self fontSize.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> initialize [
|
||||
super initialize.
|
||||
self fontName: 'Ubuntu' style:'Regular' size: 16.
|
||||
data := nil.
|
||||
wrap := false.
|
||||
bbox := nil
|
||||
texheight := 0.
|
||||
type := GL_QUADS.
|
||||
maxLineWidth := 0.
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
DiyaText >> nextSpaceFrom: index [
|
||||
index to: (data size) do: [:i|
|
||||
(data at: i) = (Character space) ifTrue:[^i - index].
|
||||
{ #category : #'text-processing' }
|
||||
DiyaText >> lastSeparatorFrom: index [
|
||||
index to: 1 by: -1 do: [:i|
|
||||
(data at: i) isSeparator ifTrue:[^i].
|
||||
].
|
||||
^ 0
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> texture [
|
||||
^style textureOf: self fontSize
|
||||
DiyaText >> lines [
|
||||
^ lines
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> maxLineHeight [
|
||||
texture ifNil: [ ^0].
|
||||
^ texture linespace
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> maxLineWidth [
|
||||
^ maxLineWidth
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> update [
|
||||
bbox ifNil: [ ^false ].
|
||||
DiyaText >> process [
|
||||
bbox ifNil: [ ^true ].
|
||||
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 * 24.
|
||||
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
|
||||
vbuffer autoRelease.
|
||||
self drawText.
|
||||
^true
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> splitLines [
|
||||
|line ret tex2D|
|
||||
ret := 1@0.
|
||||
tex2D := self texture.
|
||||
lines := OrderedCollection new.
|
||||
[
|
||||
line := OrderedCollection new.
|
||||
ret := self getLineAt: ret x to: line with: tex2D.
|
||||
lines add: ((ret y) -> line).
|
||||
(ret x < data size) and: wrap
|
||||
] whileTrue.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> styleName: aName [
|
||||
super styleName: aName.
|
||||
texture := nil.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> texture [
|
||||
^texture
|
||||
]
|
||||
|
||||
{ #category : #'menu messages' }
|
||||
DiyaText >> valign [
|
||||
^ self ? #yAlign
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaText >> valignText:h [
|
||||
self valign = #middle ifTrue:[^ (0 max:((self extent y - h) / 2 ) asFloat)].
|
||||
self valign = #bottom ifTrue:[^ (0 max:(self extent y - h ))].
|
||||
^0
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaText >> wordWrap: aBool [
|
||||
wrap := aBool.
|
||||
dirty := true
|
||||
self setDirty
|
||||
]
|
||||
|
68
Diya/DiyaTimerNode.class.st
Normal file
68
Diya/DiyaTimerNode.class.st
Normal 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
|
||||
]
|
54
Diya/DiyaUIThemesManager.class.st
Normal file
54
Diya/DiyaUIThemesManager.class.st
Normal file
@ -0,0 +1,54 @@
|
||||
Class {
|
||||
#name : #DiyaUIThemesManager,
|
||||
#superclass : #DiyaSingleton,
|
||||
#instVars : [
|
||||
'themes',
|
||||
'currentThemeName'
|
||||
],
|
||||
#category : #'Diya-UIThemes'
|
||||
}
|
||||
|
||||
{ #category : #adding }
|
||||
DiyaUIThemesManager >> addTheme:name stylesheet:sheet [
|
||||
themes at:name put: sheet
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaUIThemesManager >> currentTheme [
|
||||
^ themes at: self currentThemeName ifAbsent: [
|
||||
DiyaCoreAPIError signal: 'Undefined theme named', self currentThemeName
|
||||
]
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaUIThemesManager >> currentThemeName [
|
||||
^ currentThemeName
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaUIThemesManager >> currentThemeName: anObject [
|
||||
currentThemeName := anObject
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaUIThemesManager >> defaultTheme [
|
||||
^ themes at: #default
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaUIThemesManager >> defineDefaultTheme [
|
||||
self addTheme: #default stylesheet: DiyaDefaultTheme new.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaUIThemesManager >> initialize [
|
||||
super initialize.
|
||||
themes := Dictionary new.
|
||||
self defineDefaultTheme.
|
||||
self currentThemeName: #default.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
DiyaUIThemesManager >> themes [
|
||||
^ themes
|
||||
]
|
@ -1,5 +1,29 @@
|
||||
Class {
|
||||
#name : #DiyaWidget,
|
||||
#superclass : #Diya2DNode,
|
||||
#instVars : [
|
||||
'extent'
|
||||
],
|
||||
#category : #'Diya-Widgets'
|
||||
}
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
DiyaWidget class >> fromStyle: aStyle [
|
||||
^self new style: aStyle; yourself
|
||||
]
|
||||
|
||||
{ #category : #geometry }
|
||||
DiyaWidget >> extent [
|
||||
^extent
|
||||
]
|
||||
|
||||
{ #category : #geometry }
|
||||
DiyaWidget >> extent: size [
|
||||
extent := size.
|
||||
self setDirty.
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
DiyaWidget >> initialize [
|
||||
super initialize.
|
||||
]
|
||||
|
@ -51,17 +51,16 @@ ImageInitializer >> initializeImage [
|
||||
do: [ :c |
|
||||
[ c initialize ]
|
||||
on: Error
|
||||
do: [ c = Cursor
|
||||
ifFalse: [ retryList add: c ] ] ].
|
||||
do: [ retryList add: c ] ].
|
||||
retryList
|
||||
do: [ :c |
|
||||
Transcript
|
||||
show: 'CLASS: ' , c asString , ' is not initialized';
|
||||
cr.
|
||||
self stdlog: 'CLASS: ' , c asString , ' is not initialized, retry'.
|
||||
c initialize ].
|
||||
DiyaSingleton resetAll.
|
||||
FFIMethodRegistry resetAll.
|
||||
Smalltalk garbageCollect.
|
||||
SourceFiles := SourceFileArray new.
|
||||
"Smalltalk vm parameterAt: 45 put: (Smalltalk vm parameterAt: 44) * 2."
|
||||
Transcript show: 'Image initialized'; cr.
|
||||
]
|
||||
|
||||
|
@ -1,5 +1,16 @@
|
||||
Extension { #name : #LibC }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
LibC class >> alloc: size [
|
||||
^self uniqueInstance alloc: size
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
LibC >> alloc:size [
|
||||
^self ffiCall: #(void *malloc(size_t size))
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
LibC >> memset:pointer value: value size: size [
|
||||
^self ffiCall: #(void *memset(void *pointer, int value, size_t size))
|
||||
|
15
Diya/MatrixTransform2x3.extension.st
Normal file
15
Diya/MatrixTransform2x3.extension.st
Normal file
@ -0,0 +1,15 @@
|
||||
Extension { #name : #MatrixTransform2x3 }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
MatrixTransform2x3 >> asGLBuffer [
|
||||
|buffer|
|
||||
buffer := FFIExternalArray externalNewType: #float size: 9.
|
||||
1 to: 6 do:[:i|
|
||||
buffer at:i put: (self at:i)].
|
||||
buffer
|
||||
at: 7 put: 0;
|
||||
at: 8 put: 0;
|
||||
at: 9 put: 1.
|
||||
buffer autoRelease.
|
||||
^buffer
|
||||
]
|
@ -93,6 +93,11 @@ OpenGL class >> pixelstorei: pname param: param [
|
||||
^self ffiCall: #(void glPixelStorei( GLenum pname,GLint param))
|
||||
]
|
||||
|
||||
{ #category : #geometry }
|
||||
OpenGL class >> readPixelsOn: buffer x:x y: y w:w h:h format: fmt type: type [
|
||||
^ self ffiCall: #(void glReadPixels( GLint x,GLint y,GLsizei w,GLsizei h,GLenum fmt,GLenum type,void * buffer))
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGL class >> vertex3fX:x Y:y Z:z [
|
||||
^self ffiCall: #(void glVertex3f( GLfloat x,GLfloat y,GLfloat z))
|
||||
|
@ -11,6 +11,8 @@ Class {
|
||||
'GL_ARRAY_BUFFER',
|
||||
'GL_ARRAY_BUFFER_BINDING',
|
||||
'GL_ATTACHED_SHADERS',
|
||||
'GL_BGR',
|
||||
'GL_BGRA',
|
||||
'GL_BLEND',
|
||||
'GL_BLUE',
|
||||
'GL_BYTE',
|
||||
@ -60,6 +62,7 @@ Class {
|
||||
'GL_SRC_ALPHA',
|
||||
'GL_STATIC_DRAW',
|
||||
'GL_STENCIL_BUFFER_BIT',
|
||||
'GL_STREAM_DRAW',
|
||||
'GL_TESS_CONTROL_SHADER',
|
||||
'GL_TESS_EVALUATION_SHADER',
|
||||
'GL_TEXTURE_2D',
|
||||
@ -106,6 +109,7 @@ OpenGLConstants class >> initCommonConstants [
|
||||
GL_UNIFORM_BUFFER := 16r8A11.
|
||||
GL_STATIC_DRAW := 16r88E4.
|
||||
GL_DYNAMIC_DRAW := 16r88E8.
|
||||
GL_STREAM_DRAW := 16r88E0.
|
||||
GL_FALSE := 0.
|
||||
GL_TRUE := 1.
|
||||
GL_ARRAY_BUFFER_BINDING := 16r8894.
|
||||
@ -115,6 +119,8 @@ OpenGLConstants class >> initCommonConstants [
|
||||
GL_ALPHA := 16r1906.
|
||||
GL_RGB := 16r1907.
|
||||
GL_RGBA := 16r1908.
|
||||
GL_BGR := 16r80E0.
|
||||
GL_BGRA := 16r80E1.
|
||||
GL_LINE_SMOOTH := 16r0B20.
|
||||
GL_LINE_SMOOTH_HINT := 16r0C52
|
||||
]
|
||||
|
@ -6,7 +6,13 @@ Class {
|
||||
'cellw',
|
||||
'cellh',
|
||||
'spacing',
|
||||
'fontSize'
|
||||
'fontSize',
|
||||
'colp',
|
||||
'rowp',
|
||||
'face',
|
||||
'maxbearing',
|
||||
'maxrows',
|
||||
'meanww'
|
||||
],
|
||||
#pools : [
|
||||
'OpenGLConstants',
|
||||
@ -26,7 +32,6 @@ OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
|
||||
0 to: size y - 1 do: [ :i|
|
||||
LibC memCopy: (bitmap getHandle + (i* (size x))) to:(data getHandle + ((i + offset y) * width + (offset x) )) size: size x
|
||||
].
|
||||
bitmap free.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -44,39 +49,6 @@ OpenGLFontTex >> charmap [
|
||||
^ charmap
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex >> createBitmapFontFrom: glyphs maxBearing: maxbearing [
|
||||
|bmp metric offset nrows index element|
|
||||
data ifNotNil: [data free ].
|
||||
charmap := Dictionary new.
|
||||
nrows := glyphs size >> 5.
|
||||
(glyphs size % 32) = 0 ifFalse:[nrows := nrows + 1].
|
||||
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (nrows << 5).
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
data autoRelease.
|
||||
index := 1.
|
||||
offset := 0@0.
|
||||
width := cellw * 32.
|
||||
height := cellh * nrows.
|
||||
0 to: nrows - 1 do: [ :row|
|
||||
0 to: 31 do: [ :col| |glyph|
|
||||
element := glyphs at: index.
|
||||
metric := element at: 3.
|
||||
bmp := element at:2.
|
||||
offset := (col * cellw) @ (row*cellh).
|
||||
glyph := (DiyaFontGlyph origin: offset extent: ((metric first x asInteger) @ cellh)).
|
||||
glyph
|
||||
bearing: (metric at: 2) asFloatPoint;
|
||||
advance: (metric at: 3) asFloatPoint;
|
||||
texcoord: (Rectangle origin: (glyph origin/ (self extent) ) asFloatPoint corner: ((glyph corner) / (self extent)) asFloatPoint ).
|
||||
charmap at: element first put:glyph.
|
||||
self blitPixel8: bmp at: (offset x) @ ((offset y) + maxbearing - (metric last) ) size: metric first.
|
||||
index := index + 1.
|
||||
index > glyphs size ifTrue:[^self].
|
||||
]
|
||||
].
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> drop [
|
||||
OpenGL
|
||||
@ -91,50 +63,72 @@ OpenGLFontTex >> fontSize [
|
||||
]
|
||||
|
||||
{ #category : #'instance creation' }
|
||||
OpenGLFontTex >> fromFace: face ofSize: size [
|
||||
|minhang maxbearing rec glyphs iptr charcode w|
|
||||
OpenGLFontTex >> fromFace: aFace ofSize: size [
|
||||
|minhang rec iptr charcode w numw|
|
||||
fontSize := size.
|
||||
face setPixelWidth:0 height: size.
|
||||
glyphs := OrderedCollection new.
|
||||
cellw := 0.
|
||||
cellh := 0.
|
||||
minhang := 0.
|
||||
maxbearing := 0.
|
||||
face := aFace.
|
||||
charmap := Dictionary new.
|
||||
face setPixelWidth:0 height: self fontSize.
|
||||
cellw := cellh := minhang := maxbearing := 0.
|
||||
iptr := FFIExternalArray externalNewType: GLuint size:1.
|
||||
iptr at:1 put: 0.
|
||||
rec := (FTFaceRec fromHandle: face getHandle).
|
||||
charcode := face getFirstChar: iptr getHandle.
|
||||
meanww := 0.
|
||||
numw := 0.
|
||||
[ (iptr at: 1) = 0 ] whileFalse: [
|
||||
|bmp bmpsize metric|
|
||||
face loadCharacter: charcode flags: (1 << 2).
|
||||
w := ((rec glyph metrics width) >> 6).
|
||||
(w > (size << 1)) ifFalse:[
|
||||
metric := {
|
||||
(((rec glyph metrics width) >> 6)@ ((rec glyph metrics height) >> 6)).
|
||||
(face glyph hBearing).
|
||||
(face glyph advance).
|
||||
((rec glyph metrics horiBearingY) >> 6)
|
||||
}.
|
||||
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
|
||||
cellw := cellw max: w.
|
||||
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
|
||||
"copy buffer"
|
||||
bmpsize := (rec glyph bitmap width)*(rec glyph bitmap rows).
|
||||
bmp := FFIExternalArray externalNewType: GLubyte size:bmpsize.
|
||||
LibC memCopy: rec glyph bitmap buffer to: bmp getHandle size: bmpsize.
|
||||
glyphs add: {charcode. bmp. metric}.
|
||||
meanww := meanww + w.
|
||||
numw := numw + 1.
|
||||
].
|
||||
charcode := face getNextChar: charcode iptr: iptr getHandle.
|
||||
].
|
||||
cellh := maxbearing - minhang.
|
||||
spacing := (size >> 2) asInteger.
|
||||
self createBitmapFontFrom: glyphs maxBearing: maxbearing.
|
||||
spacing := (cellw >> 2) asInteger.
|
||||
meanww := meanww / numw.
|
||||
maxrows := 8.
|
||||
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (maxrows << 5).
|
||||
LibC memset: data getHandle value: 0 size: data size.
|
||||
width := cellw << 5.
|
||||
height := cellh.
|
||||
data autoRelease.
|
||||
iptr free.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> genGlyph:c [
|
||||
|rec offset glyph gsize|
|
||||
face setPixelWidth:0 height: self fontSize.
|
||||
face loadCharacter: c flags: (1 << 2).
|
||||
rec := (FTFaceRec fromHandle: face getHandle).
|
||||
gsize := ((rec glyph metrics width) >> 6)@((rec glyph metrics height) >> 6).
|
||||
offset := (colp * cellw) @ (rowp*cellh).
|
||||
glyph := (DiyaFontGlyph origin: offset extent: ((gsize x) @ cellh)).
|
||||
glyph
|
||||
bearing: face glyph hBearing asFloatPoint;
|
||||
advance: face glyph advance;
|
||||
tex: self.
|
||||
self blitPixel8: rec glyph bitmap buffer at: (offset x) @ ((offset y) + maxbearing - ((rec glyph metrics horiBearingY) >> 6) ) size: gsize.
|
||||
colp := (colp + 1) % 32.
|
||||
colp = 0 ifTrue:[
|
||||
rowp := rowp + 1.
|
||||
height := height + cellh.
|
||||
rowp >= maxrows ifTrue:[
|
||||
self reallocateBuffer.
|
||||
].
|
||||
].
|
||||
^glyph
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> getGlyph: c [
|
||||
^(self charmap at: c ifAbsent:[^nil])
|
||||
^(self charmap at: c ifAbsentPut:[self genGlyph:c])
|
||||
]
|
||||
|
||||
{ #category : #initialization }
|
||||
@ -148,6 +142,8 @@ OpenGLFontTex >> initialize [
|
||||
internalFormat := GL_ALPHA.
|
||||
type := GL_UNSIGNED_BYTE.
|
||||
target := GL_TEXTURE_2D.
|
||||
colp := 0.
|
||||
rowp := 0.
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
@ -155,6 +151,24 @@ OpenGLFontTex >> linespace [
|
||||
^ cellh
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> meanww [
|
||||
^ meanww
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> reallocateBuffer [
|
||||
|newbuffer|
|
||||
maxrows := maxrows + 4.
|
||||
newbuffer := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (maxrows << 5).
|
||||
LibC memset: newbuffer getHandle value: 0 size: newbuffer size.
|
||||
LibC memCopy: data getHandle to: newbuffer getHandle size: data size.
|
||||
newbuffer autoRelease.
|
||||
data free.
|
||||
data := newbuffer
|
||||
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLFontTex >> setup [
|
||||
OpenGL
|
||||
|
@ -88,11 +88,6 @@ OpenGLSL class >> linkProgram:program [
|
||||
^self ffiCall: #(void glLinkProgram(GLuint program))
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
OpenGLSL class >> resetShaders [
|
||||
self allSubclassesDo: [ :c| c reset ].
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
OpenGLSL class >> setShaderSourceFor: shader count: n string: s length: l [
|
||||
^ self ffiCall: #(void glShaderSource( GLuint shader,GLsizei n,const void* s,const GLint *l))
|
||||
@ -136,7 +131,7 @@ OpenGLSL >> checkStatus:status of: id [
|
||||
] ifFalse: [
|
||||
OpenGLSL getShaderInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
|
||||
].
|
||||
^self error: buffer asString
|
||||
^DiyaCoreAPIError signal: buffer asString
|
||||
].
|
||||
^self
|
||||
|
||||
@ -222,7 +217,7 @@ OpenGLSL >> locateUniforms [
|
||||
OpenGLSL >> setUniform: uname value: values [
|
||||
|uniform|
|
||||
uniform := uniforms at: uname asSymbol ifAbsent:[
|
||||
^self error: 'Uniform ', uname, ' is not defined in this program'].
|
||||
^DiyaCoreAPIError signal: 'Uniform ', uname, ' is not defined in this program'].
|
||||
uniform value: values
|
||||
]
|
||||
|
||||
|
@ -29,6 +29,11 @@ OpenGLTexImage2D >> border: anObject [
|
||||
border := anObject
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLTexImage2D >> bytesSize [
|
||||
^(width * height) << 2
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLTexImage2D >> data [
|
||||
^ data
|
||||
@ -59,7 +64,7 @@ OpenGLTexImage2D >> drop [
|
||||
|
||||
{ #category : #accessing }
|
||||
OpenGLTexImage2D >> extent [
|
||||
^ width @ height
|
||||
^ self width @ self height
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
|
@ -26,7 +26,7 @@ OpenGLVertexBuffer class >> deleteBuffersSize:n buffers: buffers [
|
||||
^self ffiCall: #(void glDeleteBuffers( GLsizei n,const GLuint * buffers))
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
{ #category : #'library path' }
|
||||
OpenGLVertexBuffer class >> ffiLibraryName [
|
||||
^ OpenGL ffiLibraryName
|
||||
]
|
||||
@ -78,7 +78,8 @@ OpenGLVertexBuffer >> initialize [
|
||||
vertexBufferID := FFIExternalArray externalNewType: GLint size:1.
|
||||
vertexBufferID at:1 put: -1.
|
||||
vertexBufferID autoRelease.
|
||||
OpenGLVertexBuffer genVertexBuffersSize: 1 buffers: vertexBufferID getHandle
|
||||
OpenGLVertexBuffer genVertexBuffersSize: 1 buffers: vertexBufferID getHandle.
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
|
@ -27,10 +27,10 @@ OrthoProjectionMatrix >> bottom [
|
||||
{ #category : #initialization }
|
||||
OrthoProjectionMatrix >> calculate [
|
||||
self at:1 at:1 put: (2.0 /(self right - self left)).
|
||||
self at:2 at:2 put: (2.0 / (self top - self bottom)).
|
||||
self at:2 at:2 put: (2.0 / (self bottom - self top)).
|
||||
self at:3 at:3 put: (2.0 / (self far - self near)) negated.
|
||||
self at:4 at:1 put: ((self right + self left)/ (self right - self left)) negated.
|
||||
self at:4 at:2 put: ((self top + self bottom) / (self top - self bottom)) negated.
|
||||
self at:4 at:2 put: ((self top + self bottom) / (self bottom - self top)) negated.
|
||||
self at:4 at:3 put: ((self far + self near)/(self far - self near)) negated.
|
||||
]
|
||||
|
||||
|
@ -1,16 +1,11 @@
|
||||
Extension { #name : #Point }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
Point >> asGLCoord [
|
||||
|res|
|
||||
res := DiyaRendererContext uniqueInstance resolution.
|
||||
^(self / ( res / 2.0)) + (-1.0@ -1.0).
|
||||
Point >> asArray3F [
|
||||
^ self asArray3F: 1.0
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
Point >> glNormalise [
|
||||
|res p|
|
||||
res := DiyaRendererContext uniqueInstance resolution.
|
||||
p := self / (res/ 2).
|
||||
^ (p x asFloat) @ (p y asFloat)
|
||||
Point >> asArray3F: z [
|
||||
^ { self x. self y. z }
|
||||
]
|
||||
|
@ -1,11 +1,28 @@
|
||||
Extension { #name : #SDL2 }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2 class >> SDLAllocFormat: pixel_format [
|
||||
^ self ffiCall: #(SDL_PixelFormat * SDL_AllocFormat(Uint32 pixel_format))
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2 class >> SDLBlitSurface: src srcRect: srcrect dest: dst dstRect: dstrect [
|
||||
^ self ffiCall: #(int SDL_UpperBlit(SDL_Surface* src,SDL_Rect* srcrect,SDL_Surface* dst,SDL_Rect* dstrect))
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2 class >> SDLClearError [
|
||||
^ self ffiCall: #(void SDL_ClearError(void))
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2 class >> SDLFreeFormat: handle [
|
||||
^ self ffiCall: #(void SDL_FreeFormat(SDL_PixelFormat *handle))
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2 class >> SDLGetCurrentDisplayMode: mode from:index [
|
||||
^ self ffiCall: #(int SDL_GetCurrentDisplayMode(int index, SDL_DisplayMode* mode))
|
||||
|
30
Diya/SDL2Image.class.st
Normal file
30
Diya/SDL2Image.class.st
Normal file
@ -0,0 +1,30 @@
|
||||
Class {
|
||||
#name : #SDL2Image,
|
||||
#superclass : #DiyaFFIBase,
|
||||
#pools : [
|
||||
'SDL2Constants',
|
||||
'SDL2ConstantsHint',
|
||||
'SDL2Types'
|
||||
],
|
||||
#category : #'Diya-SDL2'
|
||||
}
|
||||
|
||||
{ #category : #'as yet unclassified' }
|
||||
SDL2Image class >> SDLImgLoad: file [
|
||||
^ self ffiCall: #(SDL_Surface * IMG_Load(const char *file))
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
SDL2Image class >> checkSymbol [
|
||||
^'IMG_Load'
|
||||
]
|
||||
|
||||
{ #category : #accessing }
|
||||
SDL2Image class >> libNames [
|
||||
^#(
|
||||
'libSDL2_image.so'
|
||||
'libSDL2_image-2.0.so.0'
|
||||
'libSDL2_image-2.0.so'
|
||||
'libSDL2_image-2.0.so.0.2.3'
|
||||
)
|
||||
]
|
6
Diya/SDL2MappedEvent.extension.st
Normal file
6
Diya/SDL2MappedEvent.extension.st
Normal file
@ -0,0 +1,6 @@
|
||||
Extension { #name : #SDL2MappedEvent }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL2MappedEvent >> triggableOn: aNode [
|
||||
^aNode isRoot
|
||||
]
|
@ -25,6 +25,25 @@ SDL_DisplayMode class >> fieldsDesc [
|
||||
)
|
||||
]
|
||||
|
||||
{ #category : #converting }
|
||||
SDL_DisplayMode >> asString [
|
||||
^ 'SDL display: ', self width asString, 'x', self height asString, ' - ', self depth asString, ' bits depth'.
|
||||
]
|
||||
|
||||
{ #category : #'color mapping' }
|
||||
SDL_DisplayMode >> colormapIfNeededFor: dest [
|
||||
^ Color colorMapIfNeededFrom: self depth to: dest depth
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> depth [
|
||||
|format depth|
|
||||
format := SDL2 SDLAllocFormat: self format.
|
||||
depth := format BitsPerPixel.
|
||||
SDL2 SDLFreeFormat: format.
|
||||
^depth
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> driverdata [
|
||||
"This method was automatically generated"
|
||||
@ -37,6 +56,16 @@ SDL_DisplayMode >> driverdata: anObject [
|
||||
handle pointerAt: OFFSET_DRIVERDATA put: anObject getHandle.
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> extent [
|
||||
^ self w @ self height
|
||||
]
|
||||
|
||||
{ #category : #other }
|
||||
SDL_DisplayMode >> forceDisplayUpdate [
|
||||
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> format [
|
||||
"This method was automatically generated"
|
||||
@ -61,6 +90,11 @@ SDL_DisplayMode >> h: anObject [
|
||||
handle signedLongAt: OFFSET_H put: anObject
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> height [
|
||||
^ self h
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> refresh_rate [
|
||||
"This method was automatically generated"
|
||||
@ -84,3 +118,8 @@ SDL_DisplayMode >> w: anObject [
|
||||
"This method was automatically generated"
|
||||
handle signedLongAt: OFFSET_W put: anObject
|
||||
]
|
||||
|
||||
{ #category : #'accessing structure variables' }
|
||||
SDL_DisplayMode >> width [
|
||||
^ self w
|
||||
]
|
||||
|
11
Diya/SDL_MouseButtonEvent.extension.st
Normal file
11
Diya/SDL_MouseButtonEvent.extension.st
Normal file
@ -0,0 +1,11 @@
|
||||
Extension { #name : #'SDL_MouseButtonEvent' }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_MouseButtonEvent >> triggableOn: aNode [
|
||||
^ aNode inner: self worldPosition
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_MouseButtonEvent >> worldPosition [
|
||||
^ (self x) @ (self y )
|
||||
]
|
11
Diya/SDL_MouseMotionEvent.extension.st
Normal file
11
Diya/SDL_MouseMotionEvent.extension.st
Normal file
@ -0,0 +1,11 @@
|
||||
Extension { #name : #'SDL_MouseMotionEvent' }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_MouseMotionEvent >> triggableOn: arg1 [
|
||||
^ arg1 inner: self worldPosition
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_MouseMotionEvent >> worldPosition [
|
||||
^ (self x) @ (self y )
|
||||
]
|
13
Diya/SDL_TouchFingerEvent.extension.st
Normal file
13
Diya/SDL_TouchFingerEvent.extension.st
Normal file
@ -0,0 +1,13 @@
|
||||
Extension { #name : #'SDL_TouchFingerEvent' }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_TouchFingerEvent >> triggableOn: aNode [
|
||||
^ aNode inner: self worldPosition
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_TouchFingerEvent >> worldPosition [
|
||||
|resolution|
|
||||
resolution := DiyaRendererContext uniqueInstance resolution.
|
||||
^((self x)* (resolution x) ) @ ((self y)* (resolution y)).
|
||||
]
|
@ -6,6 +6,17 @@ SDL_Window >> destroy [
|
||||
handle beNull
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_Window class >> finalizeResourceData: aTuple [
|
||||
| handle |
|
||||
|
||||
handle := aTuple first.
|
||||
handle isNull ifTrue: [ ^ self ].
|
||||
|
||||
self destroyWindow: handle.
|
||||
handle beNull
|
||||
]
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SDL_Window >> warpMouseX:x Y:y [
|
||||
^self ffiCall: #(void SDL_WarpMouseInWindow(self,int x, int y))
|
||||
|
6
Diya/SmalltalkImage.extension.st
Normal file
6
Diya/SmalltalkImage.extension.st
Normal file
@ -0,0 +1,6 @@
|
||||
Extension { #name : #SmalltalkImage }
|
||||
|
||||
{ #category : #'*Diya' }
|
||||
SmalltalkImage >> getenv: key [
|
||||
^ self ffiCall: #(char *getenv(const char *key)) module: LibC
|
||||
]
|
27
Jenkinsfile
vendored
Normal file
27
Jenkinsfile
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
pipeline{
|
||||
agent { node{ label'master' }}
|
||||
options {
|
||||
// Limit build history with buildDiscarder option:
|
||||
// daysToKeepStr: history is only kept up to this many days.
|
||||
// numToKeepStr: only this many build logs are kept.
|
||||
// artifactDaysToKeepStr: artifacts are only kept up to this many days.
|
||||
// artifactNumToKeepStr: only this many builds have their artifacts kept.
|
||||
buildDiscarder(logRotator(numToKeepStr: "1"))
|
||||
// Enable timestamps in build log console
|
||||
timestamps()
|
||||
// Maximum time to run the whole pipeline before canceling it
|
||||
timeout(time: 1, unit: 'HOURS')
|
||||
// Use Jenkins ANSI Color Plugin for log console
|
||||
ansiColor('xterm')
|
||||
// Limit build concurrency to 1 per branch
|
||||
disableConcurrentBuilds()
|
||||
}
|
||||
stages
|
||||
{
|
||||
stage('Build image from SDK') {
|
||||
steps {
|
||||
build job: 'Diya-image', propagate: true, wait: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user