Vala プログラミング

WebGPU プログラミング

おなが@京都先端科学大

Genie + OpenGL(Gtk.GLArea)2

f:id:onagat12:20151114174806p:plain

gtk3-demoにあるGLAreaデモをGenie言語で書き直しました。

(単独のプログラムは、gtk+-3.16ソース内のtestsにあります。testglarea.c

testglarea.gs(前回のプログラム)と同じglepoxy.vapiを使っています。

 

##glarea.gs

uses

    Gtk

    GL

 

init

    Gtk.init (ref args)

    var mainWindow = new MainWindow()

    mainWindow.show_all ()

    Gtk.main ()

 

class MainWindow : Window

    glarea : GLArea

    scale_x : Scale

    scale_y : Scale

    scale_z : Scale

    phi : float

    theta : float

    psi : float

 

    gl_vao : GLuint = 0

    gl_program : GLuint

    mvp_location : GLint

 

    init

        title = "GLArea Test"

        border_width = 12;

        destroy.connect (Gtk.main_quit)

 

        var box = new Box (Orientation.VERTICAL, 0)

        box.spacing = 6;

 

        glarea = new GLArea ()

        glarea.set_size_request (400, 400)

        glarea.render.connect (on_glarea_render)

 

        var controls = new Box (Orientation.VERTICAL, 0)

        var slider_x = new Box (Orientation.HORIZONTAL, 0)

        var slider_y = new Box (Orientation.HORIZONTAL, 0)

        var slider_z = new Box (Orientation.HORIZONTAL, 0)

 

        var label_x = new Label ("X axis ")

        var label_y = new Label ("Y axis ")

        var label_z = new Label ("Z axis ")

        scale_x = new Scale.with_range (Orientation.HORIZONTAL, 0, 360, 2)

        scale_y = new Scale.with_range (Orientation.HORIZONTAL, 0, 360, 2)

        scale_z = new Scale.with_range (Orientation.HORIZONTAL, 0, 360, 2)

        scale_x.value_changed.connect (on_value_changed)

        scale_y.value_changed.connect (on_value_changed)

        scale_z.value_changed.connect (on_value_changed)

 

        slider_x.pack_start (label_x, false, false, 0)

        slider_x.pack_start (scale_x)

        slider_y.pack_start (label_y, false, false, 0)

        slider_y.pack_start (scale_y)

        slider_z.pack_start (label_z, false, false, 0)

        slider_z.pack_start (scale_z)

 

        controls.pack_start (slider_x, false, false, 0)

        controls.pack_start (slider_y, false, false, 0)

        controls.pack_start (slider_z, false, false, 0)

 

        var button = new Button.with_label ("Quit")

        button.clicked.connect (Gtk.main_quit)

 

        box.pack_start (glarea, true, true)

        box.pack_start (controls, false, false)

        box.pack_start (button, false, false)

        add (box)

 

    def on_value_changed ()

        print("value-changed")

        phi = (float)scale_x.get_value ()

        theta = (float)scale_y.get_value ()

        psi = (float)scale_z.get_value ()

        print("phi: %f", phi)

        print("theta: %f", theta)

        print("psi: %f", psi)

 

        glarea.queue_render ()

 

    def on_realize (cntxt:Gdk.GLContext)

        print ("realize")

 

        gl_buffer : GLuint = 0

 

        vert_src : GLchar* = "#version 330\n \n in vec4 position;\n uniform mat4 mvp;\n void main() {\n gl_Position = mvp * position;\n }";

 

        frag_src : GLchar* = "#version 330\n \n out vec4 outputColor;\n void main() {\n outputColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n }";

 

        /// realize

        verts : array of float = { +0.0f, +1.0f, -1.0f, -1.0f, +1.0f, -1.0f}

 

        vert_shader : GLuint

        frag_shader : GLuint

        compileSuccess : GLint = 0

 

        vert_shader = glCreateShader (GL_VERTEX_SHADER);

        frag_shader = glCreateShader (GL_FRAGMENT_SHADER);

 

        glShaderSource(vert_shader, 1, &vert_src, null);

        glCompileShader(vert_shader);

        glGetShaderiv (vert_shader, GL_COMPILE_STATUS, out compileSuccess);

        if compileSuccess == GL_FALSE do print ("vert-shader Error")

 

        glShaderSource(frag_shader, 1, &frag_src, null);

        glCompileShader(frag_shader);

        glGetShaderiv (frag_shader, GL_COMPILE_STATUS, out compileSuccess);

        if compileSuccess == GL_FALSE do print ("frag-shader Error")

 

        gl_program = glCreateProgram();

        glAttachShader(gl_program, vert_shader);

        glAttachShader(gl_program, frag_shader);

        glLinkProgram(gl_program);

 

        mvp_location = glGetUniformLocation (gl_program, "mvp");

 

        glGenVertexArrays(1, out gl_vao);

        glBindVertexArray(gl_vao);

 

        glGenBuffers(1, out gl_buffer);

        glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);

        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*verts.length, verts, GL_STATIC_DRAW);

 

        glEnableVertexAttribArray(0);

        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

        glBindVertexArray(0);

 

        glDeleteBuffers(1, out gl_buffer);

 

    def on_glarea_render (cntxt:Gdk.GLContext): bool

        print ("render")

        on_realize (cntxt)

        /// render

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

 

        var mvp = new array of float[16]

        compute_mvp (out mvp, phi, theta, psi)

 

        glUseProgram(gl_program);

        glUniformMatrix4fv (mvp_location, 1, GL_FALSE, &mvp[0]);

        glBindVertexArray(gl_vao);

        glDrawArrays(GL_TRIANGLES, 0, 3);

 

        glBindVertexArray (0);

        glUseProgram (0);

 

        glFlush();

 

        return true

 

    def compute_mvp (out res:array of float, phi:float, theta:float, psi:float)

        print "compute mvp"

 

        res = new array of float[16]

        x : float = phi * ((float)Math.PI / 180.0f)

        y : float = theta * ((float)Math.PI / 180.0f)

        z : float = psi * ((float)Math.PI / 180.0f)

        print "x: %f", x

        print "y: %f", y

        print "z: %f", z

        c1:float = Math.cosf(x); s1:float = Math.sinf(x);

        c2:float = Math.cosf(y); s2:float = Math.sinf(y);

        c3:float = Math.cosf(z); s3:float = Math.sinf(z);

        var c3c2 = c3 * c2

        var s3c1 = s3 * c1

        var c3s2s1 = c3 * s2 * s1

        var s3s1 = s3 * s1

        var c3s2c1 = c3 * s2 * c1

        var s3c2 = s3 * c2

        var c3c1 = c3 * c1

        var s3s2s1 = s3 * s2 * s1

        var c3s1 = c3 * s1

        var s3s2c1 = s3 * s2 * c1

        var c2s1 = c2 * s1

        var c2c1 = c2 * c1

 

        res[0] = 1.0f; res[4] = 0.0f; res[8] = 0.0f; res[12] = 0.0f;

        res[1] = 0.0f; res[5] = 1.0f; res[9] = 0.0f; res[13] = 0.0f;

        res[2] = 0.0f; res[6] = 0.0f; res[10] = 1.0f; res[14] = 0.0f;

        res[3] = 0.0f; res[7] = 0.0f; res[11] = 0.0f; res[15] = 1.0f;

 

        res[0] = c3c2;  res[4] = s3c1 + c3s2s1; res[8] = s3s1 - c3s2c1; res[12] = 0.0f;

        res[1] = -s3c2; res[5] = c3c1 - s3s2s1; res[9] = c3s1 + s3s2c1; res[13] = 0.0f;

        res[2] = s2;      res[6] = -c2s1;              res[10] = c2c1;              res[14] = 0.0f;

        res[3] = 0.0f;   res[7] = 0.0f;                  res[11] = 0.0f;               res[15] = 1.0f;

 

 

