1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-07-18 06:49:46 +02:00

75 Commits

Author SHA1 Message Date
d99d6f3604 Use a single big video buffer for rendering instead of one buffer peer primitive shapes
Some checks reported errors
gitea-sync/Diya-API/pipeline/head Something is wrong with the build of this commit
2022-08-13 23:00:41 +02:00
c1f2de2896 refactory code 2022-08-13 15:55:51 +02:00
766ae23f8e fix: incorrect line rendering 2022-08-13 01:47:15 +02:00
f3ef0c1aa0 fix: tf global to local problem on 2D node, add LoadingBar widget, and refactor code 2022-08-13 01:37:42 +02:00
2e4c73f8cf API improvements:
- fix: TF update bug on scale
- fix: Use local coordiate for Polygon points
- Add timer node for basic animation
- Dirty processing nodes are monitored by rootnode
- refactory code
2022-08-12 22:19:54 +02:00
2ee103191c OPENGL Rendering Performance improvement 2022-08-12 16:37:53 +02:00
a3d00d52ef Allow to fallback to VM plugins for image handling if SDL_image lib doesnt exist 2022-08-12 12:02:49 +02:00
133ddb0380 Fix: incorrect index in buffer converting 2022-08-10 23:05:25 +02:00
598e252b9e fix: add missing extension 2022-08-10 23:00:30 +02:00
664e2169f3 Refactor code + use primitive for 2D matrix transformation 2022-08-10 22:53:14 +02:00
9442050825 API improvement
- Refactor code
- Texture performance improvement
2022-08-10 19:55:49 +02:00
6f5c6b8551 allow get texture from screen, VM bug on device 2022-08-09 03:14:23 +02:00
141bf2e226 use SDL2_image for texture loading 2022-08-09 00:22:18 +02:00
676113a697 Add global display object that refers to current SDL display 2022-08-08 16:35:04 +02:00
4a95c7d6df remove dependecy on OSSDL2Driver 2022-08-08 13:11:25 +02:00
7a7665430d Remove dependencies on OSSDLDriver 2022-08-08 13:03:46 +02:00
8b6a7927f4 Correct openGL transparent color display problem, stylesheet now allows style inheritance 2022-08-08 00:12:54 +02:00
007d99804f Cache current stylesheet object in each node to gain FPS 2022-08-07 21:08:29 +02:00
c249c2e381 Rework on Graphic styling 2022-08-07 20:43:16 +02:00
6d7ab2dcd6 Merge b8257f7011 2022-08-07 18:17:07 +02:00
b8257f7011 refactory code 2022-08-07 18:15:57 +02:00
fcaadbc185 Update example 2022-08-07 11:37:08 +02:00
4467f61f32 update example 2022-08-07 11:35:34 +02:00
396fd9909d Create Jenkinsfile 2022-08-06 23:48:46 +02:00
5915d86219 Change coordinate to top down, improvement on label rendering 2022-08-06 03:11:36 +02:00
a8b89f19c5 allow to set system resolution using the DIYA_RES environment variable 2022-05-23 12:26:46 +02:00
5058d62876 wip: rework on text rendering (performance is still degraded) 2022-03-24 22:48:41 +01:00
d70df41681 wip: styling support to graphic node 2022-03-23 00:52:15 +01:00
e2adc4f733 Clean up 2022-03-22 21:29:36 +01:00
e99500acca WIP: widgets implementation 2022-03-21 22:39:52 +01:00
91cfa95ef7 minor changes 2022-03-21 19:13:11 +01:00
42aeb49947 Add assets manager, add support for application launching 2022-03-21 18:03:15 +01:00
eba462b9c0 Add bootstrap font icons support 2022-03-21 01:45:21 +01:00
ac764da076 WIP: add support for input events 2022-03-19 02:18:29 +01:00
e2a8bc046c improve font rendering in OpenGL, optimise memory usage 2022-03-17 00:32:19 +01:00
f215eb054f Merge pull request #1 from lxsang/conflict
fix conflict
2022-03-16 21:36:26 +01:00
64c0cc9b79 Merge branch 'master' into conflict 2022-03-16 21:36:18 +01:00
16269e40c3 fix conflict 2022-03-16 21:33:35 +01:00
c7b01a0e90 WIP: Add emptly classes for Base widgets 2022-03-16 18:37:51 +01:00
e8b724daa1 Support for basic primitive shapes 2022-03-16 17:48:18 +01:00
89c5e04d36 WIP: draw ellipse and circle 2022-03-16 01:32:01 +01:00
653fe07692 Add log messages 2022-03-15 19:29:57 +01:00
fcc7b13d28 Fix memory leak bug 2022-03-15 19:11:19 +01:00
172a62192e image texture support 2022-03-08 23:30:01 +01:00
9cf12f0d8c Update README.md 2022-03-07 09:35:30 +01:00
94bfc7f6f0 OpenGL: recalculate vertices only when changed.
This allows to greatly improve rendering performance
2022-03-06 19:50:19 +01:00
bd9d406c85 Text rendering is greatly improved 2022-03-06 18:33:10 +01:00
a751a6a6d3 WIP improving text rendering 2022-03-06 12:12:31 +01:00
26f37860e3 WIP imporving text rendering 2022-03-06 12:07:20 +01:00
4bfcf5a09a add GLinit 2022-03-06 01:00:01 +01:00
240add5399 add GLinit 2022-03-06 00:59:14 +01:00
b8897a6351 FreeType face now is cached as bitmap font 2022-03-06 00:58:28 +01:00
7fa21d524b let openGL do the final transformation 2022-03-05 11:55:20 +01:00
8cb2cb543a Text rendering iss working now 2022-03-04 20:28:38 +01:00
ce08ac49e2 WIP: font rendering... 2022-03-03 23:23:43 +01:00
d80f31bd42 WIP: display Freetype font in openGL 2022-03-03 19:19:40 +01:00
6808a3aa0b Add basic graph nodes and support basic transformation 2022-03-02 20:11:01 +01:00
8a59d8cba9 add basic primitive shapes (contd.) 2022-03-01 22:58:58 +01:00
a2af81994c Add freetype font manager 2022-03-01 19:22:26 +01:00
1ebd4a748c correct mouse position inside shader coodinate system 2022-02-15 22:01:26 +01:00
81548622cc avoid uninitialize value 2022-02-15 20:32:33 +01:00
e047a89801 add uniform support to shader 2022-02-15 18:04:54 +01:00
13804205f8 update shader support 2022-02-14 00:02:14 +01:00
94d3a6266b update openGL 1.10 binding 2022-02-13 17:15:23 +01:00
00c350805d add openGLSL bingding 2021-12-20 18:32:08 +01:00
b6fbebc4d4 keep old code as comment for further reference 2021-12-20 01:22:29 +01:00
0d254c6dd4 Basic example of OpenGL binding 2021-12-20 01:14:35 +01:00
4f22db8688 Reset only the unique instance in SDK environment 2021-12-19 22:52:35 +01:00
29e4065fe1 print log using stdout instead of Transcript 2021-12-19 22:41:21 +01:00
1884963e4e refactory logging 2021-12-19 22:17:29 +01:00
ae9c884997 Add cleanup code when quitting 2021-12-19 20:12:36 +01:00
ad045dcc80 Merge 7a17c17ed5 2021-12-19 20:08:49 +01:00
1d9fc2d434 resolve conflict in merge 2021-12-19 20:08:40 +01:00
80b9ee6708 Allow to reset singleton instance in DiyaBoot 2021-12-19 19:49:34 +01:00
cb9cf2f49e Allow to test Diya directly in the Pharo image 2021-12-19 19:45:16 +01:00
101 changed files with 5605 additions and 128 deletions

16
Diya/Array.extension.st Normal file
View File

@ -0,0 +1,16 @@
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])
]

View 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
]

View File

