载入中...
搜索中...
未找到
Dialogue.h
浏览该文件的文档.
1#pragma once
2
3#include "common/Module.h"
4#include "common/StateValue.h"
5
6#include <squirrel.h>
7
8#include <cstdint>
9#include <string>
10#include <unordered_map>
11
12namespace eve::avatar {
13class AvatarInstance;
14}
15#include <utility>
16#include <vector>
17
18namespace ssq {
19class Object;
20}
21
22namespace eve::dialogue {
23
29struct DataValue {
30 enum class Kind { Null, Int, Float, Bool, String, Array, Object };
31
33 long long i = 0;
34 double f = 0.0;
35 bool b = false;
36 std::string s;
37 std::vector<DataValue> arr;
38 std::vector<std::pair<std::string, DataValue>> obj;
39
40 static DataValue null() { return {}; }
41 static DataValue integer(long long v) {
44 d.i = v;
45 return d;
46 }
47 static DataValue number(double v) {
50 d.f = v;
51 return d;
52 }
53 static DataValue boolean(bool v) {
56 d.b = v;
57 return d;
58 }
59 static DataValue string(std::string v) {
62 d.s = std::move(v);
63 return d;
64 }
65 static DataValue array(std::vector<DataValue> v) {
68 d.arr = std::move(v);
69 return d;
70 }
71 static DataValue object(std::vector<std::pair<std::string, DataValue>> v) {
74 d.obj = std::move(v);
75 return d;
76 }
77
78 const DataValue *find(const std::string &key) const {
79 for (const auto &kv : obj)
80 if (kv.first == key) return &kv.second;
81 return nullptr;
82 }
83};
84
92class Dialogue : public Module {
93public:
95 Dialogue();
96 ~Dialogue() override;
97
99 bool registerCharacter(const std::string &id, const std::string &displayName);
100 bool hasCharacter(const std::string &id) const;
101 std::string getDisplayName(const std::string &id) const;
102 bool bindAvatar(const std::string &id, avatar::AvatarInstance *av);
103 avatar::AvatarInstance *getAvatar(const std::string &id) const;
104 int getCharacterCount() const;
105 std::string getCharacterId(int index) const;
106
108 bool show(const std::string &id, const std::string &slot);
109 bool hide(const std::string &id);
110 bool isShown(const std::string &id) const;
111 std::string getSlot(const std::string &id) const;
112 void setSlotX(const std::string &slot, float xNorm);
113 float getSlotX(const std::string &slot) const;
114 bool setExpression(const std::string &id, const std::string &expression);
115 bool setMotion(const std::string &id, const std::string &motion);
117 void syncStage(float stageWidth, float stageHeight);
118
120 void say(const std::string &speakerId, const std::string &text);
121 void narrate(const std::string &text);
122 void setTypeSpeed(float charsPerSecond);
123 float getTypeSpeed() const { return typeSpeed_; }
124 void skipTyping();
125 bool isTyping() const;
126 bool isWaitingAdvance() const;
127 bool isIdle() const;
128 void advance();
129
130 std::string getSpeakerId() const { return speakerId_; }
131 std::string getSpeakerName() const;
132 std::string getFullText() const { return fullText_; }
133 std::string getVisibleText() const;
134 std::string getPhase() const;
135
137 void setLipSyncEnabled(bool enabled);
138 bool isLipSyncEnabled() const { return lipSyncEnabled_; }
139 void setLipSyncParameter(const std::string &name);
140 std::string getLipSyncParameter() const { return lipSyncParameter_; }
141 void setLipSyncAmplitude(float amplitude);
142 float getLipSyncAmplitude() const { return lipSyncAmplitude_; }
143 float getLipSyncValue() const { return lipSyncValue_; }
144
146 void clearChoices();
147 bool addChoice(const std::string &id, const std::string &label);
148 void presentChoices();
149 bool isWaitingChoice() const;
150 int getChoiceCount() const;
151 std::string getChoiceId(int index) const;
152 std::string getChoiceLabel(int index) const;
153 bool selectChoice(int index);
154 std::string getSelectedChoiceId() const { return selectedChoiceId_; }
155
156 // ---- variables (global / scene; scene auto-cleared on scene switch) ----
157 struct VarValue {
158 enum class Type { Int, Float, Bool, String };
159
161 long long i = 0;
162 double f = 0.0;
163 bool b = false;
164 std::string s;
165
166 std::string toString() const;
167 std::string typeName() const;
168 bool isNumeric() const { return type == Type::Int || type == Type::Float; }
169
170 static VarValue integer(long long v);
171 static VarValue number(double v);
172 static VarValue boolean(bool v);
173 static VarValue string(std::string v);
174 };
175
177 bool setVar(const std::string &name, ssq::Object value, const std::string &scope);
179 bool setVarValue(const std::string &name, const VarValue &value, const std::string &scope);
180 VarValue getVarValue(const std::string &name, const std::string &scope) const;
181 std::string getVarType(const std::string &name, const std::string &scope) const;
182 int getVarInt(const std::string &name, int defaultValue, const std::string &scope) const;
183 float getVarFloat(const std::string &name, float defaultValue, const std::string &scope) const;
184 bool getVarBool(const std::string &name, bool defaultValue, const std::string &scope) const;
185 std::string getVarString(const std::string &name, const std::string &defaultValue,
186 const std::string &scope) const;
187 bool hasVar(const std::string &name, const std::string &scope) const;
188 bool clearVar(const std::string &name, const std::string &scope);
189 void clearVars(const std::string &scope);
190
191 // ---- conditions ----
193 bool registerCondition(const std::string &name, ssq::Object fn);
194 bool unregisterCondition(const std::string &name);
195 bool evalCondition(ssq::Object table);
196 bool evalConditionData(const DataValue &cond);
197
198 // ---- content pools ----
199 int loadPoolsFromTable(ssq::Object table);
200 int loadPoolsFromData(const DataValue &root);
202 int loadPoolsFromDnut(const std::string &source, const std::string &path);
204 int loadPoolsFromDnutFile(const std::string &path);
205 void clearPools();
206 int getPoolCount() const;
207 std::string getPoolId(int index) const;
208 bool hasPool(const std::string &id) const;
209 std::string getLastPoolsError() const { return lastPoolsError_; }
210
211 // ---- rng (weighted selection determinism) ----
213 void setRandomSeed(int seed);
214 int getRandomSeed() const { return int(rngState_); }
215
216 // ---- generated-line selection / play ----
217 std::string pickLine(const std::string &poolId, ssq::Object params);
218 std::string pickLineWithParams(const std::string &poolId,
219 const std::unordered_map<std::string, VarValue> &params);
220 bool playLine(const std::string &lineId, ssq::Object params);
221 bool playLineWithParams(const std::string &lineId,
222 const std::unordered_map<std::string, VarValue> &params);
223 bool playPool(const std::string &poolId, ssq::Object params);
224 bool playPoolWithParams(const std::string &poolId,
225 const std::unordered_map<std::string, VarValue> &params);
226 std::string getCurrentLineId() const { return currentLineId_; }
227 std::string getCurrentLineMeta(const std::string &field) const;
228 std::vector<std::string> getCurrentLineTags() const;
229
231 void update(float dt);
233 void reset();
234
236 bool captureState(StateValue& out) const;
237
244 bool restoreState(const StateValue& in, std::string* err = nullptr);
245
247 bool resetToDefaults();
248
249private:
250 struct Character {
251 std::string id;
252 std::string displayName;
253 avatar::AvatarInstance *avatar = nullptr;
254 std::string slot;
255 bool shown = false;
256 };
257
258 struct Choice {
259 std::string id;
260 std::string label;
261 };
262
263 enum class Phase { Idle, Typing, WaitingAdvance, WaitingChoice };
264
265 Character *findCharacter(const std::string &id);
266 const Character *findCharacter(const std::string &id) const;
267 void beginLine(const std::string &speakerId, const std::string &text);
268
269 std::vector<Character> characters_;
270 std::unordered_map<std::string, float> slotX_; // normalized 0..1
271
272 Phase phase_ = Phase::Idle;
273 std::string speakerId_;
274 std::string fullText_;
275 float typeSpeed_ = 40.f; // chars / second
276 float typed_ = 0.f;
277
278 std::vector<Choice> choices_;
279 std::string selectedChoiceId_;
280
281 bool lipSyncEnabled_ = true;
282 std::string lipSyncParameter_ = "mouthOpen";
283 float lipSyncAmplitude_ = 0.85f;
284 float lipSyncValue_ = 0.f;
285 float lipSyncTime_ = 0.f;
286
287 void updateLipSync(float dt);
288 void applyLipSyncToSpeaker();
289
290 // ---- procedural content (variables / conditions / pools) ----
291 struct Condition {
292 enum class Kind { Always, Cmp, All, Any, Not, Script };
293
294 Kind kind = Kind::Always;
295 std::string var;
296 std::string op;
297 VarValue value;
298 std::vector<Condition> children;
299 std::string script;
300 };
301
302 struct Line {
303 std::string id;
304 std::string speaker;
305 std::string text;
306 std::string i18nKey;
307 double weight = 1.0;
308 Condition when;
309 std::unordered_map<std::string, std::string> meta;
310 std::vector<std::string> tags;
311 };
312
313 struct Pool {
314 std::string id;
315 int noRepeat = 3;
316 std::vector<Line> lines;
317 std::vector<size_t> recent;
318 };
319
320 std::unordered_map<std::string, VarValue> *varsForScope(const std::string &scope);
321 const std::unordered_map<std::string, VarValue> *varsForScope(const std::string &scope) const;
322 std::unordered_map<std::string, VarValue> mergedVars(
323 const std::unordered_map<std::string, VarValue> &params) const;
324 std::unordered_map<std::string, std::string> stringParams(
325 const std::unordered_map<std::string, VarValue> &vars) const;
326 bool parseCondition(const DataValue &v, Condition &out, std::string &error);
327 bool parseLineData(const std::string &poolId, const DataValue &v, int index, Line &line,
328 std::string &error);
329 bool evalConditionInternal(const Condition &c,
330 const std::unordered_map<std::string, VarValue> &merged,
331 const std::unordered_map<std::string, VarValue> &params,
332 const std::string &lineId) const;
333 bool evalScriptPredicate(const std::string &name,
334 const std::unordered_map<std::string, VarValue> &merged,
335 const std::unordered_map<std::string, VarValue> &params,
336 const std::string &lineId) const;
337 bool compareEq(const VarValue &a, const VarValue &b) const;
338 bool compareOrder(const std::string &op, const VarValue &a, const VarValue &b) const;
339 std::string interpolate(const std::string &tpl,
340 const std::unordered_map<std::string, VarValue> &vars) const;
341 Pool *findPool(const std::string &id);
342 const Pool *findPool(const std::string &id) const;
343 Line *findLine(const std::string &id);
344 const Line *findLine(const std::string &id) const;
345 void applyLineMeta(const Line &line);
346 void pollSceneChange();
347 uint32_t nextRandom();
348 double nextUnit();
349
350 std::unordered_map<std::string, VarValue> globalVars_;
351 std::unordered_map<std::string, VarValue> sceneVars_;
352 std::unordered_map<std::string, HSQOBJECT> predicates_;
353 std::vector<Pool> pools_;
354 std::string lastPoolsError_;
355 uint32_t rngState_ = 0x9E3779B9u;
356 std::string lastSceneName_;
357 std::string currentLineId_;
358 std::unordered_map<std::string, std::string> currentLineMeta_;
359 std::vector<std::string> currentLineTags_;
360 HSQUIRRELVM vm_ = nullptr;
361};
362
363} // namespace eve::dialogue
uint32_t seed
struct SQVM * HSQUIRRELVM
int line
Tok kind
std::string value
std::string id
std::string error
JobScope scope
std::vector< std::string > vars
uint32_t a
uint32_t b
uint32_t c
const char * name
Definition RockMesh.cpp:21
SettlementPipeline::Stage fn
bool enabled
int d
int v
int children
Definition TreeMesh.cpp:177
Object is the base class for all game objects. It provides reference counting and dirty flag for upda...
Definition Object.h:18
JSON-compatible state value tree used by state hot reload.
Definition StateValue.h:20
Unified avatar instance. Kind is a string: "image" | "live2d" | "vroid". Script-facing API avoids ove...
Visual-novel style dialogue stage. Script: dlg <- eve.Dialogue();
Definition Dialogue.h:92
std::string pickLineWithParams(const std::string &poolId, const std::unordered_map< std::string, VarValue > &params)
Definition Dialogue.cpp:927
bool setExpression(const std::string &id, const std::string &expression)
bool setMotion(const std::string &id, const std::string &motion)
std::string getSpeakerName() const
void reset()
重置舞台与台词状态。
std::string getLastPoolsError() const
Definition Dialogue.h:209
float getLipSyncAmplitude() const
Definition Dialogue.h:142
bool clearVar(const std::string &name, const std::string &scope)
Definition Dialogue.cpp:411
bool playLineWithParams(const std::string &lineId, const std::unordered_map< std::string, VarValue > &params)
Definition Dialogue.cpp:975
std::string getSpeakerId() const
Definition Dialogue.h:130
int getCharacterCount() const
bool captureState(StateValue &out) const
Serialize conversation state (vars, rng, phase, choices, stage).
bool restoreState(const StateValue &in, std::string *err=nullptr)
Restore conversation state captured by captureState().
std::string getCurrentLineMeta(const std::string &field) const
float getSlotX(const std::string &slot) const
int loadPoolsFromDnutFile(const std::string &path)
Definition Dialogue.cpp:802
bool evalCondition(ssq::Object table)
Definition Dialogue.cpp:454
std::string getCurrentLineId() const
Definition Dialogue.h:226
std::string getFullText() const
Definition Dialogue.h:132
bool getVarBool(const std::string &name, bool defaultValue, const std::string &scope) const
Definition Dialogue.cpp:391
bool registerCharacter(const std::string &id, const std::string &displayName)
角色:注册 / 查询 / 绑定 Avatar。
bool playPool(const std::string &poolId, ssq::Object params)
Definition Dialogue.cpp:999
std::vector< std::string > getCurrentLineTags() const
bool playLine(const std::string &lineId, ssq::Object params)
Definition Dialogue.cpp:969
void narrate(const std::string &text)
int loadPoolsFromData(const DataValue &root)
Definition Dialogue.cpp:744
void clearChoices()
选项:清空/添加/展示与选择。
int loadPoolsFromDnut(const std::string &source, const std::string &path)
Definition Dialogue.cpp:792
bool setVar(const std::string &name, ssq::Object value, const std::string &scope)
Definition Dialogue.cpp:352
bool selectChoice(int index)
bool hasCharacter(const std::string &id) const
std::string getCharacterId(int index) const
void setLipSyncParameter(const std::string &name)
bool addChoice(const std::string &id, const std::string &label)
VarValue getVarValue(const std::string &name, const std::string &scope) const
Definition Dialogue.cpp:363
bool show(const std::string &id, const std::string &slot)
舞台:显示/隐藏角色、槽位与表情/动作。
void setTypeSpeed(float charsPerSecond)
float getVarFloat(const std::string &name, float defaultValue, const std::string &scope) const
Definition Dialogue.cpp:382
int loadPoolsFromTable(ssq::Object table)
Definition Dialogue.cpp:660
bool hasPool(const std::string &id) const
Definition Dialogue.cpp:832
std::string getChoiceId(int index) const
avatar::AvatarInstance * getAvatar(const std::string &id) const
bool playPoolWithParams(const std::string &poolId, const std::unordered_map< std::string, VarValue > &params)
bool unregisterCondition(const std::string &name)
Definition Dialogue.cpp:446
void update(float dt)
推进打字机 / 口型同步 / 阶段机;每帧调用。
void say(const std::string &speakerId, const std::string &text)
台词:说话/旁白、打字机效果与推进。
bool evalConditionData(const DataValue &cond)
Definition Dialogue.cpp:612
bool isWaitingChoice() const
float getLipSyncValue() const
Definition Dialogue.h:143
std::string pickLine(const std::string &poolId, ssq::Object params)
Definition Dialogue.cpp:921
std::string getChoiceLabel(int index) const
bool bindAvatar(const std::string &id, avatar::AvatarInstance *av)
void setRandomSeed(int seed)
Definition Dialogue.cpp:916
bool resetToDefaults()
Reset stage and line state (restore fallback).
std::string getVarType(const std::string &name, const std::string &scope) const
Definition Dialogue.cpp:370
void setSlotX(const std::string &slot, float xNorm)
bool registerCondition(const std::string &name, ssq::Object fn)
Definition Dialogue.cpp:431
std::string getVarString(const std::string &name, const std::string &defaultValue, const std::string &scope) const
Definition Dialogue.cpp:400
int getRandomSeed() const
Definition Dialogue.h:214
bool isShown(const std::string &id) const
std::string getLipSyncParameter() const
Definition Dialogue.h:140
void syncStage(float stageWidth, float stageHeight)
bool setVarValue(const std::string &name, const VarValue &value, const std::string &scope)
Definition Dialogue.cpp:344
std::string getSlot(const std::string &id) const
void setLipSyncEnabled(bool enabled)
口型同步:打字时驱动说话者 Avatar 参数。
std::string getSelectedChoiceId() const
Definition Dialogue.h:154
int getVarInt(const std::string &name, int defaultValue, const std::string &scope) const
Definition Dialogue.cpp:374
void setLipSyncAmplitude(float amplitude)
std::string getPoolId(int index) const
Definition Dialogue.cpp:827
bool hide(const std::string &id)
void clearVars(const std::string &scope)
Definition Dialogue.cpp:416
bool isWaitingAdvance() const
bool isLipSyncEnabled() const
Definition Dialogue.h:138
std::string getDisplayName(const std::string &id) const
std::string getVisibleText() const
float getTypeSpeed() const
Definition Dialogue.h:123
bool hasVar(const std::string &name, const std::string &scope) const
Definition Dialogue.cpp:406
std::string getPhase() const
NodeDesc when(bool cond, NodeDesc child)
Conditional: include child only when cond is true (empty group otherwise).
Definition NodeDesc.cpp:232
WidgetDesc text(std::string content, std::string id)
Static text label.
Definition Widget.cpp:235
EVEngine ECS 集成层:底层实现使用 sunxfancy/ECS.hpp https://github.com/sunxfancy/ECS.hpp
Definition ECS.h:12
Generic JSON-like value tree used by the Squirrel bridge: dialogue pools and conditions arrive as Squ...
Definition Dialogue.h:29
static DataValue null()
Definition Dialogue.h:40
static DataValue string(std::string v)
Definition Dialogue.h:59
std::vector< DataValue > arr
Definition Dialogue.h:37
static DataValue integer(long long v)
Definition Dialogue.h:41
static DataValue boolean(bool v)
Definition Dialogue.h:53
const DataValue * find(const std::string &key) const
Definition Dialogue.h:78
static DataValue array(std::vector< DataValue > v)
Definition Dialogue.h:65
static DataValue object(std::vector< std::pair< std::string, DataValue > > v)
Definition Dialogue.h:71
static DataValue number(double v)
Definition Dialogue.h:47
std::vector< std::pair< std::string, DataValue > > obj
Definition Dialogue.h:38
static VarValue number(double v)
Definition Dialogue.cpp:267
static VarValue boolean(bool v)
Definition Dialogue.cpp:274
static VarValue integer(long long v)
Definition Dialogue.cpp:260