ビルド

valac --vapidir=vapi --pkg gtk+-3.0 --pkg glepoxy -X -lepoxy -X -lm glarea.gs

Glibの数学ライブラリを使用しているので、 “-X -lm”のオプションを入れています。

Genie + OpenGL(Gtk.GLArea)

f:id:onagat12:20151114135737p:plain

gtk+-3.16から、Gtk.GLArea ウィジェが追加され、GtkWindow内で簡単にOpenGLプログラミングが出来るようになりました。OpenGL context等が自動的に設定されます。

OpenGLライブラリとして、epoxyライブラリを使用しています。

 

Gtk.GLArea ウィジェ とOpenGLを使って、三角形を描画しています。

Genie言語で記述しています。

 

vapigles2.vapiを参考に、epoxyライブラリで使用できるように追加・修正をしています。

glepoxy.vapi

glShaderSource()関数で、シェーダーファイルの指定が上手く処理できていません。

ポインターを使って記述しています。(ワーニングが出ます。)

 

##testglarea.gs

uses

    Gtk

    GL

 

init

    Gtk.init (ref args)

    var mainWindow = new MainWindow()

    mainWindow.show_all ()

    Gtk.main ()

 

class MainWindow : Window

    gl_vao : GLuint = 0

    gl_program : GLuint

 

    init

        title = "GLArea Test"

        destroy.connect (Gtk.main_quit)

 

        var box = new Box (Orientation.VERTICAL, 0)

 

        var glarea = new GLArea ()

        glarea.set_size_request (500, 400)

        glarea.render.connect (on_glarea_render)

 

        var button = new Button.with_label ("Quit")

        button.clicked.connect (Gtk.main_quit)

 

        box.pack_start (glarea, true, true)

        box.pack_start (button, false, false)

        add (box)

 

   def on_realize (cntxt:Gdk.GLContext)

        print ("realize")

 

        gl_buffer : GLuint = 0

 

        vert_src : GLchar* = "#version 330\n \n in vec4 position;\n void main() {\n gl_Position = position;\n }";

 

        frag_src : GLchar* = "#version 330\n \n out vec4 outputColor;\n void main() {\n outputColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n }";

 

        /// realize

        verts : array of float = { +0.0f, +1.0f, -1.0f, -1.0f, +1.0f, -1.0f}

 

        vert_shader : GLuint

        frag_shader : GLuint

        compileSuccess : GLint = 0

 

        vert_shader = glCreateShader (GL_VERTEX_SHADER);

        frag_shader = glCreateShader (GL_FRAGMENT_SHADER);

 

        glShaderSource(vert_shader, 1, &vert_src, null);

        glCompileShader(vert_shader);

        glGetShaderiv (vert_shader, GL_COMPILE_STATUS, out compileSuccess);

        if compileSuccess == GL_FALSE do print ("vert-shader Error")

 

        glShaderSource(frag_shader, 1, &frag_src, null);

        glCompileShader(frag_shader);

        glGetShaderiv (frag_shader, GL_COMPILE_STATUS, out compileSuccess);

        if compileSuccess == GL_FALSE do print ("frag-shader Error")

 

        gl_program = glCreateProgram();

        glAttachShader(gl_program, vert_shader);

        glAttachShader(gl_program, frag_shader);

        glLinkProgram(gl_program);

 

        glGenVertexArrays(1, out gl_vao);

        glBindVertexArray(gl_vao);

 

        glGenBuffers(1, out gl_buffer);

        glBindBuffer(GL_ARRAY_BUFFER, gl_buffer);

        glBufferData(GL_ARRAY_BUFFER, sizeof(float)*verts.length, verts, GL_STATIC_DRAW);

 

        glEnableVertexAttribArray(0);

        glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, (void*)0);

        glBindVertexArray(0);

 

        glDeleteBuffers(1, out gl_buffer);

 

   def on_glarea_render (cntxt:Gdk.GLContext): bool

        print ("render")

        on_realize (cntxt)

        /// render

        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

 

        glUseProgram(gl_program);

        glBindVertexArray(gl_vao);

        glDrawArrays(GL_TRIANGLES, 0, 3);

 

        glBindVertexArray (0);

        glUseProgram (0);

 

        glFlush();

 

        return true

 

 

