1
0
mirror of https://github.com/lxsang/Diya-API.git synced 2025-07-17 22:39:46 +02:00

18 Commits

53 changed files with 1464 additions and 440 deletions

View File

@ -12,3 +12,30 @@ Array2D >> asGLBuffer [
buffer autoRelease. buffer autoRelease.
^buffer ^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

@ -2,31 +2,31 @@ Class {
#name : #Diya2DNode, #name : #Diya2DNode,
#superclass : #DiyaNode, #superclass : #DiyaNode,
#instVars : [ #instVars : [
'color', 'vbuffer'
'vbuffer',
'bbox'
], ],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> boundingBox [ Diya2DNode >> boundingBox [
^ bbox |rec|
children ifEmpty: [ ^ Rectangle origin: 0@0 corner: 0@0 ].
rec := children first boundingBox.
children do:[:c|
rec = c ifFalse:[
rec := rec merge: c boundingBox]
].
^rec
] ]
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> color [ Diya2DNode >> draw [
^ color
]
{ #category : #accessing }
Diya2DNode >> color: anObject [
color := anObject
] ]
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> extent [ Diya2DNode >> extent [
^ bbox extent ^ self boundingBox extent
] ]
{ #category : #accessing } { #category : #accessing }
@ -38,15 +38,26 @@ Diya2DNode >> height [
Diya2DNode >> initialize [ Diya2DNode >> initialize [
super initialize. super initialize.
translation := 0@0. translation := 0@0.
scale := 1.0@1.0. scale := 1@1.
rotation := 0.0. rotation := 0.
tf := Array2D identity: 3. tf := Array2D identity: 3.
shader := Diya2DShader uniqueInstance. shader := Diya2DShader uniqueInstance.
color := Color white.
vbuffer := nil. vbuffer := nil.
] ]
{ #category : #'as yet unclassified' } { #category : #accessing }
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 : #accessing }
Diya2DNode >> recFromBuffer [ Diya2DNode >> recFromBuffer [
|maxX maxY minX minY x y| |maxX maxY minX minY x y|
maxX := minX := vbuffer at: 1. maxX := minX := vbuffer at: 1.
@ -62,36 +73,21 @@ Diya2DNode >> recFromBuffer [
^ Rectangle origin: minX@minY corner: maxX @ maxY ^ Rectangle origin: minX@minY corner: maxX @ maxY
] ]
{ #category : #initialization }
Diya2DNode >> setUpShader [
super setUpShader.
shader setUniform: #u_color value: self color asGL4FArray.
]
{ #category : #accessing } { #category : #accessing }
Diya2DNode >> updateTF [ Diya2DNode >> updateTF [
tf := Array2D identity:3. tf := Array2D identity:3.
"translation" "translation"
tf := tf +* (Array2D rows: 3 columns: 3 contents: { translation = (0@0) ifFalse:[
1.0. 0.0. translation x. tf := tf +* (Array2D translateMatrix2D: translation)].
0.0. 1.0. translation y.
0.0. 0.0. 1.0
}).
"rotation" "rotation"
tf := tf +* (Array2D rows: 3 columns: 3 contents:{ rotation = 0 ifFalse:[
rotation cos. (rotation sin) negated. 0.0. tf := tf +* (Array2D rotationMatrix2D: rotation )].
rotation sin. rotation cos. 0.0.
0.0. 0.0. 1.0
}).
"scale" "scale"
tf := tf +* (Array2D rows: 3 columns: 3 contents:{ scale = (1@1) ifFalse:[
scale x. 0.0. 0.0. tf := tf +* (Array2D scaleMatrix2D: scale)].
0.0. scale y. 0.0. self parent ifNil: [ ^self ].
0.0. 0.0. 1.0 self parent isRoot ifFalse: [tf := self parent tf +* tf ].
}). children ifNotNil: [children do:[:c| c updateTF ]].
self parent isRoot ifFalse: [ tf := self parent tf +* tf ].
children ifNotNil: [
children do:[:c| c updateTF ]].
] ]

View File

@ -4,20 +4,19 @@ Class {
#instVars : [ #instVars : [
'texture', 'texture',
'type', 'type',
'border', 'bbox'
'bcolor'
], ],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
{ #category : #accessing } { #category : #accessing }
Diya2DPrimShape >> borderColor: c [ Diya2DPrimShape >> borderWidth [
bcolor := c ^ self ? #border
] ]
{ #category : #accessing } { #category : #accessing }
Diya2DPrimShape >> borderWidth: w [ Diya2DPrimShape >> boundingBox [
border := w ^ bbox applyTf: self tf.
] ]
{ #category : #initialization } { #category : #initialization }
@ -35,19 +34,17 @@ Diya2DPrimShape >> draw [
OpenGL drawArrays: type first:0 count:((vbuffer size )>> 2 ). OpenGL drawArrays: type first:0 count:((vbuffer size )>> 2 ).
"reset value" "reset value"
self texture ifNotNil: [self texture drop.]. self texture ifNotNil: [self texture drop.].
border > 0 ifTrue: [ self drawBorder ]. self borderWidth > 0 ifTrue: [ self drawBorder ].
context vao disableAttribute: 0. context vao disableAttribute: 0.
] ]
{ #category : #initialization } { #category : #initialization }
Diya2DPrimShape >> drawBorder [ Diya2DPrimShape >> drawBorder [
"Diya2DShader uniqueInstance use." "Diya2DShader uniqueInstance use."
color = bcolor ifFalse:[ shader setUniform: #u_color value: (self ? #borderColor) asGL4FArray;
shader setUniform: #u_color value: bcolor asGL4FArray; setUniform: #u_texture_type value: 1.
setUniform: #u_texture_type value: 0.
].
OpenGL OpenGL
lineWidth: border. lineWidth: self borderWidth.
self drawLines. self drawLines.
OpenGL lineWidth: 1.0. OpenGL lineWidth: 1.0.
] ]
@ -62,23 +59,34 @@ Diya2DPrimShape >> drawLines [
self subclassResponsibility self subclassResponsibility
] ]
{ #category : #accessing }
Diya2DPrimShape >> extent [
^ bbox extent
]
{ #category : #initialization } { #category : #initialization }
Diya2DPrimShape >> initialize [ Diya2DPrimShape >> initialize [
super initialize. super initialize.
texture := nil. texture := nil.
children := nil. children := nil.
type := GL_TRIANGLES. type := GL_TRIANGLES.
border := 0. bbox := Rectangle origin: 0@0 corner: 0@0.
bcolor := Color white. ]
{ #category : #accessing }
Diya2DPrimShape >> inner: aPoint [
bbox ifNil: [ ^false ].
^ bbox containsPoint: (self local: aPoint)
] ]
{ #category : #initialization } { #category : #initialization }
Diya2DPrimShape >> setUpShader [ Diya2DPrimShape >> setUpShader [
super setUpShader super setUpShader.
texture ifNotNil:[
self shader self shader
setUniform: #u_texture_type value: texture format. 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 } { #category : #accessing }
@ -90,3 +98,8 @@ Diya2DPrimShape >> texture [
Diya2DPrimShape >> texture: anObject [ Diya2DPrimShape >> texture: anObject [
texture := anObject texture := anObject
] ]
{ #category : #accessing }
Diya2DPrimShape >> textureNamed: name [
self texture: (context assets texture: name)
]

View File

@ -10,17 +10,17 @@ Diya2DShader class >> fragmentShader [
#ifdef GL_ES #ifdef GL_ES
precision highp float; precision highp float;
#endif #endif
uniform vec2 u_resolution; uniform vec2 u_resolution;
uniform vec2 u_mouse; uniform vec2 u_mouse;
uniform float u_time; uniform float u_time;
// 2D uniforms // 2D uniforms
uniform int u_texture_type; uniform int u_texture_type;
uniform vec4 u_color; uniform vec4 u_color;
uniform vec4 u_bg_color;
uniform sampler2D u_texture; uniform sampler2D u_texture;
varying vec2 texcoord; varying vec2 texcoord;
void main(void) { void main(void) {
vec4 texcolor = vec4(1,1,1,1); vec4 texcolor = vec4(0,0,0,0);
// alpha // alpha
if(u_texture_type == 0x1906) { if(u_texture_type == 0x1906) {
texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a); texcolor = vec4(1, 1, 1, texture2D(u_texture, texcoord).a);
@ -29,7 +29,19 @@ void main(void) {
else if (u_texture_type == 0x1908){ else if (u_texture_type == 0x1908){
texcolor = texture2D(u_texture, texcoord); texcolor = texture2D(u_texture, texcoord);
} }
gl_FragColor = texcolor * u_color; 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;
}
}' }'
] ]
@ -55,6 +67,7 @@ Diya2DShader >> setUpUniforms [
self addUniform: #u_texture of: Uniform1i. self addUniform: #u_texture of: Uniform1i.
self addUniform: #u_texture_type of: Uniform1i. self addUniform: #u_texture_type of: Uniform1i.
self addUniform: #u_color of: Uniform4F. self addUniform: #u_color of: Uniform4F.
self addUniform: #u_bg_color of: Uniform4F.
self addUniform: #u_border_color of: Uniform4F. self addUniform: #u_border_color of: Uniform4F.
self addUniform: #u_border of: Uniform1F. self addUniform: #u_border of: Uniform1F.
] ]

View File

@ -0,0 +1,99 @@
Class {
#name : #DiyaApplicationLauncher,
#superclass : #DiyaApplicationModel,
#instVars : [
'currapp',
'txtFPS',
'event',
'running'
],
#category : #'Diya-Applications'
}
{ #category : #initialization }
DiyaApplicationLauncher >> appNode [
^root children first
]
{ #category : #initialization }
DiyaApplicationLauncher >> bindGlobalEvent [
|pointer |
pointer := root addNode: (DiyaCircle r: 10) at: 200@200.
pointer styleName: #pointer.
root on: #keydown do:[:e| 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.
DiyaUIThemesManager uniqueInstance currentTheme
define: #fps_text styles: {
#color -> Color red.
#fontSize -> 18.
#bgColor -> Color transparent.
};
define: #pointer styles: {
#borderColor -> Color red.
#bgColor -> Color orange.
#border -> 3
}.
root addNode: (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 styleName: #fps_text.
self bindGlobalEvent.
running := true.
self launch: self defaultApplication.
]

View File

@ -0,0 +1,49 @@
Class {
#name : #DiyaApplicationModel,
#superclass : #DiyaSingleton,
#instVars : [
'root',
'am'
],
#category : #'Diya-Applications'
}
{ #category : #accessing }
DiyaApplicationModel >> am [
^ am
]
{ #category : #accessing }
DiyaApplicationModel >> cleanup [
self subclassResponsibility
]
{ #category : #accessing }
DiyaApplicationModel >> context [
^DiyaRendererContext uniqueInstance
]
{ #category : #initialization }
DiyaApplicationModel >> initialize [
super initialize.
]
{ #category : #accessing }
DiyaApplicationModel >> main [
self subclassResponsibility
]
{ #category : #accessing }
DiyaApplicationModel >> quit [
self cleanup
]
{ #category : #accessing }
DiyaApplicationModel >> root [
^ root
]
{ #category : #accessing }
DiyaApplicationModel >> setup [
self subclassResponsibility
]

View File

@ -0,0 +1,12 @@
Class {
#name : #DiyaBaseApplication,
#superclass : #DiyaApplicationModel,
#category : #'Diya-Applications'
}
{ #category : #initialization }
DiyaBaseApplication >> initialize [
super initialize.
root := Diya2DNode new.
am := AssetManager new.
]

View File

@ -18,6 +18,11 @@ DiyaBaseObject >> logError: string [
self stderr nextPutAll: string; cr self stderr nextPutAll: string; cr
] ]
{ #category : #asserting }
DiyaBaseObject >> shouldNotBeCalled [
^DiyaCoreAPIError signal: 'Should not be called'
]
{ #category : #accessing } { #category : #accessing }
DiyaBaseObject >> stderr [ DiyaBaseObject >> stderr [
^VTermOutputDriver stderr ^VTermOutputDriver stderr

View File

@ -2,7 +2,6 @@ Class {
#name : #DiyaBoot, #name : #DiyaBoot,
#superclass : #DiyaSingleton, #superclass : #DiyaSingleton,
#instVars : [ #instVars : [
'running',
'window', 'window',
'context', 'context',
'display', 'display',
@ -41,7 +40,7 @@ DiyaBoot >> GLinit. [
{ #category : #events } { #category : #events }
DiyaBoot >> createGLContext [ DiyaBoot >> createGLContext [
context := SDL2 glCreateContext: window. context := SDL2 glCreateContext: window.
context ifNil: [ ^self error: SDL2 getErrorMessage ]. context ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
^context ^context
] ]
@ -60,7 +59,7 @@ DiyaBoot >> createWindow [
width: display w width: display w
height: display h height: display h
flags: SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL. flags: SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL.
window ifNil: [ ^self error: SDL2 getErrorMessage ]. window ifNil: [ ^DiyaCoreAPIError signal: SDL2 getErrorMessage ].
"handle fullscreen: SDL_WINDOW_FULLSCREEN." "handle fullscreen: SDL_WINDOW_FULLSCREEN."
"SDL2 glSetAttribute: SDL_GL_CONTEXT_PROFILE_MASK value: SDL_GL_CONTEXT_PROFILE_ES. "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_MAJOR_VERSION value: 2.
@ -72,120 +71,40 @@ DiyaBoot >> createWindow [
^window ^window
] ]
{ #category : #events }
DiyaBoot >> exampleNodes [
|root node style tex|
root := DiyaRootNode new.
tex := (DiyaImageTex fromFile:Smalltalk imageDirectory / 'assets'/'mrsang.png').
node := root addNode: (DiyaRectangle size: 200@200) at: 250 @ 430.
node texture: tex.
node color: (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
node borderColor: Color red.
node borderWidth: 3.0.
style := DiyaFontManager uniqueInstance style: 'Bold' from:'Ubuntu'.
"style := DiyaFontManager uniqueInstance style: 'Regular' from: 'bootstrap-icons'."
node := root addNode: (DiyaRectangle size: 208@288) at: 250 @ 50.
node color: (Color orange).
node texture: (style textureOf: 48).
node borderColor: Color red.
node borderWidth: 3.0.
node := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 20 @ 400.
node rotation: (Float pi / -8.0).
node scale: 1.5@1.5.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@340.
node extent: 250@320.
node wordWrap: true.
node := root addNode: (DiyaLine from: 10@620 to: 200@635).
node color: (Color red).
node borderWidth: 2.0.
node := root addNode: (DiyaCircle r: 100) at: 200@200.
node borderColor: Color red.
node color: Color white.
node borderWidth: 3.0.
node texture: tex.
node := root addNode: (DiyaConvexPolygon points:{250@100. 400@250. 450@80. 350@60}).
node color: Color green.
node borderColor: Color red.
node texture: tex.
node borderWidth: 3.0.
^ root
]
{ #category : #events } { #category : #events }
DiyaBoot >> init [ DiyaBoot >> init [
| status | | status |
SDL2 setHint: 'SDL_RENDER_DRIVER' value: 'opengles2'. SDL2 setHint: 'SDL_RENDER_DRIVER' value: 'opengles2'.
status := SDL2 init: SDL_INIT_EVERYTHING. status := SDL2 init: SDL_INIT_EVERYTHING.
status = 0 status = 0
ifFalse: [ ^ self error: SDL2 getErrorMessage ]. ifFalse: [ ^ DiyaCoreAPIError signal: SDL2 getErrorMessage ].
display := SDL_DisplayMode externalNew autoRelease. display := SDL_DisplayMode externalNew autoRelease.
SDL2 SDLGetCurrentDisplayMode: display from:0. SDL2 SDLGetCurrentDisplayMode: display from:0.
DiyaRendererContext reset. SDL2 showCursor: 0.
DiyaFontManager reset. DiyaSingleton resetAll.
OpenGLSL resetShaders.
DiyaFontManager uniqueInstance loadFonts. DiyaFontManager uniqueInstance loadFonts.
] ]
{ #category : #events } { #category : #events }
DiyaBoot >> initialize [ DiyaBoot >> initialize [
running := true.
display := nil. display := nil.
window := nil. window := nil.
context := nil. context := nil.
clock := DiyaClock uniqueInstance. clock := DiyaClock uniqueInstance.
] ]
{ #category : #events }
DiyaBoot >> processEvent: event [
|mappedEvt|
mappedEvt := event mapped.
mappedEvt type = SDL_KEYDOWN ifTrue: [ Transcript show: 'keydown...';cr. ^running := false. ].
mappedEvt type = SDL_QUIT ifTrue:[ ^running:= false ].
mappedEvt type = SDL_FINGERDOWN ifTrue:[^self setCursorPosition: mappedEvt ].
mappedEvt type = SDL_FINGERMOTION ifTrue:[^self setCursorPosition: mappedEvt ].
mappedEvt type = SDL_MOUSEMOTION ifTrue:[DiyaRendererContext uniqueInstance mouse: (mappedEvt x) @ (mappedEvt y)].
mappedEvt free.
]
{ #category : #events }
DiyaBoot >> randomColorChannel [
| rand |
rand := Random new.
rand := (rand next) * 255.
rand := rand asInteger.
^ rand
]
{ #category : #events } { #category : #events }
DiyaBoot >> render [ DiyaBoot >> render [
|event root text delta fps| |delta launcher|
event := SDL_Event new.
root := self exampleNodes.
DiyaRenderer uniqueInstance root: root.
text := root addNode:(DiyaText data: 'tick') at: (display w - 80)@40.
text extent: 80@40.
text fontSize: 18.
text color: Color red.
DiyaRendererContext uniqueInstance. DiyaRendererContext uniqueInstance.
launcher := DiyaApplicationLauncher uniqueInstance.
launcher setup.
self GLinit. self GLinit.
[ running ] whileTrue: [ [ launcher running ] whileTrue: [
delta := DiyaClock uniqueInstance delta asMilliSeconds. delta := DiyaClock uniqueInstance delta asMilliSeconds.
fps := ((1000/delta) asInteger). launcher delta: delta.
text data: ('FPS:', fps asString).
DiyaClock uniqueInstance tick. DiyaClock uniqueInstance tick.
[(SDL2 pollEvent: event) > 0] whileTrue: [ launcher main.
self processEvent: event
].
DiyaRenderer uniqueInstance render.
SDL2 glSwapWindow: window. SDL2 glSwapWindow: window.
delta := DiyaClock uniqueInstance delta asMilliSeconds. delta := DiyaClock uniqueInstance delta asMilliSeconds.
SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta). SDL2 delay: (0 max: (1000/ self class maxFPS) asInteger - delta).
@ -194,8 +113,23 @@ DiyaBoot >> render [
{ #category : #events } { #category : #events }
DiyaBoot >> run [ 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. self init.
self startx. self startx.
]
ifNotNil: [
self run: (arr at:1) @ (arr at: 2)
]
] ]
{ #category : #running } { #category : #running }
@ -223,12 +157,6 @@ DiyaBoot >> run: screenSize app: application [
Smalltalk garbageCollect. Smalltalk garbageCollect.
] ]
{ #category : #events }
DiyaBoot >> setCursorPosition: mappedEvt [
window warpMouseX:((mappedEvt x)* (display w) )
Y: ((mappedEvt y) * (display h))
]
{ #category : #logging } { #category : #logging }
DiyaBoot >> showSystemInfo [ DiyaBoot >> showSystemInfo [
|stream numdriver rinfo| |stream numdriver rinfo|
@ -263,7 +191,7 @@ DiyaBoot >> showSystemInfo [
{ #category : #events } { #category : #events }
DiyaBoot >> startx [ DiyaBoot >> startx [
display ifNil: [ ^self error: 'Please run #init before this method' ]. display ifNil: [ ^DiyaCoreAPIError signal: 'Please run #init before this method' ].
self createWindow. self createWindow.
self createGLContext. self createGLContext.
"SDL2 glMakeCurrent: window context: context." "SDL2 glMakeCurrent: window context: context."
@ -274,22 +202,6 @@ DiyaBoot >> startx [
self render. self render.
context delete. context delete.
window destroy. window destroy.
DiyaFontManager reset. DiyaSingleton resetAll.
DiyaRendererContext reset.
SDL2 quit. SDL2 quit.
] ]
{ #category : #events }
DiyaBoot >> step [
"renderer drawColorR: 0
g: 0
b: 0
a: 255."
OpenGL begin: GL_TRIANGLES.
"draw a simple triangle here"
OpenGL color3fR: 0.1 G:0.2 B: 0.3.
OpenGL vertex3fX: 0 Y: 0 Z: 0.
OpenGL vertex3fX: 1 Y: 0 Z: 0.
OpenGL vertex3fX: 0 Y: 1 Z: 0.
OpenGL end.
]

View File

@ -1,5 +1,52 @@
Class { Class {
#name : #DiyaButton, #name : #DiyaButton,
#superclass : #DiyaWidget, #superclass : #DiyaWidget,
#instVars : [
'label',
'rec'
],
#category : #'Diya-Widgets' #category : #'Diya-Widgets'
} }
{ #category : #accessing }
DiyaButton class >> text: string [
^ self new text: string; yourself
]
{ #category : #accessing }
DiyaButton >> icon: ico [
label icon: ico.
label setDirty.
]
{ #category : #accessing }
DiyaButton >> iconSize: size [
label iconSize: size.
]
{ #category : #initialization }
DiyaButton >> initialize [
super initialize.
rec := self addNode: (DiyaRectangle new).
label := self addNode: (DiyaLabel new).
label txt
wordWrap: false.
]
{ #category : #accessing }
DiyaButton >> label [
^ label
]
{ #category : #accessing }
DiyaButton >> text: string [
label txt: string.
]
{ #category : #accessing }
DiyaButton >> update [
rec extent: self extent.
label position: 0@0.
label extent: self extent.
^true
]

View File

@ -11,7 +11,7 @@ DiyaConvexPolygon >> calculateVertices [
vbuffer ifNotNil: [ vbuffer free ]. vbuffer ifNotNil: [ vbuffer free ].
vbuffer := FFIExternalArray externalNewType: GLfloat size:size. vbuffer := FFIExternalArray externalNewType: GLfloat size:size.
vbuffer autoRelease. vbuffer autoRelease.
points sort:[:a :b| a angle < b angle]. points sort:[:a :b| a angle > b angle].
index := 1. index := 1.
points do:[:point| points do:[:point|
texcoord := self texcoordOf: point. texcoord := self texcoordOf: point.
@ -19,7 +19,7 @@ DiyaConvexPolygon >> calculateVertices [
at: index put: point x; at: index put: point x;
at: index + 1 put: point y; at: index + 1 put: point y;
at: index + 2 put: texcoord x; at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y. at: index + 3 put: texcoord y.
index := index + 4. index := index + 4.
]. ].
p := points at: 2. p := points at: 2.
@ -28,7 +28,7 @@ DiyaConvexPolygon >> calculateVertices [
at: index put: p x; at: index put: p x;
at: index + 1 put: p y; at: index + 1 put: p y;
at: index + 2 put: texcoord x; at: index + 2 put: texcoord x;
at: index + 3 put: 1.0 - texcoord y. at: index + 3 put: texcoord y.
] ]
{ #category : #initialization } { #category : #initialization }

View File

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

View File

@ -38,6 +38,11 @@ DiyaEllipse >> drawBorder [
"do nothing" "do nothing"
] ]
{ #category : #initialization }
DiyaEllipse >> drawLines [
self shouldNotBeCalled
]
{ #category : #initialization } { #category : #initialization }
DiyaEllipse >> initialize [ DiyaEllipse >> initialize [
super initialize. super initialize.
@ -47,6 +52,13 @@ DiyaEllipse >> initialize [
shader := DiyaEllipseShader uniqueInstance. 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 } { #category : #accessing }
DiyaEllipse >> rx [ DiyaEllipse >> rx [
^ rx ^ rx
@ -55,7 +67,7 @@ DiyaEllipse >> rx [
{ #category : #accessing } { #category : #accessing }
DiyaEllipse >> rx: anObject [ DiyaEllipse >> rx: anObject [
rx := anObject. rx := anObject.
dirty := true. self setDirty
] ]
{ #category : #accessing } { #category : #accessing }
@ -66,15 +78,15 @@ DiyaEllipse >> ry [
{ #category : #accessing } { #category : #accessing }
DiyaEllipse >> ry: anObject [ DiyaEllipse >> ry: anObject [
ry := anObject. ry := anObject.
dirty := true self setDirty
] ]
{ #category : #initialization } { #category : #initialization }
DiyaEllipse >> setUpShader [ DiyaEllipse >> setUpShader [
super setUpShader. super setUpShader.
self shader self shader
setUniform: #u_border value: border; setUniform: #u_border value: (self ? #border);
setUniform: #u_border_color value: bcolor asGL4FArray; setUniform: #u_border_color value: ( self ? #borderColor) asGL4FArray;
setUniform: #u_rx value: rx; setUniform: #u_rx value: rx;
setUniform: #u_ry value: ry. setUniform: #u_ry value: ry.
] ]
@ -83,13 +95,13 @@ DiyaEllipse >> setUpShader [
DiyaEllipse >> update [ DiyaEllipse >> update [
bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry). bbox := Rectangle origin: ((rx negated) @ (ry negated)) corner: (rx @ ry).
{ {
bbox origin x. bbox corner y. 0.0. 0.0. bbox origin x. bbox origin y. 0.0. 0.0.
bbox origin x. bbox origin y. 0.0. 1.0. bbox origin x. bbox corner y. 0.0. 1.0.
bbox corner x. bbox origin y. 1.0. 1.0. bbox corner x. bbox corner y. 1.0. 1.0.
bbox corner x. bbox origin y. 1.0. 1.0. bbox corner x. bbox corner y. 1.0. 1.0.
bbox corner x. bbox corner y. 1.0. 0.0. bbox corner x. bbox origin y. 1.0. 0.0.
bbox origin x. bbox corner y. 0.0. 0.0. bbox origin x. bbox origin y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e]. } doWithIndex: [:e :i| vbuffer at: i put: e].
^true ^true
] ]

View File

@ -89,8 +89,8 @@ void draw_ellipse(inout vec4 c, vec2 p, Ellipse e, float border)
vec2 rotate_point(vec2 center, vec2 p,float angle) vec2 rotate_point(vec2 center, vec2 p,float angle)
{ {
float s = sin(angle); float s = sin(-angle);
float c = cos(angle); float c = cos(-angle);
// translate point back to origin: // translate point back to origin:
p.x -= center.x; p.x -= center.x;
@ -110,7 +110,7 @@ void main() {
vec4 color = vec4(0); vec4 color = vec4(0);
//defining ellipse //defining ellipse
Ellipse e = create_ellipse(middle, u_ry, u_rx); Ellipse e = create_ellipse(middle, u_ry, u_rx);
draw_ellipse(color, rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border); draw_ellipse(color,rotate_point(middle, gl_FragCoord.xy, rotation), e, u_border);
// Output to screen // Output to screen
gl_FragColor = color; gl_FragColor = color;
} }
@ -125,6 +125,7 @@ precision mediump float;
#endif #endif
uniform mat4 u_projection; uniform mat4 u_projection;
uniform mat3 u_transform; uniform mat3 u_transform;
uniform vec2 u_resolution;
varying float rotation; varying float rotation;
varying vec2 middle; varying vec2 middle;
varying vec2 texcoord; varying vec2 texcoord;
@ -133,7 +134,8 @@ void main()
vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0); vec3 coord_global = u_transform * vec3(gl_Vertex.xy, 1.0);
gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0); gl_Position = u_projection * vec4(coord_global.xy, 0, 1.0);
rotation = atan(u_transform[1][0], u_transform[0][0]); rotation = atan(u_transform[1][0], u_transform[0][0]);
middle = (u_transform * vec3(0.0,0.0,1.0)).xy; vec2 org = (u_transform * vec3(0.0,0.0,1.0)).xy;
middle = vec2(org.x, u_resolution.y - org.y);
texcoord = gl_Vertex.zw; texcoord = gl_Vertex.zw;
}' }'
] ]

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,114 @@
Class {
#name : #DiyaExampleApp,
#superclass : #DiyaBaseApplication,
#category : #'Diya-Applications'
}
{ #category : #accessing }
DiyaExampleApp >> cleanup [
]
{ #category : #accessing }
DiyaExampleApp >> defineStyleSheet [
DiyaUIThemesManager uniqueInstance currentTheme
define: #text_icon_1 styles: {
#color -> Color orange.
#fontSize -> 24.
#bgColor -> Color transparent.
};
define: #image_view styles: {
#color -> (Color r: 1.0 g:1.0 b:1.0 alpha:1.0 ).
#border -> 3.
#bgColor -> Color cyan.
#borderColor -> Color red
};
define: #text_view styles: {
#color -> Color green.
#fontSize -> 16.
#bgColor -> Color transparent.
#xAlign -> #center
};
define: #line_view styles: {
#color -> Color red.
#border -> 4
};
define: #ell_view styles: {
#borderColor -> Color red.
#color -> Color white.
#bgColor -> Color cyan.
#border -> 3.
};
define: #poly_view styles: {
#borderColor -> Color red.
#color -> Color green.
#border -> 3.
};
define: #button_view styles: {
#borderColor -> Color red.
#color -> Color white.
#bgColor -> Color magenta.
#border -> 1.
#yAlign -> #middle.
#xAlign -> #center
}
]
{ #category : #accessing }
DiyaExampleApp >> main [
]
{ #category : #accessing }
DiyaExampleApp >> setup [
|node node1 ell label icon button|
self defineStyleSheet.
label := root addNode: (DiyaLabel new) at: 10@40.
label extent: 250@24.
label styleName:#text_icon_1.
label icon: 16rF254.
node1 := root addNode: (DiyaRectangle size:100@150 shader: DiyaExampleShader uniqueInstance) at: 300 @ 40.
"node1 rotation: (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 styleName: #image_view.
node extent:200@200.
node := root addNode: (DiyaRectangle new) at: 10@80.
node styleName: #image_view.
node extent: 240@320.
node := root addNode: (DiyaText data: String loremIpsum) at: 10@80.
node extent: 240@320.
node wordWrap: true.
node styleName: #text_view.
node := root addNode: (DiyaLine from: 10@10 to: 200@200).
node styleName: #line_view.
ell := root addNode: (DiyaEllipse rx:100 ry: 70) at: 100@300.
ell rotation: Float pi / 6.0.
ell styleName: #ell_view.
"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 textureNamed: 'mrsang.png'.
node styleName: #poly_view.
icon := root addNode: (DiyaFontIcon data: #(16rF101 16rF155 16rF185 16rF21B 16rF298 16rF254)) at: 240@500.
icon styleName: #text_icon_1 .
button := root addNode: (DiyaButton text: 'Click me !') at: 240@460.
button extent: 200@40.
button icon:"16rF185"'mrsang.png'.
button styleName: #button_view.
^ root
]

View File

@ -26,7 +26,7 @@ DiyaFFIBase class >> moduleName [
^ aName ^ aName
]. ].
]. ].
self error: 'Unable to find FFI library (', self checkSymbol, ')'. DiyaCoreAPIError signal: 'Unable to find FFI library (', self checkSymbol, ')'.
] ]
{ #category : #'library path' } { #category : #'library path' }

View File

@ -4,7 +4,7 @@ Class {
#instVars : [ #instVars : [
'advance', 'advance',
'bearing', 'bearing',
'texcoord' 'tex'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -34,11 +34,16 @@ DiyaFontGlyph >> bearing: anObject [
] ]
{ #category : #accessing } { #category : #accessing }
DiyaFontGlyph >> texcoord [ DiyaFontGlyph >> tex [
^ texcoord ^ tex
] ]
{ #category : #accessing } { #category : #accessing }
DiyaFontGlyph >> texcoord: anObject [ DiyaFontGlyph >> tex: anObject [
texcoord := anObject tex := anObject
]
{ #category : #accessing }
DiyaFontGlyph >> texcoord [
^ (Rectangle origin: (self origin/ (tex extent) ) asFloatPoint corner: ((self corner) / (tex extent)) asFloatPoint ).
] ]

View File

@ -0,0 +1,66 @@
Class {
#name : #DiyaFontIcon,
#superclass : #DiyaText,
#pools : [
'FT2Types'
],
#category : #'Diya-Graphics'
}
{ #category : #initialization }
DiyaFontIcon >> data: code [
super data:(code isArray ifTrue: [ code ] ifFalse:[{code}]).
]
{ #category : #initialization }
DiyaFontIcon >> drawText [
|index offset tex glyph |
index := 1.
tex := self texture.
offset := (self alignLine: self fontSize)@(self valignText: self fontSize).
data do: [ :c|
glyph := tex getGlyph: c asInteger.
(self getCharsVerticesFrom: glyph offset: offset cellh: tex cellh) do: [
:e| vbuffer at: index put:e.
index := index + 1
].
"offset setX: offset x + tex spacing setY: offset y"
].
]
{ #category : #accessing }
DiyaFontIcon >> fontName [
^ self ? #textIconFamily
]
{ #category : #initialization }
DiyaFontIcon >> getLinebreakIndices: delta [
self shouldNotBeCalled
]
{ #category : #accessing }
DiyaFontIcon >> iconSize [
^ self fontSize
]
{ #category : #initialization }
DiyaFontIcon >> initialize [
super initialize.
data := { }.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24.
vbuffer autoRelease.
]
{ #category : #initialization }
DiyaFontIcon >> lastSeparatorFrom: i [
self shouldNotBeCalled
]
{ #category : #initialization }
DiyaFontIcon >> update [
data ifNil: [ ^self ].
bbox := Rectangle origin: 0@0 corner: ((data size) * (self fontSize) ) @ self fontSize.
^ super update.
]

View File

@ -22,7 +22,19 @@ DiyaFontManager class >> searchPaths [
{ #category : #initialization } { #category : #initialization }
DiyaFontManager >> defaultFamily [ DiyaFontManager >> defaultFamily [
^self error: 'No font found' ^'Ubuntu'
]
{ #category : #initialization }
DiyaFontManager >> defaultIconSet [
^ self style: 'Regular' from: 'bootstrap-icons'
]
{ #category : #initialization }
DiyaFontManager >> defaultStyle [
^'Regular'
] ]
@ -66,7 +78,7 @@ DiyaFontManager >> loadFile: aFile [
numfaces ifNil: [ numfaces := face numFaces ]. numfaces ifNil: [ numfaces := face numFaces ].
self loadFace: face. self loadFace: face.
i := i + 1. i := i + 1.
i < numfaces ] whileTrue: [ ] i < numfaces ] whileTrue
] ]
{ #category : #initialization } { #category : #initialization }
@ -97,7 +109,7 @@ DiyaFontManager >> reset [
{ #category : #initialization } { #category : #initialization }
DiyaFontManager >> style: styleName from: familyName [ DiyaFontManager >> style: styleName from: familyName [
|family| |family|
family := families at: familyName ifAbsent: [ self defaultFamily ]. family := families at: familyName ifAbsent: [ families at: self defaultFamily ].
^family style: styleName ^family style: styleName
] ]

View File

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

View File

@ -0,0 +1,28 @@
Class {
#name : #DiyaImageIcon,
#superclass : #DiyaImageView,
#category : #'Diya-Graphics'
}
{ #category : #accessing }
DiyaImageIcon >> borderWidth [
^0
]
{ #category : #accessing }
DiyaImageIcon >> iconSize [
^ self ? #iconSize
]
{ #category : #accessing }
DiyaImageIcon >> initialize [
super initialize.
]
{ #category : #accessing }
DiyaImageIcon >> update [
|v|
v := self iconSize.
self extent: (v@v).
^super update
]

View File

@ -1,6 +1,9 @@
Class { Class {
#name : #DiyaImageTex, #name : #DiyaImageTex,
#superclass : #OpenGLTexImage2D, #superclass : #OpenGLTexImage2D,
#instVars : [
'path'
],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
'OpenGLTypes' 'OpenGLTypes'
@ -21,8 +24,9 @@ DiyaImageTex >> drop [
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
DiyaImageTex >> fromFile: path [ DiyaImageTex >> fromFile: aPath [
|form color index| |form color index|
path := aPath.
Transcript show: 'Loading texture from ', path fullName;cr. Transcript show: 'Loading texture from ', path fullName;cr.
form := ImageReadWriter formFromFileNamed: path. form := ImageReadWriter formFromFileNamed: path.
data := FFIExternalArray externalNewType: GLubyte size:(form width) * (form height) * 4. data := FFIExternalArray externalNewType: GLubyte size:(form width) * (form height) * 4.
@ -61,6 +65,11 @@ DiyaImageTex >> mipmap [
^false ^false
] ]
{ #category : #accessing }
DiyaImageTex >> path [
^ path
]
{ #category : #accessing } { #category : #accessing }
DiyaImageTex >> setup [ DiyaImageTex >> setup [
OpenGL OpenGL

View File

@ -1,5 +1,16 @@
Class { Class {
#name : #DiyaImageView, #name : #DiyaImageView,
#superclass : #DiyaRectangle, #superclass : #DiyaRectangle,
#category : #'Diya-Widgets' #category : #'Diya-Graphics'
} }
{ #category : #'instance creation' }
DiyaImageView class >> from: assetName [
^self new from: assetName ; yourself
]
{ #category : #'instance creation' }
DiyaImageView >> from: name [
texture := context assets texture: name.
self extent: texture extent
]

View File

@ -1,5 +1,85 @@
Class { Class {
#name : #DiyaLabel, #name : #DiyaLabel,
#superclass : #DiyaWidget, #superclass : #DiyaWidget,
#instVars : [
'txt',
'icon'
],
#category : #'Diya-Widgets' #category : #'Diya-Widgets'
} }
{ #category : #accessing }
DiyaLabel >> fontSize [
^txt fontSize.
]
{ #category : #accessing }
DiyaLabel >> getHAlign: offset [
^ 0 max: (txt alignLine: ( txt maxLineWidth)).
]
{ #category : #accessing }
DiyaLabel >> icon [
^ icon
]
{ #category : #accessing }
DiyaLabel >> icon: anObject [
icon := nil.
anObject isNumber ifTrue: [
icon := self addNode: (DiyaFontIcon data: anObject).].
anObject isString ifTrue: [
icon := self addNode: (DiyaImageIcon from: anObject).
].
icon ifNil: [ ^ DiyaCoreAPIError signal: 'Invalid icon identification'].
self setDirty
]
{ #category : #accessing }
DiyaLabel >> iconSize [
icon ifNil: [ ^0 ].
^ icon iconSize
]
{ #category : #initialization }
DiyaLabel >> initialize [
super initialize.
txt := self addNode:(DiyaText data: '').
icon := nil.
self extent: 0@0.
]
{ #category : #accessing }
DiyaLabel >> txt [
^ txt
]
{ #category : #accessing }
DiyaLabel >> txt: anObject [
txt data: anObject.
self setDirty
]
{ #category : #accessing }
DiyaLabel >> update [
|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)).
^ true
]

View File

@ -32,17 +32,13 @@ DiyaLine class >> points: points [
yourself yourself
] ]
{ #category : #accessing }
DiyaLine >> borderColor: c [
color := c
]
{ #category : #initialization } { #category : #initialization }
DiyaLine >> draw [ DiyaLine >> draw [
shader setUniform: #u_texture_type value: 1.
OpenGL OpenGL
"enable: GL_LINE_SMOOTH; "enable: GL_LINE_SMOOTH;
hint: GL_LINE_SMOOTH_HINT mode: GL_NICEST;" hint: GL_LINE_SMOOTH_HINT mode: GL_NICEST;"
lineWidth: border. lineWidth: self borderWidth.
super draw. super draw.
OpenGL lineWidth: 1.0"; OpenGL lineWidth: 1.0";
disable: GL_LINE_SMOOTH". disable: GL_LINE_SMOOTH".
@ -53,6 +49,11 @@ DiyaLine >> drawBorder [
"do nothing" "do nothing"
] ]
{ #category : #initialization }
DiyaLine >> drawLines [
self shouldNotBeCalled
]
{ #category : #accessing } { #category : #accessing }
DiyaLine >> from [ DiyaLine >> from [
^ from ^ from
@ -61,7 +62,7 @@ DiyaLine >> from [
{ #category : #accessing } { #category : #accessing }
DiyaLine >> from: anObject [ DiyaLine >> from: anObject [
from := anObject. from := anObject.
dirty := true. self setDirty
] ]
{ #category : #initialization } { #category : #initialization }
@ -73,7 +74,11 @@ DiyaLine >> initialize [
vbuffer := FFIExternalArray externalNewType: GLfloat size:8. vbuffer := FFIExternalArray externalNewType: GLfloat size:8.
vbuffer autoRelease. vbuffer autoRelease.
type := GL_LINES. type := GL_LINES.
border := 1.0 ]
{ #category : #accessing }
DiyaLine >> inner: aPoint [
^false
] ]
{ #category : #accessing } { #category : #accessing }
@ -84,7 +89,7 @@ DiyaLine >> to [
{ #category : #accessing } { #category : #accessing }
DiyaLine >> to: anObject [ DiyaLine >> to: anObject [
to := anObject. to := anObject.
dirty := true. self setDirty
] ]
{ #category : #accessing } { #category : #accessing }

View File

@ -10,11 +10,16 @@ Class {
'tf', 'tf',
'shader', 'shader',
'context', 'context',
'dirty' 'dirty',
'ehandlers',
'root',
'styleName',
'id'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
'OpenGLTypes' 'OpenGLTypes',
'SDL2Constants'
], ],
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
@ -24,6 +29,20 @@ DiyaNode class >> with: shader [
^self new shader: shader; yourself ^self new shader: shader; yourself
] ]
{ #category : #accessing }
DiyaNode >> ? style [
| styles value|
styleName ifNotNil: [
styles := DiyaUIThemesManager uniqueInstance currentTheme ? (self styleName).
value := styles at: style ifAbsent:[nil].
value ifNotNil: [ ^value ].
].
"try to look at parent"
parent ifNil:[self styleNotFound: style].
"parent styleName = self styleName ifTrue: [self styleNotFound: style]."
^ parent ? style
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> addNode: node [ DiyaNode >> addNode: node [
^self addNode: node at: 0@0 ^self addNode: node at: 0@0
@ -35,6 +54,7 @@ DiyaNode >> addNode: node at: pos [
node parent: self. node parent: self.
node position: pos. node position: pos.
children add: node. children add: node.
node root: self root.
^ node ^ node
] ]
@ -53,11 +73,21 @@ DiyaNode >> draw [
self subclassResponsibility self subclassResponsibility
] ]
{ #category : #requirements }
DiyaNode >> empty [
children := OrderedCollection new.
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> extent [ DiyaNode >> extent [
^ self subclassResponsibility ^ self subclassResponsibility
] ]
{ #category : #accessing }
DiyaNode >> id [
^ id
]
{ #category : #initialization } { #category : #initialization }
DiyaNode >> initialize [ DiyaNode >> initialize [
super initialize. super initialize.
@ -65,12 +95,33 @@ DiyaNode >> initialize [
shader := nil. shader := nil.
context := DiyaRendererContext uniqueInstance. context := DiyaRendererContext uniqueInstance.
children := OrderedCollection new. children := OrderedCollection new.
dirty := false dirty := false.
ehandlers := Dictionary new.
styleName := nil.
root := nil.
id := Random new nextInt: 1e6
]
{ #category : #accessing }
DiyaNode >> inner: aPoint [
^ self subclassResponsibility
]
{ #category : #testing }
DiyaNode >> isDirty [
^ dirty
] ]
{ #category : #testing } { #category : #testing }
DiyaNode >> isRoot [ DiyaNode >> isRoot [
^false ^ false
]
{ #category : #convenience }
DiyaNode >> on: eventName do: aBlock [
eventName isArray ifFalse:[ ^ self register: aBlock to: eventName ].
eventName do:[:e| self register: aBlock to:e ].
] ]
{ #category : #accessing } { #category : #accessing }
@ -94,15 +145,35 @@ DiyaNode >> position: anObject [
self updateTF. 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 } { #category : #accessing }
DiyaNode >> render [ DiyaNode >> render [
dirty ifTrue:[dirty := self update not]. dirty ifTrue:[
shader ifNotNil: [ self setUpShader ]. dirty := self update not].
shader ifNotNil: [self setUpShader].
self draw. self draw.
children ifNil: [ ^self ]. children ifNil: [ ^self ].
children do: [:c | c render ]. children do: [:c | c render ].
] ]
{ #category : #accessing }
DiyaNode >> root [
^ root
]
{ #category : #accessing }
DiyaNode >> root: anObject [
root := anObject
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> rotation [ DiyaNode >> rotation [
^ rotation ^ rotation
@ -125,6 +196,16 @@ DiyaNode >> scale: anObject [
self updateTF. self updateTF.
] ]
{ #category : #initialization }
DiyaNode >> setClean [
dirty := false
]
{ #category : #initialization }
DiyaNode >> setDirty [
dirty := true
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> setUpShader [ DiyaNode >> setUpShader [
|mem| |mem|
@ -139,7 +220,7 @@ DiyaNode >> setUpShader [
"in shader, window origin is bottom left conor of the window "in shader, window origin is bottom left conor of the window
the mouse position should be transformed to this coodinate" the mouse position should be transformed to this coodinate"
shader setUniform: #u_mouse value: shader setUniform: #u_mouse value:
{ context mouse x. context resolution y - context mouse y }. { context mouse x. context mouse y }.
]. ].
mem free. mem free.
] ]
@ -157,12 +238,42 @@ DiyaNode >> shader: anObject [
shader := anObject shader := anObject
] ]
{ #category : #accessing }
DiyaNode >> styleName [
^ styleName
]
{ #category : #accessing }
DiyaNode >> styleName: anObject [
styleName := anObject.
self setDirty
]
{ #category : #'event handling' }
DiyaNode >> styleNotFound: style [
"looking for default theme in global"
^(DiyaUIThemesManager uniqueInstance defaultTheme ? (self styleName))
at: style ifAbsent:[
DiyaCoreAPIError signal: 'Query undefined style ', style, ' in', styleName.
]
]
{ #category : #accessing } { #category : #accessing }
DiyaNode >> tf [ DiyaNode >> tf [
parent ifNil: [ self error: 'TF: This node is not attached to the main tree' ].
^ tf ^ tf
] ]
{ #category : #'event handling' }
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 } { #category : #accessing }
DiyaNode >> update [ DiyaNode >> update [
^self subclassResponsibility ^self subclassResponsibility

View File

@ -37,7 +37,7 @@ DiyaPolygon >> points [
{ #category : #accessing } { #category : #accessing }
DiyaPolygon >> points: anObject [ DiyaPolygon >> points: anObject [
points := anObject. points := anObject.
dirty := true self setDirty
] ]
{ #category : #accessing } { #category : #accessing }

View File

@ -16,17 +16,14 @@ DiyaRectangle class >> size: size shader:s [
{ #category : #initialization } { #category : #initialization }
DiyaRectangle >> drawLines [ DiyaRectangle >> drawLines [
self drawLineAt: 0. OpenGL drawArrays: GL_LINE_LOOP first:0 count: (vbuffer size >> 2).
self drawLineAt: 1.
self drawLineAt: 3.
self drawLineAt: 4.
] ]
{ #category : #accessing } { #category : #accessing }
DiyaRectangle >> extent: v [ DiyaRectangle >> extent: v [
bbox := Rectangle origin:0@0 corner: v. bbox := Rectangle origin:0@0 corner: v.
dirty := true self setDirty
] ]
{ #category : #accessing } { #category : #accessing }
@ -34,8 +31,9 @@ DiyaRectangle >> initialize [
super initialize. super initialize.
self extent:10@10. self extent:10@10.
translation := nil. translation := nil.
vbuffer := FFIExternalArray externalNewType: GLfloat size:24. vbuffer := FFIExternalArray externalNewType: GLfloat size:16.
vbuffer autoRelease. vbuffer autoRelease.
type := GL_QUADS.
] ]
{ #category : #accessing } { #category : #accessing }
@ -43,13 +41,10 @@ DiyaRectangle >> update [
|extent| |extent|
extent := self extent. extent := self extent.
{ {
0.0. extent y. 0.0. 0.0. 0. 0. 0.0. 0.0.
0. 0. 0.0. 1.0. 0. extent y. 0.0. 1.0.
extent x. 0.0. 1.0. 1.0. extent x. extent y. 1.0. 1.0.
extent x. 0. 1.0. 0.0.
extent x. 0.0. 1.0. 1.0.
extent x. extent y. 1.0. 0.0.
0.0. extent y. 0.0. 0.0.
} doWithIndex: [:e :i| vbuffer at: i put: e]. } doWithIndex: [:e :i| vbuffer at: i put: e].
^true ^true
] ]

View File

@ -1,37 +0,0 @@
Class {
#name : #DiyaRenderer,
#superclass : #DiyaSingleton,
#instVars : [
'root'
],
#pools : [
'OpenGLConstants',
'OpenGLTypes'
],
#category : #'Diya-Graphics'
}
{ #category : #'instance creation' }
DiyaRenderer class >> fromContext: ctx [
^self new context: ctx; yourself
]
{ #category : #initialization }
DiyaRenderer >> initialize [
super initialize.
]
{ #category : #deleting }
DiyaRenderer >> render [
root render.
]
{ #category : #accessing }
DiyaRenderer >> root [
^ root
]
{ #category : #accessing }
DiyaRenderer >> root: anObject [
root := anObject
]

View File

@ -7,7 +7,8 @@ Class {
'vbo', 'vbo',
'vao', 'vao',
'texture0', 'texture0',
'projection' 'projection',
'assets'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -27,6 +28,16 @@ DiyaRendererContext class >> maxFloatBufferSize [
^4096 ^4096
] ]
{ #category : #accessing }
DiyaRendererContext >> assets [
^ assets
]
{ #category : #accessing }
DiyaRendererContext >> assets: anObject [
assets := anObject
]
{ #category : #accessing } { #category : #accessing }
DiyaRendererContext >> destroy [ DiyaRendererContext >> destroy [
vao delete. vao delete.
@ -53,6 +64,7 @@ DiyaRendererContext >> initialize [
vao bind. vao bind.
vbo bind: GL_ARRAY_BUFFER. vbo bind: GL_ARRAY_BUFFER.
projection := Array2D identity: 4. projection := Array2D identity: 4.
assets := AssetManager new.
] ]
{ #category : #accessing } { #category : #accessing }

View File

@ -4,23 +4,42 @@ Class {
#category : #'Diya-Graphics' #category : #'Diya-Graphics'
} }
{ #category : #accessing }
DiyaRootNode >> boundingBox [
^ Rectangle origin: 0@0 corner: context resolution
]
{ #category : #accessing } { #category : #accessing }
DiyaRootNode >> draw [ DiyaRootNode >> draw [
OpenGL clearColorR: 0.0 G: 0.0 B: 0.0 A:0. |c|
c := self ? #bgColor.
OpenGL clearColorR: c red G: c green B: c blue A: c alpha.
OpenGL clear: GL_COLOR_BUFFER_BIT. OpenGL clear: GL_COLOR_BUFFER_BIT.
context vbo bind: GL_ARRAY_BUFFER. context vbo bind: GL_ARRAY_BUFFER.
] ]
{ #category : #accessing }
DiyaRootNode >> extent [
^ context resolution
]
{ #category : #initialization } { #category : #initialization }
DiyaRootNode >> initialize [ DiyaRootNode >> initialize [
super initialize. super initialize.
parent := self. parent := self.
shader := nil. shader := nil.
root := self.
styleName := #global
] ]
{ #category : #testing } { #category : #'as yet unclassified' }
DiyaRootNode >> inner: aPoint [
^true
]
{ #category : #accessing }
DiyaRootNode >> isRoot [ DiyaRootNode >> isRoot [
^ true ^true
] ]
{ #category : #initialization } { #category : #initialization }

View File

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

View File

@ -19,7 +19,7 @@ DiyaSingleton class >> initialize [
{ #category : #'instance creation' } { #category : #'instance creation' }
DiyaSingleton class >> new [ DiyaSingleton class >> new [
self error: 'Use #uniqueInstance' ^ DiyaCoreAPIError signal: 'Use #uniqueInstance'
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
@ -31,6 +31,11 @@ DiyaSingleton class >> reset [
singletons removeKey: key singletons removeKey: key
] ]
{ #category : #'instance creation' }
DiyaSingleton class >> resetAll [
self allSubclasses do:[:e| e reset]
]
{ #category : #'instance creation' } { #category : #'instance creation' }
DiyaSingleton class >> uniqueInstance [ DiyaSingleton class >> uniqueInstance [
^singletons at: self class asString asSymbol ifAbsentPut: [ super new ]. ^singletons at: self class asString asSymbol ifAbsentPut: [ super new ].

View File

@ -0,0 +1,33 @@
Class {
#name : #DiyaStyleSheet,
#superclass : #DiyaBaseObject,
#instVars : [
'stylesheet'
],
#category : #'Diya-Graphics'
}
{ #category : #convenience }
DiyaStyleSheet >> ? sheet [
^stylesheet at: sheet ifAbsent:[
DiyaCoreAPIError signal: 'Unable to query stylesheet ', sheet
].
]
{ #category : #initialization }
DiyaStyleSheet >> define: name styles: styles [
stylesheet at: name put: styles asDictionary.
^self
]
{ #category : #initialization }
DiyaStyleSheet >> initialize [
super initialize.
stylesheet := Dictionary new.
]
{ #category : #accessing }
DiyaStyleSheet >> stylesheet [
^ stylesheet
]

View File

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

View File

@ -1,13 +1,13 @@
Class { Class {
#name : #DiyaText, #name : #DiyaText,
#superclass : #Diya2DNode, #superclass : #Diya2DPrimShape,
#instVars : [ #instVars : [
'fontStyle',
'fontSize',
'fontName',
'data', 'data',
'style', 'wrap',
'wrap' 'texheight',
'font',
'lines',
'maxLineWidth'
], ],
#pools : [ #pools : [
'FT2Types' 'FT2Types'
@ -25,6 +25,34 @@ DiyaText class >> data: string shader: s [
^ (self with:s) data: string; yourself ^ (self with:s) data: string; yourself
] ]
{ #category : #'menu messages' }
DiyaText >> align [
^ self ? #xAlign
]
{ #category : #accessing }
DiyaText >> alignLine:w [
self align = #center ifTrue:[^ 0 max:((self extent x - w) / 2.0 ) asFloat].
self align = #right ifTrue:[^ 0 max: self extent x - w].
^0
]
{ #category : #initialization }
DiyaText >> allocMemory [
vbuffer ifNotNil: [
vbuffer size >= data size
ifTrue: [^self]
ifFalse:[vbuffer free]
].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease.
]
{ #category : #accessing }
DiyaText >> borderWidth [
^0
]
{ #category : #accessing } { #category : #accessing }
DiyaText >> data [ DiyaText >> data [
^ data ^ data
@ -33,144 +61,194 @@ DiyaText >> data [
{ #category : #accessing } { #category : #accessing }
DiyaText >> data: anObject [ DiyaText >> data: anObject [
data := anObject. data := anObject.
dirty := true self setDirty
] ]
{ #category : #accessing } { #category : #initialization }
DiyaText >> draw [ DiyaText >> drawBorder [
data ifNil: [ ^self ]. self shouldNotBeCalled
self shader ]
setUniform: #u_texture_type value: self texture format.
"configure vao vbo for texture QUAD"
self texture setup.
context texture0 setImage2D: self texture.
context texture0 active.
context vao enableAttribute: 0.
OpenGLVertexArray vertexAttributePointerIndex: 0 size:4 type: GL_FLOAT normalized: GL_FALSE stride: 16 pointer: nil .
context vbo data: GL_ARRAY_BUFFER data: vbuffer usage: GL_STATIC_DRAW.
OpenGL drawArrays: GL_TRIANGLES first:0 count: ((vbuffer size) >> 2).
context vao disableAttribute: 0.
"reset value"
self texture drop.
{ #category : #initialization }
DiyaText >> drawLines [
^ self shouldNotBeCalled
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> drawText [ DiyaText >> drawText [
|vertices index tex2D offset| self splitLines.
index := 1. self formatText .
offset := 0@0.
tex2D := self texture.
1 to: data size do: [ :i|
vertices := self getCharsVerticesAt:i offset: offset on: tex2D.
vertices do: [
:e| vbuffer at: index put:e.
index := index + 1.
].
(offset x > self extent x and: wrap not) ifTrue: [ ^self ].
(offset y negated > self extent y) ifTrue: [ ^self ].
].
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> extent: v [ DiyaText >> extent: v [
bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ). bbox := Rectangle origin: 0@0 corner: (v x) @ (v y negated ).
dirty := true self setDirty
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> fontName [ DiyaText >> fontName [
^ fontName ^ self ? #fontFamily
]
{ #category : #initialization }
DiyaText >> fontName: name style: face size: size [
name ifNotNil: [ fontName := name ].
face ifNotNil: [ fontStyle := face ].
fontSize := size.
style := DiyaFontManager uniqueInstance style: self fontStyle from: self fontName.
dirty := true.
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> fontSize [ DiyaText >> fontSize [
^ fontSize ^ self ? #fontSize
]
{ #category : #initialization }
DiyaText >> fontSize: size [
self fontName: nil style:nil size: size
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> fontStyle [ DiyaText >> fontStyle [
^ fontStyle ^ self ? #fontStyle
] ]
{ #category : #accessing } { #category : #accessing }
DiyaText >> getCharsVerticesAt:i offset: offset on: tex2D [ DiyaText >> formatText [
|x y w h glyph gsize c | |offset index line|
c := (data at:i) asciiValue. lines ifNil: [^self].
c = (Character space asciiValue) ifTrue:[ offset := 0@(self valignText: (texture linespace) * (lines size)).
offset setX: (offset x + (tex2D spacing ) ) setY: offset y. index := 1.
wrap ifTrue: [ lines do:[:assoc|
(offset x + ((self nextSpaceFrom: i + 1) * (tex2D fontSize))) > (self extent x) ifTrue: [ line := assoc value.
offset setX: 0.0 setY: (offset y )- (tex2D linespace)]. 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)
]. ].
glyph := tex2D getGlyph: c.
]
{ #category : #accessing }
DiyaText >> getCharsVerticesFrom:glyph offset: offset cellh: cellh [
|x y w h gsize texcoord|
gsize := glyph extent. gsize := glyph extent.
((offset x > self extent x) and: (gsize x > 0)) ifTrue:[
wrap ifFalse: [ ^ { } ].
offset setX: 0.0 setY: (offset y )- (tex2D linespace).
offset y negated > self extent y ifTrue:[^{}].
].
x := offset x + (glyph bearing x). x := offset x + (glyph bearing x).
y := offset y - (tex2D cellh). y := offset y "- cellh".
w := (gsize x). w := (gsize x).
h := (gsize y). h := (gsize y).
texcoord := glyph texcoord.
offset setX: (offset x + (glyph advance x)) setY: offset y. offset setX: (offset x + (glyph advance x)) setY: offset y.
^{x. y + h. glyph texcoord origin x. glyph texcoord origin y. ^{x. y. texcoord origin x. texcoord origin y.
x. y. glyph texcoord origin x. glyph texcoord corner y. x. y + h. texcoord origin x. texcoord corner y.
x + w. y. glyph texcoord corner x. glyph texcoord corner y. x + w. y + h. texcoord corner x. texcoord corner y.
x. y + h. glyph texcoord origin x. glyph texcoord origin y. "x. y + h. texcoord origin x. texcoord origin y.
x + w. y. glyph texcoord corner x. glyph texcoord corner y. x + w. y. texcoord corner x. texcoord corner y."
x + w. y + h. glyph texcoord corner x. glyph texcoord origin 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 } { #category : #initialization }
DiyaText >> initialize [ DiyaText >> initialize [
super initialize. super initialize.
self fontName: 'Ubuntu' style:'Regular' size: 16.
data := nil. data := nil.
wrap := false. wrap := false.
bbox := nil texheight := 0.
type := GL_QUADS.
maxLineWidth := 0.
] ]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
DiyaText >> nextSpaceFrom: index [ DiyaText >> lastSeparatorFrom: index [
index to: (data size) do: [:i| index to: 1 by: -1 do: [:i|
(data at: i) = (Character space) ifTrue:[^i - index]. (data at: i) isSeparator ifTrue:[^i].
]. ].
^ 0 ^ 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 } { #category : #accessing }
DiyaText >> texture [ DiyaText >> texture [
^style textureOf: self fontSize texture ifNil: [ self initTexture ].
texheight = texture height ifFalse: [
texheight := texture height.
self update.
self setClean.
].
^texture
] ]
{ #category : #initialization } { #category : #initialization }
DiyaText >> update [ DiyaText >> update [
bbox ifNil: [ ^false ]. bbox ifNil: [ ^true ].
data ifNil:[^true].
data ifEmpty:[^true].
vbuffer ifNotNil: [vbuffer free]. vbuffer ifNotNil: [vbuffer free].
vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 24. vbuffer := FFIExternalArray externalNewType: GLfloat size: data size * 16.
vbuffer autoRelease. vbuffer autoRelease.
self drawText. self drawText.
^true ^true
] ]
{ #category : #'menu messages' }
DiyaText >> valign [
^ self ? #yAlign
]
{ #category : #accessing }
DiyaText >> valignText:h [
self valign = #middle ifTrue:[^ (0 max:((self extent y - h) / 2 ) asFloat)].
self valign = #bottom ifTrue:[^ (0 max:(self extent y - h ))].
^0
]
{ #category : #initialization } { #category : #initialization }
DiyaText >> wordWrap: aBool [ DiyaText >> wordWrap: aBool [
wrap := aBool. wrap := aBool.

View File

@ -0,0 +1,68 @@
Class {
#name : #DiyaUIThemesManager,
#superclass : #DiyaSingleton,
#instVars : [
'themes',
'currentThemeName'
],
#category : #'Diya-Graphics'
}
{ #category : #adding }
DiyaUIThemesManager >> addTheme:name stylesheet:sheet [
themes at:name put: sheet
]
{ #category : #accessing }
DiyaUIThemesManager >> currentTheme [
^ themes at: self currentThemeName ifAbsent: [
DiyaCoreAPIError signal: 'Undefined theme named', self currentThemeName
]
]
{ #category : #accessing }
DiyaUIThemesManager >> currentThemeName [
^ currentThemeName
]
{ #category : #accessing }
DiyaUIThemesManager >> currentThemeName: anObject [
currentThemeName := anObject
]
{ #category : #initialization }
DiyaUIThemesManager >> defaultTheme [
^ themes at: #default
]
{ #category : #initialization }
DiyaUIThemesManager >> defineDefaultTheme [
self addTheme: #default stylesheet: (DiyaStyleSheet new
define: #global styles: {
#bgColor -> (Color r: 0.2118 g: 0.2118 b: 0.2118).
#color -> Color white.
#border -> 0.
#fontSize -> 18.
#fontFamily -> DiyaFontManager uniqueInstance defaultFamily.
#textIconFamily -> 'bootstrap-icons'.
#fontStyle -> DiyaFontManager uniqueInstance defaultStyle.
#borderColor -> Color transparent.
#xAlign -> #left.
#yAlign -> #middle.
#iconSize -> 24.
}
)
]
{ #category : #initialization }
DiyaUIThemesManager >> initialize [
super initialize.
themes := Dictionary new.
self defineDefaultTheme.
self currentThemeName: #default.
]
{ #category : #accessing }
DiyaUIThemesManager >> themes [
^ themes
]

View File

@ -1,5 +1,29 @@
Class { Class {
#name : #DiyaWidget, #name : #DiyaWidget,
#superclass : #Diya2DNode, #superclass : #Diya2DNode,
#instVars : [
'extent'
],
#category : #'Diya-Widgets' #category : #'Diya-Widgets'
} }
{ #category : #'instance creation' }
DiyaWidget class >> fromStyle: aStyle [
^self new style: aStyle; yourself
]
{ #category : #geometry }
DiyaWidget >> extent [
^extent
]
{ #category : #geometry }
DiyaWidget >> extent: size [
extent := size.
self setDirty.
]
{ #category : #initialization }
DiyaWidget >> initialize [
super initialize.
]

View File

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

View File

@ -6,7 +6,13 @@ Class {
'cellw', 'cellw',
'cellh', 'cellh',
'spacing', 'spacing',
'fontSize' 'fontSize',
'colp',
'rowp',
'face',
'maxbearing',
'maxrows',
'meanww'
], ],
#pools : [ #pools : [
'OpenGLConstants', 'OpenGLConstants',
@ -26,7 +32,6 @@ OpenGLFontTex >> blitPixel8: bitmap at: offset size: size [
0 to: size y - 1 do: [ :i| 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 LibC memCopy: (bitmap getHandle + (i* (size x))) to:(data getHandle + ((i + offset y) * width + (offset x) )) size: size x
]. ].
bitmap free.
] ]
{ #category : #accessing } { #category : #accessing }
@ -44,39 +49,6 @@ OpenGLFontTex >> charmap [
^ charmap ^ charmap
] ]
{ #category : #'instance creation' }
OpenGLFontTex >> createBitmapFontFrom: glyphs maxBearing: maxbearing [
|bmp metric offset nrows index element|
data ifNotNil: [data free ].
charmap := Dictionary new.
nrows := glyphs size >> 5.
(glyphs size % 32) = 0 ifFalse:[nrows := nrows + 1].
data := FFIExternalArray externalNewType: GLubyte size:cellw * cellh * (nrows << 5).
LibC memset: data getHandle value: 0 size: data size.
data autoRelease.
index := 1.
offset := 0@0.
width := cellw * 32.
height := cellh * nrows.
0 to: nrows - 1 do: [ :row|
0 to: 31 do: [ :col| |glyph|
element := glyphs at: index.
metric := element at: 3.
bmp := element at:2.
offset := (col * cellw) @ (row*cellh).
glyph := (DiyaFontGlyph origin: offset extent: ((metric first x asInteger) @ cellh)).
glyph
bearing: (metric at: 2) asFloatPoint;
advance: (metric at: 3) asFloatPoint;
texcoord: (Rectangle origin: (glyph origin/ (self extent) ) asFloatPoint corner: ((glyph corner) / (self extent)) asFloatPoint ).
charmap at: element first put:glyph.
self blitPixel8: bmp at: (offset x) @ ((offset y) + maxbearing - (metric last) ) size: metric first.
index := index + 1.
index > glyphs size ifTrue:[^self].
]
].
]
{ #category : #accessing } { #category : #accessing }
OpenGLFontTex >> drop [ OpenGLFontTex >> drop [
OpenGL OpenGL
@ -91,50 +63,72 @@ OpenGLFontTex >> fontSize [
] ]
{ #category : #'instance creation' } { #category : #'instance creation' }
OpenGLFontTex >> fromFace: face ofSize: size [ OpenGLFontTex >> fromFace: aFace ofSize: size [
|minhang maxbearing rec glyphs iptr charcode w| |minhang rec iptr charcode w numw|
fontSize := size. fontSize := size.
face setPixelWidth:0 height: size. face := aFace.
glyphs := OrderedCollection new. charmap := Dictionary new.
cellw := 0. face setPixelWidth:0 height: self fontSize.
cellh := 0. cellw := cellh := minhang := maxbearing := 0.
minhang := 0.
maxbearing := 0.
iptr := FFIExternalArray externalNewType: GLuint size:1. iptr := FFIExternalArray externalNewType: GLuint size:1.
iptr at:1 put: 0. iptr at:1 put: 0.
rec := (FTFaceRec fromHandle: face getHandle). rec := (FTFaceRec fromHandle: face getHandle).
charcode := face getFirstChar: iptr getHandle. charcode := face getFirstChar: iptr getHandle.
meanww := 0.
numw := 0.
[ (iptr at: 1) = 0 ] whileFalse: [ [ (iptr at: 1) = 0 ] whileFalse: [
|bmp bmpsize metric|
face loadCharacter: charcode flags: (1 << 2). face loadCharacter: charcode flags: (1 << 2).
w := ((rec glyph metrics width) >> 6). w := ((rec glyph metrics width) >> 6).
(w > (size << 1)) ifFalse:[ (w > (size << 1)) ifFalse:[
metric := {
(((rec glyph metrics width) >> 6)@ ((rec glyph metrics height) >> 6)).
(face glyph hBearing).
(face glyph advance).
((rec glyph metrics horiBearingY) >> 6)
}.
maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6). maxbearing := maxbearing max: ((rec glyph metrics horiBearingY) >> 6).
cellw := cellw max: w. cellw := cellw max: w.
minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6). minhang := minhang min: ((( rec glyph metrics horiBearingY) - (rec glyph metrics height)) >> 6).
"copy buffer" meanww := meanww + w.
bmpsize := (rec glyph bitmap width)*(rec glyph bitmap rows). numw := numw + 1.
bmp := FFIExternalArray externalNewType: GLubyte size:bmpsize.
LibC memCopy: rec glyph bitmap buffer to: bmp getHandle size: bmpsize.
glyphs add: {charcode. bmp. metric}.
]. ].
charcode := face getNextChar: charcode iptr: iptr getHandle. charcode := face getNextChar: charcode iptr: iptr getHandle.
]. ].
cellh := maxbearing - minhang. cellh := maxbearing - minhang.
spacing := (size >> 2) asInteger. spacing := (cellw >> 2) asInteger.
self createBitmapFontFrom: glyphs maxBearing: maxbearing. 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. 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 } { #category : #accessing }
OpenGLFontTex >> getGlyph: c [ OpenGLFontTex >> getGlyph: c [
^(self charmap at: c ifAbsent:[^nil]) ^(self charmap at: c ifAbsentPut:[self genGlyph:c])
] ]
{ #category : #initialization } { #category : #initialization }
@ -148,6 +142,8 @@ OpenGLFontTex >> initialize [
internalFormat := GL_ALPHA. internalFormat := GL_ALPHA.
type := GL_UNSIGNED_BYTE. type := GL_UNSIGNED_BYTE.
target := GL_TEXTURE_2D. target := GL_TEXTURE_2D.
colp := 0.
rowp := 0.
] ]
{ #category : #accessing } { #category : #accessing }
@ -155,6 +151,24 @@ OpenGLFontTex >> linespace [
^ cellh ^ 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 } { #category : #accessing }
OpenGLFontTex >> setup [ OpenGLFontTex >> setup [
OpenGL OpenGL

View File

@ -88,11 +88,6 @@ OpenGLSL class >> linkProgram:program [
^self ffiCall: #(void glLinkProgram(GLuint program)) ^self ffiCall: #(void glLinkProgram(GLuint program))
] ]
{ #category : #'as yet unclassified' }
OpenGLSL class >> resetShaders [
self allSubclassesDo: [ :c| c reset ].
]
{ #category : #'as yet unclassified' } { #category : #'as yet unclassified' }
OpenGLSL class >> setShaderSourceFor: shader count: n string: s length: l [ OpenGLSL class >> setShaderSourceFor: shader count: n string: s length: l [
^ self ffiCall: #(void glShaderSource( GLuint shader,GLsizei n,const void* s,const GLint *l)) ^ self ffiCall: #(void glShaderSource( GLuint shader,GLsizei n,const void* s,const GLint *l))
@ -136,7 +131,7 @@ OpenGLSL >> checkStatus:status of: id [
] ifFalse: [ ] ifFalse: [
OpenGLSL getShaderInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer OpenGLSL getShaderInfoLogOf: id maxLength: (infoLength at: 1) lengthPtr: nil buffer: buffer
]. ].
^self error: buffer asString ^DiyaCoreAPIError signal: buffer asString
]. ].
^self ^self
@ -222,7 +217,7 @@ OpenGLSL >> locateUniforms [
OpenGLSL >> setUniform: uname value: values [ OpenGLSL >> setUniform: uname value: values [
|uniform| |uniform|
uniform := uniforms at: uname asSymbol ifAbsent:[ uniform := uniforms at: uname asSymbol ifAbsent:[
^self error: 'Uniform ', uname, ' is not defined in this program']. ^DiyaCoreAPIError signal: 'Uniform ', uname, ' is not defined in this program'].
uniform value: values uniform value: values
] ]

View File

@ -27,10 +27,10 @@ OrthoProjectionMatrix >> bottom [
{ #category : #initialization } { #category : #initialization }
OrthoProjectionMatrix >> calculate [ OrthoProjectionMatrix >> calculate [
self at:1 at:1 put: (2.0 /(self right - self left)). self at:1 at:1 put: (2.0 /(self right - self left)).
self at:2 at:2 put: (2.0 / (self top - self bottom)). self at:2 at:2 put: (2.0 / (self bottom - self top)).
self at:3 at:3 put: (2.0 / (self far - self near)) negated. self at: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:1 put: ((self right + self left)/ (self right - self left)) negated.
self at:4 at:2 put: ((self top + self bottom) / (self top - self bottom)) negated. self at:4 at:2 put: ((self top + self bottom) / (self bottom - self top)) negated.
self at:4 at:3 put: ((self far + self near)/(self far - self near)) negated. self at:4 at:3 put: ((self far + self near)/(self far - self near)) negated.
] ]

View File

@ -1,5 +1,20 @@
Extension { #name : #Point } 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' } { #category : #'*Diya' }
Point >> asGLCoord [ Point >> asGLCoord [
|res| |res|

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
]

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