Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt
diff options
context:
space:
mode:
Diffstat (limited to 'TurtleArt')
-rw-r--r--TurtleArt/taconstants.py10
-rw-r--r--TurtleArt/talogo.py15
-rw-r--r--TurtleArt/taturtle.py28
-rw-r--r--TurtleArt/tawindow.py112
4 files changed, 102 insertions, 63 deletions
diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py
index 1997d1b..e51c4d0 100644
--- a/TurtleArt/taconstants.py
+++ b/TurtleArt/taconstants.py
@@ -135,7 +135,7 @@ PALETTES = [['clean', 'forward', 'back', 'show', 'left', 'right',
['kbinput', 'push', 'printheap', 'keyboard', 'pop', 'clearheap',
'myfunc1arg', 'userdefined', 'addturtle', 'comment', 'print',
'cartesian', 'width', 'height', 'polar', 'sandwichtop_no_label',
- 'sandwichbottom', 'readpixel', 'see'],
+ 'sandwichbottom', 'readpixel', 'see', 'skin'],
['journal', 'audio', 'description', 'hideblocks', 'showblocks',
'fullscreen', 'savepix', 'savesvg', 'picturelist',
'picture1x1a', 'picture1x1', 'picture2x2', 'picture2x1',
@@ -196,7 +196,7 @@ BASIC_STYLE_1ARG = ['forward', 'back', 'left', 'right', 'seth', 'show', 'image',
'setscale', 'setpensize', 'setcolor', 'setshade', 'print', 'showaligned',
'settextsize', 'settextcolor', 'print', 'wait', 'storeinbox1', 'savepix',
'storeinbox2', 'wait', 'stack', 'push', 'nop', 'addturtle', 'comment',
- 'savesvg', 'setgray']
+ 'savesvg', 'setgray', 'skin']
BASIC_STYLE_VAR_ARG = ['userdefined', 'userdefined2args', 'userdefined3args']
BULLET_STYLE = ['templatelist', 'list']
BASIC_STYLE_2ARG = ['arc', 'setxy', 'fillscreen', 'storein', 'write']
@@ -383,6 +383,7 @@ BLOCK_NAMES = {
'show':[_('show')],
'showblocks':[_('show blocks')],
'showaligned':[_('show aligned')],
+ 'skin':[_('turtle shell')],
'sqrt':['√'],
'stack':[_('action')],
'stack1':[_('action 1')],
@@ -526,6 +527,7 @@ PRIMITIVES = {
'show':'show',
'showblocks':'showblocks',
'showaligned':'showaligned',
+ 'skin':'skin',
'sqrt':'sqrt',
'stack':'stack',
'stack1':'stack1',
@@ -609,6 +611,7 @@ DEFAULTS = {
'setxy':[0, 0],
'show':[_('text')],
'showaligned':[_('text')],
+ 'skin':[None],
'stack':[_('action')],
'storeinbox1':[100],
'storeinbox2':[100],
@@ -638,7 +641,7 @@ STRING_OR_NUMBER_ARGS = ['plus2', 'equal2', 'less2', 'greater2', 'box',
'userdefined2args', 'userdefined3args', 'storein']
CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1',
- 'storeinbox2']
+ 'storeinbox2', 'skin']
#
# Status blocks
@@ -838,6 +841,7 @@ HELP_STRINGS = {
'shade':_("holds current pen shade"),
'show':_("draws text or show media from the Journal"),
'showblocks':_("restores hidden blocks"),
+ 'skin':_("put a shell on the turtle"),
'sqrt':_("calculates square root"),
'stack1':_("invokes Action 1 stack"),
'stack2':_("invokes Action 2 stack"),
diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py
index d485d22..a9b13dc 100644
--- a/TurtleArt/talogo.py
+++ b/TurtleArt/talogo.py
@@ -348,6 +348,7 @@ class LogoCode:
'show':[1, lambda self, x: self.show(x, True)],
'showaligned':[1,lambda self, x: self.show(x, False)],
'showblocks':[0, lambda self: self.tw.showblocks()],
+ 'skin':[1, lambda self, x: self.reskin(x)],
'sound':[1, lambda self, x: self.play_sound(x)],
'sqrt':[1, lambda self, x: tasqrt(x)],
'stack1':[0, self.prim_stack1, True],
@@ -1071,6 +1072,14 @@ class LogoCode:
""" Set scale used by media object display """
self.scale = x
+ def reskin(self, media):
+ """ Reskin the turtle with an image from a file """
+ w = int(self.scale)
+ h = int(self.scale)
+ pixbuf = self.show_picture(media, 0, 0, w, h, False)
+ if pixbuf is not None:
+ self.tw.active_turtle.set_shapes([pixbuf])
+
def show(self, string, center=False):
""" Show is the general-purpose media-rendering block. """
# convert from Turtle coordinates to screen coordinates
@@ -1138,7 +1147,7 @@ class LogoCode:
else:
play_audio(self, audio[6:])
- def show_picture(self, media, x, y, w, h):
+ def show_picture(self, media, x, y, w, h, show=True):
""" Image file from Journal """
if media == "" or media[6:] == "":
pass
@@ -1179,10 +1188,12 @@ class LogoCode:
self.filepath = None
self.tw.showlabel('nofile', media[6:])
print "Couldn't open media object %s" % (media[6:])
- if pixbuf is not None:
+ if pixbuf is not None and show:
self.tw.canvas.draw_pixbuf(pixbuf, 0, 0, int(x), int(y),
int(w), int(h),
self.filepath)
+ else:
+ return pixbuf
def show_description(self, media, x, y, w, h):
""" Description field from Journal """
diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py
index 5272cd6..91e7dfc 100644
--- a/TurtleArt/taturtle.py
+++ b/TurtleArt/taturtle.py
@@ -24,12 +24,19 @@ from tasprite_factory import SVG, svg_str_to_pixbuf
from tacanvas import wrap100, color_table
from sprites import Sprite
+import logging
+_logger = logging.getLogger('turtleart-activity')
+
+
+SHAPES = 36
+
+
def generate_turtle_pixbufs(colors):
""" Generate pixbufs for generic turtles """
shapes = []
svg = SVG()
svg.set_scale(1.0)
- for i in range(36):
+ for i in range(SHAPES):
svg.set_orientation(i*10)
shapes.append(svg_str_to_pixbuf(svg.turtle(colors)))
return shapes
@@ -143,10 +150,25 @@ class Turtle:
self.spr = None
turtles.add_to_dict(key, self)
+ def set_shapes(self, shapes):
+ """ Reskin the turtle """
+ n = len(shapes)
+ if n == SHAPES:
+ self.shapes = shapes[:]
+ else:
+ if n != 1:
+ _logger.debug("%d images passed to set_shapes: ignoring" % (n))
+ images = [shapes[0]]
+ for i in range(3):
+ images.append(images[i].rotate_simple(90))
+ for i in range(SHAPES):
+ j = (i + 4) % SHAPES
+ self.shapes[j] = images[int(j/9) % 4]
+
def set_heading(self, heading):
- """ Set the turtle heading (and shape: one per 10 degrees) """
+ """ Set the turtle heading (one shape per 360/SHAPES degrees) """
self.heading = heading
- i = (int(self.heading+5)%360)/10
+ i = (int(self.heading+5)%360)/(360 / SHAPES)
if not self.hidden and self.spr is not None:
try:
self.spr.set_shape(self.shapes[i])
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index c97785a..aee66cf 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -1417,6 +1417,11 @@ class TurtleArtWindow():
gblk.spr.move_relative((0, dy * blk.scale))
grow_stack_arm(find_sandwich_top(blk))
elif blk.name in EXPANDABLE_BLOCKS:
+ # Connection may be lost during expansion, so store it...
+ blk0 = blk.connections[0]
+ if blk0 is not None:
+ dock0 = blk0.connections.index(blk)
+
if hide_button_hit(blk.spr, x, y):
dy = blk.reset_y()
elif show_button_hit(blk.spr, x, y):
@@ -1427,7 +1432,12 @@ class TurtleArtWindow():
return
self._expand_expandable(blk, blk.connections[1], dy)
- self._cascade_expandable(blk, flag=True)
+ # and restore it...
+ if blk0 is not None:
+ blk.connections[0] = blk0
+ blk0.connections[dock0] = blk
+ self._cascade_expandable(blk)
+
grow_stack_arm(find_sandwich_top(blk))
elif blk.name in EXPANDABLE_ARGS or blk.name == 'nop':
@@ -1505,22 +1515,15 @@ class TurtleArtWindow():
for gblk in find_group(blk):
gblk.spr.move_relative((0, -dy * blk.scale))
- def _cascade_expandable(self, blk, flag=False):
+ def _cascade_expandable(self, blk):
""" If expanding/shrinking a block, cascade. """
- if flag:
- print "cascading", blk.name
while blk.name in NUMBER_STYLE or \
blk.name in NUMBER_STYLE_PORCH or \
- blk.name in NUMBER_STYLE_BLOCK or \
- (flag and blk.name in COMPARE_STYLE):
+ blk.name in NUMBER_STYLE_BLOCK:
if blk.connections[0] is None:
- if flag:
- print "connections[0] is None"
break
if blk.connections[0].name in EXPANDABLE_BLOCKS:
blk = blk.connections[0]
- if flag:
- print "expanding", blk.name
dy = 20 + blk.connections[1].ey - blk.ey
blk.expand_in_y(dy)
if dy != 0:
@@ -1529,13 +1532,9 @@ class TurtleArtWindow():
for gblk in find_group(blk):
if gblk not in group:
gblk.spr.move_relative((0, dy * blk.scale))
- if flag:
- print "moving", gblk.name, dy
if blk.name in COMPARE_STYLE:
for gblk in find_group(blk):
gblk.spr.move_relative((0, -dy * blk.scale))
- if flag:
- print "moving", gblk.name, -dy
def _check_collapsibles(self, blk):
""" Check the state of collapsible blocks upon change in dock state. """
@@ -1576,12 +1575,13 @@ class TurtleArtWindow():
pass
def _snap_to_dock(self):
- """ Snap a block (dragged_block) to the dock of another block
+ """ Snap a block (selected_block) to the dock of another block
(destination_block).
"""
- dragged_block = self.drag_group[0]
+ selected_block = self.drag_group[0]
+ best_destination = None
d = 200
- for dragged_block_dockn in range(len(dragged_block.docks)):
+ for selected_block_dockn in range(len(selected_block.docks)):
for destination_block in self.just_blocks():
# Don't link to a block to which you're already connected
if destination_block in self.drag_group:
@@ -1589,17 +1589,17 @@ class TurtleArtWindow():
# Check each dock of destination for a possible connection
for destination_dockn in range(len(destination_block.docks)):
this_xy = dock_dx_dy(destination_block, destination_dockn,
- dragged_block, dragged_block_dockn)
+ selected_block, selected_block_dockn)
if magnitude(this_xy) > d:
continue
d = magnitude(this_xy)
best_xy = this_xy
best_destination = destination_block
best_destination_dockn = destination_dockn
- best_dragged_block_dockn = dragged_block_dockn
+ best_selected_block_dockn = selected_block_dockn
if d < 200:
- if not arithmetic_check(dragged_block, best_destination,
- best_dragged_block_dockn,
+ if not arithmetic_check(selected_block, best_destination,
+ best_selected_block_dockn,
best_destination_dockn):
return
for blk in self.drag_group:
@@ -1612,31 +1612,58 @@ class TurtleArtWindow():
blk_in_dock.connections[0] = None
self._put_in_trash(blk_in_dock)
- best_destination.connections[best_destination_dockn] = dragged_block
- if dragged_block.connections is not None:
- dragged_block.connections[best_dragged_block_dockn] = \
+ best_destination.connections[best_destination_dockn] = \
+ selected_block
+ if selected_block.connections is not None:
+ selected_block.connections[best_selected_block_dockn] = \
best_destination
if best_destination.name in BOOLEAN_STYLE:
if best_destination_dockn == 2 and \
- dragged_block.name in COMPARE_STYLE:
- dy = dragged_block.ey - best_destination.ey
+ selected_block.name in COMPARE_STYLE:
+ dy = selected_block.ey - best_destination.ey
best_destination.expand_in_y(dy)
- self._expand_boolean(best_destination, dragged_block, dy)
+ self._expand_boolean(best_destination, selected_block, dy)
elif best_destination.name in EXPANDABLE_BLOCKS and \
best_destination_dockn == 1:
dy = 0
- if dragged_block.name in EXPANDABLE_BLOCKS:
- dy = 20 + dragged_block.ey - best_destination.ey
+ if selected_block.name in EXPANDABLE_BLOCKS:
+ dy = 20 + selected_block.ey - best_destination.ey
best_destination.expand_in_y(dy)
else:
if best_destination.ey > 0:
dy = best_destination.reset_y()
if dy != 0:
- self._expand_expandable(best_destination, dragged_block, dy)
+ self._expand_expandable(best_destination, selected_block,
+ dy)
self._cascade_expandable(best_destination)
grow_stack_arm(find_sandwich_top(best_destination))
+ def _disconnect(self, blk):
+ """ Disconnect block from stack above it. """
+ if blk.connections[0] == None:
+ return
+ if collapsed(blk):
+ return
+ blk2 = blk.connections[0]
+ c = blk2.connections.index(blk)
+ blk2.connections[c] = None
+
+ if blk2.name in BOOLEAN_STYLE:
+ if c == 2 and blk2.ey > 0:
+ dy = -blk2.ey
+ blk2.expand_in_y(dy)
+ self._expand_boolean(blk2, blk, dy)
+ elif blk2.name in EXPANDABLE_BLOCKS and c == 1:
+ if blk2.ey > 0:
+ dy = blk2.reset_y()
+ if dy != 0:
+ self._expand_expandable(blk2, blk, dy)
+ self._cascade_expandable(blk2)
+ grow_stack_arm(find_sandwich_top(blk2))
+
+ blk.connections[0] = None
+
def _import_from_journal(self, blk):
""" Import a file from the Sugar Journal """
if self.running_sugar:
@@ -1709,31 +1736,6 @@ class TurtleArtWindow():
blk.set_image(pixbuf, x, y)
self._resize_skin(blk)
- def _disconnect(self, blk):
- """ Disconnect block from stack above it. """
- if blk.connections[0] == None:
- return
- if collapsed(blk):
- return
- blk2 = blk.connections[0]
- c = blk2.connections.index(blk)
- blk2.connections[c] = None
-
- if blk2.name in BOOLEAN_STYLE:
- if c == 2 and blk2.ey > 0:
- dy = -blk2.ey
- blk2.expand_in_y(dy)
- self._expand_boolean(blk2, blk, dy)
- elif blk2.name in EXPANDABLE_BLOCKS and c == 1:
- if blk2.ey > 0:
- dy = blk2.reset_y()
- if dy != 0:
- self._expand_expandable(blk2, blk, dy)
- self._cascade_expandable(blk2)
- grow_stack_arm(find_sandwich_top(blk2))
-
- blk.connections[0] = None
-
def _keypress_cb(self, area, event):
""" Keyboard """
keyname = gtk.gdk.keyval_name(event.keyval)