Merge branch 'master' of github.com:skykooler/Lightningbeam

This commit is contained in:
Skyler Lehmkuhl 2013-08-06 11:43:22 -04:00
commit 605d1a4c46
12 changed files with 625 additions and 109 deletions

View File

@ -42,7 +42,8 @@ class Canvas(Properties):
self.textcolor = c
def rmoveto(self, dx, dy):
x0, y0 = self._current_point()
x0, y0 = self._current_point
# x0, y0 = self._current_point()
self.moveto(x0 + dx, y0 + dy)
def rlineto(self, dx, dy):

View File

@ -171,10 +171,9 @@ class Canvas(GCanvas, GCanvasPaths):
#ctx.set_source_rgba(*self._state.fillcolor._rgba)
if self.fillcolor.image:
# surface =
ctx.set_source_pixbuf(self.fillcolor.image, 0, 0)
ctx.save()
print (self.maxx-self.minx)*1.0/self.fillcolor.image.get_width()
self._gtk_ctx.scale((self.maxx-self.minx)*1.0/self.fillcolor.image.get_width(), 1)
ctx.scale((self.maxx-self.minx)*1.0/self.fillcolor.image.get_width(), (self.maxy-self.miny)*1.0/self.fillcolor.image.get_height())
ctx.set_source_pixbuf(self.fillcolor.image, 0, 0)
ctx.fill_preserve()
ctx.restore()
else:

View File

@ -5,6 +5,7 @@
#--------------------------------------------------------------------
from math import sin, cos, pi
import sys
import win32con as wc, win32ui as ui, win32gui as gui
from win32con import PS_SOLID, BS_SOLID, RGN_AND
#from win32ui import CreatePen, CreateBrush
@ -119,6 +120,10 @@ class Canvas(GCanvas):
def set_fillcolor(self, c):
state = self._state
state.fillcolor = c
if self.fillcolor.image:
tb = gdip.TextureBrush(self.fillcolor.image)
state.win_fill_brush = tb
else:
state.win_fill_brush = gdip.SolidBrush(c._win_argb)
def get_textcolor(self):
@ -156,19 +161,41 @@ class Canvas(GCanvas):
def newpath(self):
self._win_path.Reset()
self.minx = sys.maxint
self.miny = sys.maxint
self.maxx = -sys.maxint/2
self.maxy = -sys.maxint/2
def moveto(self, x, y):
p = (x, y)
try:
self.minx = min(self.minx, x)
self.miny = min(self.miny, y)
self.maxx = max(self.maxx, x)
self.maxy = max(self.maxy, y)
except AttributeError:
self.minx = x
self.miny = y
self.maxx = x
self.maxy = y
self._current_point = p
self._win_path.StartFigure()
def lineto(self, x, y):
x0, y0 = self._current_point
self.minx = min(self.minx, x)
self.miny = min(self.miny, y)
self.maxx = max(self.maxx, x)
self.maxy = max(self.maxy, y)
self._win_path.AddLine_4f(x0, y0, x, y)
self._current_point = (x, y)
def curveto(self, p1, p2, p3):
p0 = self._current_point
self.minx = min(self.minx, p1[0], p2[0], p3[0])
self.miny = min(self.miny, p1[1], p2[1], p3[1])
self.maxx = max(self.maxx, p1[0], p2[0], p3[0])
self.maxy = max(self.maxy, p1[1], p2[1], p3[1])
self._win_path.AddBezier_4p(p0, p1, p2, p3)
self._current_point = p3
@ -182,6 +209,12 @@ class Canvas(GCanvas):
self._current_point = None
def fill(self):
if self.fillcolor.image:
self.gsave()
self._win_graphics.Scale_2f((self.maxx-self.minx)*1.0/self.fillcolor.image.GetWidth(), (self.maxy-self.miny)*1.0/self.fillcolor.image.GetHeight())
self._win_graphics.FillPath(self._state.win_fill_brush, self._win_path)
self.grestore()
else:
self._win_graphics.FillPath(self._state.win_fill_brush, self._win_path)
def stroke(self):

View File

@ -7,8 +7,12 @@
import win32con as wc, win32api as api
from GUI import Color
def rgb(red, green, blue, alpha = 1.0):
def rgb(red, green, blue, alpha = 1.0, image = False, im = ''):
color = Color()
color.image = image
if image:
color.image = im._win_image
else:
color._red = red
color._green = green
color._blue = blue

View File

@ -159,6 +159,21 @@ class SolidBrush(object):
#--------------------------------------------------------------------
class TextureBrush(object):
def __init__(self, image):
ptr = c_void_p()
wg.GdipCreateTexture(image.ptr, 4, byref(ptr))
self.ptr = ptr
def __del__(self, wg = wg):
wg.GdipDeleteBrush(self.ptr)
def __str__(self):
return "<TextureBrush>"
#--------------------------------------------------------------------
class Font(object):
def __init__(self, family, size, style):

View File

@ -1,10 +1,10 @@
Building on Windows:
1. In a CMD window, type:
1. Uncomment the line at the beginning of lightningbeam.py that says "Uncomment to build on Windows"
2. In a CMD window, type:
c:\Python27\python.exe setup.py py2exe
2. Copy the GUI folder from the root directory into dist\.
3. The executable is in dist\lightningbeam.exe. You probably do need most of the DLL's, I haven't
4. The executable is in dist\lightningbeam.exe. You probably do need most of the DLL's, I haven't
gone through them yet.
Building on Ubuntu/Debian:

View File

