mirror of
https://github.com/scratchfoundation/scratch-vm.git
synced 2024-12-23 14:32:59 -05:00
Allow ask to use say bubble via events
This commit is contained in:
parent
3fa1599b90
commit
16ca994818
3 changed files with 58 additions and 8 deletions
|
@ -23,10 +23,14 @@ class Scratch3LooksBlocks {
|
||||||
this._onTargetMoved = this._onTargetMoved.bind(this);
|
this._onTargetMoved = this._onTargetMoved.bind(this);
|
||||||
this._onResetBubbles = this._onResetBubbles.bind(this);
|
this._onResetBubbles = this._onResetBubbles.bind(this);
|
||||||
this._onTargetWillExit = this._onTargetWillExit.bind(this);
|
this._onTargetWillExit = this._onTargetWillExit.bind(this);
|
||||||
|
this._updateBubble = this._updateBubble.bind(this);
|
||||||
|
|
||||||
// Reset all bubbles on start/stop
|
// Reset all bubbles on start/stop
|
||||||
this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles);
|
this.runtime.on('PROJECT_STOP_ALL', this._onResetBubbles);
|
||||||
this.runtime.on('targetWasRemoved', this._onTargetWillExit);
|
this.runtime.on('targetWasRemoved', this._onTargetWillExit);
|
||||||
|
|
||||||
|
// Enable other blocks to use bubbles like ask/answer
|
||||||
|
this.runtime.on('SAY', this._updateBubble);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -53,19 +53,31 @@ class Scratch3SensingBlocks {
|
||||||
this._answer = answer;
|
this._answer = answer;
|
||||||
const questionObj = this._questionList.shift();
|
const questionObj = this._questionList.shift();
|
||||||
if (questionObj) {
|
if (questionObj) {
|
||||||
const resolve = questionObj[1];
|
const [_question, resolve, target, wasVisible] = questionObj;
|
||||||
|
// If the target was visible when asked, hide the say bubble.
|
||||||
|
if (wasVisible) {
|
||||||
|
this.runtime.emit('SAY', target, 'say', '');
|
||||||
|
}
|
||||||
resolve();
|
resolve();
|
||||||
this._askNextQuestion();
|
this._askNextQuestion();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_enqueueAsk (question, resolve) {
|
_enqueueAsk (question, resolve, target, wasVisible) {
|
||||||
this._questionList.push([question, resolve]);
|
this._questionList.push([question, resolve, target, wasVisible]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_askNextQuestion () {
|
_askNextQuestion () {
|
||||||
if (this._questionList.length > 0) {
|
if (this._questionList.length > 0) {
|
||||||
this.runtime.emit('QUESTION', this._questionList[0][0]);
|
const [question, _resolve, target, wasVisible] = this._questionList[0];
|
||||||
|
// If the target is visible, emit a blank question and use the
|
||||||
|
// say event to trigger a bubble.
|
||||||
|
if (wasVisible) {
|
||||||
|
this.runtime.emit('SAY', target, 'say', question);
|
||||||
|
this.runtime.emit('QUESTION', '');
|
||||||
|
} else {
|
||||||
|
this.runtime.emit('QUESTION', question);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,10 +86,11 @@ class Scratch3SensingBlocks {
|
||||||
this.runtime.emit('QUESTION', null);
|
this.runtime.emit('QUESTION', null);
|
||||||
}
|
}
|
||||||
|
|
||||||
askAndWait (args) {
|
askAndWait (args, util) {
|
||||||
|
const _target = util.target;
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
const isQuestionAsked = this._questionList.length > 0;
|
const isQuestionAsked = this._questionList.length > 0;
|
||||||
this._enqueueAsk(args.QUESTION, resolve);
|
this._enqueueAsk(args.QUESTION, resolve, _target, _target.visible);
|
||||||
if (!isQuestionAsked) {
|
if (!isQuestionAsked) {
|
||||||
this._askNextQuestion();
|
this._askNextQuestion();
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,9 +9,10 @@ test('getPrimitives', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('ask and answer', t => {
|
test('ask and answer with a hidden target', t => {
|
||||||
const rt = new Runtime();
|
const rt = new Runtime();
|
||||||
const s = new Sensing(rt);
|
const s = new Sensing(rt);
|
||||||
|
const util = {target: {visible: false}};
|
||||||
|
|
||||||
const expectedQuestion = 'a question';
|
const expectedQuestion = 'a question';
|
||||||
const expectedAnswer = 'the answer';
|
const expectedAnswer = 'the answer';
|
||||||
|
@ -24,7 +25,7 @@ test('ask and answer', t => {
|
||||||
});
|
});
|
||||||
|
|
||||||
// (1) Emit the question.
|
// (1) Emit the question.
|
||||||
const promise = s.askAndWait({QUESTION: expectedQuestion});
|
const promise = s.askAndWait({QUESTION: expectedQuestion}, util);
|
||||||
|
|
||||||
// (3) Ask block resolves after the answer is emitted.
|
// (3) Ask block resolves after the answer is emitted.
|
||||||
promise.then(() => {
|
promise.then(() => {
|
||||||
|
@ -32,3 +33,35 @@ test('ask and answer', t => {
|
||||||
t.end();
|
t.end();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('ask and answer with a visible target', t => {
|
||||||
|
const rt = new Runtime();
|
||||||
|
const s = new Sensing(rt);
|
||||||
|
const util = {target: {visible: true}};
|
||||||
|
|
||||||
|
const expectedQuestion = 'a question';
|
||||||
|
const expectedAnswer = 'the answer';
|
||||||
|
|
||||||
|
rt.removeAllListeners('SAY'); // Prevent say blocks from executing
|
||||||
|
|
||||||
|
rt.addListener('SAY', (target, type, question) => {
|
||||||
|
// Should emit SAY with the question
|
||||||
|
t.strictEqual(question, expectedQuestion);
|
||||||
|
});
|
||||||
|
|
||||||
|
rt.addListener('QUESTION', question => {
|
||||||
|
// Question should be blank for a visible target
|
||||||
|
t.strictEqual(question, '');
|
||||||
|
|
||||||
|
// Remove the say listener and add a new one to assert bubble is cleared
|
||||||
|
// by setting say to empty string after answer is received.
|
||||||
|
rt.removeAllListeners('SAY');
|
||||||
|
rt.addListener('SAY', (target, type, text) => {
|
||||||
|
t.strictEqual(text, '');
|
||||||
|
t.end();
|
||||||
|
});
|
||||||
|
rt.emit('ANSWER', expectedAnswer);
|
||||||
|
});
|
||||||
|
|
||||||
|
s.askAndWait({QUESTION: expectedQuestion}, util);
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in a new issue