<2021SC@SDUSC>开源游戏引擎Overload代码分析十:OvEditor——Panels(下)

2021SC@SDUSC

前言

这是Overload引擎相关的第十二篇文章,同时也是OvEditor分析的第七篇。Overload引擎的Github主页在这里。

本篇文章将会介绍OvEditor的Panels文件夹中剩余的一些文件,具体应该会涉及GameView,HardwareInfo和ProjectSettings(迁移至后续)。

一、GameView

1.GameView.h

namespace OvEditor::Core { class EditorRenderer; }

namespace OvEditor::Panels
{
	class GameView : public OvEditor::Panels::AView
	{
	public:
		/**
		* Constructor
		* @param p_title
		* @param p_opened
		* @param p_windowSettings
		*/
		GameView
		(
			const std::string& p_title,
			bool p_opened,
			const OvUI::Settings::PanelWindowSettings& p_windowSettings
		);

		/**
		* Update the view
		* @param p_deltaTime
		*/
		virtual void Update(float p_deltaTime) override;

		/**
		* Custom implementation of the render method
		*/
		virtual void _Render_Impl() override;

		/**
		* Returns true if the game view has a camera
		*/
		bool HasCamera() const;

		/**
		* Returns the game view camera frustum or nothing if the game isn't playing
		*/
		std::optional<OvRendering::Data::Frustum> GetActiveFrustum() const;

	private:
		OvCore::SceneSystem::SceneManager& m_sceneManager;
		bool m_hasCamera = false;
	};
}

这是游戏视窗的类,具体讲解在下面。

2.GameView.cpp

OvEditor::Panels::GameView::GameView
(
	const std::string & p_title,
	bool p_opened,
	const OvUI::Settings::PanelWindowSettings & p_windowSettings
) : AView(p_title, p_opened, p_windowSettings), m_sceneManager(EDITOR_CONTEXT(sceneManager))
{
}

void OvEditor::Panels::GameView::Update(float p_deltaTime)
{
	AView::Update(p_deltaTime);

	auto currentScene = EDITOR_CONTEXT(sceneManager).GetCurrentScene();

	if (currentScene)
	{
		auto cameraComponent = EDITOR_CONTEXT(renderer)->FindMainCamera(*currentScene);
		if (cameraComponent)
		{
			m_camera = cameraComponent->GetCamera();
			m_cameraPosition = cameraComponent->owner.transform.GetWorldPosition();
			m_cameraRotation = cameraComponent->owner.transform.GetWorldRotation();
			m_hasCamera = true;
			PrepareCamera();
		}
		else
		{
			m_camera.SetClearColor({ 0.f, 0.f, 0.f });
			m_hasCamera = false;
		}
	}
}

void OvEditor::Panels::GameView::_Render_Impl()
{
	auto& baseRenderer = *EDITOR_CONTEXT(renderer).get();
	auto& currentScene = *m_sceneManager.GetCurrentScene();

	m_fbo.Bind();

	baseRenderer.Clear(m_camera);

	uint8_t glState = baseRenderer.FetchGLState();
	baseRenderer.ApplyStateMask(glState);

	if (m_hasCamera)
	{
		if (m_camera.HasFrustumLightCulling())
		{
			m_editorRenderer.UpdateLightsInFrustum(currentScene, m_camera.GetFrustum());
		}
		else
		{
			m_editorRenderer.UpdateLights(currentScene);
		}

		m_editorRenderer.RenderScene(m_cameraPosition, m_camera);
	}

	baseRenderer.ApplyStateMask(glState);

	m_fbo.Unbind();
}

bool OvEditor::Panels::GameView::HasCamera() const
{
	return m_hasCamera;
}

std::optional<OvRendering::Data::Frustum> OvEditor::Panels::GameView::GetActiveFrustum() const
{
	return m_hasCamera ? m_camera.GetFrustum() : std::optional<OvRendering::Data::Frustum>{};
}

首先是构造函数,在此处构造函数仅传值。

Update函数首先调用AView的Update,之后获得当前的场景,如果当前的场景存在,那就找到主摄像机,并把主摄像机的设置套用到当前相机,否则就令当前相机刷新颜色为黑色,并且设置为没有相机。

_Render_Impl函数用于添加对渲染方式的自定义项。获得renderer和当前场景,绑定FBO,清除renderer,更改渲染方式,如果有摄像机,那么更新光照并渲染场景,改renderer,解绑FBO。

HasCamera()返回m_hasCamera,用于判断是否有摄像机。

GetActiveFrustum()用于在存在摄像机时获得视锥体。

二、HardwareInfo

1.HardwareInfo.h

namespace OvAnalytics::Hardware { class HardwareInfo; }

namespace OvEditor::Panels
{
	class HardwareInfo : public OvUI::Panels::PanelWindow
	{
	public:
		/**
		* Constructor
		* @param p_title
		* @param p_opened
		* @param p_windowSettings
		* @param p_logFrequency
		* @param p_maxElements
		* @param p_displayMode
		*/
		HardwareInfo
		(
			const std::string& p_title,
			bool p_opened,
			const OvUI::Settings::PanelWindowSettings& p_windowSettings,
			float p_logFrequency,
			size_t p_maxElements
		);

