Skip to content

Commit 6e4613b

Browse files
committed
feat: stop self.when of event blocks
1 parent 76e3782 commit 6e4613b

File tree

5 files changed

+331
-304
lines changed

5 files changed

+331
-304
lines changed

src/lib/ruby-generator/event.js

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,31 +12,31 @@ export default function (Generator) {
1212
Generator.event_whenkeypressed = function (block) {
1313
block.isStatement = true;
1414
const key = Generator.quote_(Generator.getFieldValue(block, 'KEY_OPTION') || null);
15-
return `${Generator.spriteName()}.when(:key_pressed, ${key}) do\n`;
15+
return `when_key_pressed(${key}) do\n`;
1616
};
1717

1818
Generator.event_whenthisspriteclicked = function (block) {
1919
block.isStatement = true;
20-
return `${Generator.spriteName()}.when(:clicked) do\n`;
20+
return `when_clicked do\n`;
2121
};
2222

2323
Generator.event_whenbackdropswitchesto = function (block) {
2424
block.isStatement = true;
2525
const backdrop = Generator.quote_(Generator.getFieldValue(block, 'BACKDROP') || '');
26-
return `${Generator.spriteName()}.when(:backdrop_switches, ${backdrop}) do\n`;
26+
return `when_backdrop_switches(${backdrop}) do\n`;
2727
};
2828

2929
Generator.event_whengreaterthan = function (block) {
3030
block.isStatement = true;
3131
const lh = Generator.quote_(Generator.getFieldValue(block, 'WHENGREATERTHANMENU').toLowerCase() || '');
3232
const rh = Generator.valueToCode(block, 'VALUE', Generator.ORDER_NONE) || '0';
33-
return `${Generator.spriteName()}.when(:greater_than, ${lh}, ${rh}) do\n`;
33+
return `when_greater_than(${lh}, ${rh}) do\n`;
3434
};
3535

3636
Generator.event_whenbroadcastreceived = function (block) {
3737
block.isStatement = true;
3838
const message = Generator.getFieldValue(block, 'BROADCAST_OPTION');
39-
return `${Generator.spriteName()}.when(:receive, ${Generator.quote_(message)}) do\n`;
39+
return `when_receive(${Generator.quote_(message)}) do\n`;
4040
};
4141

4242
Generator.event_broadcast = function (block) {
@@ -56,7 +56,7 @@ export default function (Generator) {
5656

5757
Generator.event_whenstageclicked = function (block) {
5858
block.isStatement = true;
59-
return `Stage.when(:clicked) do\n`;
59+
return `when_clicked do\n`;
6060
};
6161

6262
return Generator;

src/lib/ruby-to-blocks-converter/event.js

Lines changed: 107 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -112,16 +112,117 @@ const EventConverter = {
112112
this._addInput(block, 'BROADCAST_INPUT', inputBlock, shadowBlock);
113113
}
114114
break;
115-
case 'when_flag_clicked':
116-
if (args.length == 0 && rubyBlockArgs && rubyBlockArgs.length === 0 && rubyBlock) {
117-
block = this._createBlock('event_whenflagclicked', 'hat');
118-
this._setParent(rubyBlock, block);
119-
}
120-
break;
121115
}
122116
}
123117

124118
return block;
119+
},
120+
121+
register: function (converter) {
122+
converter.registerCallMethod('self', 'when_flag_clicked', 0, params => {
123+
const {rubyBlockArgs, rubyBlock} = params;
124+
125+
if (!rubyBlockArgs) return null;
126+
if (rubyBlockArgs.length !== 0) return null;
127+
if (!rubyBlock) return null;
128+
129+
const block = converter.createBlock('event_whenflagclicked', 'hat');
130+
converter.setParent(rubyBlock, block);
131+
return block;
132+
});
133+
134+
converter.registerCallMethod('self', 'when_key_pressed', 1, params => {
135+
const {args, rubyBlockArgs, rubyBlock} = params;
136+
137+
if (!converter.isString(args[0])) return null;
138+
if (KeyOptions.indexOf(args[0].toString()) < 0) return null;
139+
140+
if (!rubyBlockArgs) return null;
141+
if (rubyBlockArgs.length !== 0) return null;
142+
if (!rubyBlock) return null;
143+
144+
const block = converter.createBlock('event_whenkeypressed', 'hat');
145+
converter.addField(block, 'KEY_OPTION', args[0]);
146+
converter.setParent(rubyBlock, block);
147+
return block;
148+
});
149+
150+
converter.registerCallMethod('sprite', 'when_clicked', 0, params => {
151+
const {rubyBlockArgs, rubyBlock} = params;
152+
153+
if (!rubyBlockArgs) return null;
154+
if (rubyBlockArgs.length !== 0) return null;
155+
if (!rubyBlock) return null;
156+
157+
const block = converter.createBlock('event_whenthisspriteclicked', 'hat');
158+
converter.setParent(rubyBlock, block);
159+
return block;
160+
});
161+
162+
converter.registerCallMethod('stage', 'when_clicked', 0, params => {
163+
const {rubyBlockArgs, rubyBlock} = params;
164+
165+
if (!rubyBlockArgs) return null;
166+
if (rubyBlockArgs.length !== 0) return null;
167+
if (!rubyBlock) return null;
168+
169+
const block = converter.createBlock('event_whenstageclicked', 'hat');
170+
converter.setParent(rubyBlock, block);
171+
return block;
172+
});
173+
174+
converter.registerCallMethod('self', 'when_backdrop_switches', 1, params => {
175+
const {args, rubyBlockArgs, rubyBlock} = params;
176+
177+
if (!converter.isString(args[0])) return null;
178+
179+
if (!rubyBlockArgs) return null;
180+
if (rubyBlockArgs.length !== 0) return null;
181+
if (!rubyBlock) return null;
182+
183+
const block = converter.createBlock('event_whenbackdropswitchesto', 'hat');
184+
converter.addField(block, 'BACKDROP', args[0]);
185+
converter.setParent(rubyBlock, block);
186+
return block;
187+
});
188+
189+
converter.registerCallMethod('self', 'when_greater_than', 2, params => {
190+
const {args, rubyBlockArgs, rubyBlock} = params;
191+
192+
if (!converter.isString(args[0])) return null;
193+
const args0 = args[0].toString().toUpperCase();
194+
if (GreaterThanMenu.indexOf(args0) < 0) return null;
195+
if (!converter.isNumberOrBlock(args[1])) return null;
196+
197+
if (!rubyBlockArgs) return null;
198+
if (rubyBlockArgs.length !== 0) return null;
199+
if (!rubyBlock) return null;
200+
201+
const block = converter.createBlock('event_whengreaterthan', 'hat');
202+
converter.addField(block, 'WHENGREATERTHANMENU', args0);
203+
converter.addNumberInput(block, 'VALUE', 'math_number', args[1], 10);
204+
converter.setParent(rubyBlock, block);
205+
return block;
206+
});
207+
208+
converter.registerCallMethod('self', 'when_receive', 1, params => {
209+
const {args, rubyBlockArgs, rubyBlock} = params;
210+
211+
if (!converter.isString(args[0])) return null;
212+
213+
if (!rubyBlockArgs) return null;
214+
if (rubyBlockArgs.length !== 0) return null;
215+
if (!rubyBlock) return null;
216+
217+
const broadcastMsg = converter.lookupOrCreateBroadcastMsg(args[0]);
218+
const block = converter.createBlock('event_whenbroadcastreceived', 'hat');
219+
converter.addField(block, 'BROADCAST_OPTION', broadcastMsg.name, {
220+
id: broadcastMsg.id,
221+
variableType: Variable.BROADCAST_MESSAGE_TYPE
222+
});
223+
converter.setParent(rubyBlock, block);
224+
return block;
225+
});
125226
}
126227
};
127228