ビルド

valac --vapidir=../vapi --pkg gtk+-3.0 --pkg glepoxy -X -lepoxy testglarea.gs

Genie Image Viewer 2 (GtkStack)

f:id:onagat12:20150619121114p:plain

プログラムを実行したところ

 

f:id:onagat12:20150619121135p:plain

一覧表示(List)から画像を選択し、拡大表示(Large)ボタンを押すとページが

遷移し拡大画像が表示される。

 

前回のimage-viewerプログラムをGtkStackを使って書き直しました。
clutter-gtkを使用しています。
・ファイルの読み込み、前回と同様。
・ファイルパスリストの作成、前回と同様。
・画像の表示、前回と同様。

## image-viewer-stack-gs.gs
uses
    GtkClutter
    Clutter

init
     if GtkClutter.init(ref args) != InitError.SUCCESS
        print "Clutter init error"

    var win = new MainWindow ()
    win.show_all ()

    Gtk.main ()

class MainWindow : Gtk.Window
    image : Image
    actor2 : Clutter.Actor
    filename : string
    IMAGE_DIR_PATH : string = "../images/"
    STAGE_WIDTH : int = 600
    STAGE_HEIGHT : int = 600
    THUMBNAIL_SIZE : int = 150
    ROW_COUNT : int = 4
    COL_COUNT : int = 3

    init
        title = "ImageViewer"
        window_position = Gtk.WindowPosition.CENTER
        default_width = 620
        default_height = 650
        border_width = 10
        destroy.connect(Gtk.main_quit)

        var box = new Gtk.Box(Gtk.Orientation.VERTICAL, 5)
        add(box)

        var stack = new Gtk.Stack()
        stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT_RIGHT
        stack.transition_duration = 1000
   
        var widget1 = new Embed ()
        var stage1 = widget1.get_stage ()
        stage1.width = stage1.height = STAGE_WIDTH
        var widget2 = new Embed ()
        var stage2 = widget2.get_stage ()
        stage2.width = stage2.height = STAGE_WIDTH

        var img_path_list = new list of string

        try
            var directory = File.new_for_path (IMAGE_DIR_PATH)
            var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME, 0)

            file_info : FileInfo
            while (file_info = enumerator.next_file ()) != null
                filename = file_info.get_name ()
                //stdout.printf ("%s\n", file_info.get_name ());
                //stdout.printf ("%s\n", filename)
                img_path_list.add (filename)
        except e:Error
            print "Message: %s", e.message

        //stdout.printf ("%s\n", filename)
        print " "
        for s in img_path_list
            print s

        for var row = 0 to (ROW_COUNT - 1)
            for var col = 0 to (COL_COUNT - 1)
                var s = img_path_list[row * COL_COUNT + col]

                try
                    var pixbuf = new Gdk.Pixbuf.from_file (IMAGE_DIR_PATH + s)
                    image = new Image ()
                    image.set_data (pixbuf.get_pixels (),
                            pixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 : Cogl.PixelFormat.RGB_888,
                            pixbuf.width,
                            pixbuf.height,
                            pixbuf.rowstride)
                except e:Error
                    print "Message: %s", e.message

                var actor = new Clutter.Actor ()
                actor.content = image
                actor.set_size (THUMBNAIL_SIZE, THUMBNAIL_SIZE)
                actor.set_position (row * THUMBNAIL_SIZE, col * THUMBNAIL_SIZE)
                actor.reactive = true
                actor.button_press_event.connect (actor_clicked_cb)
                stage1.add_child (actor);

        stack.add_titled(widget1, "list", "List")

        actor2 = new Clutter.Actor ()
        actor2.set_size (STAGE_WIDTH, STAGE_HEIGHT)
        stage2.add_child (actor2)
        stack.add_titled(widget2, "large", "Large")

        var switcher = new Gtk.StackSwitcher()
        switcher.set_stack(stack)
        box.pack_start(switcher, false, false, 0)
        box.pack_start(stack, true, true, 0)

    def actor_clicked_cb (actor:Clutter.Actor, evt:ButtonEvent) : bool
        print "Clicked"

        var image2  = new Clutter.Image ()
        image2 = (Clutter.Image)actor.content
        actor2.content = image2

        return true

 

