GuiShapeRep.pas
上传用户:ctlcnc
上传日期:2021-12-10
资源大小:4933k
文件大小:14k
源码类别:

2D图形编程

开发平台:

Delphi

  1. unit GuiShapeRep;
  2. //---------------------------------------------------------------------------
  3. // GuiShapes.pas                                        Modified: 01-Mar-2007
  4. // Freeform shapes for Asphyre GUI foundation                     Version 1.0
  5. //---------------------------------------------------------------------------
  6. // Important Notice:
  7. //
  8. // If you modify/use this code or one of its parts either in original or
  9. // modified form, you must comply with Mozilla Public License v1.1,
  10. // specifically section 3, "Distribution Obligations". Failure to do so will
  11. // result in the license breach, which will be resolved in the court.
  12. // Remember that violating author's rights is considered a serious crime in
  13. // many countries. Thank you!
  14. //
  15. // !! Please *read* Mozilla Public License 1.1 document located at:
  16. //  http://www.mozilla.org/MPL/
  17. //
  18. // If you require any clarifications about the license, feel free to contact
  19. // us or post your question on our forums at: http://www.afterwarp.net
  20. //---------------------------------------------------------------------------
  21. // The contents of this file are subject to the Mozilla Public License
  22. // Version 1.1 (the "License"); you may not use this file except in
  23. // compliance with the License. You may obtain a copy of the License at
  24. // http://www.mozilla.org/MPL/
  25. //
  26. // Software distributed under the License is distributed on an "AS IS"
  27. // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
  28. // License for the specific language governing rights and limitations
  29. // under the License.
  30. //
  31. // The Original Code is GuiShapeRep.pas.
  32. //
  33. // The Initial Developer of the Original Code is M. Sc. Yuriy Kotsarenko.
  34. // Portions created by M. Sc. Yuriy Kotsarenko are Copyright (C) 2007,
  35. // Afterwarp Interactive. All Rights Reserved.
  36. //---------------------------------------------------------------------------
  37. interface
  38. //---------------------------------------------------------------------------
  39. uses
  40.  Types, SysUtils, Vectors2px, AsphyreXML, AsphyreClasses;
  41. //---------------------------------------------------------------------------
  42. type
  43.  TGeometryShape = class
  44.  public
  45.   function PointInside(const Point: TPoint2px): Boolean; virtual; abstract;
  46.   function BoundingBox(): TRect; virtual; abstract;
  47.   procedure MoveBy(const Shift: TPoint2px); virtual; abstract;
  48.   procedure Rescale(const Delta: TPoint2px); virtual; abstract;
  49.   procedure LoadFromXML(Node: TXMLNode); virtual; abstract;
  50.  end;
  51. //---------------------------------------------------------------------------
  52.  TPolygonShape = class(TGeometryShape)
  53.  private
  54.   Vertices: array of TPoint2px;
  55.  public
  56.   function PointInside(const Point: TPoint2px): Boolean; override;
  57.   function BoundingBox(): TRect; override;
  58.   procedure MoveBy(const Shift: TPoint2px); override;
  59.   procedure Rescale(const Delta: TPoint2px); override;
  60.   procedure LoadFromXML(Node: TXMLNode); override;
  61.  end;
  62. //---------------------------------------------------------------------------
  63.  TGuiShape = class
  64.  private
  65.   FName : string;
  66.   Shapes: array of TGeometryShape;
  67.   function Insert(Shape: TGeometryShape): Integer;
  68.   procedure ReleaseAll();
  69.  public
  70.   property Name: string read FName;
  71.   function PointInside(const Point: TPoint2px): Boolean;
  72.   function BoundingBox(): TRect;
  73.   procedure LoadFromXML(Node: TXMLNode);
  74.   constructor Create(const AName: string);
  75.   destructor Destroy(); override;
  76.  end;
  77. //---------------------------------------------------------------------------
  78.  TGuiShapes = class
  79.  private
  80.   List: TAsphyreList;
  81.   function GetCount(): Integer;
  82.   function GetItem(Index: Integer): TGuiShape;
  83.   procedure FreeItem(List: TAsphyreList; Item: Pointer);
  84.   function SortItem(List: TAsphyreList; Item1, Item2: Pointer): Integer;
  85.   function FindItem(List: TAsphyreList; Item, User: Pointer): Integer;
  86.   function GetShape(const Name: string): TGuiShape;
  87.  public
  88.   property Count: Integer read GetCount;
  89.   property Items[Index: Integer]: TGuiShape read GetItem; default;
  90.   property Shape[const Name: string]: TGuiShape read GetShape;
  91.   function Insert(const Name: string): TGuiShape;
  92.   function IndexOf(Shape: TGuiShape): Integer; overload;
  93.   function IndexOf(const Name: string): Integer; overload;
  94.   procedure Remove(Index: Integer);
  95.   procedure Clear();
  96.   procedure ParseLink(const Link: string);
  97.   constructor Create();
  98.   destructor Destroy(); override;
  99.  end;
  100. //---------------------------------------------------------------------------
  101. var
  102.  GuiShapes: TGuiShapes = nil;
  103. //---------------------------------------------------------------------------
  104. implementation
  105. //---------------------------------------------------------------------------
  106. uses
  107.  AsphyreUtils, MediaUtils;
  108. //---------------------------------------------------------------------------
  109. procedure TPolygonShape.LoadFromXML(Node: TXMLNode);
  110. var
  111.  VNode: TXMLNode;
  112.  i, Index: Integer;
  113. begin
  114.  SetLength(Vertices, ParseInt(Node.FieldValue['vertices'], 0));
  115.  for i:= 0 to Node.ChildCount - 1 do
  116.   if (LowerCase(Node.Child[i].Name) = 'vertex') then
  117.    begin
  118.     VNode:= Node.Child[i];
  119.     Index:= ParseInt(VNode.FieldValue['index'], -1);
  120.     if (Index >= 0)and(Index < Length(Vertices)) then
  121.      begin
  122.       Vertices[Index].x:= ParseInt(VNode.FieldValue['x'], 0);
  123.       Vertices[Index].y:= ParseInt(VNode.FieldValue['y'], 0);
  124.      end;
  125.    end;
  126. end;
  127. //---------------------------------------------------------------------------
  128. function TPolygonShape.BoundingBox(): TRect;
  129. var
  130.  i: Integer;
  131. begin
  132.  Result.Left  := High(Integer);
  133.  Result.Right := Low(Integer);
  134.  Result.Top   := High(Integer);
  135.  Result.Bottom:= Low(Integer);
  136.  for i:= 0 to Length(Vertices) - 1 do
  137.   begin
  138.    Result.Left  := Min2(Result.Left, Vertices[i].x);
  139.    Result.Right := Max2(Result.Right, Vertices[i].x + 1);
  140.    Result.Top   := Min2(Result.Top, Vertices[i].y);
  141.    Result.Bottom:= Max2(Result.Bottom, Vertices[i].y + 1);
  142.   end;
  143. end;
  144. //---------------------------------------------------------------------------
  145. function TPolygonShape.PointInside(const Point: TPoint2px): Boolean;
  146. var
  147.  i, VertexCount: Integer;
  148.  p1, p2: PPoint2px;
  149. begin
  150.  Result:= False;
  151.  if (Length(Vertices) < 3)  then Exit;
  152.  VertexCount:= Length(Vertices);
  153.  p1:= @Vertices[0];
  154.  for i:= 0 to VertexCount - 1 do
  155.   begin
  156.    p2:= @Vertices[(i + 1) mod VertexCount];
  157.    if (Point.y > Min2(p1.y, p2.y)) then
  158.      if (Point.y <= Max2(p1.y, p2.y)) then
  159.        if (Point.x <= Max2(p1.x, p2.x)) then
  160.          if (p1.y <> p2.y) then
  161.           begin
  162.            if (p1.x = p2.x)or(Point.x <= (Point.y - p1.y) * (p2.x - p1.x) div
  163.             (p2.y - p1.y) + p1.x) then Result:= not Result;
  164.           end;
  165.    p1:= p2;
  166.   end;
  167. end;
  168. //---------------------------------------------------------------------------
  169. procedure TPolygonShape.MoveBy(const Shift: TPoint2px);
  170. var
  171.  i: Integer;
  172. begin
  173.  for i:= 0 to Length(Vertices) - 1 do
  174.   Vertices[i]:= Vertices[i] + Shift;
  175. end;
  176. //---------------------------------------------------------------------------
  177. procedure TPolygonShape.Rescale(const Delta: TPoint2px);
  178. var
  179.  i: Integer;
  180. begin
  181.  for i:= 0 to Length(Vertices) - 1 do
  182.   begin
  183.    Vertices[i].x:= iMul16(Vertices[i].x, Delta.x);
  184.    Vertices[i].y:= iMul16(Vertices[i].y, Delta.y);
  185.   end;
  186. end;
  187. //---------------------------------------------------------------------------
  188. constructor TGuiShape.Create(const AName: string);
  189. begin
  190.  inherited Create();
  191.  FName:= AName;
  192. end;
  193. //---------------------------------------------------------------------------
  194. destructor TGuiShape.Destroy();
  195. begin
  196.  ReleaseAll();
  197.  inherited;
  198. end;
  199. //---------------------------------------------------------------------------
  200. procedure TGuiShape.ReleaseAll();
  201. var
  202.  i: Integer;
  203. begin
  204.  for i:= 0 to Length(Shapes) - 1 do
  205.   Shapes[i].Free();
  206.  SetLength(Shapes, 0);
  207. end;
  208. //---------------------------------------------------------------------------
  209. function TGuiShape.BoundingBox(): TRect;
  210. var
  211.  i: Integer;
  212.  ShapeRect: TRect;
  213. begin
  214.  Result.Left  := High(Integer);
  215.  Result.Right := Low(Integer);
  216.  Result.Top   := High(Integer);
  217.  Result.Bottom:= Low(Integer);
  218.  for i:= 0 to Length(Shapes) - 1 do
  219.   begin
  220.    ShapeRect:= Shapes[i].BoundingBox;
  221.    Result.Left  := Min2(Result.Left, ShapeRect.Left);
  222.    Result.Right := Max2(Result.Right, ShapeRect.Right);
  223.    Result.Top   := Min2(Result.Top, ShapeRect.Top);
  224.    Result.Bottom:= Max2(Result.Bottom, ShapeRect.Bottom);
  225.   end;
  226. end;
  227. //---------------------------------------------------------------------------
  228. function TGuiShape.PointInside(const Point: TPoint2px): Boolean;
  229. var
  230.  i: Integer;
  231. begin
  232.  Result:= False;
  233.  for i:= 0 to Length(Shapes) - 1 do
  234.   begin
  235.    Result:= Result or Shapes[i].PointInside(Point);
  236.    if (Result) then Break;
  237.   end;
  238. end;
  239. //---------------------------------------------------------------------------
  240. function TGuiShape.Insert(Shape: TGeometryShape): Integer;
  241. var
  242.  Index: Integer;
  243. begin
  244.  Index:= Length(Shapes);
  245.  SetLength(Shapes, Index + 1);
  246.  Shapes[Index]:= Shape;
  247.  Result:= Index;
  248. end;
  249. //---------------------------------------------------------------------------
  250. procedure TGuiShape.LoadFromXML(Node: TXMLNode);
  251. var
  252.  i: Integer;
  253.  Shape: TGeometryShape;
  254.  Child: TXMLNode;
  255.  Move : TPoint2px;
  256.  Scale: TPoint2px;
  257. begin
  258.  FName:= Node.FieldValue['name'];
  259.  // load shapes
  260.  for i:= 0 to Node.ChildCount - 1 do
  261.   if (LowerCase(Node.Child[i].Name) = 'polygon') then
  262.    begin
  263.     Shape:= TPolygonShape.Create();
  264.     Insert(Shape);
  265.     Shape.LoadFromXML(Node.Child[i]);
  266.    end;
  267.  // -> "moveby" node
  268.  Child:= Node.ChildNode['moveby'];
  269.  if (Child <> nil) then
  270.   begin
  271.    Move.x:= ParseInt(Child.FieldValue['x'], 0);
  272.    Move.y:= ParseInt(Child.FieldValue['y'], 0);
  273.   end else Move:= ZeroPoint2px;
  274.  // -> "rescale" node
  275.  Child:= Node.ChildNode['rescale'];
  276.  if (Child <> nil) then
  277.   begin
  278.    Scale.x:= ParseInt(Child.FieldValue['x'], 65536);
  279.    Scale.y:= ParseInt(Child.FieldValue['y'], 65536);
  280.   end else Scale:= Point2px(65536, 65536);
  281.  // move and rescale shapes
  282.  for i:= 0 to Length(Shapes) - 1 do
  283.   begin
  284.    Shapes[i].MoveBy(Move);
  285.    Shapes[i].Rescale(Scale);
  286.   end;
  287. end;
  288. //---------------------------------------------------------------------------
  289. constructor TGuiShapes.Create();
  290. begin
  291.  inherited;
  292.  List:= TAsphyreList.Create();
  293.  List.OnFreeItem:= FreeItem;
  294.  List.OnSortItem:= SortItem;
  295.  List.OnFindItem:= FindItem;
  296. end;
  297. //---------------------------------------------------------------------------
  298. destructor TGuiShapes.Destroy();
  299. begin
  300.  List.Free();
  301.  inherited;
  302. end;
  303. //---------------------------------------------------------------------------
  304. procedure TGuiShapes.FreeItem(List: TAsphyreList; Item: Pointer);
  305. begin
  306.  TGuiShape(Item).Free();
  307. end;
  308. //---------------------------------------------------------------------------
  309. function TGuiShapes.SortItem(List: TAsphyreList; Item1,
  310.  Item2: Pointer): Integer;
  311. begin
  312.  Result:= CompareText(TGuiShape(Item1).Name, TGuiShape(Item2).Name);
  313. end;
  314. //---------------------------------------------------------------------------
  315. function TGuiShapes.FindItem(List: TAsphyreList; Item, User: Pointer): Integer;
  316. begin
  317.  Result:= CompareText(TGuiShape(Item).Name, PChar(User));
  318. end;
  319. //---------------------------------------------------------------------------
  320. function TGuiShapes.GetCount(): Integer;
  321. begin
  322.  Result:= List.Count;
  323. end;
  324. //---------------------------------------------------------------------------
  325. function TGuiShapes.GetItem(Index: Integer): TGuiShape;
  326. begin
  327.  Result:= TGuiShape(List[Index]);
  328. end;
  329. //---------------------------------------------------------------------------
  330. function TGuiShapes.Insert(const Name: string): TGuiShape;
  331. begin
  332.  Result:= TGuiShape.Create(Name);
  333.  List.Insert(Result);
  334. end;
  335. //---------------------------------------------------------------------------
  336. function TGuiShapes.IndexOf(Shape: TGuiShape): Integer;
  337. begin
  338.  Result:= List.IndexOf(Shape);
  339. end;
  340. //---------------------------------------------------------------------------
  341. procedure TGuiShapes.Remove(Index: Integer);
  342. begin
  343.  List.Remove(Index);
  344. end;
  345. //---------------------------------------------------------------------------
  346. procedure TGuiShapes.Clear();
  347. begin
  348.  List.Clear();
  349. end;
  350. //---------------------------------------------------------------------------
  351. function TGuiShapes.IndexOf(const Name: string): Integer;
  352. begin
  353.  Result:= List.FindBy(PChar(Name));
  354. end;
  355. //---------------------------------------------------------------------------
  356. function TGuiShapes.GetShape(const Name: string): TGuiShape;
  357. var
  358.  Index: Integer;
  359. begin
  360.  Index:= IndexOf(Name);
  361.  if (Index <> -1) then Result:= TGuiShape(List[Index]) else Result:= nil;
  362. end;
  363. //---------------------------------------------------------------------------
  364. procedure TGuiShapes.ParseLink(const Link: string);
  365. var
  366.  NodeName : string;
  367.  ShapeName: string;
  368.  Root : TXMLNode;
  369.  Child: TXMLNode;
  370.  Shape: TGuiShape;
  371.  Text : string;
  372.  i, j: Integer;
  373. begin
  374.  Root:= LoadLinkXML(Link);
  375.  if (Root = nil) then Exit;
  376.  if (LowerCase(Root.Name) <> 'unires')  then
  377.   begin
  378.    Root.Free();
  379.    Exit;
  380.   end;
  381.  for i:= 0 to Root.ChildCount - 1 do
  382.   begin
  383.    NodeName:= LowerCase(Root.Child[i].Name);
  384.    if (NodeName = 'shapes') then
  385.     for j:= 0 to Root.Child[i].ChildCount - 1 do
  386.      begin
  387.       Child:= Root.Child[i].Child[j];
  388.       if (LowerCase(Child.Name) = 'shape') then
  389.        begin
  390.         ShapeName:= LowerCase(Child.FieldValue['name']);
  391.         if (Length(ShapeName) > 0) then
  392.          begin
  393.           Shape:= GetShape(ShapeName);
  394.           if (Shape = nil) then Shape:= Insert(ShapeName);
  395.           Shape.LoadFromXML(Child);
  396.          end; // if
  397.        end; // if
  398.      end; // for
  399.    if (NodeName = 'resource') then
  400.     begin
  401.      Text:= Root.Child[i].FieldValue['source'];
  402.      if (Length(Text) > 0) then ParseLink(Text);
  403.     end;
  404.   end;
  405.  Root.Free();
  406. end;
  407. //---------------------------------------------------------------------------
  408. initialization
  409.  GuiShapes:= TGuiShapes.Create();
  410. //---------------------------------------------------------------------------
  411. finalization
  412.  GuiShapes.Free();
  413.  GuiShapes:= nil;
  414. //---------------------------------------------------------------------------
  415. end.