Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

STCC-274 Convert Change tempo by X [TN] #230

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions src/scratchtocatrobat/converter/converter.py
Expand Up @@ -32,6 +32,7 @@
from org.catrobat.catroid import ProjectManager
import org.catrobat.catroid.common as catcommon
import org.catrobat.catroid.content as catbase
from org.catrobat.catroid.content.bricks.brickspinner import PickableDrum
from org.catrobat.catroid.ui.fragment import SpriteFactory
import org.catrobat.catroid.content.bricks as catbricks
import org.catrobat.catroid.formulaeditor as catformula
Expand Down Expand Up @@ -438,6 +439,11 @@ class _ScratchToCatrobat(object):
"changeVolumeBy:": catbricks.ChangeVolumeByNBrick,
"setVolumeTo:": catbricks.SetVolumeToBrick,

# music
"drum:duration:elapsed:from:": catbricks.PlayDrumForBeatsBrick,
"noteOn:duration:elapsed:from:": catbricks.PlayNoteForBeatsBrick,
"changeTempoBy:": catbricks.ChangeTempoByNBrick,

# bubble bricks
"say:duration:elapsed:from:": catbricks.SayForBubbleBrick,
"say:": catbricks.SayBubbleBrick,
Expand Down Expand Up @@ -2858,6 +2864,7 @@ def _convert_delete_line_of_list_block(self):
deleteItemBrick.setFormulaWithBrickField(catbricks.Brick.BrickField.LIST_DELETE_ITEM, index_formula)

return deleteItemBrick

if position == "all":
loop_condition_formula = catrobat.create_formula_with_value(self._converted_helper_brick_or_formula_element([list_name], "lineCountOfList:"))
catr_loop_start_brick = catbricks.RepeatBrick(loop_condition_formula)
Expand Down Expand Up @@ -3436,3 +3443,35 @@ def _convert_note_block(self):
if isinstance(arg, (str, unicode)) or isinstance(arg, catformula.Formula):
return self.CatrobatClass(arg)
log.warn("Invalid argument for NoteBrick: " + arg)

@_register_handler(_block_name_to_handler_map, "drum:duration:elapsed:from:")
def _convert_play_drum_for_beats_block(self):
[drum, duration] = self.arguments

try:
drum_int = int(drum)
except ValueError:
log.debug("There is no integer in DRUM")
return

drum_selection = PickableDrum.values()[drum_int - 1]
assert drum_selection is not None

play_drum_brick = self.CatrobatClass(catformula.Formula(duration))
play_drum_brick.drumSelection = drum_selection

return play_drum_brick

@_register_handler(_block_name_to_handler_map, "noteOn:duration:elapsed:from:")
def _convert_play_note_for_beats_block(self):
[note, duration] = self.arguments

play_note_brick = self.CatrobatClass(catformula.Formula(note), catformula.Formula(duration))
return play_note_brick

@_register_handler(_block_name_to_handler_map, "changeTempoBy:")
def _convert_change_tempo_by_block(self):
[tempo] = self.arguments

change_tempo_brick = self.CatrobatClass(catformula.Formula(tempo))
return change_tempo_brick
42 changes: 42 additions & 0 deletions src/scratchtocatrobat/converter/test_converter.py
Expand Up @@ -31,6 +31,7 @@
import org.catrobat.catroid.content.bricks.Brick as catbasebrick
import org.catrobat.catroid.formulaeditor as catformula
import org.catrobat.catroid.formulaeditor.FormulaElement.ElementType as catElementType
from scratchtocatrobat.scratch.scratch3visitor.scratch2_json_format import Scratch3_2Opcodes as opcodes
import xml.etree.cElementTree as ET

from scratchtocatrobat.converter import catrobat, converter, mediaconverter
Expand Down Expand Up @@ -1417,6 +1418,46 @@ def test_can_convert_insert_at_random_position_in_list_block(self):
assert formula_tree_value.leftChild == None
assert formula_tree_value.rightChild == None

# drum:duration:elapsed:from:
def test_can_convert_play_drum_for_beats_block(self):
drum = 2
beats = 1.0
scratch_block = ["drum:duration:elapsed:from:", drum, beats]
[catr_brick] = self.block_converter._catrobat_bricks_from(scratch_block, DUMMY_CATR_SPRITE)
assert isinstance(catr_brick, catbricks.PlayDrumForBeatsBrick)

formula_tree_list_delete_item = catr_brick.getFormulaWithBrickField(catbasebrick.BrickField.PLAY_DRUM).formulaTree # @UndefinedVariable
assert formula_tree_list_delete_item.type == catformula.FormulaElement.ElementType.NUMBER
assert formula_tree_list_delete_item.value == str(beats)
assert catr_brick.drumSelection.value == 35

# noteOn:duration:elapsed:from:
def test_can_convert_play_note_for_beats_block(self):
note = 60.0
beats = 1.0
scratch_block = ["noteOn:duration:elapsed:from:", note, beats]
[catr_brick] = self.block_converter._catrobat_bricks_from(scratch_block, DUMMY_CATR_SPRITE)
assert isinstance(catr_brick, catbricks.PlayNoteForBeatsBrick)

formula_tree_list_delete_item = catr_brick.getFormulaWithBrickField(catbasebrick.BrickField.NOTE_TO_PLAY).formulaTree # @UndefinedVariable
assert formula_tree_list_delete_item.type == catformula.FormulaElement.ElementType.NUMBER
assert formula_tree_list_delete_item.value == str(note)