ビルド
valac --pkg gtk+-3.0 --pkg clutter-gtk-1.0 --pkg gee-0.8 image-viewer-stack-gs.gs

Genie Image Viewer

f:id:onagat12:20150606235236p:plain

(プログラムを実行したところ)

f:id:onagat12:20150606235237p:plain

(画像一覧で画像を選択するとウィンドウ全体に表示される。再度クリックすると、

一覧表示に戻る。)

 

GNOME Developer Platform Demos にある clutter を利用したサンプル photo-wall.c をGenieで書き直してみました。
Genieで使い易いように、以下の箇所を変更しています。
・ファイルの読み込みには、gio libaryのGLib.FileとGLib.FileInfoを使用している。
・ファイルパスリストには、gee libraryのlistを使用している。

・imageの表示には、Clutter.ImageとGdk.Pixbufを使用している。
(写真は、「フリー写真素材 Futta.NET」の写真を利用しています。)

 

## image-viewer-gs.gs

uses
    Clutter

stage : Stage
filename : string
image : Image

STAGE_WIDTH : int = 800
STAGE_HEIGHT : int = 600
THUMBNAIL_SIZE : int = 200
is_focused : bool = false
orig_x : float = 0.0f
orig_y : float = 0.0f

init
    var IMAGE_DIR_PATH = "./images/"

    if Clutter.init(ref args) != InitError.SUCCESS
    print "Clutter init error"

   stage = new Stage ()
   stage.title = "ImageView"
   stage.set_size (STAGE_WIDTH, STAGE_HEIGHT)
   stage.set_user_resizable (true)
   stage.destroy.connect(Clutter.main_quit)

   var img_path_list = new list of string

   try
       var directory = File.new_for_path (IMAGE_DIR_PATH)
       var enumerator = directory.enumerate_children (FileAttribute.STANDARD_NAME, 0)

       file_info : FileInfo
       while (file_info = enumerator.next_file ()) != null
           filename = file_info.get_name ()
           //stdout.printf ("%s\n", file_info.get_name ());
           stdout.printf ("%s\n", filename)
           img_path_list.add (filename)
   except e:Error
       print "Message: %s", e.message

    //stdout.printf ("%s\n", filename)
   print ""
   for s in img_path_list
       print s

   var row_count = STAGE_WIDTH / THUMBNAIL_SIZE
   var col_count = STAGE_HEIGHT / THUMBNAIL_SIZE

   for var row = 0 to (row_count - 1)
       for var col = 0 to (col_count - 1)
            var s = img_path_list[row * col_count + col]

            try
                 var pixbuf = new Gdk.Pixbuf.from_file (IMAGE_DIR_PATH + s)
                 image = new Image ()
                 image.set_data (pixbuf.get_pixels (),
                                            pixbuf.has_alpha ? Cogl.PixelFormat.RGBA_8888 :  Cogl.PixelFormat.RGB_888,
                                            pixbuf.width,
                                            pixbuf.height,
                                            pixbuf.rowstride)
          except e:Error
               print "Message: %s", e.message

         var actor = new Actor ()
         actor.content = image
         actor.set_size (THUMBNAIL_SIZE, THUMBNAIL_SIZE)
         actor.set_position (row * THUMBNAIL_SIZE, col * THUMBNAIL_SIZE)
         actor.reactive = true
         actor.button_press_event.connect (actor_clicked_cb)
         stage.add_child (actor);

    stage.show()
    Clutter.main()