		/**
		* Destructor
		*/
		~HardwareInfo();

		/**
		* Update hardware info
		* @param p_deltaTime
		*/
		void Update(float p_deltaTime);

	private:
		float p_updateTimer = 0.f;
		float m_logFrequency;
		size_t m_maxElements;
		OvUI::Widgets::Plots::APlot* m_cpuUsage;
		OvUI::Widgets::Plots::APlot* m_gpuUsage;
		OvUI::Widgets::Plots::APlot* m_ramUsage;
		OvAnalytics::Hardware::HardwareInfo* m_hardwareInfo;
	};
}

硬件信息的类,具体在下面叙述。

2.HardwareInfo.cpp

OvEditor::Panels::HardwareInfo::HardwareInfo
(
	const std::string& p_title,
	bool p_opened,
	const OvUI::Settings::PanelWindowSettings& p_windowSettings,
	float p_logFrequency,
	size_t p_maxElements
) :
	PanelWindow(p_title, p_opened, p_windowSettings),
	m_logFrequency(p_logFrequency),
	m_maxElements(p_maxElements),
	m_hardwareInfo(new OvAnalytics::Hardware::HardwareInfo(m_logFrequency))
{
	m_cpuUsage = &CreateWidget<Plots::PlotLines>();
	m_gpuUsage = &CreateWidget<Plots::PlotLines>();
	m_ramUsage = &CreateWidget<Plots::PlotLines>();
	
	m_cpuUsage->minScale = 0.0f;
	m_cpuUsage->maxScale = 100.0f;
	m_cpuUsage->size.y = 75.0f;
	m_cpuUsage->data.resize(m_maxElements, 0);
	m_cpuUsage->overlay = "CPU Usage (%)";

	m_gpuUsage->minScale = 0.0f;
	m_gpuUsage->maxScale = 100.0f;
	m_gpuUsage->size.y = 75.0f;
	m_gpuUsage->data.resize(m_maxElements, 0);
	m_gpuUsage->overlay = "GPU Usage (%)";

	m_ramUsage->minScale = 0.0f;
	m_ramUsage->maxScale = 100.0f;
	m_ramUsage->size.y = 75.0f;
	m_ramUsage->data.resize(m_maxElements, 0);
	m_ramUsage->overlay = "RAM Usage (%)";
}

OvEditor::Panels::HardwareInfo::~HardwareInfo()
{
	delete m_hardwareInfo;
}

void OvEditor::Panels::HardwareInfo::Update(float p_deltaTime)
{
	m_hardwareInfo->Tick();

	p_updateTimer += p_deltaTime;

	while (p_updateTimer >= m_logFrequency)
	{
		OvAnalytics::Hardware::HardwareReport report = m_hardwareInfo->GenerateReport();

		m_cpuUsage->data.push_back(report.CPULoad);
		m_gpuUsage->data.push_back(report.GPULoad);
		m_ramUsage->data.push_back((report.RAMUsed / report.RAMMax) * 100.0f);

		if (m_cpuUsage->data.size() > m_maxElements)
			m_cpuUsage->data.erase(m_cpuUsage->data.begin());

		if (m_gpuUsage->data.size() > m_maxElements)
			m_gpuUsage->data.erase(m_gpuUsage->data.begin());

		if (m_ramUsage->data.size() > m_maxElements)
			m_ramUsage->data.erase(m_ramUsage->data.begin());

		p_updateTimer -= m_logFrequency;
	}
}

首先是构造函数,赋值之外创建了cpu,gpu和ram的信息显示,并赋上初值,将用于显示各自的利用率。

~HardwareInfo()是其析构函数。

Update首先更新cpu,gpu和ram的信息。之后更新计时器,如果计时器所记录的时间已经大于输出日志的频率,就对这三项属性进行输出,当属性存储的过多时,就清除,之后把计时器减去频率。

三、ProjectSettings

以下部分迁移至后续讲解,与当前讲解内容关联不大。

1.ProjectSettings.h

	class ProjectSettings : public OvUI::Panels::PanelWindow
	{
	public:
		/**
		* Constructor
		* @param p_title
		* @param p_opened
		* @param p_windowSettings
		*/
		ProjectSettings
		(
			const std::string& p_title,
			bool p_opened,
			const OvUI::Settings::PanelWindowSettings& p_windowSettings
		);

		/**
		* Generate a gatherer that will get the value associated to the given key
		* @param p_keyName
		*/
		template <typename T>
		std::function<T()> GenerateGatherer(const std::string& p_keyName)
		{
			return std::bind(&OvTools::Filesystem::IniFile::Get<T>, &m_projectFile, p_keyName);
		}

		/**
		* Generate a provider that will set the value associated to the given key
		* @param p_keyName
		*/
		template <typename T>
		std::function<void(T)> GenerateProvider(const std::string& p_keyName)
		{
			return std::bind(&OvTools::Filesystem::IniFile::Set<T>, &m_projectFile, p_keyName, std::placeholders::_1);
		}

	private:
		OvTools::Filesystem::IniFile& m_projectFile;
	};