formula_tree_list_delete_item = catr_brick.getFormulaWithBrickField(catbasebrick.BrickField.BEATS_TO_PLAY_NOTE).formulaTree # @UndefinedVariable
assert formula_tree_list_delete_item.type == catformula.FormulaElement.ElementType.NUMBER
assert formula_tree_list_delete_item.value == str(beats)

# changeTempoBy:
def test_can_convert_change_tempo_by_block(self):
tempo = 20.0
scratch_block = ["changeTempoBy:", tempo]
[catr_brick] = self.block_converter._catrobat_bricks_from(scratch_block, DUMMY_CATR_SPRITE)
assert isinstance(catr_brick, catbricks.ChangeTempoByNBrick)

formula_tree_list_delete_item = catr_brick.getFormulaWithBrickField(catbasebrick.BrickField.TEMPO_CHANGE).formulaTree # @UndefinedVariable
assert formula_tree_list_delete_item.type == catformula.FormulaElement.ElementType.NUMBER
assert formula_tree_list_delete_item.value == str(tempo)

# deleteLine:ofList:
def test_can_convert_delete_line_from_list_by_index_block(self):
index = 2
Expand All @@ -1427,6 +1468,7 @@ def test_can_convert_delete_line_from_list_by_index_block(self):
assert formula_tree_list_delete_item.type == catformula.FormulaElement.ElementType.NUMBER
assert formula_tree_list_delete_item.value == str(index)


# deleteLine:ofList:
def test_can_convert_delete_last_line_from_list_block(self):
scratch_block = ["deleteLine:ofList:", "last", self._name_of_test_list]
Expand Down
11 changes: 10 additions & 1 deletion src/scratchtocatrobat/scratch/scratch3visitor/blockmapping.py
@@ -1,4 +1,6 @@
import looks, motion, event, sensing, sound, operator, control, data, pen
import looks, motion, event, sensing, sound, operator, control, data, pen, music
from scratchtocatrobat.scratch.scratch3visitor.scratch2_json_format import Scratch3_2Opcodes as opcodes

visitormap = {
### event blocks ####
"event_whenflagclicked" : event.visitWhenflagclicked, #tested
Expand Down Expand Up @@ -167,5 +169,12 @@
"pen_setPenShadeToNumber" : pen.visitSetPenShadeToNumber, #tested
"pen_changePenShadeBy" : pen.visitChangePenShadeByNumber, #tested
"pen_setPenHueToNumber" : pen.visitSetPenHueToNumber, #tested

opcodes.MUSIC_PLAY_DRUM_FOR_BEATS: music.visitPlayDrumForBeats,
opcodes.MUSIC_MENU_DRUM: music.visitDrumMenu,
opcodes.MUSIC_PLAY_NOTE_FOR_BEATS: music.visitPlayNoteForBeats,
opcodes.NOTE: music.visitNoteMenu,
opcodes.MUSIC_CHANGE_TEMPO: music.visitChangeTempoBy,

}

35 changes: 35 additions & 0 deletions src/scratchtocatrobat/scratch/scratch3visitor/music.py
@@ -0,0 +1,35 @@
from visitorUtil import visitGeneric
from scratchtocatrobat.tools import logger

log = logger.log

def visitPlayDrumForBeats(blockcontext):
drum = visitGeneric(blockcontext, 'DRUM')
beats = visitGeneric(blockcontext, "BEATS")
return ['drum:duration:elapsed:from:', drum, beats]

def visitDrumMenu(blockcontext):
block = blockcontext.block
return block.fields["DRUM"][0]

def visitPlayNoteForBeats(blockcontext):
note = visitGeneric(blockcontext, 'NOTE')
beats = visitGeneric(blockcontext, "BEATS")
return ['noteOn:duration:elapsed:from:', note, beats]

def visitNoteMenu(blockcontext):
block = blockcontext.block
return block.fields["NOTE"][0]

def visitChangeTempoBy(blockcontext):
tempo = visitGeneric(blockcontext, 'TEMPO')
return ['changeTempoBy:', tempo]









Expand Up @@ -169,6 +169,13 @@ class Scratch3_2Opcodes(object):
OPERATOR_OR = "operator_or"
OPERATOR_LENGTH = "operator_length"

# music #
MUSIC_PLAY_DRUM_FOR_BEATS = "music_playDrumForBeats"
MUSIC_MENU_DRUM = "music_menu_DRUM"
MUSIC_PLAY_NOTE_FOR_BEATS = "music_playNoteForBeats"
NOTE = "note"
MUSIC_CHANGE_TEMPO = "music_changeTempo"

# not supported block #
NOT_SUPPORTED = "not_supported_block"

Expand Down Expand Up @@ -324,6 +331,12 @@ class Scratch3_2Opcodes(object):
OPERATOR_OR: "|",
OPERATOR_LENGTH: "stringLength:",

# music #
MUSIC_PLAY_DRUM_FOR_BEATS: "drum:duration:elapsed:from:",
MUSIC_PLAY_NOTE_FOR_BEATS: "noteOn:duration:elapsed:from:",
MUSIC_CHANGE_TEMPO: "changeTempoBy:",


### not suported block ###
NOT_SUPPORTED: "note:",
}
Expand Down
2 changes: 0 additions & 2 deletions src/scratchtocatrobat/scratch/scratch3visitor/sound.py
Expand Up @@ -50,5 +50,3 @@ def visitSounds_menu(blockcontext):
block = blockcontext.block
return block.fields["SOUND_MENU"][0]


#TODO: replace music extension bricks with default ones?