Skip to content

Commit 9562c44

Browse files
committed
Initial GUI
1 parent ebb95cb commit 9562c44

10 files changed

Lines changed: 295 additions & 7 deletions

File tree

assets/project.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
{"targets":[{"isStage":true,"name":"Stage","variables":{},"lists":{},"broadcasts":{},"blocks":{},"comments":{},"currentCostume":0,"costumes":[{"name":"backdrop1","dataFormat":"svg","assetId":"cd21514d0531fdffb22204e0ec5ed84a","md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg","rotationCenterX":240,"rotationCenterY":180}],"sounds":[],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"on","textToSpeechLanguage":"ro"},{"isStage":false,"name":"Donut","variables":{},"lists":{},"broadcasts":{},"blocks":{"DYTC:C,lIx4EE$!(jZ/t":{"opcode":"event_whenkeypressed","next":"l`W=i}axx0M8$Jw[![hN","parent":null,"inputs":{},"fields":{"KEY_OPTION":["space",null]},"shadow":false,"topLevel":true,"x":260,"y":499},"l`W=i}axx0M8$Jw[![hN":{"opcode":"motion_turnright","next":null,"parent":"DYTC:C,lIx4EE$!(jZ/t","inputs":{"DEGREES":[1,[4,"15"]]},"fields":{},"shadow":false,"topLevel":false}},"comments":{},"currentCostume":0,"costumes":[{"name":"donut","bitmapResolution":1,"dataFormat":"svg","assetId":"c3b5bc130c3f035513efa57b2c49e101","md5ext":"c3b5bc130c3f035513efa57b2c49e101.svg","rotationCenterX":56.47026521242515,"rotationCenterY":32.444223183765985}],"sounds":[{"name":"Bite","assetId":"0039635b1d6853face36581784558454","dataFormat":"wav","format":"adpcm","rate":22050,"sampleCount":8129,"md5ext":"0039635b1d6853face36581784558454.wav"},{"name":"Chomp","assetId":"0b1e3033140d094563248e61de4039e5","dataFormat":"wav","format":"","rate":44100,"sampleCount":11648,"md5ext":"0b1e3033140d094563248e61de4039e5.wav"}],"volume":100,"layerOrder":1,"visible":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"rotationStyle":"all around"}],"monitors":[],"extensions":[],"meta":{"semver":"3.0.0","vm":"1.2.54","agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36"}}
1+
{"targets":[{"isStage":true,"name":"Stage","variables":{"`jEk@4|i[#Fk?(8x)AV.-my variable":["my variable",0]},"lists":{},"broadcasts":{},"blocks":{},"comments":{},"currentCostume":0,"costumes":[{"name":"backdrop1","dataFormat":"svg","assetId":"cd21514d0531fdffb22204e0ec5ed84a","md5ext":"cd21514d0531fdffb22204e0ec5ed84a.svg","rotationCenterX":240,"rotationCenterY":180}],"sounds":[],"volume":100,"layerOrder":0,"tempo":60,"videoTransparency":50,"videoState":"on","textToSpeechLanguage":"en"},{"isStage":false,"name":"Cosmicat","variables":{},"lists":{},"broadcasts":{},"blocks":{"KNkqO#ZRN@fbDVj=M78g":{"opcode":"motion_goto","next":"P/e)A725u]@f}wEHk?.n","parent":"*d+j3M@MRL0)j.{N/{Xq","inputs":{"TO":[1,"crRF9,OquYp)*m]if*h/"]},"fields":{},"shadow":false,"topLevel":false},"crRF9,OquYp)*m]if*h/":{"opcode":"motion_goto_menu","next":null,"parent":"KNkqO#ZRN@fbDVj=M78g","inputs":{},"fields":{"TO":["_random_",null]},"shadow":true,"topLevel":false},"*d+j3M@MRL0)j.{N/{Xq":{"opcode":"control_forever","next":null,"parent":"lG*7*6}d*sQN5:4`{r7[","inputs":{"SUBSTACK":[2,"KNkqO#ZRN@fbDVj=M78g"]},"fields":{},"shadow":false,"topLevel":false},"P/e)A725u]@f}wEHk?.n":{"opcode":"control_wait","next":null,"parent":"KNkqO#ZRN@fbDVj=M78g","inputs":{"DURATION":[1,[5,"0.25"]]},"fields":{},"shadow":false,"topLevel":false},"lG*7*6}d*sQN5:4`{r7[":{"opcode":"event_whenflagclicked","next":"*d+j3M@MRL0)j.{N/{Xq","parent":null,"inputs":{},"fields":{},"shadow":false,"topLevel":true,"x":180,"y":-100}},"comments":{},"currentCostume":0,"costumes":[{"name":"Cosmicat","bitmapResolution":1,"dataFormat":"svg","assetId":"9a4fb3ed82f74f5df24ade1a2aa48920","md5ext":"9a4fb3ed82f74f5df24ade1a2aa48920.svg","rotationCenterX":47.2514000162754,"rotationCenterY":57.860045289335886}],"sounds":[],"volume":100,"layerOrder":1,"visible":true,"x":0,"y":0,"size":100,"direction":90,"draggable":false,"rotationStyle":"all around"}],"monitors":[],"extensions":[],"meta":{"semver":"3.0.0","vm":"1.3.14","agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36"}}

