Home > OP4JS > CODEF for Smart Mobile Studio

CODEF for Smart Mobile Studio

January 27, 2014 Leave a comment Go to comments
CodeF rocks

CodeF rocks

I never got to complete the TW3Canvas class under Smart Mobile Studio, so this post should be considered a must for SMS developers that use graphics for games or presentations. As you probably know there are some “odd” methods in TW3Canvas that is poorly documented, first and foremost drawPart and drawTile. These two methods are ported from a javascript library called CodeF – which is a super fast set of routines for writing demos and games. I wanted to implement the whole library under SMS, but sadly I never had the chance.

Patching Smart Mobile

To get this fix you have to do some “mild” patching of the file w3graphics.pas. Before you proceed make sure you make a backup of this file, just in case. Proceed at your own risk – as I take no responsibility¬†should something go wrong (although in this case, it should be fairly safe).

  • Open up w3graphics.pas
  • Remove the methods DrawPart,DrawTo and DrawTile from the TW3Canvas class
  • Remove the implementations for above methods
  • Now create a new unit called codef.pas, save it to the RTL\libraries folder

Now copy this code into the codef.pas file:

unit codef;

{ **************************************************************************** }
{                                                                              }
{ CODEF canvas methods for Smart Mobile Studio                                 }
{ Written by Jon Lennart Aasenden                                              }
{ Copyright (c) Jon Lennart Aasenden. All rights are reserved.                 }
{                                                                              }
{ **************************************************************************** }


interface

uses 
  W3System, w3image, w3graphics, w3c.DOM, w3c.Canvas2DContext;

type

  TQTXImageHelper = Class helper for TW3Image
  public
    (* Draws the image to a context, and returns the context *)
    function  toContext(var aContext:TW3GraphicContext):Boolean;overload;
    function  toContext(var aContext:TW3GraphicContext;
              var aCanvas:TW3Canvas):Boolean;overload;
  end;

  (* CODEF implementation.
     NOTE: Midhandling of sections is not implemented yet *)
  TCodeFCanvas = class helper for TW3Canvas
  public
    Procedure   Quad(const x1,y1,x2,y2,x3,y3,x4,y4:Float;
                const aColor:TColor);overload;

    procedure   Quad(const x1,y1,x2,y2:Float;
                const aFillStyle:String);overload;

    procedure   Plot(const x1,y1,aWidth:Float;
                const aColor:TColor);

    procedure   Line(const x1,y1,x2,y2:Float;
                const aWidth:Integer;
                Const aColor:TColor);

    procedure   FastFill(const aColor:TColor);overload;

    procedure   Clear;

    procedure   Triangle(const x1,y1,x2,y2,x3,y3:Float;
                const aColor:TColor);

    procedure   DrawPart(target: TW3Canvas;
                const srcX, srcY: Integer;
                const srcWidth, srcHeight: Integer;
                const dstX, dstY: Integer); overload;

    procedure   DrawPart(target: TW3Canvas;
                const srcX, srcY: Integer;
                const srcWidth, srcHeight: Integer;
                const dstX, dstY: Integer;
                const rotation: Integer); overload;

    procedure   DrawPart(target: TW3Canvas;
                const srcX, srcY: Integer;
                const srcWidth, srcHeight: Integer;
                const dstX, dstY: Integer;
                const rotation: Integer;
                const alpha: Integer); overload;

    procedure   DrawTile(target: TW3Canvas;
                const TileID: Integer;
                const TileSize: Integer;
                const dstX, dstY: Integer); overload;

    procedure   DrawTile(target: TW3Canvas;
                const TileID: Integer;
                const TileSize: Integer;
                const dstX, dstY: Integer;
                const rotation: Integer); overload;

    procedure   DrawTile(target: TW3Canvas;
                const TileID: Integer;
                const TileSize: Integer;
                const dstX, dstY: Integer;
                const rotation: Integer;
                const alpha: Integer); overload;

    procedure   DrawTo(target: TW3Canvas;
                const dstX, dstY: Integer); overload;

    procedure   DrawTo(target: TW3Canvas;
                const dstX, dstY: Integer;
                const rotation: Integer); overload;

    procedure   DrawTo(target: TW3Canvas;
                const dstX, dstY: Integer;
                const rotation: Integer;
                const alpha: Integer); overload;
  End;


implementation

//#############################################################################
// TQTXImageHelper
//#############################################################################

function  TQTXImageHelper.toContext(var aContext:TW3GraphicContext):Boolean;
var
  mCanvas:  TW3Canvas;
