Merge branch 'master' of git://factorcode.org/git/factor

db4
Doug Coleman 2008-04-28 15:18:07 -05:00
commit 1dbc37e0cd
29 changed files with 879 additions and 238 deletions

View File

@ -1,5 +1,5 @@
USING: generic help.markup help.syntax math memory
namespaces sequences kernel.private layouts sorting classes
namespaces sequences kernel.private layouts classes
kernel.private vectors combinators quotations strings words
assocs arrays math.order ;
IN: kernel
@ -241,7 +241,7 @@ ARTICLE: "conditionals" "Conditionals and logic"
"See " { $link "combinators" } " for forms which abstract away common patterns involving multiple nested branches."
{ $see-also "booleans" "bitwise-arithmetic" both? either? } ;
ARTICLE: "equality" "Equality and comparison testing"
ARTICLE: "equality" "Equality"
"There are two distinct notions of ``sameness'' when it comes to objects. You can test if two references point to the same object (" { $emphasis "identity comparison" } "), or you can test if two objects are equal in a domain-specific sense, usually by being instances of the same class, and having equal slot values (" { $emphasis "value comparison" } "). Both notions of equality are equality relations in the mathematical sense."
$nl
"Identity comparison:"
@ -250,16 +250,8 @@ $nl
{ $subsection = }
"Custom value comparison methods:"
{ $subsection equal? }
"Utility class:"
{ $subsection identity-tuple }
"Some types of objects also have an intrinsic order allowing sorting using " { $link natural-sort } ":"
{ $subsection <=> }
{ $subsection compare }
{ $subsection invert-comparison }
"Utilities for comparing objects:"
{ $subsection after? }
{ $subsection before? }
{ $subsection after=? }
{ $subsection before=? }
"An object can be cloned; the clone has distinct identity but equal value:"
{ $subsection clone } ;
@ -394,8 +386,6 @@ HELP: identity-tuple
{ $unchecked-example "T{ foo } dup clone = ." "f" }
} ;
{ <=> compare natural-sort sort-keys sort-values } related-words
HELP: clone
{ $values { "obj" object } { "cloned" "a new object" } }
{ $contract "Outputs a new object equal to the given object. This is not guaranteed to actually copy the object; it does nothing with immutable objects, and does not copy words either. However, sequences and tuples can be cloned to obtain a shallow copy of the original." } ;

View File

@ -1,9 +1,9 @@
USING: help.markup help.syntax kernel math sequences quotations
math.private ;
USING: help.markup help.syntax kernel math quotations
math.private words ;
IN: math.order
HELP: <=>
{ $values { "obj1" object } { "obj2" object } { "n" real } }
{ $values { "obj1" object } { "obj2" object } { "symbol" symbol } }
{ $contract
"Compares two objects using an intrinsic total order, for example, the natural order for real numbers and lexicographic order for strings."
$nl
@ -13,7 +13,6 @@ HELP: <=>
{ { $link +eq+ } " - indicating that " { $snippet "obj1" } " is equal to " { $snippet "obj2" } }
{ { $link +gt+ } " - indicating that " { $snippet "obj1" } " follows " { $snippet "obj2" } }
}
"The default implementation treats the two objects as sequences, and recursively compares their elements. So no extra work is required to compare sequences lexicographically."
} ;
HELP: +lt+
@ -77,3 +76,19 @@ HELP: [-]
{ $values { "x" real } { "y" real } { "z" real } }
{ $description "Subtracts " { $snippet "y" } " from " { $snippet "x" } ". If the result is less than zero, outputs zero." } ;
ARTICLE: "math.order" "Ordered objects"
"Some classes have an intrinsic order amongst instances:"
{ $subsection <=> }
{ $subsection compare }
{ $subsection invert-comparison }
"The above words return one of the following symbols:"
{ $subsection +lt+ }
{ $subsection +eq+ }
{ $subsection +gt+ }
"Utilities for comparing objects:"
{ $subsection after? }
{ $subsection before? }
{ $subsection after=? }
{ $subsection before=? } ;
ABOUT: "math.order"

View File

@ -7,11 +7,13 @@ SYMBOL: +lt+
SYMBOL: +eq+
SYMBOL: +gt+
GENERIC: <=> ( obj1 obj2 -- n )
GENERIC: <=> ( obj1 obj2 -- symbol )
: (<=>) - dup 0 < [ drop +lt+ ] [ zero? +eq+ +gt+ ? ] if ;
: (<=>) ( a b -- symbol )
2dup < [ 2drop +lt+ ] [ number= +eq+ +gt+ ? ] if ; inline
: invert-comparison ( symbol -- new-symbol )
#! Can't use case, index or nth here
dup +lt+ eq? [ drop +gt+ ] [ +eq+ eq? +eq+ +lt+ ? ] if ;
M: real <=> (<=>) ;

View File

@ -62,3 +62,5 @@ HELP: binsearch*
{ $description "Variant of " { $link binsearch } " which outputs the found element rather than its index in the sequence."
$nl
"Outputs " { $link f } " if the sequence is empty. If the sequence has at least one element, this word always outputs a sequence element." } ;
{ <=> compare natural-sort sort-keys sort-values } related-words

View File

@ -4,7 +4,7 @@ opengl.glu shuffle http.client vectors namespaces ui.gadgets
ui.gadgets.canvas ui.render ui splitting combinators tools.time
system combinators.lib float-arrays continuations
opengl.demo-support multiline ui.gestures bunny.fixed-pipeline
bunny.cel-shaded bunny.outlined bunny.model ;
bunny.cel-shaded bunny.outlined bunny.model accessors ;
IN: bunny
TUPLE: bunny-gadget model geom draw-seq draw-n ;
@ -13,38 +13,33 @@ TUPLE: bunny-gadget model geom draw-seq draw-n ;
0.0 0.0 0.375 <demo-gadget>
maybe-download read-model {
set-delegate
set-bunny-gadget-model
(>>model)
} bunny-gadget construct ;
: bunny-gadget-draw ( gadget -- draw )
{ bunny-gadget-draw-n bunny-gadget-draw-seq }
{ draw-n>> draw-seq>> }
get-slots nth ;
: bunny-gadget-next-draw ( gadget -- )
dup { bunny-gadget-draw-seq bunny-gadget-draw-n }
dup { draw-seq>> draw-n>> }
get-slots
1+ swap length mod
swap [ set-bunny-gadget-draw-n ] keep relayout-1 ;
>>draw-n relayout-1 ;
M: bunny-gadget graft* ( gadget -- )
GL_DEPTH_TEST glEnable
dup bunny-gadget-model <bunny-geom>
over {
[ <bunny-fixed-pipeline> ]
[ <bunny-cel-shaded> ]
[ <bunny-outlined> ]
} map-call-with [ ] filter
0
roll {
set-bunny-gadget-geom
set-bunny-gadget-draw-seq
set-bunny-gadget-draw-n
} set-slots ;
dup model>> <bunny-geom> >>geom
dup
[ <bunny-fixed-pipeline> ]
[ <bunny-cel-shaded> ]
[ <bunny-outlined> ] tri 3array
[ ] filter >>draw-seq
0 >>draw-n
drop ;
M: bunny-gadget ungraft* ( gadget -- )
{ bunny-gadget-geom bunny-gadget-draw-seq } get-slots
[ [ dispose ] when* ] each
[ dispose ] when* ;
[ geom>> [ dispose ] when* ]
[ draw-seq>> [ [ dispose ] when* ] each ] bi ;
M: bunny-gadget draw-gadget* ( gadget -- )
0.15 0.15 0.15 1.0 glClearColor
@ -52,7 +47,7 @@ M: bunny-gadget draw-gadget* ( gadget -- )
dup demo-gadget-set-matrices
GL_MODELVIEW glMatrixMode
0.02 -0.105 0.0 glTranslatef
{ bunny-gadget-geom bunny-gadget-draw } get-slots
{ geom>> bunny-gadget-draw } get-slots
draw-bunny ;
M: bunny-gadget pref-dim* ( gadget -- dim )

View File