def actor_clicked_cb (actor:Actor, evt:ButtonEvent) : bool
    print "Clicked"
    print "x: %d", (int)actor.x
    print "y: %d", (int)actor.y
    print "z: %d", (int)actor.z_position

    stage.remove_child (actor)
    stage.add_child (actor)

    if is_focused == false
        orig_x = actor.x
        orig_y = actor.y

    print "orig_x: %d", (int)orig_x
    print "orig_y: %d", (int)orig_y

    if is_focused == false
       actor.x = 0
       actor.y = 0
       actor.z_position = 10.0f
       actor.reactive = true
       actor.width = STAGE_WIDTH
       actor.height = STAGE_HEIGHT
   else
      actor.x = orig_x
      actor.y = orig_y
      actor.z_position = 0.0f
      actor.reactive = true
      actor.width = THUMBNAIL_SIZE
      actor.height = THUMBNAIL_SIZE

   is_focused = !is_focused

   return true

 

ビルド
valac --pkg clutter-1.0 --pkg gee-0.8 image-viewer-gs.gs

 

Vala言語とOpenGL (4)

f:id:onagat12:20150302021004p:plain

GUIをGladeで作成しました。
Gladeでの作成画面

f:id:onagat12:20150302020143p:plain

adjustmentの設定画面

