From 90a696e3e66ad1b6a3865218fb19e1093f0337b8 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Thu, 21 Jan 2010 22:04:23 +0000 Subject: adding Turtle class --- diff --git a/block.py b/block.py index 74b995c..c12a8e4 100644 --- a/block.py +++ b/block.py @@ -19,21 +19,17 @@ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. -import pygtk -pygtk.require('2.0') -import gtk -import gobject from constants import * import sprite_factory import sprites +from gettext import gettext as _ # # A class for the list of blocks and everything they share in common # class Blocks: - def __init__(self, sprite_list): + def __init__(self): self.list = [] - self.sprites = sprite_list def get_block(self, i): if i < 0 or i > len(self.list)-1: @@ -47,53 +43,47 @@ class Blocks: def append_to_list(self,block): self.list.append(block) - def insert_in_list(self,block,i): - if i < 0: - self.list.insert(0, block) - elif i > len(self.list)-1: - self.list.append(block) - else: - self.list.insert(i, block) - def remove_from_list(self, block): if block in self.list: self.list.remove(block) # - # block and spr utilities + # sprite utilities # def spr_to_block(self, spr): for b in self.list: if spr == b.spr: return b + return None # # A class for the individual blocks # class Block: - def __init__(self, blocks, proto_name, x, y, labels=[], + def __init__(self, block_list, sprite_list, proto_name, x, y, labels=[], colors=["#00FF00","#00A000"], scale=2.0): - self.blocks = blocks self.spr = None self.shape = None self.selected_shape = None - self._new_block_from_prototype(proto_name, labels, colors, scale, x, y) - self.blocks.append_to_list(self) + self.name = proto_name + self.docks = None + self.connections = None + self._new_block_from_prototype(sprite_list, proto_name, labels, colors, + scale, x, y) + block_list.append_to_list(self) # # TODO: - # save arguments - # dock and connection info - # highlight image # Logo code # HTML code # debug code # etc. - def _new_block_from_prototype(self, name, labels, colors, scale, x, y): + def _new_block_from_prototype(self, sprite_list, name, labels, colors, + scale, x, y): if len(labels) == 0: - print "%s (%d %d)" % (name, x, y) + print "new block: %s (%d %d)" % (name, x, y) else: - print "%s %s (%d %d)" % (name, labels[0], x, y) + print "new block: %s %s (%d %d)" % (name, labels[0], x, y) svg = sprite_factory.SVG() if name in TURTLE_PALETTE: @@ -118,96 +108,72 @@ class Block: svg.set_slot(True) if name in BASIC_STYLE: svg.expand(40,0) - self._make_basic_block(svg, x, y) - self.docks = (('flow',True,37,5),('flow',False,37,44)) - print "created new basic block: %s" % (str(self.spr)) + self._make_basic_block(sprite_list, svg, x, y) + self.docks = (('flow',True,37,5),('flow',False,37,39)) elif name in BASIC_STYLE_HEAD: svg.expand(40,0) svg.set_slot(False) - self._make_basic_block(svg, x, y) - self.docks = (('start',True,50,0), ('flow',False,49,55)) - print "created new basic block head: %s" % (str(self.spr)) + self._make_basic_block(sprite_list, svg, x, y) + self.docks = (('start',True,37,0), ('flow',False,37,39)) elif name in BASIC_STYLE_HEAD_1ARG: svg.expand(40,0) svg.set_slot(False) - self._make_basic_block(svg, x, y) - self.docks = (('start',True,50,0), ('string',False,21,38), - ('flow',False,75,75)) - print "created new basic block head: %s" % (str(self.spr)) + self._make_basic_block(sprite_list, svg, x, y) + self.docks = (('start',True,37,0), ('string',False,42,12), + ('flow',False,37,44)) elif name in BASIC_STYLE_TAIL: svg.expand(40,0) svg.set_tab(False) - self._make_basic_block(svg, x, y) + self._make_basic_block(sprite_list, svg, x, y) self.docks = (('flow',True,37,5),('unavailable',False,0,0)) - print "created new basic block tail: %s" % (str(self.spr)) elif name in BASIC_STYLE_1ARG: - svg.expand(20,0) + ex = 25 + ey = 0 + svg.expand(ex,ey) svg.set_innie([True]) - self._make_basic_block(svg, x, y) - self.docks = (('flow',True,37,5), ('num',False,74,21), - ('flow',False,37,44)) - print "created new basic block 1 arg: %s" % (str(self.spr)) + self._make_basic_block(sprite_list, svg, x, y) + self.docks = (('flow',True,37,5), ('num',False,42+ex*scale,12), + ('flow',False,37,44+ey)) elif name in BASIC_STYLE_2ARG: - svg.expand(20,0) + ex = 25 + ey = 0 + svg.expand(ex,ey) svg.set_innie([True,True]) - self._make_basic_block(svg, x, y) - self.docks = (('flow',True,37,5), ('num',False,74,21), - ('num',False,74,58), ('flow',False,37,81)) - print "created new basic block 2 args: %s" % (str(self.spr)) + self._make_basic_block(sprite_list, svg, x, y) + self.docks = (('flow',True,37,5), ('num',False,42+ex*scale,12), + ('num',False,42+ex*scale,54), ('flow',False,37,81)) elif name in BOX_STYLE: svg.expand(50,0) - self._make_basic_box(svg, x, y) - self.docks = (('num',True,0,12),('numend',False,105,12)) - print "created new box block: %s" % (str(self.spr)) + self._make_basic_box(sprite_list, svg, x, y) + self.docks = (('num',True,0,12),('unavailable',False,105,12)) else: svg.expand(40,0) - self._make_basic_block(svg, x, y) + self._make_basic_block(sprite_list, svg, x, y) print "don't know how to create a block for %s" % (name) if len(labels) > 0: - self.spr.set_label(labels[0]) + self.spr.set_label(_(labels[0])) for label in labels: self.spr.set_label(label, labels.index(label)) self.type = 'block' + if DEFAULTS.has_key(name): + self.defaults = DEFAULTS[name] + else: + self.defaults = [] - def _make_basic_block(self, svg, x, y): - self.shape = svg_str_to_pixbuf(svg.basic_block()) + def _make_basic_block(self, sprite_list, svg, x, y): + self.shape = sprite_factory.svg_str_to_pixbuf(svg.basic_block()) svg.set_stroke_width(SELECTED_STROKE_WIDTH) svg.set_stroke_color(SELECTED_COLOR) - self.selected_shape = svg_str_to_pixbuf(svg.basic_block()) - self.spr = sprites.Sprite(self.blocks.sprites, x, y, self.shape) + self.selected_shape =\ + sprite_factory.svg_str_to_pixbuf(svg.basic_block()) + self.spr = sprites.Sprite(sprite_list, x, y, self.shape) - def _make_basic_box(self, svg, x, y): - self.shape = svg_str_to_pixbuf(svg.basic_box()) + def _make_basic_box(self, sprite_list, svg, x, y): + self.shape = sprite_factory.svg_str_to_pixbuf(svg.basic_box()) svg.set_stroke_width(SELECTED_STROKE_WIDTH) svg.set_stroke_color(SELECTED_COLOR) - self.selected_shape = svg_str_to_pixbuf(svg.basic_box()) - self.spr = sprites.Sprite(self.blocks.sprites, x, y, self.shape) - -class Turtle: - def __init__(self, blocks, orientation=0, scale=1.0): - self.blocks = blocks - self.spr = None - self._new_turtle_from_prototype(orientation, scale) - self.blocks.append_to_list(self) - self.orientation = orientation - - def _new_turtle_from_prototype(self, orientation, scale): - svg = sprite_factory.SVG() - svg.set_scale(scale) - svg.set_orientation(orientation) - self.spr = sprites.Sprite(self.blocks.sprites, 0, 0, - svg_str_to_pixbuf(svg.turtle())) - self.type = 'turtle' - -# -# Load pixbuf from SVG string -# -def svg_str_to_pixbuf(svg_string): - pl = gtk.gdk.PixbufLoader('svg') - pl.write(svg_string) - pl.close() - pixbuf = pl.get_pixbuf() - return pixbuf + self.selected_shape = sprite_factory.svg_str_to_pixbuf(svg.basic_box()) + self.spr = sprites.Sprite(sprite_list, x, y, self.shape) diff --git a/constants.py b/constants.py index 8877a78..e4cb0a0 100644 --- a/constants.py +++ b/constants.py @@ -17,15 +17,15 @@ from gettext import gettext as _ # sprite layers # -CANVAS_LAYER = 500 -TURTLE_LAYER = 550 HIDE_LAYER = 100 +CANVAS_LAYER = 500 OVERLAY_LAYER = 525 -STATUS_LAYER = 900 -TOP_LAYER = 1000 +TURTLE_LAYER = 2550 BLOCK_LAYER = 600 CATEGORY_LAYER = 700 TAB_LAYER = 710 +STATUS_LAYER = 900 +TOP_LAYER = 1000 # # block definitions @@ -47,7 +47,7 @@ TURTLE_PALETTE = ['clean', 'forward', 'back', 'left', 'right', 'seth', 'show',\ 'set_scale', 'xcor', 'ycor', 'heading'] PEN_PALETTE = ['pen up','pen down'] NUMBER_PALETTE = ['number'] -BLOCKS_PALETTE = ['start', 'string'] +BLOCKS_PALETTE = ['start', 'string', 'store in box 1'] FLOW_PALETTE = [] MISC_PALETTE = [] PORTFOLIO_PALETTE = [] @@ -67,11 +67,12 @@ SELECTED_STROKE_WIDTH = 2.0 # default values # -DEFAULTS = {'forward':100, 'back':100, 'left':90, 'set xy':(0,0), - 'arc':(90,100), 'seth':0, 'set scale':33, 'show':_('text'), - 'set pen size':5, 'set text size':32, 'set color':0, - 'set shade':50, 'fill screen':(60,80), 'number':100, - 'random':(0,100), 'wait':1, 'repeat':4, 'store in':(_('box'),100)} +DEFAULTS = {'forward':[100], 'back':[100], 'left':[90], 'right':[90], + 'arc':[90,100], 'seth':[0], 'set scale':[33], 'show':[_('text')], + 'set pen size':[5], 'set text size':[32], 'set color':[0], + 'set shade':[50], 'fill screen':[60,80], 'number':[100], + 'random':[0,100], 'wait':[1], 'repeat':[4], 'set xy':[0,0], + 'store in':[_('box'),100]} # # 'dead key' Unicode dictionaries # diff --git a/sprite_factory.py b/sprite_factory.py index 8f58d92..22b9c56 100755 --- a/sprite_factory.py +++ b/sprite_factory.py @@ -20,6 +20,9 @@ #OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN #THE SOFTWARE. +import pygtk +pygtk.require('2.0') +import gtk import os from gettext import gettext as _ @@ -605,3 +608,13 @@ if __name__ == "__main__": main() +# +# Load pixbuf from SVG string +# +def svg_str_to_pixbuf(svg_string): + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf + diff --git a/taproject.py b/taproject.py index 2b1db79..48fd5af 100644 --- a/taproject.py +++ b/taproject.py @@ -53,6 +53,7 @@ except: import block import sprites from constants import * +from gettext import gettext as _ nolabel = ['audiooff', 'descriptionoff', 'journal'] shape_dict = {'journal':'texton', \ @@ -97,8 +98,8 @@ def load_files(tw, ta_file, create_new_project=True): read_data(tw,data) def get_load_name(tw): - dialog = gtk.FileChooserDialog("Load...", None, \ - gtk.FILE_CHOOSER_ACTION_OPEN, \ + dialog = gtk.FileChooserDialog("Load...", None, + gtk.FILE_CHOOSER_ACTION_OPEN, (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL,gtk.STOCK_OPEN, gtk.RESPONSE_OK)) dialog.set_default_response(gtk.RESPONSE_OK) return do_dialog(tw,dialog) @@ -122,9 +123,11 @@ def clone_stack(tw,text): io = StringIO(text) listdata = jload(io) data = tuplify(listdata) # json converts tuples to lists - read_stack(tw,data) + # read_stack(tw,data) + read_data(tw,data) # paste stack from the clipboard +# TODO: rebase on read data def read_stack(tw,data): clone = [] for b in data: @@ -142,22 +145,23 @@ def tuplify(t): return tuple(map(tuplify, t)) def read_data(tw,data): - blocks = [] + sprs = [] for b in data: if b[1]=='turtle': load_turtle(tw,b) - else: spr = load_spr(tw, b); blocks.append(spr) - for i in range(len(blocks)): + else: spr = load_spr(tw, b); sprs.append(spr) + for i in range(len(sprs)): cons=[] for c in data[i][4]: if c==None: cons.append(None) - else: cons.append(blocks[c]) - blocks[i].connections = cons + else: cons.append(sprs[c]) + sprs[i].connections = cons # phasing out + tw.block_list.spr_to_block(sprs[i]).connections = cons def load_spr(tw,b): media = None btype, label = b[1],None - if type(btype)==type((1,2)): + if type(btype) == type((1,2)): btype, label = btype if btype == 'title': # for backward compatibility btype = 'string' @@ -169,16 +173,13 @@ def load_spr(tw,b): except KeyError: print "swapping in a forward block for %s" % (btype) proto = tw.protodict['forward'] - blk = block.Block(tw.blocks,btype,b[2]+tw.turtle.canvas.x, - b[3]+tw.turtle.canvas.y, [btype]) + blk = block.Block(tw.block_list, tw.sprite_list, + btype, b[2]+tw.turtle.canvas.x, + b[3]+tw.turtle.canvas.y, [label]) spr = blk.spr - ''' - spr = sprites.Sprite(tw.sprites,b[2]+tw.turtle.canvas.x, - b[3]+tw.turtle.canvas.y, proto.image) - ''' - spr.type = 'block' - spr.proto = proto - if label is not None: spr.set_label(label) + spr.type = 'block' # phasing out + spr.proto = proto # phasing out + # if label is not None: spr.set_label(label) # phasing out if media is not None and media not in nolabel: try: dsobject = datastore.get(media) @@ -256,22 +257,22 @@ def save_string(tw,save_turtle=True): return text def assemble_data_to_save(tw,save_turtle=True): - bs = blocks(tw) data = [] - for i in range(len(bs)): bs[i].id=i - for b in bs: - name = b.proto.name + for i, b in enumerate(tw.block_list.list): + b.id = i + for b in tw.block_list.list: + name = (b.name, b.spr.labels[0]) if tw.defdict.has_key(name) or name in nolabel: if hasattr(b,"ds_id") and b.ds_id != None: name=(name, str(b.ds_id)) else: - name=(name, b.labels[0]) + name=(name, b.spr.labels[0]) if hasattr(b,'connections'): - connections = [get_id(x) for x in b.connections] + connections = [get_id(tw.block_list, x) for x in b.connections] else: connections = None - data.append((b.id, name, b.x-tw.turtle.canvas.x, - b.y-tw.turtle.canvas.y, connections)) + data.append((b.id, name, b.spr.x-tw.turtle.canvas.x, + b.spr.y-tw.turtle.canvas.y, connections)) if save_turtle is True: data.append((-1,'turtle', tw.turtle.xcor,tw.turtle.ycor,tw.turtle.heading, @@ -292,10 +293,11 @@ def serialize_stack(tw): return text # find the stack under the cursor and serialize it +# TODO: rebase on assemble data to save def assemble_stack_to_clone(tw): if tw.spr is None or tw.spr.type is not "block": (x,y) = tw.window.get_pointer() - spr = tw.sprites.find_sprite((x,y)) + spr = tw.sprite_list.find_sprite((x,y)) if spr is not None: print "found block of type " + spr.type else: @@ -312,25 +314,25 @@ def assemble_stack_to_clone(tw): name=(name,str(b.ds_id)) else: name=(name,b.labels[0]) - if hasattr(b,'connections'): + if hasattr(b,'connections') and b.connections is not None: connections = [get_id(x) for x in b.connections] else: connections = None - data.append((b.id,name,b.x-tw.turtle.canvas.x+20, \ + data.append((b.id,name,b.x-tw.turtle.canvas.x+20, b.y-tw.turtle.canvas.y+20,connections)) return data def save_pict(tw,fname): tc = tw.turtle.canvas - pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, tc.width, \ + pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, tc.width, tc.height) - pixbuf.get_from_drawable(tc.image, tc.image.get_colormap(), 0, 0, 0, 0, \ + pixbuf.get_from_drawable(tc.image, tc.image.get_colormap(), 0, 0, 0, 0, tc.width, tc.height) pixbuf.save(fname, 'png') -def get_id(x): +def get_id(blocks, x): if x==None: return None - return x.id + return blocks.spr_to_block(x).id def do_dialog(tw,dialog): result = None @@ -346,12 +348,14 @@ def do_dialog(tw,dialog): dialog.destroy() return result -def blocks(tw): return [spr for spr in tw.sprites.list if spr.type == 'block'] +# phasing out +def blocks(tw): return [spr for spr in tw.sprite_list.list \ + if spr.type == 'block'] def findgroup(b): group=[b] for b2 in b.connections[1:]: - if b2!=None: group.extend(findgroup(b2)) + if b2 is not None: group.extend(findgroup(b2)) return group def find_top_block(spr): @@ -363,5 +367,6 @@ def find_top_block(spr): # start a new project with a start brick def load_start(tw): - clone_stack(tw,str("[[0,\"start\",250,30,[null,null]]]")) + clone_stack(tw,"%s%s%s" % ("[[0,[\"start\",\"", _("start"), + "\"],250,30,[null,null]]]")) diff --git a/tasetup.py b/tasetup.py index 920abe3..77fc458 100644 --- a/tasetup.py +++ b/tasetup.py @@ -29,9 +29,6 @@ import time from gettext import gettext as _ -# from tasprites import * - -import block import sprites from constants import * @@ -266,21 +263,10 @@ def setup_selectors(tw,s): tw.selbuttons.append(cat) def setup_misc(tw): - # tw.category_spr = Sprite(tw, 0, 0, tw.selbuttons[0].group) - tw.category_spr = sprites.Sprite(tw.sprites, 0, 0, tw.selbuttons[0].group) + tw.category_spr = sprites.Sprite(tw.sprite_list, 0, 0, + tw.selbuttons[0].group) tw.category_spr.type = 'category' tw.category_spr.set_layer(CATEGORY_LAYER) - # masks get positioned on top of other blocks - # tw.select_mask = Sprite(tw,100,100,\ - tw.select_mask = sprites.Sprite(tw.sprites, 100, 100,\ - load_image(tw, tw.path, '', 'masknumber')) - tw.select_mask.type = 'selectmask' - tw.select_mask.hide() - # tw.select_mask_string = Sprite(tw,100,100,\ - tw.select_mask_string = sprites.Sprite(tw.sprites, 100, 100,\ - load_image(tw, tw.path, '', 'maskstring')) - tw.select_mask_string.type = 'selectmask' - tw.select_mask_string.hide() # used to hide the palette tw.hidden_palette_icon = load_image(tw, tw.path, '','blocks-') # media blocks get positioned into other blocks @@ -293,14 +279,14 @@ def setup_misc(tw): tw.media_shapes['pythonloaded'] = \ load_image(tw, tw.path_lang, 'sensors', 'nop-loaded') # coordinare systems - # tw.cartesian_coordinates_spr = Sprite(tw, tw.width/2-600, tw.height/2-450, \ - tw.cartesian_coordinates_spr = sprites.Sprite(tw.sprites, tw.width/2-600, tw.height/2-450, \ + tw.cartesian_coordinates_spr = sprites.Sprite(tw.sprite_list, + tw.width/2-600, tw.height/2-450, load_image(tw, tw.path, '', "Cartesian")) tw.cartesian_coordinates_spr.type = 'coordinates' tw.cartesian_coordinates_spr.set_layer(OVERLAY_LAYER) tw.cartesian_coordinates_spr.hide() - # tw.polar_coordinates_spr = Sprite(tw, tw.width/2-600, tw.height/2-450, \ - tw.polar_coordinates_spr = sprites.Sprite(tw.sprites, tw.width/2-600, tw.height/2-450, \ + tw.polar_coordinates_spr = sprites.Sprite(tw.sprite_list, + tw.width/2-600, tw.height/2-450, load_image(tw, tw.path, '', "polar")) tw.polar_coordinates_spr.type = 'coordinates' tw.polar_coordinates_spr.set_layer(OVERLAY_LAYER) @@ -318,9 +304,8 @@ def setup_misc(tw): tw.status_shapes['overflowerror'] = \ load_image(tw, tw.path, '', 'overflowerror') tw.status_shapes['syntaxerror'] = load_image(tw, tw.path, '', 'syntaxerror') - # tw.status_spr = Sprite(tw,0,(tw.height-175), \ - tw.status_spr = sprites.Sprite(tw.sprites, 0, (tw.height-175), \ - tw.status_shapes['status']) + tw.status_spr = sprites.Sprite(tw.sprite_list, 0, (tw.height-175), + tw.status_shapes['status']) tw.status_spr.set_label("test") # tw.status_spr.set_label_attributes(1.0, True, "left") tw.status_spr.type = 'status' @@ -334,8 +319,7 @@ def setup_selector(tw,name,y,blockdescriptions): # selector tabs offshape = load_image(tw, tw.path, 'palette', name+'off') onshape = load_image(tw, tw.path, 'palette', name+'on') - # spr = Sprite(tw,143,y,offshape) - spr = sprites.Sprite(tw.sprites, 143, y, offshape) + spr = sprites.Sprite(tw.sprite_list, 143, y, offshape) spr.set_layer(TAB_LAYER) spr.offshape = offshape spr.onshape = onshape diff --git a/taturtle.py b/taturtle.py index 823e8f8..7660f97 100644 --- a/taturtle.py +++ b/taturtle.py @@ -23,10 +23,9 @@ import gtk from math import sin,cos,pi class taTurtle: pass -# from tasprites import * from tasetup import load_image import sprites -import block +import turtlex import pango from constants import * @@ -59,16 +58,15 @@ color_table = ( def tNew(tw,w,h): t = taTurtle() t.tw, t.width, t.height = tw, w, h - # t.canvas = Sprite(tw,0,0,gtk.gdk.Pixmap(tw.area,w,h,-1)) - t.canvas = sprites.Sprite(tw.sprites, 0, 0, gtk.gdk.Pixmap(tw.area,w,h,-1)) + t.canvas = sprites.Sprite(tw.sprite_list, 0, 0, + gtk.gdk.Pixmap(tw.area,w,h,-1)) t.canvas.type = 'canvas' t.canvas.set_layer(CANVAS_LAYER) t.shapelist = \ [load_image(tw, tw.path, 'shapes','t'+str(i)) for i in range(36)] - # t.spr = Sprite(tw,100,100,t.shapelist[0]) # t.spr = sprites.Sprite(tw.sprites, 100, 100, t.shapelist[0]) - t.blk = block.Turtle(tw.blocks) - t.spr = t.blk.spr + t.t = turtlex.Turtle(tw.turtle_list, tw.sprite_list) + t.spr = t.t.spr t.spr.type = 'turtle' t.spr.set_layer(TURTLE_LAYER) t.gc = t.canvas.image.new_gc() diff --git a/tawindow.py b/tawindow.py index 4d47560..f40da15 100644 --- a/tawindow.py +++ b/tawindow.py @@ -56,6 +56,7 @@ from gettext import gettext as _ import sprites import block +import turtlex """ TurtleArt Window class abstraction @@ -129,8 +130,9 @@ class TurtleArtWindow(): """ NEW SVG/BLOCK initializations """ - self.sprites = sprites.Sprites(self.window, self.area, self.gc) - self.blocks = block.Blocks(self.sprites) + self.sprite_list = sprites.Sprites(self.window, self.area, self.gc) + self.block_list = block.Blocks() + self.turtle_list = turtlex.Turtles() """ """ self.turtle = tNew(self,self.width,self.height) @@ -166,7 +168,7 @@ class TurtleArtWindow(): change the icon for user-defined blocks after Python code is loaded """ def set_userdefined(self): - for spr in self.sprites.list: + for spr in self.sprite_list.list: if hasattr(spr,'proto') and spr.proto.name == 'nop': setimage(spr,self.media_shapes['pythonloaded']) self.nop = 'pythonloaded' @@ -178,8 +180,6 @@ class TurtleArtWindow(): if self.hide is False: for b in self._blocks(): b.set_layer(HIDE_LAYER) self._hide_palette() - self.select_mask.hide() - self.select_mask_string.hide() self.hide = True else: for b in self._blocks(): b.set_layer(BLOCK_LAYER) @@ -216,11 +216,11 @@ class TurtleArtWindow(): if verbose: print "processing remote button press: " + str(x) + " " + str(y) self.block_operation = 'click' - if self.selected_block != None: + if self.selected_block is not None: self._unselect() else: self.status_spr.set_layer(HIDE_LAYER) - spr = self.sprites.find_sprite((x,y)) + spr = self.sprite_list.find_sprite((x,y)) print "found %s at (%d,%d)" % (str(spr),x,y) self.x, self.y = x,y self.dx = 0 @@ -230,6 +230,7 @@ class TurtleArtWindow(): if hasattr(spr, 'type'): print "type: %s" % (spr.type) if spr.type == "canvas": + spr.set_layer(CANVAS_LAYER) return True elif spr.type == 'selbutton': self._select_category(spr) @@ -277,8 +278,10 @@ class TurtleArtWindow(): self.selected_block.set_label('0') # put an upper and lower bound on numbers to prevent OverflowError - if self.selected_block.proto.name == 'number' and \ - self.selected_block.labels[0] is not None: + if self.block_list.spr_to_block(self.selected_block).name == 'number'\ + and self.selected_block.labels[0] is not None: + # if self.selected_block.proto.name == 'number' and \ + # self.selected_block.labels[0] is not None: try: i = float(self.selected_block.labels[0]) if i > 1000000: @@ -290,10 +293,8 @@ class TurtleArtWindow(): except ValueError: pass - self.select_mask.hide() - self.select_mask_string.hide() self.selected_block.set_shape( - self.blocks.spr_to_block(self.selected_block).shape) + self.block_list.spr_to_block(self.selected_block).shape) self.selected_block = None """ @@ -391,7 +392,7 @@ class TurtleArtWindow(): self.block_operation = 'move' spr = self.draggroup[0] - if spr.type == 'block': + if self.block_list.spr_to_block(spr) is not None: self.spr = spr dragx, dragy = self.dragpos if mdx != 0 or mdy != 0: @@ -413,7 +414,7 @@ class TurtleArtWindow(): # move the stack for b in self.draggroup: b.move((b.x+dx, b.y+dy)) - elif spr.type=='turtle': + if self.turtle_list.spr_to_turtle(spr) is not None: type,dragx,dragy = self.dragpos if type == 'move': if mdx != 0 or mdy != 0: @@ -437,8 +438,9 @@ class TurtleArtWindow(): get_proto_from_category """ def _get_proto_from_category(self, x, y): - dx, dy = x-self.category_spr.x, y-self.category_spr.y, - pixel = self.current_category.get_pixel(self.current_category.mask,dx,dy) + pixel = self.current_category.get_pixel(self.current_category.mask, + x-self.category_spr.x, + y-self.category_spr.y) index = ((pixel%256)>>3)-1 if index==0: return 'hide' @@ -448,10 +450,11 @@ class TurtleArtWindow(): return self.current_category.blockprotos[index] """ - lets help our our user by displaying a little help + lets help our users by displaying a little help """ def _show_popup(self, x, y): - spr = self.sprites.find_sprite((x,y)) + spr = self.sprite_list.find_sprite((x,y)) + blk = self.block_list.spr_to_block(spr) if spr and spr.type == 'category': proto = self._get_proto_from_category(x, y) if proto and proto!='hide': @@ -477,9 +480,9 @@ class TurtleArtWindow(): self.timeout_tag[0] = 0 except: self.timeout_tag[0] = 0 - elif spr and spr.type == 'block': + elif spr and blk is not None: if self.timeout_tag[0] == 0: - self.timeout_tag[0] = self._do_show_popup(spr.proto.name) + self.timeout_tag[0] = self._do_show_popup(blk.name) self.spr = spr else: if self.timeout_tag[0] > 0: @@ -682,8 +685,8 @@ class TurtleArtWindow(): if self.dx != 0 or self.dy != 0: if self._sharing(): if verbose: - print "processing move: " + str(self.dx) + " " + str(self.dy) - self.activity._send_event("m:"+str(self.dx)+":"+str(self.dy)) + print "processing move: %d %d" % (self.dx, self.dy) + self.activity._send_event("m:%d:%d" % (self.dx, self.dy)) self.dx = 0 self.dy = 0 @@ -692,7 +695,8 @@ class TurtleArtWindow(): if self.draggroup == None: return spr = self.draggroup[0] - if spr.type == 'turtle': + if self.turtle_list.spr_to_turtle(spr) is not None: + print "clicked on a turtle" self.turtle.xcor = self.turtle.spr.x-self.turtle.canvas.x- \ self.turtle.canvas.width/2+30 self.turtle.ycor = self.turtle.canvas.height/2-self.turtle.spr.y+ \ @@ -701,6 +705,7 @@ class TurtleArtWindow(): display_coordinates(self) self.draggroup = None return + # remove block by dragging them onto the category palette if self.block_operation=='move' and self.category_spr.hit((x,y)): for b in self.draggroup: b.hide() self.draggroup = None @@ -715,19 +720,15 @@ class TurtleArtWindow(): if self.spr.proto.name=='number': self.selected_block = spr self.selected_block.set_shape( - self.blocks.spr_to_block( + self.block_list.spr_to_block( self.selected_block).selected_shape) - # self.select_mask.move((spr.x-5,spr.y-5)) - # self.select_mask.set_layer(MASK_LAYER) self.firstkey = True elif self.defdict.has_key(spr.proto.name): self.selected_block = spr if self.spr.proto.name=='string': self.selected_block.set_shape( - self.blocks.spr_to_block( + self.block_list.spr_to_block( self.selected_block).selected_shape) - # self.select_mask_string.move((spr.x-5,spr.y-5)) - # self.select_mask_string.set_layer(MASK_LAYER) self.firstkey = True elif self.spr.proto.name in self.importblocks: self._import_from_journal(spr) @@ -737,7 +738,7 @@ class TurtleArtWindow(): # mark block as selected self.selected_block = spr self.selected_block.set_shape( - self.blocks.spr_to_block( + self.block_list.spr_to_block( self.selected_block).selected_shape) spr.set_selected(True) self._run_stack(spr) @@ -748,14 +749,10 @@ class TurtleArtWindow(): def _click_block(self): if self.spr.proto.name=='number': self.selected_block = self.spr - self.select_mask.move((self.spr.x-5,self.spr.y-5)) - self.select_mask.set_layer(MASK_LAYER) self.firstkey = True elif self.defdict.has_key(self.spr.proto.name): self.selected_block = self.spr if self.spr.proto.name=='string': - self.select_mask_string.move((self.spr.x-5,self.spr.y-5)) - self.select_mask_string.set_layer(MASK_LAYER) self.firstkey = True elif self.spr.proto.name in self.importblocks: self._import_from_journal(self.spr) @@ -767,7 +764,7 @@ class TurtleArtWindow(): Repaint """ def _expose_cb(self, win, event): - self.sprites.redraw_sprites() + self.sprite_list.redraw_sprites() return True """ @@ -791,31 +788,37 @@ class TurtleArtWindow(): snap_to_dock """ def _snap_to_dock(self): - d=200 - me = self.draggroup[0] - for mydockn in range(len(me.proto.docks)): - for you in self._blocks(): - if you in self.draggroup: + spr = self.draggroup[0] + my_block = self.block_list.spr_to_block(spr) + d = 200 + for my_dockn in range(len(my_block.docks)): + for your_block in self.block_list.list: + # don't link to a block to which you're already connected + if your_block.spr in self.draggroup: continue - for yourdockn in range(len(you.proto.docks)): - thisxy = self._dock_dx_dy(you,yourdockn,me,mydockn) - if self._magnitude(thisxy) > d: + # check each dock of your_block for a possible connection + for your_dockn in range(len(your_block.docks)): + this_xy = self._dock_dx_dy(your_block, your_dockn, + my_block, my_dockn) + if self._magnitude(this_xy) > d: continue - d = self._magnitude(thisxy) - bestxy=thisxy - bestyou=you - bestyourdockn=yourdockn - bestmydockn=mydockn + print "found a match? %d" % (your_dockn) + d = self._magnitude(this_xy) + best_xy = this_xy + best_you = your_block + best_your_dockn = your_dockn + best_my_dockn = my_dockn + break if d<200: for b in self.draggroup: - b.move((b.x+bestxy[0],b.y+bestxy[1])) - blockindock=bestyou.connections[bestyourdockn] - if blockindock!=None: - for b in findgroup(blockindock): + b.move((b.x+best_xy[0],b.y+best_xy[1])) + block_in_dock = best_you.connections[best_your_dockn] + if block_in_dock is not None: + for b in findgroup(block_in_dock): b.hide() - bestyou.connections[bestyourdockn]=me - me.connections[bestmydockn]=bestyou - + best_you.connections[best_your_dockn] = my_block.spr + if my_block.connections is not None: + my_block.connections[best_my_dockn] = best_you.spr """ import from Journal @@ -823,7 +826,7 @@ class TurtleArtWindow(): def _import_from_journal(self, spr): if hasattr(self, "activity"): # this should be a method: _inside_sugar() chooser = ObjectChooser('Choose image', None,\ - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) + gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) try: result = chooser.run() if result == gtk.RESPONSE_ACCEPT: @@ -856,7 +859,7 @@ class TurtleArtWindow(): filter out blocks """ def _blocks(self): - return [spr for spr in self.sprites.list if spr.type == 'block'] + return [spr for spr in self.sprite_list.list if spr.type == 'block'] """ block selector pressed @@ -878,7 +881,7 @@ class TurtleArtWindow(): return True # - # Create new instance of the block + # Create new instance of a block # # load alternative image of nop block if python code is loaded @@ -887,31 +890,40 @@ class TurtleArtWindow(): # TODO: handle python-loaded case # newspr = Sprite(self,x-20,y-20,self.media_shapes['pythonloaded']) else: - # newspr = Sprite(self,x-20,y-20,proto.image) - newblk = block.Block(self.blocks,proto.name,x-20,y-20,[proto.name]) + newblk = block.Block(self.block_list, self.sprite_list, proto.name, + x-20, y-20, [proto.name]) newspr = newblk.spr newspr.set_layer(TOP_LAYER) self.dragpos = 20,20 - newspr.type = 'block' - newspr.proto = proto + newspr.type = 'block' # phasing this out + newspr.proto = proto # phasing this out if self.defdict.has_key(newspr.proto.name): - newspr.labels[0]=self.defdict[newspr.proto.name] - newspr.connections = [None]*len(proto.docks) - for i in range(len(proto.defaults)): - dock = proto.docks[i+1] + newspr.labels[0]=self.defdict[newblk.name] + newspr.connections = [None]*len(proto.docks) # phasing this out + newblk.connections = [None]*len(newblk.docks) + print "new %s" % (newblk.connections) + for i in range(len(newblk.defaults)): + dock = newblk.docks[i+1] + print dock argproto = self.protodict[self.valdict[dock[0]]] + print argproto argdock = argproto.docks[0] + print argdock nx,ny = newspr.x+dock[2]-argdock[2],newspr.y+dock[3]-argdock[3] - # argspr = Sprite(self,nx,ny,argproto.image) - argblk = block.Block(self.blocks,argproto.name,nx,ny) + argblk = block.Block(self.block_list, self.sprite_list, + argproto.name, nx, ny) argspr = argblk.spr argspr.type = 'block' argspr.proto = argproto - argspr.set_label(str(proto.defaults[i])) + argspr.set_label(str(newblk.defaults[i])) argspr.set_layer(TOP_LAYER) - argspr.connections = [newspr,None] - newspr.connections[i+1] = argspr + argspr.connections = [newspr,None] # phasing this out + argblk.connections = [newspr,None] + newspr.connections[i+1] = argspr # phasing this out + newblk.connections[i+1] = argspr + print "%s %s" % (argblk.name, argblk.connections) + print "%s %s" % (newblk.name, newblk.connections) self.draggroup = findgroup(newspr) self.block_operation = 'new' @@ -969,45 +981,46 @@ class TurtleArtWindow(): dock_dx_dy """ def _dock_dx_dy(self, block1, dock1n, block2, dock2n): - dock1 = block1.proto.docks[dock1n] - dock2 = block2.proto.docks[dock2n] - d1type,d1dir,d1x,d1y=dock1[0:4] - d2type,d2dir,d2x,d2y=dock2[0:4] + dock1 = block1.docks[dock1n] + dock2 = block2.docks[dock2n] + d1type, d1dir, d1x, d1y = dock1[0:4] + d2type, d2dir, d2x, d2y = dock2[0:4] if (d2type!='num') or (dock2n!=0): - try: - if block1.connections[dock1n] != None: + if block1.connections is not None and dock1n < block1.connections\ + and block1.connections[dock1n] is not None: return (100,100) - if block2.connections[dock2n] != None: + if block2.connections is not None and dock2n < block2.connections\ + and block2.connections[dock2n] is not None: return (100,100) - except IndexError: - print "Index Error %s %s" % (str(dock1n),str(dock2n)) - if block1==block2: return (100,100) - if d1type!=d2type: + if block1 == block2: + return (100,100) + if d1type != d2type: # some blocks can take strings or nums - if block1.proto.name in ('write', 'plus2', 'equal', 'less', 'greater', \ - 'template1', 'template2', 'template3', \ - 'template4', 'template6', 'template7', 'nop', \ - 'print', 'stack'): - if block1.proto.name == 'write' and d1type == 'string': + if block1.name in ('write', 'plus2', 'equal', 'less', 'greater', + 'template1', 'template2', 'template3', + 'template4', 'template6', 'template7', 'nop', + 'print', 'stack'): + if block1.name == 'write' and d1type == 'string': if d2type == 'num' or d2type == 'string': pass else: if d2type == 'num' or d2type == 'string': pass # some blocks can take strings, nums, or Journal - elif block1.proto.name in ('show', 'push', 'storein', 'storeinbox1', \ - 'storeinbox2'): + elif block1.name in ('show', 'push', 'storein', 'storeinbox1', + 'storeinbox2'): if d2type == 'num' or d2type == 'string' or d2type == 'journal': pass # some blocks can take media, audio, movies, of descriptions - elif block1.proto.name in ('containter'): + elif block1.name in ('containter'): if d1type == 'audiooff' or d1type == 'journal': pass else: return (100,100) - if d1dir==d2dir: + if d1dir == d2dir: return (100,100) - return (block1.x+d1x)-(block2.x+d2x),(block1.y+d1y)-(block2.y+d2y) + return ((block1.spr.x+d1x)-(block2.spr.x+d2x), + (block1.spr.y+d1y)-(block2.spr.y+d2y)) """ magnitude diff --git a/turtlex.py b/turtlex.py new file mode 100644 index 0000000..f6e160a --- /dev/null +++ b/turtlex.py @@ -0,0 +1,78 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010 Walter Bender + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +from constants import * +import sprite_factory +import sprites +from gettext import gettext as _ + +# +# A class for the list of blocks and everything they share in common +# +class Turtles: + def __init__(self): + self.list = [] + + def get_turtle(self, i): + if i < 0 or i > len(self.list)-1: + return(None) + else: + return(self.list[i]) + + def length_of_list(self): + return(len(self.list)) + + def append_to_list(self, turtle): + self.list.append(turtle) + + def remove_from_list(self, turtle): + if block in self.list: + self.list.remove(turtle) + + # + # sprite utilities + # + def spr_to_turtle(self, spr): + for b in self.list: + if spr == b.spr: + return b + return None + +# +# A class for the individual turtles +# +class Turtle: + # The turtle is not a block, just a sprite with an orientation + def __init__(self, turtle_list, sprite_list, orientation=0, scale=1.0): + self.spr = None + self.orientation = orientation + svg = sprite_factory.SVG() + svg.set_scale(scale) + svg.set_orientation(orientation) + self.spr = sprites.Sprite(sprite_list, 0, 0, + sprite_factory.svg_str_to_pixbuf(svg.turtle())) + self.type = 'turtle' + turtle_list.append_to_list(self) + print "created turtle: %s" % (str(self.spr)) + + # + # TODO: generate orientations + # -- cgit v0.9.1