1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-07-16 13:59:54 +02:00

54 Commits

Author SHA1 Message Date
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
90 changed files with 4837 additions and 120 deletions

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

@ -0,0 +1,6 @@
Extension { #name : #Array }
{ #category : #'*Diya' }
Array >> asPoint [
^ (self at: 1 ifAbsent:[0]) @ (self at: 2 ifAbsent:[0])
]

41
Diya/Array2D.extension.st Normal file
View File

@ -0,0 +1,41 @@
Extension { #name : #Array2D }
{ #category : #'*Diya' }
Array2D >> asGLBuffer [
|buffer i|
i := 1.
buffer := FFIExternalArray externalNewType: #float size: self size.
self asArray do:[:e|
buffer at:i put:e.
i := i+1
].
buffer autoRelease.
^buffer
]
{ #category : #'*Diya' }
Array2D class >> rotationMatrix2D: rotation [
^Array2D rows: 3 columns: 3 contents:{
rotation cos. (rotation sin) negated. 0.0.
rotation sin. rotation cos. 0.0.
0.0. 0.0. 1.0
}
]
{ #category : #'*Diya' }
Array2D class >> scaleMatrix2D: scale [
^Array2D rows: 3 columns: 3 contents:{
scale x. 0.0. 0.0.
0.0. scale y. 0.0.
0.0. 0.0. 1.0
}
]
{ #category : #'*Diya' }
Array2D class >> translateMatrix2D: translation [
^Array2D rows: 3 columns: 3 contents: {
1.0. 0.0. translation x.
0.0. 1.0. translation y.
0.0. 0.0. 1.0
}
]

View File

@ -0,0 +1,42 @@
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 : #'as yet unclassified' }
AssetManager >> from: location [
base := location
]
{ #category : #initialization }
AssetManager >> initialize [
super initialize.
assets := Dictionary new.
base := self class defaultAssetLocation
]
{ #category : #'as yet unclassified' }
AssetManager >> name: fileName of: type [
^assets at: fileName ifAbsentPut: [(type fromFile: (base / fileName))].
]
{ #category : #'as yet unclassified' }
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 }
]

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

@ -0,0 +1,97 @@
Class {
#name : #Diya2DNode,
#superclass : #DiyaNode,
#instVars : [
'vbuffer'
],
#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 := Array2D identity: 3.
shader := Diya2DShader uniqueInstance.
vbuffer := nil.
]
{ #category : #'as yet unclassified' }
Diya2DNode >> inner: aPoint [
^ self boundingBox containsPoint: (self local: aPoint)
]
{ #category : #accessing }
Diya2DNode >> local: aPoint [
^((aPoint - (0@0 applyTf: self tf) )/ scale)
rotateBy: rotation about: 0@0.
]
{ #category : #'as yet unclassified' }
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 := Array2D identity:3.
"translation"
translation = (0@0) ifFalse:[
tf := tf +* (Array2D translateMatrix2D: translation)].
"rotation"
rotation = 0 ifFalse:[
tf := tf +* (Array2D rotationMatrix2D: rotation )].
"scale"
scale = (1@1) ifFalse:[
tf := tf +* (Array2D scaleMatrix2D: scale)].
self parent ifNil: [ ^self ].
self parent isRoot ifFalse: [tf := self parent tf +* tf ].
children ifNotNil: [children do:[:c| c updateTF ]].
]
{ #category : #accessing }
Diya2DNode >> width [
^ self extent x
]

View File

@ -0,0 +1,140 @@
Class {
#name : #Diya2DPrimShape,
#superclass : #Diya2DNode,
#instVars : [
'texture',
'type',
'bbox'
],
#category : #'Diya-Graphics'
}
{ #category : #accessing }
Diya2DPrimShape >> bgColor [
^style get: #bgcolor
]
{ #category : #accessing }
Diya2DPrimShape >> bgColor: c [
^style set: #bgcolor value: c
]
{ #category : #accessing }
Diya2DPrimShape >> borderColor [
^style get: #borderColor
]
{ #category : #accessing }
Diya2DPrimShape >> borderColor: c [
style set: #borderColor value: c.
]
{ #category : #accessing }
Diya2DPrimShape >> borderWidth [
^style get: #border
]
{ #category : #accessing }
Diya2DPrimShape >> borderWidth: w [
style set: #border value: w.
]
{ #category : #accessing }
Diya2DPrimShape >> boundingBox [
^ bbox applyTf: self tf.
]
{ #category : #accessing }
Diya2DPrimShape >> color [
^ self style get: #color.
]
{ #category : #accessing }
Diya2DPrimShape >> color: value [
^ self style set: #color value: value
]
{ #category : #initialization }
Diya2DPrimShape >> draw [
vbuffer ifNil: [ ^self ].
"configure vao vbo for texture QUAD"
self texture ifNotNil: [
self texture setup.
context texture0 setImage2D: self texture.
context texture0 active.
].
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
OpenGL drawArrays: type first:0 count:((vbuffer size )>> 2 ).
"reset value"
self texture ifNotNil: [self texture drop.].
self borderWidth > 0 ifTrue: [ self drawBorder ].
context vao disableAttribute: 0.
]
{ #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.
children := nil.
type := GL_TRIANGLES.
bbox := Rectangle origin: 0@0 corner: 0@0.
]
{ #category : #'as yet unclassified' }
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,73 @@
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) {
vec4 texcolor = vec4(0,0,0,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);
}
else if(u_texture_type == 1)
{
texcolor = vec4(1,1,1,1);
}
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,91 @@
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 color: Color orange.
pointer borderColor: Color red.
pointer borderWidth: 2.
root on: #keydown do:[:e| Transcript show: 'keydown...';cr. running := false.].
root on: #quit do: [:e| running := false].
root on: #(fingerdown fingermotion mousemotion) do:[:e|
pointer position: e mapped worldPosition.
"Transcript show: e mapped worldPosition asString;cr."
DiyaRendererContext uniqueInstance mouse: (e mapped x) @ (e mapped y).
].
]
{ #category : #initialization }
DiyaApplicationLauncher >> defaultApplication [
^DiyaExampleApp
]
{ #category : #'as yet unclassified' }
DiyaApplicationLauncher >> delta: delta [
|fps|
delta = 0 ifTrue:[^self].
fps := ((1000/delta) asInteger).
txtFPS data: ('FPS:', fps asString).
]
{ #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 appNode addNode: currapp root.
self context assets: currapp am.
currapp setup.
]
{ #category : #initialization }
DiyaApplicationLauncher >> main [
[(SDL2 pollEvent: event) > 0] whileTrue: [
root trigger: (DiyaEvent from: event mapped).
].
currapp ifNotNil: [currapp main.].
root render.
]
{ #category : #accessing }
DiyaApplicationLauncher >> running [
^ running
]
{ #category : #initialization }
DiyaApplicationLauncher >> setup [
event := SDL_Event new.
root addNode: (Diya2DNode 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 fontSize: 18.
txtFPS color: Color red.
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,12 @@
Class {
#name : #DiyaBaseApplication,
#superclass : #DiyaApplicationModel,
#category : #'Diya-Applications'
}
{ #category : #initialization }
DiyaBaseApplication >> initialize [
super initialize.
root := Diya2DNode new.
am := AssetManager new.
]

View File

@ -3,3 +3,43 @@ 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 : #accessing }
DiyaBaseObject >> logError: string [
self stderr nextPutAll: string; cr
]
{ #category : #asserting }
DiyaBaseObject >> shouldNotBeCalled [
^DiyaCoreAPIError signal: 'Should not be called'
]
{ #category : #accessing }
DiyaBaseObject >> stderr [
^VTermOutputDriver stderr
]
{ #category : #accessing }
DiyaBaseObject >> stderror: string [
self stderr nextPutAll: string; nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdlog: string [
self stdout nextPutAll: string;
nextPutAll: Character cr asString.
]
{ #category : #accessing }
DiyaBaseObject >> stdout [
^ VTermOutputDriver stdout
]

View File

@ -1,16 +1,15 @@
Class {
#name : #DiyaBoot,
#superclass : #DiyaBaseObject,
#superclass : #DiyaSingleton,
#instVars : [
'running',
'window',
'renderer',
'display'
],
#classVars : [
'singleton'
'context',
'display',
'clock'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants',
'SDL2Types'
],
@ -18,8 +17,8 @@ Class {
}
{ #category : #'instance creation' }
DiyaBoot class >> reset [
singleton := nil
DiyaBoot class >> maxFPS [
^60
]
{ #category : #'instance creation' }
@ -32,159 +31,177 @@ 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.
ifFalse: [ ^ DiyaCoreAPIError signal: SDL2 getErrorMessage ].
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
SDL2 showCursor: 0.
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.
|delta launcher|
DiyaRendererContext uniqueInstance.
launcher := DiyaApplicationLauncher uniqueInstance.
launcher setup.
self GLinit.
[ launcher running ] whileTrue: [
delta := DiyaClock uniqueInstance delta asMilliSeconds.
launcher delta: delta.
DiyaClock uniqueInstance tick.
launcher main.
SDL2 glSwapWindow: window.
delta := DiyaClock uniqueInstance delta asMilliSeconds.
SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta).
].
]
{ #category : #events }
DiyaBoot >> run [
|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.
display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0.
self startx
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:'Display resolution: ';
nextPutAll:display w asString;
nextPutAll: 'x';
nextPutAll: display h asString; 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;
useProjection: OrthoProjectionMatrix.
self render.
renderer destroy.
context delete.
window destroy.
DiyaSingleton resetAll.
SDL2 quit.
Transcript show: 'System quit'; cr.
]

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

@ -0,0 +1,55 @@
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: id [
label icon: id.
label updateLayout.
]
{ #category : #accessing }
DiyaButton >> iconSize: size [
label iconSize: size.
]
{ #category : #initialization }
DiyaButton >> initialize [
super initialize.
style
set:#textAlign value: #center;
set:#textVAlign value: #middle;
set:#border value: 1.
rec := self addNode: (DiyaRectangle new).
label := self addNode: (DiyaLabel new).
label txt
wordWrap: false.
]
{ #category : #accessing }
DiyaButton >> label [
^ label
]
{ #category : #accessing }
DiyaButton >> text: string [
label txt: string.
]
{ #category : #accessing }
DiyaButton >> updateLayout [
rec extent: self extent.
label position: 0@0.
label extent: self extent.
]

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
]

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

@ -0,0 +1,30 @@
Class {
#name : #DiyaClock,
#superclass : #DiyaSingleton,
#instVars : [
'monotonic',
'lastTick'
],
#category : #'Diya-Runtime'
}
{ #category : #initialization }
DiyaClock >> delta [
^(DateAndTime now) - lastTick
]
{ #category : #initialization }
DiyaClock >> elapsedTime [
^(DateAndTime now) - monotonic
]
{ #category : #initialization }
DiyaClock >> initialize [
monotonic := DateAndTime now.
lastTick := monotonic.
]
{ #category : #initialization }
DiyaClock >> tick [
lastTick := DateAndTime now.
]

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:0 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,20 @@
Class {
#name : #DiyaDefaultStyle,
#superclass : #DiyaNodeStyle,
#category : #'Diya-Graphics'
}
{ #category : #initialization }
DiyaDefaultStyle >> initialize [
super initialize.
self set: #bgcolor value:(Color r: 0.2118 g: 0.2118 b: 0.2118).
self set: #color value: Color white.
self set: #border value: 0.
self set: #fontSize value: 18.
self set: #fontFamily value: DiyaFontManager uniqueInstance defaultFamily.
self set: #fontStyle value: DiyaFontManager uniqueInstance defaultStyle.
self set: #borderColor value: (Color r: 0.051 g: 0.051 b: 0.051).
self set: #bgcolor2 value: (Color r: 0.1529 g: 0.1529 b: 0.1529).
self set: #textAlign value: #left.
self set: #textVAlign value: #top
]

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

@ -0,0 +1,107 @@
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 >> draw [
OpenGL
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
super draw.
OpenGL
disable: GL_BLEND
]
{ #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 >> rx [
^ rx
]
{ #category : #accessing }
DiyaEllipse >> rx: anObject [
rx := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaEllipse >> ry [
^ ry
]
{ #category : #accessing }
DiyaEllipse >> ry: anObject [
ry := anObject.
dirty := true
]
{ #category : #initialization }
DiyaEllipse >> setUpShader [
super setUpShader.
self shader
setUniform: #u_border value: (style get: #border);
setUniform: #u_border_color value: (style get:#borderColor) asGL4FArray;
setUniform: #u_rx value: rx;
setUniform: #u_ry value: ry.
]
{ #category : #accessing }
DiyaEllipse >> update [
bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
{
bbox origin x. bbox 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
]

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'
}

40
Diya/DiyaEvent.class.st Normal file
View File

@ -0,0 +1,40 @@
Class {
#name : #DiyaEvent,
#superclass : #DiyaBaseObject,
#instVars : [
'enable',
'mapped'
],
#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
]

View File

@ -0,0 +1,83 @@
Class {
#name : #DiyaExampleApp,
#superclass : #DiyaBaseApplication,
#category : #'Diya-Applications'
}
{ #category : #accessing }
DiyaExampleApp >> cleanup [
]
{ #category : #accessing }
DiyaExampleApp >> main [
]
{ #category : #accessing }
DiyaExampleApp >> setup [
|node node1 ell label icon button|
label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@24.
label color: Color orange.
label iconSize: 24.
label icon: 16rF254.
node1 := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 300 @ 40.
"node1 rotation: (Float pi / 8.0)."
node1 scale: 1.2@1.2.
node1 on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'Mouse ', (node1 local: e mapped worldPosition) asIntegerPoint asString].
node := root addNode: (DiyaImageView from:'mrsang.png') at: 10 @ 400.
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node borderWidth:1.
node bgColor: Color cyan.
node borderColor: Color red.
node borderWidth: 3.0.
node extent:200@200.
node := root addNode: (DiyaRectangle new) at: 10@80.
node borderWidth: 1.
node extent: 240@320.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@80.
node extent: 240@320.
node wordWrap: true.
node fontSize: 16.
node bgColor: Color transparent.
node align: #center.
node := root addNode: (DiyaLine from: 10@10 to: 200@200).
node color: (Color red).
node borderWidth: 2.0.
ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 100@300.
ell borderColor: Color red.
ell color: Color white.
ell bgColor: Color cyan.
ell rotation: Float pi / 6.0.
ell borderWidth: 3.0.
"node rotation: Float pi / 2.0."
ell textureNamed:'mrsang.png'.
ell on: #(mousebuttondown fingerdown) do:[:e|
label txt: 'Ellipse clicked', (ell local:e mapped worldPosition) asIntegerPoint asString].
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}).
node color: Color green.
node borderColor: Color red.
node textureNamed: 'mrsang.png'.
node borderWidth: 3.0.
icon := root addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 240@500.
icon fontSize: 24.
icon bgColor: Color transparent.
icon color: (Color r: 209/255 g: 66/255 b:245/255 ).
button := root addNode: (DiyaButton text: 'Click me !') at: 240@460.
button extent: 200@40.
button icon:16rF185"'mrsang.png'".
button iconSize: 24.
^ 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
@ -21,5 +26,10 @@ DiyaFFIBase class >> moduleName [
^ aName
].
].
self error: 'Unable to find FFI library (', self checkSymbol, ')'.
DiyaCoreAPIError signal: 'Unable to find FFI library (', self checkSymbol, ')'.
]
{ #category : #'library path' }
DiyaFFIBase >> ffiLibraryName [
^self class ffiLibraryName
]

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,69 @@
Class {
#name : #DiyaFontIcon,
#superclass : #DiyaText,
#pools : [
'FT2Types'
],
#category : #'Diya-Graphics'
}
{ #category : #initialization }
DiyaFontIcon >> data: code [
super data:(code isArray ifTrue: [ code ] ifFalse:[{code}]).
bbox := Rectangle origin: 0@0 corner: ((data size) * (self fontSize) ) @ self fontSize.
]
{ #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 : #initialization }
DiyaFontIcon >> fontName: name style: face size: size [
super fontName: name style:face size: size.
data ifNil: [ ^ self ].
bbox := Rectangle origin: 0@0 corner: ((data size) * size ) @ size.
]
{ #category : #initialization }
DiyaFontIcon >> getLinebreakIndices: delta [
self shouldNotBeCalled
]
{ #category : #accessing }
DiyaFontIcon >> iconSize [
^ self fontSize
]
{ #category : #accessing }
DiyaFontIcon >> iconSize: v [
"self extent: "
^ self fontSize: v
]
{ #category : #initialization }
DiyaFontIcon >> initialize [
super initialize.
data := { }.
self fontName: 'bootstrap-icons' style: 'Regular' size: 16.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer autoRelease.
]
{ #category : #initialization }
DiyaFontIcon >> lastSeparatorFrom: i [
self shouldNotBeCalled
]

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.
Transcript show: 'Loaded font face ', face styleName;cr.
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,21 @@
Class {
#name : #DiyaImageIcon,
#superclass : #DiyaImageView,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaImageIcon >> iconSize [
^ self extent x
]
{ #category : #accessing }
DiyaImageIcon >> iconSize:v [
^ self extent: v@v
]
{ #category : #accessing }
DiyaImageIcon >> initialize [
super initialize.
style set: #border value: 0
]

View File

@ -0,0 +1,84 @@
Class {
#name : #DiyaImageTex,
#superclass : #OpenGLTexImage2D,
#instVars : [
'path'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #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 : #'instance creation' }
DiyaImageTex >> fromFile: aPath [
|form color index|
path := aPath.
Transcript show: 'Loading texture from ', path fullName;cr.
form := ImageReadWriter formFromFileNamed: path.
data := FFIExternalArray externalNewType: GLubyte size:(form width) * (form height) * 4.
LibC memset: data getHandle value: 0 size: data size.
data autoRelease.
width := form width.
height := form height.
index := 1.
0 to: height -1 do:[:y|
0 to: width - 1 do:[:x|
color := (form colorAt: x@y) as4bytesRGB.
data
at: index put: color first;
at: index + 1 put: (color at: 2);
at: index +2 put: (color at: 3);
at: index + 3 put: color last.
index := index + 4.
]
].
]
{ #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 >> path [
^ path
]
{ #category : #accessing }
DiyaImageTex >> setup [
OpenGL
enable: GL_CULL_FACE;
enable: GL_BLEND;
blendFnWithSfactor: GL_SRC_ALPHA dfactor: GL_ONE_MINUS_SRC_ALPHA.
OpenGLTexture
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_S param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_WRAP_T param: GL_CLAMP_TO_EDGE;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MIN_FILTER param: GL_LINEAR;
parameteri: GL_TEXTURE_2D pname: GL_TEXTURE_MAG_FILTER param: GL_LINEAR.
]

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
]

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

@ -0,0 +1,100 @@
Class {
#name : #DiyaLabel,
#superclass : #DiyaWidget,
#instVars : [
'txt',
'icon'
],
#category : #'Diya-Widgets'
}
{ #category : #accessing }
DiyaLabel >> fontSize [
^txt fontSize.
]
{ #category : #accessing }
DiyaLabel >> fontSize: value [
txt fontSize: value.
"icon ifNotNil: [ icon fontSize: value ]."
"dirty := true."
]
{ #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).
icon align: #left].
anObject isString ifTrue: [
icon := self addNode: (DiyaImageIcon from: anObject).
].
icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification'].
dirty := true.
]
{ #category : #accessing }
DiyaLabel >> iconSize [
icon ifNil: [ ^0 ].
^ icon iconSize
]
{ #category : #accessing }
DiyaLabel >> iconSize: v [
icon ifNil: [ ^self ].
icon iconSize: v
]
{ #category : #initialization }
DiyaLabel >> initialize [
super initialize.
txt := self addNode:(DiyaText data: '').
icon := nil.
self extent: 0@0.
]
{ #category : #accessing }
DiyaLabel >> txt [
^ txt
]
{ #category : #accessing }
DiyaLabel >> txt: anObject [
txt data: anObject.
dirty := true
]
{ #category : #accessing }
DiyaLabel >> updateLayout [
|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 update.
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)).
]

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

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

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

@ -0,0 +1,111 @@
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.
dirty := true.
]
{ #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.
style set: #border value: 0
]
{ #category : #'as yet unclassified' }
DiyaLine >> inner: aPoint [
^false
]
{ #category : #accessing }
DiyaLine >> to [
^ to
]
{ #category : #accessing }
DiyaLine >> to: anObject [
to := anObject.
dirty := true.
]
{ #category : #accessing }
DiyaLine >> update [
|extent|
bbox := (Rectangle origin: from corner: to ).
bbox origin = translation ifFalse:[self position: bbox origin].
from := from - bbox origin.
to := to - bbox origin.
extent := bbox extent.
bbox := (Rectangle origin: 0@0 corner: extent ).
{
0.0. 0.0. 0.0. 0.0.
extent x. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

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

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

@ -0,0 +1,249 @@
Class {
#name : #DiyaNode,
#superclass : #DiyaBaseObject,
#instVars : [
'translation',
'parent',
'children',
'scale',
'rotation',
'tf',
'shader',
'context',
'dirty',
'ehandlers',
'root',
'style',
'id'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes',
'SDL2Constants'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaNode class >> with: shader [
^self new shader: shader; yourself
]
{ #category : #accessing }
DiyaNode >> addNode: node [
^self addNode: node at: 0@0
]
{ #category : #accessing }
DiyaNode >> addNode: node at: pos [
children ifNil: [ ^self ].
node parent: self.
node position: pos.
children add: node.
node root: self root.
node style parent: style.
^ node
]
{ #category : #accessing }
DiyaNode >> boundingBox [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> children [
^children
]
{ #category : #accessing }
DiyaNode >> draw [
self subclassResponsibility
]
{ #category : #requirements }
DiyaNode >> empty [
children := OrderedCollection new.
]
{ #category : #accessing }
DiyaNode >> extent [
^ self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> id [
^ id
]
{ #category : #initialization }
DiyaNode >> initialize [
super initialize.
parent := nil.
shader := nil.
context := DiyaRendererContext uniqueInstance.
children := OrderedCollection new.
dirty := false.
ehandlers := Dictionary new.
style := DiyaNodeStyle new.
root := nil.
id := Random new nextInt: 1e6
]
{ #category : #'as yet unclassified' }
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 >> position [
^ translation
]
{ #category : #accessing }
DiyaNode >> position: anObject [
translation := anObject.
self updateTF.
]
{ #category : #convenience }
DiyaNode >> register: aBlock to: eventName [
|evtCode|
evtCode := SDL2Constants bindingOf: ('SDL_', eventName asUppercase).
evtCode ifNil: [ ^DiyaCoreAPIError signal: 'Unknow event ', eventName ].
ehandlers at: evtCode value put: aBlock.
]
{ #category : #accessing }
DiyaNode >> render [
dirty ifTrue:[
dirty := self update not].
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
]
{ #category : #accessing }
DiyaNode >> rotation [
^ rotation
]
{ #category : #accessing }
DiyaNode >> rotation: anObject [
rotation := anObject.
self updateTF.
]
{ #category : #accessing }
DiyaNode >> scale [
^ scale
]
{ #category : #accessing }
DiyaNode >> scale: anObject [
scale := anObject.
self updateTF.
]
{ #category : #accessing }
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 : #accessing }
DiyaNode >> style [
^style
]
{ #category : #accessing }
DiyaNode >> style: aStyle [
style := aStyle.
dirty := true.
parent ifNotNil: [ style parent: parent style ]
]
{ #category : #accessing }
DiyaNode >> tf [
^ tf
]
{ #category : #'as yet unclassified' }
DiyaNode >> trigger: evt [
evt enable ifFalse:[^self].
ehandlers at: evt mapped type ifPresent:[:handler| handler value: evt].
children ifNil: [^self].
evt enable ifTrue: [
"evt mapped triggableOn: children first."
children select: [:node | evt mapped triggableOn: node ] thenDo:[:node| node trigger: evt]
].
]
{ #category : #accessing }
DiyaNode >> update [
^self subclassResponsibility
]
{ #category : #accessing }
DiyaNode >> updateTF [
self subclassResponsibility
]

View File

@ -0,0 +1,45 @@
Class {
#name : #DiyaNodeStyle,
#superclass : #DiyaBaseObject,
#instVars : [
'styles',
'parent'
],
#category : #'Diya-Graphics'
}
{ #category : #'as yet unclassified' }
DiyaNodeStyle class >> inherit: parent [
^self new parent: parent; yourself
]
{ #category : #initialization }
DiyaNodeStyle >> get: styleName [
^ styles at: styleName ifAbsent: [ parent ifNotNil: [ parent get: styleName ] ifNil: nil]
]
{ #category : #initialization }
DiyaNodeStyle >> initialize [
super initialize.
styles := Dictionary new.
parent := nil.
"self set: #bgcolor value: Color transparent.
self set: #color value:Color white.
self set: #border value: 0.
self set: #borderColor value: Color transparent."
]
{ #category : #accessing }
DiyaNodeStyle >> parent [
^ parent
]
{ #category : #accessing }
DiyaNodeStyle >> parent: anObject [
parent := anObject
]
{ #category : #initialization }
DiyaNodeStyle >> set: styleName value: value [
styles at: styleName put: value
]

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

@ -0,0 +1,67 @@
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.
dirty := true
]
{ #category : #accessing }
DiyaPolygon >> recFromPoints [
|maxX maxY minX minY x y|
maxX := minX := (points at: 1) x.
maxY := minY := (points at: 1) y.
points do: [ :p|
x := p x.
y := p y.
maxX := maxX max: x.
maxY := maxY max: y.
minX := minX min: x.
minY := minY min: y.
].
^ Rectangle origin: minX@minY corner: maxX @ maxY
]
{ #category : #accessing }
DiyaPolygon >> update [
bbox := self recFromPoints.
translation = bbox origin ifFalse:[ self position: bbox origin].
points := points collect:[:e | e - bbox origin].
bbox := self recFromPoints.
self calculateVertices.
^true
]

View File

@ -0,0 +1,50 @@
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:0 count: (vbuffer size >> 2).
]
{ #category : #accessing }
DiyaRectangle >> extent: v [
bbox := Rectangle origin:0@0 corner: v.
dirty := true
]
{ #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 >> update [
|extent|
extent := self extent.
{
0. 0. 0.0. 0.0.
0. extent y. 0.0. 1.0.
extent x. extent y. 1.0. 1.0.
extent x. 0. 1.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e].
^true
]

View File

@ -0,0 +1,108 @@
Class {
#name : #DiyaRendererContext,
#superclass : #DiyaSingleton,
#instVars : [
'mouse',
'display',
'vbo',
'vao',
'texture0',
'projection',
'assets'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #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 [
vao delete.
vbo delete.
texture0 delete.
]
{ #category : #accessing }
DiyaRendererContext >> display [
^ display
]
{ #category : #accessing }
DiyaRendererContext >> display: anObject [
display := anObject
]
{ #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.
]
{ #category : #accessing }
DiyaRendererContext >> mouse [
^ mouse
]
{ #category : #accessing }
DiyaRendererContext >> mouse: anObject [
mouse := anObject
]
{ #category : #accessing }
DiyaRendererContext >> projection [
^ projection
]
{ #category : #'as yet unclassified' }
DiyaRendererContext >> resolution [
^ (display w) @ (display h)
]
{ #category : #accessing }
DiyaRendererContext >> texture0 [
^ texture0
]
{ #category : #'as yet unclassified' }
DiyaRendererContext >> useProjection: aClass [
projection := aClass fromDisplay: self display
]
{ #category : #accessing }
DiyaRendererContext >> vao [
^ vao
]
{ #category : #accessing }
DiyaRendererContext >> vbo [
^ vbo
]

View File

@ -0,0 +1,53 @@
Class {
#name : #DiyaRootNode,
#superclass : #DiyaNode,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaRootNode >> boundingBox [
^ Rectangle origin: 0@0 corner: context resolution
]
{ #category : #accessing }
DiyaRootNode >> draw [
|c|
c := style get: #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 : #accessing }
DiyaRootNode >> extent [
^ context resolution
]
{ #category : #initialization }
DiyaRootNode >> initialize [
super initialize.
parent := self.
shader := nil.
root := self.
style := DiyaDefaultStyle new
]
{ #category : #'as yet unclassified' }
DiyaRootNode >> inner: aPoint [
^true
]
{ #category : #accessing }
DiyaRootNode >> isRoot [
^true
]
{ #category : #initialization }
DiyaRootNode >> update [
^true
]
{ #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.
Transcript show: 'Initialise unique instance of ', self className; cr.
]

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 : #DiyaWidget,
#category : #'Diya-Widgets'
}

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

@ -0,0 +1,280 @@
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 style get: #textAlign
]
{ #category : #'menu messages' }
DiyaText >> align: v [
self style set: #textAlign value: v.
self formatText
]
{ #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 >> data [
^ data
]
{ #category : #accessing }
DiyaText >> data: anObject [
data := anObject.
dirty := true
]
{ #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 ).
dirty := true
]
{ #category : #accessing }
DiyaText >> fontName [
^ self style get: #fontFamily
]
{ #category : #initialization }
DiyaText >> fontName: name style: face size: size [
name ifNotNil: [style set:#fontFamily value: name].
face ifNotNil: [style set: #fontStyle value:face].
style set: #fontSize value: size.
dirty := true.
self initTexture
]
{ #category : #accessing }
DiyaText >> fontSize [
^ self style get:#fontSize
]
{ #category : #initialization }
DiyaText >> fontSize: size [
self fontName: nil style:nil size: size
]
{ #category : #accessing }
DiyaText >> fontStyle [
^ self style get: #fontStyle
]
{ #category : #accessing }
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.
style set: #border value: 0.
"style set: #bgcolor value: Color red."
type := GL_QUADS.
maxLineWidth := 0.
]
{ #category : #'as yet unclassified' }
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 : #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 >> texture [
texture ifNil: [ self initTexture ].
texheight = texture height ifFalse: [
texheight := texture height.
self update.
dirty := false.
].
^texture
]
{ #category : #initialization }
DiyaText >> update [
bbox ifNil: [ ^true ].
data ifNil:[^true].
data ifEmpty:[^true].
vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease.
self drawText.
dirty := false.
^true
]
{ #category : #'menu messages' }
DiyaText >> valign [
^ self style get: #textVAlign
]
{ #category : #'menu messages' }
DiyaText >> valign: v [
self style set: #textVAlign value: v.
self formatText.
]
{ #category : #accessing }
DiyaText >> valignText:h [
self valign = #middle ifTrue:[^ (0 max:((self extent y - h) / 2 ) asFloat)].
self valign = #bottom ifTrue:[^ (0 max:(self extent y - h ))].
^0
]
{ #category : #initialization }
DiyaText >> wordWrap: aBool [
wrap := aBool.
dirty := true
]

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'
}

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

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

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

@ -0,0 +1,56 @@
Class {
#name : #DiyaWidget,
#superclass : #Diya2DNode,
#instVars : [
'extent'
],
#category : #'Diya-Widgets'
}
{ #category : #'instance creation' }
DiyaWidget class >> fromStyle: aStyle [
^self new style: aStyle; yourself
]
{ #category : #accessing }
DiyaWidget >> bgColor:v [
^style set: #bgcolor value: v
]
{ #category : #accessing }
DiyaWidget >> color [
^style get: #color
]
{ #category : #accessing }
DiyaWidget >> color: value [
style set: #color value: value
]
{ #category : #geometry }
DiyaWidget >> extent [
^extent
]
{ #category : #geometry }
DiyaWidget >> extent: size [
extent := size.
dirty := true.
]
{ #category : #initialization }
DiyaWidget >> initialize [
super initialize.
]
{ #category : #accessing }
DiyaWidget >> update [
self updateLayout.
^ true
]
{ #category : #accessing }
DiyaWidget >> updateLayout [
self subclassResponsibility
]

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

@ -59,6 +59,7 @@ ImageInitializer >> initializeImage [
show: 'CLASS: ' , c asString , ' is not initialized';
cr.
c initialize ].
DiyaSingleton resetAll.
FFIMethodRegistry resetAll.
Smalltalk garbageCollect.
SourceFiles := SourceFileArray new.

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

@ -0,0 +1,12 @@
Extension { #name : #LibC }
{ #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
]

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

@ -0,0 +1,104 @@
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 : #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,196 @@
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_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_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_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_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,143 @@
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 >> 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 [
^ width @ 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,99 @@
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 : #'as yet unclassified' }
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
]

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

@ -0,0 +1,31 @@
Extension { #name : #Point }
{ #category : #'*Diya' }
Point >> applyTf: tf [
^(tf +* (self asArray3F)) asPoint
]
{ #category : #'*Diya' }
Point >> asArray3F [
^ self asArray3F: 1.0
]
{ #category : #'*Diya' }
Point >> asArray3F: z [
^ { self x. self y. z }
]
{ #category : #'*Diya' }
Point >> asGLCoord [
|res|
res := DiyaRendererContext uniqueInstance resolution.
^(self / ( res / 2.0)) + (-1.0@ -1.0).
]
{ #category : #'*Diya' }
Point >> glNormalise [
|res p|
res := DiyaRendererContext uniqueInstance resolution.
p := self / (res/ 2).
^ (p x asFloat) @ (p y asFloat)
]

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

@ -0,0 +1,8 @@
Extension { #name : #Rectangle }
{ #category : #'*Diya' }
Rectangle >> applyTf: tf [
^ Rectangle
origin: (self origin applyTf: tf)
corner: (self corner applyTf: tf)
]

View File

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

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

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

View File

@ -1,5 +1,8 @@
# Diya-API
Diya base system API
Diya base system API:
* SDL2, OpenGL and Freetype binding
* Base Graphic stack for touch device
* Application API for application development
```smalltalk