config.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424

2525
# Project file name
2626
# If in test mode, set the Scratch project file to load.
27-
projectFileName: str = "projects/Rotation.sb3"
27+
projectFileName: str = "projects/GtkPauseTest.sb3"
2828

2929
# Download cache size
3030
# Number of recent downloaded projects stored. 0 means infinity.
@@ -40,7 +40,7 @@
4040

4141
# Enable debug messages
4242
# Set whether debug messages (messages to stderr) should be allowed.
43-
enableDebugMessages: bool = True
43+
enableDebugMessages: bool = False
4444

4545
# Enable pygame welcome message
4646
# Enable or disable the "

gui.py

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import gi
2+
from subprocess import PIPE, Popen
3+
from threading import Thread
4+
5+
from queue import Queue, Empty
6+
7+
gi.require_version("Gtk", "3.0")
8+
from gi.repository import Gtk
9+
10+
11+
def enqueue_output(out, queue):
12+
for line in iter(out.readline, b''):
13+
queue.put(line)
14+
out.close()
15+
16+
17+
p = Popen(['python', 'main.py'], stdout=PIPE, stdin=PIPE, bufsize=1, close_fds=True, universal_newlines=True)
18+
q = Queue()
19+
t = Thread(target=enqueue_output, args=(p.stdout, q))
20+
t.daemon = True # thread dies with the program
21+
t.start()
22+
23+
24+
def pause(button):
25+
print("PAUSE", file=p.stdin)
26+
print("PAUSE")
27+
28+
29+
def stop(button):
30+
print("STOP", file=p.stdin)
31+
print("STOP")
32+
33+
34+
handlers = {
35+
"onDestroy": Gtk.main_quit,
36+
"pause": pause,
37+
"stop": stop,
38+
}
39+
40+
builder = Gtk.Builder()
41+
builder.add_from_file("main.glade")
42+
builder.connect_signals(handlers)
43+
44+
window = builder.get_object("test")
45+
window.show_all()
46+
47+
if __name__ == '__main__':
48+
Gtk.main()

