Skip to content

Commit e83211c

Browse files
committed
pixel editor, more pixel shit
1 parent b7a44e8 commit e83211c

8 files changed

Lines changed: 364 additions & 14 deletions

File tree

1.11 KB
Binary file not shown.
9.43 KB
Binary file not shown.

bscript-gui.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import os
55
import tempfile
66
import subprocess
7+
import pixeleditor
78

89
def transpile_code():
910
code = code_input.get("1.0", tk.END)
@@ -115,12 +116,15 @@ def compile_code():
115116
messagebox.showwarning("Compile Not Supported", f"Compile not supported for language: {lang}")
116117

117118

119+
118120
root = tk.Tk()
119121
root.title("BScript Compiler GUI")
120122

121123
icon = tk.PhotoImage(file="assets/icon.png")
122124
root.iconphoto(True, icon)
123125

126+
tk.Button(root, text="Pixel Editor (Beta)", command=pixeleditor.pixelEditor).pack(pady=5)
127+
tk.Label(root, text="It is not recommended to write code using this editor,\nuse an actual IDE for that!").pack(pady=10)
124128
tk.Button(root, text="Load BScript File", command=load_bs_file).pack(pady=5)
125129

126130
tk.Label(root, text="BScript Code:").pack(anchor="w")

compiler.py

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,8 @@ def transpile(self, code: str, lang: str = "c") -> str:
318318
window_width = 640
319319
window_height = 480
320320
window_title = "BScript Window"
321+
rect = False # Track if rect command was used
322+
rects = 0
321323

322324
i = 0
323325
while i < len(lines):
@@ -560,18 +562,42 @@ def transpile(self, code: str, lang: str = "c") -> str:
560562
continue
561563

562564
# Pixel drawing command
563-
m = re.match(r'pixel\s+(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+);', line)
565+
m = re.match(r'pixel\s+(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+);', line)
564566
if m:
565-
x, y, r, g, b = map(int, m.groups())
566-
draw_code = [
567-
f'{self.indent()}SDL_SetRenderDrawColor(renderer, {r}, {g}, {b}, 255);',
568-
f'{self.indent()}SDL_Rect rect = {{ {x} * 3, {y} * 3, 3, 3 }};',
569-
f'{self.indent()}SDL_RenderFillRect(renderer, &rect);'
570-
]
571-
if self.in_function:
572-
self.c_lines.extend(draw_code)
567+
if windowed:
568+
x, y, r, g, b, s = map(int, m.groups())
569+
rects += 1
570+
draw_code = [
571+
f'{self.indent()}SDL_SetRenderDrawColor(renderer, {r}, {g}, {b}, 255);',
572+
f'{self.indent()}SDL_Rect rect{rects} = {{ {x} * {s}, {y} * {s}, {s}, {s} }};',
573+
f'{self.indent()}SDL_RenderFillRect(renderer, &rect{rects});'
574+
]
575+
if self.in_function:
576+
self.c_lines.extend(draw_code)
577+
else:
578+
self.draw_code.extend(draw_code)
579+
else:
580+
raise Exception("Cannot use 'pixel' without first creating a window using the 'window;' command.")
581+
i += 1
582+
continue
583+
584+
# rect command
585+
m = re.match(r'rect\s+(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+);', line)
586+
if m:
587+
if windowed:
588+
x, y, wx, wy, r, g, b = map(int, m.groups())
589+
rects += 1
590+
draw_code = [
591+
f'{self.indent()}SDL_SetRenderDrawColor(renderer, {r}, {g}, {b}, 255);',
592+
f'{self.indent()}SDL_Rect rect{rects} = {{ {x}, {y}, {wx}, {wy} }};',
593+
f'{self.indent()}SDL_RenderFillRect(renderer, &rect{rects});'
594+
]
595+
if self.in_function:
596+
self.c_lines.extend(draw_code)
597+
else:
598+
self.draw_code.extend(draw_code)
573599
else:
574-
self.draw_code.extend(draw_code)
600+
raise Exception("Cannot use 'rect' without first creating a window using the 'window;' command.")
575601
i += 1
576602
continue
577603

@@ -608,11 +634,11 @@ def transpile(self, code: str, lang: str = "c") -> str:
608634
width = int(m.group(1))
609635
height = int(m.group(2))
610636

