보통 enum을 사용하게되면 스코프 지정이 안되서 이곳저곳에서 사용함.

 

때문에 아래처럼 또 다른 enum에서 같은 이름의 타입이 있는 상태에서 Red를 이용하게 되면

재정의 한다고 에러뜸.

 

이에 대한 해결 방법은 enum class를 이용하면 됨. (c++11이상에서 사용)

 

 

사용할 때 스코프 지정 연산자 "::"을 이용해서 사용하면 된다.

더 자세히 알고 싶으면 아래 링크로.

www.cppkorea.org/CppCoreGuidelines/Enum/

 

Enum - C++ 핵심 가이드라인

Enum: 열거형 역주 : 열거형(enumeration) 역주 : 열거체(enumerator) 역주 : 열거값(enumerator value) 열거형은 정수 값의 집합을 정의하는데 사용되며, 그런 값들의 집합을 타입으로 정의하는데 사용된다. 열

www.cppkorea.org

 

 

R"()" 을 이용하면 여러줄에 걸쳐 작성할 수 있습니다. R"(과 ") 사이에 문자열을 입력하면 됩니다.

사용 방법: R"(문자입력)"

 

코드

 

실행 화면

 

 

로우 문자열 리터럴은 R"( 과 )"  사이에 )"를 사용지 못합니다.  )"로 끝나기 때문입니다.

 

문자열 중간에 ")를 포함하려면 확장된 로우 문자열 리터럴을 사용해야 합니다.

 

중간에 )"를 넣지 못한다.

중간에 ")를 포함하려면 시작과 끝부분에 구문자를 지정해줘야 합니다.

구문자는 최대 16문자까지 구성할 수 있고 사용자가 직접 정해서 쓰면 됩니다.

 

 

이번 예제같은 경우는 "ABC"를 구문자로 설정하여 실행 해봤습니다.

아래는 ABC( 와   )ABC 사이에 ")를 출력하는 코드입니다.

 

 

실행결과 ")가 잘 나오는것을 확인할 수 있습니다.

 

실행 화면

 

데이터베이스 쿼리 문자열, 정규 표현식 등을 사용할 때 이스케이프 처리 문제를 해결할 수 있습니다.

프로젝션 행렬을 이용한 구현.

public class Test : MonoBehaviour
{
    Matrix4x4 originalProjectionMat;

    private void Start()
    {
        originalProjectionMat = Camera.main.projectionMatrix;
    }

    private void CameraShake()
    {
        Matrix4x4 pMat = originalProjectionMat;

        // roll
        pMat.m01 += Mathf.Sin(Time.time * 1.25f) * 0.4f;
        pMat.m10 += Mathf.Sin(Time.time * 1.5f) * 0.4f;

        // x
        pMat.m00 += Mathf.Sin(Time.time * 1.5f) * 0.1f;
        pMat.m11 += Mathf.Sin(Time.time * 1.5f) * 0.1f;

        Camera.main.projectionMatrix = pMat;
    }
    
    private void Update()
    {
        CameraShake();
    }
}

매트릭스 Inverse 직접 구현

 

회전행렬의 역행렬 * 이동행렬의 역행렬

    public Matrix4x4 Inverse(Matrix4x4 matrix)
    {
        // Rotate Scale Inverse
        Matrix4x4 invRot = Matrix4x4.identity;
        for(int i=0; i < 3; ++i)
        {
            Vector4 v = matrix.GetColumn(i);
            invRot.SetRow(i, v.normalized / v.magnitude);
        }

        // Translate Inverse
        Matrix4x4 invTrans = Matrix4x4.identity;
        invTrans.m03 = -matrix.m03;
        invTrans.m13 = -matrix.m13;
        invTrans.m23 = -matrix.m23;

        // Combine
        return invRot * invTrans;
    }
public float SetPixelSize(float _pixelRate)
    {
        cam= GetComponent<Camera>();
        Vector3 p1 = new Vector3(1, 0, 0);
        Vector3 p2 = new Vector3(2, 0, 0);

        p1 = cam.ScreenToWorldPoint(p1);
        p2 = cam.ScreenToWorldPoint(p2);

        float pixelSize = p2.x - p1.x;
        pixelSize *= _pixelRate;
        
        return pixelSize;
    }

 

#include <iostream>
#include <math.h>
using namespace std;

struct vec2 {
public:
	float x;
	float y;

	vec2() {

	}
	vec2(float x, float y) {
		this->x = x;
		this->y = y;
	}
};

//      (시작점)--------------------------------------->(끝점)

