载入中...
搜索中...
未找到
Dialogue.h
浏览该文件的文档.
1#pragma once
2#include "common/Export.h"
3
4
5#include "common/Module.h"
6#include "common/StateValue.h"
7#include "common/Value.h"
8
9#include <squirrel.h>
10
11#include <cstdint>
12#include <optional>
13#include <string>
14#include <unordered_map>
15
16namespace eve::avatar {
17class AvatarInstance;
18}
19#include <utility>
20#include <vector>
21
22namespace ssq {
23class Object;
24}
25
26namespace eve::dialogue {
27
38
47public:
48 // Keep the historical nested names as zero-cost aliases for C++ callers.
51
54 Dialogue();
56 ~Dialogue() override;
57
59 bool registerCharacter(const std::string &id, const std::string &displayName);
61 bool hasCharacter(const std::string &id) const;
63 std::string getDisplayName(const std::string &id) const;
65 bool bindAvatar(const std::string &id, avatar::AvatarInstance *av);
67 avatar::AvatarInstance *getAvatar(const std::string &id) const;
69 int getCharacterCount() const;
71 std::string getCharacterId(int index) const;
72
74 bool show(const std::string &id, const std::string &slot);
76 bool hide(const std::string &id);
78 bool isShown(const std::string &id) const;
80 std::string getSlot(const std::string &id) const;
82 void setSlotX(const std::string &slot, float xNorm);
84 float getSlotX(const std::string &slot) const;
86 bool setExpression(const std::string &id, const std::string &expression);
88 bool setMotion(const std::string &id, const std::string &motion);
91 void syncStage(float stageWidth, float stageHeight);
92
94 void say(const std::string &speakerId, const std::string &text);
96 void narrate(const std::string &text);
98 void setTypeSpeed(float charsPerSecond);
100 float getTypeSpeed() const { return typeSpeed_; }
102 void skipTyping();
104 bool isTyping() const;
106 bool isWaitingAdvance() const;
108 bool isIdle() const;
110 void advance();
111
113 std::string getSpeakerId() const { return speakerId_; }
115 std::string getSpeakerName() const;
117 std::string getFullText() const { return fullText_; }
119 std::string getVisibleText() const;
121 std::string getPhase() const;
122
124 void setLipSyncEnabled(bool enabled);
126 bool isLipSyncEnabled() const { return lipSyncEnabled_; }
128 void setLipSyncParameter(const std::string &name);
130 std::string getLipSyncParameter() const { return lipSyncParameter_; }
132 void setLipSyncAmplitude(float amplitude);
134 float getLipSyncAmplitude() const { return lipSyncAmplitude_; }
136 float getLipSyncValue() const { return lipSyncValue_; }
137
139 void clearChoices();
141 bool addChoice(const std::string &id, const std::string &label);
143 void presentChoices();
145 bool isWaitingChoice() const;
147 int getChoiceCount() const;
149 std::string getChoiceId(int index) const;
151 std::string getChoiceLabel(int index) const;
153 bool selectChoice(int index);
155 std::string getSelectedChoiceId() const { return selectedChoiceId_; }
156
157 // ---- variables (global / scene; scene auto-cleared on scene switch) ----
160 bool setVar(const std::string &name, ssq::Object value, const std::string &scope);
163 bool setVarValue(const std::string &name, const VarValue &value, const std::string &scope);
165 VarValue getVarValue(const std::string &name, const std::string &scope) const;
167 std::string getVarType(const std::string &name, const std::string &scope) const;
169 int getVarInt(const std::string &name, int defaultValue, const std::string &scope) const;
171 float getVarFloat(const std::string &name, float defaultValue, const std::string &scope) const;
173 bool getVarBool(const std::string &name, bool defaultValue, const std::string &scope) const;
175 std::string getVarString(const std::string &name, const std::string &defaultValue,
176 const std::string &scope) const;
178 bool hasVar(const std::string &name, const std::string &scope) const;
180 bool clearVar(const std::string &name, const std::string &scope);
182 void clearVars(const std::string &scope);
183
184 // ---- conditions ----
187 bool registerCondition(const std::string &name, ssq::Object fn);
189 bool unregisterCondition(const std::string &name);
191 bool evalCondition(ssq::Object table);
193 bool evalConditionData(const DataValue &cond);
194
195 // ---- content pools ----
197 int loadPoolsFromTable(ssq::Object table);
199 int loadPoolsFromData(const DataValue &root);
201 int replacePoolsFromData(const DataValue& root);
203 void clearPools();
205 int getPoolCount() const;
207 std::string getPoolId(int index) const;
209 bool hasPool(const std::string &id) const;
211 std::string getLastPoolsError() const { return lastPoolsError_; }
212
213 // ---- rng (weighted selection determinism) ----
216 void setRandomSeed(int seed);
218 int getRandomSeed() const { return int(rngState_); }
219
220 // ---- generated-line selection / play ----
222 std::string pickLine(const std::string &poolId, ssq::Object params);
224 std::string pickLineWithParams(const std::string &poolId,
225 const std::unordered_map<std::string, VarValue> &params);
227 bool playLine(const std::string &lineId, ssq::Object params);
229 bool playLineWithParams(const std::string &lineId,
230 const std::unordered_map<std::string, VarValue> &params);
232 bool playPool(const std::string &poolId, ssq::Object params);
234 bool playPoolWithParams(const std::string &poolId,
235 const std::unordered_map<std::string, VarValue> &params);
237 std::string getCurrentLineId() const { return currentLineId_; }
239 std::string getCurrentLineMeta(const std::string &field) const;
241 std::vector<std::string> getCurrentLineTags() const;
242
244 void update(float dt);
246 void reset();
247
249 bool captureState(StateValue& out) const;
250
257 bool restoreState(const StateValue& in, std::string* err = nullptr);
258
260 bool resetToDefaults();
261
262private:
263 int applyPoolsFromData(const DataValue& root, bool replace);
264 struct Character {
265 std::string id;
266 std::string displayName;
267 avatar::AvatarInstance *avatar = nullptr;
268 std::optional<size_t> avatarHook; // destroy-hook id on the bound avatar
269 std::string slot;
270 bool shown = false;
271 };
272
273 struct Choice {
274 std::string id;
275 std::string label;
276 };
277
278 enum class Phase { Idle, Typing, WaitingAdvance, WaitingChoice };
279
280 Character *findCharacter(const std::string &id);
281 const Character *findCharacter(const std::string &id) const;
282 void beginLine(const std::string &speakerId, const std::string &text);
283
284 std::vector<Character> characters_;
285 std::unordered_map<std::string, float> slotX_; // normalized 0..1
286
287 Phase phase_ = Phase::Idle;
288 std::string speakerId_;
289 std::string fullText_;
290 float typeSpeed_ = 40.f; // chars / second
291 float typed_ = 0.f;
292
293 std::vector<Choice> choices_;
294 std::string selectedChoiceId_;
295
296 bool lipSyncEnabled_ = true;
297 std::string lipSyncParameter_ = "mouthOpen";
298 float lipSyncAmplitude_ = 0.85f;
299 float lipSyncValue_ = 0.f;
300 float lipSyncTime_ = 0.f;
301
302 void updateLipSync(float dt);
303 void applyLipSyncToSpeaker();
304
305 // ---- procedural content (variables / conditions / pools) ----
306 struct Condition {
308 enum class Kind { Always, Cmp, All, Any, Not, Script };
309
310 Kind kind = Kind::Always;
311 std::string var;
312 std::string op;
314 std::vector<Condition> children;
315 std::string script;
316 };
317
318 struct Line {
319 std::string id;
320 std::string speaker;
321 std::string text;
322 std::string i18nKey;
323 double weight = 1.0;
324 Condition when;
325 std::unordered_map<std::string, std::string> meta;
326 std::vector<std::string> tags;
327 };
328
329 struct Pool {
330 std::string id;
331 int noRepeat = 3;
332 std::vector<Line> lines;
333 std::vector<size_t> recent;
334 };
335
336 std::unordered_map<std::string, VarValue> *varsForScope(const std::string &scope);
337 const std::unordered_map<std::string, VarValue> *varsForScope(const std::string &scope) const;
338 std::unordered_map<std::string, VarValue> mergedVars(
339 const std::unordered_map<std::string, VarValue> &params) const;
340 std::unordered_map<std::string, std::string> stringParams(
341 const std::unordered_map<std::string, VarValue> &vars) const;
342 bool parseCondition(const DataValue &v, Condition &out, std::string &error);
343 bool parseLineData(const std::string &poolId, const DataValue &v, int index, Line &line,
344 std::string &error);
345 bool evalConditionInternal(const Condition &c,
346 const std::unordered_map<std::string, VarValue> &merged,
347 const std::unordered_map<std::string, VarValue> &params,
348 const std::string &lineId) const;
349 bool evalScriptPredicate(const std::string &name,
350 const std::unordered_map<std::string, VarValue> &merged,
351 const std::unordered_map<std::string, VarValue> &params,
352 const std::string &lineId) const;
353 bool compareEq(const VarValue &a, const VarValue &b) const;
354 bool compareOrder(const std::string &op, const VarValue &a, const VarValue &b) const;
355 std::string interpolate(const std::string &tpl,
356 const std::unordered_map<std::string, VarValue> &vars) const;
357 Pool *findPool(const std::string &id);
358 const Pool *findPool(const std::string &id) const;
359 Line *findLine(const std::string &id);
360 const Line *findLine(const std::string &id) const;
361 void applyLineMeta(const Line &line);
362 void pollSceneChange();
363 uint32_t nextRandom();
364 double nextUnit();
365
366 std::unordered_map<std::string, VarValue> globalVars_;
367 std::unordered_map<std::string, VarValue> sceneVars_;
368 std::unordered_map<std::string, HSQOBJECT> predicates_;
369 std::vector<Pool> pools_;
370 std::string lastPoolsError_;
371 uint32_t rngState_ = 0x9E3779B9u;
372 std::string lastSceneName_;
373 std::string currentLineId_;
374 std::unordered_map<std::string, std::string> currentLineMeta_;
375 std::vector<std::string> currentLineTags_;
376 HSQUIRRELVM vm_ = nullptr;
377};
378
379} // namespace eve::dialogue
double value
int root
Definition AnimSmr.cpp:119
struct SQVM * HSQUIRRELVM
std::string label
#define EVENGINE_API_ORCHESTRATION
Definition Export.h:111
float v
std::int32_t c
JobScope scope
std::string text
TokenKind kind
std::string name
MeleePoint3 b
Definition MeleeHit.cpp:41
MeleePoint3 a
Definition MeleeHit.cpp:40
std::string error
Definition Package.cpp:60
std::string script
Definition PlayHost.cpp:116
std::string id
Definition PlayHost.cpp:108
std::uint32_t seed
Definition PointSet.cpp:807
int children
Definition TreeMesh.cpp:295
uint32_t index
std::vector< std::string_view > lines
Owning, renderer-independent dynamic values.
EVENGINE_API_FOUNDATION public API.
Definition Module.h:46
JSON-compatible state value tree used by state hot reload.
Definition StateValue.h:20
The canonical owning dynamic value used by data-facing protocols.
Definition Value.h:31
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:46
std::string getLastPoolsError() const
Returns the last pools error.
Definition Dialogue.h:211
float getLipSyncAmplitude() const
Returns the lip sync amplitude.
Definition Dialogue.h:134
std::string getSpeakerId() const
Returns the speaker id.
Definition Dialogue.h:113
std::string getCurrentLineId() const
Returns the current line id.
Definition Dialogue.h:237
std::string getFullText() const
Returns the full text.
Definition Dialogue.h:117
float getLipSyncValue() const
Returns the lip sync value.
Definition Dialogue.h:136
int getRandomSeed() const
Returns the random seed.
Definition Dialogue.h:218
std::string getLipSyncParameter() const
Returns the lip sync parameter.
Definition Dialogue.h:130
std::string getSelectedChoiceId() const
Returns the selected choice id.
Definition Dialogue.h:155
bool isLipSyncEnabled() const
True when lip sync enabled.
Definition Dialogue.h:126
float getTypeSpeed() const
Returns the type speed.
Definition Dialogue.h:100
const char * defaultValue
std::vector< ParamSpec > params
Vec3 interpolate(Vec3 start, Vec3 end, float amount) noexcept
Interpolate.
eve::Value VarValue
Definition Dialogue.h:37
NodeDesc when(bool cond, NodeDesc child)
Conditional: include child only when cond is true (empty group otherwise).
Definition NodeDesc.cpp:234
EVEngine ECS 集成层:底层实现使用 sunxfancy/ECS.hpp https://github.com/sunxfancy/ECS.hpp
Definition ECS.h:14
SettlementPipeline::Stage fn
bool enabled