2

Clutter 1.12
Cogl 1.10
Vala 或 C 或 Python。

我在这里可能有一个根本的误解——

我认为“演员”是 3D 多边形的东西。我将它们的颜色视为顶点颜色或纹理映射。鉴于此,我一直在尝试绘制一个自定义 Actor 并用通过 Cairo 绘制的内容填充它。我哪儿也去不了。

代码包含在下面(在 Vala 中)。任何人都可以让我正确了解 Clutter 的基础知识(文档只是没有删减它),或者,如果我很接近,请帮助我使该代码正常工作。

我希望看到一个带有笑脸的圆角矩形。我看到的是覆盖*脸部的 Cogl 路径填充。我认为paint() 是在drawme() 之后完成的

*如果您在方法paint() 中将Clutter.Color 设置为“#0001”,您会看到这一点。

/*

Clutter Actor with custom paint() and filled with a Cairo-drawn texture.
(NOT yet working.)

Compile with:

    valac \
  --pkg clutter-1.0 \
  --pkg cogl-1.0 \
    somename.vala

*/


public class SmileyRect : Clutter.Actor {

  //private vars
  private Clutter.Canvas _canvas;
  private bool _flip = false;
  private int _w = 300;
  private int _h = 300;

  //Constructor
  construct {
    _canvas = new Clutter.Canvas();
    _canvas.set_size( this._w, this._h );

    this.set_size( this._w, this._h );
    this.set_content( _canvas );

    //Connect to the draw signal - this is as-per Clutter docs.
    _canvas.draw.connect( drawme );

    //Make it reactive and connect to the button-press-event
    this.set_reactive( true );
    this.button_press_event.connect( button_press );
  }

  /*
    Button press signal handler.
    Changes the colour of what will be painted on the canvas.
  */
  private bool button_press ( Clutter.ButtonEvent evt ) {
    this._flip = !this._flip; //Jiggle a value.
    this.redraw(); // Forces re-run of the drawme() method.
    return true; //all done with this signal.
  }

  //Common function to draw Cogl stuff - used in paint and pick.
  private void draw_rr( Clutter.Color? color ) {
    if (color != null ) { Cogl.set_source_color4ub(color.red,color.green,color.blue,color.alpha); }
    Cogl.Path.round_rectangle( 0, 0, this._w, this._h, 15, 0.3f );
    Cogl.Path.close();

    // When from paint(): 
    // Is there some way to fill this Cogl path with the contents
    // of this._canvas? Or some other paradigm?
    if (color != null ) { Cogl.Path.fill(); }
  }

  /* Some kind of freaky, this magic paint() thing.
     Took me ages to get it running.
     I want to draw a rounded rectangle as the basic shape
     of this actor. 
  */
  public override void paint() {
    stdout.printf("paint runs.\n");
    // I did try a transparent color #0000 - just to see. No go.
    // #000f - draws a black rounded rect *OVER* the Cairo canvas. It covers
    // the smiley face.
    this.draw_rr( Clutter.Color.from_string("#0000") );
  }


  /* I followed paint() example, but the argument was tricky.
     I eventually found it from some PyClutter source code. 
  */
  public override void pick(Clutter.Color color) {
    stdout.printf("pick runs.\n");
    this.draw_rr( color );
  }

  /*
    Draws the Cairo art to the canvas.
    I want this art to be the bitmap/pixmap that *fills* the
    basic rounded rectangle shape of this actor.
    i.e I want the smile face cairo rectangle to be *within* the
    polygon that is draw via Cogl in paint() method.

    Does this even make sense?
  */
  private bool drawme( Cairo.Context ctx, int width, int height) {
    //Draw a rectangle
    double[] col;
    if (this._flip) {
      col = {1f,0f,0f};
      } 
    else {
      col = {0f,1f,0f};
    }

    ctx.set_source_rgb( col[0], col[1], col[2] );
    ctx.rectangle( 0, 0, width, height );
    ctx.fill();

    //Draw a smiley face.

    // Aside: Been trying to avoid all the weird casting of the floats/doubles used below
    // (see the generated c source.) Not at all sure what's going on there.
    // Also not sure about that 'f' on the numbers. Where/when do I have to use it?

    double pi = 3.14f;
    double w = (double) width;
    double h = (double) height;

    ctx.set_line_width( 6f );

    ctx.set_source_rgb( 0f, 0f, 0.8f );

    //eyes
    ctx.move_to( w/3f, h/3f );
    ctx.rel_line_to( 0f, h/6f );
    ctx.move_to(  2*(w/3f), h/3f );
    ctx.rel_line_to( 0f, h/6f );
    ctx.stroke();

    ctx.set_source_rgb( 1f, 1f, 0f );

    double rad = (w > h) ? h : w;
    //face
    ctx.arc( w/2f, h/2f, (rad/2f) - 20f,0f,2f * pi );
    ctx.stroke();
    //smile
    ctx.arc( w/2f, h/2f, (rad/3f) -10f, pi/3f, 2f * (pi/3f) );
    ctx.stroke();

    return true;
  }

  //Redraw - forces invalidate which trips the draw event
  public void redraw() {
    this._canvas.invalidate();
  }
} //end SmileyRect class



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

  var stage = new Clutter.Stage();
  stage.set_size(400,400);

  var rs = new SmileyRect();
  stage.add_child(rs);
  rs.redraw();

  stage.destroy.connect(Clutter.main_quit);
  stage.show();
  Clutter.main();

}
4

0 回答 0