int main() {
	cin.tie(NULL);
	ios::sync_with_stdio(false);
	
	vec2 posStart(0,0);// 시작점
	vec2 posEnd(10,10);// 끝점

	vec2 arrow1(0, 0);// 화살표 1
	vec2 arrow2(0, 0);// 화살표 2

	float width = 1;  // 너비
	float length = 3; // 길이

	float distance = sqrtf(powf(posEnd.x - posStart.x, 2) + powf(posEnd.y - posStart.y, 2));
	cout << "distance : " << distance << '\n';

	//float th = atan2f(pend.x - pstart.x, pend.y - pstart.y) * (180 / 3.14f);
	float th = atan2f(posEnd.y - posStart.y, posEnd.x - posStart.x);
	cout << "th : " << th << '\n';

	arrow1.x = (distance - length) * cosf(th) - (width / 2.f) * sinf(th) + posStart.x;
	arrow1.y = (distance - length) * sinf(th) + (width / 2.f) * cosf(th) + posStart.y;

	arrow2.x = (distance - length) * cosf(th) + (width / 2.f) * sinf(th) + posStart.x;
	arrow2.y = (distance - length) * sinf(th) - (width / 2.f) * cosf(th) + posStart.y;

	cout << "arrow1 x : " << arrow1.x << ", y : " << arrow1.y << '\n';
	cout << "arrow2 x : " << arrow2.x << ", y : " << arrow2.y << '\n';

	return 0;
}

'게임 개발 > C++ console' 카테고리의 다른 글

배열 안에서 숫자 움직이기 (MBCS, WBCS 연습 겸)  (0) 2021.01.13
빙고게임2 (MBCS,WBCS 연습겸)  (0) 2021.01.13
미디 키보드 건반 프로그램  (0) 2020.01.14
마리오게임  (0) 2019.12.03
TextRPG  (0) 2019.11.12

 

 

Canvas 에서 Screen Space -  Camera 일 경우 마우스 클릭 위치에 UI를 옮기고 싶으면 아래와 같이 하면 됨.

 

ContextMenuEx 스크립트를 만듬.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ContextMenuEx : MonoBehaviour
{
    public RectTransform targetRectTr;
    public Camera uiCamera;
    public RectTransform menuUITr;

    private Vector2 screenPoint;
    private void Start()
    {
        targetRectTr = GetComponent<RectTransform>();
        uiCamera = Camera.main;
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0))
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(targetRectTr, Input.mousePosition, uiCamera, out screenPoint);
            menuUITr.localPosition = screenPoint;
        }
    }
}

 

회색으로 색칠된 UI가 Panel, 빨간색으로 색칠된 UI가 menuUI이다.

마우스 클릭시 클릭된 위치에 menuUI가 잘 나온다.

 

 

패널 바깥부분 누르면 튀어나옴. Panel영역 안에서만 나오게 하고 싶으면 RectTransformUtility.RectangleContainsScreenPoint()함수를 이용하면 됨.

 

Panel영역 내에서만 나타나게 하는 코드

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ContextMenuEx : MonoBehaviour
{
    // RectTransform 범위
    public RectTransform targetRectTr;
    public Camera uiCamera;
    public RectTransform menuUITr;

    private Vector2 screenPoint;
    private void Start()
    {
        uiCamera = Camera.main;
    }
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.Mouse0) &&
            RectTransformUtility.RectangleContainsScreenPoint(targetRectTr, Input.mousePosition, uiCamera))
        {
            RectTransformUtility.ScreenPointToLocalPointInRectangle(targetRectTr, Input.mousePosition, uiCamera, out screenPoint);
            menuUITr.localPosition = screenPoint;
        }
    }
}

 

 

간단하게 만들어봄.

InputFieldTabManager inputFieldTabMrg = new InputFieldTabManager();를 이용하여 선언 후.

inputFieldTabMrg.Add(인풋필드); 로 인풋필드를 추가해준다.

inputFieldTabMrg.SetFocus(); 를 이용하여 포커스를 맞춘 후

 

Update() 함수 안에서 inputFieldTabMrg.CheckFocus() 함수를 실행해주면 된다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

/// <summary>
/// InputField에서 Tab과 Shift+Tab키를 누르는 것을 관리하는 클래스
/// </summary>
public class InputFieldTabManager
{
    private List<InputField> list;
    private int curPos;

    public InputFieldTabManager()
    {
        list = new List<InputField>();
    }

    /// <summary>
    /// Focus 할 InputField를 설정한다.
    /// </summary>
    /// <param name="idx">Focus 할 InputField의 index 번호</param>
    public void SetFocus(int idx = 0)
    {
        if (idx >= 0 && idx < list.Count)
            list[idx].Select();
    }

