Last time we talked about creating this whole test framework and test classes and all that, we had sth where we could actually create test classes which extended like kind of a base test class, and we could demonstrate each individual OpenGL or feature or whatever we want to really do with OpenGL in kind of a sandbox test environment that was really clear for us to demonstrate and have samples of the various pages that we learned about in OpenGL.
Today we’re gonna be extending that, how we could create some test menu where we could click on a test, and it would construct a new test, and then when we went back to the main menu, it would delete that test and unload all the resources and present us with that test menu again?
1、Why didn’t make these Test methods pure virtual functions?
The reason we left them as just virtual function and implemented them with a blank body like that code below is that we could selectively choose which ones we actually want to implement ourselves, if there were equals 0 if they were all pure virtual we’d have to have all these 3 methods in TestMenu class, but with making them as virtual function we could just go ahead and delete some of the functions that we don’t need, like this:
class Test
{
public:
Test() {}
virtual ~Test() {}
virtual void OnUpdate(float deltatime) {}
// virtual void OnUpdate(float deltatime) = 0; // pure virtual.
virtual void OnRender() {}
virtual void OnImGuiRender() {}
};
class TestMenu : public Test
{
public:
TestMenu();
~TestMenu() {}
void OnImGuiRender() override;
};
and everything will still work fine, we don’t have to implement them, it’s just an option that’s given to us.
2、代码实现
在原有的Test.h
文件基础上,增加一个新类:TestMenu
。
The TestMenu
class is going to do 2 things: it’s going to contain a collection of all of our tests and we want a way to be able to basically present them with a specific name, so we need a pointer to a test class, a test object instance, but we also want to store a name that we can provide the test like a label, it would appears for our button in the test menu. Another thing is: a pointer to our current test, the reason we need this is our menu is going to change the current test is active.
Test.h
代码:
#pragma once
#include <functional>
#include <vector>
#include <string>
#include <iostream>
namespace test
{
class Test
{
public:
Test() {}
virtual ~Test() {}
virtual void OnUpdate(float deltatime) {}
virtual void OnRender() {}
virtual void OnImGuiRender() {}
};
class TestMenu : public Test
{
public:
TestMenu(Test*& currentTestPointer);
void OnImGuiRender() override;
template<typename T>
void RegisterTest(const std::string& name)
{
std::cout << "Registering test " << name << std::endl;
m_Tests.push_back(std::make_pair(name, []() { return new T(); }));
}
private:
// Mark it as reference so that the TestMenu is able to write to this pointer and thus change the current test.
Test*& m_CurrentTest;
// Instead of providing a Test pointer for the second element of our pair, we're gonna provide it with a lambda,
// a function that constructs that Test class of ours.(this function returns a Test pointer and doesn't take
// any parameters)
std::vector< std::pair<std::string, std::function<Test*()>> > m_Tests;
};
}
如图:src/tests
下增加Test.cpp
文件。
回到Application.cpp
,所做的修改如图:
3、运行效果
测试1
hit F5
点击按钮“Clear Color”
可以修改背景颜色
点击按钮“<-”
点击“关闭”
程序关闭正常
测试2
再次hit F5
点击按钮“Clear Color”
点击关闭
程序关闭正常