栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

<2021SC@SDUSC>开源游戏引擎Overload代码分析二:OvWindowing——Context

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

<2021SC@SDUSC>开源游戏引擎Overload代码分析二:OvWindowing——Context

2021SC@SDUSC

Overload代码分析二:OvWindowing——Context
  • 前言
  • Context
    • 一、Device.h
    • 二、EDeviceError.h
    • 三、Device.cpp
      • 1.构造函数
      • 2.析构函数
      • 3.GetMonitorSize()
      • 4.GetCursorInstance()
      • 5.HasVsync()
      • 6.SetVsync()
      • 7.PollEvents()
      • 8.GetElapsedTime()
      • 9.已提过的函数
  • Cursor
    • 一、ECursorMode.h
    • 二、ECursorShape.h
  • 总结

前言

这是Overload引擎相关的第四篇文章,同时也是OvWindowing分析的第二篇。Overload引擎的Github主页在这里。
本篇文章会开始介绍OvWindowing的各类头文件及函数定义,首先是在Context文件夹中的各类文件,以及Cursor文件夹中的文件。

Context

咱先看.h文件,后看.cpp文件。

一、Device.h

我们在上一篇博客中已经提到了Device.h,其中提到了Device类,咱们再在这里放一下代码:

namespace OvWindowing::Context
{
	
	class Device
	{
	public:
		
		static OvTools::Eventing::Event ErrorEvent;

		
		Device(const Settings::DeviceSettings& p_deviceSettings);

		
		~Device();

		
		std::pair GetMonitorSize() const;

		
		GLFWcursor* GetCursorInstance(Cursor::ECursorShape p_cursorShape) const;

		
		bool HasVsync() const;

		
		void SetVsync(bool p_value);

		
		void PollEvents() const;

		
		float GetElapsedTime() const;

	private:
		void BindErrorCallback();
		void CreateCursors();
		void DestroyCursors();

	private:
		bool m_vsync = true;
		bool m_isAlive = false;
		std::unordered_map m_cursors;
	};
}

具体的功能我们在讲函数实现的时候在细说。

二、EDeviceError.h

定义了EDeviceError,见代码:

namespace OvWindowing::Context
{
	
	enum class EDeviceError
	{
		NOT_INITIALIZED		= 0x00010001,
		NO_CURRENT_ConTEXT	= 0x00010002,
		INVALID_ENUM		= 0x00010003,
		INVALID_VALUE		= 0x00010004,
		OUT_OF_MEMORY		= 0x00010005,
		API_UNAVAILABLE		= 0x00010006,
		VERSION_UNAVAILABLE = 0x00010007,
		PLATFORM_ERROR		= 0x00010008,
		FORMAT_UNAVAILABLE	= 0x00010009,
		NO_WINDOW_ConTEXT	= 0x0001000A
	};
}

看到enum class就很明了了,就是用枚举定义了一些可返回的错误类型。

三、Device.cpp

cpp内部按顺序讲解函数。

1.构造函数
OvWindowing::Context::Device::Device(const Settings::DeviceSettings& p_deviceSettings)
{
	BindErrorCallback();

	int initializationCode = glfwInit();

	if (initializationCode == GLFW_FALSE)
	{
		throw std::runtime_error("Failed to Init GLFW");
		glfwTerminate();
	}
	else
	{
		CreateCursors();

		if (p_deviceSettings.debugProfile)
			glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);

		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, p_deviceSettings.contextMajorVersion);
		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, p_deviceSettings.contextMinorVersion);

		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
		glfwWindowHint(GLFW_SAMPLES, p_deviceSettings.samples);

		m_isAlive = true;
	}
}

第一句调用BindErrorCallback(),用于绑定错误回调,当发生错误时可以返回易读的错误,也是主要基于glfw,内部实现为:

void OvWindowing::Context::Device::BindErrorCallback()
{
	auto errorCallback = [](int p_code, const char* p_description)
	{
		ErrorEvent.Invoke(static_cast(p_code), p_description);
	};

	glfwSetErrorCallback(errorCallback);
}

其实就是唤醒错误事件,用glfw进行错误回调的设置。
第二步是初始化glfw,如果初始化失败(initializationCode == GLFW_FALSE),那就报错并且调用glfwTerminate()来终止glfw程序。
如果初始化没有失败,首先调用CreateCursors()来创建指针,内部实现为:

void OvWindowing::Context::Device::CreateCursors()
{
	m_cursors[Cursor::ECursorShape::ARROW] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::ARROW));
	m_cursors[Cursor::ECursorShape::IBEAM] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::IBEAM));
	m_cursors[Cursor::ECursorShape::CROSSHAIR] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::CROSSHAIR));
	m_cursors[Cursor::ECursorShape::HAND] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::HAND));
	m_cursors[Cursor::ECursorShape::HRESIZE] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::HRESIZE));
	m_cursors[Cursor::ECursorShape::VRESIZE] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::VRESIZE));
}