f:id:onagat12:20150302020220p:plain

Scale上のスライダの表示方法は、下に書いてあります。

 

gtkcluttergl4.vala
using Gtk;
using GtkClutter;
using Clutter;

public class Main : Object
{
    const string UI_FILE = "mainwindow.ui";
    private Builder builder;

    private Clutter.Actor coglbox;
    private static float alpha;

    public Main ()
    {
        try
        {
             builder = new Builder ();
             builder.add_from_file (UI_FILE);
             builder.connect_signals (this);

             CreateUI ();

             var window = builder.get_object ("window1") as Gtk.Window;
             window.title = "GtkClutterGL4";
             window.destroy.connect (Gtk.main_quit);
             window.show_all ();
        }
        catch (Error e) {
            stderr.printf ("Could not load UI: %s\n", e.message);
        }
    }

    private void CreateUI ()
    {
          var box = builder.get_object ("box1") as Gtk.Box;
           var widget = new Embed ();
           box.pack_start (widget, true, true, 0);

           var stage = widget.get_stage ();
           stage.width = stage.height = 400;
           stage.background_color = Clutter.Color () { alpha = 255 };

           coglbox = new Clutter.Actor ();
           stage.add_actor (coglbox);
           coglbox.paint.connect (paint_cb);

           var button = builder.get_object ("button1") as Button;
           button.clicked.connect (Gtk.main_quit);

           var scale = builder.get_object ("scale1") as Scale;
           scale.value_changed.connect *1;
                alpha = (float)scale.get_value ();
                coglbox.queue_redraw ();
           });
     }

    private void paint_cb ()
    {
          //stdout.printf("paint-cb \n");
         Cogl.TextureVertex vertices1[3];

         Cogl.push_matrix ();
         Cogl.translate (200, 200, 0);
         Cogl.rotate (alpha, 0, 0, 1);

         vertices1[0].x = 0;
         vertices1[0].y = -150;
         vertices1[0].z = 0;
         vertices1[0].color.set_from_4f (1.0f, 0.0f, 0.0f, 1.0f);

         vertices1[1].x = -150;
         vertices1[1].y = 150;
         vertices1[1].z = 0;
         vertices1[1].color.set_from_4f (0.0f, 1.0f, 0.0f, 1.0f);

         vertices1[2].x = 150;
         vertices1[2].y = 150;
         vertices1[2].z = 0;
         vertices1[2].color.set_from_4f (0.0f, 0.0f, 1.0f, 1.0f);

        Cogl.polygon (vertices1, true);

        Cogl.pop_matrix();
    }
}

void main (string[] args)
{
     GtkClutter.init (ref args);

     new Main ();

     Gtk.main ();
}
ビルド
valac --pkg gtk+-3.0 --pkg clutter-gtk-1.0 gtkcluttergl4.vala

