def slideshow(): oldalgo = g.getalgo() oldrule = g.getrule() message = "Hit space to continue or escape to exit the slide show..." g.show(message) for root, dirs, files in os.walk(g.getdir("app") + "Patterns"): for name in files: if name.startswith("."): # ignore hidden files (like .DS_Store on Mac) pass else: g.new("") g.setalgo("QuickLife") # nicer to start from this algo fullname = join(root, name) g.open(fullname, False) # don't add file to Open/Run Recent submenu g.update() if name.endswith(".lua") or name.endswith(".py"): # reshow message in case it was changed by script g.show(message) while True: event = g.getevent() if event == "key space none": break g.doevent(event) # allow keyboard/mouse interaction sleep(0.01) # avoid hogging cpu # if all patterns have been displayed then restore original algo and rule # (don't do this if user hits escape in case they want to explore pattern) g.new("untitled") g.setalgo(oldalgo) g.setrule(oldrule)
def lookforkeys(event, deltax, deltay): global oldcells, selrect, selpatt # look for keys used to flip/rotate selection if event == "key x none" or event == "key y none": # flip floating selection left-right or top-bottom if len(oldcells) > 0: g.clear(0) g.putcells(selpatt, deltax, deltay) if " x " in event: g.flip(0) else: g.flip(1) selpatt = g.transform(g.getcells(selrect), -deltax, -deltay) if len(oldcells) > 0: g.clear(0) g.putcells(oldcells) g.putcells(selpatt, deltax, deltay) g.update() return if event == "key > none" or event == "key < none": # rotate floating selection clockwise or anticlockwise; # because we use g.rotate below we have to use the exact same # calculation (see Selection::Rotate in wxselect.cpp) for rotrect: midx = selrect[0] + int((selrect[2]-1)/2) midy = selrect[1] + int((selrect[3]-1)/2) newleft = midx + selrect[1] - midy newtop = midy + selrect[0] - midx rotrect = [ newleft, newtop, selrect[3], selrect[2] ] if not rectingrid(rotrect): g.warn("Rotation is not allowed if selection would be outside grid.") return g.clear(0) if len(oldcells) > 0: g.putcells(oldcells) oldcells = g.join(oldcells, g.getcells(rotrect)) g.clear(0) g.select(rotrect) g.clear(0) g.select(selrect) g.putcells(selpatt, deltax, deltay) if " > " in event: g.rotate(0) else: g.rotate(1) selrect = g.getselrect() if selrect != rotrect: g.warn("Bug: selrect != rotrect") selpatt = g.transform(g.getcells(selrect), -deltax, -deltay) if len(oldcells) > 0: g.clear(0) g.putcells(oldcells) g.putcells(selpatt, deltax, deltay) g.update() return if event == "key h none": showhelp2() return g.doevent(event)
def slideshow (): oldalgo = g.getalgo() oldrule = g.getrule() message = "Hit space to continue or escape to exit the slide show..." g.show(message) for root, dirs, files in os.walk(g.getdir("app") + "Patterns"): for name in files: if name.startswith("."): # ignore hidden files (like .DS_Store on Mac) pass else: fullname = join(root, name) g.open(fullname, False) # don't add file to Open/Run Recent submenu g.update() if name.endswith(".pl") or name.endswith(".py"): # reshow message in case it was changed by script g.show(message) while True: event = g.getevent() if event == "key space none": break g.doevent(event) # allow keyboard/mouse interaction sleep(0.01) # avoid hogging cpu if "CVS" in dirs: dirs.remove("CVS") # don't visit CVS directories # if all patterns have been displayed then restore original algo and rule # (don't do this if user hits escape in case they want to explore pattern) g.new("untitled") g.setalgo(oldalgo) g.setrule(oldrule)
def lookforkeys(event): global oldcells, object # look for keys used to flip/rotate object if event == "key x none" or event == "key y none": # flip floating object left-right or top-bottom g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) obox = getminbox(object) if event == "key x none": # translate object so that bounding box doesn't change xshift = 2 * (obox.left + int(obox.wd//2)) if obox.wd % 2 == 0: xshift -= 1 object = g.transform(object, xshift, 0, -1, 0, 0, 1) else: # translate object so that bounding box doesn't change yshift = 2 * (obox.top + int(obox.ht//2)) if obox.ht % 2 == 0: yshift -= 1 object = g.transform(object, 0, yshift, 1, 0, 0, -1) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key > none" or event == "key < none": # rotate floating object clockwise or anticlockwise # about the center of the object's bounding box obox = getminbox(object) midx = obox.left + int(obox.wd//2) midy = obox.top + int(obox.ht//2) newleft = midx + obox.top - midy newtop = midy + obox.left - midx rotrect = [ newleft, newtop, obox.ht, obox.wd ] if not rectingrid(rotrect): g.show("Rotation is not allowed if object would be outside grid.") return g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) if event == "key > none": # rotate clockwise object = g.transform(object, 0, 0, 0, -1, 1, 0) else: # rotate anticlockwise object = g.transform(object, 0, 0, 0, 1, -1, 0) # shift rotated object to same position as rotrect obox = getminbox(object) object = g.transform(object, newleft - obox.left, newtop - obox.top) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key h none": # best not to show Help window while dragging object! return g.doevent(event)
def lookforkeys(event): global oldcells, object # look for keys used to flip/rotate object if event == "key x none" or event == "key y none": # flip floating object left-right or top-bottom g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) obox = getminbox(object) if event == "key x none": # translate object so that bounding box doesn't change xshift = 2 * (obox.left + int(obox.wd/2)) if obox.wd % 2 == 0: xshift -= 1 object = g.transform(object, xshift, 0, -1, 0, 0, 1) else: # translate object so that bounding box doesn't change yshift = 2 * (obox.top + int(obox.ht/2)) if obox.ht % 2 == 0: yshift -= 1 object = g.transform(object, 0, yshift, 1, 0, 0, -1) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key > none" or event == "key < none": # rotate floating object clockwise or anticlockwise # about the center of the object's bounding box obox = getminbox(object) midx = obox.left + int(obox.wd/2) midy = obox.top + int(obox.ht/2) newleft = midx + obox.top - midy newtop = midy + obox.left - midx rotrect = [ newleft, newtop, obox.ht, obox.wd ] if not rectingrid(rotrect): g.warn("Rotation is not allowed if object would be outside grid.") return g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) if event == "key > none": # rotate clockwise object = g.transform(object, 0, 0, 0, -1, 1, 0) else: # rotate anticlockwise object = g.transform(object, 0, 0, 0, 1, -1, 0) # shift rotated object to same position as rotrect obox = getminbox(object) object = g.transform(object, newleft - obox.left, newtop - obox.top) oldcells = underneath(object) g.putcells(object) g.update() return if event == "key h none": showhelp2() return g.doevent(event)
def drawlines(): global oldline, firstcell started = False oldmouse = "" while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left altctrlshift" evt, x, y, butt, mods = event.split() oldmouse = x + ' ' + y if started: # draw permanent line from start pos to end pos endx = int(x) endy = int(y) drawline(startx, starty, endx, endy) # this is also the start of another line startx = endx starty = endy oldline = [] firstcell = [] else: # start first line startx = int(x) starty = int(y) firstcell = [startx, starty, g.getcell(startx, starty)] g.setcell(startx, starty, drawstate) g.update() started = True g.show( "Click where to end this line (and start another line)...") else: # event might be "" or "key m none" if len(event) > 0: g.doevent(event) mousepos = g.getxy() if started and len(mousepos) == 0: # erase old line if mouse is not over grid if len(oldline) > 0: eraseline(oldline) oldline = [] g.update() elif started and len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so erase old line (if any) and draw new line if len(oldline) > 0: eraseline(oldline) x, y = mousepos.split() oldline = drawline(startx, starty, int(x), int(y)) oldmouse = mousepos
def drawlines(): global oldline, firstcell started = False oldmouse = "" while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left altctrlshift" evt, x, y, butt, mods = event.split() oldmouse = x + ' ' + y if started: # draw permanent line from start pos to end pos endx = int(x) endy = int(y) drawline(startx, starty, endx, endy) # this is also the start of another line startx = endx starty = endy oldline = [] firstcell = [] else: # start first line startx = int(x) starty = int(y) firstcell = [ startx, starty, g.getcell(startx, starty) ] g.setcell(startx, starty, drawstate) g.update() started = True g.show("Click where to end this line (and start another line)...") else: # event might be "" or "key m none" if len(event) > 0: g.doevent(event) mousepos = g.getxy() if started and len(mousepos) == 0: # erase old line if mouse is not over grid if len(oldline) > 0: eraseline(oldline) oldline = [] g.update() elif started and len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so erase old line (if any) and draw new line if len(oldline) > 0: eraseline(oldline) x, y = mousepos.split() oldline = drawline(startx, starty, int(x), int(y)) oldmouse = mousepos
def check_keyboard(): global runflag while 1: evt = g.getevent() if evt != "": g.show(state + " -- " + nextstate + " :: " + instr + "; regs=" + str(registers) + " -- 'r' to toggle run mode, any key to step") if evt == "key q none": g.setclipstr(s) g.exit() if evt == "key r none": runflag = 1 - runflag elif evt == "key g none": break else: g.doevent(evt) if runflag == 1: break
def EventLoop(): global volume, genspersec nextgen = 0.0 running = True while True: space = False event = g.getevent() if len(event) == 0: sleep(0.005) # don't hog CPU if idle elif event == "key space none": running = False space = True nextgen = 0 elif event == "key return none": running = not running elif event == "key h none": ShowHelp() elif event == "key up none": volume = min(1.0, volume + 0.1) ShowInfo() elif event == "key down none": volume = max(0.0, volume - 0.1) ShowInfo() elif event == "key = none" or event == "key + none": genspersec = min(30, genspersec + 1) ShowInfo() elif event == "key - none": genspersec = max(1, genspersec - 1) ShowInfo() else: g.doevent(event) # might be a keyboard shortcut if (running or space) and time() >= nextgen: g.run(1) if g.empty(): g.exit("The pattern died.") PlaySound() g.update() if not space: nextgen = time() + 1.0 / genspersec
def burp(): test_signal=pattern(""" 40bo$41bo$39b3o17$40bo4bo4bo4bo4bo$41bo4bo4bo4bo4bo$39b3o2b3o2b3o2b3o 2b3o3$40bo4bo4bo4bo4bo$41bo4bo4bo4bo4bo$39b3o2b3o2b3o2b3o2b3o3$40bo4bo 4bo4bo4bo$41bo4bo4bo4bo4bo$39b3o2b3o2b3o2b3o2b3o3$40bo4bo4bo4bo4bo$41b o4bo4bo4bo4bo$39b3o2b3o2b3o2b3o2b3o3$bo38bo4bo4bo4bo4bo18bo$2bo38bo4bo 4bo4bo4bo18bo$3o36b3o2b3o2b3o2b3o2b3o16b3o37$40bo$41bo$39b3o!""") prepare_burp() ticks=0 tickstep=5 last_signal=-99999 viewport_speed=16 sel_speed=0.0 delta_sel=0.0 delay=-1.0 run_flag=False ch="" selx=600.0 sely=365.0 place_signal=3 helpstring="""Use ENTER and SPACE to run or halt the pattern; use + and - to change the step size or delay value; use arrow keys and mouse tools to pan and zoom in any pane; T toggles between a tiled view and a single-pane view; S creates another signal fleet near the detection mechanism; R resets the Heisenburp device to its initial state; Q quits out of the script and restores original settings.""" instr="Press H for help. " g.show(instr + str(tickstep)) g.select([selx,sely,50,50]) # keyboard handling while ch<>"q": if place_signal>0: if ticks-last_signal>1846: test_signal.put(-150,60) last_signal=ticks place_signal-=1 if place_signal>0 and run_flag==True: show_status_text("Next signal placement in " \ + str(1847 - ticks + last_signal) + " ticks. " + instr, delay, tickstep) else: show_status_text(instr,delay,tickstep) event = g.getevent() if event.startswith("key"): evt, ch, mods = event.split() else: ch = "" if ch=="r": prepare_burp() ticks=0 last_signal=-99999 viewport_speed=16 sel_speed=0 run_flag=False selx=600.0 sely=365.0 place_signal=3 g.select([selx,sely,50,50]) elif ch=="h": g.note(helpstring) elif ch=="t": g.setoption("tilelayers",1-g.getoption("tilelayers")) elif ch=="=" or ch=="+": if delay>.01: delay/=2 elif delay==.01: delay=-1 else: if tickstep==1: tickstep=3 elif tickstep<250: tickstep=(tickstep-1)*2+1 elif ch=="-" or ch=="_": if delay==-1: if tickstep==1: delay=.01 else: if tickstep==3: tickstep=1 else: tickstep=(tickstep-1)/2+1 else: if delay<1: delay*=2 elif ch=="space": run_flag=False elif ch=="return": run_flag=not run_flag elif ch=="s": place_signal+=1 else: # just pass any other keyboard/mouse event through to Golly g.doevent(event) # generation and selection speed handling if ch=="space" or run_flag==True: g.run(tickstep) currlayer = g.getlayer() if currlayer != 4: # user has switched layer so temporarily change it back # so we only change location of bottom right layer g.check(False) g.setlayer(4) x, y = getposint() oldticks=ticks ticks+=tickstep delta_view=int(ticks/viewport_speed) - int(oldticks/viewport_speed) if delta_view <> 0: # assumes diagonal motion for now setposint(x + delta_view, y + delta_view) sel = g.getselrect() if len(sel)<>0: x, y, w, h = sel if int(selx)<>x: # user changed selection # prepare to move new selection instead (!?!) # -- use floating-point selx, sely to account for fractional speeds selx=x sely=y else: selx+=sel_speed*tickstep sely+=sel_speed*tickstep g.select([selx, sely, w, h]) else: g.select([selx, sely, 50, 50]) if currlayer != 4: g.setlayer(currlayer) g.check(True) # change viewport speed at appropriate times to follow the action if oldticks<4570 and ticks>=4570: sel_speed=.666667 # one-time correction to catch up with the signal at high sim speeds g.select([600+(ticks-4570)*1.5, 365+(ticks-4570)*1.5, w, h]) if selx>2125: sel_speed=0 g.select([2125, sely+2125-selx, w, h]) if oldticks<4750 and ticks>=4750: viewport_speed=1.5 if oldticks<6125 and ticks>=6125: viewport_speed=16 if oldticks>=11995: viewport_speed=99999.9 # stop automatically after the last signal passes through the device if oldticks - last_signal<8705 and ticks - last_signal>=8705: run_flag=False if run_flag==True and delay>0: sleep(delay) g.update()
def Main(self): g.show("left click on a pattern to change, 'h' for help") gollyMode = False while True: event = g.getevent() if ("key" in event and "return" in event) or (gollyMode and " a " in event): gollyMode = not gollyMode if gollyMode: g.show("In golly mode") g.update() else: g.show("left click on a pattern, right click to finish") g.setrule("B3/S23") g.setalgo("HashLife") g.reset() g.update() continue if gollyMode: if " delete " in event: g.clear(0) if "click" in event and "ctrl" in event and g.getxy() != "": x, y = g.getxy().split() cell = g.getcell(int(x), int(y)) if cell >= 0 and cell <= 1: g.setcell(int(x), int(y), 1 - cell) g.update() if " c " in event and "ctrl" in event and g.getselrect() != []: g.copy() if " v " in event and "ctrl" in event and g.getxy() != "": x, y = g.getxy().split() g.paste(int(x), int(y), "or") if " space " in event: if "ctrl" in event: g.run(10) else: g.run(1) g.doevent(event) continue if "click" in event: if "left" in event: if self.ExistinCircuitHandler() == None: if self.SignalClickHandler(event) == None: g.show("left click on a pattern, h for help") elif "key" in event: if " space " in event: for i in xrange(0, 30): g.run(60) g.update() g.reset() g.update() if " a " in event: if g.getrule() == "Perrier": g.setrule("B3/S23") g.setalgo("HashLife") g.update() else: g.setrule("Perrier") for key in self.smarCells: x, y = key.split(":") g.setcell(int(x), int(y), self.smarCells[key] + 2) gollyMode = True g.show("In golly mode") g.update() if " s " in event: fname = os.path.join(g.getdir("data"), "MetadataManager.json") #self.Save(fname) if " h " in event: noteMessage = "Viewing and Selecting\n\n" noteMessage += "'left click' to chose gun or glider\n" noteMessage += "'a' to see in colors, a to go back \n" noteMessage += "'space' see ahead 1800 generations \n" noteMessage += "'enter' gollyMode, stays in the script \n" noteMessage += "\n Editing Gun \n\n" noteMessage += "'left click' to place\n" noteMessage += "'right click' to switch gun/orientation \n" noteMessage += "'delete' to delete the gun \n" noteMessage += "'left-right arrow' - one step adjustment\n" noteMessage += "\n In Golly Mode \n\n" noteMessage += "'delete' to clear selection\n" noteMessage += "'ctrl' + 'click' to draw \n" noteMessage += "'ctrl' + 'c' to copy selection \n" noteMessage += "'ctrl' + 'v' to paste in mouse location \n" noteMessage += "'space' + to run 1 generation \n" noteMessage += "'ctrl' +'space' to run 10 generations \n" g.note(noteMessage)
elif key == 'n': testCA.clear() testCA.rand_fill(rand_r) testCA.draw(addstr) initpat = testCA.cur_state.copy() elif key == 'return': running = not running elif key == 'space': testCA.run(1) testCA.draw(addstr) elif key == 'delete': testCA.cur_state = initpat testCA.draw(addstr) running = False elif key == 'r': idx = g.getstring("Enter random fill size", str(rand_r)) rand_r = int(idx) elif key == 'h': g.note(helpstr) else: g.doevent(event) else: g.doevent(event)
def moveselection(): global oldcells, selrect, selpatt # wait for 1st click in selection while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() x = int(xstr) y = int(ystr) if cellinrect(x, y, selrect): oldmouse = xstr + ' ' + ystr firstx = x firsty = y xoffset = firstx - selrect[0] yoffset = firsty - selrect[1] if mods == "alt": # don't delete pattern in selection oldcells = g.getcells(selrect) break elif event == "key h none": showhelp1() else: g.doevent(event) # wait for 2nd click while moving selection g.show("Move mouse and click again..." + helpmsg) gotclick = False while not gotclick: event = g.getevent() if event.startswith("click"): evt, x, y, butt, mods = event.split() mousepos = x+' '+y gotclick = True else: if len(event) > 0: lookforkeys(event, x - firstx, y - firsty) # update xoffset,yoffset in case selection was rotated xoffset = x - selrect[0] yoffset = y - selrect[1] mousepos = g.getxy() if len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so move selection rect and pattern g.clear(0) if len(oldcells) > 0: g.putcells(oldcells) xstr, ystr = mousepos.split() x = int(xstr) y = int(ystr) selrect[0] = x - xoffset selrect[1] = y - yoffset if g.getwidth() > 0: # ensure selrect doesn't move beyond left/right edge of grid if selrect[0] < gridl: selrect[0] = gridl x = selrect[0] + xoffset elif selrect[0] + selrect[2] - 1 > gridr: selrect[0] = gridr + 1 - selrect[2] x = selrect[0] + xoffset if g.getheight() > 0: # ensure selrect doesn't move beyond top/bottom edge of grid if selrect[1] < gridt: selrect[1] = gridt y = selrect[1] + yoffset elif selrect[1] + selrect[3] - 1 > gridb: selrect[1] = gridb + 1 - selrect[3] y = selrect[1] + yoffset g.select(selrect) oldcells = g.getcells(selrect) g.putcells(selpatt, x - firstx, y - firsty) oldmouse = mousepos g.update()
def moveobject(): global oldcells, object, object1 # wait for click in or near a live cell while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() result = findlivecell(int(xstr), int(ystr)) if len(result) > 0: prevx = int(xstr) prevy = int(ystr) oldmouse = xstr + ' ' + ystr g.show("Extracting object...") x, y = result object = getobject(x, y) object1 = list(object) # save in case user aborts script if mods == "alt": # don't delete object oldcells = list(object) break else: g.warn("Click on or near a live cell belonging to the desired object.") elif event == "key h none": showhelp() else: g.doevent(event) # wait for mouse-up while moving object g.show("Move mouse and release button...") mousedown = True while mousedown: event = g.getevent() if event.startswith("mup"): mousedown = False elif len(event) > 0: lookforkeys(event) mousepos = g.getxy() if len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so move object g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) xstr, ystr = mousepos.split() x = int(xstr) y = int(ystr) if g.getwidth() > 0: # ensure object doesn't move beyond left/right edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.left < gridl: x += gridl - obox.left elif obox.right > gridr: x -= obox.right - gridr if g.getheight() > 0: # ensure object doesn't move beyond top/bottom edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.top < gridt: y += gridt - obox.top elif obox.bottom > gridb: y -= obox.bottom - gridb object = g.transform(object, x - prevx, y - prevy) oldcells = underneath(object) g.putcells(object) prevx = x prevy = y oldmouse = mousepos g.update()
# Set Directory Back to Parent Folder fileLoc = g.getdir("rules") + generationDir # Creates Subfolder specific to Rule Set to hold Generation Patterns fileLoc += rule.replace("/", "_") + "/" if (os.path.isdir(fileLoc) is not True): os.mkdir(fileLoc) # Prepare File Names for each Genereration's Pattern File fileNamePrefix = fileLoc + rule.replace("/", "_") + "_" # Loop and Save Patterns for i in range(int(timeElapsed) + 1): # Stop Loop if Universe is Empty if (g.empty()): break # Determine File Names fileNameRLE = fileNamePrefix + str(i) + ".rle" # Determine Previous File Names fileNamePrevRLE = fileNamePrefix + str(i - 1) + ".rle" g.save(fileNameRLE, "rle") # Compare Previous Generation to Determine Class I Systems if (i > 0 and compare_rle(fileNameRLE, fileNamePrevRLE)): break g.run(1) # Close g.doevent("key q cmd")
def moveobject(): global oldcells, object, object1 # wait for 1st click in live cell while True: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() result = findlivecell(int(xstr), int(ystr)) if len(result) > 0: prevx = int(xstr) prevy = int(ystr) oldmouse = xstr + ' ' + ystr g.show("Extracting object...") x, y = result object = getobject(x, y) object1 = list(object) # save in case user aborts script if mods == "alt": # don't delete object oldcells = list(object) break else: g.warn("Click on or near a live cell belonging to the desired object.") elif event == "key h none": showhelp1() else: g.doevent(event) # wait for 2nd click while moving object g.show("Move mouse and click again..." + helpmsg) gotclick = False while not gotclick: event = g.getevent() if event.startswith("click"): evt, x, y, butt, mods = event.split() mousepos = x+' '+y gotclick = True else: if len(event) > 0: lookforkeys(event) mousepos = g.getxy() if len(mousepos) > 0 and mousepos != oldmouse: # mouse has moved, so move object g.putcells(object, 0, 0, 1, 0, 0, 1, "xor") # erase object if len(oldcells) > 0: g.putcells(oldcells) xstr, ystr = mousepos.split() x = int(xstr) y = int(ystr) if g.getwidth() > 0: # ensure object doesn't move beyond left/right edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.left < gridl: x += gridl - obox.left elif obox.right > gridr: x -= obox.right - gridr if g.getheight() > 0: # ensure object doesn't move beyond top/bottom edge of grid obox = getminbox( g.transform(object, x - prevx, y - prevy) ) if obox.top < gridt: y += gridt - obox.top elif obox.bottom > gridb: y -= obox.bottom - gridb object = g.transform(object, x - prevx, y - prevy) oldcells = underneath(object) g.putcells(object) prevx = x prevy = y oldmouse = mousepos g.update()
def floodfill(): newstate = g.getoption("drawingstate") oldstate = newstate # wait for user to click a cell g.show("Click the region you wish to fill... (hit escape to abort)") while oldstate == newstate: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() x = int(xstr) y = int(ystr) if x < minx or x > maxx or y < miny or y > maxy: # click is outside pattern's bounding box in unbounded universe g.warn("Click within the pattern's bounding box\n" + "otherwise the fill will be unbounded.") else: # note that user might have changed drawing state newstate = g.getoption("drawingstate") oldstate = g.getcell(x, y) if oldstate == newstate: g.warn("The clicked cell must have a different state\n" + "to the current drawing state.") else: g.doevent(event) # tell Golly to handle all further keyboard/mouse events g.getevent(False) # do flood fill starting with clicked cell g.show("Filling clicked region... (hit escape to stop)") clist = [(x, y)] g.setcell(x, y, newstate) oldsecs = time() while len(clist) > 0: # remove cell from start of clist x, y = clist.pop(0) newsecs = time() if newsecs - oldsecs >= 0.5: # show changed pattern every half second oldsecs = newsecs g.update() # check if any orthogonal neighboring cells are in oldstate if checkneighbor(x, y - 1, oldstate): g.setcell(x, y - 1, newstate) clist.append((x, y - 1)) if checkneighbor(x, y + 1, oldstate): g.setcell(x, y + 1, newstate) clist.append((x, y + 1)) if checkneighbor(x + 1, y, oldstate): g.setcell(x + 1, y, newstate) clist.append((x + 1, y)) if checkneighbor(x - 1, y, oldstate): g.setcell(x - 1, y, newstate) clist.append((x - 1, y)) # diagonal neighbors are more complicated because we don't # want to cross a diagonal line of live cells if checkneighbor(x + 1, y + 1, oldstate) and (g.getcell( x, y + 1) == 0 or g.getcell(x + 1, y) == 0): g.setcell(x + 1, y + 1, newstate) clist.append((x + 1, y + 1)) if checkneighbor(x + 1, y - 1, oldstate) and (g.getcell( x, y - 1) == 0 or g.getcell(x + 1, y) == 0): g.setcell(x + 1, y - 1, newstate) clist.append((x + 1, y - 1)) if checkneighbor(x - 1, y + 1, oldstate) and (g.getcell( x, y + 1) == 0 or g.getcell(x - 1, y) == 0): g.setcell(x - 1, y + 1, newstate) clist.append((x - 1, y + 1)) if checkneighbor(x - 1, y - 1, oldstate) and (g.getcell( x, y - 1) == 0 or g.getcell(x - 1, y) == 0): g.setcell(x - 1, y - 1, newstate) clist.append((x - 1, y - 1))
def floodfill(): newstate = g.getoption("drawingstate") oldstate = newstate # wait for user to click a cell g.show("Click the region you wish to fill... (hit escape to abort)") while oldstate == newstate: event = g.getevent() if event.startswith("click"): # event is a string like "click 10 20 left none" evt, xstr, ystr, butt, mods = event.split() x = int(xstr) y = int(ystr) if x < minx or x > maxx or y < miny or y > maxy: # click is outside pattern's bounding box in unbounded universe g.warn("Click within the pattern's bounding box\n"+ "otherwise the fill will be unbounded.") else: # note that user might have changed drawing state newstate = g.getoption("drawingstate") oldstate = g.getcell(x, y) if oldstate == newstate: g.warn("The clicked cell must have a different state\n"+ "to the current drawing state.") else: g.doevent(event) # tell Golly to handle all further keyboard/mouse events g.getevent(False) # do flood fill starting with clicked cell g.show("Filling clicked region... (hit escape to stop)") clist = [ (x,y) ] g.setcell(x, y, newstate) oldsecs = time() while len(clist) > 0: # remove cell from start of clist x, y = clist.pop(0) newsecs = time() if newsecs - oldsecs >= 0.5: # show changed pattern every half second oldsecs = newsecs g.update() # check if any orthogonal neighboring cells are in oldstate if checkneighbor( x, y-1, oldstate): g.setcell( x, y-1, newstate) clist.append( (x, y-1) ) if checkneighbor( x, y+1, oldstate): g.setcell( x, y+1, newstate) clist.append( (x, y+1) ) if checkneighbor( x+1, y, oldstate): g.setcell( x+1, y, newstate) clist.append( (x+1, y) ) if checkneighbor( x-1, y, oldstate): g.setcell( x-1, y, newstate) clist.append( (x-1, y) ) # diagonal neighbors are more complicated because we don't # want to cross a diagonal line of live cells if checkneighbor( x+1, y+1, oldstate) and (g.getcell(x, y+1) == 0 or g.getcell(x+1, y) == 0): g.setcell( x+1, y+1, newstate) clist.append( (x+1, y+1) ) if checkneighbor( x+1, y-1, oldstate) and (g.getcell(x, y-1) == 0 or g.getcell(x+1, y) == 0): g.setcell( x+1, y-1, newstate) clist.append( (x+1, y-1) ) if checkneighbor( x-1, y+1, oldstate) and (g.getcell(x, y+1) == 0 or g.getcell(x-1, y) == 0): g.setcell( x-1, y+1, newstate) clist.append( (x-1, y+1) ) if checkneighbor( x-1, y-1, oldstate) and (g.getcell(x, y-1) == 0 or g.getcell(x-1, y) == 0): g.setcell( x-1, y-1, newstate) clist.append( (x-1, y-1) )