1 /**
2 * Copyright © Novelate 2020
3 * License: MIT (https://github.com/Novelate/NovelateEngine/blob/master/LICENSE)
4 * Author: Jacob Jensen (bausshf)
5 * Website: https://novelate.com/
6 * ------
7 * Novelate is a free and open-source visual novel engine and framework written in the D programming language.
8 * It can be used freely for both personal and commercial projects.
9 * ------
10 * Module Description:
11 * This module handles scenes.
12 */
13 module novelate.scripting.scene;
14
15 import std.conv : to;
16 import std.algorithm : countUntil, endsWith;
17
18 /// Wrapper around a scene configuration.
19 final class NovelateScene
20 {
21 private:
22 /// The name.
23 string _name;
24 /// The music.
25 string _music;
26 /// The background.
27 string _background;
28 /// The animation.
29 string _animation;
30 /// The animation direction.
31 string _animationDirection;
32 /// The animation start position.
33 string _animationStartPosition;
34 /// Boolean determining whether the scene name should be displayed or not.
35 bool _displaySceneName;
36 /// Boolean determining whether the configuration is parsing actions.
37 bool _parseActions;
38 /// The actions.
39 NovelateSceneAction[] _actions;
40
41 public:
42 final:
43 package(novelate)
44 {
45 this(string name)
46 {
47 _name = name;
48
49 _actions = [];
50 }
51
52 /**
53 * Updates the scene with a line to parse from the parsed Novelate content.
54 * Params:
55 * line = The line to parse.
56 */
57 void updateScene(string line)
58 {
59 if (line == "---")
60 {
61 _parseActions = true;
62 }
63 else
64 {
65 if (_parseActions)
66 {
67 if (line == "===")
68 {
69 _actions ~= new NovelateSceneAction(NovelateSceneActionType.actionChange, line);
70 }
71 else
72 {
73 auto valueIndex = line.countUntil("=");
74
75 if (valueIndex < 1)
76 {
77 if (line.endsWith(";"))
78 {
79 _actions ~= new NovelateSceneAction(NovelateSceneActionType.action, line[0 .. $-1]);
80 }
81 else
82 {
83 _actions ~= new NovelateSceneAction(NovelateSceneActionType.characterChange, line);
84 }
85 }
86 else
87 {
88 import std.array : replace;
89
90 auto name = line[0 .. valueIndex];
91 auto value = line[valueIndex + 1 .. $];
92
93 _actions ~= new NovelateSceneAction(NovelateSceneActionType.option, name, value.replace("\\n", "\n"));
94 }
95 }
96 }
97 else
98 {
99 auto valueIndex = line.countUntil("=");
100
101 if (valueIndex < 1)
102 {
103 return;
104 }
105
106 auto name = line[0 .. valueIndex];
107 auto value = line[valueIndex + 1 .. $];
108
109 switch (name)
110 {
111 case "Music": _music = value; break;
112 case "Background": _background = value; break;
113 case "Animation": _animation = value; break;
114 case "AnimationDirection": _animationDirection = value; break;
115 case "AnimationStartPosition": _animationStartPosition = value; break;
116 case "DisplaySceneName": _displaySceneName = to!bool(value); break;
117
118 default: break;
119 }
120 }
121 }
122 }
123 }
124
125 @property
126 {
127 /// Gets the name of the scene.
128 string name() { return _name; }
129
130 /// Gets the music of the scene.
131 string music() { return _music; }
132
133 /// Gets the background of the scene.
134 string background() { return _background; }
135
136 /// Gets the animation of the scene.
137 string animation() { return _animation; }
138
139 /// Gets the animation direction of the scene.
140 string animationDirection() { return _animationDirection; }
141
142 /// Gets the animation start position of the scene.
143 string animationStartPosition() { return _animationStartPosition; }
144
145 /// Gets a boolean determining whether the scene name should be displayed or not.
146 bool displaySceneName() { return _displaySceneName; }
147
148 /// Gets the actions of the scene.
149 NovelateSceneAction[] actions() { return _actions; }
150 }
151 }
152
153 /// Enumeration of scene action types.
154 enum NovelateSceneActionType
155 {
156 /// A character change.
157 characterChange,
158 /// An option. This means an optiion for inputting configurations, setting data etc.
159 option,
160 /// An action to execute.
161 action,
162 /// An action change. This forces a wait for the next set of actions.
163 actionChange
164 }
165
166 /// Wrapper around a scene action.
167 final class NovelateSceneAction
168 {
169 private:
170 /// The type.
171 NovelateSceneActionType _type;
172 /// The name.
173 string _name;
174 /// The value.
175 string _value;
176
177 public:
178 final:
179 /**
180 * Creates a new scene action.
181 * Params:
182 * type = The type of the scene action.
183 * name = The name of the scene action.
184 */
185 this(NovelateSceneActionType type, string name)
186 {
187 _type = type;
188 _name = name;
189 }
190
191 /**
192 * Creates a new scene action.
193 * Params:
194 * type = The type of the scene action.
195 * name = The name of the scene action.
196 * value = The value of the scene action.
197 */
198 this(NovelateSceneActionType type, string name, string value)
199 {
200 this(type, name);
201
202 _value = value;
203 }
204
205 @property
206 {
207 /// Gets the type.
208 NovelateSceneActionType type() { return _type; }
209
210 /// Gets the name.
211 string name() { return _name; }
212
213 /// Gets the value.
214 string value() { return _value; }
215 }
216 }
217
218 /// The scene collection.
219 private NovelateScene[string] _scenes;
220
221 public:
222 /**
223 * Gets a scene.
224 * Params:
225 * name = The name of the scene to get.
226 * Returns:
227 * The scene.
228 */
229 NovelateScene getScene(string name)
230 {
231 if (!_scenes)
232 {
233 return null;
234 }
235
236 return _scenes.get(name, null);
237 }
238
239 package(novelate):
240 /**
241 * Creates a scene base.
242 * Params:
243 * name = The name of the scene to create a base for.
244 * Returns:
245 * The scene base created.
246 */
247 NovelateScene createSceneBase(string name)
248 {
249 auto scene = new NovelateScene(name);
250
251 _scenes[scene.name] = scene;
252
253 return scene;
254 }