Scaleのスライダの表示
スライダを表示する方法は、gladeで設定する方法とプログラム内で設定する
方法があります。
1 galdeで設定
 glade上でスライダを表示するには、Scaleにアジャストメントを設定する。
 設定の方法
    1    Scaleを選択。
    2 Scaleプロパティ内のアジャストメントの右側のアイコンをクリック。
    3 アジャストメントの選択ダイアログで、新規(New)をクリック。
    4 ajdjustment1オブジェクトが生成される。
    5 ajdjustment1を選択し、必要な設定をする。

2 プログラム内で設定
 gladeのuiファイルからScaleを取り出し、set_rangeメソッドで設定する。
 例 var scale = builder.get_object ("scale1") as Scale;
            scale.set_range (0, 100);

 

注意 このブログでは、引数なしの無名関数の表示が変になります。注釈のようになっています。

*1:) => {
                stdout.printf ("%f\n", scale.get_value (

Vala言語とOpenGL (3)

f:id:onagat12:20150301021658p:plain

三角形の回転にScaleウィジェを利用しています。

gtkclutter3.vala
using Gtk;
using GtkClutter;
using Clutter;

public class MainWindow : Gtk.Window
{
   private Clutter.Actor coglbox;
   private static float alpha;

   public MainWindow ()
   {
        title = "GtkClutterGL";
        set_default_size (400, 460);
        destroy.connect (Gtk.main_quit);

        var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
        var box2 = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
        var scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 360, 2);
        var button = new Gtk.Button.with_label ("Quit");
        button.clicked.connect (Gtk.main_quit);

        vbox.pack_start (box2, true, true, 0);
        vbox.pack_start (scale, false, false, 0);
        vbox.pack_start (button, false, false, 0);
        add (vbox);

        var widget = new Embed ();
        box2.pack_start (widget, true, true, 0);

        var stage = widget.get_stage ();
        stage.width = stage.height = 400;
        stage.background_color = Clutter.Color () { alpha = 255 };

        coglbox = new Clutter.Actor ();
        stage.add_actor (coglbox);
        coglbox.paint.connect (paint_cb);

        scale.value_changed.connect *1;
             alpha = (float)scale.get_value ();
             coglbox.queue_redraw ();
        });
   }

   private void paint_cb ()
   {
       Cogl.TextureVertex vertices1[3];

       Cogl.push_matrix ();
       Cogl.translate (200, 200, 0);
       Cogl.rotate (alpha, 0, 0, 1);

       vertices1[0].x = 0;
       vertices1[0].y = -150;
       vertices1[0].z = 0;
       vertices1[0].color.set_from_4f (1.0f, 0.0f, 0.0f, 1.0f);

       vertices1[1].x = -150;
       vertices1[1].y = 150;
       vertices1[1].z = 0;
       vertices1[1].color.set_from_4f (0.0f, 1.0f, 0.0f, 1.0f);

       vertices1[2].x = 150;
       vertices1[2].y = 150;
       vertices1[2].z = 0;
       vertices1[2].color.set_from_4f (0.0f, 0.0f, 1.0f, 1.0f);

       Cogl.polygon (vertices1, true);

       Cogl.pop_matrix();
    }
}

void main (string[] args)
{
     GtkClutter.init (ref args);
     var window = new MainWindow ();
     window.show_all ();
     Gtk.main ();
}
ビルド
valac --pkg gtk+-3.0 --pkg clutter-gtk-1.0 gtkcluttergl3.vala

Scaleの使い方
1 Scaleウィジェの生成には、Scale.with_rangeメソッドを使います。
        var scale = new Gtk.Scale.with_range (Gtk.Orientation.HORIZONTAL, 0, 360, 2);
    Scaleの方向、初めの値、終りの値、ステップの値を設定します。
2 Scaleの値によって三角形を回転させるには、value_changedシグナルを使います。
    これは、Scaleの親クラスであるRangeのシグナルです。
        scale.value_changed.connect *2;
            alpha = (float)scale.get_value ();
            coglbox.queue_redraw ();
        });

