UDN
Search public documentation:
DevelopmentKitGemsCreatingAMouseInterfaceKR
English Translation
日本語訳
中国翻译
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
日本語訳
中国翻译
Interested in the Unreal Engine?
Visit the Unreal Technology site.
Looking for jobs and company info?
Check out the Epic games site.
Questions about support via UDN?
Contact the UDN Staff
마우스 인터페이스 만들기
문서 변경내역: James Tan 작성. 홍성진 번역.
UDK 2011년 1월 버전으로 최종 테스팅, PC 호환
개요
화면에 커서 추가하기
언리얼스크립트
자체 마우스 포지셔닝 코드를 만들 수 있습니다. 어떤 식이냐면, 변경된 것이 있는지 알아보기 위해 aMouseX 와 aMouseY 를 폴링하는 커스텀 플레이어 인풋을 추가하는 식입니다. 변경된 것이 있으면 MousePosition 변수에 덧붙인다음 마우스 커서가 화면 범위내에 있도록 제한(clamp)합니다. 새 GameInfo 는 이렇습니다. 사용할 HUD 클래스와 PlayerController 클래스를 정의하는 단순 GameInfo 입니다.
class MouseInterfaceGameInfo extends GameInfo;
defaultproperties
{
// HUD 타입을 마우스 인터페이스 HUD 로 설정
HUDType=class'MouseInterfaceHUD'
// 플레이어 콘트롤러를 마우스 인터페이스 플레이어 콘트롤러로 설정
PlayerControllerClass=class'MouseInterfacePlayerController'
}
class MouseInterfaceHUD extends HUD;
// 화면상에 커서를 나타내는 텍스처
var const Texture2D CursorTexture;
// 커서의 색
var const Color CursorColor;
event PostRender()
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
// 가용 PlayerOwner 및 CursorTexture 가 있는지 확인
if (PlayerOwner != None && CursorTexture != None)
{
// MouseInterfacePlayerInput 를 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
if (MouseInterfacePlayerInput != None)
{
// 마우스 위치로 캔버스 위치 설정
Canvas.SetPos(MouseInterfacePlayerInput.MousePosition.X, MouseInterfacePlayerInput.MousePosition.Y);
// 커서 컬러 설정
Canvas.DrawColor = CursorColor;
// 화면상에 텍스처 그리기
Canvas.DrawTile(CursorTexture, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
}
}
Super.PostRender();
}
defaultproperties
{
CursorColor=(R=255,G=255,B=255,A=255)
CursorTexture=Texture2D'EngineResources.Cursors.Arrow'
}
- PostRender 가 실행되면 PlayerOwner 에서 새 PlayerInput 을 구하는데, 이는 PlayerController 입니다.
- 새 PlayerInput 이 있으면, Canvas 위치를 새 PlayerInput 내에 저장된 MousePosition 으로 설정합니다.
- 그런 다음 컬러를 default properties 내에 정의된 커서 컬러에 설정합니다.
- 마지막으로 마우스 커서를 나타내는 텍스처를 그립니다.
class MouseInterfacePlayerController extends PlayerController;
// 이 함수 null
function UpdateRotation(float DeltaTime);
defaultproperties
{
// 인풋 클래스를 마우스 인터페이스 플레이어 인풋으로 설정
InputClass=class'MouseInterfacePlayerInput'
}
class MouseInterfacePlayerInput extends PlayerInput;
// 저장된 마우스 위치. 다른 클래스가 변경은 못해도 접근은 할 수 있도록 private write 로 설정.
var PrivateWrite IntPoint MousePosition;
event PlayerInput(float DeltaTime)
{
// 마우스 처리
// 가용 HUD 있는지 확인
if (myHUD != None)
{
// 마우스 위치에 aMouseX 를 더한 다음 뷰포트 폭 내로 제한
MousePosition.X = Clamp(MousePosition.X + aMouseX, 0, myHUD.SizeX);
// 마우스 위치에 aMouseY 를 더한 다음 뷰포트 높이 내로 제한
MousePosition.Y = Clamp(MousePosition.Y - aMouseY, 0, myHUD.SizeY);
}
Super.PlayerInput(DeltaTime);
}
defaultproperties
{
}
- PlayerInput 이 실행되면 마우스 위치 조절을 처리합니다.
- HUD 는 마우스 위치를 뷰포트 내로 제한시키기 위해 필요합니다. PlayerInput 은 PlayerController 내의 오브젝트이므로, PlayerController 내의 변수에 직접 접근할 수 있습니다.
- input config 내에 묶여 있는 aMouseX 및 aMouseY 를 사용하여 그 값을 우리 MousePosition 변수에 더합니다. 올바른 결과를 내기 위해서는 세로 계산을 거꾸로 해야 합니다.
- 결과를 제한하여 마우스 위치가 항상 뷰포트 내에 있도록 합니다.
스케일폼
마우스 위치를 폴링하는 데는 스케일폼을 사용할 수도 있습니다. 특히 이 젬에서 대부분의 스크립트는 거의 그대로입니다. 예외라면 스케일폼을 사용하는 경우, 위에서 만든 커스텀 플레이어 인풋 클래스는 더이상 마우스 변화를 폴링하지 않는다는 점입니다. 대신 스케일폼이 마우스 위치 변화를 감지하면 새 위치를 언리얼스크립트로 넘겨줍니다. 어도비 플래시로 쓴 액션스크립트입니다. 마우스가 움직이면 액션스크립트는 커서를 호출한 레이어의 위치를 스케일폼의 마우스 위치로 설정한 다음, 언리얼스크립트에도 스케일폼의 마우스 위치를 전송합니다.
import flash.external.ExternalInterface;
// 보통의 "윈도우" 포인터 숨김
Mouse.hide();
var mouseListener:Object = new Object();
mouseListener.onMouseMove = function() {
// 커서 인스턴스 위치를 마우스 위치로 설정
cursor._x = _root._xmouse;
cursor._y = _root._ymouse;
// 언리얼스크립트에 새 마우스 좌표 전달
ExternalInterface.call("UpdateMousePosition", _root._xmouse, _root._ymouse);
updateAfterEvent();
};
Mouse.addListener(mouseListener);
class MouseInterfaceGFx extends GFxMoviePlayer;
var MouseInterfaceHUD MouseInterfaceHUD;
function Init(optional LocalPlayer LocalPlayer)
{
// 스케일폼 무비 초기화
Super.Init(LocalPlayer);
Start();
Advance(0);
}
event UpdateMousePosition(float X, float Y)
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
if (MouseInterfaceHUD != None && MouseInterfaceHUD.PlayerOwner != None)
{
MouseInterfacePlayerInput = MouseInterfacePlayerInput(MouseInterfaceHUD.PlayerOwner.PlayerInput);
if (MouseInterfacePlayerInput != None)
{
MouseInterfacePlayerInput.SetMousePosition(X, Y);
}
}
}
defaultproperties
{
bDisplayWithHudOff=false
TimingMode=TM_Game
MovieInfo=SwfMovie'MouseInterfaceContent.MouseInterfaceCursor'
bPauseGameWhileActive=false
}
class MouseInterfaceHUD extends HUD;
// 화면상의 커서를 나타내는 텍스처
var const Texture2D CursorTexture;
// 커서의 색
var const Color CursorColor;
// 스케일폼 사용?
var bool UsingScaleForm;
// 스케일폼 마우스 무비
var MouseInterfaceGFx MouseInterfaceGFx;
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
// 스케일폼을 사용중이라면, 스케일폼 무비를 생성
if (UsingScaleForm)
{
MouseInterfaceGFx = new () class'MouseInterfaceGFx';
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.MouseInterfaceHUD = Self;
MouseInterfaceGFx.SetTimingMode(TM_Game);
MouseInterfaceGFx.Init(class'Engine'.static.GetEngine().GamePlayers[MouseInterfaceGFx.LocalPlayerOwnerIndex]);
}
}
}
simulated event Destroyed()
{
Super.Destroyed();
// 스케일폼 무비가 존재하면, 소멸시킴
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.Close(true);
MouseInterfaceGFx = None;
}
}
function PreCalcValues()
{
Super.PreCalcValues();
// 스케일폼 무비가 존재하면, 뷰포트를 리셋시키고, 스케일 모드와 얼라인먼트를
// 화면 해상도에 일치.
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.SetViewport(0, 0, SizeX, SizeY);
MouseInterfaceGFx.SetViewScaleMode(SM_NoScale);
MouseInterfaceGFx.SetAlignment(Align_TopLeft);
}
}
event PostRender()
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local MouseInterfaceInteractionInterface MouseInteractionInterface;
local Vector HitLocation, HitNormal;
Super.PostRender();
// 스케일폼을 사용중이지 않고 적합한 커서가 있음을 확인
if (!UsingScaleForm && CursorTexture != None)
{
// 적합한 PlayerOwner 가 있는지 확인
if (PlayerOwner != None)
{
// MouseInterfacePlayerInput 을 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
// 스케일폼을 사용중이지 않고 적합한 커서 텍스처가 있으면, 렌더.
if (MouseInterfacePlayerInput != None)
{
// 캔버스 위치를 마우스 위치로 설정
Canvas.SetPos(MouseInterfacePlayerInput.MousePosition.X, MouseInterfacePlayerInput.MousePosition.Y);
// 커서 컬러를 설정
Canvas.DrawColor = CursorColor;
// 화면상에 텍스처 그리기
Canvas.DrawTile(CursorTexture, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
}
}
}
Super.PostRender();
}
class MouseInterfacePlayerInput extends PlayerInput;
var PrivateWrite IntPoint MousePosition;
event PlayerInput(float DeltaTime)
{
local MouseInterfaceHUD MouseInterfaceHUD;
// 마우스 이동 처리
// 적절한 HUD 클래스가 있는지 검사
MouseInterfaceHUD = MouseInterfaceHUD(MyHUD);
if (MouseInterfaceHUD != None)
{
if (!MouseInterfaceHUD.UsingScaleForm)
{
// 스케일폼을 사용중이지 않으면, 마우스 인풋을 직접 읽음.
// 마우스 위치에 aMouseX 를 더한 다음 뷰포트 폭 범위 안으로 제한
MousePosition.X = Clamp(MousePosition.X + aMouseX, 0, MouseInterfaceHUD.SizeX);
// 마우스 위치에 aMouseY 를 더한 다음 뷰포트 높이 범위 안으로 제한
MousePosition.Y = Clamp(MousePosition.Y - aMouseY, 0, MouseInterfaceHUD.SizeY);
}
}
Super.PlayerInput(DeltaTime);
}
function SetMousePosition(int X, int Y)
{
if (MyHUD != None)
{
MousePosition.X = Clamp(X, 0, MyHUD.SizeX);
MousePosition.Y = Clamp(Y, 0, MyHUD.SizeY);
}
}
defaultproperties
{
}
관련 토픽
마우스 2D 좌표를 원해!
마우스 2D 좌표를 구하려면, MouseInterfacePlayerInput 에 접근해야 합니다. HUD 내에서 구하려면.
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local IntPoint MousePosition;
// 적합한 PlayerOwner 가 있는지 확인
if (PlayerOwner != None)
{
// MouseInterfacePlayerInput 를 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
if (MouseInterfacePlayerInput != None)
{
// 마우스 X 위치를 구하고/사용
MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
// 마우스 Y 위치를 구하고/사용
MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
}
}
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local IntPoint MousePosition;
// MouseInterfacePlayerInput 를 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerInput);
if (MouseInterfacePlayerInput != None)
{
// 마우스 X 위치를 구하고/사용
MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
// 마우스 Y 위치를 구하고/사용
MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
}
관련 토픽
마우스 인터액션 인터페이스 추가하기
interface MouseInterfaceInteractionInterface; // 왼쪽 마우스 버튼이 눌렸을 때 호출 function MouseLeftPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal); // 왼쪽 마우스 버튼이 놓였을 때 호출 function MouseLeftReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 오른쪽 마우스 버튼이 눌렸을 때 호출 function MouseRightPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal); // 오른쪽 마우스 버튼이 놓였을 때 호출 function MouseRightReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 가운데 마우스 버튼이 눌렸을 때 호출 function MouseMiddlePressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal); // 가운데 마우스 버튼이 놓였을 때 호출 function MouseMiddleReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 휠 버튼을 위로 굴렸을 때 호출 function MouseScrollUp(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 휠 버튼을 아래로 굴렸을 때 호출 function MouseScrollDown(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 마우스가 액터 위로 움직였을 때 호출 function MouseOver(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 마우스가 액터 (위에 있다가) 밖으로 움직였을 때 호출 function MouseOut(Vector MouseWorldOrigin, Vector MouseWorldDirection); // 마우스 추적 적중 위치를 반환 function Vector GetHitLocation(); // 마우스 추적 적중 노멀을 반환 function Vector GetHitNormal(); // 캔버스 내 deprojection 으로 계산된 마우스 월드 원점을 반환 function Vector GetMouseWorldOrigin(); // 캔버스 내 deprojection 으로 계산된 마우스 월드 방향을 반환 function Vector GetMouseWorldDirection();
관련 토픽
마우스 상호작용을 내기 위해 PlayerController 와 HUD 사용하기
class MouseInterfacePlayerController extends PlayerController;
// 마우스 이벤트 열거형
enum EMouseEvent
{
LeftMouseButton,
RightMouseButton,
MiddleMouseButton,
ScrollWheelUp,
ScrollWheelDown,
};
// 마우스 입력 처리
function HandleMouseInput(EMouseEvent MouseEvent, EInputEvent InputEvent)
{
local MouseInterfaceHUD MouseInterfaceHUD;
// HUD 구하기 위해 형 변환
MouseInterfaceHUD = MouseInterfaceHUD(myHUD);
if (MouseInterfaceHUD != None)
{
// 이것의 입력 종류 검출
if (InputEvent == IE_Pressed)
{
// pressed 이벤트 처리
switch (MouseEvent)
{
case LeftMouseButton:
MouseInterfaceHUD.PendingLeftPressed = true;
break;
case RightMouseButton:
MouseInterfaceHUD.PendingRightPressed = true;
break;
case MiddleMouseButton:
MouseInterfaceHUD.PendingMiddlePressed = true;
break;
case ScrollWheelUp:
MouseInterfaceHUD.PendingScrollUp = true;
break;
case ScrollWheelDown:
MouseInterfaceHUD.PendingScrollDown = true;
break;
default:
break;
}
}
else if (InputEvent == IE_Released)
{
// released 이벤트 처리
switch (MouseEvent)
{
case LeftMouseButton:
MouseInterfaceHUD.PendingLeftReleased = true;
break;
case RightMouseButton:
MouseInterfaceHUD.PendingRightReleased = true;
break;
case MiddleMouseButton:
MouseInterfaceHUD.PendingMiddleReleased = true;
break;
default:
break;
}
}
}
}
// 마우스 좌우버튼을 눌렀을 때 사용할 후크
exec function StartFire(optional byte FireModeNum)
{
HandleMouseInput((FireModeNum == 0) ? LeftMouseButton : RightMouseButton, IE_Pressed);
Super.StartFire(FireModeNum);
}
// 마우스 좌우버튼을 놓았을 때 사용할 후크
exec function StopFire(optional byte FireModeNum)
{
HandleMouseInput((FireModeNum == 0) ? LeftMouseButton : RightMouseButton, IE_Released);
Super.StopFire(FireModeNum);
}
// 가운데 마우스 버튼이 눌렸을 때 호출
exec function MiddleMousePressed()
{
HandleMouseInput(MiddleMouseButton, IE_Pressed);
}
// 가운데 마우스 버튼이 놓였을 때 호출
exec function MiddleMouseReleased()
{
HandleMouseInput(MiddleMouseButton, IE_Released);
}
// 휠 버튼을 위로 굴렸을 때 호출
exec function MiddleMouseScrollUp()
{
HandleMouseInput(ScrollWheelUp, IE_Pressed);
}
// 휠 버튼을 아래로 굴렸을 때 호출
exec function MiddleMouseScrollDown()
{
HandleMouseInput(ScrollWheelDown, IE_Pressed);
}
// 이 함수 null
function UpdateRotation(float DeltaTime);
// 이 함수에 있을 때는 StartFire 가 전역적으로 호출되지 않기에 이 상태 덮어쓰기
auto state PlayerWaiting
{
exec function StartFire(optional byte FireModeNum)
{
Global.StartFire(FireModeNum);
}
}
defaultproperties
{
// 인풋 클래스를 마우스 인터페이스 플레이어 인풋으로 설정
InputClass=class'MouseInterfacePlayerInput'
}
- exec 함수는 키 바인드를 통해 호출됩니다.
- 어느 exec 함수라도 호출되면, 거기서 HandleMouseInput 을 호출하고, 그리고서 액션을 HUD 로 유예시킵니다.
; 기존 마우스 스크롤 업/다운 키 바인드 제거 -Bindings=(Name="MouseScrollUp",Command="PrevWeapon") -Bindings=(Name="MouseScrollDown",Command="NextWeapon") ; 가운데 마우스 버튼 및 새 스크롤 휠 키 바인드 추가 .Bindings=(Name="MiddleMouseButton",Command="MiddleMousePressed | OnRelease MiddleMouseReleased") .Bindings=(Name="MouseScrollUp",Command="GBA_PrevWeapon | MiddleMouseScrollUp") .Bindings=(Name="MouseScrollDown",Command="GBA_NextWeapon | MiddleMouseScrollDown")
class MouseInterfaceHUD extends HUD;
// 화면상의 커서를 나타내는 텍스처
var const Texture2D CursorTexture;
// 커서의 컬러
var const Color CursorColor;
// 계류중인 마우스 왼쪽버튼 pressed 이벤트
var bool PendingLeftPressed;
// 계류중인 마우스 왼쪽버튼 released 이벤트
var bool PendingLeftReleased;
// 계류중인 마우스 오른쪽버튼 pressed 이벤트
var bool PendingRightPressed;
// 계류중인 마우스 오른쪽버튼 released 이벤트
var bool PendingRightReleased;
// 계류중인 마우스 가운데버튼 pressed 이벤트
var bool PendingMiddlePressed;
// 계류중인 마우스 가운데버튼 released 이벤트
var bool PendingMiddleReleased;
// 계류중인 마우스 휠 버튼 scroll up 이벤트
var bool PendingScrollUp;
// 계류중인 마우스 휠 버튼 scroll down 이벤트
var bool PendingScrollDown;
// 캐시된 마우스 월드 원점
var Vector CachedMouseWorldOrigin;
// 캐시된 마우스 월드 방향
var Vector CachedMouseWorldDirection;
// 지난 마우스 인터액션 인터페이스
var MouseInterfaceInteractionInterface LastMouseInteractionInterface;
// Use ScaleForm?
var bool UsingScaleForm;
// Scaleform mouse movie
var MouseInterfaceGFx MouseInterfaceGFx;
simulated event PostBeginPlay()
{
Super.PostBeginPlay();
// 스케일폼을 사용중이라면, 스케일폼 무비 생성
if (UsingScaleForm)
{
MouseInterfaceGFx = new () class'MouseInterfaceGFx';
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.MouseInterfaceHUD = Self;
MouseInterfaceGFx.SetTimingMode(TM_Game);
MouseInterfaceGFx.Init(class'Engine'.static.GetEngine().GamePlayers[MouseInterfaceGFx.LocalPlayerOwnerIndex]);
}
}
}
simulated event Destroyed()
{
Super.Destroyed();
// 스케일폼 무비가 존재하면, 소멸시킴
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.Close(true);
MouseInterfaceGFx = None;
}
}
function PreCalcValues()
{
Super.PreCalcValues();
// 스케일폼 무비가 존재하면, 그 뷰포트를 리셋시키고, 스케일 모드와 얼라인먼트를
// 화면 해상도에 일치
if (MouseInterfaceGFx != None)
{
MouseInterfaceGFx.SetViewport(0, 0, SizeX, SizeY);
MouseInterfaceGFx.SetViewScaleMode(SM_NoScale);
MouseInterfaceGFx.SetAlignment(Align_TopLeft);
}
}
event PostRender()
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local MouseInterfaceInteractionInterface MouseInteractionInterface;
local Vector HitLocation, HitNormal;
Super.PostRender();
// Ensure that we aren't using ScaleForm and that we have a valid cursor
if (!UsingScaleForm && CursorTexture != None)
{
// 가용 PlayerOwner 있는지 확인
if (PlayerOwner != None)
{
// MouseInterfacePlayerInput 를 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
// 스케일폼을 사용하지 않고 적합한 커서 텍스처가 있으면 렌더
if (MouseInterfacePlayerInput != None)
{
// 캔버스 위치를 마우스 위치로 설정
Canvas.SetPos(MouseInterfacePlayerInput.MousePosition.X, MouseInterfacePlayerInput.MousePosition.Y);
// 커서 컬러 설정
Canvas.DrawColor = CursorColor;
// 화면상에 텍스처 그리기
Canvas.DrawTile(CursorTexture, CursorTexture.SizeX, CursorTexture.SizeY, 0.f, 0.f, CursorTexture.SizeX, CursorTexture.SizeY,, true);
}
}
}
// 현재 마우스 인터액션 인터페이스 구하기
MouseInteractionInterface = GetMouseActor(HitLocation, HitNormal);
// 마우스 오버 및 마우스 아웃 처리
// 기존에 마우스 인터액션 인터페이스가 있었는지?
if (LastMouseInteractionInterface != None)
{
// 지난 마우스 인터액션 인터페이스가 현재 마우스 인터액션과 다르다면
if (LastMouseInteractionInterface != MouseInteractionInterface)
{
// 마우스 아웃 함수 호출
LastMouseInteractionInterface.MouseOut(CachedMouseWorldOrigin, CachedMouseWorldDirection);
// 새 마우스 인터액션 인터페이스 할당
LastMouseInteractionInterface = MouseInteractionInterface;
// 지난 마우스 인터액션 인터페이스가 none 이 아니면
if (LastMouseInteractionInterface != None)
{
// 마우스 오버 함수 호출
LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection); // Call mouse over
}
}
}
else if (MouseInteractionInterface != None)
{
// 새 마우스 인터액션 인터페이스 할당
LastMouseInteractionInterface = MouseInteractionInterface;
// 마우스 오버 함수 호출
LastMouseInteractionInterface.MouseOver(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
if (LastMouseInteractionInterface != None)
{
// 왼쪽 마우스 버튼 처리
if (PendingLeftPressed)
{
if (PendingLeftReleased)
{
// 왼쪽 클릭이니, 버리기
PendingLeftPressed = false;
PendingLeftReleased = false;
}
else
{
// 왼쪽 눌림
PendingLeftPressed = false;
LastMouseInteractionInterface.MouseLeftPressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
}
}
else if (PendingLeftReleased)
{
// 왼쪽 뗌
PendingLeftReleased = false;
LastMouseInteractionInterface.MouseLeftReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
// 마우스 오른쪽 버튼 처리
if (PendingRightPressed)
{
if (PendingRightReleased)
{
// 오른 클릭이니, 버리기
PendingRightPressed = false;
PendingRightReleased = false;
}
else
{
// 오른쪽 눌림
PendingRightPressed = false;
LastMouseInteractionInterface.MouseRightPressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
}
}
else if (PendingRightReleased)
{
// 오른쪽 뗌
PendingRightReleased = false;
LastMouseInteractionInterface.MouseRightReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
// 가운데 마우스 버튼 처리
if (PendingMiddlePressed)
{
if (PendingMiddleReleased)
{
// 가운데 클릭이니, 버리기
PendingMiddlePressed = false;
PendingMiddleReleased = false;
}
else
{
// 가운데 눌림
PendingMiddlePressed = false;
LastMouseInteractionInterface.MouseMiddlePressed(CachedMouseWorldOrigin, CachedMouseWorldDirection, HitLocation, HitNormal);
}
}
else if (PendingMiddleReleased)
{
PendingMiddleReleased = false;
LastMouseInteractionInterface.MouseMiddleReleased(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
// 가운데 마우스 버튼 스크롤 업 처리
if (PendingScrollUp)
{
PendingScrollUp = false;
LastMouseInteractionInterface.MouseScrollUp(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
// 가운데 마우스 버튼 스크롤 다운 처리
if (PendingScrollDown)
{
PendingScrollDown = false;
LastMouseInteractionInterface.MouseScrollDown(CachedMouseWorldOrigin, CachedMouseWorldDirection);
}
}
}
function MouseInterfaceInteractionInterface GetMouseActor(optional out Vector HitLocation, optional out Vector HitNormal)
{
local MouseInterfaceInteractionInterface MouseInteractionInterface;
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local Vector2D MousePosition;
local Actor HitActor;
// 가용 캔버스 및 플레이어 오너가 있는지 확인
if (Canvas == None || PlayerOwner == None)
{
return None;
}
// 새 플레이어 인풋을 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
// 플레이어 인풋이 사용가능한지 확인
if (MouseInterfacePlayerInput == None)
{
return None;
}
// 마우스 위치를 IntPoint 로 저장했으나, Vector2D 여야 함
MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
// 마우스 위치를 Deproject 하여 캐시된 벡터에 저장
Canvas.DeProject(MousePosition, CachedMouseWorldOrigin, CachedMouseWorldDirection);
// 트레이스 액터 이터레이터 수행. 가장 위의 마우스 인터액션 인터페이스를 구할 수 있도록
// 하나의 이터레이터 사용. 이는 (스태틱 메시처럼) 다른 추적가능 오브젝트가
// 마우스 인터액션 인터페이스 위에 있는 경우를 다룸.
ForEach TraceActors(class'Actor', HitActor, HitLocation, HitNormal, CachedMouseWorldOrigin + CachedMouseWorldDirection * 65536.f, CachedMouseWorldOrigin,,, TRACEFLAG_Bullet)
{
// HitActor 가 그 마우스 인터액션 인터페이스를 구현하는지 확인하기 위해 형 변환
MouseInteractionInterface = MouseInterfaceInteractionInterface(HitActor);
if (MouseInteractionInterface != None)
{
return MouseInteractionInterface;
}
}
return None;
}
function Vector GetMouseWorldLocation()
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local Vector2D MousePosition;
local Vector MouseWorldOrigin, MouseWorldDirection, HitLocation, HitNormal;
// 적합한 캔버스와 플레이어 오너가 있는지 확인
if (Canvas == None || PlayerOwner == None)
{
return Vect(0, 0, 0);
}
// 새 플레이어 인풋을 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
// 플레이어 인풋이 적합한지 확인
if (MouseInterfacePlayerInput == None)
{
return Vect(0, 0, 0);
}
// 마우스 위치를 IntPoint 로 저장하나, Vector2D 로 필요
MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
// 마우스 위치를 Deproject 하고 캐시 벡터에 저장
Canvas.DeProject(MousePosition, MouseWorldOrigin, MouseWorldDirection);
// 실제 마우스 월드 위치를 구하기 위해 trace 수행
Trace(HitLocation, HitNormal, MouseWorldOrigin + MouseWorldDirection * 65536.f, MouseWorldOrigin , true,,, TRACEFLAG_Bullet);
return HitLocation;
}
defaultproperties
{
// 마우스 좌표를 구하기 위해 언리얼의 플레이어 인풋을 사용하려면 거짓으로 설정
UsingScaleForm=true
CursorColor=(R=255,G=255,B=255,A=255)
CursorTexture=Texture2D'EngineResources.Cursors.Arrow'
}
- 렌더링되는 매 프레임마다 마우스 커서 렌더링합니다.
- 월드 내 추적을 수행하여 현재 마우스 인터액션 인터페이스를 구합니다. 현재 마우스 인터액션 인터페이스가 지난 번 것과 다르다면, 적절한 마우스 오버 및/또는 마우스 아웃 함수를 호출합니다.
- 가용 마우스 인터액션 인터페이스가 있으면, HUD 는 곧 유예된 마우스 입력을 처리합니다.
- 각 마우스 입력에 대해 적절한 인터페이스 함수를 호출하고 불리언을 리셋시킵니다.
마우스 3D 좌표를 원해!
마우스 2D 좌표에 따라 마우스 3D 좌표를 구하려면, HUD 클래스 내에서 이 함수를 사용하면 됩니다. HUD 클래스가 필요한 이유는 Deproject 함수가 필요하기 때문입니다.
function Vector GetMouseWorldLocation()
{
local MouseInterfacePlayerInput MouseInterfacePlayerInput;
local Vector2D MousePosition;
local Vector MouseWorldOrigin, MouseWorldDirection, HitLocation, HitNormal;
// 적합한 캔버스와 플레이어 오너가 있는지 확인
if (Canvas == None || PlayerOwner == None)
{
return Vect(0, 0, 0);
}
// 새 플레이어 인풋을 구하기 위해 형 변환
MouseInterfacePlayerInput = MouseInterfacePlayerInput(PlayerOwner.PlayerInput);
// 플레이어 인풋이 적합한지 확인
if (MouseInterfacePlayerInput == None)
{
return Vect(0, 0, 0);
}
// 마우스 위치를 IntPoint 로 저장하나, Vector2D 로 저장 필요
MousePosition.X = MouseInterfacePlayerInput.MousePosition.X;
MousePosition.Y = MouseInterfacePlayerInput.MousePosition.Y;
// 마우스 위치를 Deproject 하여 캐시 벡터에 저장
Canvas.DeProject(MousePosition, MouseWorldOrigin, MouseWorldDirection);
// 실제 마우스 월드 위치를 구하기 위해 trace 수행
Trace(HitLocation, HitNormal, MouseWorldOrigin + MouseWorldDirection * 65536.f, MouseWorldOrigin , true,,, TRACEFLAG_Bullet);
return HitLocation;
}
관련 토픽
키즈멧 Mouse Input 이벤트 추가하기
class SeqEvent_MouseInput extends SequenceEvent;
var Vector HitLocation;
var Vector HitNormal;
var Vector MouseWorldOrigin;
var Vector MouseWorldDirection;
event Activated()
{
local MouseInterfaceInteractionInterface MouseInteractionInterface;
// originator 를 형 변환하여 마우스 인터액션 인터페이스임을 확인
MouseInteractionInterface = MouseInterfaceInteractionInterface(Originator);
if (MouseInteractionInterface != None)
{
// 이벤트가 활성화되었을 때 적절한 값을 밀어줄 수 있도록 값 구해오기
MouseWorldOrigin = MouseInteractionInterface.GetMouseWorldOrigin();
MouseWorldDirection = MouseInteractionInterface.GetMouseWorldDirection();
HitLocation = MouseInteractionInterface.GetHitLocation();
HitNormal = MouseInteractionInterface.GetHitNormal();
}
}
defaultproperties
{
ObjName="Mouse Input"
ObjCategory="Input"
bPlayerOnly=false
MaxTriggerCount=0
OutputLinks(0)=(LinkDesc="Left Pressed")
OutputLinks(1)=(LinkDesc="Left Released")
OutputLinks(2)=(LinkDesc="Right Pressed")
OutputLinks(3)=(LinkDesc="Right Released")
OutputLinks(4)=(LinkDesc="Middle Pressed")
OutputLinks(5)=(LinkDesc="Middle Released")
OutputLinks(6)=(LinkDesc="Scroll Up")
OutputLinks(7)=(LinkDesc="Scroll Down")
OutputLinks(8)=(LinkDesc="Mouse Over")
OutputLinks(9)=(LinkDesc="Mouse Out")
VariableLinks(1)=(ExpectedType=class'SeqVar_Vector',LinkDesc="HitLocation",bWriteable=true,PropertyName=HitLocation)
VariableLinks(2)=(ExpectedType=class'SeqVar_Vector',LinkDesc="HitNormal",bWriteable=true,PropertyName=HitNormal)
VariableLinks(3)=(ExpectedType=class'SeqVar_Vector',LinkDesc="MouseWorldOrigin",bWriteable=true,PropertyName=MouseWorldOrigin)
VariableLinks(4)=(ExpectedType=class'SeqVar_Vector',LinkDesc="MouseWorldDirection",bWriteable=true,PropertyName=MouseWorldDirection)
}
관련 토픽
예제로 서브클래싱된 KActor 추가하기
class MouseInterfaceKActor extends KActor
Implements(MouseInterfaceInteractionInterface);
var Vector CachedMouseHitLocation;
var Vector CachedMouseHitNormal;
var Vector CachedMouseWorldOrigin;
var Vector CachedMouseWorldDirection;
// ===
// MouseInterfaceInteractionInterface 구현
// ===
function MouseLeftPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = HitLocation;
CachedMouseHitNormal = HitNormal;
TriggerEventClass(class'SeqEvent_MouseInput', Self, 0);
}
function MouseLeftReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 1);
}
function MouseRightPressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = HitLocation;
CachedMouseHitNormal = HitNormal;
TriggerEventClass(class'SeqEvent_MouseInput', Self, 2);
}
function MouseRightReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 3);
}
function MouseMiddlePressed(Vector MouseWorldOrigin, Vector MouseWorldDirection, Vector HitLocation, Vector HitNormal)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = HitLocation;
CachedMouseHitNormal = HitNormal;
TriggerEventClass(class'SeqEvent_MouseInput', Self, 4);
}
function MouseMiddleReleased(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 5);
}
function MouseScrollUp(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 6);
}
function MouseScrollDown(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 7);
}
function MouseOver(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 8);
}
function MouseOut(Vector MouseWorldOrigin, Vector MouseWorldDirection)
{
CachedMouseWorldOrigin = MouseWorldOrigin;
CachedMouseWorldDirection = MouseWorldDirection;
CachedMouseHitLocation = Vect(0.f, 0.f, 0.f);
CachedMouseHitNormal = Vect(0.f, 0.f, 0.f);
TriggerEventClass(class'SeqEvent_MouseInput', Self, 9);
}
function Vector GetHitLocation()
{
return CachedMouseHitLocation;
}
function Vector GetHitNormal()
{
return CachedMouseHitNormal;
}
function Vector GetMouseWorldOrigin()
{
return CachedMouseWorldOrigin;
}
function Vector GetMouseWorldDirection()
{
return CachedMouseWorldDirection;
}
defaultproperties
{
SupportedEvents(4)=class'SeqEvent_MouseInput'
}
- 어느 인터페이스 구현 함수든 HUD 를 통해 실행되면, 부착된 Mouse Input 키즈멧 노드를 트리거시킵니다. 트리거 콜 마지막의 수치가 아웃풋 인덱스입니다.
키즈멧 Mouse Input 이벤트 사용하기
"Lightmass" 탭을 펼치고, "Use Global Illumination" 체크를 해제합니다. 테스트 맵에 라이트매스를 사용할 필요는 없습니다.
"콘텐츠 브라우저"를 열고 "액터 클래스" 탭을 선택합니다. 클래스 트리를 확장하여 "MouseInterfaceKActor" 를 선택합니다. 이렇게 해 두고서 월드 뷰포트 안에 맥락 메뉴를 열어 보면, 월드에 추가시킬 수 있을 것입니다.
월드 뷰포트 내에서 우클릭하여 뷰포트 맥락 메뉴를 엽니다. "Add MouseInterfaceKActor Here" 를 선택하여 MouseInterfaceKActor 를 추가합니다.
MouseInterfaceKActor 에 보이는 스태틱 메시가 없기 때문에, 처음엔 선택된 변형 위젯(선택, 이동, 회전, 스케일 위젯)으로 나타날 것입니다. F4 키를 눌러 액터 속성 창을 엽니다. 선택을 정하려면 상단의 자물쇠 아이콘을 클릭합니다.
"콘텐츠 브라우저"에서 괜찮은 스태틱 메시를 찾아 선택합니다.
"Dynamic SMActor" 탭을 펼치고, "Static Mesh Component" 오브젝트를 확장한 다음, "Static Mesh Component" 탭을 확장합니다. "Static Mesh" 필드 옆의 녹색 화살표를 누르면 "콘텐츠 브라우저"에서 선택해 둔 스태틱 메시가 설정됩니다. 월드 뷰포트에 통을 볼 수 있을 것입니다.
레벨에 필수 라이팅을 추가하고 레벨을 컴파일합니다.
에디터 툴바 내의
Mouse Input 이벤트입니다. 확인해 보면 모든 출력 링크들이 발생할 지 모르는 마우스 인풋 타입을 참조하고 있습니다. 이벤트는 우리가 사용할 수도 있는 다양한 변수를 출력하기도 합니다.
Mouse Input 이벤트를 테스트하기 위해, 약간의 로그 액션을 만듭시다.
테스트하고자 하는 이벤트 출력에 대해 적절한 문구를 약간 출력하도록 로그 액션을 설정합니다.
모든 이벤트 출력을 테스트하기 위한 로그 액션을 더 만듭니다. 전부 적절히 연결해 줍니다.
PIE 내에서 레벨을 실행하면 마우스 인풋 키즈멧 인터페이스를 테스트할 수 있을 것입니다. 마우스 버튼과 스크롤링은 마우스가 MouseInterfaceKActor 위에 있을 때만 반응한다는 점, 기억하시기 바랍니다.
MouseInterfaceKActor 에 총을 쏠 수 있도록 하는 시퀸스를 만들어 이 예제를 확장해 봅시다. 새 벡터 변수를 만드는 것부터 시작합니다. 마우스 원점과 마우스 적중 위치를 저장할 수 있도록 하기 위해서입니다.
벡터 변수를 이벤트의 변수 출력, "HitLocation", "Mouse WorldOrigin" 에 바인딩합니다.
새 "Spawn Projectile" 액션을 추가합니다. 이는 액션이 실행될 때 발사체를 만들어 냅니다.
새로이 생성된 "Spawn Projectile" 액션입니다.
"Spawn Projectile" 액션을 왼쪽 마우스 버튼이 눌릴 때 활성화되는 "Log" 액션으로 연결합니다. "Mouse WorldOrigin" 변수를 "Spawn Projectile" 이벤트 상의 "Spawn Location" 입력으로 연결합니다. "HitLocation" 변수를 "Spawn Projectile" 이벤트 상의 "Target Location" 입력으로 연결합니다. 그러면 "Spawn Projectile" 이 마우스 월드 원점 위치에 마우스 적중 위치를 향해 나아가는 발사체를 스폰하게 합니다. 이를 통해 월드의 MouseInterfaceKActor 에 발사하는 듯한 모습을 낼 수 있습니다.
스폰시킬 발사체 종류를 설정합니다.
"All Players" 변수를 추가합니다. "Spawn Projectile" 액션의 필수 입력입니다.
새로이 만든 "All Players" 변수입니다.
"All Players" 변수를 "Spawn Projectile" 로 연결합니다.
PIE 를 실행하고 키즈멧을 테스트합니다. 이제 MouseInterfaceKActor 에 발사할 수 있을 것입니다.
관련 토픽
다운로드
- MouseInterface.zip 다운로드: 이 젬에 사용된 콘텐츠입니다.