实际上就是把指针的各个参数做了个赋值。
之后确定是否开启了debug,如果开启了,那么就把window设置中对应的属性(GLFW_OPENGL_DEBUG_CONTEXT)设为true。
之后就是对glfw创建的window设定了各种参数,最后把m_isAlive设为true,表示window有效。

2.析构函数
OvWindowing::Context::Device::~Device()
{
	if (m_isAlive)
	{
		DestroyCursors();
		glfwTerminate();
	}
}

普通的析构函数,首先判断是否window有效(存在),如果存在就先销毁指针,内部也是调用glfw销毁每个参数。之后把glfw中止,释放资源。

3.GetMonitorSize()

用于获得基础窗口的长宽,单位为像素。

std::pair OvWindowing::Context::Device::GetMonitorSize() const
{
	const GLFWvidmode * mode = glfwGetVideoMode(glfwGetPrimaryMonitor());

	return std::pair(static_cast(mode->width), static_cast(mode->height));
}

首先通过glfw获得控制器,可以视作获得当前页面的句柄,然后获取页面的video mode,通过它就能得到屏幕空间下的窗口长宽。

4.GetCursorInstance()

用于获得指定指针形状下的一个指针实例。

GLFWcursor * OvWindowing::Context::Device::GetCursorInstance(Cursor::ECursorShape p_cursorShape) const
{
	return m_cursors.at(p_cursorShape);
}

内部就只有一句代码,at()是unordered_map的方法,用于获得指定键的对应值,不细讲了,需要的可以自行搜索。

5.HasVsync()

返回是否开启vsync。

bool OvWindowing::Context::Device::HasVsync() const
{
	return m_vsync;
}

单纯返回属性值。

6.SetVsync()

设置是否开启vsync。

void OvWindowing::Context::Device::SetVsync(bool p_value)
{
	glfwSwapInterval(p_value ? 1 : 0);
	m_vsync = p_value;
}

首先给定是否要开启,如果要的话,会把交换帧的间隔变为1,否则可以视作未改变,之后更改对应属性(m_vsync)。

7.PollEvents()

只是对glfw的一层封装,用于开启输入及事件管理。

void OvWindowing::Context::Device::PollEvents() const
{
	glfwPollEvents();
}
8.GetElapsedTime()

获得经过的时间,也就是程序运行的时间。

float OvWindowing::Context::Device::GetElapsedTime() const
{
	return static_cast(glfwGetTime());
}

实现是直接glfw获得经过时间。

9.已提过的函数

以下函数我们在上面讲过了,就不再重复。

void OvWindowing::Context::Device::BindErrorCallback()
{
	auto errorCallback = [](int p_code, const char* p_description)
	{
		ErrorEvent.Invoke(static_cast(p_code), p_description);
	};

	glfwSetErrorCallback(errorCallback);
}

void OvWindowing::Context::Device::CreateCursors()
{
	m_cursors[Cursor::ECursorShape::ARROW] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::ARROW));
	m_cursors[Cursor::ECursorShape::IBEAM] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::IBEAM));
	m_cursors[Cursor::ECursorShape::CROSSHAIR] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::CROSSHAIR));
	m_cursors[Cursor::ECursorShape::HAND] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::HAND));
	m_cursors[Cursor::ECursorShape::HRESIZE] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::HRESIZE));
	m_cursors[Cursor::ECursorShape::VRESIZE] = glfwCreateStandardCursor(static_cast(Cursor::ECursorShape::VRESIZE));
}

void OvWindowing::Context::Device::DestroyCursors()
{
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::ARROW]);
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::IBEAM]);
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::CROSSHAIR]);
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::HAND]);
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::HRESIZE]);
	glfwDestroyCursor(m_cursors[Cursor::ECursorShape::VRESIZE]);
}

Cursor

虽说标题中我们只说到了Context文件夹,但我们要顺便说一下Cursor文件夹中的文件,因为这和咱们Context文件夹中的一些函数和属性有关。

一、ECursorMode.h
namespace OvWindowing::Cursor
{
	
	enum class ECursorMode
	{
		NORMAL		= 0x00034001,
		DISABLED	= 0x00034003,
		HIDDEN		= 0x00034002
	};
}

枚举定义了指针的模式,分别是正常,无效和隐藏。

二、ECursorShape.h
namespace OvWindowing::Cursor
{
	
	enum class ECursorShape
	{
		ARROW		= 0x00036001,
		IBEAM		= 0x00036002,
		CROSSHAIR	= 0x00036003,
		HAND		= 0x00036004,
		HRESIZE		= 0x00036005,
		VRESIZE		= 0x00036006
	};
}

同样是枚举定义,不过定义的是指针样式,名字对应形状,不翻译了。

总结

本次文章介绍的代码量和上次相比少了不少,同时也很简单易懂,清晰明了,应该算是很好理解的一章了。之后咱们会将其他文件夹中的头文件等,也不难,所以已经没有什么好怕的了。到了OvEditor中,会再难起来,在此之前,不用担心。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/317467.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号