C2GUI.pas
上传用户:yj_qiu
上传日期:2022-08-08
资源大小:23636k
文件大小:24k
源码类别:

游戏引擎

开发平台:

Delphi

  1. (*
  2.  @Abstract(CAST II Engine ACS (GUI) wrapper unit)
  3.  (C) 2006 George "Mirage" Bakhtadze. <a href="http://www.casteng.com">www.casteng.com</a> <br>
  4.  The source code may be used under either MPL 1.1 or LGPL 2.1 license. See included license.txt file <br>
  5.  Unit contains classes which brings the power of ACS GUI library to CAST II engine
  6. *)
  7. {$Include GDefines.inc}
  8. {$Include C2Defines.inc}
  9. unit C2GUI;
  10. interface
  11. uses
  12.   Math,
  13.   TextFile,
  14.   BaseTypes, Basics, Base3D, Props, Models, BaseGraph, BaseClasses, BaseMsg, ItemMsg, ACSBase, GUIFitter,
  15.   Resources, CAST2, C22D, C2Visual, C2Materials, C2Core;
  16. type
  17.   TCFont = class(TItem)
  18.     destructor Destroy; override;
  19.   protected
  20.     FFont: BaseGraph.TFont;
  21.   public
  22.     property Font: BaseGraph.TFont read FFont;
  23.   end;
  24.   TCBitmapFont = class(TCFont)
  25.     constructor Create(AManager: TItemsManager); override;
  26.     procedure AddProperties(const Result: Props.TProperties); override;
  27.     procedure SetProperties(Properties: Props.TProperties); override;
  28.   protected
  29.     procedure ResolveLinks; override;
  30.   end;
  31.   TC2GUIItem = class(TVisible)
  32.     constructor Create(AManager: TItemsManager); override;
  33.     constructor Construct(AManager: TItemsManager); override;
  34.     procedure InitAItem; virtual; abstract;
  35.     procedure HandleMessage(const Msg: TMessage); override;
  36.     procedure OnSceneAdd; override;
  37.     procedure OnSceneLoaded; override;
  38.     procedure AddProperties(const Result: Props.TProperties); override;
  39.     procedure SetProperties(Properties: Props.TProperties); override;
  40.     procedure Render; override;
  41.     procedure Process(const DeltaT: Float); override;
  42.   protected
  43.     Aggregate: ACSBase.TBaseGUIItem;
  44. //    function isActuallyVisible: Boolean; override;
  45.   end;
  46.   T3DFitter = class(TFitter)
  47.   private
  48.     MinControlLength, MaxControlLength, ControlLength: Single;
  49.     PushLocation, PushLocationWorld: TVector3s;                         // Starting position of the item
  50.     PushOrientation: TQuaternion;
  51.     RotAxis: TVector3s;
  52.     PushAxisX, PushAxisY: Single;                                       // Axis in screen space along which the item being moved
  53.     CenterX, CenterY,
  54.     XRBarX, XRBarY, YRBarX, YRBarY, ZRBarX, ZRBarY,
  55.     XBarX, XBarY, YBarX, YBarY, ZBarX, ZBarY: Single; // Control points coordinates
  56.     VisibleAreas: TSet32;
  57.     FCamera: CAST2.TCamera;
  58. //debug
  59.     projsx, projsy: single;
  60.     function GetAreaAt(MX, MY: Single): Integer;
  61.     function Project(Vector: TVector3s; out AX, AY: Single): Boolean;
  62.     procedure SavePushState(MX, MY: Single);
  63.     procedure SetCamera(const Value: CAST2.TCamera);
  64.   protected
  65.     procedure BuildAreas; override;
  66.     procedure HandleMove(AX, AY: Single); override;
  67.     function GetAffectedItem: TItem; override;
  68.     procedure SetAffectedItem(const Value: TItem); override;
  69.   public
  70.     XAColor, YAColor, ZAColor: BaseTypes.TColor;
  71.     AffectedProcessing: CAST2.TProcessing;
  72.     Location: TLocation;
  73.     Orientation: TQuaternion;
  74.     constructor Create(AManager: TItemsManager); override;
  75.     procedure ResetFitter; override;
  76.     function GUIHandleMessage(const Msg: TMessage): Boolean; override;
  77.     procedure Draw; override;
  78.     property Camera: CAST2.TCamera read FCamera write SetCamera;
  79.   end;
  80.   // Returns list of classes introduced by the unit
  81.   function GetUnitClassList: TClassArray;
  82. implementation
  83. uses SysUtils;
  84. function GetUnitClassList: TClassArray;
  85. begin
  86.   Result := GetClassList([T3DFitter]);
  87. end;
  88. { TCFont }
  89. destructor TCFont.Destroy;
  90. begin
  91.   inherited;
  92.   if FFont <> nil then FFont.Free;
  93. end;
  94. { TCBitmapFont }
  95. constructor TCBitmapFont.Create(AManager: TItemsManager);
  96. begin
  97.   inherited;
  98.   FFont := TBitmapFont.Create(AManager);
  99. end;
  100. procedure TCBitmapFont.AddProperties(const Result: Props.TProperties);
  101. begin
  102.   inherited;
  103.   AddItemLink(Result, 'Bitmap',   [], 'TImageResource');
  104.   AddItemLink(Result, 'UV map',   [], 'TUVMapResource');
  105.   AddItemLink(Result, 'Char map', [], 'TCharMapResource');
  106. end;
  107. procedure TCBitmapFont.SetProperties(Properties: Props.TProperties);
  108. begin
  109.   inherited;
  110.   if Properties.Valid('Bitmap')   then SetLinkProperty('Bitmap',   Properties['Bitmap']);
  111.   if Properties.Valid('UV map')   then SetLinkProperty('UV map',   Properties['UV map']);
  112.   if Properties.Valid('Char map') then SetLinkProperty('Char map', Properties['Char map']);
  113.   ResolveLinks;
  114. end;
  115. procedure TCBitmapFont.ResolveLinks;
  116. var LinkedRes: TItem; BFont: TBitmapFont;
  117. begin
  118.   Assert(FFont <> nil, ClassName + '.ResolveLinks: Font is undefined');
  119.   BFont := FFont as TBitmapFont;
  120.   if ResolveLink('UV map', LinkedRes) then begin
  121.     BFont.UVMap    := (LinkedRes as TUVMapResource).Data;
  122.     BFont.TotalUVs := (LinkedRes as TUVMapResource).TotalElements;
  123.   end;
  124.   if ResolveLink('Char map', LinkedRes) then begin
  125.     BFont.CharMap         := (LinkedRes as TCharMapResource).Data;
  126.     BFont.TotalCharacters := (LinkedRes as TCharMapResource).TotalElements;
  127.   end;
  128.   if ResolveLink('Bitmap', LinkedRes) then begin
  129.     BFont.Bitmap       := (LinkedRes as TImageResource).Data;
  130.     BFont.BitmapFormat := (LinkedRes as TImageResource).Format;
  131.     BFont.XScale       := (LinkedRes as TImageResource).Width;
  132.     BFont.YScale       := (LinkedRes as TImageResource).Height;
  133.   end;
  134.   FFont := BFont;
  135. end;
  136. { TC2GUIItem }
  137. constructor TC2GUIItem.Create(AManager: TItemsManager);
  138. begin
  139.   inherited;
  140.   TesselatorKind := tkNone;
  141.   Assert(AManager is TBaseCore, ClassName + '.Create: AManager should be an instance of TBaseCore or one of its descendants');
  142.   Assert(Screen is TC2Screen, ClassName + '.Create: Screen should be an instance of TC2Screen or one of its descendants');
  143.   TC2Screen(Screen).SetCore(AManager as TCore);
  144. end;
  145. constructor TC2GUIItem.Construct(AManager: TItemsManager);
  146. begin
  147.   inherited;
  148. end;
  149. procedure TC2GUIItem.OnSceneAdd;
  150. begin
  151.   inherited;
  152.   if BaseGraph.Screen = nil then begin
  153. //    BaseGraph.Screen := TC2Screen.Create;
  154. //    TC2Screen(BaseGraph.Screen).SetCore(FManager as TCore);
  155.   end;  
  156. end;
  157. procedure TC2GUIItem.OnSceneLoaded;
  158. begin
  159.   inherited;
  160. end;
  161. procedure TC2GUIItem.AddProperties(const Result: Props.TProperties);
  162. begin
  163.   inherited;
  164. {  if AItem <> nil then begin
  165.     LinksPush;
  166. //    AItem.AddProperties(Result);
  167.     Props := Props.TProperties.Create;
  168.     AItem.GetProperties(Props);
  169.     Result.Merge(Props, False);
  170.     Props.Free;
  171.     LinksPop;
  172.   end;}
  173. end;
  174. procedure TC2GUIItem.SetProperties(Properties: Props.TProperties);
  175. begin
  176.   inherited;
  177. {  if AItem <> nil then begin
  178. //    PropagateObjectLinks(AItem);
  179.     AItem.SetProperties(Properties);
  180.   end;}
  181. end;
  182. procedure TC2GUIItem.Render;
  183. var SolidTech, TextTech: TTechnique;
  184. //procedure RenderItem(Item: TC2GUIItem);
  185. //var i, j: Integer;
  186. //begin
  187. //  if Assigned(Item.CurTechnique) then begin
  188. //    TC2Screen(Screen).SetTechnique(pkText,  Item.CurTechnique);
  189. //    TC2Screen(Screen).SetTechnique(pkSolid, Item.CurTechnique);
  190. ////    TC2Screen(Screen).SetTechnique(pkSolid, FManager.Root.GetChildByFullName('Root itemMaterials2D2D Technique 1') as TTechnique);
  191. //    Item.Aggregate.Draw;
  192. //  end;
  193. //  for i := 0 to Item.Aggregate.TotalChilds-1 do begin
  194. //    if (Item.Aggregate.Childs[i] is TBaseGUIItem) and (isVisible in Item.Aggregate.Childs[i].State) then
  195. //      RenderItem(TC2GUIItem(TBaseGUIItem(Item.Aggregate.Childs[i]).AggregatedItem)) else
  196. //        if Item.Aggregate.Childs[i] is TDummyItem then for i := 0 to Item.Aggregate.TotalChilds-1 do
  197. //  end;
  198. //end;
  199.   procedure RenderItem(Item: TItem);
  200.   var i: Integer; C2GUIItem: TC2GUIItem;
  201.   begin
  202.     if not (isVisible in Item.State) then Exit;
  203.     if Item is TBaseGUIItem then begin
  204.         C2GUIItem := TBaseGUIItem(Item).AggregatedItem as TC2GUIItem;
  205.         if Assigned(C2GUIItem.CurTechnique) then begin
  206.           TC2Screen(Screen).SetTechnique(pkText,  C2GUIItem.CurTechnique);
  207.           TC2Screen(Screen).SetTechnique(pkSolid, C2GUIItem.CurTechnique);
  208.       //    TC2Screen(Screen).SetTechnique(pkSolid, FManager.Root.GetChildByFullName('Root itemMaterials2D2D Technique 1') as TTechnique);
  209.           TBaseGUIItem(Item).Draw;
  210.         end;
  211.   //    end;
  212.     end;// else Assert(Item is TDummyItem, Format('Only GUI items or dummy items are allowed in GUI hierarchy, but an item of class %s found', [Item.ClassName]));
  213.     for i := 0 to Item.TotalChilds-1 do RenderItem(Item.Childs[i]);
  214.   end;
  215. begin
  216.   inherited;
  217.   
  218.   SolidTech := TC2Screen(Screen).SolidTechnique;
  219.   TextTech  := TC2Screen(Screen).TextTechnique;
  220.   Screen.CurrentZ := ClearingZ;                           // ToDo: Eliminate it
  221.   RenderItem(Self.Aggregate);
  222.   TC2Screen(Screen).SetTechnique(pkSolid, SolidTech);
  223.   TC2Screen(Screen).SetTechnique(pkText,  TextTech);
  224. end;
  225. procedure TC2GUIItem.HandleMessage(const Msg: TMessage);
  226. begin
  227.   inherited;
  228. //  AItem.HandleMessage(Msg);
  229.   if Msg.ClassType = TAggregateMsg then begin
  230.     Aggregate := TAggregateMsg(Msg).Aggregate as TBaseGUIItem;
  231. //    FState := Aggregate.State;
  232.     if Aggregate is TGUIRootItem then TesselatorKind := tkShared;
  233.   end;
  234. end;
  235. procedure TC2GUIItem.Process(const DeltaT: Float);
  236. begin
  237.   inherited;
  238. //  AItem.Process;
  239. end;
  240. {function TC2GUIItem.isActuallyVisible: Boolean;
  241. var Item: TItem;
  242. begin
  243. //  if not Assigned(Aggregate) then Exit;
  244.   Item := Aggregate;
  245.   while Assigned(Item) and
  246.         not (((Item is TVisible) or (Item is TBaseGUIItem) or (Item is TDummyItem)) and not (isVisible in Item.State)) do
  247.     Item := Item.Parent;
  248.   Result := not Assigned(Item) and Assigned(Aggregate);
  249. end;}
  250. { T3DFitter }
  251. function T3DFitter.GetAreaAt(MX, MY: Single): Integer;
  252. var i: Integer;
  253. begin
  254.   Result := -1;
  255.   for i := haCenter to haZRotate do if IsInArea(MX, MY, Areas[i]) then Result:= i;
  256. end;
  257. function T3DFitter.Project(Vector: TVector3s; out AX, AY: Single): Boolean;
  258. var Transformed: TVector4s;
  259. begin
  260. //  Transformed := Transform4Vector3s(Camera.TotalMatrix, AddVector3s(AffectedProcessing.Position, Transform3Vector3s(CutMatrix3s(AffectedProcessing.Transform), Vector)));
  261.   Transformed := Transform4Vector3s(Camera.TotalMatrix, Transform4Vector33s(AffectedProcessing.Transform, Vector));
  262.   if Transformed.W > 0 then begin
  263.     Transformed.W := 1/Transformed.W;
  264.     AX := Camera.RenderWidth  shr 1 * (1 + Transformed.X * Transformed.W);
  265.     AY := Camera.RenderHeight shr 1 * (1 - Transformed.Y * Transformed.W);
  266.     Result := True;
  267. //    (AX >= 0) and (AY >= 0) and (AX < Camera.ScreenWidth) and (AY < Camera.ScreenHeight);
  268.   end else Result := False;
  269. end;
  270. procedure T3DFitter.SavePushState(MX, MY: Single);
  271. begin
  272.   if not Assigned(AffectedProcessing) then Exit;
  273.   HoverArea := GetAreaAt(MX, MY);
  274.   Project(GetVector3s(0, 0, 0), PushAxisX, PushAxisY);
  275. {  case HoverArea of
  276.     haXMove: Project(GetVector3s(ControlLength, 0, 0), PushX, PushY);
  277.     haYMove: Project(GetVector3s(0, ControlLength, 0), PushX, PushY);
  278.     haZMove: Project(GetVector3s(0, 0, ControlLength), PushX, PushY);
  279.   end;}
  280.   PushX := MX; PushY := MY;
  281.   PushAxisX := (PushX - PushAxisX);// / ControlLength;// / Sqrt( Sqr(PushX - PushAxisX) + Sqr(PushY - PushAxisY) );
  282.   PushAxisY := (PushY - PushAxisY);// / ControlLength;// / Sqrt( Sqr(PushX - PushAxisX) + Sqr(PushY - PushAxisY) );
  283.   PushLocation := AffectedProcessing.Position;
  284.   PushLocationWorld := AffectedProcessing.GetAbsLocation;
  285.   PushOrientation   := AffectedProcessing.Orientation;// AffectedProcessing.GetAbsOrientation;
  286.   case HoverArea of
  287.     haXRotate: RotAxis := AffectedProcessing.RightVector;
  288.     haYRotate: RotAxis := AffectedProcessing.UpVector;
  289.     haZRotate: RotAxis := AffectedProcessing.ForwardVector;
  290.   end;
  291. end;
  292. procedure T3DFitter.SetCamera(const Value: CAST2.TCamera);
  293. begin
  294.   FCamera := Value;
  295.   if FCamera <> nil then begin                            // Expand the control on entire screen to issue GUI events (TGUIDownMsg etc)
  296.     Width  := FCamera.RenderWidth;
  297.     Height := FCamera.RenderHeight;
  298.   end;
  299. end;
  300. procedure T3DFitter.BuildAreas;
  301.   function SquareArea(CX, CY: single): BaseTypes.TArea;
  302.   begin
  303.     Result := GetArea(CX - DefaultSize*0.5, CY - DefaultSize*0.5, CX + DefaultSize*0.5, CY + DefaultSize*0.5);
  304.   end;
  305.   procedure CalcControlLength;                            // Calculate control axis length taking in account min and max values
  306.   var Dist, CX, CY, FX, FY: Single;
  307.   begin
  308.     ControlLength := 1;
  309.     Project(GetVector3s(0, 0, 0), CX, CY);                // Check the maximum possible length of control axis
  310.     Project(Transform3Vector3sTransp(CutMatrix3s(AffectedProcessing.Transform), Camera.RightVector), FX, FY);                  // by projection of the camera's rught vector
  311.     Dist := Sqr(FX - CX) + Sqr(FY - CY);
  312.     if Dist < Sqr(MinControlLength) then ControlLength := MinControlLength / Sqrt(Dist);
  313.     if Dist > Sqr(MaxControlLength) then ControlLength := MaxControlLength / Sqrt(Dist);
  314.   end;
  315. begin
  316.   VisibleAreas := [];
  317.   if (Camera = nil) or (AffectedProcessing = nil) then Exit;
  318.   CalcControlLength;
  319.   if Project(GetVector3s(0, 0, 0), CenterX, CenterY) then Include(VisibleAreas, haCenter);
  320.   Areas[haCenter] := SquareArea(CenterX, CenterY);
  321.   if Project(GetVector3s(ControlLength, 0, 0), XBarX, XBarY) then Include(VisibleAreas, haXMove);
  322.   Areas[haXMove]  := SquareArea(XBarX, XBarY);
  323.   if Project(GetVector3s(0, ControlLength, 0), YBarX, YBarY) then Include(VisibleAreas, haYMove);
  324.   Areas[haYMove]  := SquareArea(YBarX, YBarY);
  325.   if Project(GetVector3s(0, 0, ControlLength), ZBarX, ZBarY) then Include(VisibleAreas, haZMove);
  326.   Areas[haZMove]  := SquareArea(ZBarX, ZBarY);
  327.   if Project(GetVector3s(0, -ControlLength*2, 0), XRBarX, XRBarY) then Include(VisibleAreas, haXRotate);
  328.   Areas[haXRotate]  := SquareArea(XRBarX, XRBarY);
  329.   if Project(GetVector3s(0, 0, -ControlLength*2), YRBarX, YRBarY) then Include(VisibleAreas, haYRotate);
  330.   Areas[haYRotate]  := SquareArea(YRBarX, YRBarY);
  331.   if Project(GetVector3s(-ControlLength*2, 0, 0), ZRBarX, ZRBarY) then Include(VisibleAreas, haZRotate);
  332.   Areas[haZRotate]  := SquareArea(ZRBarX, ZRBarY);
  333. end;
  334. procedure T3DFitter.HandleMove(AX, AY: Single);
  335.   function ScreenToCamera(X, Y: Single): TVector3s;
  336.   begin
  337.     Result.X := (X - 0.5*Camera.RenderWidth ) / Camera.RenderWidth;
  338.     Result.Y := (0.5*Camera.RenderHeight - Y) / Camera.RenderHeight / Camera.CurrentAspectRatio;
  339.     Result.Z := 0.5 / Sin(Camera.HFoV/2)*Cos(Camera.HFoV/2);
  340.   end;
  341.   function CameraToWorld(const V: TVector3s): TVector3s;
  342.   begin
  343.     Result := Transform4Vector3s(InvertMatrix4s(Camera.ViewMatrix), V).XYZ;
  344.   //  d := 0.5*Camera.ScreenWidth / Sin(Camera.HFoV/2)*Cos(Camera.HFoV/2);
  345.   //  Result := AddVector3s(Camera.GetAbsLocation, ScaleVector3s(Camera.ForwardVector, -d*0));
  346.   end;
  347.   procedure DoMove;
  348.   var
  349.     ReverseMat: TMatrix4s;
  350.     MV, WP1, WP2, SP1, SP2, Axis: TVector3s;
  351.     d, wd, CosA, SinB, SinC: Extended;
  352.     Op: TItemMoveOp;
  353.   begin
  354.     case HoverArea of
  355.       haCenter: ;
  356.       haXMove: begin                                                          // AX/|AX| * MV * cos
  357.         Axis := AffectedProcessing.RightVector;
  358.       end;
  359.       haYMove: Axis := AffectedProcessing.UpVector;
  360.       haZMove: Axis := AffectedProcessing.ForwardVector;
  361.     end;
  362.     wd := Sqr(PushAxisX) + Sqr(PushAxisY);
  363.     d  := (PushAxisX * (AX - PushX) + PushAxisY * (AY - PushY)) / wd; // |AxP|/|MV|*cos
  364. //    d :=
  365.     MV.X := PushAxisX * d;
  366.     MV.Y := PushAxisY * d;                                                    // MV - move vector projected on PushAxis
  367.     projsx := PushX + MV.X;
  368.     projsy := PushY + MV.Y;
  369.     if Sqr(MV.X) + Sqr(MV.Y) > Sqr(0.1) then begin
  370.       SP1 := CameraToWorld(ScreenToCamera(PushX, PushY));
  371.       SP2 := CameraToWorld(ScreenToCamera(PushX + MV.X, PushY + MV.Y));
  372.       WP1 := AddVector3s(PushLocationWorld, ScaleVector3s(Axis, ControlLength));
  373.       d   := Sqrt(SqrMagnitude(SubVector3s(WP1, Camera.Position))/
  374.                   SqrMagnitude(SubVector3s(SP1, Camera.Position)));
  375.       WP2 := AddVector3s(Camera.Position, ScaleVector3s(SubVector3s(SP2, Camera.Position), d));
  376.       wd  := Sqrt(SqrMagnitude(SubVector3s(WP2, WP1)));
  377.   // sin(b)/wd = sin(c)/x => x = sin(c)*wd/sin(b)
  378.       CosA := DotProductVector3s(Axis, SubVector3s(WP2, WP1))/wd;
  379.       SinB := Sqrt(1 - Sqr(DotProductVector3s(Axis, NormalizeVector3s(SubVector3s(WP2, Camera.Position)))));
  380.       SinC := Sqrt(1 - Sqr(DotProductVector3s(SubVector3s(WP2, WP1), NormalizeVector3s(SubVector3s(WP2, Camera.Position)))/wd));
  381.       wd := wd * SinC / SinB * Sign(CosA);
  382.   //    Location := AddVector3s(PushLocation, ScaleVector3s(Axis, wd));
  383.       if (AffectedProcessing.Parent is CAST2.TProcessing) then
  384.         ReverseMat := InvertMatrix4s(CAST2.TProcessing(AffectedProcessing.Parent).Transform)
  385.       else
  386.         ReverseMat := IdentityMatrix4s;
  387.       Location := Transform4Vector3s(ReverseMat, AddVector3s(PushLocationWorld, ScaleVector3s(Axis, wd)));
  388.     end else Location := GetLocationFromVec3s(PushLocation);
  389.     if Assigned(AffectedItem) then
  390.       if UseOperations then begin
  391.         Op := TItemMoveOp.Create;
  392.         if Op.Init(AffectedProcessing, Location) then
  393.           SendMessage(TOperationMsg.Create(Op), nil, [mfCore])
  394.         else
  395.           Op.Free;
  396.       end else
  397.         AffectedProcessing.Location := Location;
  398.   end;
  399.   procedure DoRotate;
  400.   var
  401. //    ReverseMat: TMatrix4s;
  402.     NewPos, OldPos: TVector3s;
  403.     Ang, t: Extended;
  404.     Quat: TQuaternion;
  405.     Op: TItemRotateOp;
  406.     function GetPointOnPlane(UseOld: Boolean; var Res: TVector3s): Boolean;
  407.     var d, wd, PX, PY: Extended; W: TVector3s;
  408.     begin
  409.       Result := True;
  410.       if UseOld then begin
  411.         PX := PushX; PY := PushY;
  412.       end else begin
  413.         PX := AX; PY := AY;
  414.       end;
  415.       W := Camera.Position;
  416.       d := DotProductVector3s(RotAxis, SubVector3s(AffectedProcessing.GetAbsLocation, W));
  417.       W := SubVector3s(CameraToWorld(ScreenToCamera(PX, PY)), W);
  418.       wd := DotProductVector3s(RotAxis, W);
  419.       if Abs(wd) > epsilon then
  420.         Res := AddVector3s(Camera.Position, ScaleVector3s(W, d/wd)) else begin
  421.           if UseOld then
  422.             AddVector3s(Res, AffectedProcessing.GetAbsLocation, RotAxis) else
  423.               Res := CameraToWorld(ScreenToCamera(PX, PY));
  424.         end;
  425.     end;
  426.   begin
  427.     if not GetPointOnPlane(True, OldPos) or not GetPointOnPlane(False, NewPos) then Exit;
  428.     SubVector3s(OldPos, OldPos, AffectedProcessing.GetAbsLocation);
  429.     SubVector3s(NewPos, NewPos, AffectedProcessing.GetAbsLocation);
  430.     t := DotProductVector3s(OldPos, NewPos) / Sqrt(SqrMagnitude(OldPos)) / Sqrt(SqrMagnitude(NewPos));
  431.     if (t > 1) then t := 1;
  432.     if (t < -1) then t := -1;
  433.     Ang := -ArcCos(t);
  434.     if DotProductVector3s(CrossProductVector3s(OldPos, NewPos), RotAxis) > 0 then Ang := - Ang;
  435.     Quat := GetQuaternion(Ang, RotAxis);
  436. {      if (AffectedProcessing.Parent is TProcessing) then
  437.         ReverseMat := RotTransMatrixInvert(TProcessing(AffectedProcessing.Parent).Transform) else
  438.           ReverseMat := IdentityMatrix4s;}
  439.     if Assigned(AffectedItem) then
  440.       if UseOperations then begin
  441.         Op := TItemRotateOp.Create;
  442.         if Op.Init(AffectedProcessing, NormalizeQuaternion(MulQuaternion(Quat, PushOrientation))) then
  443.           SendMessage(TOperationMsg.Create(Op), nil, [mfCore])
  444.         else
  445.           Op.Free;
  446.       end else
  447.         AffectedProcessing.Orientation := NormalizeQuaternion(MulQuaternion(Quat, PushOrientation));
  448.   end;
  449. begin
  450.   if (Camera = nil) or (AffectedProcessing = nil) or (HoverArea = -1) then Exit;
  451.   case HoverArea of
  452.     haCenter, haXMove, haYMove, haZMove: DoMove;
  453.     haXRotate, haYRotate, haZRotate: DoRotate;
  454.   end;
  455. end;
  456. function T3DFitter.GetAffectedItem: TItem;
  457. begin
  458.   Result := AffectedProcessing;
  459. end;
  460. procedure T3DFitter.SetAffectedItem(const Value: TItem);
  461. begin
  462.   if Value is CAST2.TProcessing then
  463.     AffectedProcessing := Value as CAST2.TProcessing else begin
  464.       {$IFDEF LOGGING} Log.Log(ClassName + '.SetAffectedItem: Affected item is not a TProcessing', lkError); {$ENDIF}
  465.     end;
  466.   BuildAreas;  
  467. end;
  468. constructor T3DFitter.Create(AManager: TItemsManager);
  469. begin
  470.   inherited;
  471.   XAColor.C := $FF0000FF;
  472.   YAColor.C := $FF00FF00;
  473.   ZAColor.C := $FFFF0000;
  474.   MinControlLength := 16;
  475.   MaxControlLength := 64;
  476. end;
  477. procedure T3DFitter.ResetFitter;
  478. begin
  479.   inherited;
  480.   FCamera := nil;
  481. end;
  482. function T3DFitter.GUIHandleMessage(const Msg: TMessage): Boolean;
  483. var i: Integer; OMX, OMY: Integer; MX, MY: Single; Processed: Boolean;
  484. begin
  485.   if Msg is TMouseMsg then with TMouseMsg(Msg) do begin
  486.     OMX := X; OMY := Y;
  487.     MX  := X; MY  := Y;
  488.     ScreenToClient(MX, MY);
  489.   end else begin
  490.     OMX := 0; OMY := 0;
  491.   end;
  492.   Result := inherited GUIHandleMessage(Msg);
  493.   if not Result then Exit;
  494.   if Msg is TMouseMsg then with TMouseMsg(Msg) do begin
  495.     Processed := False;
  496.     if (Msg.ClassType = TMouseDownMsg) then begin
  497.       if Hover then begin
  498.         SavePushState(MX, MY);
  499.         Processed := True;
  500.       end;
  501.     end else if (Msg.ClassType = TMouseMoveMsg) then begin
  502.       Processed := True;
  503.       if Pushed then HandleMove(MX, MY) else begin
  504.         HoverArea := -1;
  505.         for i := haCenter to haZRotate do if IsInArea(MX, MY, Areas[i]) then HoverArea := i;
  506.         Processed := HoverArea <> -1;
  507.       end;
  508.     end;
  509.     if not Processed then begin                           // Restore mouse coordinates to allow the message handling by other controls
  510.       X := OMX;
  511.       Y := OMY;
  512.     end;
  513.   end;
  514. end;
  515. procedure T3DFitter.Draw;
  516. begin
  517.   if not (haCenter in VisibleAreas) then Exit;
  518.   inherited;
  519.   BuildAreas;
  520.   if haCenter = HoverArea then Screen.SetColor(Color) else Screen.SetColor(NormalColor);
  521.   Screen.Bar(Areas[haCenter].X1, Areas[haCenter].Y1, Areas[haCenter].X2, Areas[haCenter].Y2);
  522.   if haXMove in VisibleAreas then begin
  523.     if haXMove = HoverArea then Screen.SetColor(Color) else Screen.SetColor(XAColor);
  524.     Screen.Line(CenterX, CenterY, XBarX, XBarY);
  525.     Screen.Bar(Areas[haXMove].X1, Areas[haXMove].Y1, Areas[haXMove].X2, Areas[haXMove].Y2);
  526.   end;
  527.   if haYMove in VisibleAreas then begin
  528.     if haYMove = HoverArea then Screen.SetColor(Color) else Screen.SetColor(YAColor);
  529.     Screen.Line(CenterX, CenterY, YBarX, YBarY);
  530.     Screen.Bar(Areas[haYMove].X1, Areas[haYMove].Y1, Areas[haYMove].X2, Areas[haYMove].Y2);
  531.   end;
  532.   if haZMove in VisibleAreas then begin
  533.     if haZMove = HoverArea then Screen.SetColor(Color) else Screen.SetColor(ZAColor);
  534.     Screen.Line(CenterX, CenterY, ZBarX, ZBarY);
  535.     Screen.Bar(Areas[haZMove].X1, Areas[haZMove].Y1, Areas[haZMove].X2, Areas[haZMove].Y2);
  536.   end;
  537.   if haXRotate in VisibleAreas then begin
  538.     if haXRotate = HoverArea then Screen.SetColor(Color) else Screen.SetColor(XAColor);
  539.     Screen.Line(CenterX, CenterY, XRBarX, XRBarY);
  540.     Screen.Bar(Areas[haXRotate].X1+RoundShift, Areas[haXRotate].Y1, Areas[haXRotate].X2-RoundShift, Areas[haXRotate].Y2);
  541.     Screen.Bar(Areas[haXRotate].X1, Areas[haXRotate].Y1+RoundShift, Areas[haXRotate].X2, Areas[haXRotate].Y2-RoundShift);
  542.   end;
  543.   if haYRotate in VisibleAreas then begin
  544.     if haYRotate = HoverArea then Screen.SetColor(Color) else Screen.SetColor(YAColor);
  545.     Screen.Line(CenterX, CenterY, YRBarX, YRBarY);
  546.     Screen.Bar(Areas[haYRotate].X1+RoundShift, Areas[haYRotate].Y1, Areas[haYRotate].X2-RoundShift, Areas[haYRotate].Y2);
  547.     Screen.Bar(Areas[haYRotate].X1, Areas[haYRotate].Y1+RoundShift, Areas[haYRotate].X2, Areas[haYRotate].Y2-RoundShift);
  548.   end;
  549.   if haZRotate in VisibleAreas then begin
  550.     if haZRotate = HoverArea then Screen.SetColor(Color) else Screen.SetColor(ZAColor);
  551.     Screen.Line(CenterX, CenterY, ZRBarX, ZRBarY);
  552.     Screen.Bar(Areas[haZRotate].X1+RoundShift, Areas[haZRotate].Y1, Areas[haZRotate].X2-RoundShift, Areas[haZRotate].Y2);
  553.     Screen.Bar(Areas[haZRotate].X1, Areas[haZRotate].Y1+RoundShift, Areas[haZRotate].X2, Areas[haZRotate].Y2-RoundShift);
  554.   end;
  555.   if Pushed then begin
  556.     Screen.SetColor(GetColor($FFFFFF00));
  557. //    Screen.Bar(PushX - 2, PushY - 2, PushX + 2, PushY + 2);
  558.     Screen.SetColor(GetColor($FF00FF00));
  559.     Screen.Bar(projsx - 2, projsy - 2, projsx + 2, projsy + 2);
  560.   end;
  561. end;
  562. initialization
  563.   ACSBase.AggregatedClass := TC2GUIItem;
  564.   GlobalClassList.Add('C2GUI', GetUnitClassList);
  565. end.