src/lib/ruby-to-blocks-converter/index.js

Lines changed: 102 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,12 @@ class RubyToBlocksConverter {
104104
MyBlocksConverter,
105105
MakeyMakeyConverter
106106
];
107+
this._receiverToMethods = {};
107108
this.reset();
109+
110+
this._converters.forEach(x => {
111+
if (x.hasOwnProperty('register')) x.register(this);
112+
});
108113
}
109114

110115
get errors () {
@@ -270,6 +275,79 @@ class RubyToBlocksConverter {
270275
});
271276
}
272277

278+
registerCallMethod (receiverName, name, numArgs, createBlockFunc) {
279+
if (receiverName === 'self') {
280+
this.registerCallMethod('sprite', name, numArgs, createBlockFunc);
281+
this.registerCallMethod('stage', name, numArgs, createBlockFunc);
282+
return;
283+
}
284+
let methodToNumArgs = this._receiverToMethods[receiverName];
285+
if (!methodToNumArgs) methodToNumArgs = this._receiverToMethods[receiverName] = {};
286+
287+
let numArgsToCreateBlockFuncs = methodToNumArgs[name];
288+
if (!numArgsToCreateBlockFuncs) numArgsToCreateBlockFuncs = methodToNumArgs[name] = {};
289+
290+
let createBlockFuncs = numArgsToCreateBlockFuncs[numArgs];
291+
if (!createBlockFuncs) createBlockFuncs = numArgsToCreateBlockFuncs[numArgs] = [];
292+
293+
createBlockFuncs.push(createBlockFunc);
294+
}
295+
296+
_callMethod (receiver, name, args, rubyBlockArgs, rubyBlock, node) {
297+
const receiverName = this._getReceiverName(receiver);
298+
if (!receiverName) return null;
299+
300+
const methodToNumArgs = this._receiverToMethods[receiverName];
301+
if (!methodToNumArgs) return null;
302+
303+
const numArgsToCreateBlockFuncs = methodToNumArgs[name];
304+
if (!numArgsToCreateBlockFuncs) return null;
305+
306+
const createBlockFuncs = numArgsToCreateBlockFuncs[args.length];
307+
if (!createBlockFuncs) return null;
308+
309+
const params = {
310+
receiver: receiver,
311+
receiverName: receiverName,
312+
name: name,
313+
args: args,
314+
rubyBlockArgs: rubyBlockArgs,
315+
rubyBlock: rubyBlock,
316+
node: node
317+
};
318+
for (let i = 0; i < createBlockFuncs.length; i++) {
319+
const createBlockFunc = createBlockFuncs[i];
320+
const block = createBlockFunc.apply(this, [params]);
321+
if (block) return block;
322+
}
323+
324+
return null;
325+
}
326+
327+
_getReceiverName (receiver) {
328+
if (this._isSelf(receiver) || receiver === Opal.nil) {
329+
if (this._context.target && this._context.target.isStage) {
330+
return 'stage';
331+
}
332+
return 'sprite';
333+
}
334+
335+
if (this._isBlock(receiver) && receiver.opcode === 'ruby_expression') {
336+
const textBlock = this._context.blocks[receiver.inputs.EXPRESSION.block];
337+
return textBlock.fields.TEXT.value;
338+
}
339+
340+
return null;
341+
}
342+
343+
createBlock (opcode, type, attributes = {}) {
344+
return this._createBlock(opcode, type, attributes);
345+
}
346+
347+
setParent (block, parent) {
348+
return this._setParent(block, parent);
349+
}
350+
273351
_callConvertersHandler (handlerName, ...args) {
274352
for (let i = 0; i < this._converters.length; i++) {
275353
const converter = this._converters[i];
@@ -386,6 +464,10 @@ class RubyToBlocksConverter {
386464
return block instanceof Primitive && block.type === 'self';
387465
}
388466

467+
isString (value) {
468+
return this._isString(value);
469+
}
470+
389471
_isString (value) {
390472
return _.isString(value) || (value && value.type === 'str');
391473
}
@@ -434,6 +516,10 @@ class RubyToBlocksConverter {
434516
return /^value/.test(this._getBlockType(block));
435517
}
436518

519+
isNumberOrBlock (numberOrBlock) {
520+
return this._isNumberOrBlock(numberOrBlock);
521+
}
522+
437523
_isNumberOrBlock (numberOrBlock) {
438524
return this._isNumber(numberOrBlock) || this._isValueBlock(numberOrBlock);
439525
}
@@ -565,6 +651,10 @@ class RubyToBlocksConverter {
565651
return block;
566652
}
567653

654+
addField (block, name, value, attributes = {}) {
655+
return this._addField(block, name, value, attributes);
656+
}
657+
568658
_addField (block, name, value, attributes = {}) {
569659
if (!this._isBlock(block)) {
570660
return;
@@ -594,6 +684,10 @@ class RubyToBlocksConverter {
594684
};
595685
}
596686

687+
addNumberInput (block, name, opcode, inputValue, shadowValue) {
688+
return this._addNumberInput(block, name, opcode, inputValue, shadowValue);
689+
}
690+
597691
_addNumberInput (block, name, opcode, inputValue, shadowValue) {
598692
let shadowBlock;
599693
if (!this._isNumber(inputValue)) {
@@ -696,6 +790,10 @@ class RubyToBlocksConverter {
696790
return this._lookupOrCreateVariableOrList(name, Variable.LIST_TYPE);
697791
}
698792

793+
lookupOrCreateBroadcastMsg (name) {
794+
return this._lookupOrCreateBroadcastMsg(name);
795+
}
796+
699797
_lookupOrCreateBroadcastMsg (name) {
700798
name = name.toString();
701799
const key = name.toLowerCase();
@@ -996,7 +1094,10 @@ class RubyToBlocksConverter {
9961094
rubyBlock = this._processStatement(rubyBlockNode);
9971095
}
9981096

999-
let block = this._callConvertersHandler('onSend', receiver, name, args, rubyBlockArgs, rubyBlock, node);
1097+
let block = this._callMethod(receiver, name, args, rubyBlockArgs, rubyBlock, node);
1098+
if (!block) {
1099+
block = this._callConvertersHandler('onSend', receiver, name, args, rubyBlockArgs, rubyBlock, node);
1100+
}
10001101
if (!block) {
10011102
if ((this._isSelf(receiver) || receiver === Opal.nil) && !rubyBlock) {
10021103
switch (name) {

0 commit comments

Comments
 (0)