basilisk-engine 0.1.22__py3-none-any.whl → 0.1.23__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.

Potentially problematic release.


This version of basilisk-engine might be problematic. Click here for more details.

Files changed (93) hide show
  1. basilisk/__init__.py +15 -15
  2. basilisk/audio/sound.py +27 -27
  3. basilisk/bsk_assets/cube.obj +48 -48
  4. basilisk/collisions/broad/broad_aabb.py +102 -102
  5. basilisk/collisions/broad/broad_bvh.py +137 -137
  6. basilisk/collisions/collider.py +95 -95
  7. basilisk/collisions/collider_handler.py +224 -224
  8. basilisk/collisions/narrow/contact_manifold.py +95 -95
  9. basilisk/collisions/narrow/dataclasses.py +34 -34
  10. basilisk/collisions/narrow/deprecated.py +46 -46
  11. basilisk/collisions/narrow/epa.py +91 -91
  12. basilisk/collisions/narrow/gjk.py +66 -66
  13. basilisk/collisions/narrow/graham_scan.py +24 -24
  14. basilisk/collisions/narrow/helper.py +29 -29
  15. basilisk/collisions/narrow/line_intersections.py +106 -106
  16. basilisk/collisions/narrow/sutherland_hodgman.py +75 -75
  17. basilisk/config.py +4 -3
  18. basilisk/draw/draw.py +100 -100
  19. basilisk/draw/draw_handler.py +175 -179
  20. basilisk/draw/font_renderer.py +28 -28
  21. basilisk/engine.py +165 -217
  22. basilisk/generic/abstract_bvh.py +15 -15
  23. basilisk/generic/abstract_custom.py +133 -133
  24. basilisk/generic/collisions.py +72 -72
  25. basilisk/generic/input_validation.py +66 -66
  26. basilisk/generic/math.py +6 -6
  27. basilisk/generic/matrices.py +35 -35
  28. basilisk/generic/meshes.py +72 -72
  29. basilisk/generic/quat.py +142 -142
  30. basilisk/generic/quat_methods.py +7 -7
  31. basilisk/generic/raycast_result.py +26 -26
  32. basilisk/generic/vec3.py +143 -143
  33. basilisk/input/mouse.py +61 -61
  34. basilisk/input/path.py +14 -14
  35. basilisk/input_output/IO_handler.py +93 -0
  36. basilisk/input_output/__init__.py +0 -0
  37. basilisk/input_output/clock.py +50 -0
  38. basilisk/input_output/keys.py +44 -0
  39. basilisk/input_output/mouse.py +62 -0
  40. basilisk/input_output/path.py +14 -0
  41. basilisk/mesh/cube.py +33 -33
  42. basilisk/mesh/mesh.py +230 -230
  43. basilisk/mesh/mesh_from_data.py +130 -130
  44. basilisk/mesh/model.py +271 -271
  45. basilisk/mesh/narrow_aabb.py +89 -89
  46. basilisk/mesh/narrow_bvh.py +91 -91
  47. basilisk/mesh/narrow_primative.py +23 -23
  48. basilisk/nodes/helper.py +28 -28
  49. basilisk/nodes/node.py +686 -684
  50. basilisk/nodes/node_handler.py +97 -96
  51. basilisk/particles/particle_handler.py +64 -64
  52. basilisk/particles/particle_renderer.py +92 -92
  53. basilisk/physics/impulse.py +112 -112
  54. basilisk/physics/physics_body.py +43 -43
  55. basilisk/physics/physics_engine.py +35 -35
  56. basilisk/render/batch.py +105 -105
  57. basilisk/render/camera.py +267 -222
  58. basilisk/render/chunk.py +106 -106
  59. basilisk/render/chunk_handler.py +165 -165
  60. basilisk/render/frame.py +99 -101
  61. basilisk/render/framebuffer.py +131 -130
  62. basilisk/render/image.py +87 -87
  63. basilisk/render/image_handler.py +120 -122
  64. basilisk/render/light.py +96 -96
  65. basilisk/render/light_handler.py +58 -58
  66. basilisk/render/material.py +219 -219
  67. basilisk/render/material_handler.py +131 -135
  68. basilisk/render/post_process.py +139 -139
  69. basilisk/render/shader.py +109 -110
  70. basilisk/render/shader_handler.py +83 -80
  71. basilisk/render/sky.py +120 -120
  72. basilisk/scene.py +279 -276
  73. basilisk/shaders/batch.frag +276 -276
  74. basilisk/shaders/batch.vert +115 -115
  75. basilisk/shaders/crt.frag +31 -31
  76. basilisk/shaders/draw.frag +22 -22
  77. basilisk/shaders/draw.vert +25 -25
  78. basilisk/shaders/filter.frag +22 -22
  79. basilisk/shaders/frame.frag +12 -12
  80. basilisk/shaders/frame.vert +13 -13
  81. basilisk/shaders/geometry.frag +8 -8
  82. basilisk/shaders/geometry.vert +41 -41
  83. basilisk/shaders/normal.frag +59 -59
  84. basilisk/shaders/normal.vert +96 -96
  85. basilisk/shaders/particle.frag +71 -71
  86. basilisk/shaders/particle.vert +84 -84
  87. basilisk/shaders/sky.frag +9 -9
  88. basilisk/shaders/sky.vert +13 -13
  89. {basilisk_engine-0.1.22.dist-info → basilisk_engine-0.1.23.dist-info}/METADATA +45 -38
  90. basilisk_engine-0.1.23.dist-info/RECORD +109 -0
  91. {basilisk_engine-0.1.22.dist-info → basilisk_engine-0.1.23.dist-info}/WHEEL +1 -1
  92. basilisk_engine-0.1.22.dist-info/RECORD +0 -103
  93. {basilisk_engine-0.1.22.dist-info → basilisk_engine-0.1.23.dist-info}/top_level.txt +0 -0
