diff options
author | Pootle daemon <pootle@pootle.sugarlabs.org> | 2013-10-31 04:30:47 (GMT) |
---|---|---|
committer | Pootle daemon <pootle@pootle.sugarlabs.org> | 2013-10-31 04:30:47 (GMT) |
commit | 4ed97f79ceb34d615fb9406ad4e724fe75b17f8f (patch) | |
tree | ceec46869eeb06cf0ddfec1d74cd188e9c783176 | |
parent | 72757585f57a2cca7a72bc195547e03f05eb43ab (diff) | |
parent | b48fb2038fd32a95e58b603a0edad402331bf150 (diff) |
Merge branch 'master' of git.sugarlabs.org:turtleart/mainline
-rw-r--r-- | TurtleArt/tabasics.py | 7 | ||||
-rw-r--r-- | TurtleArt/taconstants.py | 63 | ||||
-rw-r--r-- | TurtleArt/talogo.py | 66 | ||||
-rw-r--r-- | TurtleArt/taturtle.py | 13 | ||||
-rw-r--r-- | TurtleArt/tautils.py | 2 | ||||
-rw-r--r-- | TurtleArt/tawindow.py | 132 | ||||
-rw-r--r-- | TurtleArtActivity.py | 1 | ||||
-rw-r--r-- | plugins/turtle_blocks_extras/turtle_blocks_extras.py | 464 | ||||
-rw-r--r-- | pysamples/brain.py | 3 | ||||
-rw-r--r-- | pysamples/csound.py | 25 | ||||
-rw-r--r-- | pysamples/dotted_line.py | 4 | ||||
-rw-r--r-- | pysamples/forward_push.py | 4 | ||||
-rw-r--r-- | pysamples/grecord.py | 11 | ||||
-rw-r--r-- | pysamples/serial.py | 4 | ||||
-rw-r--r-- | pysamples/sinewave.py | 3 | ||||
-rw-r--r-- | pysamples/speak.py | 4 | ||||
-rw-r--r-- | pysamples/uturn.py | 2 | ||||
-rw-r--r-- | samples/basic-intro-1.ta | 239 | ||||
-rwxr-xr-x | turtleblocks.py | 3 |
19 files changed, 552 insertions, 498 deletions
diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py index a80b3ae..ce84a49 100644 --- a/TurtleArt/tabasics.py +++ b/TurtleArt/tabasics.py @@ -1039,11 +1039,11 @@ buttons')) self.tw.lc.def_prim( 'nop3', 1, Primitive(self.tw.lc.prim_define_stack, - arg_descs=[ArgSlot(TYPE_STRING)])) + arg_descs=[ArgSlot(TYPE_OBJECT)])) primitive_dictionary['stack'] = Primitive( self.tw.lc.prim_invoke_stack, - arg_descs=[ArgSlot(TYPE_STRING)]) + arg_descs=[ArgSlot(TYPE_OBJECT)]) palette.add_block('stack', style='basic-style-1arg', label=_('action'), @@ -1052,7 +1052,8 @@ buttons')) logo_command='action', default=_('action'), help_string=_('invokes named action stack')) - self.tw.lc.def_prim('stack', 1, primitive_dictionary['stack'], True) + self.tw.lc.def_prim('stack', 1, + primitive_dictionary['stack'], True) palette.add_block('storeinbox1', hidden=True, diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py index 9666573..43ae9bc 100644 --- a/TurtleArt/taconstants.py +++ b/TurtleArt/taconstants.py @@ -79,6 +79,69 @@ XO4 = 'xo4' UNKNOWN = 'unknown' TMP_SVG_PATH = '/tmp/turtle_output.svg' +KEY_DICT = { + 'Left': 1, + 'KP_Left': 1, + 'Up': 2, + 'KP_Up': 2, + 'Right': 3, + 'KP_Right': 3, + 'Down': 4, + 'KP_Down': 4, + 'BackSpace': 8, + 'Tab': 9, + 'Return': 13, + 'Escape': 27, + 'space': 32, + ' ': 32, + 'exclam': 33, + 'quotedbl': 34, + 'numbersign': 35, + 'dollar': 36, + 'percent': 37, + 'ampersand': 38, + 'apostrophe': 39, + 'parenleft': 40, + 'parenright': 41, + 'asterisk': 42, + 'plus': 43, + 'comma': 44, + 'minus': 45, + 'period': 46, + 'slash': 47, + 'colon': 58, + 'semicolon': 59, + 'less': 60, + 'equal': 61, + 'greater': 62, + 'question': 63, + 'at': 64, + 'underscore': 95, + 'bracketleft': 91, + 'backslash': 92, + 'bracketright': 93, + 'asciicircum': 94, + 'grave': 96, + 'braceleft': 123, + 'bar': 124, + 'braceright': 125, + 'asciitilde': 126, + 'Delete': 127, + } +REVERSE_KEY_DICT = { + 1: _('left'), + 2: _('up'), + 3: _('right'), + 4: _('down'), + 8: _('backspace'), + 9: _('tab'), + # TRANS: enter is the name of the enter (or return) key + 13: _('enter'), + 27: 'esc', + # TRANS: space is the name of the space key + 32: _('space'), + 127: _('delete') + } class Color(object): diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index b1db4ff..2b297ef 100644 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -39,12 +39,12 @@ import traceback from tablock import (Block, Media, media_blocks_dictionary) from taconstants import (TAB_LAYER, DEFAULT_SCALE, ICON_SIZE) -from tajail import myfunc +from tajail import (myfunc, myfunc_import) from tapalette import (block_names, value_blocks) from tatype import (TATypeError, TYPES_NUMERIC) from tautils import (get_pixbuf_from_journal, data_from_file, get_stack_name, text_media_type, round_int, debug_output, find_group, - get_path, image_to_base64, data_to_string) + get_path, image_to_base64, data_to_string, data_to_file) try: from util.RtfParser import RtfTextOnly @@ -164,7 +164,6 @@ class LogoCode: self.hidden_turtle = None - self.keyboard = 0 self.trace = 0 self.update_values = False self.gplay = None @@ -819,10 +818,57 @@ class LogoCode: return name else: # make sure '5' and '5.0' point to the same action stack - if isinstance(name, (int, long)): - name = float(name) + if isinstance(name, (int, long, float)): + if int(name) == name: + name = int(name) + else: + name = float(name) return 'stack3' + str(name) + def load_heap(self, path): + """ Load FILO from file """ + if self.tw.running_sugar: + # Choose a datastore object and push data to heap (Sugar only) + chooser_dialog(self.tw.parent, path, self.push_file_data_to_heap) + else: + if not os.path.exists(path): + path, tw.load_save_folder = get_load_name( + '.*', self.tw.load_save_folder) + if path is None: + return + + data = data_from_file(path) + if data is not None: + for val in data: + self.heap.append(val) + + def save_heap(self, path): + """ save FILO to file """ + if self.tw.running_sugar: + from sugar import profile + from sugar.datastore import datastore + from sugar.activity import activity + + # Save JSON-encoded heap to temporary file + heap_file = os.path.join(get_path(activity, 'instance'), + str(path) + '.txt') + data_to_file(self.heap, heap_file) + + # Create a datastore object + dsobject = datastore.create() + + # Write any metadata (specifically set the title of the file + # and specify that this is a plain text file). + dsobject.metadata['title'] = str(path) + dsobject.metadata['icon-color'] = profile.get_color().to_string() + dsobject.metadata['mime_type'] = 'text/plain' + dsobject.set_file_path(heap_file) + datastore.write(dsobject) + dsobject.destroy() + else: + heap_file = path + data_to_file(self.heap, heap_file) + def get_heap(self): return self.heap @@ -833,6 +879,16 @@ class LogoCode: while self.heap: self.heap.pop() + def prim_myblock(self, *args): + """ Run Python code imported from Journal """ + if self.bindex is not None and self.bindex in self.tw.myblock: + # try: + myfunc_import(self, self.tw.myblock[self.bindex], args) + ''' + except: + raise logoerror("#syntaxerror") + ''' + def prim_myfunction(self, f, *args): """ Programmable block (Call tajail.myfunc and convert any errors to logoerrors) """ diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py index abea538..88f4782 100644 --- a/TurtleArt/taturtle.py +++ b/TurtleArt/taturtle.py @@ -735,6 +735,19 @@ class Turtle: round_int(w)]])) self._turtles.turtle_window.send_event(event) + def read_pixel(self): + """ Read r, g, b, a from the canvas and push b, g, r to the stack """ + r, g, b, a = self.get_pixel() + self._turtles.turtle_window.lc.heap.append(b) + self._turtles.turtle_window.lc.heap.append(g) + self._turtles.turtle_window.lc.heap.append(r) + + def get_color_index(self): + r, g, b, a = self.get_pixel() + color_index = self._turtles.turtle_window.canvas.get_color_index( + r, g, b) + return color_index + def get_name(self): return self._name diff --git a/TurtleArt/tautils.py b/TurtleArt/tautils.py index 634ee01..ef80877 100644 --- a/TurtleArt/tautils.py +++ b/TurtleArt/tautils.py @@ -819,7 +819,7 @@ def get_stack_name(blk): return 'stack2' elif top_block.name == 'hat': try: - return top_block.connections[1].values[0] + return str(top_block.connections[1].values[0]) except (AttributeError, TypeError, IndexError): # AttributeError: t_b has no attribute 'connections' or t_b.c[1] # has no attribute 'value' diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py index 948f1f4..5d8f715 100644 --- a/TurtleArt/tawindow.py +++ b/TurtleArt/tawindow.py @@ -58,13 +58,14 @@ from taconstants import (HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, PYTHON_SKIN, PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, EXPANDABLE_ARGS, XO1, XO15, XO175, XO30, XO4, TITLEXY, CONTENT_ARGS, CONSTANTS, EXPAND_SKIN, PROTO_LAYER, - EXPANDABLE_FLOW, SUFFIX, TMP_SVG_PATH, Color) + EXPANDABLE_FLOW, SUFFIX, TMP_SVG_PATH, Color, + KEY_DICT) from tapalette import (palette_names, palette_blocks, expandable_blocks, block_names, content_blocks, default_values, special_names, block_styles, help_strings, hidden_proto_blocks, string_or_number_args, make_palette, palette_name_to_index, - palette_init_on_start) + palette_init_on_start, palette_i18n_names) from talogo import (LogoCode, primitive_dictionary, logoerror) from tacanvas import TurtleGraphics from tablock import (Blocks, Block, Media, media_blocks_dictionary) @@ -170,6 +171,7 @@ class TurtleArtWindow(): self._autohide_shape = True self.keypress = '' self.keyvalue = 0 + self.keyboard = 0 self._focus_out_id = None self._insert_text_id = None self._text_to_check = False @@ -420,7 +422,7 @@ class TurtleArtWindow(): # If setup fails, remove the plugin from the list self.turtleart_plugins.remove(plugin) - def _start_plugins(self): + def start_plugins(self): ''' Start is called everytime we execute blocks. ''' for plugin in self.turtleart_plugins: if hasattr(plugin, 'start'): @@ -1487,6 +1489,18 @@ class TurtleArtWindow(): self.button_press(event.get_state() & gtk.gdk.CONTROL_MASK, x, y) return True + def get_mouse_flag(self): + return self.mouse_flag + + def get_mouse_button(self): + return self.mouse_flag == 1 + + def get_mouse_x(self): + return int(self.mouse_x - (self.canvas.width / 2)) + + def get_mouse_y(self): + return int((self.canvas.height / 2) - self.mouse_y) + def button_press(self, mask, x, y): if self.running_sugar: self._show_unfullscreen_button() @@ -3176,7 +3190,7 @@ before making changes to your program')) if self.canvas.cr_svg is None: self.canvas.setup_svg_surface() self.running_blocks = True - self._start_plugins() # Let the plugins know we are running. + self.start_plugins() # Let the plugins know we are running. top = find_top_block(blk) code = self.lc.generate_code(top, self.just_blocks()) self.lc.run_blocks(code) @@ -3603,6 +3617,19 @@ before making changes to your program')) return True + def get_keyboard_input(self): + """ Query keyboard and update cached keyboard input """ + if len(self.keypress) == 1: + self.keyboard = ord(self.keypress[0]) + elif self.keypress in KEY_DICT: + self.keyboard = KEY_DICT[self.keypress] + else: + self.keyboard = 0 + + def get_keyboard(self): + """ Return cached keyboard input """ + return self.keyboard + def _process_keyboard_commands(self, keyname, block_flag=True): ''' Use the keyboard to move blocks and turtle ''' mov_dict = {'KP_Up': [0, 20], 'j': [0, 20], 'Up': [0, 20], @@ -4803,3 +4830,100 @@ variable')) (b1x, b1y) = block1.spr.get_xy() (b2x, b2y) = block2.spr.get_xy() return ((b1x + d1x) - (b2x + d2x), (b1y + d1y) - (b2y + d2y)) + + def prim_load_block(self, *args): + ''' Load a block on to the canvas ''' + # Place the block at the active turtle (x, y) and move the turtle + # into position to place the next block in the stack. + # TODO: Add expandable argument, media block arguments + name = args[0] + pos = self.turtles.get_active_turtle().get_xy() + values = [] + for i in range(len(args) - 1): + values.append(args[i + 1]) + if len(values) > 0: + dy = int(self._find_block(name, pos[0], pos[1], values)) + else: + if name == 'delete': + for blk in self.just_blocks(): + if blk.status == 'load block': + blk.type = 'trash' + blk.spr.hide() + dy = 0 + else: + dy = int(self._find_block(name, pos[0], pos[1])) + + # Reposition turtle to end of flow + pos = self.turtles.get_active_turtle().get_xy() + pos[1] -= dy + self.turtles.get_active_turtle().move_turtle(pos) + + def _make_block(self, name, x, y, defaults): + if defaults is None: + self._new_block(name, x, y, defaults) + else: + for i, v in enumerate(defaults): + if isinstance(v, float) and int(v) == v: + defaults[i] = int(v) + self._new_block(name, x, y, defaults) + + # Find the block we just created and attach it to a stack. + self.drag_group = None + spr = self.sprite_list.find_sprite((x, y)) + if spr is not None: + blk = self.block_list.spr_to_block(spr) + if blk is not None: + self.drag_group = find_group(blk) + for b in self.drag_group: + b.status = 'load block' + self._snap_to_dock() + + # Disassociate new block from mouse. + self.drag_group = None + return blk.docks[-1][3] + + def _find_block(self, blkname, x, y, defaults=None): + """ Create a new block. It is a bit more work than just calling + _new_block(). We need to: + (1) translate the label name into the internal block name; + (2) 'dock' the block onto a stack where appropriate; and + (3) disassociate the new block from the mouse. """ + x, y = self.turtles.turtle_to_screen_coordinates((x, y)) + for name in block_names: + # Translate label name into block/prim name. + if blkname in block_names[name]: # block label is an array + # print 'found a match', blkname, name, block_names[name] + if name in content_blocks or \ + (name in block_primitives and + block_primitives[name] == name): + # print '_make_block', blkname, name + return self._make_block(name, x, y, defaults) + elif blkname in block_names: + # print '_make_block', blkname + return self._make_block(blkname, x, y, defaults) + for name in special_names: + # Translate label name into block/prim name. + if blkname in special_names[name]: + return self._make_block(name, x, y, defaults) + # Check for a macro + if blkname in MACROS: + self.new_macro(blkname, x, y) + return 0 # Fix me: calculate flow position + # Block not found + raise logoerror("#syntaxerror") + return -1 + + def prim_load_palette(self, arg): + ''' Select a palette ''' + if type(arg) in [int, float]: + if int(arg) < 0 or int(arg) > len(palette_names): + raise logoerror("#syntaxerror") + else: + self.show_toolbar_palette(int(arg)) + else: + if type(arg) == unicode: + arg = arg.encode('utf-8') + if arg in palette_names or arg in palette_i18n_names: + self.show_toolbar_palette(palette_name_to_index(arg)) + else: + raise logoerror("#syntaxerror") diff --git a/TurtleArtActivity.py b/TurtleArtActivity.py index c2980bb..c413358 100644 --- a/TurtleArtActivity.py +++ b/TurtleArtActivity.py @@ -227,6 +227,7 @@ class TurtleArtActivity(activity.Activity): if pyee.block is not None: pyee.block.highlight() self.tw.showlabel('status', str(pyee)) + _logger.debug(pyee) return if not pythoncode: return diff --git a/plugins/turtle_blocks_extras/turtle_blocks_extras.py b/plugins/turtle_blocks_extras/turtle_blocks_extras.py index c5357c4..9136a83 100644 --- a/plugins/turtle_blocks_extras/turtle_blocks_extras.py +++ b/plugins/turtle_blocks_extras/turtle_blocks_extras.py @@ -27,17 +27,16 @@ from plugins.plugin import Plugin from TurtleArt.tapalette import (make_palette, define_logo_function, block_names, block_primitives, special_names, content_blocks, palette_name_to_index, - palette_names, palette_i18n_names) + palette_names) from TurtleArt.talogo import (primitive_dictionary, logoerror, media_blocks_dictionary) from TurtleArt.taconstants import (DEFAULT_SCALE, CONSTANTS, MEDIA_SHAPES, SKIN_PATHS, BLOCKS_WITH_SKIN, PYTHON_SKIN, MEDIA_BLOCK2TYPE, VOICES, - MACROS, Color) + MACROS, Color, KEY_DICT, REVERSE_KEY_DICT) from TurtleArt.tautils import (round_int, debug_output, get_path, data_to_string, find_group, image_to_base64, hat_on_top, listify, data_from_file) -from TurtleArt.tajail import myfunc_import from TurtleArt.taprimitive import (ArgSlot, ConstantArg, Primitive) from TurtleArt.tatype import (TYPE_BOOL, TYPE_BOX, TYPE_CHAR, TYPE_INT, TYPE_FLOAT, TYPE_OBJECT, TYPE_STRING, @@ -45,22 +44,6 @@ from TurtleArt.tatype import (TYPE_BOOL, TYPE_BOX, TYPE_CHAR, TYPE_INT, from TurtleArt.taturtle import Turtle -def _num_type(x): - """ Is x a number type? """ - if type(x) == int: - return True - if type(x) == float: - return True - if type(x) == ord: - return True - return False - - -def _millisecond(): - """ Current time in milliseconds """ - return time() * 1000 - - class Turtle_blocks_extras(Plugin): """ a class for defining the extra palettes that distinguish Turtle Blocks from Turtle Art """ @@ -72,7 +55,6 @@ class Turtle_blocks_extras(Plugin): SKIN_PATHS.append('plugins/turtle_blocks_extras/images') self.heap = self.tw.lc.heap - self.keyboard = self.tw.lc.keyboard self.title_height = int((self.tw.canvas.height / 20) * self.tw.scale) # set up Turtle Block palettes @@ -251,7 +233,8 @@ Journal')) self.tw.lc.def_prim('setscale', 1, Primitive(self.tw.lc.set_scale, arg_descs=[ArgSlot(TYPE_NUMBER)], - call_afterwards=self.after_set_scale)) + call_afterwards=lambda value: self.after_set( + 'scale', value))) primitive_dictionary['savepix'] = self._prim_save_picture palette.add_block('savepix', @@ -347,7 +330,6 @@ amplitude, and duration (in seconds)')) help_string=_('Palette of sensor blocks'), position=6) - primitive_dictionary['mousebutton'] = self._prim_mouse_button palette.add_block('mousebutton', hidden=True, style='box-style', @@ -357,9 +339,9 @@ amplitude, and duration (in seconds)')) help_string=_('returns 1 if mouse button is \ pressed')) self.tw.lc.def_prim('mousebutton', 0, - lambda self: primitive_dictionary['mousebutton']()) + Primitive(self.tw.get_mouse_flag, + return_type=TYPE_NUMBER)) - primitive_dictionary['mousebutton2'] = self._prim_mouse_button_bool palette.add_block('mousebutton2', style='boolean-block-style', label=_('button down'), @@ -368,10 +350,9 @@ pressed')) help_string=_('returns True if mouse button is \ pressed')) self.tw.lc.def_prim('mousebutton2', 0, - lambda self: - primitive_dictionary['mousebutton2']()) + Primitive(self.tw.get_mouse_button, + return_type=TYPE_BOOL)) - primitive_dictionary['mousex'] = self._prim_mouse_x palette.add_block('mousex', style='box-style', label=_('mouse x'), @@ -379,10 +360,10 @@ pressed')) value_block=True, help_string=_('returns mouse x coordinate')) self.tw.lc.def_prim('mousex', 0, - lambda self: - primitive_dictionary['mousex']()) + Primitive(self.tw.get_mouse_x, + return_type=TYPE_NUMBER, + call_afterwards=self.after_mouse_x)) - primitive_dictionary['mousey'] = self._prim_mouse_y palette.add_block('mousey', style='box-style', label=_('mouse y'), @@ -390,10 +371,10 @@ pressed')) value_block=True, help_string=_('returns mouse y coordinate')) self.tw.lc.def_prim('mousey', 0, - lambda self: - primitive_dictionary['mousey']()) + Primitive(self.tw.get_mouse_y, + return_type=TYPE_NUMBER, + call_afterwards=self.after_mouse_y)) - primitive_dictionary['kbinput'] = self._prim_kbinput palette.add_block('kbinput', style='basic-style-extended-vertical', label=_('query keyboard'), @@ -401,9 +382,9 @@ pressed')) help_string=_('query for keyboard input (results \ stored in keyboard block)')) self.tw.lc.def_prim('kbinput', 0, - lambda self: primitive_dictionary['kbinput']()) + Primitive(self.tw.get_keyboard_input, + call_afterwards=self.after_keypress)) - primitive_dictionary['keyboard'] = self._prim_keyboard palette.add_block('keyboard', style='box-style', label=_('keyboard'), @@ -413,9 +394,9 @@ stored in keyboard block)')) help_string=_('holds results of query-keyboard \ block as ASCII')) self.tw.lc.def_prim('keyboard', 0, - lambda self: primitive_dictionary['keyboard']()) + Primitive(self.tw.get_keyboard, + return_type=TYPE_NUMBER)) - primitive_dictionary['readpixel'] = self._prim_readpixel palette.add_block('readpixel', style='basic-style-extended-vertical', label=_('read pixel'), @@ -424,9 +405,8 @@ block as ASCII')) help_string=_('RGB color under the turtle is pushed \ to the stack')) self.tw.lc.def_prim('readpixel', 0, - lambda self: primitive_dictionary['readpixel']()) + Primitive(Turtle.read_pixel)) - primitive_dictionary['see'] = self._prim_see palette.add_block('see', style='box-style', label=_('turtle sees'), @@ -435,7 +415,9 @@ to the stack')) help_string=_('returns the color that the turtle \ "sees"')) self.tw.lc.def_prim('see', 0, - lambda self: primitive_dictionary['see']()) + Primitive(Turtle.get_color_index, + return_type=TYPE_NUMBER, + call_afterwards=self.after_see)) palette.add_block('time', style='box-style', @@ -543,7 +525,6 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n') Primitive(self.tw.lc.get_heap, return_type=TYPE_BOOL))]))])) - primitive_dictionary['saveheap'] = self._prim_save_heap palette.add_block('saveheap', style='basic-style-1arg', label=_('save heap to file'), @@ -552,9 +533,9 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n') help_string=_('saves FILO (first-in \ last-out heap) to a file')) self.tw.lc.def_prim('saveheap', 1, - lambda self, x: primitive_dictionary['saveheap'](x)) + Primitive(self.tw.lc.save_heap, + arg_descs=[ArgSlot(TYPE_STRING)])) - primitive_dictionary['loadheap'] = self._prim_load_heap palette.add_block('loadheap', style='basic-style-1arg', label=_('load heap from file'), @@ -563,7 +544,10 @@ last-out heap) to a file')) help_string=_('loads FILO (first-in \ last-out heap) from a file')) self.tw.lc.def_prim('loadheap', 1, - lambda self, x: primitive_dictionary['loadheap'](x)) + Primitive(self.tw.lc.load_heap, + arg_descs=[ArgSlot(TYPE_STRING)], + return_type=TYPE_STRING, + call_afterwards=self.after_push)) palette.add_block('isheapempty2', style='boolean-block-style', @@ -687,7 +671,6 @@ advanced multi-variable math equations, e.g., sin(x+y+z)')) self.tw.lc.def_prim('cartesian', 0, lambda self: self.tw.set_cartesian(True)) - primitive_dictionary['userdefined'] = self._prim_myblock palette.add_block('userdefined', style='basic-style-var-arg', label=' ', @@ -698,8 +681,8 @@ advanced multi-variable math equations, e.g., sin(x+y+z)')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined', 1, - lambda self, x: - primitive_dictionary['userdefined']([x])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined') PYTHON_SKIN.append('userdefined') @@ -715,8 +698,9 @@ module found in the Journal')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined2', 2, - lambda self, x, y: - primitive_dictionary['userdefined']([x, y])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined2args') PYTHON_SKIN.append('userdefined2args') @@ -732,15 +716,16 @@ module found in the Journal')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined3', 3, - lambda self, x, y, z: - primitive_dictionary['userdefined']([x, y, z])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined3args') PYTHON_SKIN.append('userdefined3args') MEDIA_SHAPES.append('pythonsmall') MEDIA_SHAPES.append('pythonoff') MEDIA_SHAPES.append('pythonon') - primitive_dictionary['loadblock'] = self._prim_load_block palette.add_block('loadblock', style='basic-style-var-arg', label=_('load'), @@ -748,8 +733,8 @@ module found in the Journal')) default=_('forward'), help_string=_('loads a block')) self.tw.lc.def_prim('loadblock', 1, - lambda self, x: - primitive_dictionary['loadblock'](x)) + Primitive(self.tw.prim_load_block, + arg_descs=[ArgSlot(TYPE_STRING)])) palette.add_block('loadblock2arg', style='basic-style-var-arg', @@ -760,8 +745,9 @@ module found in the Journal')) default=[_('forward'), 100], help_string=_('loads a block')) self.tw.lc.def_prim('loadblock2', 2, - lambda self, x, y: - primitive_dictionary['loadblock']([x, y])) + Primitive(self.tw.prim_load_block, + arg_descs=[ArgSlot(TYPE_STRING), + ArgSlot(TYPE_OBJECT)])) palette.add_block('loadblock3arg', style='basic-style-var-arg', @@ -772,10 +758,11 @@ module found in the Journal')) default=[_('setxy'), 0, 0], help_string=_('loads a block')) self.tw.lc.def_prim('loadblock3', 3, - lambda self, x, y, z: - primitive_dictionary['loadblock']([x, y, z])) + Primitive(self.tw.prim_load_block, + arg_descs=[ArgSlot(TYPE_STRING), + ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) - primitive_dictionary['loadpalette'] = self._prim_load_palette palette.add_block('loadpalette', style='basic-style-1arg', string_or_number=True, @@ -784,8 +771,8 @@ module found in the Journal')) default=_('turtle'), help_string=_('selects a palette')) self.tw.lc.def_prim('loadpalette', 1, - lambda self, x: - primitive_dictionary['loadpalette'](x)) + Primitive(self.tw.prim_load_palette, + arg_descs=[ArgSlot(TYPE_STRING)])) palette.add_block('addturtle', style='basic-style-1arg', @@ -1126,93 +1113,19 @@ Journal objects')) # Block primitives - def _prim_keyboard(self): - """ Return last character typed """ - return self.tw.lc.keyboard - - def _prim_kbinput(self): - """ Query keyboard """ - DICT = { - 'Left': 1, - 'KP_Left': 1, - 'Up': 2, - 'KP_Up': 2, - 'Right': 3, - 'KP_Right': 3, - 'Down': 4, - 'KP_Down': 4, - 'BackSpace': 8, - 'Tab': 9, - 'Return': 13, - 'Escape': 27, - 'space': 32, - ' ': 32, - 'exclam': 33, - 'quotedbl': 34, - 'numbersign': 35, - 'dollar': 36, - 'percent': 37, - 'ampersand': 38, - 'apostrophe': 39, - 'parenleft': 40, - 'parenright': 41, - 'asterisk': 42, - 'plus': 43, - 'comma': 44, - 'minus': 45, - 'period': 46, - 'slash': 47, - 'colon': 58, - 'semicolon': 59, - 'less': 60, - 'equal': 61, - 'greater': 62, - 'question': 63, - 'at': 64, - 'underscore': 95, - 'bracketleft': 91, - 'backslash': 92, - 'bracketright': 93, - 'asciicircum': 94, - 'grave': 96, - 'braceleft': 123, - 'bar': 124, - 'braceright': 125, - 'asciitilde': 126, - 'Delete': 127, - } - REVERSE_DICT = { - 1: _('left'), - 2: _('up'), - 3: _('right'), - 4: _('down'), - 8: _('backspace'), - 9: _('tab'), - # TRANS: enter is the name of the enter (or return) key - 13: _('enter'), - 27: 'esc', - # TRANS: space is the name of the space key - 32: _('space'), - 127: _('delete') - } - - if len(self.tw.keypress) == 1: - self.tw.lc.keyboard = ord(self.tw.keypress[0]) - elif self.tw.keypress in DICT: - self.tw.lc.keyboard = DICT[self.tw.keypress] - else: - self.tw.lc.keyboard = 0 + def after_keypress(self): if self.tw.lc.update_values: - if self.tw.keypress in DICT: - if DICT[self.tw.keypress] in REVERSE_DICT: + if self.tw.keypress in KEY_DICT: + if KEY_DICT[self.tw.keypress] in REVERSE_KEY_DICT: self.tw.lc.update_label_value( - 'keyboard', REVERSE_DICT[DICT[self.tw.keypress]]) + 'keyboard', REVERSE_KEY_DICT[ + KEY_DICT[self.tw.keypress]]) else: - self.tw.lc.update_label_value('keyboard', - chr(DICT[self.tw.keypress])) - elif self.tw.lc.keyboard > 0: + self.tw.lc.update_label_value( + 'keyboard', chr(KEY_DICT[self.tw.keypress])) + elif self.tw.keyboard > 0: self.tw.lc.update_label_value('keyboard', - chr(self.tw.lc.keyboard)) + chr(self.tw.keyboard)) self.tw.keypress = '' def _prim_list(self, blklist): @@ -1221,121 +1134,19 @@ Journal objects')) self.tw.lc.ireturn() yield True - def _prim_myblock(self, x): - """ Run Python code imported from Journal """ - if self.tw.lc.bindex is not None and \ - self.tw.lc.bindex in self.tw.myblock: - try: - if len(x) == 1: - myfunc_import(self, self.tw.myblock[self.tw.lc.bindex], - x[0]) - else: - myfunc_import(self, self.tw.myblock[self.tw.lc.bindex], x) - except: - raise logoerror("#syntaxerror") - - def _prim_myfunction(self, f, x): - """ Programmable block """ - for i, v in enumerate(x): - if isinstance(v, int): # Pass float values to Python block - x[i] = float(v) - try: - y = myfunc(f, x) - if str(y) == 'nan': - debug_output('Python function returned NAN', - self.tw.running_sugar) - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - else: - return y - except ZeroDivisionError: - self.tw.lc.stop_logo() - raise logoerror("#zerodivide") - except ValueError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except SyntaxError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except NameError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except OverflowError: - self.tw.lc.stop_logo() - raise logoerror("#overflowerror") - except TypeError: - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - - def after_pop(self): + def after_pop(self, *ignored_args): if self.tw.lc.update_values: if not self.tw.lc.heap: self.tw.lc.update_label_value('pop') else: self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) - def after_push(self, val): + def after_push(self, *ignored_args): if self.tw.lc.update_values: - self.tw.lc.update_label_value('pop', val) - - def _prim_load_heap(self, path): - """ Load FILO from file """ - if type(path) == float: - path = '' - if self.tw.running_sugar: - # Choose a datastore object and push data to heap (Sugar only) - chooser_dialog(self.tw.parent, path, - self.tw.lc.push_file_data_to_heap) - else: - if not os.path.exists(path): - path, tw.load_save_folder = get_load_name( - '.*', self.tw.load_save_folder) - if path is None: - return - - data = data_from_file(path) - if data is not None: - for val in data: - self.tw.lc.heap.append(val) - - if len(self.tw.lc.heap) > 0: - self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) - - def _prim_save_heap(self, path): - """ save FILO to file """ - # TODO: add GNOME save - - if self.tw.running_sugar: - from sugar import profile - from sugar.datastore import datastore - from sugar.activity import activity - - # Save JSON-encoded heap to temporary file - heap_file = os.path.join(get_path(activity, 'instance'), - str(path) + '.txt') - data_to_file(self.tw.lc.heap, heap_file) - - # Create a datastore object - dsobject = datastore.create() - - # Write any metadata (specifically set the title of the file - # and specify that this is a plain text file). - dsobject.metadata['title'] = str(path) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'text/plain' - dsobject.set_file_path(heap_file) - datastore.write(dsobject) - dsobject.destroy() - else: - heap_file = path - data_to_file(self.tw.lc.heap, heap_file) - - def _prim_readpixel(self): - """ Read r, g, b, a from the canvas and push b, g, r to the stack """ - r, g, b, a = self.tw.turtles.get_active_turtle().get_pixel() - self.tw.lc.heap.append(b) - self.tw.lc.heap.append(g) - self.tw.lc.heap.append(r) + if not self.tw.lc.heap: + self.tw.lc.update_label_value('pop') + else: + self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) def _prim_save_picture(self, name): """ Save canvas to file as PNG """ @@ -1439,46 +1250,22 @@ Journal objects')) csd.write("\n</CsoundSynthesizer>") csd.close() - def _prim_mouse_x(self): - """ Return mouse x coordinate """ - mousex = int(self.tw.mouse_x - (self.tw.canvas.width / 2)) - if self.tw.lc.update_values: - self.tw.lc.update_label_value('mousex', mousex) - return mousex - - def _prim_mouse_y(self): - """ Return mouse y coordinate """ - mousey = int((self.tw.canvas.height / 2) - self.tw.mouse_y) + def after_mouse_x(self): + """ Show mouse x coordinate """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('mousey', mousey) - return mousey - - def _prim_mouse_button(self): - """ Return 1 if mouse button is pressed """ - if self.tw.mouse_flag == 1: - return 1 - else: - return 0 + self.tw.lc.update_label_value('mousex', self.tw.get_mouse_x()) - def _prim_mouse_button_bool(self): - """ Return True if mouse button is pressed """ - if self.tw.mouse_flag == 1: - return True - else: - return False - - def _prim_see(self): - """ Read r, g, b from the canvas and return a corresponding palette - color """ - r, g, b, a = self.tw.turtles.get_active_turtle().get_pixel() - color_index = self.tw.canvas.get_color_index(r, g, b) + def after_mouse_y(self): + """ Show mouse y coordinate """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('see', color_index) - return color_index + self.tw.lc.update_label_value('mousey', self.tw.get_mouse_y()) - def after_set_scale(self, val): + def after_see(self): + """ Show color under turtle """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('scale', scale) + self.tw.lc.update_label_value( + 'see', + self.tw.turtles.get_active_turtle().get_color_index()) def _prim_show(self, string, center=False): """ Show is the general-purpose media-rendering block. """ @@ -1587,101 +1374,8 @@ Journal objects')) self.tw.activity.stop_turtle_button.set_icon("stopiton") self.tw.activity.stop_turtle_button.set_tooltip(_('Stop turtle')) - def _prim_load_block(self, blkname): - ''' Load a block on to the canvas ''' - # Place the block at the active turtle (x, y) and move the turtle - # into position to place the next block in the stack. - # TODO: Add expandable argument - pos = self.tw.turtles.get_active_turtle().get_xy() - if isinstance(blkname, list): - name = blkname[0] - if len(blkname) > 1: - value = blkname[1:] - dy = int(self._find_block(name, pos[0], pos[1], value)) - else: - dy = int(self._find_block(name, pos[0], pos[1])) - else: - name = blkname - if name == 'delete': - for blk in self.tw.just_blocks(): - if blk.status == 'load block': - blk.type = 'trash' - blk.spr.hide() - dy = 0 - else: - dy = int(self._find_block(name, pos[0], pos[1])) - - # Reposition turtle to end of flow - pos = self.tw.turtles.get_active_turtle().get_xy() - pos[1] -= dy - self.tw.turtles.get_active_turtle().move_turtle(pos) - - def _make_block(self, name, x, y, defaults): - if defaults is None: - self.tw._new_block(name, x, y, defaults) - else: - for i, v in enumerate(defaults): - if type(v) == float and int(v) == v: - defaults[i] = int(v) - self.tw._new_block(name, x, y, defaults) - - # Find the block we just created and attach it to a stack. - self.tw.drag_group = None - spr = self.tw.sprite_list.find_sprite((x, y)) - if spr is not None: - blk = self.tw.block_list.spr_to_block(spr) - if blk is not None: - self.tw.drag_group = find_group(blk) - for b in self.tw.drag_group: - b.status = 'load block' - self.tw._snap_to_dock() - - # Disassociate new block from mouse. - self.tw.drag_group = None - return blk.docks[-1][3] - - def _find_block(self, blkname, x, y, defaults=None): - """ Create a new block. It is a bit more work than just calling - _new_block(). We need to: - (1) translate the label name into the internal block name; - (2) 'dock' the block onto a stack where appropriate; and - (3) disassociate the new block from the mouse. """ - x, y = self.tw.turtles.turtle_to_screen_coordinates((x, y)) - for name in block_names: - # Translate label name into block/prim name. - if blkname in block_names[name]: # block label is an array - # print 'found a match', blkname, name, block_names[name] - if name in content_blocks or \ - (name in block_primitives and - block_primitives[name] == name): - # print '_make_block', blkname, name - return self._make_block(name, x, y, defaults) - elif blkname in block_names: - # print '_make_block', blkname - return self._make_block(blkname, x, y, defaults) - for name in special_names: - # Translate label name into block/prim name. - if blkname in special_names[name]: - return self._make_block(name, x, y, defaults) - # Check for a macro - if blkname in MACROS: - self.tw.new_macro(blkname, x, y) - return 0 # Fix me: calculate flow position - # Block not found - raise logoerror("#syntaxerror") - return -1 - - def _prim_load_palette(self, arg): - ''' Select a palette ''' - if type(arg) in [int, float]: - if int(arg) < 0 or int(arg) > len(palette_names): - raise logoerror("#syntaxerror") - else: - self.tw.show_toolbar_palette(int(arg)) - else: - if type(arg) == unicode: - arg = arg.encode('utf-8') - if arg in palette_names or arg in palette_i18n_names: - self.tw.show_toolbar_palette(palette_name_to_index(arg)) - else: - raise logoerror("#syntaxerror") + def after_set(self, name, value=None): + ''' Update the associated value blocks ''' + if value is not None: + if self.tw.lc.update_values: + self.tw.lc.update_label_value(name, value) diff --git a/pysamples/brain.py b/pysamples/brain.py index 33ee320..3510e03 100644 --- a/pysamples/brain.py +++ b/pysamples/brain.py @@ -21,7 +21,7 @@ # <http://www.gnu.org/licenses/>. -def myblock(tw, text): +def myblock(tw, args): ''' Dialog with AIML library: Usage: Load this code into a Python Block. Pass text as an argument and the robot's response will be pushed to the stack. Use a Pop Block to pop the response @@ -104,6 +104,7 @@ Close other activities and try once more.')) return kernel + text = args[0] if not hasattr(tw, 'aiml_kernel'): tw.aiml_kernel = brain_load(tw, get_default_voice()) response_text = brain_respond(tw.aiml_kernel, text) diff --git a/pysamples/csound.py b/pysamples/csound.py index a935674..ec1b014 100644 --- a/pysamples/csound.py +++ b/pysamples/csound.py @@ -17,16 +17,24 @@ def myblock(tw, sound): import os dirs = [os.path.join( - os.environ['HOME'], - 'Activities/TamTamMini.activity/common/Resources/Sounds/')] + os.environ['HOME'], + 'Activities/TamTamMini.activity/common/Resources/Sounds/'), + os.path.join( + os.environ['HOME'], + 'Activities/TamTamJam.activity/common/Resources/Sounds/'), + os.path.join( + os.environ['HOME'], + 'Activities/TamTamEdit.activity/common/Resources/Sounds/')] orchlines = [] scorelines = [] instrlist = [] def finddir(): + print dirs for d in dirs: if os.path.isdir(d): return d + return '.' def playSine(pitch=1000, amplitude=5000, duration=1, starttime=0, pitch_envelope='default', amplitude_envelope='default'): @@ -128,18 +136,17 @@ def myblock(tw, sound): csd.write("\n</CsoundSynthesizer>") csd.close() - if type(sound) == float: - playSine(pitch=float(sound)) - elif type(sound) == list: # Create a score by computing a sinewave. - if len(sound) == 1: + if len(sound) == 1: + if isinstance(sound[0], float) or isinstance(sound[0], int): playSine(pitch=float(sound[0])) - elif len(sound) == 2: + else: # Create a score from a prerecorded Wave file. + playWave(sound[0]) + else: + if len(sound) == 2: playSine(pitch=float(sound[0]), amplitude=float(sound[1])) else: playSine(pitch=float(sound[0]), amplitude=float(sound[1]), duration=float(sound[2])) - else: # Create a score from a prerecorded Wave file. - playWave(sound) if tw.running_sugar: path = os.path.join(get_path(tw.activity, 'instance'), 'tmp.csd') else: diff --git a/pysamples/dotted_line.py b/pysamples/dotted_line.py index c0d3008..098e0a4 100644 --- a/pysamples/dotted_line.py +++ b/pysamples/dotted_line.py @@ -124,11 +124,11 @@ # of the numeric argument block docked to the Python block. -def myblock(tw, line_length): +def myblock(tw, args): ''' Draw a dotted line of length line_length. ''' try: # make sure line_length is a number - line_length = float(line_length) + line_length = float(args[0]) except ValueError: return if tw.turtles.get_active_turtle().get_pen_state(): diff --git a/pysamples/forward_push.py b/pysamples/forward_push.py index ca527db..80fe818 100644 --- a/pysamples/forward_push.py +++ b/pysamples/forward_push.py @@ -10,7 +10,7 @@ # destination to the FILO. -def myblock(tw, name): +def myblock(tw, args): ''' ''' def _prim_forward_push(tw, line_length): @@ -42,7 +42,7 @@ def myblock(tw, name): # Create a new block prototype. palette.add_block('forwardpush', style='basic-style-1arg', - label=name, + label=args[0], default=100, prim_name='forwardpush', help_string=_('push destination rgb value to heap')) diff --git a/pysamples/grecord.py b/pysamples/grecord.py index a28b82c..486fdb7 100644 --- a/pysamples/grecord.py +++ b/pysamples/grecord.py @@ -10,7 +10,7 @@ # Sugar Journal. -def myblock(tw, arg): +def myblock(tw, args): ''' Record and playback a sound (Sugar only) ''' import os import gst @@ -204,12 +204,9 @@ def myblock(tw, arg): # Sometime we need to parse multiple arguments, e.g., save, savename save_name = '%s_%s' % (tw.activity.name, _('sound')) - if isinstance(arg, list): - cmd = arg[0].lower() - if len(arg) > 1: - save_name = str(arg[1]) - else: - cmd = arg.lower() + cmd = args[0].lower() + if len(args) > 1: + save_name = str(arg[1]) if cmd == 'start' or cmd == _('start').lower(): tw.grecord.start_recording_audio() diff --git a/pysamples/serial.py b/pysamples/serial.py index 84772ab..d15011c 100644 --- a/pysamples/serial.py +++ b/pysamples/serial.py @@ -9,13 +9,13 @@ # (3) use a Pop Block to retrieve any strings input from serial device. -def myblock(tw, x): # x is the string to transmit +def myblock(tw, args): # x is the string to transmit import serial # you may need to install this library # serial device on USB, 9600 baud ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=1) - ser.write(str(x)) # send string x + ser.write(str(args[0])) # send string x st = ser.read(1000) # read up to 1000 bytes tw.lc.heap.append(st) # append to heap ser.close() diff --git a/pysamples/sinewave.py b/pysamples/sinewave.py index 4f14c4c..a060f34 100644 --- a/pysamples/sinewave.py +++ b/pysamples/sinewave.py @@ -8,8 +8,9 @@ # the speaker at the specified frequency. -def myblock(tw, frequency): +def myblock(tw, args): ''' Plays a sound at frequency frequency ''' import os + frequency = args[0] os.system('speaker-test -t sine -l 1 -f %d' % (int(frequency))) diff --git a/pysamples/speak.py b/pysamples/speak.py index 30762a9..13215e8 100644 --- a/pysamples/speak.py +++ b/pysamples/speak.py @@ -28,7 +28,7 @@ def myblock(tw, arg): import os pitch = None - if type(arg) == type([]): + if len(arg) > 1: text = arg[0] if len(arg) > 1: pitch = int(arg[1]) @@ -37,7 +37,7 @@ def myblock(tw, arg): elif pitch < 0: pitch = 0 else: - text = arg + text = arg[0] # Turtle Art numbers are passed as float, # but they may be integer values. diff --git a/pysamples/uturn.py b/pysamples/uturn.py index edd2bcd..f6ff2e0 100644 --- a/pysamples/uturn.py +++ b/pysamples/uturn.py @@ -8,7 +8,7 @@ # can use the u-turn block as you would any other block. -def myblock(tw, arg): +def myblock(tw, args): ''' Add a uturn block to the 'turtle' palette ''' # def_prim takes 3 arguments: the primitive name, the number of diff --git a/samples/basic-intro-1.ta b/samples/basic-intro-1.ta index 17cff6a..c6d34c8 100644 --- a/samples/basic-intro-1.ta +++ b/samples/basic-intro-1.ta @@ -1,72 +1,167 @@ -[[0, ["start", 2.0], 788, 178, [null, 67]], -[1, "forward", 437, 523, [6, 2, 3]], -[2, ["number", 100], 508, 523, [1, null]], -[3, "right", 437, 565, [1, 5, null]], -[4, ["number", 360], 565, 565, [5, null]], -[5, ["division2", 0], 495, 565, [3, 4, 58]], -[6, ["repeat", 21], 419, 481, [26, 56, 1, null]], -[7, ["repeat", 168], 29, 324, [39, 8, 16, null]], -[8, ["number", 10], 88, 324, [7, null]], -[9, "startfill", 47, 450, [11, 28]], -[10, "stopfill", 47, 534, [28, 17]], -[11, "setgray", 47, 408, [16, 13, 9]], -[12, ["number", 300], 190, 408, [13, null]], -[13, ["division2", 0], 120, 408, [11, 12, 48]], -[14, ["number", 1], 212, 744, [15, null]], -[15, ["minus2", 0], 115, 702, [46, 50, 14]], -[16, "setcolor", 47, 366, [7, 66, 11]], -[17, "setcolor", 47, 576, [10, 71, 30]], -[18, ["repeat", 21], 418, 240, [24, 52, 19, null]], -[19, "forward", 436, 282, [18, 20, 23]], -[20, ["number", 100], 507, 282, [19, null]], -[21, ["division2", 0], 494, 324, [23, 22, 54]], -[22, ["number", 360], 564, 324, [21, null]], -[23, "left", 436, 324, [19, 21, null]], -[24, "hat", 418, 186, [null, 25, 18]], -[25, ["number", 2], 476, 198, [24, null]], -[26, "hat", 419, 427, [null, 27, 6]], -[27, ["number", 1], 477, 439, [26, null]], -[28, "stack", 47, 492, [9, 60, 10]], -[29, ["number", 1], 856, 392, [42, null]], -[30, "stack", 47, 618, [17, 64, 46]], -[31, ["repeat", 42], 788, 434, [42, 32, 37, null]], -[32, ["number", 2], 847, 434, [31, null]], -[33, ["number", 1], 928, 602, [34, null]], -[34, ["plus2", 0], 874, 560, [44, 62, 33]], -[35, "hat", 29, 186, [null, 36, 39]], -[36, ["string", "action"], 87, 198, [35, null]], -[37, "stack", 806, 476, [31, 38, 44]], -[38, ["string", "action"], 864, 476, [37, null]], -[39, ["storein", 0], 29, 240, [35, 40, 41, 7]], -[40, ["string", "box 1"], 97, 240, [39, null]], -[41, ["number", 12], 97, 282, [39, null]], -[42, ["storein", 0], 788, 350, [67, 43, 29, 31]], -[43, ["string", "box 2"], 856, 350, [42, null]], -[44, ["storein", 0], 806, 518, [37, 45, 34, null]], -[45, ["string", "box 2"], 874, 518, [44, null]], -[46, ["storein", 0], 47, 660, [30, 47, 15, null]], -[47, ["string", "box 1"], 115, 660, [46, null]], -[48, "box", 214, 450, [13, 49, null]], -[49, ["string", "box 1"], 269, 450, [48, null]], -[50, "box", 188, 702, [15, 51, null]], -[51, ["string", "box 1"], 243, 702, [50, null]], -[52, "box", 477, 240, [18, 53, null]], -[53, ["string", "box 1"], 532, 240, [52, null]], -[54, "box", 588, 366, [21, 55, null]], -[55, ["string", "box 1"], 643, 366, [54, null]], -[56, "box", 478, 481, [6, 57, null]], -[57, ["string", "box 1"], 533, 481, [56, null]], -[58, "box", 589, 607, [5, 59, null]], -[59, ["string", "box 1"], 644, 607, [58, null]], -[60, "box", 105, 492, [28, 61, null]], -[61, ["string", "box 2"], 160, 492, [60, null]], -[62, "box", 928, 560, [34, 63, null]], -[63, ["string", "box 2"], 983, 560, [62, null]], -[64, "box", 105, 618, [30, 65, null]], -[65, ["string", "box 2"], 160, 618, [64, null]], -[66, "red", 124, 366, [16, null]], -[67, "fillscreen2", 788, 224, [0, 68, 69, 70, 42]], -[68, ["number", 60], 870, 224, [67, null]], -[69, ["number", 80], 870, 266, [67, null]], -[70, ["number", 100], 870, 308, [67, null]], -[71, "orange", 124, 576, [17, null]]] +[[0, ["start", 2.0], 30, 550, [null, 164]], +[1, ["setxy2", 20], 1317, 731, [83, 5, 166, 6]], +[2, ["number", 20], 1429, 773, [5, null]], +[3, "xcor", 1429, 731, [5, null]], +[4, "ycor", 1429, 813, [166, null]], +[5, ["plus2", 0], 1375, 731, [1, 3, 2]], +[6, ["vspace", 0], 1317, 855, [1, 89]], +[7, "penup", 1317, 521, [156, 19]], +[8, "pendown", 1317, 1317, [25, 158]], +[9, ["number", 60], 1429, 855, [166, null]], +[10, "hat", 33, 869, [null, 11, 70]], +[11, ["string", "next"], 91, 881, [10, null]], +[12, "stack", 30, 638, [164, 13, null]], +[13, ["string", "next"], 88, 638, [12, null]], +[14, "clean", 33, 1007, [75, 37]], +[15, "hat", 1334, 415, [null, 36, 72]], +[16, "stack", 33, 1217, [73, 35, 31]], +[17, "show", 1317, 1191, [30, 18, 25]], +[18, ["string", "The repeat block repeats an action."], 1375, 1191, [17, null]], +[19, ["setxy2", 0], 1317, 563, [7, 20, 21, 83]], +[20, ["number", -300], 1375, 563, [19, null]], +[21, ["number", 100], 1375, 605, [19, null]], +[22, ["setxy2", 0], 1317, 1065, [87, 23, 29, 30]], +[23, ["number", -300], 1375, 1065, [22, null]], +[24, ["number", 80], 1453, 1149, [29, null]], +[25, ["setxy2", 0], 1317, 1233, [17, 26, 27, 8]], +[26, ["number", 0], 1375, 1233, [25, null]], +[27, ["number", 0], 1375, 1275, [25, null]], +[28, "ycor", 1429, 1107, [29, null]], +[29, ["minus2", 0], 1375, 1107, [22, 28, 24]], +[30, ["vspace", 0], 1317, 1149, [22, 17]], +[31, "storeinbox1", 33, 1259, [16, 34, null]], +[32, ["number", 1], 205, 1301, [34, null]], +[33, "box1", 205, 1259, [34, null]], +[34, ["plus2", 0], 151, 1259, [31, 33, 32]], +[35, "box1", 91, 1217, [16, null]], +[36, ["number", 3], 1392, 427, [15, null]], +[37, ["if", 0], 33, 1049, [14, 41, 38, 73]], +[38, "storeinbox1", 51, 1115, [37, 39, null]], +[39, ["number", 0], 169, 1115, [38, null]], +[40, "box1", 135, 1015, [41, null]], +[41, ["greater2", 0], 89, 1015, [37, 40, 42, null]], +[42, ["number", 3], 159, 1057, [41, null]], +[43, ["number", 1], 1384, 194, [69, null]], +[44, "penup", 1344, 270, [71, 45]], +[45, ["setxy2", 0], 1344, 312, [44, 46, 47, 85]], +[46, ["number", -300], 1402, 312, [45, null]], +[47, ["number", 100], 1402, 354, [45, null]], +[48, ["setxy2", 0], 1344, 984, [77, 49, 50, 53]], +[49, ["number", -300], 1402, 984, [48, null]], +[50, ["minus2", 0], 1402, 1026, [48, 51, 52]], +[51, "ycor", 1456, 1026, [50, null]], +[52, ["number", 40.0], 1480, 1068, [50, null]], +[53, ["vspace", 0], 1344, 1068, [48, 54]], +[54, "show", 1344, 1110, [53, 55, 56]], +[55, ["string", "The turtle can move forward, back, left, and right."], 1402, 1110, [54, null]], +[56, ["setxy2", 0], 1344, 1152, [54, 57, 58, 59]], +[57, ["number", 0], 1402, 1152, [56, null]], +[58, ["number", 0], 1402, 1194, [56, null]], +[59, "pendown", 1344, 1236, [56, null]], +[60, ["setxy2", 0], 1344, 480, [85, 61, 62, 81]], +[61, ["number", -300], 1402, 480, [60, null]], +[62, ["number", 25.0], 1402, 522, [60, null]], +[63, ["setxy2", 0], 1344, 648, [81, 64, 65, 79]], +[64, ["number", -300], 1402, 648, [63, null]], +[65, ["number", -50.0], 1402, 690, [63, null]], +[66, ["setxy2", 0], 1344, 816, [79, 67, 68, 77]], +[67, ["number", -300], 1402, 816, [66, null]], +[68, ["number", -125], 1402, 858, [66, null]], +[69, "hat", 1326, 182, [null, 43, 71]], +[70, "showblocks", 33, 923, [10, 75]], +[71, "sandwichclampcollapsed", 1326, 236, [69, 44, null]], +[72, "sandwichclampcollapsed", 1334, 469, [15, 156, null]], +[73, ["loadblock", 0], 33, 1175, [37, 74, 16]], +[74, ["string", "delete"], 91, 1175, [73, null]], +[75, "loadpalette", 33, 965, [70, 76, 14]], +[76, ["string", "turtle"], 94, 965, [75, null]], +[77, ["loadblock2arg", 0], 1344, 900, [66, 78, 97, 48]], +[78, ["string", "right"], 1402, 900, [77, null]], +[79, ["loadblock2arg", 0], 1344, 732, [63, 80, 96, 66]], +[80, ["string", "left"], 1402, 732, [79, null]], +[81, ["loadblock2arg", 0], 1344, 564, [60, 82, 95, 63]], +[82, ["string", "back"], 1402, 564, [81, null]], +[83, ["loadblock2arg", 0], 1317, 647, [19, 84, 91, 1]], +[84, ["string", "repeat"], 1375, 647, [83, null]], +[85, ["loadblock2arg", 0], 1344, 396, [45, 86, 94, 60]], +[86, ["string", "forward"], 1402, 396, [85, null]], +[87, ["loadblock2arg", 0], 1317, 981, [89, 88, 93, 22]], +[88, ["string", "right"], 1375, 981, [87, null]], +[89, ["loadblock2arg", 0], 1317, 897, [6, 90, 92, 87]], +[90, ["string", "forward"], 1375, 897, [89, null]], +[91, ["number", 4], 1375, 689, [83, null]], +[92, ["number", 100], 1375, 939, [89, null]], +[93, ["number", 90], 1375, 1023, [87, null]], +[94, ["number", 100], 1402, 438, [85, null]], +[95, ["number", 100], 1402, 606, [81, null]], +[96, ["number", 90], 1402, 774, [79, null]], +[97, ["number", 90], 1402, 942, [77, null]], +[98, "hat", 1327, 69, [null, 99, 100]], +[99, ["number", 0], 1385, 81, [98, null]], +[100, "sandwichclampcollapsed", 1327, 123, [98, 101, null]], +[101, "penup", 1310, 133, [100, 102]], +[102, ["setxy2", 0], 1310, 175, [101, 103, 104, 105]], +[103, ["number", -300], 1368, 175, [102, null]], +[104, ["number", -75], 1368, 217, [102, null]], +[105, ["loadblock2arg", 0], 1310, 259, [102, 106, 107, 108]], +[106, ["string", "forward"], 1368, 259, [105, null]], +[107, ["number", 100], 1368, 301, [105, null]], +[108, ["setxy2", 0], 1310, 343, [105, 109, 110, 113]], +[109, ["number", -300], 1368, 343, [108, null]], +[110, ["minus2", 0], 1368, 385, [108, 111, 112]], +[111, "ycor", 1422, 385, [110, null]], +[112, ["number", 75], 1446, 427, [110, null]], +[113, ["vspace", 0], 1310, 427, [108, 114]], +[114, "show", 1310, 469, [113, 115, 116]], +[115, ["string", "The turtle goes forward 100 steps."], 1368, 469, [114, null]], +[116, ["setxy2", 0], 1310, 511, [114, 117, 118, 119]], +[117, ["number", 0], 1368, 511, [116, null]], +[118, ["number", 0], 1368, 553, [116, null]], +[119, "pendown", 1310, 595, [116, 120]], +[120, "forward", 1310, 637, [119, 121, null]], +[121, ["number", 100], 1381, 637, [120, null]], +[122, "hat", 1329, 296, [null, 123, 124]], +[123, ["number", 2], 1387, 308, [122, null]], +[124, "sandwichclampcollapsed", 1329, 350, [122, 125, null]], +[125, "penup", 1312, 360, [124, 126]], +[126, ["setxy2", 0], 1312, 402, [125, 127, 128, 129]], +[127, ["number", -300], 1370, 402, [126, null]], +[128, ["number", 100], 1370, 444, [126, null]], +[129, ["loadblock2arg", 0], 1312, 486, [126, 130, 131, 132]], +[130, ["string", "forward"], 1370, 486, [129, null]], +[131, ["number", 100], 1370, 528, [129, null]], +[132, ["loadblock2arg", 0], 1312, 570, [129, 136, 133, 134]], +[133, ["number", 45], 1370, 612, [132, null]], +[134, ["loadblock2arg", 0], 1312, 654, [132, 149, 135, 137]], +[135, ["number", 100], 1370, 696, [134, null]], +[136, ["string", "right"], 1370, 570, [132, null]], +[137, ["setxy2", 0], 1312, 738, [134, 138, 139, 142]], +[138, ["number", -300], 1370, 738, [137, null]], +[139, ["minus2", 0], 1370, 780, [137, 140, 141]], +[140, "ycor", 1424, 780, [139, null]], +[141, ["number", 200], 1448, 822, [139, null]], +[142, ["vspace", 0], 1312, 822, [137, 143]], +[143, "show", 1312, 864, [142, 144, 145]], +[144, ["string", "The turtle runs a stack of blocks, starting from the top block."], 1370, 864, [143, null]], +[145, ["setxy2", 0], 1312, 906, [143, 146, 147, 148]], +[146, ["number", 0], 1370, 906, [145, null]], +[147, ["number", 0], 1370, 948, [145, null]], +[148, "pendown", 1312, 990, [145, 150]], +[149, ["string", "forward"], 1370, 654, [134, null]], +[150, "forward", 1312, 1032, [148, 151, 152]], +[151, ["number", 100], 1383, 1032, [150, null]], +[152, "right", 1312, 1074, [150, 153, 154]], +[153, ["number", 45], 1370, 1074, [152, null]], +[154, "forward", 1312, 1116, [152, 155, null]], +[155, ["number", 100], 1383, 1116, [154, null]], +[156, "loadpalette", 1317, 479, [72, 157, 7]], +[157, ["string", "flow"], 1378, 479, [156, null]], +[158, ["repeat", 21], 1317, 1359, [8, 159, 160, null]], +[159, ["number", 4], 1376, 1359, [158, null]], +[160, "forward", 1335, 1401, [158, 161, 162]], +[161, ["number", 100], 1406, 1401, [160, null]], +[162, "right", 1335, 1443, [160, 163, null]], +[163, ["number", 90], 1393, 1443, [162, null]], +[164, "comment", 30, 596, [0, 165, 12]], +[165, ["string", "Click on the start block."], 113, 596, [164, null]], +[166, ["plus2", 0], 1375, 813, [1, 4, 9]]] diff --git a/turtleblocks.py b/turtleblocks.py index 1e6495f..55a02dc 100755 --- a/turtleblocks.py +++ b/turtleblocks.py @@ -569,6 +569,7 @@ Would you like to save before quitting?')) if pyee.block is not None: pyee.block.highlight() self.tw.showlabel('status', str(pyee)) + print pyee return if not pythoncode: return @@ -582,7 +583,7 @@ Would you like to save before quitting?')) (filename, self.tw.load_save_folder) = get_save_name( save_type, self.tw.load_save_folder, default_name) if isinstance(filename, unicode): - filename = filename.encode('utf8') + filename = filename.encode('utf-8') if filename is not None: f = file(filename, 'w') f.write(pythoncode) |