*1:) => {;
             stdout.printf ("%f\n", scale.get_value (

*2:) => {
            stdout.printf ("%f\n", scale.get_value (

Vala言語とOpenGL (2)

f:id:onagat12:20150301012106p:plain

GtkウィンドウにOpenGLを描画していることが分かるように、ボタン(Button)を
ウィンドウに追加しました。
また、Stageのmotion_eventシグナルを使って、Stage上でマウスを動かすと
三角形が回転するようにしました。コールバック関数には、無名関数を使っています。

gtkcluttergl2.vala
using Gtk;
using GtkClutter;
using Clutter;

public class MainWindow : Gtk.Window
{
    private Clutter.Actor coglbox;
    private static float alpha;

    public MainWindow ()

    {
         title = "GtkClutterGL";
         set_default_size (300, 300);
         destroy.connect (Gtk.main_quit);

         var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
         var box2 = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
         var button = new Gtk.Button.with_label ("Quit");
         button.clicked.connect (Gtk.main_quit);

         vbox.pack_start (box2, true, true, 0);
         vbox.pack_start (button, false, false, 0);
         add (vbox);

         var widget = new Embed ();
         box2.pack_start (widget, true, true, 0);

         var stage = widget.get_stage ();
         stage.width = stage.height = 300;
         stage.background_color = Clutter.Color () { alpha = 255 };

         coglbox = new Clutter.Actor ();
         stage.add_actor (coglbox);
         coglbox.paint.connect (paint_cb);

         stage.motion_event.connect ((evt) => {
              GLib.message ("Motion event - Stage");
              stdout.printf ("x = %f y = %f\n", evt.x, evt.y);
              alpha = alpha + 0.5f;
              coglbox.queue_redraw ();
              return true;
        });
     }

    private void paint_cb ()

    {
         Cogl.TextureVertex vertices1[3];

         Cogl.push_matrix ();
         Cogl.translate (150, 150, 0);
         Cogl.rotate (alpha, 0, 0, 1);

         vertices1[0].x = 0;
         vertices1[0].y = -150;
         vertices1[0].z = 0;
         vertices1[0].color.set_from_4f (1.0f, 0.0f, 0.0f, 1.0f);

         vertices1[1].x = -150;
         vertices1[1].y = 150;
         vertices1[1].z = 0;
         vertices1[1].color.set_from_4f (0.0f, 1.0f, 0.0f, 1.0f);

         vertices1[2].x = 150;
         vertices1[2].y = 150;
         vertices1[2].z = 0;
         vertices1[2].color.set_from_4f (0.0f, 0.0f, 1.0f, 1.0f);

         Cogl.polygon (vertices1, true);

         Cogl.pop_matrix();
     }

}

void main (string[] args)
{
     GtkClutter.init (ref args);
     var window = new MainWindow ();
     window.show_all ();
     Gtk.main ();
}
ビルド
valac --pkg gtk+-3.0 --pkg clutter-gtk-1.0 gtkcluttergl2.vala

説明
1 メインのウィンドウに縦方向のBox(vbox)を配置します。その中に、Box(box2)と
  ボタン(button)を配置します。また、box2にEmbedウィジェを貼り付けます。
       var vbox = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
          var box2 = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
          var button = new Gtk.Button.with_label ("Quit");
          button.clicked.connect (Gtk.main_quit);
          vbox.pack_start (box2, true, true, 0);
          vbox.pack_start (button, false, false, 0);
          add (vbox);

          var widget = new Embed ();
          box2.pack_start (widget, true, true, 0);
2 Stageのmotion_eventシグナルを使った三角形の回転
          stage.motion_event.connect ((evt) => {
               GLib.message ("Motion event - Stage");
               stdout.printf ("x = %f y = %f\n", evt.x, evt.y);
               alpha = alpha + 0.5f;
               coglbox.queue_redraw ();
               return true;
           });
  paint_cbコールバック関数(coglboxアクターのコールバック関数)
     ここでopenglのrotate関数で回転させる。
           Cogl.rotate (alpha, 0, 0, 1);