basilisk/render/frame.py CHANGED
@@ -1,102 +1,100 @@
1
- import numpy as np
2
- import moderngl as mgl
3
- from .shader import Shader
4
- from .framebuffer import Framebuffer
5
-
6
- from .post_process import PostProcess
7
-
8
- class Frame:
9
- shader: Shader=None
10
- vbo: mgl.Buffer=None
11
- vao: mgl.VertexArray=None
12
- framebuffer: mgl.Framebuffer=None
13
-
14
- def __init__(self, scene, resolution=1, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
15
- """
16
- Basilisk render destination.
17
- Can be used to render to the screen or for headless rendering
18
- """
19
-
20
- self.scene = scene
21
- self.engine = scene.engine
22
- self.ctx = scene.ctx
23
-
24
- # Load framebuffer
25
- self.resolution = resolution
26
- self.filter = filter
27
- size = tuple(map(lambda x: int(x * self.resolution), self.engine.win_size))
28
- self.framebuffer = Framebuffer(self.engine, size=size, filter=self.filter)
29
- self.ping_pong_buffer = Framebuffer(self.engine, size=size, filter=self.filter)
30
-
31
- # Load Shaders
32
- self.shader = Shader(self.engine, self.engine.root + '/shaders/frame.vert', self.engine.root + '/shaders/frame.frag')
33
- self.scene.shader_handler.add(self.shader)
34
-
35
- # Load VAO
36
- self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
37
- self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
38
-
39
- # TEMP TESTING
40
- self.post_processes = []
41
-
42
-
43
- def render(self) -> None:
44
- """
45
- Renders the current frame to the screen
46
- """
47
-
48
- for process in self.post_processes:
49
- self.ping_pong_buffer = process.apply(self.framebuffer, self.ping_pong_buffer)
50
-
51
- temp = self.framebuffer
52
- self.framebuffer = self.ping_pong_buffer
53
- self.ping_pong_buffer = temp
54
-
55
- self.ctx.screen.use()
56
- self.shader.program['screenTexture'] = 0
57
- self.framebuffer.texture.use(location=0)
58
- self.vao.render()
59
-
60
-
61
- def use(self) -> None:
62
- """
63
- Uses the frame as a render target
64
- """
65
-
66
- self.framebuffer.use()
67
- self.clear()
68
-
69
- def add_post_process(self, post_process: PostProcess) -> PostProcess:
70
- """
71
- Add a post process to the frames post process stack
72
- """
73
-
74
- self.post_processes.append(post_process)
75
- return post_process
76
-
77
- def save(self, destination: str=None) -> None:
78
- """
79
- Saves the frame as an image to the given file destination
80
- """
81
-
82
- self.framebuffer.save(destination)
83
-
84
- def clear(self):
85
- self.framebuffer.clear()
86
-
87
- def resize(self, size: tuple[int]=None) -> None:
88
- """
89
- Resize the frame to the given size. None for window size
90
- """
91
-
92
- size = tuple(map(lambda x: int(x * self.resolution), self.engine.win_size))
93
- self.framebuffer.resize(size)
94
- self.ping_pong_buffer.resize(size)
95
-
96
- def __del__(self) -> None:
97
- """
98
- Releases memory used by the frame
99
- """
100
-
101
- if self.vbo: self.vbo.release()
1
+ import numpy as np
2
+ import moderngl as mgl
3
+ from .shader import Shader
4
+ from .framebuffer import Framebuffer
5
+
6
+ from .post_process import PostProcess
7
+
8
+ class Frame:
9
+ shader: Shader=None
10
+ vbo: mgl.Buffer=None
11
+ vao: mgl.VertexArray=None
12
+ framebuffer: mgl.Framebuffer=None
13
+
14
+ def __init__(self, engine, resolution=1, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
15
+ """
16
+ Basilisk render destination.
17
+ Can be used to render to the screen or for headless rendering
18
+ """
19
+
20
+ self.engine = engine
21
+ self.ctx = engine.ctx
22
+
23
+ # Load framebuffer
24
+ self.resolution = resolution
25
+ self.filter = filter
26
+ size = tuple(map(lambda x: int(x * self.resolution), self.engine.win_size))
27
+ self.framebuffer = Framebuffer(self.engine, size=size, filter=self.filter)
28
+ self.ping_pong_buffer = Framebuffer(self.engine, size=size, filter=self.filter)
29
+
30
+ # Load Shaders
31
+ self.shader = Shader(self.engine, self.engine.root + '/shaders/frame.vert', self.engine.root + '/shaders/frame.frag')
32
+ self.engine.shader_handler.add(self.shader)
33
+
34
+ # Load VAO
35
+ self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
36
+ self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
37
+
38
+ # TEMP TESTING
39
+ self.post_processes = []
40
+
41
+
42
+ def render(self) -> None:
43
+ """
44
+ Renders the current frame to the screen
45
+ """
46
+
47
+ for process in self.post_processes:
48
+ self.ping_pong_buffer = process.apply(self.framebuffer, self.ping_pong_buffer)
49
+
50
+ temp = self.framebuffer
51
+ self.framebuffer = self.ping_pong_buffer
52
+ self.ping_pong_buffer = temp
53
+
54
+ self.ctx.screen.use()
55
+ self.shader.program['screenTexture'] = 0
56
+ self.framebuffer.texture.use(location=0)
57
+ self.vao.render()
58
+
59
+
60
+ def use(self) -> None:
61
+ """
62
+ Uses the frame as a render target
63
+ """
64
+
65
+ self.framebuffer.use()
66
+
67
+ def add_post_process(self, post_process: PostProcess) -> PostProcess:
68
+ """
69
+ Add a post process to the frames post process stack
70
+ """
71
+
72
+ self.post_processes.append(post_process)
73
+ return post_process
74
+
75
+ def save(self, destination: str=None) -> None:
76
+ """
77
+ Saves the frame as an image to the given file destination
78
+ """
79
+
80
+ self.framebuffer.save(destination)
81
+
82
+ def clear(self):
83
+ self.framebuffer.clear()
84
+
85
+ def resize(self, size: tuple[int]=None) -> None:
86
+ """
87
+ Resize the frame to the given size. None for window size
88
+ """
89
+
90
+ size = tuple(map(lambda x: int(x * self.resolution), self.engine.win_size))
91
+ self.framebuffer.resize(size)
92
+ self.ping_pong_buffer.resize(size)
93
+
94
+ def __del__(self) -> None:
95
+ """
96
+ Releases memory used by the frame
97
+ """
98
+
99
+ if self.vbo: self.vbo.release()
102
100
  if self.vao: self.vao.release()
@@ -1,131 +1,132 @@
1
- import numpy as np
2
- import moderngl as mgl
3
- from PIL import Image
4
- from ..render.shader import Shader
5
-
6
-
7
- class Framebuffer:
8
- engine: ...
9
- """Reference to the parent engine"""
10
- fbo: mgl.Framebuffer = None
11
- """The core framebuffer the object provides abstraction for."""
12
- texture: mgl.Texture = None
13
- """The color texture of the framebuffer"""
14
- depth: mgl.Texture = None
15
- """The depth texture of the framebuffer"""
16
- size: tuple[int]
17
- """The dimensions of the framebuffer (x, y)"""
18
-
19
- def __init__(self, engine, size: tuple[int]=None, resolution_scale: float=1.0, components: int=4, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
20
- """
21
- Abstraction to the mgl framebuffer
22
- Args:
23
- engine: mgl.Engine:
24
- The parent engine
25
- size: tuple[int]:
26
- The dimensions of the framebuffer (x, y)
27
- """
28
-
29
- # Set attributes
30
- self.engine = engine
31
- self.ctx = engine.ctx
32
- self.components = components
33
-
34
- # Set the size
35
- self.resolution_scale = resolution_scale
36
- self._size = size
37
- self.size = self._size if self._size else self.engine.win_size
38
- self.size = (int(self.size[0] * resolution_scale), int(self.size[1] * resolution_scale))
39
-
40
- # Create the fbo
41
- self.texture = self.ctx.texture(self.size, components=self.components)
42
- self.depth = self.ctx.depth_texture(self.size)
43
- self.fbo = self.ctx.framebuffer([self.texture], self.depth)
44
-
45
- # Load Shaders
46
- self.shader = Shader(self.engine, self.engine.root + '/shaders/frame.vert', self.engine.root + '/shaders/frame.frag')
47
- self.engine.scene.shader_handler.add(self.shader)
48
-
49
- # Load VAO
50
- self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
51
- self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
52
-
53
- # Save the filter
54
- self.filter = filter
55
-
56
- # Add to the engine for updates
57
- self.engine.fbos.append(self)
58
-
59
- def render(self) -> None:
60
- self.shader.program['screenTexture'] = 0
61
- self.texture.use(location=0)
62
- self.vao.render()
63
-
64
- def use(self) -> None:
65
- """
66
- Select this framebuffer for use
67
- """
68
-
69
- self.fbo.use()
70
-
71
- def clear(self) -> None:
72
- """
73
- Clear all data currently in the textures (set to black)
74
- """
75
-
76
- self.fbo.clear()
77
-
78
- def save(self, destination: str=None) -> None:
79
- """
80
- Saves the frame as an image to the given file destination
81
- """
82
-
83
- path = destination if destination else 'screenshot'
84
-
85
- data = self.fbo.read(components=3, alignment=1)
86
- img = Image.frombytes('RGB', self.size, data).transpose(Image.FLIP_TOP_BOTTOM)
87
- img.save(f'{path}.png')
88
-
89
- def resize(self, size: tuple[int]=None) -> None:
90
- """
91
- Resize the buffer to the given size. None for window size
92
- """
93
-
94
- # Release old memory
95
- self.__del__()
96
-
97
- # Set/get size attribute
98
- if size:
99
- self.size = size
100
- else:
101
- self.size = self._size if self._size else self.engine.win_size
102
- self.size = (int(self.size[0] * self.resolution_scale), int(self.size[1] * self.resolution_scale))
103
-
104
- # Create the fbo
105
- self.texture = self.ctx.texture(self.size, components=self.components)
106
- self.depth = self.ctx.depth_texture(self.size)
107
- self.fbo = self.ctx.framebuffer([self.texture], self.depth)
108
-
109
- self.filter = self._filter
110
-
111
- @property
112
- def data(self):
113
- return self.fbo.read(components=3, alignment=1)
114
-
115
- @property
116
- def filter(self):
117
- return self.texture.filter
118
-
119
- @filter.setter
120
- def filter(self, value):
121
- self._filter = value
122
- self.texture.filter = value
123
-
124
- def __repr__(self) -> str:
125
- return f'<bsk.Framebuffer | size: {self.size}>'
126
-
127
- def __del__(self) -> None:
128
- # Release any existing memory in case of a resize
129
- if self.texture: self.texture.release()
130
- if self.depth: self.depth.release()
1
+ import numpy as np
2
+ import moderngl as mgl
3
+ from PIL import Image
4
+ from ..render.shader import Shader
5
+
6
+
7
+ class Framebuffer:
8
+ engine: ...
9
+ """Reference to the parent engine"""
10
+ fbo: mgl.Framebuffer = None
11
+ """The core framebuffer the object provides abstraction for."""
12
+ texture: mgl.Texture = None
13
+ """The color texture of the framebuffer"""
14
+ depth: mgl.Texture = None
15
+ """The depth texture of the framebuffer"""
16
+ size: tuple[int]
17
+ """The dimensions of the framebuffer (x, y)"""
18
+
19
+ def __init__(self, engine, size: tuple[int]=None, resolution_scale: float=1.0, components: int=4, filter=(mgl.LINEAR, mgl.LINEAR)) -> None:
20
+ """
21
+ Abstraction to the mgl framebuffer
22
+ Args:
23
+ engine: mgl.Engine:
24
+ The parent engine
25
+ size: tuple[int]:
26
+ The dimensions of the framebuffer (x, y)
27
+ """
28
+
29
+ # Set attributes
30
+ self.engine = engine
31
+ self.ctx = engine.ctx
32
+ self.components = components
33
+
34
+ # Set the size
35
+ self.resolution_scale = resolution_scale
36
+ self._size = size
37
+ self.size = self._size if self._size else self.engine.win_size
38
+ self.size = (int(self.size[0] * resolution_scale), int(self.size[1] * resolution_scale))
39
+
40
+ # Create the fbo
41
+ self.texture = self.ctx.texture(self.size, components=self.components)
42
+ self.depth = self.ctx.depth_texture(self.size)
43
+ self.fbo = self.ctx.framebuffer([self.texture], self.depth)
44
+
45
+ # Load Shaders
46
+ self.shader = Shader(self.engine, self.engine.root + '/shaders/frame.vert', self.engine.root + '/shaders/frame.frag')
47
+ self.engine.shader_handler.add(self.shader)
48
+
49
+ # Load VAO
50
+ self.vbo = self.ctx.buffer(np.array([[-1, -1, 0, 0, 0], [1, -1, 0, 1, 0], [1, 1, 0, 1, 1], [-1, 1, 0, 0, 1], [-1, -1, 0, 0, 0], [1, 1, 0, 1, 1]], dtype='f4'))
51
+ self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
52
+
53
+ # Save the filter
54
+ self.filter = filter
55
+
56
+ # Add to the engine for updates
57
+ self.engine.fbos.append(self)
58
+
59
+ def render(self) -> None:
60
+ self.shader.program['screenTexture'] = 0
61
+ self.texture.use(location=0)
62
+ self.vao.render()
63
+
64
+ def use(self) -> None:
65
+ """
66
+ Select this framebuffer for use
67
+ """
68
+
69
+ self.fbo.use()
70
+
71
+ def clear(self) -> None:
72
+ """
73
+ Clear all data currently in the textures (set to black)
74
+ """
75
+
76
+ self.fbo.clear()
77
+
78
+ def save(self, destination: str=None) -> None:
79
+ """
80
+ Saves the frame as an image to the given file destination
81
+ """
82
+
83
+ path = destination if destination else 'screenshot'
84
+
85
+ data = self.fbo.read(components=3, alignment=1)
86
+ img = Image.frombytes('RGB', self.size, data).transpose(Image.FLIP_TOP_BOTTOM)
87
+ img.save(f'{path}.png')
88
+
89
+ def resize(self, size: tuple[int]=None) -> None:
90
+ """
91
+ Resize the buffer to the given size. None for window size
92
+ """
93
+
94
+ # Release old memory
95
+ self.__del__()
96
+
97
+ # Set/get size attribute
98
+ if size:
99
+ self.size = size
100
+ else:
101
+ self.size = self._size if self._size else self.engine.win_size
102
+ self.size = (int(self.size[0] * self.resolution_scale), int(self.size[1] * self.resolution_scale))
103
+
104
+ # Create the fbo
105
+ print(self.size)
106
+ self.texture = self.ctx.texture(self.size, components=self.components)
107
+ self.depth = self.ctx.depth_texture(self.size)
108
+ self.fbo = self.ctx.framebuffer([self.texture], self.depth)
109
+
110
+ self.filter = self._filter
111
+
112
+ @property
113
+ def data(self):
114
+ return self.fbo.read(components=3, alignment=1)
115
+
116
+ @property
117
+ def filter(self):
118
+ return self.texture.filter
119
+
120
+ @filter.setter
121
+ def filter(self, value):
122
+ self._filter = value
123
+ self.texture.filter = value
124
+
125
+ def __repr__(self) -> str:
126
+ return f'<bsk.Framebuffer | size: {self.size}>'
127
+
128
+ def __del__(self) -> None:
129
+ # Release any existing memory in case of a resize
130
+ if self.texture: self.texture.release()
131
+ if self.depth: self.depth.release()
131
132
  if self.fbo: self.fbo.release()
basilisk/render/image.py CHANGED
@@ -1,88 +1,88 @@
1
- import os
2
- import sys
3
- import numpy as np
4
- import moderngl as mgl
5
- import glm
6
- import pygame as pg
7
- from PIL import Image as PIL_Image
8
-
9
-
10
- texture_sizes = (8, 64, 512, 1024, 2048)
11
-
12
-
13
- class Image():
14
- name: str
15
- """Name of the image"""
16
- index: glm.ivec2
17
- """Location of the image in the texture arrays"""
18
- data: np.ndarray
19
- """Array of the texture data"""
20
- size: int
21
- """The width and height in pixels of the image"""
22
-
23
- def __init__(self, path: str | os.PathLike | pg.Surface | mgl.Texture) -> None:
24
- """
25
- A basilisk image object that contains a moderngl texture
26
- Args:
27
- path: str | os.PathLike | pg.Surface
28
- The string path to the image. Can also read a pygame surface
29
- """
30
-
31
- # Check if the user is loading a pygame surface
32
- if isinstance(path, str) or isinstance(path, os.PathLike):
33
- return self._from_path(path)
34
- elif isinstance(path, pg.Surface):
35
- return self._from_surface(path)
36
- elif isinstance(path, mgl.Texture):
37
- return self._from_texture(path)
38
-
39
- raise TypeError(f'Invalid path type: {type(path)}. Expected a string or os.PathLike')
40
-
41
- def _from_path(self, path: str | os.PathLike) -> None:
42
- """
43
- Loads a basilisk image from a pygame surface
44
- Args:
45
- """
46
-
47
- # Get name from path
48
- self.name = path.split('/')[-1].split('\\')[-1].split('.')[0]
49
-
50
- # Load image
51
- img = PIL_Image.open(path).convert('RGBA')
52
- # Set the size in one of the size buckets
53
- size_buckets = texture_sizes
54
- self.size = size_buckets[np.argmin(np.array([abs(size - img.size[0]) for size in size_buckets]))]
55
- img = img.resize((self.size, self.size))
56
- # Get the image data
57
- self.data = img.tobytes()
58
-
59
- # Default index value (to be set by image handler)
60
- self.index = glm.ivec2(1, 1)
61
-
62
- def _from_surface(self, surf: pg.Surface) -> None:
63
- """
64
- Loads a basilisk image from a pygame surface
65
- Args:
66
- """
67
-
68
- # Set the size in one of the size buckets
69
- size_buckets = texture_sizes
70
- self.size = size_buckets[np.argmin(np.array([abs(size - surf.get_size()[0]) for size in size_buckets]))]
71
- surf = pg.transform.scale(surf, (self.size, self.size)).convert_alpha()
72
- # Get image data
73
- self.data = pg.image.tobytes(surf, 'RGBA')
74
-
75
- # Default index value (to be set by image handler)
76
- self.index = glm.ivec2(1, 1)
77
-
78
- def _from_texture(self, texture: mgl.Texture):
79
- """
80
-
81
- """
82
- ...
83
-
84
- def __repr__(self) -> str:
85
- """
86
- Returns a string representation of the object
87
- """
1
+ import os
2
+ import sys
3
+ import numpy as np
4
+ import moderngl as mgl
5
+ import glm
6
+ import pygame as pg
7
+ from PIL import Image as PIL_Image
8
+
9
+
10
+ texture_sizes = (8, 64, 512, 1024, 2048)
11
+
12
+
13
+ class Image():
14
+ name: str
15
+ """Name of the image"""
16
+ index: glm.ivec2
17
+ """Location of the image in the texture arrays"""
18
+ data: np.ndarray
19
+ """Array of the texture data"""
20
+ size: int
21
+ """The width and height in pixels of the image"""
22
+
23
+ def __init__(self, path: str | os.PathLike | pg.Surface | mgl.Texture) -> None:
24
+ """
25
+ A basilisk image object that contains a moderngl texture
26
+ Args:
27
+ path: str | os.PathLike | pg.Surface
28
+ The string path to the image. Can also read a pygame surface
29
+ """
30
+
31
+ # Check if the user is loading a pygame surface
32
+ if isinstance(path, str) or isinstance(path, os.PathLike):
33
+ return self._from_path(path)
34
+ elif isinstance(path, pg.Surface):
35
+ return self._from_surface(path)
36
+ elif isinstance(path, mgl.Texture):
37
+ return self._from_texture(path)
38
+
39
+ raise TypeError(f'Invalid path type: {type(path)}. Expected a string or os.PathLike')
40
+
41
+ def _from_path(self, path: str | os.PathLike) -> None:
42
+ """
43
+ Loads a basilisk image from a pygame surface
44
+ Args:
45
+ """
46
+
47
+ # Get name from path
48
+ self.name = path.split('/')[-1].split('\\')[-1].split('.')[0]
49
+
50
+ # Load image
51
+ img = PIL_Image.open(path).convert('RGBA')
52
+ # Set the size in one of the size buckets
53
+ size_buckets = texture_sizes
54
+ self.size = size_buckets[np.argmin(np.array([abs(size - img.size[0]) for size in size_buckets]))]
55
+ img = img.resize((self.size, self.size))
56
+ # Get the image data
57
+ self.data = img.tobytes()
58
+
59
+ # Default index value (to be set by image handler)
60
+ self.index = glm.ivec2(1, 1)
61
+
62
+ def _from_surface(self, surf: pg.Surface) -> None:
63
+ """
64
+ Loads a basilisk image from a pygame surface
65
+ Args:
66
+ """
67
+
68
+ # Set the size in one of the size buckets
69
+ size_buckets = texture_sizes
70
+ self.size = size_buckets[np.argmin(np.array([abs(size - surf.get_size()[0]) for size in size_buckets]))]
71
+ surf = pg.transform.scale(surf, (self.size, self.size)).convert_alpha()
72
+ # Get image data
73
+ self.data = pg.image.tobytes(surf, 'RGBA')
74
+
75
+ # Default index value (to be set by image handler)
76
+ self.index = glm.ivec2(1, 1)
77
+
78
+ def _from_texture(self, texture: mgl.Texture):
79
+ """
80
+
81
+ """
82
+ ...
83
+
84
+ def __repr__(self) -> str:
85
+ """
86
+ Returns a string representation of the object
87
+ """
88
88
  return f'<Basilisk Image | {self.name}, ({self.size}x{self.size}), {sys.getsizeof(self.data) / 1024 / 1024:.2} mb>'