2.ProjectSettings.cpp

OvEditor::Panels::ProjectSettings::ProjectSettings(const std::string & p_title, bool p_opened, const OvUI::Settings::PanelWindowSettings & p_windowSettings) :
	PanelWindow(p_title, p_opened, p_windowSettings),
	m_projectFile(EDITOR_CONTEXT(projectSettings))
{
	auto& saveButton = CreateWidget<Buttons::Button>("Apply");
	saveButton.idleBackgroundColor = { 0.0f, 0.5f, 0.0f };
	saveButton.ClickedEvent += [this]
	{
		EDITOR_CONTEXT(ApplyProjectSettings());
		m_projectFile.Rewrite();
	};

	saveButton.lineBreak = false;

	auto& resetButton = CreateWidget<Buttons::Button>("Reset");
	resetButton.idleBackgroundColor = { 0.5f, 0.0f, 0.0f };
	resetButton.ClickedEvent += [this]
	{
		EDITOR_CONTEXT(ResetProjectSettings());
	};

	CreateWidget<OvUI::Widgets::Visual::Separator>();

	{
		/* Physics settings */
		auto& root = CreateWidget<Layout::GroupCollapsable>("Physics");
		auto& columns = root.CreateWidget<Layout::Columns<2>>();
		columns.widths[0] = 125;

		GUIDrawer::DrawScalar<float>(columns, "Gravity", GenerateGatherer<float>("gravity"), GenerateProvider<float>("gravity"), 0.1f, GUIDrawer::_MIN_FLOAT, GUIDrawer::_MAX_FLOAT);
	}

	{
		/* Build settings */
		auto& generationRoot = CreateWidget<Layout::GroupCollapsable>("Build");
		auto& columns = generationRoot.CreateWidget<Layout::Columns<2>>();
		columns.widths[0] = 125;

		GUIDrawer::DrawBoolean(columns, "Development build", GenerateGatherer<bool>("dev_build"), GenerateProvider<bool>("dev_build"));
	}

	{
		/* Windowing settings */
		auto& windowingRoot = CreateWidget<Layout::GroupCollapsable>("Windowing");
		auto& columns = windowingRoot.CreateWidget<Layout::Columns<2>>();
		columns.widths[0] = 125;

		GUIDrawer::DrawScalar<int>(columns, "Resolution X", GenerateGatherer<int>("x_resolution"), GenerateProvider<int>("x_resolution"), 1, 0, 10000);
		GUIDrawer::DrawScalar<int>(columns, "Resolution Y", GenerateGatherer<int>("y_resolution"), GenerateProvider<int>("y_resolution"), 1, 0, 10000);
		GUIDrawer::DrawBoolean(columns, "Fullscreen", GenerateGatherer<bool>("fullscreen"), GenerateProvider<bool>("fullscreen"));
		GUIDrawer::DrawString(columns, "Executable name", GenerateGatherer<std::string>("executable_name"), GenerateProvider<std::string>("executable_name"));
	}

	{
		/* Rendering settings */
		auto& renderingRoot = CreateWidget<Layout::GroupCollapsable>("Rendering");
		auto& columns = renderingRoot.CreateWidget<Layout::Columns<2>>();
		columns.widths[0] = 125;

		GUIDrawer::DrawBoolean(columns, "Vertical Sync.", GenerateGatherer<bool>("vsync"), GenerateProvider<bool>("vsync"));
		GUIDrawer::DrawBoolean(columns, "Multi-sampling", GenerateGatherer<bool>("multisampling"), GenerateProvider<bool>("multisampling"));
		GUIDrawer::DrawScalar<int>(columns, "Samples", GenerateGatherer<int>("samples"), GenerateProvider<int>("samples"), 1, 2, 16);
		GUIDrawer::DrawScalar<int>(columns, "OpenGL Major", GenerateGatherer<int>("opengl_major"), GenerateProvider<int>("opengl_major"), 1, 3, 4);
		GUIDrawer::DrawScalar<int>(columns, "OpenGL Minor", GenerateGatherer<int>("opengl_minor"), GenerateProvider<int>("opengl_minor"), 1, 0, 6);
	}

	{
		/* Scene Management settings */
		auto& gameRoot = CreateWidget<Layout::GroupCollapsable>("Scene Management");
		auto& columns = gameRoot.CreateWidget<Layout::Columns<2>>();
		columns.widths[0] = 125;

		GUIDrawer::DrawDDString(columns, "Start scene", GenerateGatherer<std::string>("start_scene"), GenerateProvider<std::string>("start_scene"), "File");
	}
}

总结

本篇文章讲了GameView,HardwareInfo两个部分。

Diana

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值