MainMenu.glade renamed to main.glade

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,11 @@
323323
</object>
324324
</child>
325325
</object>
326+
<object class="GtkImage" id="aboutIcon1">
327+
<property name="visible">True</property>
328+
<property name="can-focus">False</property>
329+
<property name="icon-name">dialog-information</property>
330+
</object>
326331
<object class="GtkAdjustment" id="cacheSize">
327332
<property name="upper">64</property>
328333
<property name="step-increment">2</property>
@@ -1425,4 +1430,219 @@ on startup.</property>
14251430
</object>
14261431
</child>
14271432
</object>
1433+
<object class="GtkWindow" id="test">
1434+
<property name="can-focus">False</property>
1435+
<child>
1436+
<object class="GtkBox">
1437+
<property name="visible">True</property>
1438+
<property name="can-focus">False</property>
1439+
<property name="margin-start">8</property>
1440+
<property name="margin-end">8</property>
1441+
<property name="margin-top">8</property>
1442+
<property name="margin-bottom">8</property>
1443+
<property name="orientation">vertical</property>
1444+
<child>
1445+
<object class="GtkBox">
1446+
<property name="visible">True</property>
1447+
<property name="can-focus">False</property>
1448+
<property name="orientation">vertical</property>
1449+
<child>
1450+
<object class="GtkLabel">
1451+
<property name="visible">True</property>
1452+
<property name="can-focus">False</property>
1453+
<property name="label" translatable="yes">Test controls</property>
1454+
<property name="xalign">0</property>
1455+
<attributes>
1456+
<attribute name="weight" value="ultralight"/>
1457+
<attribute name="absolute-size" value="28000"/>
1458+
</attributes>
1459+
</object>
1460+
<packing>
1461+
<property name="expand">False</property>
1462+
<property name="fill">True</property>
1463+
<property name="position">0</property>
1464+
</packing>
1465+
</child>
1466+
</object>
1467+
<packing>
1468+
<property name="expand">False</property>
1469+
<property name="fill">True</property>
1470+
<property name="position">0</property>
1471+
</packing>
1472+
</child>
1473+
<child>
1474+
<object class="GtkBox">
1475+
<property name="visible">True</property>
1476+
<property name="can-focus">False</property>
1477+
<property name="halign">center</property>
1478+
<property name="valign">center</property>
1479+
<property name="spacing">8</property>
1480+
<child>
1481+
<object class="GtkButton">
1482+
<property name="width-request">160</property>
1483+
<property name="height-request">128</property>
1484+
<property name="visible">True</property>
1485+
<property name="can-focus">True</property>
1486+
<property name="receives-default">True</property>
1487+
<property name="halign">center</property>
1488+
<property name="valign">center</property>
1489+
<signal name="clicked" handler="pause" swapped="no"/>
1490+
<child>
1491+
<object class="GtkBox">
1492+
<property name="visible">True</property>
1493+
<property name="can-focus">False</property>
1494+
<property name="halign">center</property>
1495+
<property name="valign">center</property>
1496+
<property name="orientation">vertical</property>
1497+
<child>
1498+
<object class="GtkImage">
1499+
<property name="visible">True</property>
1500+
<property name="can-focus">False</property>
1501+
<property name="pixel-size">48</property>
1502+
<property name="icon-name">media-playback-pause</property>
1503+
<property name="icon_size">6</property>
1504+
</object>
1505+
<packing>
1506+
<property name="expand">False</property>
1507+
<property name="fill">True</property>
1508+
<property name="position">0</property>
1509+
</packing>
1510+
</child>
1511+
<child>
1512+
<object class="GtkLabel">
1513+
<property name="visible">True</property>
1514+
<property name="can-focus">False</property>
1515+
<property name="label" translatable="yes">Pause/resume project</property>
1516+
<attributes>
1517+
<attribute name="weight" value="semibold"/>
1518+
</attributes>
1519+
</object>
1520+
<packing>
1521+
<property name="expand">False</property>
1522+
<property name="fill">True</property>
1523+
<property name="position">1</property>
1524+
</packing>
1525+
</child>
1526+
<child>
1527+
<placeholder/>
1528+
</child>
1529+
</object>
1530+
</child>
1531+
</object>
1532+
<packing>
1533+
<property name="expand">False</property>
1534+
<property name="fill">True</property>
1535+
<property name="position">0</property>
1536+
</packing>
1537+
</child>
1538+
<child>
1539+
<object class="GtkButton">
1540+
<property name="width-request">160</property>
1541+
<property name="height-request">128</property>
1542+
<property name="visible">True</property>
1543+
<property name="can-focus">True</property>
1544+
<property name="receives-default">True</property>
1545+
<property name="halign">center</property>
1546+
<property name="valign">center</property>
1547+
<signal name="clicked" handler="stop" swapped="no"/>
1548+
<child>
1549+
<object class="GtkBox">
1550+
<property name="visible">True</property>
1551+
<property name="can-focus">False</property>
1552+
<property name="halign">center</property>
1553+
<property name="valign">center</property>
1554+
<property name="orientation">vertical</property>
1555+
<child>
1556+
<object class="GtkImage">
1557+
<property name="visible">True</property>
1558+
<property name="can-focus">False</property>
1559+
<property name="pixel-size">48</property>
1560+
<property name="icon-name">media-playback-stop</property>
1561+
<property name="icon_size">6</property>
1562+
</object>
1563+
<packing>
1564+
<property name="expand">False</property>
1565+
<property name="fill">True</property>
1566+
<property name="position">0</property>
1567+
</packing>
1568+
</child>
1569+
<child>
1570+
<object class="GtkLabel">
1571+
<property name="visible">True</property>
1572+
<property name="can-focus">False</property>
1573+
<property name="label" translatable="yes">Quit player</property>
1574+
<attributes>
1575+
<attribute name="weight" value="semibold"/>
1576+
</attributes>
1577+
</object>
1578+
<packing>
1579+
<property name="expand">False</property>
1580+
<property name="fill">True</property>
1581+
<property name="position">1</property>
1582+
</packing>
1583+
</child>
1584+
<child>
1585+
<placeholder/>
1586+
</child>
1587+
</object>
1588+
</child>
1589+
</object>
1590+
<packing>
1591+
<property name="expand">False</property>
1592+
<property name="fill">True</property>
1593+
<property name="position">1</property>
1594+
</packing>
1595+
</child>
1596+
</object>
1597+
<packing>
1598+
<property name="expand">True</property>
1599+
<property name="fill">True</property>
1600+
<property name="position">1</property>
1601+
</packing>
1602+
</child>
1603+
<child>
1604+
<object class="GtkBox">
1605+
<property name="visible">True</property>
1606+
<property name="can-focus">False</property>
1607+
<child>
1608+
<object class="GtkLinkButton">
1609+
<property name="label" translatable="yes">Need a GUI for browsing projects on scratch.mit.edu?</property>
1610+
<property name="visible">True</property>
1611+
<property name="can-focus">True</property>
1612+
<property name="receives-default">True</property>
1613+
<property name="relief">none</property>
1614+
<property name="uri">https://example.org</property>
1615+
</object>
1616+
<packing>
1617+
<property name="expand">False</property>
1618+
<property name="fill">True</property>
1619+
<property name="position">0</property>
1620+
</packing>
1621+
</child>
1622+
<child>
1623+
<object class="GtkButton">
1624+
<property name="label" translatable="yes">About</property>
1625+
<property name="visible">True</property>
1626+
<property name="can-focus">True</property>
1627+
<property name="receives-default">True</property>
1628+
<property name="image">aboutIcon1</property>
1629+
<property name="always-show-image">True</property>
1630+
</object>
1631+
<packing>
1632+
<property name="expand">False</property>
1633+
<property name="fill">True</property>
1634+
<property name="pack-type">end</property>
1635+
<property name="position">1</property>
1636+
</packing>
1637+
</child>
1638+
</object>
1639+
<packing>
1640+
<property name="expand">False</property>
1641+
<property name="fill">True</property>
1642+
<property name="position">2</property>
1643+
</packing>
1644+
</child>
1645+
</object>
1646+
</child>
1647+
</object>
14281648
</interface>