611-
if not (0 <= width <= 255) or not (0 <= height <= 255):
612-
raise Exception(f"Invalid window size: {width}x{height}. Each dimension must be between 0 and 255 pixels.")
637+
if not (0 <= width) or not (0 <= height):
638+
raise Exception(f"Invalid window size: {width}x{height}. Each dimension must be above 0 pixels.")
613639

614-
window_width = width*3
615-
window_height = height*3
640+
window_width = width
641+
window_height = height
616642
i += 1
617643
continue
618644

exported_pixels.bs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Exported pixel data from Pixel Editor
2+
3+
windowSize 640,640;
4+
window;
5+
6+
pixel 1,0,255,255,0,80;
7+
pixel 2,0,255,255,0,80;
8+
pixel 3,0,255,255,0,80;
9+
pixel 4,0,255,255,0,80;
10+
pixel 5,0,255,255,0,80;
11+
pixel 6,0,255,255,0,80;
12+
pixel 0,1,255,255,0,80;
13+
pixel 1,1,255,255,0,80;
14+
pixel 3,1,255,255,0,80;
15+
pixel 4,1,255,255,0,80;
16+
pixel 6,1,255,255,0,80;
17+
pixel 7,1,255,255,0,80;
18+
pixel 0,2,255,255,0,80;
19+
pixel 1,2,255,255,0,80;
20+
pixel 3,2,255,255,0,80;
21+
pixel 4,2,255,255,0,80;
22+
pixel 6,2,255,255,0,80;
23+
pixel 7,2,255,255,0,80;
24+
pixel 0,3,255,255,0,80;
25+
pixel 1,3,255,255,0,80;
26+
pixel 3,3,255,255,0,80;
27+
pixel 4,3,255,255,0,80;
28+
pixel 6,3,255,255,0,80;
29+
pixel 7,3,255,255,0,80;
30+
pixel 0,4,255,255,0,80;
31+
pixel 2,4,255,255,0,80;
32+
pixel 3,4,255,255,0,80;
33+
pixel 4,4,255,255,0,80;
34+
pixel 5,4,255,255,0,80;
35+
pixel 7,4,255,255,0,80;
36+
pixel 0,5,255,255,0,80;
37+
pixel 1,5,255,255,0,80;
38+
pixel 6,5,255,255,0,80;
39+
pixel 7,5,255,255,0,80;
40+
pixel 0,6,255,255,0,80;
41+
pixel 1,6,255,255,0,80;
42+
pixel 2,6,255,255,0,80;
43+
pixel 3,6,255,255,0,80;
44+
pixel 4,6,255,255,0,80;
45+
pixel 5,6,255,255,0,80;
46+
pixel 6,6,255,255,0,80;
47+
pixel 7,6,255,255,0,80;
48+
pixel 1,7,255,255,0,80;
49+
pixel 2,7,255,255,0,80;
50+
pixel 3,7,255,255,0,80;
51+
pixel 4,7,255,255,0,80;
52+
pixel 5,7,255,255,0,80;
53+
pixel 6,7,255,255,0,80;