    /// <summary>
    /// Tab, Shift+Tab 키를 눌렀을 때 반응 할 InputField를 추가한다.
    /// </summary>
    /// <param name="inputField">추가 할 InputField</param>
    public void Add(InputField inputField)
    {
        list.Add(inputField);
    }

    /// <summary>
    /// 현재 위치를 얻는다.
    /// </summary>
    /// <returns>현재 위치의 Index</returns>
    private int GetCurerntPos()
    {
        for (int i = 0; i < list.Count; ++i)
        {
            if (list[i].isFocused == true)
            {
                curPos = i;
                break;
            }
        }
        return curPos;
    }

    /// <summary>
    /// 다음 InputField로 Focus한다.
    /// </summary>
    private void MoveNext()
    {
        GetCurerntPos();
        if (curPos < list.Count - 1)
        {
            ++curPos;
            list[curPos].Select();
        }
    }

    /// <summary>
    /// 이전 InputField로 Focus한다.
    /// </summary>
    private void MovePrev()
    {
        GetCurerntPos();
        if (curPos > 0)
        {
            --curPos;
            list[curPos].Select();
        }
    }

    /// <summary>
    /// Tab키와 Shift + Tab키를 눌렀는지 체크하여 눌렀으면 Focus를 옮긴다.
    /// </summary>
    public void CheckFocus()
    {
        if (Input.GetKeyDown(KeyCode.Tab) && !Input.GetKey(KeyCode.LeftShift))
        {
            MoveNext();
        }
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Tab))
        {
            MovePrev();
        }
    }
}

 

혹은 Selctable이용하기.

부모 오브젝트에 넣어주기만 하면 알아서 세팅해줌.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class FocusControll : MonoBehaviour
{
    [SerializeField]
    Selectable[] selectables;

    int selectedIdx = 0;
    Coroutine focusupdate = null;
    private void Awake()
    {
        selectables = GetComponentsInChildren<Selectable>(true);
    }

    private void OnEnable()
    {
        //for(int i =0; i < selectables.Length; i++)
        //{
        //    if(selectables[i].gameObject.activeSelf == true && selectables[i].IsInteractable() == true)
        //    {
        //        selectables[i
        //        break;
        //    }
        //}
        StartCoroutine(SetDefFocus());
        focusupdate = StartCoroutine(FocusUpdate());
    }
    IEnumerator SetDefFocus()
    {
        yield return new WaitForEndOfFrame();
        for (int i = 0; i < selectables.Length; i++)
        {
            if (selectables[i].gameObject.activeSelf == true && selectables[i].IsInteractable() == true)
            {
                selectables[i].Select();
                
                selectedIdx = i;
                break;
            }
        }
    }
    private void OnDisable()
    {
        StopCoroutine(focusupdate);
    }

    IEnumerator FocusUpdate()
    {
        while (true)
        {
            KeyDownBind();
            yield return new WaitForSeconds(0);
        }
    }

    private void KeyDownBind()
    {
        if (Input.GetKey(KeyCode.LeftShift) && Input.GetKeyDown(KeyCode.Tab))
        {
            Debug.Log("backward");
            int idx = 0;
            if (selectedIdx <= 0)
            {
                idx = selectables.Length - 1;
            }
            else
            {
                idx = selectedIdx - 1;
            }
            for (int i = idx; i < selectables.Length; i--)
            {
                if (selectables[i].gameObject.activeSelf == true && selectables[i].IsInteractable() == true)
                {
                    selectables[i].Select();
                    
                    selectedIdx = i;
                    break;
                }
                if (i == 0)
                    i = selectables.Length - 1;
            }
        }
        else if (Input.GetKeyDown(KeyCode.Tab))
        {
            Debug.Log("forward");
            int idx = 0;
            if (selectedIdx >= selectables.Length - 1)
            {
                idx = 0;
            }
            else
            {
                idx = selectedIdx + 1;
            }
            for (int i = idx; i < selectables.Length; i++)
            {
                if (selectables[i].gameObject.activeSelf == true && selectables[i].IsInteractable() == true)
                {
                    selectables[i].Select();
                    
                    selectedIdx = i;
                    break;
                }
            }
            
        }
        else if (Input.GetKeyDown(KeyCode.KeypadEnter)||Input.GetKeyDown(KeyCode.Return))
        {
            Button button = GetComponentInChildren<Button>(true);
            if(button != null)
                button.onClick.Invoke();
        }
    }
}

+ Recent posts