begin
  aContext:=NIL;
  result:=self.Ready;
  if result then
  Begin
    aContext:=TW3GraphicContext.Create(null);
    aContext.Allocate(self.Width,self.height);
    mCanvas:=TW3Canvas.Create(aContext);
    try
      mCanvas.putImageData(self.toImageData,0,0);
    finally
      mCanvas.free;
    end;
  end;
end;

function TQTXImageHelper.toContext(var aContext:TW3GraphicContext;
         var aCanvas:TW3Canvas):Boolean;
begin
  aContext:=NIL;
  aCanvas:=NIL;
  result:=self.Ready;
  if result then
  Begin
    aContext:=TW3GraphicContext.Create(null);
    aContext.Allocate(self.Width,self.height);
    aCanvas:=TW3Canvas.Create(aContext);
    aCanvas.putImageData(self.toImageData,0,0);
  end;
end;


//#############################################################################
// TCodeFCanvas
//#############################################################################

Procedure TCodeFCanvas.FastFill(const aColor:TColor);
var
  mFillStyle: String;
  mAlpha: Float;
Begin
  mFillStyle:=self.FillStyle;
  mAlpha:=self.globalAlpha;
  self.GlobalAlpha:=1;
  self.FillStyle:=ColorToWebStr(aColor);
  self.FillRectF(0,0,self.Context.Width,self.Context.Height);
  self.FillStyle:=mFillStyle;
  self.globalAlpha:=mAlpha;
end;

procedure TCodeFCanvas.Clear;
begin
  self.clearRectF(0,0,self.Context.Width,self.Context.Height);
end;

procedure TCodeFCanvas.DrawPart(target: TW3Canvas;
          const srcX, srcY: Integer;
          const srcWidth, srcHeight: Integer;
          const dstX, dstY: Integer);
begin
  if target <> nil then
  begin
    target.Handle.translate(dstX,dstY);
    target.Handle.drawImage(JElement(self.Context.handle),srcX,srcY,
      srcWidth,srcHeight,0,0,srcWidth,srcHeight);
    target.Handle.setTransform(1,0,0,1,0,0);
  end;
end;

procedure TCodeFCanvas.DrawPart(target: TW3Canvas;
          const srcX, srcY: Integer;
          const srcWidth, srcHeight: Integer;
          const dstX, dstY: Integer;
          const rotation: Integer);
begin
  if target <> nil then
  begin
    target.Handle.translate(dstX, dstY);
    target.Handle.rotate(DegToRad(rotation));
    target.Handle.drawImage(JElement(self.Context.Handle), srcX, srcY,
      srcWidth, srcHeight, 0, 0, srcWidth, srcHeight);
    target.Handle.setTransform(1, 0, 0, 1, 0, 0);
  end;
end;

procedure TCodeFCanvas.DrawPart(target: TW3Canvas;
          const srcX, srcY: Integer;
          const srcWidth, srcHeight: Integer;
          const dstX, dstY: Integer;
          const rotation: Integer;
          const alpha: Integer);
var
  mAlpha: Float;
begin
  if target <> nil then
  begin
    mAlpha := target.GlobalAlpha;
    target.GlobalAlpha := (1 / 255) * alpha;
    target.Handle.translate(dstX, dstY);
    target.Handle.rotate(DegToRad(rotation));
    target.Handle.drawImage(JElement(self.Context.Handle), srcX, srcY,
      srcWidth, srcHeight, 0, 0, srcWidth, srcHeight);
    target.Handle.setTransform(1, 0, 0, 1, 0, 0);
    target.GlobalAlpha := mAlpha;
  end;
end;

procedure TCodeFCanvas.Triangle(const x1,y1,x2,y2,x3,y3:Float;
          const aColor:TColor);
Begin
  self.Beginpath;
  self.moveToF(x1,y1);
  self.lineToF(x2,y2);
  self.linetoF(x3,y3);
  self.ClosePath;
  self.fillStyle:=ColorToWebStr(aColor);
  self.Fill();
end;

procedure TCodeFCanvas.Plot(const x1,y1,aWidth:Float;
          const aColor:TColor);
begin
  Quad(x1,y1,x1+awidth,y1, x1+awidth,y1+awidth,x1,y1+awidth,aColor);
end;

procedure TCodeFCanvas.Line(const x1,y1,x2,y2:Float;
          const aWidth:Integer;
          Const aColor:TColor);
var
  mTemp:  String;