pixeleditor.py

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
import pygame
2+
import pygame_gui
3+
4+
def pixelEditor():
5+
class PixelEditor:
6+
def __init__(self, screen, manager):
7+
self.manager = manager
8+
self.screen = screen
9+
self.scale = 1
10+
self.pixelscale = 1
11+
self.grid_size = 8
12+
self.color = (255, 0, 0)
13+
14+
self.pixel_size = 80 # initial: 640 / 8 = 80
15+
self.grid_width = self.grid_height = self.grid_size
16+
self.pixels = [[(0, 0, 0) for _ in range(self.grid_width)] for _ in range(self.grid_height)]
17+
18+
self.setup_ui()
19+
20+
def setup_ui(self):
21+
self.r_slider = pygame_gui.elements.UIHorizontalSlider(
22+
relative_rect=pygame.Rect((10, 660), (200, 20)),
23+
start_value=255, value_range=(0, 255), manager=self.manager
24+
)
25+
self.g_slider = pygame_gui.elements.UIHorizontalSlider(
26+
relative_rect=pygame.Rect((10, 690), (200, 20)),
27+
start_value=0, value_range=(0, 255), manager=self.manager
28+
)
29+
self.b_slider = pygame_gui.elements.UIHorizontalSlider(
30+
relative_rect=pygame.Rect((10, 720), (200, 20)),
31+
start_value=0, value_range=(0, 255), manager=self.manager
32+
)
33+
34+
self.color_preview = pygame_gui.elements.UIPanel(
35+
relative_rect=pygame.Rect((220, 660), (60, 80)),
36+
starting_height=1, manager=self.manager
37+
)
38+
39+
self.scale_dropdown = pygame_gui.elements.UIDropDownMenu(
40+
options_list=["1x", "2x", "3x"],
41+
starting_option="1x",
42+
relative_rect=pygame.Rect((300, 660), (100, 30)),
43+
manager=self.manager
44+
)
45+
46+
self.scale_input = pygame_gui.elements.UITextEntryLine(
47+
relative_rect=pygame.Rect((410, 660), (50, 30)),
48+
manager=self.manager
49+
)
50+
self.scale_input.set_text("1")
51+
self.scale_input.set_allowed_characters("0123456789")
52+
def update_color(self):
53+
self.color = (
54+
int(self.r_slider.get_current_value()),
55+
int(self.g_slider.get_current_value()),
56+
int(self.b_slider.get_current_value())
57+
)
58+
59+
def update_preview(self):
60+
preview_surface = pygame.Surface((60, 80))
61+
preview_surface.fill(self.color)
62+
self.color_preview.set_image(preview_surface)
63+
64+
def draw(self):
65+
for y, row in enumerate(self.pixels):
66+
for x, color in enumerate(row):
67+
pygame.draw.rect(
68+
self.screen, color,
69+
(x * self.pixel_size, y * self.pixel_size,
70+
self.pixel_size, self.pixel_size)
71+
)
72+
73+
def edit_pixel(self, pos):
74+
x, y = pos
75+
pixel_x = x // self.pixel_size
76+
pixel_y = y // self.pixel_size
77+
if 0 <= pixel_x < self.grid_width and 0 <= pixel_y < self.grid_height:
78+
self.pixels[pixel_y][pixel_x] = self.color
79+
80+
def export_to_bs(self, filename="exported_pixels.bs"):
81+
with open(filename, "w") as f:
82+
f.write("// Exported pixel data from Pixel Editor\n\nwindowSize = 8,8;\nwindow;\n\n")
83+
s = self.pixel_size
84+
for y in range(self.grid_height):
85+
for x in range(self.grid_width):
86+
r, g, b = self.pixels[y][x]
87+
if (r, g, b) != (0, 0, 0):
88+
f.write(f"pixel {x},{y},{r},{g},{b},{s};\n")
89+
print(f"Exported to {filename}")
90+
91+
def change_scale(self, factor):
92+
self.scale = int(factor[0])
93+
new_size = 640 * self.scale
94+
pygame.display.set_mode((new_size, 800))
95+
self.pixel_size = new_size // self.grid_size
96+
97+
def changePixelScale(self, factor):
98+
self.pixelscale = self.scale_input.get_text()
99+
if self.pixelscale.isdigit():
100+
self.pixelscale = int(self.pixelscale)
101+
if self.pixelscale < 1:
102+
self.pixelscale = 1
103+
104+
105+
# Setup
106+
pygame.init()
107+
screen = pygame.display.set_mode((640, 800))
108+
pygame.display.set_caption("Pixel Editor for BScript (Beta)")
109+
clock = pygame.time.Clock()
110+
manager = pygame_gui.UIManager((640, 800))
111+
editor = PixelEditor(screen, manager)
112+
running = True
113+
114+
while running:
115+
time_delta = clock.tick(60) / 1000.0
116+
for event in pygame.event.get():
117+
if event.type == pygame.QUIT:
118+
running = False
119+
120+
elif event.type == pygame.MOUSEBUTTONDOWN:
121+
if event.button == 1 and event.pos[1] < 640 * editor.scale:
122+
editor.edit_pixel(event.pos)
123+
124+
elif event.type == pygame.KEYDOWN:
125+
if event.key == pygame.K_s:
126+
editor.export_to_bs()
127+
128+
elif event.type == pygame_gui.UI_DROP_DOWN_MENU_CHANGED:
129+
if event.ui_element == editor.scale_dropdown:
130+
editor.change_scale(event.text)
131+
132+
manager.process_events(event)
133+
134+
editor.update_color()
135+
editor.update_preview()
136+
137+
screen.fill((30, 30, 30))
138+
editor.draw()
139+
manager.update(time_delta)
140+
manager.draw_ui(screen)
141+
pygame.display.flip()
142+
143+
pygame.quit()

tests/sprites.bs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//This code is generated by pixelsetup.py
2+
//It creates variables for 64 pixels with alternating colors
3+
//You can copy this code into your BScript file to use the pixel variables
4+
5+
pixel 0, 0, 255, 255, 255;
6+
pixel 1, 1, 255, 0, 0;
7+
pixel 2, 2, 255, 255, 255;
8+
pixel 3, 3, 255, 0, 0;
9+
pixel 4, 4, 255, 255, 255;
10+
pixel 5, 5, 255, 0, 0;
11+
pixel 6, 6, 255, 255, 255;
12+
pixel 7, 7, 255, 0, 0;
13+
pixel 8, 8, 255, 255, 255;
14+
pixel 9, 9, 255, 0, 0;
15+
pixel 10, 10, 255, 255, 255;
16+
pixel 11, 11, 255, 0, 0;
17+
pixel 12, 12, 255, 255, 255;
18+
pixel 13, 13, 255, 0, 0;
19+
pixel 14, 14, 255, 255, 255;
20+
pixel 15, 15, 255, 0, 0;
21+
pixel 16, 16, 255, 255, 255;
22+
pixel 17, 17, 255, 0, 0;
23+
pixel 18, 18, 255, 255, 255;
24+
pixel 19, 19, 255, 0, 0;
25+
pixel 20, 20, 255, 255, 255;
26+
pixel 21, 21, 255, 0, 0;
27+
pixel 22, 22, 255, 255, 255;
28+
pixel 23, 23, 255, 0, 0;
29+
pixel 24, 24, 255, 255, 255;
30+
pixel 25, 25, 255, 0, 0;
31+
pixel 26, 26, 255, 255, 255;
32+
pixel 27, 27, 255, 0, 0;
33+
pixel 28, 28, 255, 255, 255;
34+
pixel 29, 29, 255, 0, 0;
35+
pixel 30, 30, 255, 255, 255;
36+
pixel 31, 31, 255, 0, 0;
37+
pixel 32, 32, 255, 255, 255;
38+
pixel 33, 33, 255, 0, 0;
39+
pixel 34, 34, 255, 255, 255;
40+
pixel 35, 35, 255, 0, 0;
41+
pixel 36, 36, 255, 255, 255;
42+
pixel 37, 37, 255, 0, 0;
43+
pixel 38, 38, 255, 255, 255;
44+
pixel 39, 39, 255, 0, 0;
45+
pixel 40, 40, 255, 255, 255;
46+
pixel 41, 41, 255, 0, 0;
47+
pixel 42, 42, 255, 255, 255;
48+
pixel 43, 43, 255, 0, 0;
49+
pixel 44, 44, 255, 255, 255;
50+
pixel 45, 45, 255, 0, 0;
51+
pixel 46, 46, 255, 255, 255;
52+
pixel 47, 47, 255, 0, 0;
53+
pixel 48, 48, 255, 255, 255;
54+
pixel 49, 49, 255, 0, 0;
55+
pixel 50, 50, 255, 255, 255;
56+
pixel 51, 51, 255, 0, 0;
57+
pixel 52, 52, 255, 255, 255;
58+
pixel 53, 53, 255, 0, 0;
59+
pixel 54, 54, 255, 255, 255;
60+
pixel 55, 55, 255, 0, 0;
61+
pixel 56, 56, 255, 255, 255;
62+
pixel 57, 57, 255, 0, 0;
63+
pixel 58, 58, 255, 255, 255;
64+
pixel 59, 59, 255, 0, 0;
65+
pixel 60, 60, 255, 255, 255;
66+
pixel 61, 61, 255, 0, 0;
67+
pixel 62, 62, 255, 255, 255;
68+
pixel 63, 63, 255, 0, 0;

0 commit comments

Comments
 (0)