2026-02-15 09:22:57 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @file main.cpp
|
2026-02-15 13:32:42 +08:00
|
|
|
|
* @brief Extra2D 场景图测试示例
|
2026-02-15 09:22:57 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
#include <extra2d/extra2d.h>
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
|
|
using namespace extra2d;
|
|
|
|
|
|
|
2026-02-18 17:15:49 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 基础场景类,演示场景图功能
|
|
|
|
|
|
*/
|
|
|
|
|
|
class BasicScene : public Scene {
|
|
|
|
|
|
public:
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 场景进入时初始化场景图
|
|
|
|
|
|
*/
|
|
|
|
|
|
void onEnter() override {
|
|
|
|
|
|
float width = getWidth();
|
|
|
|
|
|
float height = getHeight();
|
|
|
|
|
|
|
|
|
|
|
|
auto root = makeShared<Node>();
|
|
|
|
|
|
root->setName("Root");
|
|
|
|
|
|
root->setPos(width / 2, height / 2);
|
|
|
|
|
|
addChild(root);
|
|
|
|
|
|
|
|
|
|
|
|
auto parent1 = makeShared<Node>();
|
|
|
|
|
|
parent1->setName("Parent1");
|
|
|
|
|
|
parent1->setPos(-200, 0);
|
|
|
|
|
|
root->addChild(parent1);
|
|
|
|
|
|
|
|
|
|
|
|
auto rect1 = ShapeNode::createFilledRect(Rect(-50, -50, 100, 100),
|
|
|
|
|
|
Color(1.0f, 0.4f, 0.4f, 1.0f));
|
|
|
|
|
|
rect1->setName("RedRect");
|
|
|
|
|
|
parent1->addChild(rect1);
|
|
|
|
|
|
|
|
|
|
|
|
auto child1 = makeShared<Node>();
|
|
|
|
|
|
child1->setName("Child1");
|
|
|
|
|
|
child1->setPos(80, 0);
|
|
|
|
|
|
child1->setRotation(45);
|
|
|
|
|
|
child1->setScale(0.5f);
|
|
|
|
|
|
parent1->addChild(child1);
|
|
|
|
|
|
|
|
|
|
|
|
auto smallRect = ShapeNode::createFilledRect(Rect(-30, -30, 60, 60),
|
|
|
|
|
|
Color(1.0f, 0.8f, 0.4f, 1.0f));
|
|
|
|
|
|
smallRect->setName("OrangeRect");
|
|
|
|
|
|
child1->addChild(smallRect);
|
|
|
|
|
|
|
|
|
|
|
|
auto parent2 = makeShared<Node>();
|
|
|
|
|
|
parent2->setName("Parent2");
|
|
|
|
|
|
parent2->setPos(200, 0);
|
|
|
|
|
|
root->addChild(parent2);
|
|
|
|
|
|
|
|
|
|
|
|
auto circle1 = ShapeNode::createFilledCircle(Vec2(0, 0), 60,
|
|
|
|
|
|
Color(0.4f, 0.4f, 1.0f, 1.0f));
|
|
|
|
|
|
circle1->setName("BlueCircle");
|
|
|
|
|
|
parent2->addChild(circle1);
|
|
|
|
|
|
|
|
|
|
|
|
auto child2 = makeShared<Node>();
|
|
|
|
|
|
child2->setName("Child2");
|
|
|
|
|
|
child2->setPos(0, 100);
|
|
|
|
|
|
parent2->addChild(child2);
|
|
|
|
|
|
|
|
|
|
|
|
auto triangle = ShapeNode::createFilledTriangle(
|
|
|
|
|
|
Vec2(0, -40), Vec2(-35, 30), Vec2(35, 30),
|
|
|
|
|
|
Color(0.4f, 1.0f, 0.4f, 1.0f));
|
|
|
|
|
|
triangle->setName("GreenTriangle");
|
|
|
|
|
|
child2->addChild(triangle);
|
|
|
|
|
|
|
|
|
|
|
|
auto line = ShapeNode::createLine(Vec2(-300, -200), Vec2(300, -200),
|
|
|
|
|
|
Color(1.0f, 1.0f, 1.0f, 1.0f), 2.0f);
|
|
|
|
|
|
line->setName("BottomLine");
|
|
|
|
|
|
root->addChild(line);
|
|
|
|
|
|
|
|
|
|
|
|
auto polygon = ShapeNode::createFilledPolygon(
|
|
|
|
|
|
{Vec2(0, -50), Vec2(50, 0), Vec2(30, 50), Vec2(-30, 50), Vec2(-50, 0)},
|
|
|
|
|
|
Color(1.0f, 0.4f, 1.0f, 1.0f));
|
|
|
|
|
|
polygon->setName("PurplePolygon");
|
|
|
|
|
|
polygon->setPos(0, -150);
|
|
|
|
|
|
root->addChild(polygon);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 场景退出时清理资源
|
|
|
|
|
|
*/
|
|
|
|
|
|
void onExit() override { clearChildren(); }
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 自定义渲染逻辑
|
|
|
|
|
|
* @param renderer 渲染后端
|
|
|
|
|
|
*/
|
2026-02-20 15:04:21 +08:00
|
|
|
|
void onRender(Renderer &renderer) override { Scene::onRender(renderer); }
|
2026-02-18 17:15:49 +08:00
|
|
|
|
};
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-15 12:36:36 +08:00
|
|
|
|
int main(int argc, char *argv[]) {
|
|
|
|
|
|
(void)argc;
|
|
|
|
|
|
(void)argv;
|
|
|
|
|
|
|
2026-02-15 13:32:42 +08:00
|
|
|
|
std::cout << "Extra2D Scene Graph Demo - Starting..." << std::endl;
|
2026-02-15 12:36:36 +08:00
|
|
|
|
|
|
|
|
|
|
Application &app = Application::get();
|
|
|
|
|
|
|
2026-02-17 00:34:14 +08:00
|
|
|
|
app.use<WindowModule>([](auto &cfg) {
|
|
|
|
|
|
cfg.w = 1280;
|
|
|
|
|
|
cfg.h = 720;
|
|
|
|
|
|
cfg.priority = 0;
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-02-20 15:04:21 +08:00
|
|
|
|
app.use<RenderModule>([](auto &cfg) { cfg.priority = 10; });
|
2026-02-17 00:34:14 +08:00
|
|
|
|
|
2026-02-16 23:14:12 +08:00
|
|
|
|
std::cout << "Initializing application..." << std::endl;
|
|
|
|
|
|
if (!app.init()) {
|
2026-02-15 12:36:36 +08:00
|
|
|
|
std::cerr << "Failed to initialize application!" << std::endl;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "Application initialized successfully!" << std::endl;
|
2026-02-17 00:12:32 +08:00
|
|
|
|
|
|
|
|
|
|
auto *win = app.window();
|
2026-02-16 23:14:12 +08:00
|
|
|
|
if (win) {
|
2026-02-17 00:12:32 +08:00
|
|
|
|
std::cout << "Window: " << win->width() << "x" << win->height()
|
|
|
|
|
|
<< std::endl;
|
2026-02-16 23:14:12 +08:00
|
|
|
|
}
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-16 23:14:12 +08:00
|
|
|
|
auto eventService = ServiceLocator::instance().getService<IEventService>();
|
2026-02-15 13:32:42 +08:00
|
|
|
|
if (eventService) {
|
|
|
|
|
|
eventService->addListener(EventType::KeyPressed, [](Event &e) {
|
|
|
|
|
|
auto &keyEvent = std::get<KeyEvent>(e.data);
|
|
|
|
|
|
if (keyEvent.keyCode == static_cast<int>(Key::Escape)) {
|
|
|
|
|
|
e.handled = true;
|
|
|
|
|
|
Application::get().quit();
|
|
|
|
|
|
}
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
eventService->addListener(EventType::MouseButtonPressed, [](Event &e) {
|
|
|
|
|
|
auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
|
|
|
|
|
|
std::cout << "[Click] Button " << mouseEvent.button << " at ("
|
|
|
|
|
|
<< mouseEvent.position.x << ", " << mouseEvent.position.y << ")"
|
|
|
|
|
|
<< std::endl;
|
|
|
|
|
|
});
|
|
|
|
|
|
}
|
2026-02-15 12:36:36 +08:00
|
|
|
|
|
2026-02-18 17:15:49 +08:00
|
|
|
|
auto scene = makeShared<BasicScene>();
|
2026-02-15 13:32:42 +08:00
|
|
|
|
scene->setBackgroundColor(Color(0.12f, 0.12f, 0.16f, 1.0f));
|
2026-02-16 23:14:12 +08:00
|
|
|
|
if (win) {
|
|
|
|
|
|
scene->setViewportSize(static_cast<float>(win->width()),
|
|
|
|
|
|
static_cast<float>(win->height()));
|
|
|
|
|
|
}
|
2026-02-15 13:32:42 +08:00
|
|
|
|
|
2026-02-16 23:14:12 +08:00
|
|
|
|
auto cameraService = ServiceLocator::instance().getService<ICameraService>();
|
|
|
|
|
|
if (cameraService && win) {
|
2026-02-15 13:37:08 +08:00
|
|
|
|
ViewportConfig vpConfig;
|
2026-02-16 23:14:12 +08:00
|
|
|
|
vpConfig.logicWidth = static_cast<float>(win->width());
|
|
|
|
|
|
vpConfig.logicHeight = static_cast<float>(win->height());
|
2026-02-15 13:37:08 +08:00
|
|
|
|
vpConfig.mode = ViewportMode::AspectRatio;
|
|
|
|
|
|
cameraService->setViewportConfig(vpConfig);
|
2026-02-16 23:14:12 +08:00
|
|
|
|
cameraService->updateViewport(win->width(), win->height());
|
2026-02-15 13:37:08 +08:00
|
|
|
|
cameraService->applyViewportAdapter();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-02-15 12:36:36 +08:00
|
|
|
|
app.enterScene(scene);
|
|
|
|
|
|
|
2026-02-15 13:32:42 +08:00
|
|
|
|
std::cout << "\nControls:" << std::endl;
|
|
|
|
|
|
std::cout << " ESC - Exit" << std::endl;
|
|
|
|
|
|
std::cout << " Mouse Click - Print position" << std::endl;
|
|
|
|
|
|
std::cout << "\nRunning main loop...\n" << std::endl;
|
|
|
|
|
|
|
2026-02-15 12:36:36 +08:00
|
|
|
|
app.run();
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "Shutting down..." << std::endl;
|
|
|
|
|
|
app.shutdown();
|
|
|
|
|
|
|
|
|
|
|
|
std::cout << "Goodbye!" << std::endl;
|
|
|
|
|
|
return 0;
|
2026-02-15 09:22:57 +08:00
|
|
|
|
}
|