main.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
along with this program. If not, see <https://www.gnu.org/licenses/>.
2020
"""
2121

22-
__version__ = "v0.7.0"
22+
__version__ = "v0.8.0"
2323
__author__ = "Secret-chest"
2424

2525
import tkinter.simpledialog
@@ -74,6 +74,7 @@
7474
from tkinter import filedialog
7575
from targetSprite import TargetSprite
7676
import eventContainer
77+
import select
7778

7879
sys.stdout = sys.__stdout__
7980

@@ -242,6 +243,15 @@ def buttonbox(self):
242243
# Mainloop
243244
lastTime = time.time_ns()
244245
while projectRunning:
246+
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
247+
if rlist:
248+
line = sys.stdin.readline().strip()
249+
if line:
250+
if line.startswith("STOP"):
251+
pygame.quit()
252+
elif line.startswith("PAUSE"):
253+
isPaused = not isPaused
254+
245255
keyEventContainer.keyEvents = set()
246256
# Process Pygame events
247257
for event in pygame.event.get():

projects/GtkPauseTest.sb3

12.2 KB
Binary file not shown.

projects/Rotation2.sb3

-621 Bytes
Binary file not shown.

projects/WaitUntil.sb3

27.3 KB
Binary file not shown.

scratch.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,16 @@ def execute(block, s, events=eventContainer.EventContainer()):
221221
print(_("debug-prefix"), _("block-waiting", time=block.timeDelay), file=sys.stderr)
222222
return block
223223

224+
elif opcode == "control_wait_until": # wait until <>
225+
block.screenRefresh = True
226+
truth = block.target.blocks[inputs["CONDITION"][1]].evaluateBlockValue(events)
227+
if truth:
228+
block.blockRan = True
229+
nextBlock = s.target.blocks[block.next]
230+
return nextBlock
231+
else:
232+
return block
233+
224234
elif opcode == "event_whenflagclicked": # when green flag clicked
225235
pass
226236

targetSprite.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,9 @@ def setXyDelta(self, dx, dy):
102102
def setRot(self, rot):
103103
self.direction = rot
104104
print(_("debug-prefix"), _("new-sprite-rotation", rot=rot, name=self.name), file=sys.stderr)
105-
self.sprite = self.image
106-
self.sprite = pygame.transform.rotate(self.sprite, 90 - self.direction)
107-
self.rect = self.sprite.get_rect(center=self.rect.center)
105+
center = self.sprite.get_rect().center
106+
self.sprite = pygame.transform.rotate(self.image, 90 - self.direction)
107+
self.rect = self.sprite.get_rect(center=center)
108108

109109
# Relatively set self rotation (turn)
110110
def setRotDelta(self, drot):

0 commit comments

Comments
 (0)