@ -1,5 +1,5 @@
USING: arrays bunny.model continuations kernel multiline opengl opengl.shaders
opengl.capabilities opengl.gl sequences sequences.lib ;
opengl.capabilities opengl.gl sequences sequences.lib accessors ;
IN: bunny.cel-shaded
STRING: vertex-shader-source
@ -68,11 +68,12 @@ TUPLE: bunny-cel-shaded program ;
: <bunny-cel-shaded> ( gadget -- draw )
drop
cel-shading-supported? [
bunny-cel-shaded new
vertex-shader-source <vertex-shader> check-gl-shader
cel-shaded-fragment-shader-lib-source <fragment-shader> check-gl-shader
cel-shaded-fragment-shader-main-source <fragment-shader> check-gl-shader
3array <gl-program> check-gl-program
{ set-bunny-cel-shaded-program } bunny-cel-shaded construct
>>program
] [ f ] if ;
: (draw-cel-shaded-bunny) ( geom program -- )
@ -85,8 +86,8 @@ TUPLE: bunny-cel-shaded program ;
} [ bunny-geom ] with-gl-program ;
M: bunny-cel-shaded draw-bunny
bunny-cel-shaded-program (draw-cel-shaded-bunny) ;
program>> (draw-cel-shaded-bunny) ;
M: bunny-cel-shaded dispose
bunny-cel-shaded-program delete-gl-program ;
program>> delete-gl-program ;

View File

@ -6,7 +6,7 @@ TUPLE: bunny-fixed-pipeline ;
: <bunny-fixed-pipeline> ( gadget -- draw )
drop
{ } bunny-fixed-pipeline construct ;
bunny-fixed-pipeline new ;
M: bunny-fixed-pipeline draw-bunny
drop

View File