@ -83,12 +83,13 @@ class PyGUIFormatter(Formatter):
class CodeEditor(ScrollableView):
def __init__(self):
ScrollableView.__init__(self)
self.text = "var a = {b:5, c:[3, 'df \\'']};\n_xscale\nif (this.hitTest(_root._xmouse, root._ymouse, false)) {\n\n\ttrace('hi');\n}"
self.text = "_root.onMouseDown = function () {\n\ttrace('Hi');\n};"
self.font = Font('Courier', 16)
self.selecting = False
self.lexer = ActionScriptLexer()
self.cursorpos = 0
self.scursorpos = 0
self.selection = (0,0)
self.formatter = PyGUIFormatter()
# self.filter = NameHighlightFilter(
self.filter = EverythingHighlightFilter(
@ -169,6 +170,7 @@ class CodeEditor(ScrollableView):
except:
pass
self.scursorpos = self.cursorpos
self.selection = (self.cursorpos, self.cursorpos)
if int(y/self.font.height):
self.cursorpos+=1
self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
@ -183,6 +185,7 @@ class CodeEditor(ScrollableView):
pass
if int(y/self.font.height):
self.cursorpos+=1
self.selection = (min(self.cursorpos, self.scursorpos), max(self.cursorpos, self.scursorpos))
self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
def key_down(self, event):
keydict = {127:"backspace",63272:"delete",63232:"up_arrow",63233:"down_arrow",
@ -241,6 +244,8 @@ class CodeEditor(ScrollableView):
else:
self.text=self.text[:self.cursorpos]+str(key)+self.text[self.cursorpos:]
self.cursorpos += 1
self.scursorpos = self.cursorpos
self.selection = (self.cursorpos, self.cursorpos)
self.invalidate_rect([0,0,self.extent[0],self.extent[1]])
class test(Application):
def __init__(self):

View File

@ -15,7 +15,7 @@ os.putenv("UBUNTU_MENUPROXY", "0")
#import objc, AppKit, cPickle
#Uncomment to build on Windows
#import ctypes, ctypes.wintypes, win32print
# import ctypes, ctypes.wintypes, win32print
#SVLGUI - my custom GUI wrapper to abstract the GUI
import svlgui
@ -49,6 +49,8 @@ global undo_stack
global redo_stack
undo_stack = []
redo_stack = []
global preferences
preferences={}
def clear(arr):
arr.__delslice__(0,len(arr))
@ -108,6 +110,7 @@ def onMouseDownGroup(self, x, y,button=1,clicks=1):
if svlgui.MODE in [" ", "s"]:
if self.hitTest(x, y):
self.clicked = True
elif svlgui.MODE in ["r", "e", "p"]:
if svlgui.MODE=="r":
# 'c' stands for 'current'
@ -115,7 +118,19 @@ def onMouseDownGroup(self, x, y,button=1,clicks=1):
elif svlgui.MODE=="e":
self.cshape = ellipse(x, y, 0, 0)
elif svlgui.MODE=="p":
self.cshape = shape(x, y)
# self.cshape = shape(x, y)
self.cshape = svlgui.Line(svlgui.Point(x, y),svlgui.Point(x,y))
for i in self.lines:
if abs(self.cshape.endpoint1.x-i.endpoint1.x)<10 and abs(self.cshape.endpoint1.y-i.endpoint1.y)<10:
self.cshape.connection1 = i.endpoint1
self.cshape.connection1.lines.add(self.cshape)
break
elif abs(self.cshape.endpoint1.x-i.endpoint2.x)<10 and abs(self.cshape.endpoint1.y-i.endpoint2.y)<10:
self.cshape.connection1 = i.endpoint2
self.cshape.connection1.lines.add(self.cshape)
break
self.lines.append(self.cshape)
return
#self.cshape.rotation = 5
self.cshape.initx,self.cshape.inity = x, y
self.add(self.cshape)
@ -182,9 +197,18 @@ def onMouseUpGroup(self, x, y,button=1,clicks=1):
undo_stack[-1] = undo_stack[-1].complete({"obj":cobj, "frame":self.activelayer.currentframe, "layer":self.activelayer})
clear(redo_stack)
elif svlgui.MODE=="p":
print len(self.cshape.shapedata)
'''print len(self.cshape.shapedata)
self.cshape.shapedata = misc_funcs.simplify_shape(self.cshape.shapedata, svlgui.PMODE.split()[-1],1)
print len(self.cshape.shapedata)
print len(self.cshape.shapedata)'''
for i in self.lines:
if abs(self.cshape.endpoint2.x-i.endpoint1.x)<10 and abs(self.cshape.endpoint2.y-i.endpoint1.y)<10:
self.cshape.connection2 = i.endpoint1
self.cshape.connection2.lines.add(self.cshape)
break
elif abs(self.cshape.endpoint2.x-i.endpoint2.x)<10 and abs(self.cshape.endpoint2.y-i.endpoint2.y)<10:
self.cshape.connection2 = i.endpoint2
self.cshape.connection2.lines.add(self.cshape)
break
self.cshape = None
MainWindow.stage.draw()
def onMouseUpObj(self, x, y,button=1,clicks=1):
@ -243,7 +267,9 @@ def onMouseDragGroup(self, x, y,button=1,clicks=1):
y=y-self.cshape.inity
self.cshape.shapedata = [["M",x/2,0],["C",4*x/5,0,x,y/5,x,y/2],["C",x,4*y/5,4*x/5,y,x/2,y],["C",x/5,y,0,4*y/5,0,y/2],["C",0,y/5,x/5,0,x/2,0]]
elif svlgui.MODE == "p":
self.cshape.shapedata.append(["L",x-self.cshape.initx,y-self.cshape.inity])
# self.cshape.shapedata.append(["L",x-self.cshape.initx,y-self.cshape.inity])
self.cshape.endpoint2.x = x
self.cshape.endpoint2.y = y
def onMouseDragObj(self, x, y,button=1,clicks=1):
if svlgui.MODE==" ":
self.x = x-self.initx
@ -324,15 +350,19 @@ fps="+str(svlgui.FRAMERATE)+"\n"+"".join([i.print_sc() for i in svlgui.Library])
def run_file(self=None):
global root
print "RUNNING"
print svlgui.FILE.name
root.descendItem().activelayer.frames[root.descendItem().activelayer.currentframe].actions = MainWindow.scriptwindow.text
open(os.getenv('HOME')+"/test.sc", "w").write(create_sc(root))
# open(os.getenv('HOME')+"/test.sc", "w").write(create_sc(root))
open(svlgui.FILE.name+".sc", "w").write(create_sc(root))
# svlgui.execute("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
# x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
x = os.system("swfc"+svlgui.sep+"swfc_"+svlgui.PLATFORM+" "+svlgui.FILE.name+".sc -o "+svlgui.FILE.name+".swf")
if sys.version_info < (2, 6):
if x==5: # which is the error value returned when linking libjpeg fails
if svlgui.alert("You appear to be missing libjpeg. Install it?", confirm=True):
os.system("""osascript -e 'do shell script "mkdir -p /usr/local/lib; cp swfc/libjpeg.8.dylib /usr/local/lib" with administrator privileges'""")
x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
# x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+svlgui.FILE.name+".sc -o "+svlgui.FILE.name+".swf")
if x==5:
svlgui.alert("Sorry, something has gone terribly wrong.")
else:
@ -340,14 +370,42 @@ def run_file(self=None):
#TODO: Make this cross-platform compatible
if svlgui.PLATFORM=="win32":
# Untested.
logloc = os.getenv('HOME')+"\\AppData\\Roaming\\Macromedia\\Flash Player\\Logs\\flashlog.txt"
logloc = os.path.expanduser("~")+"\\AppData\\Roaming\\Macromedia\\Flash Player\\Logs\\flashlog.txt"
if not os.path.exists(os.path.expanduser("~")+"\\flashplayerdebugger.exe"):
result = svlgui.alert("You do not have a Flash debugger installed. Install one?", confirm=True)
if not result:
svlgui.alert("Aborting.")
return
else:
svlgui.alert("The Flash Debugger will download when you click Ok.\nThis may take some time.")
urllib.urlretrieve("http://download.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.exe", os.path.expanduser("~")+"\\flashplayerdebugger.exe")
if not os.path.exists(os.path.expanduser('~')+'\\mm.cfg'):
with open(os.path.expanduser('~')+"/mm.cfg", "w") as mm:
mm.write("ErrorReportingEnable=1\nTraceOutputFileEnable=1")
elif "linux" in svlgui.PLATFORM:
logloc = os.getenv('HOME')+"/.macromedia/Flash_Player/Logs/flashlog.txt"
if not os.path.exists('/usr/bin/flashplayerdebugger'):
if os.system('which gnash')==0:
if not 'use_gnash' in preferences:
if svlgui.alert("You have GNASH installed. Do you wish to use it instead of Adobe's flash player?", confirm=True):
use_gnash = True
return
else:
result = svlgui.alert("You do not have a Flash debugger installed. Install one?", confirm=True)
if not result:
svlgui.alert("Aborting.")
return
else:
svlgui.alert("The Flash Debugger will download when you click Ok.\nThis may take some time.")
if not "PPC" in svlgui.PLATFORM:
urllib.urlretrieve("http://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz", "fp.tar.gz")
os.system("tar -zxf fp.tar.gz")
os.system("gksudo mv flashplayerdebugger /usr/bin/")
if not os.path.exists(os.getenv('HOME')+"/mm.cfg"):
# By default, the Flash debugger on Linux does not log traces.
# So, we create a configuration file to tell it to do so if the user hasn't already.
with open(os.getenv('HOME')+"/mm.cfg", "w") as mm:
mm.write("ErrorReportingEnable=1\nTraceOutputFileEnable=1")
logloc = os.getenv('HOME')+"/.macromedia/Flash_Player/Logs/flashlog.txt"
elif svlgui.PLATFORM=="osx":
logloc = os.getenv('HOME')+"/Library/Preferences/Macromedia/Flash Player/Logs/flashlog.txt"
if not os.path.exists('/Applications/Flash Player Debugger.app'):
@ -399,21 +457,31 @@ def run_file(self=None):
outputtext.scroll_bottom() # this doesn't work
except:
pass
return True
if hasattr(svlgui, 'gobject'):
svlgui.gobject.timeout_add(20, updatetrace, outputtext)
else:
r = misc_funcs.RepeatTimer(0.02, updatetrace, args=[outputtext])
print dir(outputwin.window)
r.daemon = True
r.start()
if svlgui.PLATFORM=="osx":
osx_flash_player_loc = "/Applications/Flash\ Player\ Debugger.app"
success = svlgui.execute("open -a "+osx_flash_player_loc+" "+os.getenv('HOME')+"/test.swf")
# success = svlgui.execute("open -a "+osx_flash_player_loc+" "+os.getenv('HOME')+"/test.swf")
success = svlgui.execute("open -a "+osx_flash_player_loc+" "+svlgui.FILE.name+".swf")
if not success:
svlgui.alert("Oops! Didn't work. I probably couldn't find your Flash debugger!")
elif svlgui.PLATFORM=='win32':
win_flash_player_loc = ""
svlgui.execute('start '+win_flash_player_loc+" test.swf")
win_flash_player_loc = os.path.expanduser("~")+"\\flashplayerdebugger.exe"
# svlgui.execute('start '+win_flash_player_loc+" test.swf")
svlgui.execute('start '+win_flash_player_loc+" "+svlgui.FILE.name+".swf")
elif svlgui.PLATFORM.startswith('linux'):
linux_flash_player_loc = ""
svlgui.execute("xdg-open "+linux_flash_player_loc+" "+os.getenv('HOME')+"/test.swf")
linux_flash_player_loc = "/usr/bin/flashplayerdebugger"
# if not svlgui.execute(linux_flash_player_loc+" "+os.getenv('HOME')+"/test.swf &"):
if not svlgui.execute(linux_flash_player_loc+" "+svlgui.FILE.name+".swf &"):
if '64' in svlgui.PLATFORM:
svlgui.alert("Flash debugger failed to launch! Try installing ia32-libs.")
elif '32' in svlgui.PLATFORM:
svlgui.alert("Flash debugger failed to launch! No idea why.")
def create_html5(root):
retval = "<head>\n\
<style type=\"text/css\">\n\
@ -539,7 +607,11 @@ def open_file(widget=None):
global root
MainWindow.stage.delete(root)
shutil.rmtree(svlgui.SECURETEMPDIR)
try:
thetarfile = tarfile.open(fileobj=svlgui.file_dialog("open").open("rb"),mode="r:gz")
except AttributeError:
# User cancelled
return
basefile = thetarfile.extractfile("basefile")
root, svlgui.Library = pickle.load(basefile)
svlgui.SECURETEMPDIR = tempfile.mkdtemp()
@ -566,8 +638,11 @@ def save_file(widget=None):
tarinfo = tarfile.TarInfo('basefile')
tarinfo.size = len(data)
if svlgui.FILE.name.startswith(svlgui.TEMPDIR):
try:
thetarfile = tarfile.open(fileobj=svlgui.file_dialog("save", name="untitled.beam").open('wb'),mode="w:gz")
print thetarfile.name
except AttributeError:
# User cancelled
return
else:
thetarfile = tarfile.open(svlgui.FILE.name,mode="w:gz")
thetarfile.addfile(tarinfo, StringIO.StringIO(data))
@ -607,7 +682,11 @@ def save_file_as(widget=None):
data = pickle.dumps((root,svlgui.Library))
tarinfo = tarfile.TarInfo('basefile')
tarinfo.size = len(data)
try:
thetarfile = tarfile.open(fileobj=svlgui.file_dialog("save", name="untitled.beam").open('wb'),mode="w:gz")
except AttributeError:
# User cancelled
return
thetarfile.addfile(tarinfo, StringIO.StringIO(data))
#Save the path so we can come back here
lastpath = os.path.abspath(".")
@ -629,7 +708,11 @@ def save_file_as(widget=None):
svlgui.FILE = thetarfile
pass
def import_to_stage(widget=None):
thefile = svlgui.file_dialog("open",None,["jpg","png","bmp","wav"]).path
try:
thefile = svlgui.file_dialog("open",None,["jpg","png","bmp","wav","mp3","ogg"]).path
except AttributeError:
# User cancelled
return
for i in ("jpg","png","bmp"):
if thefile.endswith(i):
# im = svlgui.Image(thefile)
@ -638,9 +721,17 @@ def import_to_stage(widget=None):
os.system("sips -s format png "+thefile+" --out "+svlgui.SECURETEMPDIR+"/"+".".join(thefile.split("/")[-1].split(".")[:-1])+".png")
elif "linux" in svlgui.PLATFORM:
os.system("convert "+thefile+" "+svlgui.SECURETEMPDIR+"/"+".".join(thefile.split("/")[-1].split(".")[:-1])+".png")
thefile = svlgui.SECURETEMPDIR+"/"+".".join(thefile.split("/")[-1].split(".")[:-1])+".png"
elif svlgui.PLATFORM=="win32":
from PIL import Image
im = Image.open(thefile)
# Use alpha channel if available (e.g. GIF)
transparency = im.info["transparency"] if 'transparency' in im.info else None
if transparency:
im.save(svlgui.SECURETEMPDIR+"\\"+".".join(thefile.split("\\")[-1].split(".")[:-1])+".png", transparency=transparency)
else:
im.save(svlgui.SECURETEMPDIR+"\\"+".".join(thefile.split("\\")[-1].split(".")[:-1])+".png")
thefile = svlgui.SECURETEMPDIR+svlgui.sep+".".join(thefile.split(svlgui.sep)[-1].split(".")[:-1])+".png"
im = box(100,100,200,200,svlgui.Color(thefile))
print im.filled
im.onMouseDown = onMouseDownObj
im.onMouseMove = onMouseMoveObj
im.onMouseDrag = onMouseDragObj
@ -649,7 +740,31 @@ def import_to_stage(widget=None):
root.descendItem().add(im)
break
else:
if thefile.endswith("wav"):
for i in ("wav", "mp3", "ogg"):
if thefile.endswith(i):
if i in ("mp3", "ogg"):
if svlgui.PLATFORM=="win32":
if os.system("C:\\Progra~2\\MPlayer\\mplayer.exe")!=0:
if os.system("C:\\Progra~1\\MPlayer\\mplayer.exe")!=0:
result = svlgui.alert("To import mp3 and ogg files you must install mplayer. This will take about 3 MB of space. Install?", confirm=True)
if not result:
return
urllib.urlretrieve("http://mplayer.kenkon.net/files/mplayer-win32-mingw-dev-svn20061001.exe", "mplayerdl.exe")
os.system("mplayerdl.exe")
mpath = "C:\\Progra~2\\MPlayer\\mplayer.exe"
else:
mpath = "C:\\Progra~1\\MPlayer\\mplayer.exe"
else:
mpath = "C:\\Progra~2\\MPlayer\\mplayer.exe"
else:
mpath = "mplayer"
theorigfile = thefile
thefile = svlgui.SECURETEMPDIR+svlgui.sep+thefile.split(svlgui.sep)[-1].replace(" ","_").replace("-","_").split(".")[0]+'.wav'
print mpath+' -srate 48000 -vo null -vc null -ao pcm:fast:file="'+thefile+'" "'+theorigfile+'"'
if svlgui.PLATFORM=="win32":
os.system(mpath+' -srate 48000 -vo null -vc null -ao pcm:fast:file=\\"'+thefile+'\\" "'+theorigfile+'"')
else:
os.system(mpath+' -srate 48000 -vo null -vc null -ao pcm:fast:file="'+thefile+'" "'+theorigfile+'"')
if svlgui.PLATFORM=="osx":
if not os.path.exists('sox/sox'):
try:
@ -679,6 +794,18 @@ def import_to_stage(widget=None):
os.system("""osascript -e 'do shell script "easy_install numpy" with administrator privileges'""")
import numpy as NP
SOX_EXEC = 'sox/sox'
elif svlgui.PLATFORM=="win32":
SOX_EXEC = "C:\\Progra~2\\sox-14~1\\sox.exe"
if not os.path.exists(SOX_EXEC):
if os.path.exists("C:\\Progra~1\\sox-14~1\\sox.exe"):
SOX_EXEC = "C:\\Progra~1\\sox-14~1\\sox.exe"
else:
urllib.urlretrieve("http://downloads.sourceforge.net/project/sox/sox/14.4.0/sox-14.4.0-win32.exe?r=&ts=1358725954&use_mirror=iweb", 'sox.exe')
os.system("sox.exe")
import numpy as NP
elif "linux" in svlgui.PLATFORM:
import numpy as NP
SOX_EXEC = "sox"
svlgui.NP = NP
num_channels = 1
out_byps = 2 # Bytes per sample you want, must be 1, 2, 4, or 8
@ -692,8 +819,12 @@ def import_to_stage(widget=None):
data = NP.fromstring(subprocess.check_output(cmd),'<i%d'%(out_byps))
data = data.reshape(len(data)/num_channels, num_channels)
info = subprocess.check_output([SOX_EXEC,'--i',thefile])
sound = svlgui.Sound(data, name=thefile.split('/')[-1], path=thefile, info=info)
if i=="mp3":
sound = svlgui.Sound(data, name=thefile.split(svlgui.sep)[-1], path=theorigfile, info=info, type=i)
else:
sound = svlgui.Sound(data, name=thefile.split(svlgui.sep)[-1], path=thefile, info=info, type=i)
root.descendItem().add(sound)
break
MainWindow.stage.draw()
def import_to_library(widget=None):
@ -754,6 +885,39 @@ def redo(widget=None):
undo_stack.append(e)
MainWindow.stage.draw()
def cut(widget=None):
if MainWindow.scriptwindow.is_focused():
clip = MainWindow.scriptwindow.text[MainWindow.scriptwindow.selection[0]:MainWindow.scriptwindow.selection[1]]
MainWindow.scriptwindow.insert("")
svlgui.app.set_clipboard(clip)
def copy(widget=None):
if MainWindow.scriptwindow.is_focused():
clip = MainWindow.scriptwindow.text[MainWindow.scriptwindow.selection[0]:MainWindow.scriptwindow.selection[1]]
svlgui.app.set_clipboard(clip)
def paste(widget=None):
clip = svlgui.app.get_clipboard() if svlgui.app.query_clipboard() else None
if clip:
print clip
if MainWindow.stage.is_focused():
ctext = svlgui.Text(clip,200,100)
ctext.editing = False
# svlgui.CURRENTTEXT = self.ctext
ctext.onMouseDown = onMouseDownText
ctext.onMouseDrag = onMouseDragText
ctext.onMouseUp = onMouseUpText
self = root.descendItem()
self.add(ctext)
# self.add(self.ctext)
# self.ctext = None
undo_stack.append(edit("add_object", self, {"frame":self.activelayer.currentframe, "layer":self.activelayer}, \
{"frame":self.activelayer.currentframe, "layer":self.activelayer, \
"obj":self.activelayer.frames[self.activelayer.currentframe].objs[-1]}))
self.activelayer.currentselect = self.activelayer.frames[self.activelayer.currentframe].objs[-1]
MainWindow.stage.draw()
elif MainWindow.scriptwindow.is_focused():
MainWindow.scriptwindow.insert(clip)
def add_keyframe(widget=None):
print "af> ", root.descendItem().activeframe
root.descendItem().add_frame(True)
@ -811,6 +975,29 @@ def convert_to_symbol(widget=None):
svlgui.ConvertToSymbolWindow(root, onMouseDownMC)
MainWindow.stage.draw()
def export_svg(widget=None):
pass
def export_swf(widget=None):
global root
root.descendItem().activelayer.frames[root.descendItem().activelayer.currentframe].actions = MainWindow.scriptwindow.text
f = svlgui.file_dialog("save", name="untitled.swf")
if not f:
return
open(f.path+".sc",'w').write(create_sc(root))
# svlgui.execute("swfc/swfc_"+svlgui.PLATFORM+" "+os.getenv('HOME')+"/test.sc -o "+os.getenv('HOME')+"/test.swf")
x = os.system("swfc"+svlgui.sep+"swfc_"+svlgui.PLATFORM+" "+f.path+".sc -o "+f.path)
if sys.version_info < (2, 6):
if x==5: # which is the error value returned when linking libjpeg fails
if svlgui.alert("You appear to be missing libjpeg. Install it?", confirm=True):
os.system("""osascript -e 'do shell script "mkdir -p /usr/local/lib; cp swfc/libjpeg.8.dylib /usr/local/lib" with administrator privileges'""")
x = os.system("swfc/swfc_"+svlgui.PLATFORM+" "+f.path+".sc -o "+f.path)
if x==5:
svlgui.alert("Sorry, something has gone terribly wrong.")
else:
return
def about(widget=None):
svlgui.alert("Lightningbeam v1.0-alpha1\nLast Updated: "+update_date()+
"\nCreated by: Skyler Lehmkuhl\nBased on SWIFT")
@ -830,9 +1017,9 @@ svlgui.menufuncs([["File",
["Edit",
("Undo", undo, "/z"),
("Redo", redo, "/^z"),
"Cut",
"Copy",
"Paste",
("Cut", cut, "/x"),
("Copy", copy, "/c"),
("Paste", paste, "/v"),
"Delete",
("Preferences",preferences,"")],
["Timeline",
@ -844,10 +1031,11 @@ svlgui.menufuncs([["File",
("Import to Stage",import_to_stage,"/I"),
("Import to Library",import_to_library)],
["Export",
"Export .swf",
("Export .swf",export_swf,""),
"Export HTML5",
"Export Native Application",
"Export .sc",
("Export SVG",export_svg,""),
"Export Image",
"Export Video",
"Export .pdf",

View File

@ -231,7 +231,7 @@ class MainWindowOSX:
# self.toolbox.buttons[1][0]._int().enabled = False
self.toolbox.buttons[3][0]._int().enabled = False
self.toolbox.buttons[4][0]._int().enabled = False
self.scriptwindow = svlgui.TextView()
self.scriptwindow = svlgui.TextView(code=True)
self.paintgroup = svlgui.RadioGroup("Draw straight", "Draw smooth", "Draw as inked")
def setmode(self):
svlgui.PMODE = self.value

View File

@ -96,8 +96,30 @@ def lastval(arr,index):
return i
def angle_to_point(point1, point2):
deltaX = point2.x-point1.x
deltaY = point2.y-point1.y
angleInDegrees = math.atan2(-deltaY, deltaX) * 180 / math.pi
if angleInDegrees<0: angleInDegrees = 360+angleInDegrees
return angleInDegrees
def sqr(x) :
return x * x
def dist2(v, w):
return sqr(v.x - w.x) + sqr(v.y - w.y)
def distToSegmentSquared(p, v, w):
l2 = dist2(v, w)
if l2 == 0:
return dist2(p, v)
t = ((p.x - v.x) * (w.x - v.x) + (p.y - v.y) * (w.y - v.y)) / l2
if t < 0:
return dist2(p, v)
if t > 1:
return dist2(p, w)
return dist2(p, svlgui.Point(x=(v.x+t*(w.x-v.x)), y=(v.y+t*(w.y-v.y))))
def distToSegment(p, v, w):
return math.sqrt(distToSegmentSquared(p, v, w))
def catmullRom2bezier( points ) :
#crp = points.split(/[,\s]/);

View File

@ -14,6 +14,8 @@ import ez_setup
ez_setup.use_setuptools()
import sys
import shutil
import pygments
from setuptools import setup
@ -70,3 +72,11 @@ setup(
name="Lightningbeam",
**extra_options
)
if sys.platform == 'win32':
shutil.rmtree("dist\GUI")
shutil.rmtree("dist\pygments")
print "Copying PyGUI files..."
shutil.copytree("GUI", "dist\GUI")
print "Copying Pygments files..."
shutil.copytree("\\".join(pygments.__file__.split("\\")[:-1]), "dist\pygments")

255
svlgui.py
View File

@ -1,4 +1,4 @@
#! /usr/bin/python
#! /usr/bin/python
# -*- coding:utf-8 -*-
# © 2012 Skyler Lehmkuhl
# Released under the GPLv3. For more information, see gpl.txt.
@ -176,6 +176,8 @@ LINECOLOR = Color("#990099")
FILLCOLOR = Color("#00FF00")
TEXTCOLOR = Color("#000000")
LINEWIDTH = 2
#Magic. Detect platform and select appropriate toolkit. To be used throughout code.
if sys.platform=="linux2":
id = platform.machine()
@ -340,6 +342,9 @@ if SYSTEM=="osx":
m.new_cmd.enabled = 1
m.undo_cmd.enabled = 1
m.redo_cmd.enabled = 1
m.copy_cmd.enabled = 1
m.cut_cmd.enabled = 1
m.paste_cmd.enabled = 1
m.run_file.enabled = 1
m.run_html.enabled = 1
m.create_sc.enabled = 1
@ -352,6 +357,7 @@ if SYSTEM=="osx":
m.send_to_back.enabled = 1
m.import_to_stage.enabled = 1
m.import_to_library.enabled = 1
m.export_swf.enabled = 1
m.convert_to_symbol.enabled = 1
m.preferences_cmd.enabled = 1
@ -569,8 +575,8 @@ def menufuncs(j):
#menu = GUI.Menu("Test", [("Run", 'run_file')])
menus.append(menu)
else:
cmds={"New":"new_cmd", "Save":"save_cmd", "Save As":"save_as_cmd", "Open":"open_cmd","About Lightningbeam...":"about_cmd",\
"Preferences":"preferences_cmd", "Undo":"undo_cmd", "Redo":"redo_cmd"}
cmds={"New...":"new_cmd", "Save":"save_cmd", "Save As":"save_as_cmd", "Open":"open_cmd","About Lightningbeam...":"about_cmd",\
"Preferences":"preferences_cmd", "Undo":"undo_cmd", "Redo":"redo_cmd", "Cut":"cut_cmd", "Copy":"copy_cmd", "Paste":"paste_cmd"}
[setattr(app,cmds[k[0]],k[1]) for k in i if (k[0] in cmds)]
class VBox(Widget):
@ -1183,6 +1189,9 @@ class Canvas(Widget):
self.canvas.invalidate_rect((0,0,self.canvas.extent[0],self.canvas.extent[1]))
elif SYSTEM=="html":
jscommunicate("drawcanvas("+self.tid+")")
def is_focused(self):
if SYSTEM=="osx":
return self.canvas.is_target()
def add(self, obj, x, y):
obj.x = x
obj.y = y
@ -1209,8 +1218,15 @@ class TextView(Widget):
def _settext(self, text):
if SYSTEM=="osx":
self.box.text = text
def _getselection(self):
if SYSTEM=="osx":
return self.box.selection
def _setselection(self, tup):
if SYSTEM=="osx":
self.box.selection = tup
text = property(_gettext, _settext)
def __init__(self,editable=True,width=False,height=False):
selection = property(_getselection, _setselection)
def __init__(self,editable=True,width=False,height=False,code=False):
if SYSTEM=="gtk":
self.sw=ScrolledWindow()
self.box=gtk.TextView()
@ -1228,8 +1244,10 @@ class TextView(Widget):
def mouse_down(self, event):
self.become_target()
GUI.TextEditor.mouse_down(self, event)
# self.box = OSXTextEditor(scrolling="hv")
if code:
self.box = CodeEditor()
else:
self.box = OSXTextEditor(scrolling="hv")
self.box.font = Font("Courier", 12, [])
if width and height:
self.box.size = (width, height)
@ -1242,9 +1260,20 @@ class TextView(Widget):
return self.box
elif SYSTEM=="html":
return self.box
def is_focused(self):
if SYSTEM=="osx":
return self.box.is_target()
def insert(self, text):
if SYSTEM=="osx":
if isinstance(self.box, CodeEditor):
self.box.text = self.box.text[:self.box.selection[0]]+text+self.box.text[self.box.selection[1]:]
self.box.scursorpos = self.box.cursorpos = self.box.selection[0]+len(text)
self.box.selection = (self.box.selection[0]+len(text), self.box.selection[0]+len(text))
self.box.invalidate_rect([0,0,self.box.extent[0],self.box.extent[1]])
def scroll_bottom(self):
if SYSTEM=="osx":
self.scroll_page_down();
self.box.invalidate()
class TextEntry(Widget):
def __init__(self,text="",password=False):
@ -1950,7 +1979,7 @@ class Text (object):
class Sound:
"""Class for storing sounds in."""
def __init__(self, data, name, path, info):
def __init__(self, data, name, path, info, type):
global Library
Library.append(self)
self.data = data
@ -1962,6 +1991,7 @@ class Sound:
self.yscale = 0
self.path = path
self.iname = None
self.type = type
reading_comments_flag = False
other = ''
for l in info.splitlines():
@ -2017,7 +2047,7 @@ class Sound:
def hitTest(self, x, y):
return False
def print_sc(self):
retval = ".sound "+self.name+" \""+self.path+"\"\n"
retval = ".sound "+self.name+" \""+self.path.replace("\\","\\\\")+"\"\n"
return retval
def print_html(self):
retval = "var "+self.name.replace(".","_")+" = new Sound();\n"+self.name.replace(".","_")+"._sound = new Audio('"+self.path.split("/")[-1]+"');\n"
@ -2520,6 +2550,9 @@ class Group (object):
self.tempgroup = None
self.is_mc = False
self.name = "g"+str(int(random.random()*10000))+str(SITER)
self.lines = []
self.fills = []
self.activepoint = None
if "onload" in kwargs:
kwargs["onload"](self)
def draw(self,cr=None,transform=None,rect=None):
@ -2540,6 +2573,8 @@ class Group (object):
cr.pencolor = Color([0,0,1]).pygui
cr.stroke_rect([sorted([self.startx,self.cx])[0], sorted([self.starty,self.cy])[0], \
sorted([self.startx,self.cx])[1], sorted([self.starty,self.cy])[1]])
for i in self.lines:
i.draw(cr, rect=rect)
def add(self, *args):
self.activelayer.add(*args)
def add_frame(self, populate):
@ -2611,6 +2646,66 @@ class Group (object):
self.tempgroup = None
self.activelayer.currentselect = None
self.startx, self.starty = x, y
if MODE in " s":
for i in self.lines:
if abs(x-i.endpoint1.x)<10 and abs(y-i.endpoint1.y)<10:
i.endpoint1.x = x
i.endpoint1.y = y
self.activepoint = i.endpoint1
return
elif abs(x-i.endpoint2.x)<10 and abs(y-i.endpoint2.y)<10:
i.endpoint2.x = x
i.endpoint2.y = y
self.activepoint = i.endpoint2
return
elif MODE=="b":
nlines = [i for i in self.lines]
endsleft = True
while endsleft:
endsleft = False
print nlines
for i in reversed(nlines):
if not (i.endpoint1 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
nlines.remove(i)
endsleft = True
elif not (i.endpoint2 in [j.endpoint1 for j in nlines if not j==i]+[j.endpoint2 for j in nlines if not j==i]):
nlines.remove(i)
endsleft = True
if nlines:
mindist = sys.maxint
point = Point(x, y)
closestsegment = None
for i in nlines:
d = misc_funcs.distToSegment(point,i.endpoint1,i.endpoint2)
if d<mindist:
mindist = d
closestsegment = i
if closestsegment:
# Then go to endpoint of closestsegment counterclockwise from point
angle1 = misc_funcs.angle_to_point(point, closestsegment.endpoint1)
angle2 = misc_funcs.angle_to_point(point, closestsegment.endpoint2)
if (angle1<angle2 and angle2-angle1<180):
startpoint = closestsegment.endpoint2
else:
startpoint = closestsegment.endpoint1
print startpoint.lines
linelist = [closestsegment]
# nextline = max([[closestsegment.angle(i),i] for i in startpoint.lines if not i in linelist])
# print nextline
# Then, follow clockwise-most segment leading off from said point
while True:
try:
nextline = max([[closestsegment.angle(i),i] for i in startpoint.lines if not i==closestsegment])[1]
except:
break
closestsegment = nextline
if not nextline in linelist:
linelist.append(nextline)
else:
break
print "*****",linelist
# Continue until closestsegment is reached. I _think_ this is inevitable.
self.selecting = True
else:
self.onMouseDown(self, x, y, button=button, clicks=clicks)
@ -2628,6 +2723,25 @@ class Group (object):
if self.activelayer.level and MODE in [" ", "s"]:
if self.activelayer.currentselect:
self.activelayer.currentselect._onMouseUp(x, y, button=button, clicks=clicks)
elif self.activepoint:
for i in self.lines:
if abs(self.activepoint.x-i.endpoint1.x)<10 and abs(self.activepoint.y-i.endpoint1.y)<10:
try:
[j for j in self.lines if self.activepoint==j.endpoint1][0].assign(i.endpoint1, 1)
except IndexError:
try:
[j for j in self.lines if self.activepoint==j.endpoint2][0].assign(i.endpoint1, 2)
break
except IndexError: pass
if abs(self.activepoint.x-i.endpoint2.x)<10 and abs(self.activepoint.y-i.endpoint2.y)<10:
try:
[j for j in self.lines if self.activepoint==j.endpoint1][0].assign(i.endpoint2, 1)
except IndexError:
try:
[j for j in self.lines if self.activepoint==j.endpoint2][0].assign(i.endpoint2, 2)
break
except IndexError: pass
break
elif abs(self.startx-x)>4 or abs(self.starty-y)>4:
objs = []
for i in reversed(self.currentFrame()):
@ -2662,6 +2776,9 @@ class Group (object):
if self.activelayer.level and MODE in [" ", "s"]:
if self.activelayer.currentselect:
self.activelayer.currentselect._onMouseDrag(x, y, button=button)
elif self.activepoint:
self.activepoint.x = x
self.activepoint.y = y
else:
self.onMouseDrag(self, x, y, button=button)
def onMouseDrag(self, self1, x, y, button=1, clicks=1):
@ -2800,6 +2917,119 @@ class TemporaryGroup(Group):
elif key=="down_arrow":
self1.y+=1
class Point(object):
"""represents an x,y point, might store other data in the future"""
def __init__(self, x, y):
super(Point, self).__init__()
self.x = x
self.y = y
self.lines = set()
def __repr__(self):
return "<Point x="+str(self.x)+" y="+str(self.y)+">"
class Line(object):
"""Use Lines to build Shapes while allowing paintbucketing."""
def __init__(self, endpoint1, endpoint2, connection1 = None, connection2 = None):
super(Line, self).__init__()
self.endpoint1 = endpoint1
self.endpoint2 = endpoint2
self.endpoint1.lines.add(self)
self.endpoint2.lines.add(self)
self.connection1 = connection1
self.connection2 = connection2
if self.connection1: self.connection1.lines.add(self)
if self.connection2: self.connection2.lines.add(self)
self.linecolor = LINECOLOR
self.linewidth = LINEWIDTH
def __repr__(self):
return "<Line (endpoint1=("+str(self.endpoint1.x)+","+str(self.endpoint1.y)+"),endpoint2=("+str(self.endpoint2.x)+","+str(self.endpoint2.y)+"))>"
def assign(self, point, which):
if which==1:
self.connection1 = point
self.connection1.lines.add(self)
elif which==2:
self.connection2 = point
self.connection2.lines.add(self)
def angle(self, other):
if self.endpoint1==other.endpoint1:
x1 = self.endpoint2.x-self.endpoint1.x
y1 = self.endpoint2.y-self.endpoint1.y
x2 = other.endpoint2.x-other.endpoint1.x
y2 = other.endpoint2.y-other.endpoint1.y
elif self.endpoint2==other.endpoint1:
x1 = self.endpoint1.x-self.endpoint2.x
y1 = self.endpoint1.y-self.endpoint2.y
x2 = other.endpoint2.x-other.endpoint1.x
y2 = other.endpoint2.y-other.endpoint1.y
elif self.endpoint1==other.endpoint2:
x1 = self.endpoint2.x-self.endpoint1.x
y1 = self.endpoint2.y-self.endpoint1.y
x2 = other.endpoint1.x-other.endpoint2.x
y2 = other.endpoint1.y-other.endpoint2.y
elif self.endpoint2==other.endpoint2:
x1 = self.endpoint1.x-self.endpoint2.x
y1 = self.endpoint1.y-self.endpoint2.y
x2 = other.endpoint1.x-other.endpoint2.x
y2 = other.endpoint1.y-other.endpoint2.y
dot = x1*x2+y1*y2
mag1 = math.sqrt(x1**2+y1**2)
mag2 = math.sqrt(x2**2+y2**2)
angle = math.acos(dot/(mag1*mag2))/math.pi*180
cz = x1*y2-y1*x2
if cz>0: angle=360-angle
return angle
def draw(self, cr=None, transform=None, rect=None):
if self.connection1:
self.endpoint1 = self.connection1
if self.connection2:
self.endpoint2 = self.connection2
if SYSTEM=="gtk":
cr.save()
cr.set_source(self.linecolor.cairo)
cr.set_line_width(max(self.linewidth,1))
cr.move_to(self.endpoint1.x,self.endpoint2.y)
cr.line_to(self.endpoint2.x,self.endpoint2.y)
cr.stroke()
cr.restore()
elif SYSTEM=="android":
global tb
tb+="cr.save()\n"
tb+="cr.lineWidth = "+str(max(self.linewidth,1))+"\n"
tb+="cr.moveTo("+str(self.endpoint1.x)+","+str(self.endpoint1.y)+")\n"
tb+="cr.lineTo("+str(self.endpoint2.x)+","+str(self.endpoint2.y)+")\n"
tb+="cr.stroke()\n"
tb+="cr.restore()\n"
elif SYSTEM=="osx":
if USING_GL:
cr.save()
glColor3f(1.0,0.0,0.0)
glBegin(GL_LINES)
cr.x, cr.y = (self.endpoint1.x, self.endpoint1.y)
glVertex2f(cr.x, -cr.y)
point = (self.endpoint2.x, self.endpoint2.y)
glVertex2f(point[0], -point[1]) # because OpenGL swaps y coords
cr.x, cr.y = point
glEnd()
cr.restore()
else:
cr.gsave()
cr.newpath()
cr.pencolor = self.linecolor.pygui
cr.pensize = max(self.linewidth,1)
cr.moveto(self.endpoint1.x, self.endpoint1.y)
cr.lineto(self.endpoint2.x,self.endpoint2.y)
cr.stroke()
cr.grestore()
elif SYSTEM=="html":
tb = ""
tb+="cr.save()\n"
tb+="cr.lineWidth = "+str(max(self.linewidth,1))+"\n"
tb+="cr.moveTo("+str(self.endpoint1.x)+","+str(self.endpoint1.y)+")\n"
tb+="cr.lineTo("+str(self.endpoint2.x)+","+str(self.endpoint2.y)+")\n"
tb+="cr.stroke()\n"
tb+="cr.restore()\n"
jscommunicate(tb)
def set_cursor(curs, widget=None):
if SYSTEM == "osx":
@ -2888,6 +3118,14 @@ def file_dialog(mode="open",default=None,types=None,multiple=False,name=None):
for i in types:
ntypes.append(GUI.Files.FileType())
ntypes[-1].suffix = i
image = ["jpg", "jpeg", "png", "tiff", "tga"]
audio = ["wav", "mp3", "ogg"]
if i in image:
ntypes[-1].name = i.upper()+" Images"
elif i in audio:
ntypes[-1].name = i.upper()+" Audio"
else:
ntypes[-1].name = i.upper()+" Files"
if i in mactypes:
ntypes[-1].mac_type=mactypes[i]
types = ntypes
@ -2901,7 +3139,8 @@ def file_dialog(mode="open",default=None,types=None,multiple=False,name=None):
def execute(command):
rv = os.system(command.replace("/",sep))
if PLATFORM == "osx":
print command.replace("/",sep)
if SYSTEM == "osx":
if rv==0:
return True
else: