/usr/src/castle-game-engine-6.4/window/castlewindowtouch.pas is in castle-game-engine-src 6.4+dfsg1-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 | {
Copyright 2013-2017 Michalis Kamburelis.
This file is part of "Castle Game Engine".
"Castle Game Engine" is free software; see the file COPYING.txt,
included in this distribution, for details about the copyright.
"Castle Game Engine" is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
----------------------------------------------------------------------------
}
{ Window with controls for easy navigation on touch interfaces. }
unit CastleWindowTouch;
{$I castleconf.inc}
interface
uses Classes, CastleWindow, CastleControls, CastleCameras;
type
TTouchInterface = (
tiNone,
tiCtlWalkCtlRotate,
tiCtlWalkDragRotate,
tiCtlFlyCtlWalkDragRotate,
tiCtlPanXYDragRotate);
{ Full-featured window for rendering (see @link(TCastleWindow))
with optional touch controls, to provide a 3D navigation comfortable
on touch devices (phones, tablets and such).
In addition to all the goodies of the @link(TCastleWindow) functionality,
this class can additionally manage one or two TCastleTouchControl instances.
They will be automatically positioned in the bottom-left
and bottom-right corners of the screen,
and will allow the user to navigate using the default SceneManager.Camera.
In the simplest case, just set @link(AutomaticTouchInterface) to @true,
and the touch controls will automatically adjust to the current
navigation type of the camera (examine, walk, fly...). }
TCastleWindowTouch = class(TCastleWindow)
private
FAutomaticTouchInterface: boolean;
FControl: array [boolean { right side? }] of TCastleTouchControl;
FTouchInterface: TTouchInterface;
FAutomaticWalkTouchCtl: TTouchInterface;
procedure SetTouchInterface(const Value: TTouchInterface);
procedure SetAutomaticTouchInterface(const Value: boolean);
procedure SetAutomaticWalkTouchCtl(const Value: TTouchInterface);
{ Sets touch controls depending on the current navigation mode.
Should be called each time after navigation mode changed. }
procedure UpdateAutomaticTouchInterface;
public
constructor Create(AOwner: TComponent); override;
protected
procedure NavigationInfoChanged; override;
procedure DoUpdate; override;
public
const
DefaultAutomaticWalkTouchCtl = tiCtlWalkDragRotate;
{ Configure touch controls to be displayed on the window.
This automatically manages under the hood 0, 1 or 2
TCastleTouchControl instances, placing them at suitable positions
and handling their operations.
Note that you can set AutomaticTouchInterface = @true to have this property
automatically adjusted. (In which case you should not set this directly.) }
property TouchInterface: TTouchInterface
read FTouchInterface write SetTouchInterface;
published
{ Automatically adjust TouchInterface (showing / hiding proper
touch controls) based on the current navigation type.
The navigation type is obtained from the camera of the default viewport,
see TCastleWindow.NavigationType. }
property AutomaticTouchInterface: boolean
read FAutomaticTouchInterface write SetAutomaticTouchInterface
default false;
{ When using AutomaticTouchInterface = @true,
which touch interface should be used when walking
(since there are multiple sensible choices).
Select between tiCtlWalkCtlRotate or tiCtlWalkDragRotate (default).}
property AutomaticWalkTouchCtl: TTouchInterface
read FAutomaticWalkTouchCtl write SetAutomaticWalkTouchCtl
default DefaultAutomaticWalkTouchCtl;
end;
const
etciNone = tiNone deprecated;
etciCtlWalkCtlRotate = tiCtlWalkCtlRotate deprecated;
etciCtlWalkDragRotate = tiCtlWalkDragRotate deprecated;
etciCtlFlyCtlWalkDragRotate = tiCtlFlyCtlWalkDragRotate deprecated;
etciCtlPanXYDragRotate = tiCtlPanXYDragRotate deprecated;
implementation
uses SysUtils, CastleUIControls, CastleUtils;
constructor TCastleWindowTouch.Create(AOwner: TComponent);
begin
inherited;
FAutomaticWalkTouchCtl := DefaultAutomaticWalkTouchCtl;
end;
procedure TCastleWindowTouch.DoUpdate;
var
Tx, Ty, Tz, TLength, Rx, Ry, Rz, RAngle: Double;
RightSide: boolean;
begin
inherited;
if (FControl[false] <> nil) or
(FControl[true] <> nil) then
begin
Tx := 0; Ty := 0; Tz := 0; TLength := 0;
Rx := 0; Ry := 0; Rz := 0; RAngle := 0;
for RightSide in boolean do
if FControl[RightSide] <> nil then
begin
FControl[RightSide].GetSensorTranslation(Tx, Ty, Tz, TLength);
FControl[RightSide].GetSensorRotation(Rx, Ry, Rz, RAngle);
end;
SceneManager.SensorTranslation(Tx, Ty, Tz, TLength, Fps.SecondsPassed);
SceneManager.SensorRotation(Rx, Ry, Rz, RAngle, Fps.SecondsPassed);
end;
end;
procedure TCastleWindowTouch.SetTouchInterface(const Value: TTouchInterface);
procedure UpdateTouchController(
const RightSide, CtlVisible: boolean; const Mode: TCastleTouchCtlMode);
var
NewControl: TCastleTouchControl;
begin
if FControl[RightSide] <> nil then
begin
if CtlVisible then
FControl[RightSide].TouchMode := Mode else
FreeAndNil(FControl[RightSide]); // this automatically removes FControl[RightSide] from Controls list
end else
if CtlVisible then
begin
NewControl := TCastleTouchControl.Create(self);
NewControl.TouchMode := Mode;
if not RightSide then
NewControl.Position := tpLeft else
NewControl.Position := tpRight;
Controls.InsertFront(NewControl);
FControl[RightSide] := NewControl;
end;
end;
var
WalkCamera: TWalkCamera;
procedure UpdateTouchControllers(
const MouseDragMode: TMouseDragMode;
const LeftVisible, RightVisible: boolean;
const LeftMode: TCastleTouchCtlMode = ctcmWalking;
const RightMode: TCastleTouchCtlMode = ctcmWalking);
begin
UpdateTouchController(false, LeftVisible , LeftMode);
UpdateTouchController(true , RightVisible, RightMode);
if WalkCamera <> nil then
WalkCamera.MouseDragMode := MouseDragMode;
end;
begin
if FTouchInterface <> Value then
begin
FTouchInterface := Value;
WalkCamera := SceneManager.WalkCamera(false);
case Value of
tiNone:
UpdateTouchControllers(mdWalk, false, false);
tiCtlWalkCtlRotate:
UpdateTouchControllers(mdNone, true, true, ctcmWalking, ctcmHeadRotation);
tiCtlWalkDragRotate:
UpdateTouchControllers(mdRotate, false, true, ctcmWalking, ctcmWalking);
tiCtlFlyCtlWalkDragRotate:
UpdateTouchControllers(mdRotate, true, true, ctcmFlyUpdown, ctcmWalking);
tiCtlPanXYDragRotate:
UpdateTouchControllers(mdRotate, false, true, ctcmPanXY, ctcmPanXY);
else raise EInternalError.Create('Value unhandled in SetTouchInterface');
end;
end;
end;
procedure TCastleWindowTouch.UpdateAutomaticTouchInterface;
begin
if AutomaticTouchInterface then
begin
case NavigationType of
ntNone: TouchInterface := tiNone;
ntWalk: TouchInterface := FAutomaticWalkTouchCtl;
ntFly: TouchInterface := tiCtlFlyCtlWalkDragRotate;
ntExamine: TouchInterface := tiCtlPanXYDragRotate;
ntTurntable: TouchInterface := tiCtlPanXYDragRotate;
else raise EInternalError.Create('TCastleWindowTouch.UpdateAutomaticTouchInterface not implemented for this NavigationType value');
end;
end;
end;
procedure TCastleWindowTouch.SetAutomaticTouchInterface(const Value: boolean);
begin
if FAutomaticTouchInterface <> Value then
begin
FAutomaticTouchInterface := Value;
{ change TouchInterface immediately, in case we just set
AutomaticTouchInterface := true }
UpdateAutomaticTouchInterface;
end;
end;
procedure TCastleWindowTouch.SetAutomaticWalkTouchCtl(const Value: TTouchInterface);
begin
if FAutomaticWalkTouchCtl <> Value then
begin
FAutomaticWalkTouchCtl := Value;
UpdateAutomaticTouchInterface;
end;
end;
procedure TCastleWindowTouch.NavigationInfoChanged;
begin
inherited;
UpdateAutomaticTouchInterface;
end;
end.
|