- add dialog wrapper, so that "tutorial.dialog()" typed into the
Help->Nasal-Console opens the adjustment dialog - reset Nasal namespace for emebedded Nasal for every tutorial - rename <voice> to <audio> (in the hope that this won't be mixed up with Festival voice synthesis; should we call it <audio-sample>?) - rename <instruction> to <message> for consistency reasons, so there are now <step><message>s, <error><message>s, and <end><message>s
This commit is contained in:
parent
318c08f9c7
commit
dcd471b63d
1 changed files with 47 additions and 32 deletions
|
@ -30,16 +30,16 @@
|
||||||
#
|
#
|
||||||
# <step> - Tutorial step - a segment of the tutorial, consisting of
|
# <step> - Tutorial step - a segment of the tutorial, consisting of
|
||||||
# the following:
|
# the following:
|
||||||
# <instruction> - Text instruction displayed when the tutorial reaches
|
# <message> - Text instruction displayed when the tutorial reaches
|
||||||
# this step, and when neither the exit nor any error
|
# this step, and when neither the exit nor any error
|
||||||
# criteria have been fulfilled
|
# criteria have been fulfilled
|
||||||
# <instruction-voice> - Optional: wav filename to play when displaying
|
# <audio> - Optional: wav filename to play when displaying
|
||||||
# instruction
|
# instruction
|
||||||
# <error> - Error conditions, causing error messages to be displayed.
|
# <error> - Error conditions, causing error messages to be displayed.
|
||||||
# The tutorial doesn't advance while any error conditions are
|
# The tutorial doesn't advance while any error conditions are
|
||||||
# fulfilled. Consists of one or more check nodes:
|
# fulfilled. Consists of one or more check nodes:
|
||||||
# <message> - Error message to display if error criteria fulfilled.
|
# <message> - Error message to display if error criteria fulfilled.
|
||||||
# <msg-voice> - Optional: wav filename to play when error condition fulfilled.
|
# <audio> - Optional: wav filename to play when error condition fulfilled.
|
||||||
# <condition> - error condition (see $FG_ROOT/Docs/README.condition)
|
# <condition> - error condition (see $FG_ROOT/Docs/README.condition)
|
||||||
#
|
#
|
||||||
# <exit> - Exit criteria causing tutorial to progress to next step.
|
# <exit> - Exit criteria causing tutorial to progress to next step.
|
||||||
|
@ -47,7 +47,7 @@
|
||||||
#
|
#
|
||||||
# <end>
|
# <end>
|
||||||
# <message>> - Optional: Text to display when the tutorial exits the last step.
|
# <message>> - Optional: Text to display when the tutorial exits the last step.
|
||||||
# <msg-voice> - Optional: wav filename to play when the tutorial exits the last step
|
# <audio> - Optional: wav filename to play when the tutorial exits the last step
|
||||||
|
|
||||||
#
|
#
|
||||||
# GLOBAL VARIABLES
|
# GLOBAL VARIABLES
|
||||||
|
@ -93,6 +93,7 @@ var startTutorial = func {
|
||||||
|
|
||||||
set_properties(tutorial.getChild("init"));
|
set_properties(tutorial.getChild("init"));
|
||||||
set_cursor(tutorial);
|
set_cursor(tutorial);
|
||||||
|
init_nasal();
|
||||||
run_nasal(tutorial);
|
run_nasal(tutorial);
|
||||||
|
|
||||||
var dir = tutorial.getChild("audio-dir");
|
var dir = tutorial.getChild("audio-dir");
|
||||||
|
@ -130,6 +131,7 @@ var startTutorial = func {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var stopTutorial = func {
|
var stopTutorial = func {
|
||||||
is_running(0);
|
is_running(0);
|
||||||
set_cursor(props.Node.new());
|
set_cursor(props.Node.new());
|
||||||
|
@ -137,7 +139,6 @@ var stopTutorial = func {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# stepTutorial
|
# stepTutorial
|
||||||
#
|
#
|
||||||
# This function does the actual work. It is executed every 5 seconds.
|
# This function does the actual work. It is executed every 5 seconds.
|
||||||
|
@ -171,14 +172,14 @@ var stepTutorial = func {
|
||||||
message = m.getValue();
|
message = m.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
var v = end.getNode("voice");
|
var v = end.getNode("audio");
|
||||||
if (v != nil) {
|
if (v != nil) {
|
||||||
voice = v.getValue();
|
voice = v.getValue();
|
||||||
}
|
}
|
||||||
run_nasal(end);
|
run_nasal(end);
|
||||||
}
|
}
|
||||||
say(message, voice);
|
say(message, voice);
|
||||||
say("Deviations : " ~ num_errors);
|
say("Deviations: " ~ num_errors);
|
||||||
is_running(0);
|
is_running(0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -186,7 +187,7 @@ var stepTutorial = func {
|
||||||
var step = tutorial.getChildren("step")[current_step];
|
var step = tutorial.getChildren("step")[current_step];
|
||||||
set_cursor(step);
|
set_cursor(step);
|
||||||
|
|
||||||
var instr = step.getChild("instruction");
|
var instr = step.getChild("message");
|
||||||
message = instr != nil ? instr.getValue() : "Tutorial step " ~ current_step;
|
message = instr != nil ? instr.getValue() : "Tutorial step " ~ current_step;
|
||||||
|
|
||||||
if (!num_step_runs) {
|
if (!num_step_runs) {
|
||||||
|
@ -198,8 +199,9 @@ var stepTutorial = func {
|
||||||
# We then do not go through the error or exit processing, giving the user
|
# We then do not go through the error or exit processing, giving the user
|
||||||
# time to react to the instructions.
|
# time to react to the instructions.
|
||||||
|
|
||||||
if (step.getChild("instruction-voice") != nil) {
|
var v = step.getChild("audio");
|
||||||
voice = step.getChild("instruction-voice").getValue();
|
if (v != nil) {
|
||||||
|
voice = v.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
say(message, voice);
|
say(message, voice);
|
||||||
|
@ -224,7 +226,7 @@ var stepTutorial = func {
|
||||||
if (m != nil) {
|
if (m != nil) {
|
||||||
message = m.getValue();
|
message = m.getValue();
|
||||||
|
|
||||||
var v = e.getChild("msg-voice");
|
var v = e.getChild("audio");
|
||||||
voice = v != nil ? v.getValue() : nil;
|
voice = v != nil ? v.getValue() : nil;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -254,6 +256,7 @@ var stepTutorial = func {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# scan all <set> blocks and set their <property> to <value>
|
# scan all <set> blocks and set their <property> to <value>
|
||||||
# <set>
|
# <set>
|
||||||
# <property>/foo/bar</property>
|
# <property>/foo/bar</property>
|
||||||
|
@ -273,6 +276,7 @@ var set_properties = func(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var set_cursor = func(node) {
|
var set_cursor = func(node) {
|
||||||
node != nil or return;
|
node != nil or return;
|
||||||
var loc = node.getNode("marker");
|
var loc = node.getNode("marker");
|
||||||
|
@ -292,7 +296,7 @@ var set_cursor = func(node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Set and return running state. Disable/enable stop menu.
|
# Set and return running state. Disable/enable stop menu.
|
||||||
#
|
#
|
||||||
var is_running = func(which = nil) {
|
var is_running = func(which = nil) {
|
||||||
|
@ -305,14 +309,14 @@ var is_running = func(which = nil) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#
|
|
||||||
# Output the message and optional sound recording.
|
# Output the message and optional sound recording.
|
||||||
#
|
#
|
||||||
var m_lastmsgcount = 0;
|
var lastmsgcount = 0;
|
||||||
var say = func(msg, snd = nil, lerror = 0) {
|
var say = func(msg, snd = nil, error = 0) {
|
||||||
var lastmsg = getprop("/sim/tutorial/last-message");
|
var lastmsg = getprop("/sim/tutorial/last-message");
|
||||||
|
|
||||||
if ((msg != lastmsg) or (lerror == 1 and m_lastmsgcount == 1)) {
|
if (msg != lastmsg or (error == 1 and lastmsgcount == 1)) {
|
||||||
# Error messages are only displayed every 10 seconds (2 iterations)
|
# Error messages are only displayed every 10 seconds (2 iterations)
|
||||||
# Other messages are only displayed if they change
|
# Other messages are only displayed if they change
|
||||||
if (snd == nil) {
|
if (snd == nil) {
|
||||||
|
@ -321,40 +325,51 @@ var say = func(msg, snd = nil, lerror = 0) {
|
||||||
} else {
|
} else {
|
||||||
# Play the audio, and write directly to the screen-logger to avoid
|
# Play the audio, and write directly to the screen-logger to avoid
|
||||||
# any tts being sent to festival.
|
# any tts being sent to festival.
|
||||||
lprop = { path : audio_dir, file : snd };
|
var prop = { path : audio_dir, file : snd };
|
||||||
fgcommand("play-audio-message", props.Node.new(lprop) );
|
fgcommand("play-audio-message", props.Node.new(prop));
|
||||||
screen.log.write(msg, 1, 1, 1);
|
screen.log.write(msg, 1, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
setprop("/sim/tutorial/last-message", msg);
|
setprop("/sim/tutorial/last-message", msg);
|
||||||
m_lastmsgcount = 0;
|
lastmsgcount = 0;
|
||||||
} else {
|
} else {
|
||||||
m_lastmsgcount += 1;
|
lastmsgcount += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var run_nasal = func(node) {
|
var run_nasal = func(node) {
|
||||||
node != nil or return;
|
node != nil or return;
|
||||||
foreach (var n; node.getChildren("nasal")) {
|
foreach (var n; node.getChildren("nasal")) {
|
||||||
if (n.getNode("module") == nil) {
|
if (n.getNode("module") == nil) {
|
||||||
n.getNode("module", 1).setValue("__tut");
|
n.getNode("module", 1).setValue("__tutorial");
|
||||||
}
|
}
|
||||||
fgcommand("nasal", n);
|
fgcommand("nasal", n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
globals.__tut = {
|
|
||||||
say : say,
|
# Set up the namespace for embedded Nasal.
|
||||||
next : func { current_step += 1; num_step_runs = 0 },
|
#
|
||||||
previous : func {
|
var init_nasal = func {
|
||||||
if (current_step > 0) {
|
globals.__tutorial = {
|
||||||
current_step -= 1;
|
say : say,
|
||||||
}
|
next : func { current_step += 1; num_step_runs = 0 },
|
||||||
num_step_runs = 0;
|
previous : func {
|
||||||
},
|
if (current_step > 0) {
|
||||||
};
|
current_step -= 1;
|
||||||
|
}
|
||||||
|
num_step_runs = 0;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
var dialog = func {
|
||||||
|
fgcommand("dialog-show", props.Node.new({ "dialog-name" : "marker-adjust" }));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var marker = nil;
|
var marker = nil;
|
||||||
|
|
Loading…
Add table
Reference in a new issue