@ -2,7 +2,7 @@ USING: alien alien.c-types arrays sequences math math.vectors
math.matrices math.parser io io.files kernel opengl opengl.gl
opengl.glu io.encodings.ascii opengl.capabilities shuffle
http.client vectors splitting tools.time system combinators
float-arrays continuations namespaces sequences.lib ;
float-arrays continuations namespaces sequences.lib accessors ;
IN: bunny.model
: numbers ( str -- seq )
@ -85,24 +85,24 @@ M: bunny-dlist bunny-geom
bunny-dlist-list glCallList ;
M: bunny-buffers bunny-geom
dup {
bunny-buffers-array
bunny-buffers-element-array
} get-slots [
dup { array>> element-array>> } get-slots [
{ GL_VERTEX_ARRAY GL_NORMAL_ARRAY } [
GL_DOUBLE 0 0 buffer-offset glNormalPointer
dup bunny-buffers-nv "double" heap-size * buffer-offset
3 GL_DOUBLE 0 roll glVertexPointer
bunny-buffers-ni
GL_TRIANGLES swap GL_UNSIGNED_INT 0 buffer-offset glDrawElements
[
nv>> "double" heap-size * buffer-offset
3 GL_DOUBLE 0 roll glVertexPointer
] [
ni>>
GL_TRIANGLES swap GL_UNSIGNED_INT 0 buffer-offset glDrawElements
] bi
] all-enabled-client-state
] with-array-element-buffers ;
M: bunny-dlist dispose
bunny-dlist-list delete-dlist ;
list>> delete-dlist ;
M: bunny-buffers dispose
{ bunny-buffers-array bunny-buffers-element-array } get-slots
{ array>> element-array>> } get-slots
delete-gl-buffer delete-gl-buffer ;
: <bunny-geom> ( model -- geom )

View File

@ -1,6 +1,7 @@
USING: arrays bunny.model bunny.cel-shaded continuations kernel
math multiline opengl opengl.shaders opengl.framebuffers
opengl.gl opengl.capabilities sequences ui.gadgets combinators ;
opengl.gl opengl.capabilities sequences ui.gadgets combinators
accessors ;
IN: bunny.outlined
STRING: outlined-pass1-fragment-shader-main-source
@ -139,9 +140,9 @@ TUPLE: bunny-outlined
: <bunny-outlined> ( gadget -- draw )
outlining-supported? [
pass1-program pass2-program {
set-bunny-outlined-gadget
set-bunny-outlined-pass1-program
set-bunny-outlined-pass2-program
(>>gadget)
(>>pass1-program)
(>>pass2-program)
} bunny-outlined construct
] [ drop f ] if ;
@ -169,35 +170,33 @@ TUPLE: bunny-outlined
] with-framebuffer ;
: dispose-framebuffer ( draw -- )
dup bunny-outlined-framebuffer-dim [
dup framebuffer-dim>> [
{
[ bunny-outlined-framebuffer [ delete-framebuffer ] when* ]
[ bunny-outlined-color-texture [ delete-texture ] when* ]
[ bunny-outlined-normal-texture [ delete-texture ] when* ]
[ bunny-outlined-depth-texture [ delete-texture ] when* ]
[ f swap set-bunny-outlined-framebuffer-dim ]
[ framebuffer>> [ delete-framebuffer ] when* ]
[ color-texture>> [ delete-texture ] when* ]
[ normal-texture>> [ delete-texture ] when* ]
[ depth-texture>> [ delete-texture ] when* ]
[ f >>framebuffer-dim drop ]
} cleave
] [ drop ] if ;
: remake-framebuffer-if-needed ( draw -- )
dup bunny-outlined-gadget rect-dim
over bunny-outlined-framebuffer-dim
dup [ gadget>> dim>> ] [ framebuffer-dim>> ] bi
over =
[ 2drop ]
[
swap dup dispose-framebuffer >r
dup GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
swap dup GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
swap dup GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT (framebuffer-texture)
swap >r
[ (make-framebuffer) ] 3keep
r> r> {
set-bunny-outlined-framebuffer
set-bunny-outlined-color-texture
set-bunny-outlined-normal-texture
set-bunny-outlined-depth-texture
set-bunny-outlined-framebuffer-dim
} set-slots
[ 2drop ] [
[ dup dispose-framebuffer dup ] dip {
[
GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
[ >>color-texture drop ] keep
] [
GL_RGBA16F_ARB GL_RGBA (framebuffer-texture)
[ >>normal-texture drop ] keep
] [
GL_DEPTH_COMPONENT32 GL_DEPTH_COMPONENT (framebuffer-texture)
[ >>depth-texture drop ] keep
]
} 2cleave
(make-framebuffer) >>framebuffer drop
] if ;
: clear-framebuffer ( -- )
@ -209,31 +208,34 @@ TUPLE: bunny-outlined
GL_COLOR_BUFFER_BIT glClear ;
: (pass1) ( geom draw -- )
dup bunny-outlined-framebuffer [
dup framebuffer>> [
clear-framebuffer
{ GL_COLOR_ATTACHMENT0_EXT GL_COLOR_ATTACHMENT1_EXT } set-draw-buffers
bunny-outlined-pass1-program (draw-cel-shaded-bunny)
pass1-program>> (draw-cel-shaded-bunny)
] with-framebuffer ;
: (pass2) ( draw -- )
init-matrices
dup bunny-outlined-color-texture GL_TEXTURE_2D GL_TEXTURE0 bind-texture-unit
dup bunny-outlined-normal-texture GL_TEXTURE_2D GL_TEXTURE1 bind-texture-unit
dup bunny-outlined-depth-texture GL_TEXTURE_2D GL_TEXTURE2 bind-texture-unit
bunny-outlined-pass2-program {
{ "colormap" [ 0 glUniform1i ] }
{ "normalmap" [ 1 glUniform1i ] }
{ "depthmap" [ 2 glUniform1i ] }
{ "line_color" [ 0.1 0.0 0.1 1.0 glUniform4f ] }
} [ { -1.0 -1.0 } { 1.0 1.0 } rect-vertices ] with-gl-program ;
init-matrices {
[ color-texture>> GL_TEXTURE_2D GL_TEXTURE0 bind-texture-unit ]
[ normal-texture>> GL_TEXTURE_2D GL_TEXTURE1 bind-texture-unit ]
[ depth-texture>> GL_TEXTURE_2D GL_TEXTURE2 bind-texture-unit ]
[
pass2-program>> {
{ "colormap" [ 0 glUniform1i ] }
{ "normalmap" [ 1 glUniform1i ] }
{ "depthmap" [ 2 glUniform1i ] }
{ "line_color" [ 0.1 0.0 0.1 1.0 glUniform4f ] }
} [ { -1.0 -1.0 } { 1.0 1.0 } rect-vertices ]
with-gl-program
]
} cleave ;
M: bunny-outlined draw-bunny
dup remake-framebuffer-if-needed
[ (pass1) ] keep (pass2) ;
[ remake-framebuffer-if-needed ]
[ (pass1) ]
[ (pass2) ] tri ;
M: bunny-outlined dispose
{
[ bunny-outlined-pass1-program [ delete-gl-program ] when* ]
[ bunny-outlined-pass2-program [ delete-gl-program ] when* ]
[ dispose-framebuffer ]
} cleave ;
[ pass1-program>> [ delete-gl-program ] when* ]
[ pass2-program>> [ delete-gl-program ] when* ]
[ dispose-framebuffer ] tri ;

View File

@ -104,6 +104,7 @@ $nl
ARTICLE: "objects" "Objects"
"An " { $emphasis "object" } " is any datum which may be identified. All values are objects in Factor. Each object carries type information, and types are checked at runtime; Factor is dynamically typed."
{ $subsection "equality" }
{ $subsection "math.order" }
{ $subsection "classes" }
{ $subsection "tuples" }
{ $subsection "generic" }

View File

@ -1,18 +1,11 @@
USING: arrays combinators.lib kernel math math.functions
math.order math.vectors namespaces opengl opengl.gl sequences ui
ui.gadgets ui.gestures ui.render ;
ui.gadgets ui.gestures ui.render accessors ;
IN: opengl.demo-support
: NEAR-PLANE 1.0 64.0 / ; inline
: FAR-PLANE 4.0 ; inline
: FOV 2.0 sqrt 1+ ; inline
: MOUSE-MOTION-SCALE 0.5 ; inline
: MOUSE-DISTANCE-SCALE 1.0 64.0 / ; inline
: KEY-ROTATE-STEP 1.0 ; inline
: KEY-DISTANCE-STEP 1.0 64.0 / ; inline
: DIMS { 640 480 } ; inline
: FOV-RATIO ( -- fov ) DIMS dup first2 min v/n ;
SYMBOL: last-drag-loc
@ -20,7 +13,20 @@ TUPLE: demo-gadget yaw pitch distance ;
: <demo-gadget> ( yaw pitch distance -- gadget )
demo-gadget construct-gadget
[ { set-demo-gadget-yaw set-demo-gadget-pitch set-demo-gadget-distance } set-slots ] keep ;
[ { (>>yaw) (>>pitch) (>>distance) } set-slots ] keep ;
GENERIC: far-plane ( gadget -- z )
GENERIC: near-plane ( gadget -- z )
GENERIC: distance-step ( gadget -- dz )
M: demo-gadget far-plane ( gadget -- z )
drop 4.0 ;
M: demo-gadget near-plane ( gadget -- z )
drop 1.0 64.0 / ;
M: demo-gadget distance-step ( gadget -- dz )
drop 1.0 64.0 / ;
: fov-ratio ( gadget -- fov ) dim>> dup first2 min v/n ;
: yaw-demo-gadget ( yaw gadget -- )
[ [ demo-gadget-yaw + ] keep set-demo-gadget-yaw ] keep relayout-1 ;
@ -32,26 +38,31 @@ TUPLE: demo-gadget yaw pitch distance ;
[ [ demo-gadget-distance + ] keep set-demo-gadget-distance ] keep relayout-1 ;
M: demo-gadget pref-dim* ( gadget -- dim )
drop DIMS ;
drop { 640 480 } ;
: -+ ( x -- -x x )
dup neg swap ;
: demo-gadget-frustum ( -- -x x -y y near far )
FOV-RATIO NEAR-PLANE FOV / v*n
first2 [ -+ ] bi@ NEAR-PLANE FAR-PLANE ;
: demo-gadget-frustum ( gadget -- -x x -y y near far )
[ near-plane ] [ far-plane ] [ fov-ratio ] tri [
nip swap FOV / v*n
first2 [ -+ ] bi@
] 3keep drop ;
: demo-gadget-set-matrices ( gadget -- )
GL_PROJECTION glMatrixMode
glLoadIdentity
demo-gadget-frustum glFrustum
GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT bitor glClear
GL_MODELVIEW glMatrixMode
glLoadIdentity
[ >r 0.0 0.0 r> demo-gadget-distance neg glTranslatef ]
[ demo-gadget-pitch 1.0 0.0 0.0 glRotatef ]
[ demo-gadget-yaw 0.0 1.0 0.0 glRotatef ]
tri ;
[
GL_PROJECTION glMatrixMode
glLoadIdentity
demo-gadget-frustum glFrustum
] [
GL_MODELVIEW glMatrixMode
glLoadIdentity
[ >r 0.0 0.0 r> distance>> neg glTranslatef ]
[ pitch>> 1.0 0.0 0.0 glRotatef ]
[ yaw>> 0.0 1.0 0.0 glRotatef ]
tri
] bi ;
: reset-last-drag-rel ( -- )
{ 0 0 } last-drag-loc set-global ;
@ -66,11 +77,11 @@ demo-gadget H{
{ T{ key-down f f "RIGHT" } [ KEY-ROTATE-STEP swap yaw-demo-gadget ] }
{ T{ key-down f f "DOWN" } [ KEY-ROTATE-STEP neg swap pitch-demo-gadget ] }
{ T{ key-down f f "UP" } [ KEY-ROTATE-STEP swap pitch-demo-gadget ] }
{ T{ key-down f f "=" } [ KEY-DISTANCE-STEP neg swap zoom-demo-gadget ] }
{ T{ key-down f f "-" } [ KEY-DISTANCE-STEP swap zoom-demo-gadget ] }
{ T{ key-down f f "=" } [ dup distance-step neg swap zoom-demo-gadget ] }
{ T{ key-down f f "-" } [ dup distance-step swap zoom-demo-gadget ] }
{ T{ button-down f f 1 } [ drop reset-last-drag-rel ] }
{ T{ drag f 1 } [ drag-yaw-pitch rot [ pitch-demo-gadget ] keep yaw-demo-gadget ] }
{ T{ mouse-scroll } [ scroll-direction get second MOUSE-DISTANCE-SCALE * swap zoom-demo-gadget ] }
{ T{ mouse-scroll } [ scroll-direction get second over distance-step * swap zoom-demo-gadget ] }
} set-gestures

View File

@ -0,0 +1 @@
Joe Groff

View File

@ -0,0 +1,284 @@
USING: kernel opengl.demo-support opengl.gl opengl.shaders opengl.framebuffers
opengl multiline ui.gadgets accessors sequences ui.render ui math
arrays arrays.lib combinators ;
IN: spheres
STRING: plane-vertex-shader
varying vec3 object_position;
void
main()
{
object_position = gl_Vertex.xyz;
gl_Position = ftransform();
}
;
STRING: plane-fragment-shader
varying vec3 object_position;
void
main()
{
float distance_factor = (gl_FragCoord.z * 0.5 + 0.5);
distance_factor = pow(distance_factor, 500.0)*0.5;
gl_FragColor = fract((floor(0.125*object_position.x)+floor(0.125*object_position.z)) * 0.5) == 0.0
? vec4(1.0, 1.0 - distance_factor, 1.0 - distance_factor, 1.0)
: vec4(1.0, distance_factor, distance_factor, 1.0);
}
;
STRING: sphere-vertex-shader
attribute vec3 center;
attribute float radius;
attribute vec4 surface_color;
varying float vradius;
varying vec3 sphere_position;
varying vec4 world_position, vcolor;
void
main()
{
world_position = gl_ModelViewMatrix * vec4(center, 1);
sphere_position = gl_Vertex.xyz;
gl_Position = gl_ProjectionMatrix * (world_position + vec4(sphere_position * radius, 0));
vcolor = surface_color;
vradius = radius;
}
;
STRING: sphere-solid-color-fragment-shader
uniform vec3 light_position;
varying vec4 vcolor;
const vec4 ambient = vec4(0.25, 0.2, 0.25, 1.0);
const vec4 diffuse = vec4(0.75, 0.8, 0.75, 1.0);
vec4
sphere_color(vec3 point, vec3 normal)
{
vec3 transformed_light_position = (gl_ModelViewMatrix * vec4(light_position, 1)).xyz;
vec3 direction = normalize(transformed_light_position - point);
float d = max(0.0, dot(normal, direction));
return ambient * vcolor + diffuse * vec4(d * vcolor.rgb, vcolor.a);
}
;
STRING: sphere-texture-fragment-shader
uniform samplerCube surface_texture;
vec4
sphere_color(vec3 point, vec3 normal)
{
vec3 reflect = reflect(normalize(point), normal);
return textureCube(surface_texture, reflect * gl_NormalMatrix);
}
;
STRING: sphere-main-fragment-shader
varying float vradius;
varying vec3 sphere_position;
varying vec4 world_position;
vec4 sphere_color(vec3 point, vec3 normal);
void
main()
{
float radius = length(sphere_position);
if(radius > 1.0) discard;
vec3 surface = sphere_position + vec3(0.0, 0.0, sqrt(1.0 - radius*radius));
vec4 world_surface = world_position + vec4(surface * vradius, 0);
vec4 transformed_surface = gl_ProjectionMatrix * world_surface;
gl_FragDepth = (transformed_surface.z/transformed_surface.w + 1.0) * 0.5;
gl_FragColor = sphere_color(world_surface.xyz, surface);
}
;
TUPLE: spheres-gadget
plane-program solid-sphere-program texture-sphere-program
reflection-framebuffer reflection-depthbuffer
reflection-texture ;
: <spheres-gadget> ( -- gadget )
20.0 10.0 20.0 <demo-gadget>
{ set-delegate } spheres-gadget construct ;
M: spheres-gadget near-plane ( gadget -- z )
drop 1.0 ;
M: spheres-gadget far-plane ( gadget -- z )
drop 512.0 ;
M: spheres-gadget distance-step ( gadget -- dz )
drop 0.5 ;
: (reflection-dim) ( -- w h )
512 512 ;
: (make-reflection-texture) ( -- texture )
gen-texture [
GL_TEXTURE_CUBE_MAP swap glBindTexture
GL_TEXTURE_CUBE_MAP GL_TEXTURE_MAG_FILTER GL_LINEAR glTexParameteri
GL_TEXTURE_CUBE_MAP GL_TEXTURE_MIN_FILTER GL_LINEAR glTexParameteri
GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_S GL_CLAMP glTexParameteri
GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_T GL_CLAMP glTexParameteri
GL_TEXTURE_CUBE_MAP GL_TEXTURE_WRAP_R GL_CLAMP glTexParameteri
GL_TEXTURE_CUBE_MAP_POSITIVE_X
GL_TEXTURE_CUBE_MAP_POSITIVE_Y
GL_TEXTURE_CUBE_MAP_POSITIVE_Z
GL_TEXTURE_CUBE_MAP_NEGATIVE_X
GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 6 narray
[ 0 GL_RGBA8 (reflection-dim) 0 GL_RGBA GL_UNSIGNED_BYTE f glTexImage2D ]
each
] keep ;
: (make-reflection-depthbuffer) ( -- depthbuffer )
gen-renderbuffer [
GL_RENDERBUFFER_EXT swap glBindRenderbufferEXT
GL_RENDERBUFFER_EXT GL_DEPTH_COMPONENT32 (reflection-dim) glRenderbufferStorageEXT
] keep ;
: (make-reflection-framebuffer) ( depthbuffer -- framebuffer )
gen-framebuffer dup [
swap >r
GL_FRAMEBUFFER_EXT GL_DEPTH_ATTACHMENT_EXT GL_RENDERBUFFER_EXT r>
glFramebufferRenderbufferEXT
] with-framebuffer ;
: (plane-program) ( -- program )
plane-vertex-shader plane-fragment-shader <simple-gl-program> ;
: (solid-sphere-program) ( -- program )
sphere-vertex-shader <vertex-shader> check-gl-shader
sphere-solid-color-fragment-shader <fragment-shader> check-gl-shader
sphere-main-fragment-shader <fragment-shader> check-gl-shader
3array <gl-program> check-gl-program ;
: (texture-sphere-program) ( -- program )
sphere-vertex-shader <vertex-shader> check-gl-shader
sphere-texture-fragment-shader <fragment-shader> check-gl-shader
sphere-main-fragment-shader <fragment-shader> check-gl-shader
3array <gl-program> check-gl-program ;
M: spheres-gadget graft* ( gadget -- )
(plane-program) >>plane-program
(solid-sphere-program) >>solid-sphere-program
(texture-sphere-program) >>texture-sphere-program
(make-reflection-texture) >>reflection-texture
(make-reflection-depthbuffer) [ >>reflection-depthbuffer ] keep
(make-reflection-framebuffer) >>reflection-framebuffer
drop ;
M: spheres-gadget ungraft* ( gadget -- )
{
[ reflection-framebuffer>> [ delete-framebuffer ] when* ]
[ reflection-depthbuffer>> [ delete-renderbuffer ] when* ]
[ reflection-texture>> [ delete-texture ] when* ]
[ solid-sphere-program>> [ delete-gl-program ] when* ]
[ texture-sphere-program>> [ delete-gl-program ] when* ]
[ plane-program>> [ delete-gl-program ] when* ]
} cleave ;
M: spheres-gadget pref-dim* ( gadget -- dim )
drop { 640 480 } ;
: (draw-sphere) ( program center radius surfacecolor -- )
roll
[ [ "center" glGetAttribLocation swap first3 glVertexAttrib3f ] curry ]
[ [ "radius" glGetAttribLocation swap glVertexAttrib1f ] curry ]
[ [ "surface_color" glGetAttribLocation swap first4 glVertexAttrib4f ] curry ]
tri tri*
{ -1.0 -1.0 } { 1.0 1.0 } rect-vertices ;
: sphere-scene ( gadget -- )
GL_DEPTH_BUFFER_BIT GL_COLOR_BUFFER_BIT bitor glClear
[
solid-sphere-program>> dup {
{ "light_position" [ 0.0 0.0 100.0 glUniform3f ] }
} [
{
[ { 7.0 0.0 0.0 } 1.0 { 1.0 0.0 0.0 1.0 } (draw-sphere) ]
[ { -7.0 0.0 0.0 } 1.0 { 0.0 1.0 0.0 1.0 } (draw-sphere) ]
[ { 0.0 0.0 7.0 } 1.0 { 0.0 0.0 1.0 1.0 } (draw-sphere) ]
[ { 0.0 0.0 -7.0 } 1.0 { 1.0 1.0 0.0 1.0 } (draw-sphere) ]
[ { 0.0 7.0 0.0 } 1.0 { 1.0 0.0 1.0 1.0 } (draw-sphere) ]
[ { 0.0 -7.0 0.0 } 1.0 { 0.0 1.0 1.0 1.0 } (draw-sphere) ]
} cleave
] with-gl-program
] [
plane-program>> { } [
GL_QUADS [
-1000.0 -30.0 1000.0 glVertex3f
-1000.0 -30.0 -1000.0 glVertex3f
1000.0 -30.0 -1000.0 glVertex3f
1000.0 -30.0 1000.0 glVertex3f
] do-state
] with-gl-program
] bi ;
: reflection-frustum ( gadget -- -x x -y y near far )
[ near-plane ] [ far-plane ] bi [
drop dup [ -+ ] bi@
] 2keep ;
: (reflection-face) ( gadget face -- )
swap reflection-texture>> >r >r
GL_FRAMEBUFFER_EXT
GL_COLOR_ATTACHMENT0_EXT
r> r> 0 glFramebufferTexture2DEXT
check-framebuffer ;
: (draw-reflection-texture) ( gadget -- )
dup reflection-framebuffer>> [ {
[ drop 0 0 (reflection-dim) glViewport ]
[
GL_PROJECTION glMatrixMode
glLoadIdentity
reflection-frustum glFrustum
GL_MODELVIEW glMatrixMode
glLoadIdentity
180.0 0.0 0.0 1.0 glRotatef
]
[ GL_TEXTURE_CUBE_MAP_NEGATIVE_Z (reflection-face) ]
[ sphere-scene ]
[ GL_TEXTURE_CUBE_MAP_POSITIVE_X (reflection-face)
90.0 0.0 1.0 0.0 glRotatef ]
[ sphere-scene ]
[ GL_TEXTURE_CUBE_MAP_POSITIVE_Z (reflection-face)
90.0 0.0 1.0 0.0 glRotatef glPushMatrix ]
[ sphere-scene ]
[ GL_TEXTURE_CUBE_MAP_NEGATIVE_X (reflection-face)
90.0 0.0 1.0 0.0 glRotatef ]
[ sphere-scene ]
[ GL_TEXTURE_CUBE_MAP_NEGATIVE_Y (reflection-face)
glPopMatrix glPushMatrix -90.0 1.0 0.0 0.0 glRotatef ]
[ sphere-scene ]
[ GL_TEXTURE_CUBE_MAP_POSITIVE_Y (reflection-face)
glPopMatrix 90.0 1.0 0.0 0.0 glRotatef ]
[ sphere-scene ]
[ dim>> 0 0 rot first2 glViewport ]
} cleave ] with-framebuffer ;
M: spheres-gadget draw-gadget* ( gadget -- )
GL_DEPTH_TEST glEnable
GL_SCISSOR_TEST glDisable
0.15 0.15 1.0 1.0 glClearColor {
[ (draw-reflection-texture) ]
[ demo-gadget-set-matrices ]
[ sphere-scene ]
[ reflection-texture>> GL_TEXTURE_CUBE_MAP GL_TEXTURE0 bind-texture-unit ]
[
texture-sphere-program>> dup {
{ "surface_texture" [ 0 glUniform1i ] }
} [
{ 0.0 0.0 0.0 } 4.0 { 1.0 0.0 0.0 1.0 } (draw-sphere)
] with-gl-program
]
} cleave ;
: spheres-window ( -- )
[ <spheres-gadget> "Spheres" open-window ] with-ui ;
MAIN: spheres-window

View File

@ -0,0 +1 @@
Draw pixel-perfect spheres using GLSL shaders

2
extra/spheres/tags.txt Normal file
View File

@ -0,0 +1,2 @@
opengl
glsl

View File

@ -4,7 +4,7 @@ IN: windows.com
HELP: com-query-interface
{ $values { "interface" "Pointer to a COM interface implementing " { $snippet "IUnknown" } } { "iid" "An interface GUID (IID)" } { "interface'" "Pointer to a COM interface implementing the interface indicated by " { $snippet "iid" } } }
{ $description "A small wrapper around " { $link IUnknown::QueryInterface } ". Queries " { $snippet "interface" } " to see if it implements the interface indicated by " { $snippet "iid" } ". Returns a pointer to the " { $snippet "iid" } " interface if implemented, or raises an error if the object does not implement the interface.\n\nCOM memory management conventions state that the returned pointer must be immediately retained using " { $link com-add-ref } ". The pointer must then be released using " { $link com-release } " when it is no longer needed." } ;
{ $description "A small wrapper around " { $link IUnknown::QueryInterface } ". Queries " { $snippet "interface" } " to see if it implements the interface indicated by " { $snippet "iid" } ". Returns a pointer to the " { $snippet "iid" } " interface if implemented, or raises an error if the object does not implement the interface.\n\nCOM memory management conventions state that the returned pointer must be released using " { $link com-release } " when it is no longer needed." } ;
HELP: com-add-ref
{ $values { "interface" "Pointer to a COM interface implementing " { $snippet "IUnknown" } } }

View File

@ -1,93 +1,91 @@
USING: kernel windows.com windows.com.syntax windows.ole32
alien alien.syntax tools.test libc alien.c-types arrays.lib
namespaces arrays continuations ;
IN: windows.com.tests
! Create some test COM interfaces
COM-INTERFACE: ISimple IUnknown {216fb341-0eb2-44b1-8edb-60b76e353abc}
HRESULT returnOK ( )
HRESULT returnError ( ) ;
COM-INTERFACE: IInherited ISimple {9620ecec-8438-423b-bb14-86f835aa40dd}
int getX ( )
void setX ( int newX ) ;
! Implement the IInherited interface in factor using alien-callbacks
C-STRUCT: test-implementation
{ "void*" "vtbl" }
{ "int" "x" } ;
: QueryInterface-callback
"HRESULT" { "void*" "REFGUID" "void**" } "stdcall" [ nip 0 swap set-void*-nth S_OK ]
alien-callback ;
: AddRef-callback
"ULONG" { "void*" } "stdcall" [ drop 2 ]
alien-callback ;
: Release-callback
"ULONG" { "void*" } "stdcall" [ drop 1 ]
alien-callback ;
: returnOK-callback
"HRESULT" { "void*" } "stdcall" [ drop S_OK ]
alien-callback ;
: returnError-callback
"HRESULT" { "void*" } "stdcall" [ drop E_FAIL ]
alien-callback ;
: getX-callback
"int" { "void*" } "stdcall" [ test-implementation-x ]
alien-callback ;
: setX-callback
"void" { "void*" "int" } "stdcall" [ swap set-test-implementation-x ]
alien-callback ;
SYMBOL: +test-implementation-vtbl+
SYMBOL: +guinea-pig-implementation+
: (make-test-implementation) ( x imp -- imp )
[ set-test-implementation-x ] keep
+test-implementation-vtbl+ get over set-test-implementation-vtbl ;
: <test-implementation> ( x -- imp )
"test-implementation" <c-object> (make-test-implementation) ;
: <malloced-test-implementation> ( x -- imp )
"test-implementation" heap-size malloc (make-test-implementation) ;
QueryInterface-callback
AddRef-callback
Release-callback
returnOK-callback
returnError-callback
getX-callback
setX-callback
7 narray >c-void*-array
dup byte-length [
[ byte-array>memory ] keep
+test-implementation-vtbl+ set
! Test that the words defined by COM-INTERFACE: do their magic
"{216fb341-0eb2-44b1-8edb-60b76e353abc}" string>guid 1array [ ISimple-iid ] unit-test
"{9620ecec-8438-423b-bb14-86f835aa40dd}" string>guid 1array [ IInherited-iid ] unit-test
"{00000000-0000-0000-C000-000000000046}" string>guid 1array [ IUnknown-iid ] unit-test
S_OK 1array [ 0 <test-implementation> ISimple::returnOK ] unit-test
E_FAIL <long> *long 1array [ 0 <test-implementation> ISimple::returnError ] unit-test
1984 1array [ 0 <test-implementation> dup 1984 IInherited::setX IInherited::getX ] unit-test
! Test that the helper functions for QueryInterface, AddRef, Release work
0 <malloced-test-implementation> +guinea-pig-implementation+ set
[
+guinea-pig-implementation+ get 1array [
+guinea-pig-implementation+ get com-add-ref
] unit-test
{ } [ +guinea-pig-implementation+ get com-release ] unit-test
+guinea-pig-implementation+ get 1array [
+guinea-pig-implementation+ get IUnknown-iid com-query-interface
] unit-test
] [ +guinea-pig-implementation+ get free ] [ ] cleanup
] with-malloc
USING: kernel windows.com windows.com.syntax windows.ole32
alien alien.syntax tools.test libc alien.c-types arrays.lib
namespaces arrays continuations accessors math windows.com.wrapper
windows.com.wrapper.private ;
IN: windows.com.tests
COM-INTERFACE: ISimple IUnknown {216fb341-0eb2-44b1-8edb-60b76e353abc}
HRESULT returnOK ( )
HRESULT returnError ( ) ;
COM-INTERFACE: IInherited ISimple {9620ecec-8438-423b-bb14-86f835aa40dd}
int getX ( )
void setX ( int newX ) ;
COM-INTERFACE: IUnrelated IUnknown {b06ac3f4-30e4-406b-a7cd-c29cead4552c}
int xPlus ( int y )
int xMulAdd ( int mul, int add ) ;
"{216fb341-0eb2-44b1-8edb-60b76e353abc}" string>guid 1array [ ISimple-iid ] unit-test
"{9620ecec-8438-423b-bb14-86f835aa40dd}" string>guid 1array [ IInherited-iid ] unit-test
"{00000000-0000-0000-C000-000000000046}" string>guid 1array [ IUnknown-iid ] unit-test
"{b06ac3f4-30e4-406b-a7cd-c29cead4552c}" string>guid 1array [ IUnrelated-iid ] unit-test
SYMBOL: +test-wrapper+
SYMBOL: +guinea-pig-implementation+
SYMBOL: +orig-wrapped-objects+
+wrapped-objects+ get-global clone +orig-wrapped-objects+ set-global
TUPLE: test-implementation x ;
C: <test-implementation> test-implementation
{
{ "IInherited" {
[ drop S_OK ] ! ISimple::returnOK
[ drop E_FAIL ] ! ISimple::returnError
[ x>> ] ! IInherited::getX
[ >>x drop ] ! IInherited::setX
} }
{ "IUnrelated" {
[ swap x>> + ] ! IUnrelated::xPlus
[ spin x>> * + ] ! IUnrealted::xMulAdd
} }
} <com-wrapper>
dup +test-wrapper+ set [
0 <test-implementation> swap com-wrap
dup +guinea-pig-implementation+ set [ drop
S_OK 1array [ +guinea-pig-implementation+ get ISimple::returnOK ] unit-test
E_FAIL <long> *long 1array [ +guinea-pig-implementation+ get ISimple::returnError ] unit-test
20 1array [ +guinea-pig-implementation+ get dup 20 IInherited::setX IInherited::getX ] unit-test
420 1array [
+guinea-pig-implementation+ get
IUnrelated-iid com-query-interface
[ 20 20 IUnrelated::xMulAdd ] with-com-interface
] unit-test
40 1array [
+guinea-pig-implementation+ get
IUnrelated-iid com-query-interface
[ 20 IUnrelated::xPlus ] with-com-interface
] unit-test
+guinea-pig-implementation+ get 1array [
+guinea-pig-implementation+ get com-add-ref
] unit-test
{ } [ +guinea-pig-implementation+ get com-release ] unit-test
+guinea-pig-implementation+ get 1array [
+guinea-pig-implementation+ get IUnknown-iid com-query-interface
dup com-release
] unit-test
+guinea-pig-implementation+ get 1array [
+guinea-pig-implementation+ get ISimple-iid com-query-interface
dup com-release
] unit-test
"void*" heap-size +guinea-pig-implementation+ get <displaced-alien>
+guinea-pig-implementation+ get
2array [
+guinea-pig-implementation+ get IUnrelated-iid com-query-interface
dup ISimple-iid com-query-interface
over com-release dup com-release
] unit-test
] with-com-interface
] with-disposal
! Ensure that we freed +guinea-pig-implementation
+orig-wrapped-objects+ get-global 1array [ +wrapped-objects+ get-global ] unit-test

View File

@ -1,12 +1,31 @@
USING: alien alien.c-types windows.com.syntax windows.ole32
windows.types continuations kernel ;
windows.types continuations kernel alien.syntax ;
IN: windows.com
LIBRARY: ole32
COM-INTERFACE: IUnknown f {00000000-0000-0000-C000-000000000046}
HRESULT QueryInterface ( REFGUID iid, void** ppvObject )
ULONG AddRef ( )
ULONG Release ( ) ;
COM-INTERFACE: IDataObject IUnknown {0000010E-0000-0000-C000-000000000046}
HRESULT GetData ( FORMATETC* pFormatetc, STGMEDIUM* pmedium )
HRESULT GetDataHere ( FORMATETC* pFormatetc, STGMEDIUM* pmedium )
HRESULT QueryGetData ( FORMATETC* pFormatetc )
HRESULT GetCanonicalFormatEtc ( FORMATETC* pFormatetcIn, FORMATETC* pFormatetcOut )
HRESULT SetData ( FORMATETC* pFormatetc, STGMEDIUM* pmedium, BOOL fRelease )
HRESULT EnumFormatEtc ( DWORD dwDirection, IEnumFORMATETC** ppenumFormatetc )
HRESULT DAdvise ( FORMATETC* pFormatetc, DWORD advf, IAdviseSink* pAdvSink, DWORD* pdwConnection )
HRESULT DUnadvise ( DWORD pdwConnection )
HRESULT EnumDAdvise ( IEnumSTATDATA** ppenumAdvise ) ;
COM-INTERFACE: IDropTarget IUnknown {00000122-0000-0000-C000-000000000046}
HRESULT DragEnter ( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
HRESULT DragOver ( DWORD grfKeyState, POINTL pt, DWORD* pdwEffect )
HRESULT DragLeave ( )
HRESULT Drop ( IDataObject* pDataObject, DWORD grfKeyState, POINTL pt, DWORD* pdwEffect ) ;
: com-query-interface ( interface iid -- interface' )
f <void*>
[ IUnknown::QueryInterface ole32-error ] keep
@ -19,4 +38,4 @@ COM-INTERFACE: IUnknown f {00000000-0000-0000-C000-000000000046}
IUnknown::Release drop ; inline
: with-com-interface ( interface quot -- )
[ keep ] [ com-release ] [ ] cleanup ; inline
over [ slip ] [ com-release ] [ ] cleanup ; inline

View File

@ -55,8 +55,12 @@ unless
: (function-word) ( function interface -- word )
name>> "::" rot name>> 3append create-in ;
: all-functions ( definition -- functions )
dup parent>> [ all-functions ] [ { } ] if*
: family-tree ( definition -- definitions )
dup parent>> [ family-tree ] [ { } ] if*
swap add ;
: family-tree-functions ( definition -- functions )
dup parent>> [ family-tree-functions ] [ { } ] if*
swap functions>> append ;
: (define-word-for-function) ( function interface n -- )
@ -69,7 +73,7 @@ unless
[ [ (iid-word) ] [ iid>> 1quotation ] bi define ]
[ name>> "com-interface" swap typedef ]
[
dup all-functions
dup family-tree-functions
[ (define-word-for-function) ] with each-index
]
tri ;

View File

@ -0,0 +1 @@
Joe Groff

View File

@ -0,0 +1 @@
Wrap Factor objects with implementations of COM interfaces

View File

@ -0,0 +1,3 @@
windows
com
bindings

View File

@ -0,0 +1,40 @@
USING: help.markup help.syntax io kernel math quotations
multiline alien windows.com windows.com.syntax continuations ;
IN: windows.com.wrapper
HELP: <com-wrapper>
{ $values { "implementations" "an assoc relating COM interface names to arrays of quotations implementing that interface" } { "wrapper" "a " { $link com-wrapper } " tuple" } }
{ $description "Constructs a " { $link com-wrapper } " tuple. Each key in the " { $snippet "implementations" } " assoc must be the name of an interface defined with " { $link POSTPONE: COM-INTERFACE: } ". The corresponding value must be an array of quotations implementing the methods of that interface in order, including those of its parent interfaces. The " { $snippet "IUnknown" } " methods (" { $link IUnknown::QueryInterface } ", " { $link IUnknown::AddRef } ", and " { $link IUnknown::Release } ") will be defined automatically and must not be specified in the array. These quotations should have stack effects mirroring those of the interface methods being implemented; for example, a method " { $snippet "void foobar ( int foo, int bar )" } " should be implemented with a quotation of effect " { $snippet "( this foo bar -- )" } ". The " { $snippet "this" } " parameter (that is, the leftmost parameter of any COM method) will be automatically converted from an alien pointer to the underlying Factor object before the quotation is invoked.\n\nThe resulting wrapper can be applied to a Factor object using the " { $link com-wrap } " word. The COM interface pointer returned by " { $snippet "com-wrap" } " can then be passed to C functions requiring a COM object as a parameter. The vtables constructed by " { $snippet "<com-wrapper>" } " are stored on the non-GC heap in order to be accessible to C functions; when the wrapper objects and its vtables are no longer needed, the object's resources must be freed using " { $link dispose } ".\n\nExample:" }
{ $code <"
COM-INTERFACE: ISimple IUnknown {216fb341-0eb2-44b1-8edb-60b76e353abc}
HRESULT returnOK ( )
HRESULT returnError ( ) ;
COM-INTERFACE: IInherited ISimple {9620ecec-8438-423b-bb14-86f835aa40dd}
int getX ( )
void setX ( int newX ) ;
COM-INTERFACE: IUnrelated IUnknown {b06ac3f4-30e4-406b-a7cd-c29cead4552c}
int xPlus ( int y )
int xMulAdd ( int mul, int add ) ;
{
{ "IInherited" {
[ drop S_OK ] ! ISimple::returnOK
[ drop E_FAIL ] ! ISimple::returnError
[ x>> ] ! IInherited::getX
[ >>x drop ] ! IInherited::setX
} }
{ "IUnrelated" {
[ swap x>> + ] ! IUnrelated::xPlus
[ spin x>> * + ] ! IUnrealted::xMulAdd
} }
} <com-wrapper>
"> } ;
HELP: com-wrap
{ $values { "object" "The factor object to wrap" } { "wrapper" "A " { $link com-wrapper } " object" } { "wrapped-object" "A COM object referencing " { $snippet "object" } } }
{ $description "Allocates a COM object using the implementations in the " { $snippet "wrapper" } " object for the vtables and " { $snippet "object" } " for the \"this\" parameter. The COM object is allocated on the heap with an initial reference count of 1. The object will automatically deallocate itself when its reference count reaches 0 as a result of calling " { $link IUnknown::Release } " or " { $link com-release } " on it.\n\nNote that if " { $snippet "wrapper" } " implements multiple interfaces, you cannot count on the returned COM object pointer implementing any particular interface beyond " { $snippet "IUnknown" } ". You will need to use " { $link com-query-interface } " or " { $link IUnknown::QueryInterface } " to ask the object for the particular interface you need." } ;
HELP: com-wrapper
{ $class-description "The tuple class used to store COM wrapper information. Objects of this class should be treated as opaque by user code. A com-wrapper can be constructed using the " { $link <com-wrapper> } " constructor and applied to a Factor object using " { $link com-wrap } "." } ;

View File

@ -0,0 +1,111 @@
USING: alien alien.c-types windows.com.syntax
windows.com.syntax.private windows.com continuations kernel
sequences.lib namespaces windows.ole32 libc
assocs accessors arrays sequences quotations combinators
math combinators.lib words compiler.units ;
IN: windows.com.wrapper
TUPLE: com-wrapper vtbls freed? ;
<PRIVATE
SYMBOL: +wrapped-objects+
+wrapped-objects+ get-global
[ H{ } +wrapped-objects+ set-global ]
unless
: com-unwrap ( wrapped -- object )
+wrapped-objects+ get-global at*
[ "invalid COM wrapping pointer" throw ] unless ;
: (free-wrapped-object) ( wrapped -- )
[ +wrapped-objects+ get-global delete-at ] keep
free ;
: (make-query-interface) ( interfaces -- quot )
[
[ swap 16 memory>byte-array ] %
[
>r find-com-interface-definition family-tree
r> 1quotation [ >r iid>> r> 2array ] curry map
] map-index concat
[ f ] add ,
\ case ,
"void*" heap-size
[ * rot <displaced-alien> com-add-ref 0 rot set-void*-nth S_OK ]
curry ,
[ nip f 0 rot set-void*-nth E_NOINTERFACE ] ,
\ if* ,
] [ ] make ;
: (make-add-ref) ( interfaces -- quot )
length "void*" heap-size * [ swap <displaced-alien>
0 over ulong-nth
1+ [ 0 rot set-ulong-nth ] keep
] curry ;
: (make-release) ( interfaces -- quot )
length "void*" heap-size * [ over <displaced-alien>
0 over ulong-nth
1- [ 0 rot set-ulong-nth ] keep
dup zero? [ swap (free-wrapped-object) ] [ nip ] if
] curry ;
: (make-iunknown-methods) ( interfaces -- quots )
[ (make-query-interface) ]
[ (make-add-ref) ]
[ (make-release) ] tri
3array ;
: (thunk) ( n -- quot )
dup 0 =
[ drop [ ] ]
[ "void*" heap-size neg * [ swap <displaced-alien> ] curry ]
if ;
: (thunked-quots) ( quots iunknown-methods thunk -- quots' )
[ [ swap 2array ] curry map swap ] keep
[ com-unwrap ] compose [ swap 2array ] curry map append ;
: compile-alien-callback ( return parameters abi quot -- alien )
[ alien-callback ] 4 ncurry
[ gensym [ swap define ] keep ] with-compilation-unit
execute ;
: (make-vtbl) ( interface-name quots iunknown-methods n -- )
(thunk) (thunked-quots)
swap find-com-interface-definition family-tree-functions [
{ return>> parameters>> } get-slots
dup length 1- roll [
first dup empty?
[ 2drop [ ] ]
[ swap [ ndip ] 2curry ]
if
] [ second ] bi compose
"stdcall" swap compile-alien-callback
] 2map >c-void*-array [ byte-length malloc ] keep
over byte-array>memory ;
: (make-vtbls) ( implementations -- vtbls )
dup [ first ] map (make-iunknown-methods)
[ >r >r first2 r> r> swap (make-vtbl) ] curry map-index ;
: (malloc-wrapped-object) ( wrapper -- wrapped-object )
vtbls>> length "void*" heap-size *
[ "ulong" heap-size + malloc ] keep
over <displaced-alien>
1 0 rot set-ulong-nth ;
PRIVATE>
: <com-wrapper> ( implementations -- wrapper )
(make-vtbls) f com-wrapper construct-boa ;
M: com-wrapper dispose
t >>freed?
vtbls>> [ free ] each ;
: com-wrap ( object wrapper -- wrapped-object )
dup (malloc-wrapped-object) >r vtbls>> r>
[ [ set-void*-nth ] curry each-index ] keep
[ +wrapped-objects+ get-global set-at ] keep ;

View File

@ -0,0 +1,68 @@
USING: windows.com windows.com.wrapper combinators
windows.kernel32 windows.ole32 windows.shell32 kernel accessors
prettyprint namespaces ui.tools.listener ui.tools.workspace
alien.c-types alien sequences math ;
IN: windows.dragdrop-listener
: filenames-from-hdrop ( hdrop -- filenames )
dup HEX: FFFFFFFF f 0 DragQueryFile ! get count of files
[
2dup f 0 DragQueryFile 1+ ! get size of filename buffer
dup "WCHAR" <c-array>
[ swap DragQueryFile drop ] keep
alien>u16-string
] with map ;
: filenames-from-data-object ( data-object -- filenames )
"FORMATETC" <c-object>
CF_HDROP over set-FORMATETC-cfFormat
f over set-FORMATETC-ptd
DVASPECT_CONTENT over set-FORMATETC-dwAspect
-1 over set-FORMATETC-lindex
TYMED_HGLOBAL over set-FORMATETC-tymed
"STGMEDIUM" <c-object>
[ IDataObject::GetData ] keep swap succeeded? [
dup STGMEDIUM-data
[ filenames-from-hdrop ] with-global-lock
swap ReleaseStgMedium
] [ drop f ] if ;
TUPLE: listener-dragdrop hWnd last-drop-effect ;
: <listener-dragdrop> ( hWnd -- object )
DROPEFFECT_NONE listener-dragdrop construct-boa ;
SYMBOL: +listener-dragdrop-wrapper+
{
{ "IDropTarget" {
[ ! DragEnter
>r 2drop
filenames-from-data-object
length 1 = [ DROPEFFECT_COPY ] [ DROPEFFECT_NONE ] if
dup 0 r> set-ulong-nth
>>last-drop-effect drop
S_OK
] [ ! DragOver
>r 2drop last-drop-effect>> 0 r> set-ulong-nth
S_OK
] [ ! DragLeave
drop S_OK
] [ ! Drop
>r 2drop nip
filenames-from-data-object
dup length 1 = [
first unparse [ "USE: parser " % % " run-file" % ] "" make
eval-listener
DROPEFFECT_COPY
] [ 2drop DROPEFFECT_NONE ] if
0 r> set-ulong-nth
S_OK
]
} }
} <com-wrapper> +listener-dragdrop-wrapper+ set-global
: dragdrop-listener-window ( -- )
get-workspace parent>> handle>> hWnd>>
dup <listener-dragdrop>
+listener-dragdrop-wrapper+ get-global com-wrap
[ RegisterDragDrop ole32-error ] with-com-interface ;

View File

@ -1,6 +1,6 @@
! Copyright (C) 2005, 2006 Doug Coleman.
! See http://factorcode.org/license.txt for BSD license.
USING: alien alien.syntax windows.types ;
USING: alien alien.syntax kernel windows.types ;
IN: windows.kernel32
: MAX_PATH 260 ; inline
@ -1573,3 +1573,6 @@ FUNCTION: BOOL WriteProcessMemory ( HANDLE hProcess, void* lpBaseAddress, void*
! FUNCTION: WriteTapemark
! FUNCTION: WTSGetActiveConsoleSessionId
! FUNCTION: ZombifyActCtx
: with-global-lock ( HGLOBAL quot -- )
swap [ GlobalLock swap call ] keep GlobalUnlock drop ; inline

View File

@ -4,13 +4,7 @@ IN: windows.ole32
LIBRARY: ole32
C-STRUCT: GUID
{ "DWORD" "part1" }
{ "DWORD" "part2" }
{ "DWORD" "part3" }
{ "DWORD" "part4" } ;
TYPEDEF: void* REFGUID
TYPEDEF: GUID* REFGUID
TYPEDEF: void* LPUNKNOWN
TYPEDEF: wchar_t* LPOLESTR
TYPEDEF: wchar_t* LPCOLESTR
@ -25,6 +19,7 @@ FUNCTION: HRESULT CLSIDFromString ( LPOLESTR lpsz, REFGUID out_rguid ) ;
: S_OK 0 ; inline
: S_FALSE 1 ; inline
: E_NOINTERFACE HEX: 80004002 ; inline
: E_FAIL HEX: 80004005 ; inline
: E_INVALIDARG HEX: 80070057 ; inline
@ -40,11 +35,92 @@ FUNCTION: HRESULT CLSIDFromString ( LPOLESTR lpsz, REFGUID out_rguid ) ;
: DD_DEFDRAGDELAY 200 ; inline
: DD_DEFDRAGMINDIST 2 ; inline
: ole32-error ( n -- )
dup S_OK = [
: CF_TEXT 1 ; inline
: CF_BITMAP 2 ; inline
: CF_METAFILEPICT 3 ; inline
: CF_SYLK 4 ; inline
: CF_DIF 5 ; inline
: CF_TIFF 6 ; inline
: CF_OEMTEXT 7 ; inline
: CF_DIB 8 ; inline
: CF_PALETTE 9 ; inline
: CF_PENDATA 10 ; inline
: CF_RIFF 11 ; inline
: CF_WAVE 12 ; inline
: CF_UNICODETEXT 13 ; inline
: CF_ENHMETAFILE 14 ; inline
: CF_HDROP 15 ; inline
: CF_LOCALE 16 ; inline
: CF_MAX 17 ; inline
: CF_OWNERDISPLAY HEX: 0080 ; inline
: CF_DSPTEXT HEX: 0081 ; inline
: CF_DSPBITMAP HEX: 0082 ; inline
: CF_DSPMETAFILEPICT HEX: 0083 ; inline
: CF_DSPENHMETAFILE HEX: 008E ; inline
: DVASPECT_CONTENT 1 ; inline
: DVASPECT_THUMBNAIL 2 ; inline
: DVASPECT_ICON 4 ; inline
: DVASPECT_DOCPRINT 8 ; inline
: TYMED_HGLOBAL 1 ; inline
: TYMED_FILE 2 ; inline
: TYMED_ISTREAM 4 ; inline
: TYMED_ISTORAGE 8 ; inline
: TYMED_GDI 16 ; inline
: TYMED_MFPICT 32 ; inline
: TYMED_ENHMF 64 ; inline
: TYMED_NULL 0 ; inline
C-STRUCT: DVTARGETDEVICE
{ "DWORD" "tdSize" }
{ "WORD" "tdDriverNameOffset" }
{ "WORD" "tdDeviceNameOffset" }
{ "WORD" "tdPortNameOffset" }
{ "WORD" "tdExtDevmodeOffset" }
{ "BYTE[1]" "tdData" } ;
TYPEDEF: WORD CLIPFORMAT
TYPEDEF: POINT POINTL
C-STRUCT: FORMATETC
{ "CLIPFORMAT" "cfFormat" }
{ "DVTARGETDEVICE*" "ptd" }
{ "DWORD" "dwAspect" }
{ "LONG" "lindex" }
{ "DWORD" "tymed" } ;
TYPEDEF: FORMATETC* LPFORMATETC
C-STRUCT: STGMEDIUM
{ "DWORD" "tymed" }
{ "void*" "data" }
{ "LPUNKNOWN" "punkForRelease" } ;
TYPEDEF: STGMEDIUM* LPSTGMEDIUM
: COINIT_MULTITHREADED 0 ; inline
: COINIT_APARTMENTTHREADED 2 ; inline
: COINIT_DISABLE_OLE1DDE 4 ; inline
: COINIT_SPEED_OVER_MEMORY 8 ; inline
FUNCTION: HRESULT OleInitialize ( void* reserved ) ;
FUNCTION: HRESULT CoInitializeEx ( void* reserved, DWORD dwCoInit ) ;
FUNCTION: HRESULT RegisterDragDrop ( HWND hWnd, IDropTarget* pDropTarget ) ;
FUNCTION: HRESULT RevokeDragDrop ( HWND hWnd ) ;
FUNCTION: void ReleaseStgMedium ( LPSTGMEDIUM pmedium ) ;
: succeeded? ( hresult -- ? )
0 HEX: 7FFFFFFF between? ;
: ole32-error ( hresult -- )
dup succeeded? [
drop
] [ (win32-error-string) throw ] if ;
: ole-initialize ( -- )
f OleInitialize ole32-error ;
: guid= ( a b -- ? )
IsEqualGUID c-bool> ;

View File

@ -167,6 +167,15 @@ TYPEDEF: DWORD SHGDNF
TYPEDEF: ULONG SFGAOF
C-STRUCT: DROPFILES
{ "DWORD" "pFiles" }
{ "POINT" "pt" }
{ "BOOL" "fNC" }
{ "BOOL" "fWide" } ;
TYPEDEF: DROPFILES* LPDROPFILES
TYPEDEF: DROPFILES* LPCDROPFILES
TYPEDEF: HANDLE HDROP
C-STRUCT: SHITEMID
{ "USHORT" "cb" }
{ "BYTE[1]" "abID" } ;
@ -210,5 +219,6 @@ COM-INTERFACE: IShellFolder IUnknown {000214E6-0000-0000-C000-000000000046}
FUNCTION: HRESULT SHGetDesktopFolder ( IShellFolder** ppshf ) ;
FUNCTION: HRESULT StrRetToBufW ( STRRET *pstr, PCUITEMID_CHILD pidl, LPWSTR pszBuf, UINT cchBuf ) ;
: StrRetToBuf StrRetToBufW ; inline
FUNCTION: UINT DragQueryFileW ( HDROP hDrop, UINT iFile, LPWSTR lpszFile, UINT cch ) ;
: DragQueryFile DragQueryFileW ; inline

0
extra/windows/time/time.factor Executable file → Normal file
View File