Begin
  mtemp:=self.StrokeStyle;
  self.StrokeStyle:=ColorToWebStr(aColor);
  self.linewidth:=aWidth;
  self.Beginpath;
  self.moveToF(x1,y1);
  self.lineToF(x2,y2);
  self.Stroke;
  self.closepath;
  self.StrokeStyle:=mTemp;
end;

Procedure TCodeFCanvas.Quad(const x1,y1,x2,y2,x3,y3,x4,y4:Float;
          const aColor:TColor);
begin
  self.Beginpath;
  self.moveToF(x1,y1);
  self.linetoF(x2,y2);
  self.linetoF(x3,y3);
  self.linetoF(x4,y4);
  self.closepath;
  self.fillstyle:=ColorToWebStr(aColor);
  self.Fill;
end;

procedure TCodeFCanvas.Quad(const x1,y1,x2,y2:Float;
          const aFillStyle:String);
begin
  self.Beginpath;
  self.moveToF(x1,y1);
  self.linetoF(x1+x2,y1);
  self.linetoF(x1+x2,y1+y2);
  self.linetoF(x1,y1+y2);
  self.closepath;
  self.fillStyle:=aFillStyle;
  self.Fill;
end;

procedure TCodeFCanvas.DrawTile(target: TW3Canvas;
  const TileID: Integer;
  const TileSize: Integer;
  const dstX, dstY: Integer);
var
  srcX,srcY: Integer;
begin
  if target <> nil then
  begin
    srcX := TileID mod Floor(self.Context.Width / TileSize) * TileSize;
    srcY := Floor(TileID / (self.Context.Width / TileSize)) * TileSize;
    DrawPart(target, srcX, srcY, TileSize, TileSize, dstX, dstY);
  end;
end;

procedure TCodeFCanvas.DrawTile(target: TW3Canvas;
  const TileID: Integer;
  const TileSize: Integer;
  const dstX, dstY: Integer;
  const rotation: Integer);
var
  srcX, srcY: Integer;
begin
  if target <> nil then
  begin
    srcX := TileID mod Floor(self.Context.Width / TileSize) * TileSize;
    srcY := Floor(TileID / (self.Context.Width / TileSize)) * TileSize;
    DrawPart(target, srcX, srcY, TileSize, TileSize, dstX, dstY, rotation);
  end;
end;

procedure TCodeFCanvas.DrawTile(target: TW3Canvas;
  const TileID: Integer;
  const TileSize: Integer;
  const dstX, dstY: Integer;
  const rotation: Integer;
  const alpha: Integer);
var
  srcX, srcY: Integer;
begin
  if target <> nil then
  begin
    srcX := TileID mod Floor(self.Context.Width / TileSize) * TileSize;
    srcY := Floor(TileID / (self.Context.Width / TileSize)) * TileSize;
    DrawPart(target, srcX, srcY, TileSize, TileSize, dstX, dstY, rotation, alpha);
  end;
end;

procedure TCodeFCanvas.DrawTo(target: TW3Canvas;
  const dstX, dstY: Integer);
begin
  if target <> nil then
  target.Handle.drawImage(JElement(self.Context.Handle), dstX, dstY);
end;

procedure TCodeFCanvas.DrawTo(target: TW3Canvas;
  const dstX, dstY: Integer;
  const rotation: Integer);
begin
  if target <> nil then
  begin
    target.Handle.translate(dstX, dstY);
    target.Handle.rotate(DegToRad(rotation));
    target.Handle.drawImage(JElement(self.Context.Handle), 0, 0);
    target.Handle.setTransform(1, 0, 0, 1, 0, 0);
  end;
end;

procedure TCodeFCanvas.DrawTo(target: TW3Canvas;
  const dstX, dstY: Integer;
  const rotation: Integer;
  const alpha: Integer);
var
  mAlpha: Float;
begin
  if target <> nil then
  begin
    mAlpha := target.Handle.globalAlpha;
    target.GlobalAlpha := (1 / 255) * alpha;
    target.Handle.translate(dstX, dstY);
    target.Handle.rotate(DegToRad(rotation));
    target.Handle.drawImage(JElement(self.Context.Handle), 0, 0);
    target.Handle.setTransform(1, 0, 0, 1, 0, 0);
    target.GlobalAlpha := mAlpha;
  end;
end;


end.

Using CodeF

Whenever you want to use these new methods, simply incldude the codef.pas unit in your uses list, and the methods become a part of your normal TW3Canvas class. For inspiration, visit the CODEF demo scene and have a look what other people are making with CodeF.

Note: the above is only a port of a single library, CodeF consists of many such modules.

Advertisements
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: