pyscratch-pysc 1.0.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- assets/bullet_hell/enemy.py +130 -0
- assets/bullet_hell/enemy_bullets.py +230 -0
- assets/bullet_hell/main.py +11 -0
- assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
- assets/bullet_hell/old_verisons/enemy.py +226 -0
- assets/bullet_hell/old_verisons/game_start.py +6 -0
- assets/bullet_hell/old_verisons/main.py +50 -0
- assets/bullet_hell/old_verisons/player.py +76 -0
- assets/bullet_hell/player.py +89 -0
- assets/bullet_hell/player_bullets.py +34 -0
- assets/bullet_hell/setting.py +33 -0
- examples/animated_sprite/main.py +7 -0
- examples/animated_sprite/my_sprite.py +79 -0
- examples/bullet_hell/enemy.py +152 -0
- examples/bullet_hell/enemy_bullet.py +88 -0
- examples/bullet_hell/main.py +17 -0
- examples/bullet_hell/player.py +39 -0
- examples/bullet_hell/player_bullet.py +31 -0
- examples/doodle_jump/main.py +9 -0
- examples/doodle_jump/platforms.py +51 -0
- examples/doodle_jump/player.py +52 -0
- examples/fish/assets/bullet_hell/enemy.py +130 -0
- examples/fish/assets/bullet_hell/enemy_bullets.py +230 -0
- examples/fish/assets/bullet_hell/main.py +11 -0
- examples/fish/assets/bullet_hell/old_verisons/bullet_hell.py +379 -0
- examples/fish/assets/bullet_hell/old_verisons/enemy.py +226 -0
- examples/fish/assets/bullet_hell/old_verisons/game_start.py +6 -0
- examples/fish/assets/bullet_hell/old_verisons/main.py +50 -0
- examples/fish/assets/bullet_hell/old_verisons/player.py +76 -0
- examples/fish/assets/bullet_hell/player.py +89 -0
- examples/fish/assets/bullet_hell/player_bullets.py +34 -0
- examples/fish/assets/bullet_hell/setting.py +33 -0
- examples/fish/fish.py +67 -0
- examples/fish/main.py +4 -0
- examples/getting-started/step 1 - create a sprite/main.py +11 -0
- examples/getting-started/step 1 - create a sprite/player.py +5 -0
- examples/getting-started/step 2 - control a sprite/main.py +11 -0
- examples/getting-started/step 2 - control a sprite/player.py +42 -0
- examples/getting-started/step 3 - backdrops/main.py +17 -0
- examples/getting-started/step 3 - backdrops/player.py +33 -0
- examples/getting-started/step 4 - clone a sprite/enemy.py +53 -0
- examples/getting-started/step 4 - clone a sprite/main.py +17 -0
- examples/getting-started/step 4 - clone a sprite/player.py +32 -0
- examples/getting-started/step 4 - clone a sprite (simple)/enemy.py +42 -0
- examples/getting-started/step 4 - clone a sprite (simple)/main.py +17 -0
- examples/getting-started/step 4 - clone a sprite (simple)/player.py +32 -0
- examples/getting-started/step 5 - local variables/enemy.py +52 -0
- examples/getting-started/step 5 - local variables/main.py +17 -0
- examples/getting-started/step 5 - local variables/player.py +49 -0
- examples/getting-started/step 6 - shared variables/enemy.py +64 -0
- examples/getting-started/step 6 - shared variables/main.py +17 -0
- examples/getting-started/step 6 - shared variables/player.py +80 -0
- examples/getting-started/step 7 - Referencing other sprites/enemy.py +83 -0
- examples/getting-started/step 7 - Referencing other sprites/hearts.py +39 -0
- examples/getting-started/step 7 - Referencing other sprites/main.py +23 -0
- examples/getting-started/step 7 - Referencing other sprites/player.py +59 -0
- examples/getting-started/step 8 - sprite variables/enemy.py +98 -0
- examples/getting-started/step 8 - sprite variables/hearts.py +39 -0
- examples/getting-started/step 8 - sprite variables/main.py +22 -0
- examples/getting-started/step 8 - sprite variables/player.py +63 -0
- examples/getting-started/step 9 - messages/enemy.py +98 -0
- examples/getting-started/step 9 - messages/hearts.py +39 -0
- examples/getting-started/step 9 - messages/main.py +23 -0
- examples/getting-started/step 9 - messages/player.py +78 -0
- examples/perspective_background/main.py +14 -0
- examples/perspective_background/player.py +52 -0
- examples/perspective_background/trees.py +39 -0
- examples/simple_pong/ball.py +72 -0
- examples/simple_pong/left_paddle.py +36 -0
- examples/simple_pong/main.py +21 -0
- examples/simple_pong/right_paddle.py +37 -0
- examples/simple_pong/score_display.py +54 -0
- pyscratch/__init__.py +48 -0
- pyscratch/event.py +263 -0
- pyscratch/game_module.py +1589 -0
- pyscratch/helper.py +561 -0
- pyscratch/sprite.py +1920 -0
- pyscratch/tools/sprite_preview/left_panel/frame_preview_card.py +238 -0
- pyscratch/tools/sprite_preview/left_panel/frame_preview_panel.py +42 -0
- pyscratch/tools/sprite_preview/main.py +18 -0
- pyscratch/tools/sprite_preview/main_panel/animation_display.py +77 -0
- pyscratch/tools/sprite_preview/main_panel/frame_bin.py +33 -0
- pyscratch/tools/sprite_preview/main_panel/play_edit_ui.py +64 -0
- pyscratch/tools/sprite_preview/main_panel/set_as_sprite_folder.py +22 -0
- pyscratch/tools/sprite_preview/main_panel/sprite_edit_ui.py +174 -0
- pyscratch/tools/sprite_preview/main_panel/warning_message.py +25 -0
- pyscratch/tools/sprite_preview/right_panel/back_button.py +35 -0
- pyscratch/tools/sprite_preview/right_panel/cut_button.py +32 -0
- pyscratch/tools/sprite_preview/right_panel/cut_parameter_fitting.py +152 -0
- pyscratch/tools/sprite_preview/right_panel/cut_parameters.py +42 -0
- pyscratch/tools/sprite_preview/right_panel/file_display.py +84 -0
- pyscratch/tools/sprite_preview/right_panel/file_display_area.py +57 -0
- pyscratch/tools/sprite_preview/right_panel/spritesheet_view.py +262 -0
- pyscratch/tools/sprite_preview/right_panel/ss_select_corner.py +208 -0
- pyscratch/tools/sprite_preview/settings.py +14 -0
- pyscratch/tools/sprite_preview/utils/input_box.py +235 -0
- pyscratch/tools/sprite_preview/utils/render_wrapped_file_name.py +86 -0
- pyscratch_pysc-1.0.3.dist-info/METADATA +37 -0
- pyscratch_pysc-1.0.3.dist-info/RECORD +101 -0
- pyscratch_pysc-1.0.3.dist-info/WHEEL +5 -0
- pyscratch_pysc-1.0.3.dist-info/top_level.txt +3 -0
@@ -0,0 +1,35 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import List, Tuple
|
3
|
+
import pyscratch as pysc
|
4
|
+
from pyscratch.sprite import Sprite
|
5
|
+
from settings import *
|
6
|
+
from .file_display import FileDisplay
|
7
|
+
w, h = 50*1.62, 50
|
8
|
+
colour = (127, 127, 127)
|
9
|
+
button = pysc.create_rect_sprite(colour, w, h)
|
10
|
+
button.set_xy((900, 550))
|
11
|
+
pysc.game.change_layer(button, 1)
|
12
|
+
|
13
|
+
#button.when_game_start().add_handler(lambda: button.lock_to(pysc.game.shared_data['folder_navigation'], offset=(0,0)))
|
14
|
+
|
15
|
+
|
16
|
+
|
17
|
+
def on_click():
|
18
|
+
if pysc.game.shared_data['cut_or_nav_mode'] == 'nav':
|
19
|
+
pysc.game.broadcast_message('back_nav', None)
|
20
|
+
else:
|
21
|
+
#pysc.game.broadcast_message('cut', None)
|
22
|
+
pysc.game.broadcast_message('cut_or_nav_mode_change', 'nav')
|
23
|
+
|
24
|
+
button.when_this_sprite_clicked().add_handler(on_click)
|
25
|
+
|
26
|
+
|
27
|
+
def on_msg_mode_change(mode):
|
28
|
+
pysc.game.shared_data['cut_or_nav_mode'] = mode
|
29
|
+
if mode == 'nav':
|
30
|
+
button.write_text("Back", DEFAULT_FONT24, offset=(w/2, h/2))
|
31
|
+
else:
|
32
|
+
button.write_text("Back", DEFAULT_FONT24, offset=(w/2, h/2))
|
33
|
+
|
34
|
+
|
35
|
+
button.when_receive_message('cut_or_nav_mode_change').add_handler(on_msg_mode_change)
|
@@ -0,0 +1,32 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import List, Tuple
|
3
|
+
import pyscratch as pysc
|
4
|
+
from pyscratch.sprite import Sprite
|
5
|
+
from settings import *
|
6
|
+
from .file_display import FileDisplay
|
7
|
+
w, h = 50*1.62, 50
|
8
|
+
colour = (127, 127, 127)
|
9
|
+
button = pysc.create_rect_sprite(colour, w, h)
|
10
|
+
button.set_xy((1100, 550))
|
11
|
+
pysc.game.change_layer(button, 1)
|
12
|
+
|
13
|
+
def on_click():
|
14
|
+
if pysc.game.shared_data['cut_or_nav_mode'] == 'nav':
|
15
|
+
#pysc.game.broadcast_message('cut_or_nav_mode_change', 'cut')
|
16
|
+
pass
|
17
|
+
else:
|
18
|
+
pysc.game.broadcast_message('cut', None)
|
19
|
+
#pysc.game.broadcast_message('cut_or_nav_mode_change', 'nav')
|
20
|
+
|
21
|
+
button.when_this_sprite_clicked().add_handler(on_click)
|
22
|
+
|
23
|
+
|
24
|
+
def on_msg_mode_change(mode):
|
25
|
+
pysc.game.shared_data['cut_or_nav_mode'] = mode
|
26
|
+
if mode == 'nav':
|
27
|
+
button.write_text("...", DEFAULT_FONT24, offset=(w/2, h/2))
|
28
|
+
else:
|
29
|
+
button.write_text("Cut", DEFAULT_FONT24, offset=(w/2, h/2))
|
30
|
+
|
31
|
+
|
32
|
+
button.when_receive_message('cut_or_nav_mode_change').add_handler(on_msg_mode_change)
|
@@ -0,0 +1,152 @@
|
|
1
|
+
import pygame
|
2
|
+
import numpy as np
|
3
|
+
from settings import *
|
4
|
+
import pyscratch as pysc
|
5
|
+
game = pysc.game
|
6
|
+
xpos2 = 1050
|
7
|
+
|
8
|
+
|
9
|
+
w, h = 50*1.62, 40
|
10
|
+
colour = (255, 127, 127)
|
11
|
+
button = pysc.create_rect_sprite(colour, w, h)
|
12
|
+
button.set_xy((1200, 650))
|
13
|
+
button.write_text("Fit", DEFAULT_FONT24, offset=(w/2, h/2))
|
14
|
+
pysc.game.change_layer(button, 1)
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
def on_click():
|
19
|
+
if not 'image_on_right_display' in pysc.game.shared_data:
|
20
|
+
pysc.game.broadcast_message('warning', 'image not selected' )
|
21
|
+
return
|
22
|
+
|
23
|
+
if game['offset_x'] is None: return
|
24
|
+
if game['offset_y'] is None: return
|
25
|
+
if game['size_x'] is None: return
|
26
|
+
if game['size_y'] is None: return
|
27
|
+
|
28
|
+
|
29
|
+
img: pygame.Surface = game['image_on_right_display']
|
30
|
+
|
31
|
+
|
32
|
+
fitter = ParamsFitter(img)
|
33
|
+
|
34
|
+
n_col, pixel_x, offset_x = fitter.find_best_x(game['offset_x'], game['limit_x'])
|
35
|
+
n_row, pixel_y, offset_y = fitter.find_best_y(game['offset_y'], game['limit_y'])
|
36
|
+
|
37
|
+
if (n_col and pixel_x and (not offset_x is None)):
|
38
|
+
game['n_col'] = n_col
|
39
|
+
game['pixel_x'] = pixel_x
|
40
|
+
game['offset_x'] = offset_x
|
41
|
+
game['size_x'] = min(game['limit_x'] - game['offset_x']+1, game['size_x'])
|
42
|
+
|
43
|
+
if (n_row and pixel_y and (not offset_y is None)):
|
44
|
+
game['n_row'] = n_row
|
45
|
+
game['pixel_y'] = pixel_y
|
46
|
+
game['offset_y'] = offset_y
|
47
|
+
game['offset_y'] = offset_y
|
48
|
+
game['size_y'] = min(game['limit_y'] - game['offset_y']+1, game['size_y'])
|
49
|
+
|
50
|
+
|
51
|
+
#game.broadcast_message('n_row_change')
|
52
|
+
#game.broadcast_message('n_col_change')
|
53
|
+
|
54
|
+
#game.broadcast_message('pixel_x_change')
|
55
|
+
|
56
|
+
#game.broadcast_message('pixel_y_change')
|
57
|
+
|
58
|
+
#game.broadcast_message('offset_x_change')
|
59
|
+
#game.broadcast_message('offset_y_change')
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
button.when_this_sprite_clicked().add_handler(on_click)
|
65
|
+
|
66
|
+
from itertools import product
|
67
|
+
class ParamsFitter:
|
68
|
+
|
69
|
+
def __init__(self, surface):
|
70
|
+
|
71
|
+
self.surface = surface
|
72
|
+
self.arr = pygame.surfarray.pixels_alpha(surface)
|
73
|
+
|
74
|
+
self.yslits = ParamsFitter.get_slit_values(self.arr.mean(0))
|
75
|
+
self.xslits = ParamsFitter.get_slit_values(self.arr.mean(1))
|
76
|
+
|
77
|
+
def num_frames_x(self, offset, limit):
|
78
|
+
# TODO: think about it: is the boundary correct?
|
79
|
+
return ParamsFitter.get_num_frames(self.xslits[offset: limit+2])
|
80
|
+
|
81
|
+
def num_frames_y(self, offset, limit):
|
82
|
+
return ParamsFitter.get_num_frames(self.yslits[offset: limit+2])
|
83
|
+
|
84
|
+
def find_best_x(self, offset_centre: int, limit:int):
|
85
|
+
offset_centre = int(offset_centre)
|
86
|
+
limit = int(limit)
|
87
|
+
|
88
|
+
return ParamsFitter.search_best(self.xslits[: limit+2], offset_centre)
|
89
|
+
|
90
|
+
def find_best_y(self, offset_centre: int, limit:int):
|
91
|
+
offset_centre = int(offset_centre)
|
92
|
+
limit = int(limit)
|
93
|
+
return ParamsFitter.search_best(self.yslits[: limit+2], offset_centre)
|
94
|
+
|
95
|
+
@staticmethod
|
96
|
+
def search_best(slit_values, centre_offset, step_range_ratio=0.1, offset_range_ratio=0.1):
|
97
|
+
#print(len(slit_values))
|
98
|
+
n_frame = int(ParamsFitter.get_num_frames(slit_values[centre_offset:]))
|
99
|
+
print(ParamsFitter.get_num_frames_rank(slit_values[centre_offset:]))
|
100
|
+
|
101
|
+
# TODO: possibly DIV BY ZERO?
|
102
|
+
step_size = max(1, (len(slit_values[centre_offset:])-1)/n_frame )
|
103
|
+
|
104
|
+
step_range = round(step_size*step_range_ratio)
|
105
|
+
offset_range = round(step_size*offset_range_ratio)
|
106
|
+
|
107
|
+
step_size = round(step_size)
|
108
|
+
|
109
|
+
# TODO: very easy to go out of boundary
|
110
|
+
step_sizes = range(step_size+step_range+1, max(0, step_size-step_range), -1)
|
111
|
+
offsets = range(max(0,centre_offset-offset_range), centre_offset+offset_range+1)
|
112
|
+
|
113
|
+
vmin = np.inf
|
114
|
+
best_ss = None
|
115
|
+
best_os = None
|
116
|
+
for ss, os in product(step_sizes, offsets):
|
117
|
+
|
118
|
+
n, v = ParamsFitter.eval_cut(slit_values, ss, os)
|
119
|
+
#print(f"trying: pixel_sz:{ss}, offset:{os} -> {n, v}")
|
120
|
+
if not n == n_frame: continue
|
121
|
+
if v < vmin:
|
122
|
+
best_ss = ss
|
123
|
+
best_os = os
|
124
|
+
vmin = v
|
125
|
+
#print(ss, os, v)
|
126
|
+
|
127
|
+
|
128
|
+
|
129
|
+
print(f"n_frame: {n_frame}, pixel_sz:{best_ss}, offset:{best_os} -> {vmin}")
|
130
|
+
return n_frame, best_ss, best_os
|
131
|
+
|
132
|
+
@staticmethod
|
133
|
+
def get_num_frames(slit_values):
|
134
|
+
return np.argmax(np.abs(np.fft.fft(slit_values))[1:len(slit_values)//2])+1
|
135
|
+
|
136
|
+
@staticmethod
|
137
|
+
def get_num_frames_rank(slit_values):
|
138
|
+
return np.argsort(np.abs(np.fft.fft(slit_values))[1:len(slit_values)//2])+1
|
139
|
+
|
140
|
+
|
141
|
+
@staticmethod
|
142
|
+
def get_rough_est_num_pixel(slit_values):
|
143
|
+
return (len(slit_values)-1)/ParamsFitter.get_num_frames(slit_values)
|
144
|
+
|
145
|
+
@staticmethod
|
146
|
+
def eval_cut(slit_values, step_size, offset=0):
|
147
|
+
cut_indices = np.arange(offset, len(slit_values), step_size)
|
148
|
+
return len(cut_indices)-1, slit_values[cut_indices].mean()
|
149
|
+
|
150
|
+
@staticmethod
|
151
|
+
def get_slit_values(axis_mean):
|
152
|
+
return np.r_[[0], (axis_mean[1:]+axis_mean[:-1]), [0]]
|
@@ -0,0 +1,42 @@
|
|
1
|
+
from utils.input_box import IntegerInputBox, FloatInputBoxHoriLabel
|
2
|
+
import pyscratch as pysc
|
3
|
+
from settings import *
|
4
|
+
|
5
|
+
xpos1 = 830
|
6
|
+
xpos2 = 1050
|
7
|
+
|
8
|
+
offset_x_input = IntegerInputBox('offset_x', 'offset_x_change', "0", 80)
|
9
|
+
offset_x_input.set_xy((xpos1, 605))
|
10
|
+
|
11
|
+
|
12
|
+
offset_y_input = IntegerInputBox('offset_y', 'offset_y_change', "0", 80)
|
13
|
+
offset_y_input.set_xy((xpos2, 605))
|
14
|
+
|
15
|
+
pysc.game['limit_x'] = None
|
16
|
+
pysc.game['limit_y'] = None
|
17
|
+
|
18
|
+
pysc.game['size_x'] = None
|
19
|
+
pysc.game['size_y'] = None
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
row_input = IntegerInputBox('n_row', "n_row_change", "", 80)
|
24
|
+
row_input.set_xy((xpos1, 650))
|
25
|
+
|
26
|
+
col_input = IntegerInputBox('n_col', "n_col_change", "", 80)
|
27
|
+
col_input.set_xy((xpos2, 650))
|
28
|
+
|
29
|
+
|
30
|
+
pixel_x_input = IntegerInputBox('pixel_x', 'pixel_x_change', "0", 80)
|
31
|
+
pixel_x_input.set_xy((xpos1, 695))
|
32
|
+
|
33
|
+
pixel_y_input = IntegerInputBox('pixel_y', 'pixel_y_change', "0", 80)
|
34
|
+
pixel_y_input.set_xy((xpos2, 695))
|
35
|
+
|
36
|
+
|
37
|
+
pysc.game.change_layer(offset_x_input, 1)
|
38
|
+
pysc.game.change_layer(offset_y_input, 1)
|
39
|
+
pysc.game.change_layer(row_input, 1)
|
40
|
+
pysc.game.change_layer(col_input, 1)
|
41
|
+
pysc.game.change_layer(pixel_x_input, 1)
|
42
|
+
pysc.game.change_layer(pixel_y_input, 1)
|
@@ -0,0 +1,84 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import Tuple
|
3
|
+
import pyscratch as pysc
|
4
|
+
|
5
|
+
from utils.render_wrapped_file_name import render_wrapped_file_name
|
6
|
+
from settings import *
|
7
|
+
|
8
|
+
width, height = 100, 140
|
9
|
+
colour = (130, 130, 130)
|
10
|
+
|
11
|
+
spacing = 10
|
12
|
+
n_cols = 5
|
13
|
+
|
14
|
+
def try_load_image(path):
|
15
|
+
try:
|
16
|
+
return pysc.load_image(path)
|
17
|
+
except:
|
18
|
+
return None
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
def FileDisplay(path: Path, order: int, panel_top_left):
|
23
|
+
sprite = pysc.create_rect_sprite(colour, width, height)
|
24
|
+
|
25
|
+
# set the position
|
26
|
+
|
27
|
+
panel_x, panel_y = panel_top_left
|
28
|
+
sprite.x = spacing+(order%n_cols)*(width+spacing)+panel_x +width/2
|
29
|
+
sprite.y = spacing+(order//n_cols)*(height+spacing)+panel_y +height/2
|
30
|
+
|
31
|
+
# set the display
|
32
|
+
|
33
|
+
surface = try_load_image(path)
|
34
|
+
if not surface:
|
35
|
+
# TODO: messy af
|
36
|
+
if path.is_file():
|
37
|
+
sprite.remove()
|
38
|
+
return None
|
39
|
+
|
40
|
+
text = render_wrapped_file_name(path.name+'/', 8, DEFAULT_FONT24)
|
41
|
+
sprite.draw(text, offset=(width/2, height/2) )
|
42
|
+
#sprite.write_text(path.name+'/', DEFAULT_FONT24, offset=(width/2, height/2))
|
43
|
+
|
44
|
+
else:
|
45
|
+
image_margin = 20
|
46
|
+
text_height = 20
|
47
|
+
fit = "horizontal" if surface.get_width() >= surface.get_height() else "vertical"
|
48
|
+
surface = pysc.scale_to_fit_aspect(surface, (width-image_margin, height-text_height-image_margin ), fit)
|
49
|
+
sprite.draw(surface, (width/2, (height-text_height)/2))
|
50
|
+
|
51
|
+
text = render_wrapped_file_name(path.name, 8, DEFAULT_FONT24, color= (255, 255, 255), max_lines=2)
|
52
|
+
sprite.draw(text,offset=(width/2, height-20), reset=False)
|
53
|
+
|
54
|
+
|
55
|
+
|
56
|
+
sprite.sprite_data['is_file'] = path.is_file()
|
57
|
+
|
58
|
+
|
59
|
+
def on_click():
|
60
|
+
if not path.is_file():
|
61
|
+
pysc.game.broadcast_message('folder_update', path)
|
62
|
+
else:
|
63
|
+
pysc.game.broadcast_message('image_selected', path)
|
64
|
+
#pysc.game.broadcast_message('cut_or_nav_mode_change', 'cut')
|
65
|
+
|
66
|
+
|
67
|
+
|
68
|
+
sprite.when_this_sprite_clicked().add_handler(on_click)
|
69
|
+
|
70
|
+
|
71
|
+
def on_msg_mode_change(mode):
|
72
|
+
if mode == 'nav':
|
73
|
+
sprite.show()
|
74
|
+
#pysc.game.bring_to_front(sprite)
|
75
|
+
else:
|
76
|
+
sprite.hide()
|
77
|
+
|
78
|
+
sprite.when_receive_message('cut_or_nav_mode_change').add_handler(on_msg_mode_change)
|
79
|
+
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
return sprite
|
84
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
from pathlib import Path
|
2
|
+
from typing import List, Tuple, cast
|
3
|
+
import pyscratch as pysc
|
4
|
+
from pyscratch.sprite import Sprite
|
5
|
+
from settings import *
|
6
|
+
from .file_display import FileDisplay
|
7
|
+
|
8
|
+
width, height = RIGHT_PANEL_WIDTH, SCREEN_HEIGHT - PANEL_MARGIN - BOTTOM_RIGHT_PANEL_HEIGHT
|
9
|
+
|
10
|
+
colour = 255, 255, 255
|
11
|
+
folder_navigation = pysc.create_rect_sprite(colour, width, height)
|
12
|
+
|
13
|
+
folder_navigation.set_xy((SCREEN_WIDTH - PANEL_MARGIN - RIGHT_PANEL_WIDTH/2, SCREEN_HEIGHT/2-BOTTOM_RIGHT_PANEL_HEIGHT/2))
|
14
|
+
|
15
|
+
topleft = folder_navigation.x-width/2, folder_navigation.y-height/2
|
16
|
+
|
17
|
+
folder_navigation['file_display_list'] = []
|
18
|
+
|
19
|
+
def on_msg_folder_update(path: Path):
|
20
|
+
#folder_navigation.sprite_data['path'] = path
|
21
|
+
pysc.game.shared_data['path'] = path
|
22
|
+
|
23
|
+
for fdisp in folder_navigation['file_display_list']:
|
24
|
+
fdisp.remove()
|
25
|
+
|
26
|
+
folder_navigation['file_display_list'] = []
|
27
|
+
file_display_list = folder_navigation['file_display_list']
|
28
|
+
|
29
|
+
c = 0
|
30
|
+
for f in path.iterdir():
|
31
|
+
fdisp = FileDisplay(f, c, topleft)
|
32
|
+
if fdisp:
|
33
|
+
c+=1
|
34
|
+
file_display_list.append(fdisp)
|
35
|
+
|
36
|
+
folder_navigation.when_receive_message('folder_update').add_handler(on_msg_folder_update)
|
37
|
+
|
38
|
+
|
39
|
+
def on_msg_back_nav(_):
|
40
|
+
path: Path = pysc.game['path']
|
41
|
+
pysc.game.broadcast_message('folder_update', path.parent)
|
42
|
+
|
43
|
+
|
44
|
+
|
45
|
+
folder_navigation.when_receive_message('back_nav').add_handler(on_msg_back_nav)
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
def on_msg_mode_change(mode):
|
50
|
+
if mode == 'nav':
|
51
|
+
folder_navigation.show()
|
52
|
+
pysc.game.move_to_back(folder_navigation)
|
53
|
+
else:
|
54
|
+
folder_navigation.hide()
|
55
|
+
|
56
|
+
folder_navigation.when_receive_message('cut_or_nav_mode_change').add_handler(on_msg_mode_change)
|
57
|
+
pysc.game['folder_navigation'] = folder_navigation
|
@@ -0,0 +1,262 @@
|
|
1
|
+
"""
|
2
|
+
pysc.game.broadcast_message
|
3
|
+
("cut_sprite_frame_drop", dict(sprite=sprite, position=pysc.get_mouse_pos()))
|
4
|
+
|
5
|
+
"""
|
6
|
+
from pathlib import Path
|
7
|
+
from typing import List, Tuple, cast
|
8
|
+
|
9
|
+
import numpy as np
|
10
|
+
from pygame import Surface
|
11
|
+
import pyscratch as pysc
|
12
|
+
from settings import *
|
13
|
+
game = pysc.game
|
14
|
+
width, height = RIGHT_PANEL_WIDTH, SCREEN_HEIGHT - PANEL_MARGIN - BOTTOM_RIGHT_PANEL_HEIGHT
|
15
|
+
|
16
|
+
colour = 255, 255, 255, 255
|
17
|
+
ss_view = pysc.create_rect_sprite(colour, width, height)
|
18
|
+
|
19
|
+
ss_view.set_xy((SCREEN_WIDTH - PANEL_MARGIN - RIGHT_PANEL_WIDTH/2, SCREEN_HEIGHT/2-BOTTOM_RIGHT_PANEL_HEIGHT/2))
|
20
|
+
#ss_view.set_draggable(False)
|
21
|
+
#topleft = ss_view.x-width/2, ss_view.y-height/2
|
22
|
+
pysc.game['ss_view'] = ss_view
|
23
|
+
|
24
|
+
def topleft():
|
25
|
+
return ss_view.x-width/2, ss_view.y-height/2
|
26
|
+
ss_view['frame_list'] = []
|
27
|
+
|
28
|
+
pysc.game['ss_view_topleft'] = topleft()
|
29
|
+
pysc.game['ss_view_buttom_right'] = ss_view.x+width/2, ss_view.y+height/2
|
30
|
+
|
31
|
+
|
32
|
+
|
33
|
+
ss_view['spritesheet_sprite'] = None
|
34
|
+
pysc.game['ss_sprite'] = None
|
35
|
+
def on_msg_mode_change(mode):
|
36
|
+
if not mode == 'nav':
|
37
|
+
ss_view.show()
|
38
|
+
pysc.game.move_to_back(ss_view)
|
39
|
+
for f in ss_view.sprite_data['frame_list']:
|
40
|
+
f.show()
|
41
|
+
|
42
|
+
else:
|
43
|
+
ss_view.hide()
|
44
|
+
for f in ss_view.sprite_data['frame_list']:
|
45
|
+
f.hide()
|
46
|
+
if ss_sprite := ss_view['spritesheet_sprite']:
|
47
|
+
ss_sprite.hide()
|
48
|
+
|
49
|
+
|
50
|
+
ss_view.when_receive_message('cut_or_nav_mode_change').add_handler(on_msg_mode_change)
|
51
|
+
|
52
|
+
def try_load_image(path):
|
53
|
+
try:
|
54
|
+
return pysc.load_image(path)
|
55
|
+
except:
|
56
|
+
return None
|
57
|
+
|
58
|
+
|
59
|
+
def on_msg_image_selected(path):
|
60
|
+
|
61
|
+
for f in ss_view['frame_list']:
|
62
|
+
f.remove()
|
63
|
+
ss_view['frame_list'] = []
|
64
|
+
|
65
|
+
img = try_load_image(path)
|
66
|
+
if img:
|
67
|
+
pysc.game.shared_data['image_on_right_display'] = img
|
68
|
+
|
69
|
+
if ss_sprite := ss_view['spritesheet_sprite']:
|
70
|
+
ss_sprite.remove()
|
71
|
+
|
72
|
+
ss_view['spritesheet_sprite'] = pysc.Sprite({'a':[img]})
|
73
|
+
|
74
|
+
ss_sprite:pysc.Sprite = ss_view['spritesheet_sprite']
|
75
|
+
|
76
|
+
pysc.game['ss_sprite'] = ss_sprite
|
77
|
+
ss_sprite.oob_limit=np.inf
|
78
|
+
ss_sprite['original_width'] = img.get_width()
|
79
|
+
ss_sprite['original_height'] = img.get_height()
|
80
|
+
game.change_layer(ss_sprite, 0)
|
81
|
+
|
82
|
+
|
83
|
+
#ss_sprite.lock_to(ss_view, offset=(0,0))
|
84
|
+
#ss_sprite.set_xy((0,0))
|
85
|
+
|
86
|
+
ss_sprite.set_xy((ss_view.rect.centerx, ss_view.rect.centery))
|
87
|
+
ss_sprite.set_draggable(True) #TODO: dragging a locked sprite leads to unexpected behaviour
|
88
|
+
|
89
|
+
ss_sprite._drawing_manager.set_mask_threshold(-1)
|
90
|
+
|
91
|
+
|
92
|
+
pysc.game.broadcast_message('cut_or_nav_mode_change', 'cut')
|
93
|
+
pass
|
94
|
+
|
95
|
+
ss_view.when_receive_message('image_selected').add_handler(on_msg_image_selected)
|
96
|
+
from itertools import product
|
97
|
+
def on_msg_cut(_):
|
98
|
+
ss_view.draw(pysc.create_rect((0,0,0,0), 1, 1)) # reset
|
99
|
+
|
100
|
+
if not 'image_on_right_display' in pysc.game.shared_data:
|
101
|
+
pysc.game.broadcast_message('warning', 'image not selected' )
|
102
|
+
return
|
103
|
+
|
104
|
+
for f in ss_view['frame_list']:
|
105
|
+
f.remove()
|
106
|
+
ss_view['frame_list'] = []
|
107
|
+
|
108
|
+
|
109
|
+
if ss_sprite := ss_view['spritesheet_sprite']:
|
110
|
+
ss_sprite.hide()
|
111
|
+
|
112
|
+
|
113
|
+
spritesheet: pygame.Surface = pysc.game.shared_data['image_on_right_display']
|
114
|
+
|
115
|
+
n_row = pysc.game.shared_data['n_row']
|
116
|
+
n_col = pysc.game.shared_data['n_col']
|
117
|
+
|
118
|
+
if not n_row:
|
119
|
+
print('invalid n_row')
|
120
|
+
pysc.game.broadcast_message('warning', 'invalid n_row' )
|
121
|
+
return
|
122
|
+
|
123
|
+
if not n_col:
|
124
|
+
print('invalid n_col')
|
125
|
+
pysc.game.broadcast_message('warning', 'invalid n_col' )
|
126
|
+
return
|
127
|
+
n_row = int(n_row)
|
128
|
+
n_col = int(n_col)
|
129
|
+
print(game['offset_x'], game['offset_y'], game['size_x'], game['size_y'])
|
130
|
+
spritesheet_to_cut = spritesheet.subsurface(game['offset_x'], game['offset_y'], game['size_x'], game['size_y'])
|
131
|
+
|
132
|
+
for i, (r, c) in enumerate(product(range(n_row), range(n_col))):
|
133
|
+
frame = pysc.get_frame_from_sprite_sheet_by_frame_size(spritesheet_to_cut, game['pixel_x'], game['pixel_y'], c, r)
|
134
|
+
sprite = SpriteFrameAfterCut(frame, i, ss_sprite.scale_factor, n_col)
|
135
|
+
ss_view['frame_list'].append(sprite)
|
136
|
+
|
137
|
+
ss_view.when_receive_message('cut').add_handler(on_msg_cut)
|
138
|
+
|
139
|
+
|
140
|
+
|
141
|
+
def SpriteFrameAfterCut(surface: Surface, order, scale_factor, n_col):
|
142
|
+
w, h = surface.get_width()*scale_factor, surface.get_height()*scale_factor
|
143
|
+
sprite = pysc.Sprite({'always':[surface]})
|
144
|
+
sprite.oob_limit = np.inf
|
145
|
+
sprite.scale_by(scale_factor)
|
146
|
+
|
147
|
+
|
148
|
+
spacing = 0
|
149
|
+
lt = topleft()
|
150
|
+
x = spacing+(order%n_col)*(w + spacing)+lt[0] +w/2
|
151
|
+
y = spacing+(order//n_col)*(h+spacing)+lt[1] +h/2
|
152
|
+
|
153
|
+
sprite['x'] = x
|
154
|
+
sprite['y'] = y
|
155
|
+
|
156
|
+
sprite.set_xy((x,y))
|
157
|
+
sprite.set_draggable(True)
|
158
|
+
|
159
|
+
|
160
|
+
|
161
|
+
def on_mouse_release():
|
162
|
+
|
163
|
+
pysc.game.broadcast_message("cut_sprite_frame_drop", dict(surface=surface, sprite=sprite, position=pysc.get_mouse_pos()))
|
164
|
+
pass
|
165
|
+
|
166
|
+
|
167
|
+
|
168
|
+
pysc.game.when_this_sprite_click_released(sprite).add_handler(on_mouse_release)
|
169
|
+
|
170
|
+
|
171
|
+
return sprite
|
172
|
+
|
173
|
+
|
174
|
+
|
175
|
+
# TODO: The scrolling becomes hard to use because touching only happens in the non-transparent pixels
|
176
|
+
|
177
|
+
|
178
|
+
def on_scroll(updown):
|
179
|
+
#if updown.
|
180
|
+
ss_sprite:pysc.Sprite = ss_view['spritesheet_sprite']
|
181
|
+
if not ss_sprite: return
|
182
|
+
if not ss_sprite.is_touching_mouse():
|
183
|
+
return
|
184
|
+
|
185
|
+
if updown == 'up':
|
186
|
+
ss_sprite.scale_by(1.05)
|
187
|
+
else:
|
188
|
+
ss_sprite.scale_by(1/1.05)
|
189
|
+
|
190
|
+
pysc.game.broadcast_message("ss_sprite_scale_change")
|
191
|
+
|
192
|
+
pysc.game.when_mouse_scroll([ss_view]).add_handler(on_scroll)
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
def draw_cutting_rect(surface, colour, x0, y0, x1, y1, n_row, n_col):
|
197
|
+
|
198
|
+
n_row = 1 if not n_row else n_row
|
199
|
+
n_col = 1 if not n_col else n_col
|
200
|
+
|
201
|
+
x0, x1 = min(x0, x1), max(x0, x1)
|
202
|
+
y0, y1 = min(y0, y1), max(y0, y1)
|
203
|
+
|
204
|
+
n_line_h = n_row - 1
|
205
|
+
n_line_v = n_col - 1
|
206
|
+
|
207
|
+
|
208
|
+
pygame.draw.lines(surface, colour, True, [(x0, y0), (x0, y1), (x1, y1), (x1, y0)])
|
209
|
+
|
210
|
+
x_step = (x1 - x0)/n_col # vertical lines
|
211
|
+
y_step = (y1 - y0)/n_row # horizontal lines
|
212
|
+
#
|
213
|
+
for lx in range(int(n_line_v)):
|
214
|
+
xpos = (1+lx)*x_step
|
215
|
+
xpos += x0
|
216
|
+
pygame.draw.line(surface, colour, (xpos, y0), (xpos, y1))
|
217
|
+
|
218
|
+
for ly in range(int(n_line_h)):
|
219
|
+
ypos = (1+ly)*y_step
|
220
|
+
ypos += y0
|
221
|
+
pygame.draw.line(surface, colour, (x0, ypos), (x1, ypos))
|
222
|
+
|
223
|
+
return x_step, y_step
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
|
228
|
+
def draw_selection_rect():
|
229
|
+
cir0, cir1 = pysc.game['c0'], pysc.game['c1']
|
230
|
+
while True:
|
231
|
+
yield 1/30
|
232
|
+
ss_sprite:pysc.Sprite = ss_view['spritesheet_sprite']
|
233
|
+
if not ss_sprite:
|
234
|
+
continue
|
235
|
+
|
236
|
+
if game['pixel_x'] is None: continue
|
237
|
+
if game['pixel_y'] is None: continue
|
238
|
+
|
239
|
+
ss_view._drawing_manager.frames[0].fill((255,255,255))
|
240
|
+
|
241
|
+
n_col = 1 if not pysc.game['n_col'] else pysc.game['n_col']
|
242
|
+
n_row = 1 if not pysc.game['n_row'] else pysc.game['n_row']
|
243
|
+
|
244
|
+
|
245
|
+
# top left of the selected rect
|
246
|
+
gx0 = game['offset_x']*ss_sprite.scale_factor + ss_sprite.rect.left - ss_view.rect.left
|
247
|
+
gy0 = game['offset_y']*ss_sprite.scale_factor + ss_sprite.rect.top - ss_view.rect.top
|
248
|
+
|
249
|
+
gx1 = gx0 + game['pixel_x']*n_col*ss_sprite.scale_factor
|
250
|
+
gy1 = gy0 + game['pixel_y']*n_row*ss_sprite.scale_factor
|
251
|
+
|
252
|
+
|
253
|
+
#pygame.draw.lines(ss_view._drawing_manager.frames[0], (0,0,0), True, [(gx0, gy0), (gx0, gy1), (gx1, gy1), (gx1, gy0)])
|
254
|
+
|
255
|
+
draw_cutting_rect(
|
256
|
+
ss_view._drawing_manager.frames[0],
|
257
|
+
(0,0,0),
|
258
|
+
gx0, gy0, gx1, gy1,
|
259
|
+
pysc.game['n_row'], pysc.game['n_col']
|
260
|
+
)
|
261
|
+
|
262
|
+
ss_view.when_game_start().add_handler(draw_selection_rect)
|