Better narration processing

This commit is contained in:
2026-01-22 17:15:19 +03:00
parent 4b24d85123
commit cd91174f5d
23 changed files with 1301 additions and 367 deletions

View File

@@ -22,7 +22,10 @@
#include "EditorGizmoModule.h"
#include "PhysicsModule.h"
#include "PlayerActionModule.h"
#include "CharacterModule.h"
#include "CharacterManagerModule.h"
#include "items.h"
#include "physics.h"
#include "GUIModule.h"
#include "GUIModuleCommon.h"
namespace ECS
@@ -263,60 +266,105 @@ struct GUIListener : public Ogre::RenderTargetListener {
"This game does not autosave. Please use save function to keep your state");
ImGui::PopFont();
ImGui::End();
} else if (ECS::get().get<GUI>().enabled) {
if (ECS::get().get<GUI>().narrationBox) {
ImVec2 size = ImGui::GetMainViewport()->Size;
ImGui::SetNextWindowPos(ImVec2(0,
size.y * 0.75f),
ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(size.x,
size.y * 0.25f),
ImGuiCond_Always);
ImGui::Begin("Narration...", NULL,
ImGuiWindowFlags_NoTitleBar);
ImGui::PushFont(midFont);
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::TextWrapped(
"%s", ECS::get()
.get<GUI>()
.narrationText.c_str());
if (ECS::get().get<GUI>().choices.size() == 0) {
ImGui::SetCursorScreenPos(p);
if (ImGui::InvisibleButton(
"Background",
ImGui::GetWindowSize()))
ECS::get<LuaBase>().mLua->call_handler(
"narration_progress");
} else {
int i;
for (i = 0; i < ECS::get()
.get<GUI>()
.choices.size();
i++) {
if (ImGui::Button(
ECS::get()
.get<GUI>()
.choices[i]
.c_str())) {
ECS::get()
.get_mut<GUI>()
.narration_answer =
i + 1;
std::cout << "answer: "
<< i + 1
<< std::endl;
ECS::modified<GUI>();
ECS::get<LuaBase>()
.mLua
->call_handler(
"narration_answered");
}
}
}
ImGui::Spacing();
ImGui::PopFont();
ImGui::End();
} else if (ECS::get().get<GUI>().mainMenu) {
} else if (ECS::get<GUI>().narrationHandlers.size() > 0) {
ECS::get_mut<GUI>().grab = false;
ECS::get_mut<GUI>().grabChanged = true;
ECS::get_mut<GUI>().enabled = true;
ECS::get_mut<GUI>().narrationBox = true;
ImVec2 size = ImGui::GetMainViewport()->Size;
ImGui::SetNextWindowPos(ImVec2(0, size.y * 0.75f),
ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(size.x, size.y * 0.25f),
ImGuiCond_Always);
ImGui::Begin("Narration...", NULL,
ImGuiWindowFlags_NoTitleBar);
ImGui::PushFont(midFont);
ImVec2 p = ImGui::GetCursorScreenPos();
GUI::NarrationHandler *narration =
ECS::get<GUI>().narrationHandlers.front();
if (!narration->is_active())
narration->_event("narration_activate");
ImGui::TextWrapped(
"%s", narration->getNarrationText().c_str());
if (narration->getChoices().size() == 0) {
ImGui::SetCursorScreenPos(p);
if (ImGui::InvisibleButton(
"Background",
ImGui::GetWindowSize()))
narration->progress();
} else {
int i;
for (i = 0; i < narration->getChoices().size();
i++) {
if (ImGui::Button(
narration->getChoices()[i]
.c_str())) {
narration->setNarrationAnswer(
i + 1);
std::cout << "answer: " << i + 1
<< std::endl;
}
}
}
if (narration->is_complete()) {
ECS::get_mut<GUI>().enabled = false;
ECS::get_mut<GUI>().narrationBox = false;
ECS::get_mut<GUI>().grab = true;
ECS::get_mut<GUI>().grabChanged = true;
ECS::get_mut<GUI>().removeNarrationHandler(
narration);
delete narration;
}
ImGui::Spacing();
ImGui::PopFont();
ImGui::End();
ECS::modified<GUI>();
} else if (ECS::get().get<GUI>().narrationBox) {
ImVec2 size = ImGui::GetMainViewport()->Size;
ImGui::SetNextWindowPos(ImVec2(0, size.y * 0.75f),
ImGuiCond_Always);
ImGui::SetNextWindowSize(ImVec2(size.x, size.y * 0.25f),
ImGuiCond_Always);
ImGui::Begin("Narration...", NULL,
ImGuiWindowFlags_NoTitleBar);
ImGui::PushFont(midFont);
ImVec2 p = ImGui::GetCursorScreenPos();
ImGui::TextWrapped(
"%s",
ECS::get().get<GUI>().narrationText.c_str());
if (ECS::get().get<GUI>().choices.size() == 0) {
ImGui::SetCursorScreenPos(p);
if (ImGui::InvisibleButton(
"Background",
ImGui::GetWindowSize()))
ECS::get<LuaBase>().mLua->call_handler(
"narration_progress");
} else {
int i;
for (i = 0;
i < ECS::get().get<GUI>().choices.size();
i++) {
if (ImGui::Button(ECS::get()
.get<GUI>()
.choices[i]
.c_str())) {
ECS::get()
.get_mut<GUI>()
.narration_answer =
i + 1;
std::cout << "answer: " << i + 1
<< std::endl;
ECS::modified<GUI>();
ECS::get<LuaBase>().mLua->call_handler(
"narration_answered");
}
}
}
ImGui::Spacing();
ImGui::PopFont();
ImGui::End();
} else if (ECS::get().get<GUI>().enabled) {
if (ECS::get().get<GUI>().mainMenu) {
ImVec2 size = ImGui::GetMainViewport()->Size;
ImGui::SetNextWindowPos(ImVec2(0, 0),
ImGuiCond_Always);
@@ -495,27 +543,103 @@ struct GUIListener : public Ogre::RenderTargetListener {
} else {
ECS::ActionNodeList &list =
ECS::get_mut<ECS::ActionNodeList>();
if (list.nodes.size() > 0) {
Ogre::Vector3 queryPos =
ECS::get<Camera>()
.mCameraNode
->_getDerivedPosition();
std::vector<size_t> points;
list.query(queryPos, points);
for (auto &p : points) {
std::cout << p << std::endl
<< list.nodes[p].props.dump()
<< std::endl;
if (list.dynamicNodes.size() > 0) {
int j;
Ogre::Vector3 queryPos;
std::vector<size_t> points = list.points;
std::vector<float> distances = list.distances;
Ogre::SceneNode *cameraNode =
ECS::get<Camera>().mCameraNode;
Ogre::Vector3 cameraPos =
cameraNode->_getDerivedPosition();
float minDistance = 25.0f;
int i;
list.selected = -1;
for (i = 0; i < points.size(); i++) {
size_t p = points[i];
float distance = distances[i];
float radius = list.dynamicNodes[p]
.props["radius"]
.get<float>();
float height = list.dynamicNodes[p]
.props["height"]
.get<float>();
float actDistance = radius * radius +
height * height;
float textDistance =
actDistance + 2.0f * 2.0f;
Ogre::Vector2 screenPos =
projectToScreen(
list.nodes[p].position);
list.dynamicNodes[p]
.position);
if (screenPos.x < 0)
continue;
std::cout << list.nodes[p].position
<< " " << screenPos
<< std::endl;
ImGui::SetNextWindowPos(ImVec2(
screenPos.x, screenPos.y));
// FIXME: move this to system to filter points there
Ogre::Vector3 hitPosition;
JPH::BodyID hitBody;
bool hit =
JoltPhysicsWrapper::getSingleton()
.raycastQuery(
list.dynamicNodes[p]
.position,
cameraPos,
hitPosition,
hitBody);
if (hit)
continue;
if (list.selected == -1) {
if (distance < actDistance)
list.selected = p;
}
ImDrawList *drawList =
ImGui::GetBackgroundDrawList();
ImVec2 center = ImVec2(screenPos.x,
screenPos.y);
float circleRadius = 8.0f;
ImColor circleColor(
ImVec4(0.3f, 0.3f, 0.3f, 1.0f));
if (p == list.selected) {
circleRadius = 16.0f;
circleColor = ImColor(
ImVec4(0, 0, 1, 1));
}
drawList->AddCircleFilled(center,
circleRadius,
circleColor);
drawList->AddCircle(
center, circleRadius,
IM_COL32(64, 64, 255, 255));
ImVec2 textSize = ImGui::CalcTextSize(
list.dynamicNodes[p]
.action_text.c_str());
ImVec2 textPos = ImVec2(
center.x - (textSize.x * 0.5f),
center.y + circleRadius + 4.0f);
if (distance < textDistance) {
drawList->AddText(
ImVec2(textPos.x + 1,
textPos.y + 1),
IM_COL32(0, 0, 0, 200),
list.dynamicNodes[p]
.action_text
.c_str());
drawList->AddText(
ImVec2(textPos.x,
textPos.y),
IM_COL32(255, 32, 64,
255),
list.dynamicNodes[p]
.action_text
.c_str());
}
#if 0
ImGui::SetNextWindowPos(
ImVec2(screenPos.x,
screenPos.y),
ImGuiCond_Always,
ImVec2(0.5f, 0.5f));
ImGui::Begin(
("SensorLabel##" +
Ogre::StringConverter::toString(
@@ -524,10 +648,27 @@ struct GUIListener : public Ogre::RenderTargetListener {
nullptr,
ImGuiWindowFlags_NoBackground |
ImGuiWindowFlags_NoTitleBar |
ImGuiWindowFlags_AlwaysAutoResize |
ImGuiWindowFlags_NoInputs);
ImGui::TextColored(ImVec4(1, 0, 0, 1),
"SENSOR TRIGGERED");
ImDrawList *drawList =
ImGui::GetWindowDrawList();
ImVec2 cursor =
ImGui::GetCursorScreenPos();
drawList->AddCircleFilled(
ImVec2(cursor.x, cursor.y),
16.0f,
IM_COL32(0, 0, 255, 255));
drawList->AddCircle(
ImVec2(cursor.x, cursor.y),
16.0f,
IM_COL32(32, 32, 255, 255));
ImGui::TextColored(
ImVec4(1, 0, 0, 1), "%s",
list.nodes[p]
.action_text.c_str());
ImGui::End();
#endif
}
}
}