@ -0,0 +1,6 @@
Extension { #name : #ClassDescription }
{ #category : #'*Diya' }
ClassDescription >> classCommentBlank [
^ ''
]

16
Diya/Color.extension.st Normal file
View File

@ -0,0 +1,16 @@
Extension { #name : #Color }
{ #category : #'*Diya' }
Color >> as4bytesRGB [
^{
(self red* 255) asInteger.
(self green * 255) asInteger.
(self blue*255) asInteger.
(self alpha* 255) asInteger
}
]
{ #category : #'*Diya' }
Color >> asGL4FArray [
^{self red. self green. self blue. self alpha }
]

View File

@ -0,0 +1,6 @@
Extension { #name : #DiskStore }
{ #category : #'*Diya' }
DiskStore class >> inform: string [
Transcript show: string; cr.
]

106
Diya/Diya2DNode.class.st Normal file
View File

@ -0,0 +1,106 @@
Class {
#name : #Diya2DNode,
#superclass : #DiyaNode,
#instVars : [
'vbuffer',
'voffset'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DNode >> boundingBox [
|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 >> draw [
]
{ #category : #accessing }
Diya2DNode >> extent [
^ self boundingBox extent
]
{ #category : #accessing }
Diya2DNode >> height [
^ self extent y
]
{ #category : #initialization }
Diya2DNode >> initialize [
super initialize.
translation := 0@0.
scale := 1@1.
rotation := 0.
tf := MatrixTransform2x3 identity .
shader := Diya2DShader uniqueInstance.
vbuffer := nil.
voffset := 0.
]
{ #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.
maxY := minY := vbuffer at: 2.
1 to: vbuffer size by: 4 do: [ :i|
x := vbuffer at: i.
y := vbuffer at: i + 1.
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 }
Diya2DNode >> updateTF [
tf := MatrixTransform2x3 identity.
"translation"
tf setOffset: translation + pivot.
"rotation"
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 ]].
]
{ #category : #accessing }
Diya2DNode >> width [
^ self extent x
]

View File

@ -0,0 +1,106 @@
Class {
#name : #Diya2DPrimShape,
#superclass : #Diya2DNode,
#instVars : [
'texture',
'type',
'bbox'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DPrimShape >> borderWidth [
^ self ? #border
]
{ #category : #accessing }
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: [
context setTexture: self texture.
].
voffset := context submitData: vbuffer.
OpenGL drawArrays: type first: voffset count:((vbuffer size )>> 2 ).
"reset value"
self texture ifNotNil: [self texture drop.].
self borderWidth > 0 ifTrue: [ self drawBorder ].
OpenGL
disable: GL_CULL_FACE;
disable: GL_BLEND.
]
{ #category : #initialization }
Diya2DPrimShape >> drawBorder [
"Diya2DShader uniqueInstance use."
shader setUniform: #u_color value: (self ? #borderColor) asGL4FArray;
setUniform: #u_texture_type value: 1.
OpenGL
lineWidth: self borderWidth.
self drawLines.
OpenGL lineWidth: 1.0.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLineAt: offset [
OpenGL drawArrays: GL_LINES first:(offset) count:2.
]
{ #category : #initialization }
Diya2DPrimShape >> drawLines [
self subclassResponsibility
]
{ #category : #accessing }
Diya2DPrimShape >> extent [
^ bbox extent
]
{ #category : #initialization }
Diya2DPrimShape >> initialize [
super initialize.
texture := nil.
type := GL_TRIANGLES.
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.
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 }
Diya2DPrimShape >> texture [
^ texture
]
{ #category : #accessing }
Diya2DPrimShape >> texture: anObject [
texture := anObject
]
{ #category : #accessing }
Diya2DPrimShape >> textureNamed: name [
self texture: (context assets texture: name)
]

View File

@ -0,0 +1,75 @@
Class {
#name : #Diya2DShader,
#superclass : #OpenGLSL,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
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) {
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);
}
// 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;
}
}'
]
{ #category : #accessing }
Diya2DShader class >> vertexShader [
^'
#ifdef GL_ES
precision mediump float;
#endif
uniform mat4 u_projection;
uniform mat3 u_transform;
varying vec2 texcoord;
void main()
{
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
texcoord = gl_Vertex.zw;
}'
]
{ #category : #initialization }
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.
]

View 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.
]

View 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
]

View 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.
]

View File

@ -3,3 +3,45 @@ Class {
#superclass : #Object,
#category : #'Diya-Core'
}
{ #category : #accessing }
DiyaBaseObject >> checkGLError: mark [
|err|
err := OpenGL getError.
err = 0 ifFalse:[
self stderror:mark, ': return error code ', err hex.
].
]
{ #category : #asserting }
DiyaBaseObject >> shouldNotBeCalled [
^DiyaCoreAPIError signal: 'Should not be called'
]
{ #category : #accessing }
DiyaBaseObject >> stderr [
^VTermOutputDriver stderr
]
{ #category : #accessing }
DiyaBaseObject >> stderror: string [
self stderr
nextPutAll: DateAndTime now asString;
nextPutAll: ': ';
nextPutAll: string;
nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdlog: string [
self stdout
nextPutAll: DateAndTime now asString;
nextPutAll: ': ';
nextPutAll: string;
nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdout [
^ VTermOutputDriver stdout
]

View File

@ -1,25 +1,29 @@
Class {
#name : #DiyaBoot,
#superclass : #DiyaBaseObject,
#superclass : #DiyaSingleton,
#instVars : [
'running',
'window',
'renderer',
'display'
],
#classVars : [
'singleton'
'context',
'display',
'clock'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants',
'SDL2Types'
],
#category : #'Diya-Runtime'
}
{ #category : #'class initialization' }
DiyaBoot class >> initialize [
Smalltalk globals at: #DiyaDisplay put: nil
]
{ #category : #'instance creation' }
DiyaBoot class >> reset [
singleton := nil
DiyaBoot class >> maxFPS [
^60
]
{ #category : #'instance creation' }
@ -32,159 +36,178 @@ DiyaBoot class >> startx [
self uniqueInstance run
]
{ #category : #'instance creation' }
DiyaBoot class >> uniqueInstance [
singleton ifNil: [ singleton := self new ].
^ singleton
{ #category : #events }
DiyaBoot >> GLinit. [
OpenGL viewportX: 0 Y:0 W: display w H: display h.
OpenGL enable: GL_TEXTURE_2D.
]
{ #category : #events }
DiyaBoot >> checkDrivers [
|ndriver usableDrivers|
ndriver := SDL2 SDLGetNumVideoDrivers.
usableDrivers := OrderedCollection new.
Transcript show: 'Available drivers: '.
0 to: ndriver - 1 do: [ :i | |dname|
dname := SDL2 SDLGetVideoDriver: i.
Transcript show: dname, ' '.
(SDL2 SDLVideoInit: dname) = 0 ifTrue:[
usableDrivers add: dname.
SDL2 SDLVideoQuit
]
].
Transcript cr.
]
{ #category : #events }
DiyaBoot >> createRenderer [
|numdriver rinfo|
numdriver := SDL2 SDLGetNumRenderDrivers.
Transcript show: 'SDL_RENDER_DRIVER available:'.
rinfo := SDL_RendererInfo externalNew autoRelease.
0 to: numdriver - 1 do:[:i|
SDL2 SDLGetRendererDriverInfo: rinfo from: i.
Transcript show: rinfo name readString, ' '.
].
Transcript cr.
renderer := window primCreateRenderer: -1 flags: SDL_RENDERER_ACCELERATED.
renderer ifNil: [ ^self error: SDL2 getErrorMessage ].
renderer primGetRendererInfo: rinfo.
Transcript show: 'SDL_RENDER_DRIVER selected: ', rinfo name readString;cr.
^renderer
DiyaBoot >> createGLContext [
context := SDL2 glCreateContext: window.
context ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
^context
]
{ #category : #events }
DiyaBoot >> createWindow [
|handle|
handle := SDL2 createWindow: 'Diya test'
SDL2
glSetAttribute: SDL_GL_MULTISAMPLEBUFFERS value: 1;
glSetAttribute: SDL_GL_MULTISAMPLESAMPLES value: 2.
OpenGL enable: GL_MULTISAMPLE.
window := SDL2 createWindow: 'Diya'
x: 0
y: 0
width: display w
height: display h
flags: SDL_WINDOW_SHOWN.
handle ifNil: [ ^self error: SDL2 getErrorMessage ].
flags: SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL.
window ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
"handle fullscreen: SDL_WINDOW_FULLSCREEN."
^handle
"SDL2 glSetAttribute: SDL_GL_CONTEXT_PROFILE_MASK value: SDL_GL_CONTEXT_PROFILE_ES.
SDL2 glSetAttribute: SDL_GL_CONTEXT_MAJOR_VERSION value: 2.
SDL2 glSetAttribute: SDL_GL_CONTEXT_MINOR_VERSION value: 0.
SDL2 glSetAttribute: SDL_GL_ACCELERATED_VISUAL value: 1."
"SDL2 glSetAttribute: SDL_GL_DOUBLEBUFFER value: 1.
SDL2 glSetAttribute: SDL_GL_DEPTH_SIZE value: 24."
^window
]
{ #category : #events }
DiyaBoot >> init [
| status nvdrivers |
Transcript show:'System: ',
(Smalltalk globals at: #CODENAME ifAbsent:['']),
'-v',(Smalltalk globals at: #VERSION ifAbsent: ['']);
cr.
| status |
SDL2 setHint: 'SDL_RENDER_DRIVER' value: 'opengles2'.
status := SDL2 init: SDL_INIT_EVERYTHING.
status = 0
ifFalse: [ ^ self error: SDL2 getErrorMessage ].
nvdrivers := SDL2 SDLGetNumVideoDrivers.
Transcript show: 'Supported video dirvers:'.
0 to: nvdrivers -1 do: [ :i |
Transcript show: (SDL2 SDLGetVideoDriver: i), ' '.
].
Transcript cr.
Transcript show: 'Current selected video driver: ',
(SDL2 SDLGetCurrentVideoDriver);
cr.
status = 0
ifFalse: [ ^ DiyaCoreAPIError signal: SDL2 getErrorMessage ].
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
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
]
{ #category : #events }
DiyaBoot >> processEvent: event [
|mappedEvt|
mappedEvt := event mapped.
mappedEvt type = SDL_KEYDOWN ifTrue: [ Transcript show: 'keydown...'. ^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 ].
]
{ #category : #events }
DiyaBoot >> randomColorChannel [
| rand |
rand := Random new.
rand := (rand next) * 255.
rand := rand asInteger.
^ rand
display := nil.
window := nil.
context := nil.
clock := DiyaClock uniqueInstance.
]
{ #category : #events }
DiyaBoot >> render [
|event|
event := SDL_Event new.
[ running ] whileTrue: [
[ (SDL2 pollEvent: event) > 0 ] whileTrue: [
self processEvent: event
].
renderer drawColorR: self randomColorChannel
g: self randomColorChannel
b: self randomColorChannel
a: 255.
renderer clear.
renderer present.
SDL2 delay: 50.
|launcher|
DiyaRendererContext uniqueInstance.
launcher := DiyaApplicationLauncher uniqueInstance.
launcher setup.
self GLinit.
[ launcher running ] whileTrue: [
DiyaClock uniqueInstance tick.
launcher main.
SDL2 glSwapWindow: window.
SDL2 delay:
(0 max:
(1000/ self class maxFPS) asInteger - (DiyaClock uniqueInstance lapDelta asMilliSeconds)).
].
]
{ #category : #events }
DiyaBoot >> run [
self init.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
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 : #events }
{ #category : #running }
DiyaBoot >> run: screenSize [
self run: screenSize app: nil
]
{ #category : #running }
DiyaBoot >> run: screenSize app: application [
"
this function should be used only in
SDK environment, in real embeded system
it is always the #run command that is executed
automatically.
"
OpenGLTypes initialize.
OpenGLConstants initialize.
self init.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
display w: screenSize x.
display h: screenSize y.
self startx
self startx.
self class reset.
DiyaClock reset.
DiyaRendererContext reset.
Smalltalk garbageCollect.
]
{ #category : #events }
DiyaBoot >> setCursorPosition: mappedEvt [
Transcript show: 'x: ', mappedEvt x asString, ' - y: ', mappedEvt y asString; cr.
window warpMouseX:((mappedEvt x)* (display w) )
Y: ((mappedEvt y) * (display h))
{ #category : #logging }
DiyaBoot >> showSystemInfo [
|stream numdriver rinfo|
stream := (String new: 255) writeStream.
stream nextPutAll:'System: ';
nextPutAll:(Smalltalk globals at: #CODENAME ifAbsent:['']);
nextPutAll: '-v';
nextPutAll:(Smalltalk globals at: #VERSION ifAbsent: ['']);cr.
numdriver := SDL2 SDLGetNumVideoDrivers.
stream nextPutAll: 'Supported video dirvers:'.
0 to: numdriver -1 do: [ :i |
stream nextPutAll: (SDL2 SDLGetVideoDriver: i); nextPutAll: ' '.
].
stream cr.
stream nextPutAll: 'Current selected video driver: ';
nextPutAll:(SDL2 SDLGetCurrentVideoDriver);cr.
numdriver := SDL2 SDLGetNumRenderDrivers.
stream nextPutAll: 'SDL_RENDER_DRIVER available:'.
rinfo := SDL_RendererInfo externalNew autoRelease.
0 to: numdriver - 1 do:[:i|
SDL2 SDLGetRendererDriverInfo: rinfo from: i.
stream nextPutAll: rinfo name readString; nextPutAll:' '.
].
stream cr.
stream nextPutAll: DiyaDisplay asString; cr.
stream cr.
self stdout nextPutAll: stream contents
]
{ #category : #events }
DiyaBoot >> startx [
Transcript show:'Display resolution: ', display w asString, 'x',display h asString;cr.
window := self createWindow.
renderer := self createRenderer.
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;
window: window;
useProjection: OrthoProjectionMatrix.
self render.
renderer destroy.
context delete.
window destroy.
DiyaSingleton resetAll.
SDL2 quit.
Transcript show: 'System quit'; cr.
]

51
Diya/DiyaButton.class.st Normal file
View File

@ -0,0 +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.
]

15
Diya/DiyaCircle.class.st Normal file
View File

@ -0,0 +1,15 @@
Class {
#name : #DiyaCircle,
#superclass : #DiyaEllipse,
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r [
^self rx: r ry:r
]
{ #category : #'as yet unclassified' }
DiyaCircle class >> r: r shader:s [
^self rx: r ry:r shader:s
]

43
Diya/DiyaClock.class.st Normal file
View File

@ -0,0 +1,43 @@
Class {
#name : #DiyaClock,
#superclass : #DiyaSingleton,
#instVars : [
'monotonic',
'lastTick',
'lapTime'
],
#category : #'Diya-Runtime'
}
{ #category : #initialization }
DiyaClock >> delta [
^ self lapDelta + self lapTime
]
{ #category : #initialization }
DiyaClock >> elapsedTime [
^(DateAndTime now) - monotonic
]
{ #category : #initialization }
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.
]

View File

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

View File

@ -0,0 +1,48 @@
Class {
#name : #DiyaConvexPolygon,
#superclass : #DiyaPolygon,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaConvexPolygon >> calculateVertices [
|size index p texcoord|
size := (points size + 1) << 2.
vbuffer ifNotNil: [ vbuffer free ].
vbuffer := FFIExternalArray externalNewType: GLfloat size:size.
vbuffer autoRelease.
points sort:[:a :b| a angle > b angle].
index := 1.
points do:[:point|
texcoord := self texcoordOf: point.
vbuffer
at: index put: point x;
at: index + 1 put: point y;
at: index + 2 put: texcoord x;
at: index + 3 put: texcoord y.
index := index + 4.
].
p := points at: 2.
texcoord := self texcoordOf: p.
vbuffer
at: index put: p x;
at: index + 1 put: p y;
at: index + 2 put: texcoord x;
at: index + 3 put: texcoord y.
]
{ #category : #initialization }
DiyaConvexPolygon >> drawLines [
OpenGL drawArrays: GL_LINE_LOOP first:voffset count: (vbuffer size >> 2) - 1.
]
{ #category : #initialization }
DiyaConvexPolygon >> initialize [
super initialize.
type := GL_TRIANGLE_FAN
]
{ #category : #accessing }
DiyaConvexPolygon >> texcoordOf: point [
^ (point / (self extent )) asFloatPoint
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaCoreAPIError,
#superclass : #DiyaError,
#category : #'Diya-Events'
}

View 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.
]

97
Diya/DiyaEllipse.class.st Normal file
View File

@ -0,0 +1,97 @@
Class {
#name : #DiyaEllipse,
#superclass : #Diya2DPrimShape,
#instVars : [
'rx',
'ry'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry [
^self new rx: rx;
ry: ry;
yourself
]
{ #category : #'as yet unclassified' }
DiyaEllipse class >> rx: rx ry: ry shader: s [
^self new rx: rx;
ry: ry;
shader: s;
yourself
]
{ #category : #initialization }
DiyaEllipse >> drawBorder [
"do nothing"
]
{ #category : #initialization }
DiyaEllipse >> drawLines [
self shouldNotBeCalled
]
{ #category : #initialization }
DiyaEllipse >> initialize [
super initialize.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size: 24.
vbuffer autoRelease.
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
]
{ #category : #accessing }
DiyaEllipse >> rx: anObject [
rx := anObject.
self setDirty
]
{ #category : #accessing }
DiyaEllipse >> ry [
^ ry
]
{ #category : #accessing }
DiyaEllipse >> ry: anObject [
ry := anObject.
self setDirty
]
{ #category : #initialization }
DiyaEllipse >> setUpShader [
super setUpShader.
self shader
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)) .
]

View File

@ -0,0 +1,148 @@
Class {
#name : #DiyaEllipseShader,
#superclass : #Diya2DShader,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
DiyaEllipseShader 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_border_color;
uniform sampler2D u_texture;
uniform float u_border;
uniform float u_rx;
uniform float u_ry;
varying float rotation;
varying vec2 middle;
varying vec2 texcoord;
struct Ellipse
{
vec2 c;
float minor;
float major;
float f;
};
float get_foci(float major, float minor)
{
return sqrt((major*major)-(minor*minor));
}
Ellipse create_ellipse(vec2 c, float mi, float ma)
{
Ellipse e;
e.c = c;
e.major = max(mi,ma);
e.minor = min(mi,ma);
e.f = get_foci(e.major, e.minor);
return e;
}
bool is_inside_ellipse(vec2 p, Ellipse e)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / (e.major*e.major);
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / (e.minor*e.minor);
return first+second <= 1.0;
}
bool is_inside_border(vec2 p, Ellipse e, float w)
{
float first = ((p.x-e.c.x)*(p.x-e.c.x)) / ((e.major-w)*(e.major-w));
float second = ((p.y-e.c.y)*(p.y-e.c.y)) / ((e.minor-w)*(e.minor-w));
float sum = first + second;
return sum<= 1.0;
}
void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border)
{
c = vec4(0);
if (is_inside_border(p,e, border))
{
vec4 texcolor = vec4(1);
// vec2 uv = (p - (e.c - vec2(e.major , e.minor))) / vec2(e.major*2.0, e.minor*2.0);
// alpha
if(u_texture_type == 0x1906) {
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
}
// rgba
else if (u_texture_type == 0x1908){
texcolor = texture2D(u_texture, texcoord);
}
c = texcolor * u_color;
}
else
{
if (is_inside_ellipse(p, e))
{
c = u_border_color;
}
}
}
vec2 rotate_point(vec2 center, vec2 p,float angle)
{
float s = sin(-angle);
float c = cos(-angle);
// translate point back to origin:
p.x -= center.x;
p.y -= center.y;
// rotate point
float xnew = p.x * c - p.y * s;
float ynew = p.x * s + p.y * c;
// translate point back:
p.x = xnew + center.x;
p.y = ynew + center.y;
return p;
}
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);
// Output to screen
gl_FragColor = color;
}
'
]
{ #category : #accessing }
DiyaEllipseShader class >> vertexShader [
^'
#ifdef GL_ES
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;
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]);
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;
}'
]
{ #category : #initialization }
DiyaEllipseShader >> setUpUniforms [
super setUpUniforms.
self addUniform: #u_rx of: Uniform1F.
self addUniform: #u_ry of: Uniform1F.
]

5
Diya/DiyaError.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaError,
#superclass : #Error,
#category : #'Diya-Events'
}

51
Diya/DiyaEvent.class.st Normal file
View 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
]

View 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
]

View File

@ -0,0 +1,23 @@
Class {
#name : #DiyaExampleShader,
#superclass : #Diya2DShader,
#category : #'Diya-Shaders'
}
{ #category : #accessing }
DiyaExampleShader class >> fragmentShader [
^ '
#ifdef GL_ES
precision mediump float;
#endif
uniform vec2 u_resolution;
uniform vec2 u_mouse;
uniform float u_time;
void main()
{
vec2 mouse = u_mouse / u_resolution;
vec2 px = (gl_FragCoord.xy/u_resolution);
gl_FragColor = vec4(abs(sin(u_time)), px/mouse, 1.0);
}
'
]

View File

@ -9,6 +9,11 @@ DiyaFFIBase class >> checkSymbol [
^self subclassResponsibility
]
{ #category : #accessing }
DiyaFFIBase class >> ffiLibraryName [
^ self moduleName
]
{ #category : #accessing }
DiyaFFIBase class >> libNames [
^self subclassResponsibility
@ -17,9 +22,16 @@ 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' }
DiyaFFIBase >> ffiLibraryName [
^self class ffiLibraryName
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaFFILibNotFound,
#superclass : #DiyaError,
#category : #'Diya-Events'
}

View File

@ -0,0 +1,52 @@
Class {
#name : #DiyaFontFamily,
#superclass : #DiyaBaseObject,
#instVars : [
'styles',
'name'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontFamily class >> fromFace: face [
^self new addFace: face; yourself.
]
{ #category : #accessing }
DiyaFontFamily >> addFace: face [
name ifNil: [ name := face familyName ].
styles at: face styleName ifAbsentPut: [(DiyaFontStyle fromFace: face)].
]
{ #category : #initialization }
DiyaFontFamily >> initialize [
super initialize.
styles := Dictionary new.
name := nil
]
{ #category : #accessing }
DiyaFontFamily >> name [
^ name
]
{ #category : #accessing }
DiyaFontFamily >> name: anObject [
name := anObject
]
{ #category : #accessing }
DiyaFontFamily >> style: styleName [
^styles at: styleName ifAbsent: [^styles at: 'Regular']
]
{ #category : #accessing }
DiyaFontFamily >> styleNames [
^styles keys
]
{ #category : #accessing }
DiyaFontFamily >> styles [
^ styles
]

View File

@ -0,0 +1,49 @@
Class {
#name : #DiyaFontGlyph,
#superclass : #Rectangle,
#instVars : [
'advance',
'bearing',
'tex'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Fonts'
}
{ #category : #accessing }
DiyaFontGlyph >> advance [
^ advance
]
{ #category : #accessing }
DiyaFontGlyph >> advance: anObject [
advance := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> bearing [
^ bearing
]
{ #category : #accessing }
DiyaFontGlyph >> bearing: anObject [
bearing := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> tex [
^ tex
]
{ #category : #accessing }
DiyaFontGlyph >> tex: anObject [
tex := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> texcoord [
^ (Rectangle origin: (self origin/ (tex extent) ) asFloatPoint corner: ((self corner) / (tex extent)) asFloatPoint ).
]

View 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.
]

View File

@ -0,0 +1,115 @@
Class {
#name : #DiyaFontManager,
#superclass : #DiyaSingleton,
#instVars : [
'families'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontManager class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton reset.
]
{ #category : #'as yet unclassified' }
DiyaFontManager class >> searchPaths [
^ {
Smalltalk imageDirectory / 'fonts'
}
]
{ #category : #initialization }
DiyaFontManager >> defaultFamily [
^'Ubuntu'
]
{ #category : #initialization }
DiyaFontManager >> defaultIconSet [
^ self style: 'Regular' from: 'bootstrap-icons'
]
{ #category : #initialization }
DiyaFontManager >> defaultStyle [
^'Regular'
]
{ #category : #accessing }
DiyaFontManager >> families [
^ families
]
{ #category : #accessing }
DiyaFontManager >> familyNames [
^ families keys
]
{ #category : #initialization }
DiyaFontManager >> initialize [
super initialize.
families := Dictionary new.
]
{ #category : #initialization }
DiyaFontManager >> loadFace: face [
|family|
family := families at: face familyName ifAbsentPut:[DiyaFontFamily fromFace: face].
family addFace: face
]
{ #category : #initialization }
DiyaFontManager >> loadFile: aFile [
| path face i numfaces |
path := aFile fullName convertToWithConverter: UTF8TextConverter new.
Transcript show: 'Loading font file ', path;cr.
i := 0.
numfaces := nil.
[ face := FreeTypeFace basicNew
filename: path;
index: i.
face newFaceFromFile: path index: i.
face loadFields.
self stdlog: 'Loaded font face ', face styleName.
numfaces ifNil: [ numfaces := face numFaces ].
self loadFace: face.
i := i + 1.
i < numfaces ] whileTrue
]
{ #category : #initialization }
DiyaFontManager >> loadFonts [
self loadFonts: false.
]
{ #category : #initialization }
DiyaFontManager >> loadFonts: force [
force ifTrue:[self reset].
self class searchPaths do:[:path| self loadPath: path].
]
{ #category : #initialization }
DiyaFontManager >> loadPath: path [
path entries do:[:entry| entry isFile ifTrue:[self loadFile: entry ]].
]
{ #category : #initialization }
DiyaFontManager >> reset [
"reset all stored faces"
families := Dictionary new.
]
{ #category : #initialization }
DiyaFontManager >> style: styleName from: familyName [
|family|
family := families at: familyName ifAbsent: [ families at: self defaultFamily ].
^family style: styleName
]

View File

@ -0,0 +1,56 @@
Class {
#name : #DiyaFontStyle,
#superclass : #DiyaBaseObject,
#instVars : [
'texmap',
'face',
'name'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
DiyaFontStyle class >> fromFace: aFace [
^self new face: aFace; yourself
]
{ #category : #accessing }
DiyaFontStyle >> face [
^ face
]
{ #category : #accessing }
DiyaFontStyle >> face: anObject [
face := anObject
]
{ #category : #initialization }
DiyaFontStyle >> initialize [
super initialize.
texmap := Dictionary new.
]
{ #category : #accessing }
DiyaFontStyle >> name [
^ name
]
{ #category : #accessing }
DiyaFontStyle >> name: anObject [
name := anObject
]
{ #category : #accessing }
DiyaFontStyle >> texmap [
^ texmap
]
{ #category : #initialization }
DiyaFontStyle >> textureOf: size [
|tex|
tex := texmap at: size ifAbsentPut: [
""
OpenGLFontTex fromFace: face ofSize: size
].
^tex
]

5
Diya/DiyaHbox.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaHbox,
#superclass : #DiyaLayout,
#category : #'Diya-Widgets'
}

View 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
]

173
Diya/DiyaImageTex.class.st Normal file
View File

@ -0,0 +1,173 @@
Class {
#name : #DiyaImageTex,
#superclass : #OpenGLTexImage2D,
#instVars : [
'name'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#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
]
{ #category : #accessing }
DiyaImageTex >> drop [
"OpenGL
disable: GL_CULL_FACE;
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 >> 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.
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' }
DiyaImageTex >> initialize [
super initialize.
level := 0.
border := 0.
format := GL_RGBA.
internalFormat := GL_RGBA.
type := GL_UNSIGNED_BYTE.
target := GL_TEXTURE_2D.
]
{ #category : #accessing }
DiyaImageTex >> mipmap [
^false
]
{ #category : #accessing }
DiyaImageTex >> name [
^ name
]
{ #category : #accessing }
DiyaImageTex >> setup [
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
]

View File

@ -0,0 +1,16 @@
Class {
#name : #DiyaImageView,
#superclass : #DiyaRectangle,
#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
]

85
Diya/DiyaLabel.class.st Normal file
View File

@ -0,0 +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
]

5
Diya/DiyaLayout.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaLayout,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

113
Diya/DiyaLine.class.st Normal file
View File

@ -0,0 +1,113 @@
Class {
#name : #DiyaLine,
#superclass : #Diya2DPrimShape,
#instVars : [
'from',
'to'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 [
^ self new
from: p1;
to: p2;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> from: p1 to: p2 shader:s [
^ self new
from: p1;
to: p2;
shader: s;
yourself
]
{ #category : #'instance creation' }
DiyaLine class >> points: points [
^ self new
points: points;
yourself
]
{ #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: self borderWidth.
super draw.
OpenGL lineWidth: 1.0";
disable: GL_LINE_SMOOTH".
]
{ #category : #initialization }
DiyaLine >> drawBorder [
"do nothing"
]
{ #category : #initialization }
DiyaLine >> drawLines [
self shouldNotBeCalled
]
{ #category : #accessing }
DiyaLine >> from [
^ from
]
{ #category : #accessing }
DiyaLine >> from: anObject [
from := anObject.
self setDirty
]
{ #category : #initialization }
DiyaLine >> initialize [
super initialize.
translation := nil.
self from: 0@0.
self to: 10@10.
vbuffer := FFIExternalArray externalNewType: GLfloat size:8.
vbuffer autoRelease.
type := GL_LINES.
]
{ #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 }
DiyaLine >> to [
^ to
]
{ #category : #accessing }
DiyaLine >> to: anObject [
to := anObject.
self setDirty
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaListView,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View 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
]

View File

@ -0,0 +1,40 @@
Class {
#name : #DiyaMetaNode,
#superclass : #DiyaNode,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaMetaNode >> addNode: node at: pos [
self shouldNotBeCalled
]
{ #category : #accessing }
DiyaMetaNode >> boundingBox [
^ 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 [
]

350
Diya/DiyaNode.class.st Normal file
View File

@ -0,0 +1,350 @@
Class {
#name : #DiyaNode,
#superclass : #DiyaBaseObject,
#instVars : [
'translation',
'parent',
'children',
'scale',
'rotation',
'tf',
'shader',
'context',
'ehandlers',
'root',
'styleName',
'style',
'id',
'visibility',
'pivot'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
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
]
{ #category : #accessing }
DiyaNode >> addNode: node at: pos [
children ifNil: [ ^self ].
node parent: self.
children add: node.
node position: pos.
node root: self root.
node setDirtyAll.
^ node
]
{ #category : #accessing }
DiyaNode >> boundingBox [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> children [
^children
]
{ #category : #rendering }
DiyaNode >> draw [
self subclassResponsibility
]
{ #category : #requirements }
DiyaNode >> empty [
children := 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.
parent := nil.
shader := nil.
context := DiyaRendererContext uniqueInstance.
children := OrderedCollection new.
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
]
{ #category : #convenience }
DiyaNode >> on: eventName do: aBlock [
eventName isArray ifFalse:[ ^ self register: aBlock to: eventName ].
eventName do:[:e| self register: aBlock to:e ].
]
{ #category : #accessing }
DiyaNode >> parent [
^ parent
]
{ #category : #accessing }
DiyaNode >> parent: anObject [
parent := anObject
]
{ #category : #accessing }
DiyaNode >> pivot [
^ pivot
]
{ #category : #accessing }
DiyaNode >> position [
^ translation
]
{ #category : #accessing }
DiyaNode >> position: anObject [
translation := anObject.
self updateTF.
]
{ #category : #processing }
DiyaNode >> process [
^self subclassResponsibility
]
{ #category : #convenience }
DiyaNode >> register: aBlock to: eventName [
|evtCode|
evtCode := SDL2Constants bindingOf: ('SDL_', eventName asUppercase).
evtCode ifNil: [ evtCode := eventName ].
ehandlers at: evtCode value put: aBlock.
]
{ #category : #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 [
visibility ifFalse:[^self].
shader ifNotNil: [self setUpShader].
self draw.
children ifNil: [ ^self ].
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 }
DiyaNode >> rotation [
^ rotation
]
{ #category : #accessing }
DiyaNode >> rotation: anObject [
rotation := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> rotation: anObject pivot: p [
rotation := anObject.
pivot := p.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> scale [
^ scale
]
{ #category : #accessing }
DiyaNode >> scale: anObject [
scale := anObject.
self updateTF.
]
{ #category : #'changing state' }
DiyaNode >> setClean [
root ifNil: [ ^self ].
root cleanDirtyNode: self.
]
{ #category : #'changing state' }
DiyaNode >> setDirty [
root ifNil: [ ^self ].
self root enqueueDirtyNode: self.
]
{ #category : #'changing state' }
DiyaNode >> setDirtyAll [
self setDirty.
children ifNotNil: [
children do:[:c| c setDirtyAll] ]
]
{ #category : #rendering }
DiyaNode >> setUpShader [
|mem|
mem := self tf asGLBuffer.
shader use;
setUniform: #u_time value: DiyaClock uniqueInstance elapsedTime asFloat;
setUniform: #u_projection value: {GL_FALSE. context projection buffer};
setUniform: #u_resolution value: { context resolution x. context resolution y };
setUniform: #u_texture value: 0;
setUniform: #u_transform value: {GL_TRUE. mem}.
context mouse ifNotNil: [
"in shader, window origin is bottom left conor of the window
the mouse position should be transformed to this coodinate"
shader setUniform: #u_mouse value:
{ context mouse x. context mouse y }.
].
mem free.
]
{ #category : #accessing }
DiyaNode >> shader [
shader ifNil: [
parent ifNil: [ ^nil ].
^parent shader ].
^ shader
]
{ #category : #accessing }
DiyaNode >> shader: anObject [
shader := anObject
]
{ #category : #stepping }
DiyaNode >> step [
]
{ #category : #stepping }
DiyaNode >> stepDown [
self step.
children ifNotNil: [ children do:[:c | c stepDown ] ]
]
{ #category : #accessing }
DiyaNode >> styleName [
^ styleName
]
{ #category : #accessing }
DiyaNode >> styleName: anObject [
styleName := anObject.
style := nil.
self setDirty
]
{ #category : #'event handling' }
DiyaNode >> styleNotFound: styleAttr [
DiyaCoreAPIError signal: 'Query undefined style ', styleAttr, ' in', styleName.
]
{ #category : #accessing }
DiyaNode >> tf [
^ tf
]
{ #category : #'event handling' }
DiyaNode >> trigger: evt [
evt enable ifFalse:[^self].
ehandlers at: evt mapped type ifPresent:[:handler|
evt target: self.
handler value: evt].
children ifNil: [^self].
evt enable ifTrue: [
"evt mapped triggableOn: children first."
children select: [:node | evt mapped triggableOn: node ] thenDo:[:node| node trigger: evt]
].
]
{ #category : #processing }
DiyaNode >> updateTF [
self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> visibility [
^ visibility
]
{ #category : #accessing }
DiyaNode >> visibility: anObject [
visibility := anObject
]

48
Diya/DiyaPolygon.class.st Normal file
View File

@ -0,0 +1,48 @@
Class {
#name : #DiyaPolygon,
#superclass : #Diya2DPrimShape,
#instVars : [
'points'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points [
^self new points: points; yourself
]
{ #category : #'as yet unclassified' }
DiyaPolygon class >> points: points shader:s [
^self new points: points; shader:s; yourself
]
{ #category : #accessing }
DiyaPolygon >> calculateVertices [
^self subclassResponsibility
]
{ #category : #initialization }
DiyaPolygon >> initialize [
super initialize.
points := {}.
vbuffer := nil.
]
{ #category : #accessing }
DiyaPolygon >> points [
^ points
]
{ #category : #accessing }
DiyaPolygon >> points: anObject [
points := anObject.
self setDirty
]
{ #category : #accessing }
DiyaPolygon >> process [
bbox := Rectangle encompassing: points.
self calculateVertices.
^true
]

View File

@ -0,0 +1,64 @@
Class {
#name : #DiyaRectangle,
#superclass : #Diya2DPrimShape,
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRectangle class >> size: size [
^(self new) extent: size; yourself
]
{ #category : #'instance creation' }
DiyaRectangle class >> size: size shader:s [
^(self with:s) extent: size; yourself
]
{ #category : #initialization }
DiyaRectangle >> drawLines [
OpenGL drawArrays: GL_LINE_LOOP first:voffset count: (vbuffer size >> 2).
]
{ #category : #accessing }
DiyaRectangle >> extent: v [
bbox := Rectangle origin:0@0 corner: v.
self setDirty
]
{ #category : #accessing }
DiyaRectangle >> initialize [
super initialize.
self extent:10@10.
translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:16.
vbuffer autoRelease.
type := GL_QUADS.
]
{ #category : #accessing }
DiyaRectangle >> process [
|extent|
extent := self 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: 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
]

View File

@ -0,0 +1,181 @@
Class {
#name : #DiyaRendererContext,
#superclass : #DiyaSingleton,
#instVars : [
'mouse',
'display',
'vbo',
'vao',
'texture0',
'projection',
'assets',
'window',
'vbuffer',
'voffset'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaRendererContext class >> bufferSize [
^ 524288 "512Kb"
]
{ #category : #'instance creation' }
DiyaRendererContext class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton destroy
]
{ #category : #'instance creation' }
DiyaRendererContext class >> maxFloatBufferSize [
^4096
]
{ #category : #accessing }
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
]
{ #category : #accessing }
DiyaRendererContext >> display: anObject [
display := anObject
]
{ #category : #registration }
DiyaRendererContext >> enableGLAttribute: attribute [
vao enableAttribute: attribute.
]
{ #category : #accessing }
DiyaRendererContext >> initialize [
super initialize.
vbo := OpenGLVertexBuffer new.
vao := OpenGLVertexArray new.
texture0 := OpenGLTexture fromUnit: 0.
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 }
DiyaRendererContext >> mouse [
^ mouse
]
{ #category : #accessing }
DiyaRendererContext >> mouse: anObject [
mouse := anObject
]
{ #category : #accessing }
DiyaRendererContext >> projection [
^ projection
]
{ #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 : #registration }
DiyaRendererContext >> useProjection: aClass [
projection := aClass fromDisplay: self display
]
{ #category : #accessing }
DiyaRendererContext >> vao [
^ vao
]
{ #category : #accessing }
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
]

View File

@ -0,0 +1,91 @@
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 [
|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."
]
{ #category : #'add/remove' }
DiyaRootNode >> enqueueDirtyNode: aNode [
(Q includes: aNode ) ifFalse:[ Q add: aNode].
]
{ #category : #accessing }
DiyaRootNode >> extent [
^ context resolution
]
{ #category : #initialization }
DiyaRootNode >> initialize [
super initialize.
parent := self.
shader := nil.
root := self.
styleName := #global.
Q := OrderedCollection new
]
{ #category : #accessing }
DiyaRootNode >> inner: aPoint [
^true
]
{ #category : #accessing }
DiyaRootNode >> isRoot [
^true
]
{ #category : #initialization }
DiyaRootNode >> process [
]
{ #category : #accessing }
DiyaRootNode >> processingQueue [
^ Q
]
{ #category : #initialization }
DiyaRootNode >> setClean [
]
{ #category : #initialization }
DiyaRootNode >> setDirty [
]
{ #category : #accessing }
DiyaRootNode >> updateTF [
"donothing"
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaRuntimeError,
#superclass : #DiyaError,
#category : #'Diya-Events'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaScrollPanel,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,48 @@
Class {
#name : #DiyaSingleton,
#superclass : #DiyaBaseObject,
#classVars : [
'singletons'
],
#category : #'Diya-Core'
}
{ #category : #'instance creation' }
DiyaSingleton class >> cleanUpInstance: singleton [
"do nothing for now"
]
{ #category : #'class initialization' }
DiyaSingleton class >> initialize [
singletons := Dictionary new.
]
{ #category : #'instance creation' }
DiyaSingleton class >> new [
^ DiyaCoreAPIError signal: 'Use #uniqueInstance'
]
{ #category : #'instance creation' }
DiyaSingleton class >> reset [
|singleton key|
key := self class asString asSymbol.
singleton := singletons at: key ifAbsent: [ ^ self ].
self cleanUpInstance: singleton.
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 ].
]
{ #category : #initialization }
DiyaSingleton >> initialize [
super initialize.
self stdlog: 'Initialise unique instance of ', self className.
]

41
Diya/DiyaStyle.class.st Normal file
View 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
]

View 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
]

5
Diya/DiyaSwitch.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaSwitch,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTableLayout,
#superclass : #DiyaLayout,
#category : #'Diya-Widgets'
}

260
Diya/DiyaText.class.st Normal file
View File

@ -0,0 +1,260 @@
Class {
#name : #DiyaText,
#superclass : #Diya2DPrimShape,
#instVars : [
'data',
'wrap',
'texheight',
'font',
'lines',
'maxLineWidth'
],
#pools : [
'FT2Types'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaText class >> data: string [
^ (self new) data: string; yourself
]
{ #category : #'as yet unclassified' }
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
]
{ #category : #accessing }
DiyaText >> data: anObject [
data := anObject.
self setDirty
]
{ #category : #initialization }
DiyaText >> drawBorder [
self shouldNotBeCalled
]
{ #category : #initialization }
DiyaText >> drawLines [
^ self shouldNotBeCalled
]
{ #category : #accessing }
DiyaText >> drawText [
self splitLines.
self formatText .
]
{ #category : #accessing }
DiyaText >> extent: v [
bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ).
self setDirty
]
{ #category : #accessing }
DiyaText >> fontName [
^ self ? #fontFamily
]
{ #category : #accessing }
DiyaText >> fontSize [
^ self ? #fontSize
]
{ #category : #accessing }
DiyaText >> 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 >> getCharsVerticesFrom:glyph offset: offset cellh: cellh [
|x y w h gsize texcoord|
gsize := glyph extent.
x := offset x + (glyph bearing x).
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. 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.
data := nil.
wrap := false.
texheight := 0.
type := GL_QUADS.
maxLineWidth := 0.
]
{ #category : #'text-processing' }
DiyaText >> lastSeparatorFrom: index [
index to: 1 by: -1 do: [:i|
(data at: i) isSeparator ifTrue:[^i].
].
^ 0
]
{ #category : #accessing }
DiyaText >> lines [
^ lines
]
{ #category : #accessing }
DiyaText >> maxLineHeight [
texture ifNil: [ ^0].
^ texture linespace
]
{ #category : #accessing }
DiyaText >> maxLineWidth [
^ maxLineWidth
]
{ #category : #initialization }
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 * 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.
self setDirty
]

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTextArea,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaTextInput,
#superclass : #DiyaWidget,
#category : #'Diya-Widgets'
}

View File

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

View 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
]

5
Diya/DiyaVbox.class.st Normal file
View File

@ -0,0 +1,5 @@
Class {
#name : #DiyaVbox,
#superclass : #DiyaLayout,
#category : #'Diya-Widgets'
}

29
Diya/DiyaWidget.class.st Normal file
View File

@ -0,0 +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.
]

View File

@ -0,0 +1,6 @@
Extension { #name : #Duration }
{ #category : #'*Diya' }
Duration >> asFloat [
^ seconds asFloat + (nanos / 1e9) asFloat
]

11
Diya/FT2Face.extension.st Normal file
View File

@ -0,0 +1,11 @@
Extension { #name : #FT2Face }
{ #category : #'*Diya' }
FT2Face >> getFirstChar: gindex [
^self ffiCall: #(FT_ULong FT_Get_First_Char(self,FT_UInt *gindex)).
]
{ #category : #'*Diya' }
FT2Face >> getNextChar: charcode iptr: gindex [
^self ffiCall: #( FT_ULong FT_Get_Next_Char(self,FT_ULong charcode,FT_UInt *gindex )).
]

View File

@ -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.
]

23
Diya/LibC.extension.st Normal file
View File

@ -0,0 +1,23 @@
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))
]
{ #category : #'*Diya' }
LibC class >> memset:pointer value: value size: size [
^self uniqueInstance memset: pointer value: value size: size
]

View 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
]

109
Diya/OpenGL.class.st Normal file
View File

@ -0,0 +1,109 @@
Class {
#name : #OpenGL,
#superclass : #DiyaFFIBase,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
OpenGL class >> begin: mode [
^ self ffiCall: #(void glBegin(GLenum mode))
]
{ #category : #'as yet unclassified' }
OpenGL class >> blendFnOn:buf sfactor: sfactor dfactor: dfactor [
^ self ffiCall: #(void glBlendFunci( GLuint buf,GLenum sfactor,GLenum dfactor))
]
{ #category : #'as yet unclassified' }
OpenGL class >> blendFnWithSfactor: sfactor dfactor: dfactor [
^ self ffiCall: #(void glBlendFunc( GLenum sfactor,GLenum dfactor))
]
{ #category : #accessing }
OpenGL class >> checkSymbol [
^#glDrawArrays
]
{ #category : #'as yet unclassified' }
OpenGL class >> clear: mask [
^ self ffiCall: #(void glClear(GLbitfield mask))
]
{ #category : #'as yet unclassified' }
OpenGL class >> clearColorR: red G: green B: blue A:alpha [
^self ffiCall: #(void glClearColor( GLclampf red,GLclampf green,GLclampf blue,GLclampf alpha))
]
{ #category : #accessing }
OpenGL class >> color3fR: red G: green B: blue [
^self ffiCall: #(void glColor3f(GLfloat red,GLfloat green,GLfloat blue))
]
{ #category : #'as yet unclassified' }
OpenGL class >> disable: cap [
^ self ffiCall: #(void glDisable( GLenum cap))
]
{ #category : #'as yet unclassified' }
OpenGL class >> drawArrays: mode first: idx count:n [
^self ffiCall: #(void glDrawArrays(GLenum mode,GLint idx,GLsizei n))
]
{ #category : #'as yet unclassified' }
OpenGL class >> enable: cap [
^ self ffiCall: #(void glEnable( GLenum cap))
]
{ #category : #accessing }
OpenGL class >> end [
^ self ffiCall: #(void glEnd( void ))
]
{ #category : #'as yet unclassified' }
OpenGL class >> getError [
^self ffiCall: #(GLenum glGetError( void))
]
{ #category : #'as yet unclassified' }
OpenGL class >> getIntegerv: pname data: data [
^self ffiCall: #(void glGetIntegerv( GLenum pname,GLint * data))
]
{ #category : #'as yet unclassified' }
OpenGL class >> hint:target mode:mode [
^self ffiCall: #(void glHint( GLenum target,GLenum mode))
]
{ #category : #accessing }
OpenGL class >> libNames [
^#('libGL.so.1')
]
{ #category : #geometry }
OpenGL class >> lineWidth: width [
^ self ffiCall: #(void glLineWidth(GLfloat width))
]
{ #category : #accessing }
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))
]
{ #category : #'as yet unclassified' }
OpenGL class >> viewportX: x Y:y W: width H:height [
^ self ffiCall: #(void glViewport(GLint x,GLint y,GLsizei width,GLsizei height))
]

View File

@ -0,0 +1,202 @@
Class {
#name : #OpenGLConstants,
#superclass : #SharedPool,
#classVars : [
'GL_ACCUM_BUFFER_BIT',
'GL_ACTIVE_ATTRIBUTES',
'GL_ACTIVE_ATTRIBUTE_MAX_LENGTH',
'GL_ACTIVE_UNIFORMS',
'GL_ACTIVE_UNIFORM_MAX_LENGTH',
'GL_ALPHA',
'GL_ARRAY_BUFFER',
'GL_ARRAY_BUFFER_BINDING',
'GL_ATTACHED_SHADERS',
'GL_BGR',
'GL_BGRA',
'GL_BLEND',
'GL_BLUE',
'GL_BYTE',
'GL_CLAMP_TO_BORDER',
'GL_CLAMP_TO_EDGE',
'GL_COLOR_BUFFER_BIT',
'GL_COMPILE_STATUS',
'GL_COMPUTE_SHADER',
'GL_CULL_FACE',
'GL_DELETE_STATUS',
'GL_DEPTH_BUFFER_BIT',
'GL_DOUBLE',
'GL_DYNAMIC_DRAW',
'GL_FALSE',
'GL_FIXED',
'GL_FLOAT',
'GL_FRAGMENT_SHADER',
'GL_GEOMETRY_SHADER',
'GL_GREEN',
'GL_HALF_FLOAT',
'GL_INFO_LOG_LENGTH',
'GL_INT',
'GL_INT_2_10_10_10_REV',
'GL_LINEAR',
'GL_LINES',
'GL_LINE_LOOP',
'GL_LINE_SMOOTH',
'GL_LINE_SMOOTH_HINT',
'GL_LINE_STRIP',
'GL_LINK_STATUS',
'GL_MAX_TEXTURE_SIZE',
'GL_MULTISAMPLE',
'GL_NEAREST',
'GL_NICEST',
'GL_ONE_MINUS_SRC_ALPHA',
'GL_PACK_ALIGNMENT',
'GL_POINTS',
'GL_POLYGON',
'GL_QUADS',
'GL_QUAD_STRIP',
'GL_RED',
'GL_RGB',
'GL_RGBA',
'GL_SHADER_SOURCE_LENGTH',
'GL_SHADER_TYPE',
'GL_SHORT',
'GL_SRC_ALPHA',
'GL_STATIC_DRAW',
'GL_STENCIL_BUFFER_BIT',
'GL_STREAM_DRAW',
'GL_TESS_CONTROL_SHADER',
'GL_TESS_EVALUATION_SHADER',
'GL_TEXTURE_2D',
'GL_TEXTURE_BUFFER',
'GL_TEXTURE_MAG_FILTER',
'GL_TEXTURE_MIN_FILTER',
'GL_TEXTURE_UNIT_BASE',
'GL_TEXTURE_WRAP_S',
'GL_TEXTURE_WRAP_T',
'GL_TRIANGLES',
'GL_TRIANGLE_FAN',
'GL_TRIANGLE_STRIP',
'GL_TRUE',
'GL_UNIFORM_BUFFER',
'GL_UNPACK_ALIGNMENT',
'GL_UNSIGNED_BYTE',
'GL_UNSIGNED_INT',
'GL_UNSIGNED_INT_10F_11F_11F_REV',
'GL_UNSIGNED_INT_2_10_10_10_REV',
'GL_UNSIGNED_SHORT',
'GL_VALIDATE_STATUS',
'GL_VERTEX_SHADER'
],
#category : #'Diya-OpenGL'
}
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonConstants [
GL_BYTE := 16r1400.
GL_UNSIGNED_BYTE := 16r1401.
GL_SHORT := 16r1402.
GL_UNSIGNED_SHORT := 16r1403.
GL_INT := 16r1404.
GL_UNSIGNED_INT := 16r1405.
GL_HALF_FLOAT := 16r140B.
GL_FLOAT := 16r1406.
GL_DOUBLE := 16r140A.
GL_FIXED := 16r140C.
GL_INT_2_10_10_10_REV := 16r8D9F.
GL_UNSIGNED_INT_2_10_10_10_REV := 16r8368.
GL_UNSIGNED_INT_10F_11F_11F_REV := 16r8C3B.
GL_ARRAY_BUFFER := 16r8892.
GL_TEXTURE_BUFFER := 16r8C2A.
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.
GL_RED := 16r1903.
GL_BLUE := 16r1905.
GL_GREEN := 16r1904.
GL_ALPHA := 16r1906.
GL_RGB := 16r1907.
GL_RGBA := 16r1908.
GL_BGR := 16r80E0.
GL_BGRA := 16r80E1.
GL_LINE_SMOOTH := 16r0B20.
GL_LINE_SMOOTH_HINT := 16r0C52
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonMask [
GL_COLOR_BUFFER_BIT := 16r00004000.
GL_DEPTH_BUFFER_BIT := 16r00000100.
GL_ACCUM_BUFFER_BIT := 16r00000200.
GL_STENCIL_BUFFER_BIT := 16r00000400.
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonMode [
GL_TRIANGLES := 16r0004.
GL_POINTS := 16r0000.
GL_LINES := 16r0001.
GL_LINE_STRIP := 16r0003.
GL_LINE_LOOP := 16r0002.
GL_TRIANGLE_STRIP := 16r0005.
GL_TRIANGLE_FAN := 16r0006.
GL_QUADS := 16r0007.
GL_QUAD_STRIP := 16r0008.
GL_POLYGON := 16r0009.
GL_BLEND := 16r0BE2.
GL_SRC_ALPHA := 16r0302.
GL_ONE_MINUS_SRC_ALPHA := 16r0303.
GL_CULL_FACE := 16r0B44.
GL_PACK_ALIGNMENT := 16r0D05.
GL_UNPACK_ALIGNMENT := 16r0CF5.
GL_NICEST := 16r1102.
GL_MULTISAMPLE := 16r809D
]
{ #category : #'class initialization' }
OpenGLConstants class >> initCommonShader [
GL_COMPUTE_SHADER := 16r91B9.
GL_VERTEX_SHADER := 16r8B31.
GL_TESS_CONTROL_SHADER := 16r8E88.
GL_TESS_EVALUATION_SHADER := 16r8E87.
GL_GEOMETRY_SHADER := 16r8DD9.
GL_FRAGMENT_SHADER := 16r8B30.
GL_SHADER_TYPE := 16r8B4F.
GL_DELETE_STATUS := 16r8B80.
GL_COMPILE_STATUS := 16r8B81.
GL_INFO_LOG_LENGTH := 16r8B84.
GL_SHADER_SOURCE_LENGTH := 16r8B88.
GL_LINK_STATUS := 16r8B82.
GL_VALIDATE_STATUS := 16r8B83.
GL_ATTACHED_SHADERS := 16r8B85.
GL_ACTIVE_ATTRIBUTES := 16r8B89.
GL_ACTIVE_ATTRIBUTE_MAX_LENGTH := 16r8B8A.
GL_ACTIVE_UNIFORMS := 16r8B86.
GL_ACTIVE_UNIFORM_MAX_LENGTH := 16r8B87.
]
{ #category : #'class initialization' }
OpenGLConstants class >> initTextureConstants [
GL_TEXTURE_WRAP_S := 16r2802.
GL_TEXTURE_2D := 16r0DE1.
GL_CLAMP_TO_EDGE := 16r812F.
GL_TEXTURE_WRAP_T := 16r2803.
GL_TEXTURE_MIN_FILTER := 16r2801.
GL_TEXTURE_MAG_FILTER := 16r2800.
GL_LINEAR := 16r2601.
GL_NEAREST := 16r2600.
GL_TEXTURE_UNIT_BASE := 16r84C0.
GL_MAX_TEXTURE_SIZE := 16r0D33.
GL_CLAMP_TO_BORDER := 16r812D
]
{ #category : #'class initialization' }
OpenGLConstants class >> initialize [
self initCommonMode.
self initCommonMask.
self initCommonShader.
self initCommonConstants.
self initTextureConstants.
]

189
Diya/OpenGLFontTex.class.st Normal file
View File

@ -0,0 +1,189 @@
Class {
#name : #OpenGLFontTex,
#superclass : #OpenGLTexImage2D,
#instVars : [
'charmap',
'cellw',
'cellh',
'spacing',
'fontSize',
'colp',
'rowp',
'face',
'maxbearing',
'maxrows',
'meanww'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Fonts'
}
{ #category : #'instance creation' }
OpenGLFontTex class >> fromFace: face ofSize: size [
^self new fromFace: face ofSize: size; yourself
]
{ #category : #'instance creation' }
OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
size = (0@0) ifTrue:[^self].
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
].
]
{ #category : #accessing }
OpenGLFontTex >> cellh [
^ cellh
]
{ #category : #accessing }
OpenGLFontTex >> cellw [
^ cellw
]
{ #category : #accessing }
OpenGLFontTex >> charmap [
^ charmap
]
{ #category : #accessing }
OpenGLFontTex >> drop [
OpenGL
pixelstorei: GL_UNPACK_ALIGNMENT param: 4;
disable: GL_CULL_FACE;
disable: GL_BLEND.
]
{ #category : #accessing }
OpenGLFontTex >> fontSize [
^ fontSize
]
{ #category : #'instance creation' }
OpenGLFontTex >> fromFace: aFace ofSize: size [
|minhang rec iptr charcode w numw|
fontSize := size.
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: [
face loadCharacter: charcode flags: (1 << 2).
w := ((rec glyph metrics width) >> 6).
(w > (size << 1)) ifFalse:[
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
cellw := cellw max: w.
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
meanww := meanww + w.
numw := numw + 1.
].
charcode := face getNextChar: charcode iptr: iptr getHandle.
].
cellh := maxbearing - minhang.
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 ifAbsentPut:[self genGlyph:c])
]
{ #category : #initialization }
OpenGLFontTex >> initialize [
super initialize.
charmap := Dictionary new.
data := nil.
level := 0.
border := 0.
format := GL_ALPHA.
internalFormat := GL_ALPHA.
type := GL_UNSIGNED_BYTE.
target := GL_TEXTURE_2D.
colp := 0.
rowp := 0.
]
{ #category : #accessing }
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
enable: GL_CULL_FACE;
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA;
pixelstorei: GL_UNPACK_ALIGNMENT param: 1.
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 : #accessing }
OpenGLFontTex >> spacing [
^ spacing
]

232
Diya/OpenGLSL.class.st Normal file
View File

@ -0,0 +1,232 @@
Class {
#name : #OpenGLSL,
#superclass : #DiyaSingleton,
#instVars : [
'programID',
'uniforms'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLSL class >> attachShader: shader to: program [
^self ffiCall: #(void glAttachShader(GLuint program,GLuint shader))
]
{ #category : #'instance creation' }
OpenGLSL class >> cleanUpInstance: singleton [
singleton ifNil:[^self].
singleton delete
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> compileShader: shader [
^ self ffiCall: #(void glCompileShader( GLuint shader))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> createProgram [
^self ffiCall: #(GLuint glCreateProgram(void))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> createShader: shaderType [
^ self ffiCall: #(GLuint glCreateShader( GLenum shaderType))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> deleteProgram: program [
^self ffiCall: #(void glDeleteProgram(GLuint program))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> deleteShader: shader [
^ self ffiCall: #(void glDeleteShader( GLuint shader))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> detachShaderFrom: program shader:shader [
^ self ffiCall: #(void glDetachShader(GLuint program,GLuint shader))
]
{ #category : #'library path' }
OpenGLSL class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #accessing }
OpenGLSL class >> fragmentShader [
^ self subclassResponsibility
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getProgramInfoLogOf: prog maxLength: maxLength lengthPtr: length buffer: infoLog [
^self ffiCall:#(void glGetProgramInfoLog(GLuint prog,GLsizei maxLength,GLsizei *length,GLchar *infoLog))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getShaderInfoLogOf: shader maxLength: maxLength lengthPtr: length buffer: infoLog [
^self ffiCall:#(void glGetShaderInfoLog(GLuint shader,GLsizei maxLength,GLsizei *length,GLchar *infoLog))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getShaderiv:shader parameterName: pname params: ptr [
^ self ffiCall: #(void glGetShaderiv(GLuint shader,GLenum pname,GLint *ptr))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> getUniformLocation: uname ofProgram: program [
^self ffiCall:#(GLint glGetUniformLocation( GLuint program,const GLchar *uname))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> linkProgram:program [
^self ffiCall: #(void glLinkProgram(GLuint program))
]
{ #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))
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> systemUniforms [
^#(u_time u_resolution u_mouse)
]
{ #category : #'as yet unclassified' }
OpenGLSL class >> useProgram:program [
^self ffiCall:#(void glUseProgram(GLuint program))
]
{ #category : #accessing }
OpenGLSL class >> vertexShader [
^self subclassResponsibility
]
{ #category : #initialization }
OpenGLSL >> addUniform: uname of: utype [
uniforms at:uname put: (utype fromName: uname).
]
{ #category : #compiling }
OpenGLSL >> checkStatus:status of: id [
|infoLength buffer result|
result := FFIExternalArray externalNewType: GLint size: 1.
infoLength := FFIExternalArray externalNewType: GLint size: 1.
infoLength at: 1 put: 0.
infoLength autoRelease.
result autoRelease.
OpenGLSL getShaderiv: id parameterName: status params: result getHandle.
OpenGLSL getShaderiv: id parameterName: GL_INFO_LOG_LENGTH params: infoLength getHandle.
(infoLength at:1) > 0 ifTrue: [
"report the error"
buffer := ByteArray new:(infoLength at: 1).
id = programID ifTrue: [
OpenGLSL getProgramInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
] ifFalse: [
OpenGLSL getShaderInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
].
^DiyaCoreAPIError signal: buffer asString
].
^self
]
{ #category : #compiling }
OpenGLSL >> compile [
|vertexShaderID fragmentShaderID|
vertexShaderID := OpenGLSL createShader: GL_VERTEX_SHADER.
fragmentShaderID := OpenGLSL createShader: GL_FRAGMENT_SHADER.
self compileVertexShader: vertexShaderID.
self compileFragmentShader: fragmentShaderID.
programID := OpenGLSL createProgram.
OpenGLSL attachShader: vertexShaderID to: programID.
OpenGLSL attachShader: fragmentShaderID to: programID.
OpenGLSL linkProgram: programID.
self checkStatus: GL_LINK_STATUS of: programID.
OpenGLSL detachShaderFrom: programID shader: vertexShaderID.
OpenGLSL detachShaderFrom: programID shader: fragmentShaderID.
OpenGLSL deleteShader: vertexShaderID.
OpenGLSL deleteShader: fragmentShaderID.
self locateUniforms
]
{ #category : #compiling }
OpenGLSL >> compileFragmentShader:fragmentShaderID [
self getSourcePtr:self class fragmentShader for: fragmentShaderID.
OpenGLSL compileShader: fragmentShaderID.
self checkStatus:GL_COMPILE_STATUS of: fragmentShaderID
]
{ #category : #compiling }
OpenGLSL >> compileVertexShader: vertexShaderID [
self getSourcePtr:self class vertexShader for: vertexShaderID.
OpenGLSL compileShader: vertexShaderID.
self checkStatus:GL_COMPILE_STATUS of: vertexShaderID
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> delete [
OpenGLSL deleteProgram: programID
]
{ #category : #compiling }
OpenGLSL >> getSourcePtr: string for: shaderId [
|xarray|
xarray := FFIExternalArray externalNewType: 'char*' size: 1.
xarray at:1 put: (ExternalAddress fromString: string).
xarray autoRelease.
OpenGLSL setShaderSourceFor: shaderId count: 1 string: xarray getHandle length: nil.
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> getUniformLocation:uname [
^ self class getUniformLocation: uname asString ofProgram: programID
]
{ #category : #initialization }
OpenGLSL >> initialize [
super initialize.
uniforms := Dictionary new.
self addUniform: #u_time of: Uniform1F.
self addUniform: #u_resolution of: Uniform2F.
self addUniform: #u_mouse of: Uniform2F.
self addUniform: #u_projection of: UniformMatrix4fv.
self addUniform: #u_transform of: UniformMatrix3fv.
self setUpUniforms.
self compile
]
{ #category : #compiling }
OpenGLSL >> locateUniforms [
|loc|
uniforms valuesDo: [ :uniform|
loc := self getUniformLocation: uniform uname.
loc = -1 ifFalse:[uniform location: loc]
]
]
{ #category : #initialization }
OpenGLSL >> setUniform: uname value: values [
|uniform|
uniform := uniforms at: uname asSymbol ifAbsent:[
^DiyaCoreAPIError signal: 'Uniform ', uname, ' is not defined in this program'].
uniform value: values
]
{ #category : #initialization }
OpenGLSL >> setUpUniforms [
"do nothing, custom uniform can be set up by subclass"
]
{ #category : #'submorphs-add/remove' }
OpenGLSL >> use [
^OpenGLSL useProgram: programID
]

View File

@ -0,0 +1,111 @@
Class {
#name : #OpenGLSLUniform,
#superclass : #DiyaBaseObject,
#instVars : [
'uname',
'location'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> fromName: uname [
^self new uname: uname; yourself
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> fromName: uname at: location [
^self new uname: uname; location: location; yourself
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform1f: location value: v0 [
^self ffiCall: #(void glUniform1f(GLint location,GLfloat v0))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform1i: location value: v0 [
^self ffiCall: #(void glUniform1i(GLint location,GLint v0))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform2f: location value: v0 value: v1 [
^self ffiCall: #(void glUniform2f(GLint location,GLfloat v0,GLfloat v1))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform2i: location value: v0 value: v1 [
^self ffiCall: #(void glUniform2i(GLint location,GLint v0,GLint v1))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform3f: location value: v0 value: v1 value: v2 [
^self ffiCall: #(void glUniform3f(GLint location,GLfloat v0,GLfloat v1,GLfloat v2))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform3i: location value: v0 value: v1 value: v2 [
^self ffiCall: #(void glUniform3i(GLint location,GLint v0,GLint v1,GLint v2))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform4f: location value: v0 value: v1 value: v2 value: v3 [
^self ffiCall: #(void glUniform4f(GLint location,GLfloat v0,GLfloat v1,GLfloat v2, GLfloat v3))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniform4i: location value: v0 value: v1 value: v2 value: v3 [
^self ffiCall: #(void glUniform4i(GLint location,GLint v0,GLint v1,GLint v2, GLint v3))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniformMatrix3fv: location count: count transpose: transpose value: value [
^self ffiCall: #(void glUniformMatrix3fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat *value))
]
{ #category : #'as yet unclassified' }
OpenGLSLUniform class >> uniformMatrix4fv: location count: count transpose: transpose value: value [
^self ffiCall: #(void glUniformMatrix4fv(GLint location,GLsizei count,GLboolean transpose,const GLfloat *value))
]
{ #category : #accessing }
OpenGLSLUniform >> location [
^ location
]
{ #category : #accessing }
OpenGLSLUniform >> location: anObject [
location := anObject
]
{ #category : #accessing }
OpenGLSLUniform >> setUniformValue: value [
^ self subclassResponsibility
]
{ #category : #accessing }
OpenGLSLUniform >> uname [
^ uname
]
{ #category : #accessing }
OpenGLSLUniform >> uname: anObject [
uname := anObject
]
{ #category : #accessing }
OpenGLSLUniform >> value: values [
location = -1 ifTrue: [ ^self ].
self setUniformValue: values.
]

View File

@ -0,0 +1,148 @@
Class {
#name : #OpenGLTexImage2D,
#superclass : #DiyaBaseObject,
#instVars : [
'target',
'level',
'internalFormat',
'width',
'height',
'border',
'format',
'type',
'data'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
OpenGLTexImage2D >> border [
^ border
]
{ #category : #accessing }
OpenGLTexImage2D >> border: anObject [
border := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> bytesSize [
^(width * height) << 2
]
{ #category : #accessing }
OpenGLTexImage2D >> data [
^ data
]
{ #category : #accessing }
OpenGLTexImage2D >> data: anObject [
data := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> debug [
self
stdlog: 'Target:',target hex;
stdlog: 'level:',level asString;
stdlog: 'border :',border asString;
stdlog: 'width :',width asString;
stdlog: 'height :',height asString;
stdlog: 'type :',type hex;
stdlog: 'format :',format hex;
stdlog: 'internalformat :',internalFormat hex
]
{ #category : #accessing }
OpenGLTexImage2D >> drop [
^self subclassResponsibility
]
{ #category : #accessing }
OpenGLTexImage2D >> extent [
^ self width @ self height
]
{ #category : #accessing }
OpenGLTexImage2D >> format [
^ format
]
{ #category : #accessing }
OpenGLTexImage2D >> format: anObject [
format := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> height [
^ height
]
{ #category : #accessing }
OpenGLTexImage2D >> height: anObject [
height := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> internalFormat [
^ internalFormat
]
{ #category : #accessing }
OpenGLTexImage2D >> internalFormat: anObject [
internalFormat := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> level [
^ level
]
{ #category : #accessing }
OpenGLTexImage2D >> level: anObject [
level := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> mipmap [
^false
]
{ #category : #accessing }
OpenGLTexImage2D >> setup [
^self subclassResponsibility
]
{ #category : #accessing }
OpenGLTexImage2D >> target [
^ target
]
{ #category : #accessing }
OpenGLTexImage2D >> target: anObject [
target := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> type [
^ type
]
{ #category : #accessing }
OpenGLTexImage2D >> type: anObject [
type := anObject
]
{ #category : #accessing }
OpenGLTexImage2D >> width [
^ width
]
{ #category : #accessing }
OpenGLTexImage2D >> width: anObject [
width := anObject
]

136
Diya/OpenGLTexture.class.st Normal file
View File

@ -0,0 +1,136 @@
Class {
#name : #OpenGLTexture,
#superclass : #DiyaBaseObject,
#instVars : [
'textureID',
'unit'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLTexture class >> active: unit [
^self ffiActive: GL_TEXTURE_UNIT_BASE + unit
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> bind: target texture: texture [
^ self ffiCall: #(void glBindTexture(GLenum target,GLuint texture))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> bindDefault: target [
self bind: target texture: 0
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> delete: n pointer:textures [
^ self ffiCall: #(void glDeleteTextures(GLsizei n,const GLuint * textures))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> ffiActive: unit [
^self ffiCall: #(void glActiveTexture( GLenum unit))
]
{ #category : #'library path' }
OpenGLTexture class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> fromUnit: unit [
^self new unit: unit; yourself
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> genTexture: n pointer: textures [
^ self ffiCall: #(void glGenTextures(GLsizei n,GLuint * textures))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> generateMipmap: target [
^self ffiCall: #(void glGenerateMipmap(GLenum target))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> image2D: target level: level internalformat: internalformat w: width h: height border: border format: fmt type: type data: data [
^ self ffiCall: #(void glTexImage2D( GLenum target,GLint level,GLint internalformat,GLsizei width,GLsizei height,GLint border,GLenum fmt,GLenum type,const void * data))
]
{ #category : #'as yet unclassified' }
OpenGLTexture class >> parameteri: target pname: pname param: param [
^ self ffiCall: #(void glTexParameteri( GLenum target,GLenum pname,GLint param))
]
{ #category : #initialization }
OpenGLTexture >> active [
self class active: self unit
]
{ #category : #initialization }
OpenGLTexture >> bind: target [
^ self class bind: target texture: self textureID
]
{ #category : #initialization }
OpenGLTexture >> delete [
self class delete: 1 pointer: textureID getHandle.
]
{ #category : #initialization }
OpenGLTexture >> initialize [
textureID := FFIExternalArray externalNewType: GLint size:1.
textureID autoRelease.
textureID at:1 put: -1.
self class genTexture: 1 pointer: textureID getHandle.
unit := 0.
]
{ #category : #initialization }
OpenGLTexture >> maxTextureSize [
|ptr v|
ptr := FFIExternalArray externalNewType: GLint size:1.
ptr at:1 put: -1.
OpenGL getIntegerv: GL_MAX_TEXTURE_SIZE data: ptr getHandle.
v := ptr at:1.
ptr free.
^v
]
{ #category : #initialization }
OpenGLTexture >> setImage2D: tex2D [
self bind: tex2D target.
self class image2D: tex2D target
level: tex2D level
internalformat: tex2D internalFormat
w: tex2D width
h: tex2D height
border: tex2D border
format: tex2D format
type: tex2D type
data: tex2D data getHandle.
tex2D mipmap ifTrue:[
self class generateMipmap: tex2D target
].
]
{ #category : #initialization }
OpenGLTexture >> textureID [
^textureID at: 1
]
{ #category : #accessing }
OpenGLTexture >> unit [
^ unit
]
{ #category : #accessing }
OpenGLTexture >> unit: anObject [
unit := anObject
]

55
Diya/OpenGLTypes.class.st Normal file
View File

@ -0,0 +1,55 @@
Class {
#name : #OpenGLTypes,
#superclass : #SharedPool,
#classVars : [
'GLbitfield',
'GLboolean',
'GLbyte',
'GLchar',
'GLclampd',
'GLclampf',
'GLdouble',
'GLenum',
'GLfixed',
'GLfloat',
'GLhalf',
'GLint',
'GLint64',
'GLintptr',
'GLshort',
'GLsizei',
'GLsizeiptr',
'GLsync',
'GLubyte',
'GLuint',
'GLuint64',
'GLushort'
],
#category : #'Diya-OpenGL'
}
{ #category : #'class initialization' }
OpenGLTypes class >> initialize [
GLfloat := #float.
GLubyte := #uint8.
GLenum := #int32.
GLboolean := #uint8.
GLbitfield := #int32.
GLbyte := #int8.
GLclampd := #double.
GLclampf := #float.
GLdouble := #double.
GLfixed := #int32.
GLhalf := #uint16.
GLint := #int32.
GLint64 := #int64.
GLintptr := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLshort := #int16.
GLsizei := #int32.
GLsizeiptr := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLsync := Smalltalk wordSize = 8 ifTrue: [ #int64 ] ifFalse: [ #int32 ].
GLuint := #uint32.
GLuint64 := #uint64.
GLushort := #uint16.
GLchar := #char.
]

View File

@ -0,0 +1,101 @@
Class {
#name : #OpenGLVertexArray,
#superclass : #DiyaBaseObject,
#instVars : [
'vertexArrayID'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> bind:array [
^self ffiCall:#(void glBindVertexArray( GLuint array))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> deteleVertexArraysSize:n arrays: arrays [
^self ffiCall:#(void glDeleteVertexArrays( GLsizei n,const GLuint *arrays))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> disableArrayAttribute: vaobj index: index [
^self ffiCall: #(void glDisableVertexArrayAttrib( GLuint vaobj,GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> disableAttributeArray: index [
^self ffiCall: #(void glDisableVertexAttribArray( GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> enableArrayAttribute: vaobj index: index [
^self ffiCall: #(void glEnableVertexArrayAttrib( GLuint vaobj,GLuint index))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> enableAttributeArray: index [
^self ffiCall: #(void glEnableVertexAttribArray( GLuint index))
]
{ #category : #'library path' }
OpenGLVertexArray class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> genVertexArraysSize: n arrays: arrays [
^self ffiCall:#(void glGenVertexArrays( GLsizei n,GLuint *arrays))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributeLPointerIndex: index size: size type: type stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribLPointer( GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributePointerIndex: index size: size type: type normalized: normalized stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribPointer( GLuint index,GLint size,GLenum type,GLboolean normalized,GLsizei stride,const void * pointer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray class >> vertexAttributelPointerIndex: index size: size type: type stride: stride pointer: pointer [
^self ffiCall: #(void glVertexAttribIPointer( GLuint index,GLint size,GLenum type,GLsizei stride,const void * pointer))
]
{ #category : #accessing }
OpenGLVertexArray >> bind [
OpenGLVertexArray bind: self vertexArrayID
]
{ #category : #accessing }
OpenGLVertexArray >> delete [
OpenGLVertexArray deteleVertexArraysSize:1 arrays: vertexArrayID getHandle.
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray >> disableAttribute: index [
^OpenGLVertexArray disableAttributeArray: index
]
{ #category : #'as yet unclassified' }
OpenGLVertexArray >> enableAttribute: index [
^OpenGLVertexArray enableAttributeArray: index
]
{ #category : #initialization }
OpenGLVertexArray >> initialize [
vertexArrayID := FFIExternalArray externalNewType: GLint size:1.
vertexArrayID autoRelease.
vertexArrayID at:1 put: -1.
OpenGLVertexArray genVertexArraysSize: 1 arrays: vertexArrayID getHandle.
]
{ #category : #accessing }
OpenGLVertexArray >> vertexArrayID [
^vertexArrayID at: 1
]

View File

@ -0,0 +1,100 @@
Class {
#name : #OpenGLVertexBuffer,
#superclass : #DiyaBaseObject,
#instVars : [
'vertexBufferID'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> bind: target buffer: buffer [
^ self ffiCall: #(void glBindBuffer( GLenum target,GLuint buffer))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> bufferData:target size: size data: data usage: usage [
^self ffiCall: #(void glBufferData( GLenum target,GLsizeiptr size,const void * data,GLenum usage))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> deleteBuffersSize:n buffers: buffers [
^self ffiCall: #(void glDeleteBuffers( GLsizei n,const GLuint * buffers))
]
{ #category : #'library path' }
OpenGLVertexBuffer class >> ffiLibraryName [
^ OpenGL ffiLibraryName
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> genVertexBuffersSize:n buffers: buffers [
^self ffiCall: #(void glGenBuffers( GLsizei n,GLuint * buffers))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> getBufferData: target offset: offset size: size data: data [
^self ffiCall: #(void glGetBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,void * data))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> namedBufferData:buffer size: size data: data usage: usage [
^self ffiCall: #(void glNamedBufferData(GLuint buffer,GLsizeiptr size,const void *data,GLenum usage))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer class >> subData:target offset: offset size: size data: data [
^self ffiCall: #(void glBufferSubData(GLenum target,GLintptr offset,GLsizeiptr size,const void * data))
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> bind: target [
^OpenGLVertexBuffer bind:target buffer: self vertexBufferID
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> data:target data: data size: size usage: usage [
self bind: target.
^OpenGLVertexBuffer bufferData: target size: size data:(data ifNil:[data] ifNotNil: [data getHandle]) usage: usage
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> data:target data: data usage: usage [
self bind: target.
^OpenGLVertexBuffer bufferData: target size: (data size) << 2 data:data getHandle usage: usage
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> delete [
OpenGLVertexBuffer deleteBuffersSize: 1 buffers: vertexBufferID getHandle.
]
{ #category : #initialization }
OpenGLVertexBuffer >> initialize [
vertexBufferID := FFIExternalArray externalNewType: GLint size:1.
vertexBufferID at:1 put: -1.
vertexBufferID autoRelease.
OpenGLVertexBuffer genVertexBuffersSize: 1 buffers: vertexBufferID getHandle.
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> subData:target offset: offset data:data [
self bind: target.
^OpenGLVertexBuffer subData: target offset: offset size: (data size) << 2 data: data getHandle
]
{ #category : #'as yet unclassified' }
OpenGLVertexBuffer >> subData:target offset: offset data:data size: size [
self bind: target.
^OpenGLVertexBuffer subData: target offset: offset size: size data: data getHandle
]
{ #category : #initialization }
OpenGLVertexBuffer >> vertexBufferID [
^ vertexBufferID at: 1
]

View File

@ -0,0 +1,96 @@
Class {
#name : #OrthoProjectionMatrix,
#superclass : #ProjectionMatrix,
#instVars : [
'viewport',
'near',
'far'
],
#category : #'Diya-Math'
}
{ #category : #'as yet unclassified' }
OrthoProjectionMatrix class >> fromDisplay: display [
^ self viewport: (Rectangle origin: 0@0 corner: (display w) @ (display h) ) near: -1.0 far: 1.0.
]
{ #category : #'as yet unclassified' }
OrthoProjectionMatrix class >> viewport:v near:n far:f [
^ self new setViewport: v near:n far:f; yourself.
]
{ #category : #accessing }
OrthoProjectionMatrix >> bottom [
^ viewport origin y
]
{ #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 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 bottom - self top)) negated.
self at:4 at:3 put: ((self far + self near)/(self far - self near)) negated.
]
{ #category : #initialization }
OrthoProjectionMatrix >> default [
viewport := Rectangle origin: -1.0@ -1.0 corner: 1.0@1.0.
near := -1.0.
far := 1.0.
]
{ #category : #accessing }
OrthoProjectionMatrix >> far [
^ far
]
{ #category : #accessing }
OrthoProjectionMatrix >> far: anObject [
far := anObject
]
{ #category : #accessing }
OrthoProjectionMatrix >> left [
^ viewport origin x
]
{ #category : #accessing }
OrthoProjectionMatrix >> near [
^ near
]
{ #category : #accessing }
OrthoProjectionMatrix >> near: anObject [
near := anObject
]
{ #category : #accessing }
OrthoProjectionMatrix >> right [
^ viewport corner x
]
{ #category : #initialization }
OrthoProjectionMatrix >> setViewport: v near: n far:f [
viewport := v.
near := n.
far := f.
self update.
]
{ #category : #accessing }
OrthoProjectionMatrix >> top [
^ viewport corner y
]
{ #category : #accessing }
OrthoProjectionMatrix >> viewport [
^ viewport
]
{ #category : #accessing }
OrthoProjectionMatrix >> viewport: anObject [
viewport := anObject
]

11
Diya/Point.extension.st Normal file
View File

@ -0,0 +1,11 @@
Extension { #name : #Point }
{ #category : #'*Diya' }
Point >> asArray3F [
^ self asArray3F: 1.0
]
{ #category : #'*Diya' }
Point >> asArray3F: z [
^ { self x. self y. z }
]

View File

@ -0,0 +1,55 @@
Class {
#name : #ProjectionMatrix,
#superclass : #Array2D,
#instVars : [
'buffer'
],
#category : #'Diya-Math'
}
{ #category : #'instance creation' }
ProjectionMatrix class >> fromDisplay: display [
^self subclassResponsibility
]
{ #category : #accessing }
ProjectionMatrix >> buffer [
^ buffer
]
{ #category : #initialization }
ProjectionMatrix >> calculate [
self subclassResponsibility
]
{ #category : #initialization }
ProjectionMatrix >> default [
]
{ #category : #initialization }
ProjectionMatrix >> handle [
^buffer getHandle
]
{ #category : #initialization }
ProjectionMatrix >> initialize [
super initialize.
self rows:4 columns: 4 contents: ((Array new: 16) atAllPut: 0).
1 to: 4 do: [ :i| self at: i at:i put: 1.0 ].
buffer := FFIExternalArray externalNewType: #float size: self size.
buffer autoRelease.
self default.
self update
]
{ #category : #initialization }
ProjectionMatrix >> update [
|i|
self calculate.
i := 1.
self asArray do:[:e|
buffer at:i put:e.
i := i+1
].
]

View File

@ -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
View 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'
)
]

View File

@ -0,0 +1,6 @@
Extension { #name : #SDL2MappedEvent }
{ #category : #'*Diya' }
SDL2MappedEvent >> triggableOn: aNode [
^aNode isRoot
]

View File

@ -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
]

View 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 )
]

View 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 )
]

View 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)).
]

View File

@ -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))

View File

@ -0,0 +1,6 @@
Extension { #name : #SmalltalkImage }
{ #category : #'*Diya' }
SmalltalkImage >> getenv: key [
^ self ffiCall: #(char *getenv(const char *key)) module: LibC
]

14
Diya/Uniform1F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform1F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform1F >> setUniformValue: value [
OpenGLSLUniform uniform1f: location value: value
]

14
Diya/Uniform1i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform1i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform1i >> setUniformValue: value [
OpenGLSLUniform uniform1i: location value: value
]

14
Diya/Uniform2F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform2F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform2F >> setUniformValue: value [
OpenGLSLUniform uniform2f: location value: value first value: value last
]

14
Diya/Uniform2i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform2i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform2i >> setUniformValue: value [
OpenGLSLUniform uniform2i: location value: value first value: value last
]

14
Diya/Uniform3F.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform3F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform3F >> setUniformValue: value [
OpenGLSLUniform uniform3f: location value: value first value: (value at:2) value: value last
]

14
Diya/Uniform3i.class.st Normal file
View File

@ -0,0 +1,14 @@
Class {
#name : #Uniform3i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform3i >> setUniformValue: value [
OpenGLSLUniform uniform3i: location value: value first value: (value at:2) value: value last
]

18
Diya/Uniform4F.class.st Normal file
View File

@ -0,0 +1,18 @@
Class {
#name : #Uniform4F,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform4F >> setUniformValue: value [
OpenGLSLUniform uniform4f: location
value: value first
value: (value at:2)
value: (value at:3)
value: value last
]

18
Diya/Uniform4i.class.st Normal file
View File

@ -0,0 +1,18 @@
Class {
#name : #Uniform4i,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
Uniform4i >> setUniformValue: value [
OpenGLSLUniform uniform4i: location
value: value first
value: (value at:2)
value: (value at:3)
value: value last
]

View File

@ -0,0 +1,18 @@
Class {
#name : #UniformMatrix3fv,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
UniformMatrix3fv >> setUniformValue: value [
OpenGLSLUniform
uniformMatrix3fv: location
count: 1
transpose: value first
value: value last getHandle
]

View File

@ -0,0 +1,18 @@
Class {
#name : #UniformMatrix4fv,
#superclass : #OpenGLSLUniform,
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-OpenGL'
}
{ #category : #accessing }
UniformMatrix4fv >> setUniformValue: value [
OpenGLSLUniform
uniformMatrix4fv: location
count: 1
transpose: value first
value: value last getHandle
]

27
Jenkinsfile vendored Normal file
View 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
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More