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

@@ -3,6 +3,14 @@ import glm
3
3
  from ..render.image import Image
4
4
 
5
5
 
6
+ def validate_int(module: str, name: str, value: int | float | glm.int32) -> float:
7
+ if isinstance(value, int) or isinstance(value, float):
8
+ return int(round(value))
9
+ elif isinstance(value, glm.int32):
10
+ return int(value.value)
11
+ else:
12
+ raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
13
+
6
14
  def validate_float(module: str, name: str, value: float | int | glm.float32) -> float:
7
15
  if isinstance(value, float) or isinstance(value, int):
8
16
  return float(value)
@@ -10,7 +18,7 @@ def validate_float(module: str, name: str, value: float | int | glm.float32) ->
10
18
  return float(value.value)
11
19
  else:
12
20
  raise TypeError(f"{module}: Invalid {name} value type {type(value)}. Expected float.")
13
-
21
+
14
22
  def validate_glm_vec3(module: str, name: str, value: tuple | list | glm.vec3 | np.ndarray) -> glm.vec3:
15
23
  if isinstance(value, tuple) or isinstance(value, list) or isinstance(value, np.ndarray):
16
24
  if len(value) != 3: raise ValueError(f"{module}: Invalid number of values for {name}. Expected 3 values, got {len(value)} values")
@@ -2,6 +2,7 @@ import numpy as np
2
2
  import moderngl as mgl
3
3
  from PIL import Image
4
4
  from ..render.shader import Shader
5
+ from ..generic.input_validation import validate_int
5
6
 
6
7
 
7
8
  class Framebuffer:
@@ -36,7 +37,7 @@ class Framebuffer:
36
37
  self._size = size
37
38
  self.scale = scale
38
39
  self.texture_filter = (mgl.LINEAR, mgl.LINEAR) if linear_filter else (mgl.NEAREST, mgl.NEAREST)
39
- self.n_attachments = n_color_attachments
40
+ self.n_attachments = n_color_attachments
40
41
 
41
42
  self.load_pipeline()
42
43
  self.generate_fbo()
@@ -59,6 +60,10 @@ class Framebuffer:
59
60
  # Create the internal fbo
60
61
  self.fbo = self.ctx.framebuffer(self._color_attachments, self._depth_attachment)
61
62
 
63
+ # Set the show attachment to default
64
+ self._show = -1
65
+ self.show = 0
66
+
62
67
  def resize(self, new_size: tuple[int]=None) -> None:
63
68
  """
64
69
  Update set size framebuffers with the given size.
@@ -86,13 +91,18 @@ class Framebuffer:
86
91
  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'))
87
92
  self.vao = self.ctx.vertex_array(self.shader.program, [(self.vbo, '3f 2f', 'in_position', 'in_uv')], skip_errors=True)
88
93
 
89
- def render(self, render_target=None) -> None:
94
+ def render(self, render_target=None, show: int=None) -> None:
95
+ """
96
+ Render the fbo to the screen
97
+ If the fbo has multiple attachments, show will specifiy which is shown
98
+ Depth is considered the last show element
99
+ """
90
100
 
91
- target = render_target if render_target else self.engine.frame
101
+ if not isinstance(show, type(None)): self.show = show
92
102
 
103
+ target = render_target if render_target else self.engine.frame
93
104
  target.use()
94
- self.shader.program['screenTexture'] = 0
95
- self.texture.use(location=0)
105
+
96
106
  self.vao.render()
97
107
 
98
108
  def use(self) -> None:
@@ -143,13 +153,23 @@ class Framebuffer:
143
153
  def data(self) -> bytes:
144
154
  """Reads the data from the fbo"""
145
155
  return self.fbo.read()
146
-
156
+ @property
157
+ def show(self) -> int:
158
+ return self._show
147
159
 
148
160
  @size.setter
149
161
  def size(self, value: tuple[int]=None) -> tuple[int]:
150
162
  self.resize(value)
151
163
  return self.size
152
164
 
165
+ @show.setter
166
+ def show(self, value: int) -> None:
167
+ value = validate_int("Framebuffer", "show", value)
168
+ if value == self._show: return
169
+ self._show = value
170
+ self.shader.program['screenTexture'] = value+1
171
+ self.color_attachments[value].use(location=value+1)
172
+
153
173
  def __repr__(self) -> str:
154
174
  return f'<bsk.Framebuffer | size: {self.size}>'
155
175
 
basilisk/render/image.py CHANGED
@@ -19,6 +19,8 @@ class Image():
19
19
  """Array of the texture data"""
20
20
  size: int
21
21
  """The width and height in pixels of the image"""
22
+ texture: mgl.Texture | None=None
23
+ """Texture of the image. Only created and retrived if needed by other module"""
22
24
 
23
25
  def __init__(self, path: str | os.PathLike | pg.Surface | mgl.Texture) -> None:
24
26
  """
@@ -81,8 +83,39 @@ class Image():
81
83
  """
82
84
  ...
83
85
 
86
+ def build_texture(self, ctx: mgl.Context) -> mgl.Texture:
87
+ """
88
+ Builds a texture from the image data
89
+ """
90
+
91
+ # Release existing memory
92
+ if self.texture: self.texture.release()
93
+
94
+ # Make the texture from image data
95
+ self.texture = ctx.texture((self.size, self.size), components=4, data=self.data)
96
+ # Texture formatting
97
+ self.texture.build_mipmaps()
98
+ self.texture.filter = (mgl.LINEAR_MIPMAP_LINEAR, mgl.LINEAR)
99
+ self.texture.anisotropy = 32.0
100
+
101
+ return self.texture
102
+
103
+ def use(self, slot: int) -> None:
104
+ """
105
+ Use the image at the given slot
106
+ """
107
+
108
+ if not self.texture:
109
+ raise LookupError("bsk.Image: cannot use an image without a texture. Use texture.build_texture() before texture.use()")
110
+
111
+ # Bind to the given slot
112
+ self.texture.use(location=slot)
113
+
84
114
  def __repr__(self) -> str:
85
115
  """
86
116
  Returns a string representation of the object
87
117
  """
88
- return f'<Basilisk Image | {self.name}, ({self.size}x{self.size}), {sys.getsizeof(self.data) / 1024 / 1024:.2} mb>'
118
+ return f'<Basilisk Image | {self.name}, ({self.size}x{self.size}), {sys.getsizeof(self.data) / 1024 / 1024:.2} mb>'
119
+
120
+ def __del__(self) -> None:
121
+ if self.texture: self.texture.release()
@@ -152,7 +152,9 @@ class Material():
152
152
  @texture.setter
153
153
  def texture(self, value: Image | None):
154
154
  self._texture = validate_image("Material", "texture", value)
155
- if self.material_handler: self.material_handler.write(regenerate=True)
155
+ if not self.material_handler: return
156
+ self.material_handler.image_handler.add(value)
157
+ self.material_handler.write(regenerate=True)
156
158
 
157
159
  @normal.setter
158
160
  def normal(self, value: Image | None):
@@ -13,6 +13,8 @@ class MaterialHandler():
13
13
  """List containing all the materials in the engine"""
14
14
  data_texture: mgl.Texture
15
15
  """ModernGL texture containing all the material data for materials in the engine"""
16
+ image_handler: ImageHandler=None
17
+ """Handler for all images in the game"""
16
18
 
17
19
  def __init__(self, engine) -> None:
18
20
  """
basilisk/render/shader.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import moderngl as mgl
2
- import random
2
+ from .image import Image
3
3
 
4
4
  attribute_mappings = {
5
5
  'in_position' : [0, 1, 2],
@@ -48,6 +48,7 @@ class Shader:
48
48
  self.attribute_indices = []
49
49
  self.fmt = ''
50
50
  self.attributes = []
51
+ self.bindings = 1
51
52
 
52
53
  # Default vertex and fragment shaders
53
54
  if vert == None: vert = self.engine.root + '/shaders/batch.vert'
@@ -112,6 +113,21 @@ class Shader:
112
113
 
113
114
  self.program[name].write(value)
114
115
 
116
+ def bind(self, sampler: mgl.Texture | mgl.TextureArray | mgl.TextureCube | Image, name: str, slot: int=None) -> None:
117
+ """
118
+ Binds the given sampler to the next availible slot
119
+ """
120
+
121
+ # Use the next slot if no slot is given
122
+ if not slot: slot = self.bindings; self.bindings+=1
123
+
124
+ if isinstance(sampler, Image,): sampler = sampler.build_texture(self.ctx)
125
+
126
+ # Use the sampler
127
+ self.program[name] = slot
128
+ sampler.use(location=slot)
129
+
130
+
115
131
  def __del__(self) -> int:
116
132
  if self.program: self.program.release()
117
133
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: basilisk-engine
3
- Version: 0.1.28
3
+ Version: 0.1.29
4
4
  Summary: Python 3D Framework
5
5
  Home-page: https://basilisk-website.vercel.app/
6
6
  Author: Name
@@ -33,7 +33,7 @@ basilisk/generic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,
33
33
  basilisk/generic/abstract_bvh.py,sha256=BZv9mgkUpNu3bcqmn9I60VqMZocebeyUOoER2Wdky3g,368
34
34
  basilisk/generic/abstract_custom.py,sha256=wwtQUu7JkCKEt7zgGDrjBlsB5DdYHkMhq4yv3Wlpv9k,4406
35
35
  basilisk/generic/collisions.py,sha256=lMhZJkbFuoQTXCF-sQmV5f7_3SaEn_nvhwXNU5YaecM,2562
36
- basilisk/generic/input_validation.py,sha256=r6lqqTzB92KOiIBptcimkVkrJn_rnDO1unHXQOOnhu4,3511
36
+ basilisk/generic/input_validation.py,sha256=bsI-4pzF9LFkmxvlLOCHQ0-dqKJrTRBZd1tIX4rzYaQ,3859
37
37
  basilisk/generic/math.py,sha256=1vIX7VMD-qatd1QcC1w52uP9VKGmD6jdcA7_syUoMWI,170
38
38
  basilisk/generic/matrices.py,sha256=N21nL_B2jsZ2Oxsw9jpY03qIHaElAZcj_hnWs85K0t8,1288
39
39
  basilisk/generic/meshes.py,sha256=Rijhvr1NWx0HU2WTaROsspWfyd9FZU27sdkpxGl9xvk,2567
@@ -41,9 +41,6 @@ basilisk/generic/quat.py,sha256=gEqvQvNwx5K7e0zqY0TFTAFtNFSkOatleoP9HQQ-xyk,5102
41
41
  basilisk/generic/quat_methods.py,sha256=SO18ush7pfeGUmncPy4i5nsab1e_zkQkY6zT1bAsSDY,234
42
42
  basilisk/generic/raycast_result.py,sha256=waVmS9fYhLoz_G_DU2Mj7896rF0Xy_59JVGALq-kD7g,783
43
43
  basilisk/generic/vec3.py,sha256=AtPSz2S1ZqAm-sZUz4phB09hgFxMIsJnQdU1wmxiOBw,5137
44
- basilisk/input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
45
- basilisk/input/mouse.py,sha256=waXJLIyka4IVe3W2WH5SNNxiOQRouYo3NxafP3fg0qg,1937
46
- basilisk/input/path.py,sha256=GpFYe3Uu6VZAuKh9Q2nQM1H8immiCp_snznLG9FKcvU,441
47
44
  basilisk/input_output/IO_handler.py,sha256=DDQEjmIHzWo99rk1riT_QJKGQ5F8-lOilmchRXeQuYI,2822
48
45
  basilisk/input_output/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
46
  basilisk/input_output/clock.py,sha256=GHTagpPyPlLjWyonaHV8M-nPCcdHcHL4JobbuUOxYf0,1462
@@ -75,15 +72,15 @@ basilisk/render/camera.py,sha256=pOM5sVSHl_joHwsBLd8Y7CzLUL-16XBBQfgsnM8jc6Q,964
75
72
  basilisk/render/chunk.py,sha256=Yyyh6jEEG_JQIk02hEDs1L-UbmKDZQcAHtGV4pxSJ7U,2715
76
73
  basilisk/render/chunk_handler.py,sha256=PJNGWv3DURm8rYKb3WlGVx6CJ5arbaIiMwA1UN-G480,6332
77
74
  basilisk/render/frame.py,sha256=v7EuQ7FRXzxyeS7QFlqyz-jzveAkQkglxhHVjv6zAFY,2917
78
- basilisk/render/framebuffer.py,sha256=XZBBw4WwX6XgbtlacwLUVhSSXCDIQjQAqGwWKkakLN4,5537
79
- basilisk/render/image.py,sha256=HotYV1bUCJ71bJLfdertz2AKKh0q5k268Ph_tbzP9ss,2873
75
+ basilisk/render/framebuffer.py,sha256=28_oqR_eLNytyTS_2kNIHIY30T5ICoOK80jRnTZdtQ8,6222
76
+ basilisk/render/image.py,sha256=d-5RGr-TlsGqvI-GQ8_pV-FNdmTzD0mlk2K3K4XNuwQ,3984
80
77
  basilisk/render/image_handler.py,sha256=DNb-AiouziLVQu3NkoG1F90YZTHHWyhFYhaWJ9uiUOU,4175
81
78
  basilisk/render/light.py,sha256=SOOh5zAGUCgQdJjWb5MlJgtvdxkEV8AWqQ4P93bJj2g,3783
82
79
  basilisk/render/light_handler.py,sha256=gvg4OhDMy8dZg5XNcOZB4_1G2uE1gBFRxlBeoG3l3vM,2104
83
- basilisk/render/material.py,sha256=RdZDy-pqxlpBW8n8JOsxETmd5XjXu6cxrCd5_6_DOww,9436
84
- basilisk/render/material_handler.py,sha256=CG_a_cV4V_1iYdhCjn7etFxIbAXyRgVicR135rim0oA,3983
80
+ basilisk/render/material.py,sha256=MYcNbhNyVJ3DeAB8cq-aMYRPJfWxBA1c1xpODXJqbsY,9510
81
+ basilisk/render/material_handler.py,sha256=b5K-Y3uzCqb1G9WMyvbonuh4GAOQnu5IkeNCq09PKBs,4065
85
82
  basilisk/render/post_process.py,sha256=iDQ05SUXUUmVcCq4m6c16m0yfWxQjM3NB9vciorJnV0,4959
86
- basilisk/render/shader.py,sha256=PQ0XwE4ZtekQBdVUKwLsXbbTlsI_yuUVsJM1Iy4MPsc,4259
83
+ basilisk/render/shader.py,sha256=q5eSvWTEP55oNoM7kepEizSOQyjDkDLV2RrFiySaKOI,4799
87
84
  basilisk/render/shader_handler.py,sha256=w1bGwVXm61_dDVlX9WgU8CKOMdqTjcooNlMsdN9lVnc,2738
88
85
  basilisk/render/sky.py,sha256=orTtgkU35AHZTUGk9IevSXwVs6tktoDP52yEUM5Rg0E,4768
89
86
  basilisk/shaders/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -103,7 +100,7 @@ basilisk/shaders/particle.frag,sha256=JXhPDvgd7JDw0-PCZtCOjHTTw2DMeeSaBvTr5fHuIy
103
100
  basilisk/shaders/particle.vert,sha256=bJv3hsWjWYb-g0mgdCV9eH-TVRwpCzhA3wsgSUI3WEM,2943
104
101
  basilisk/shaders/sky.frag,sha256=KG8ablNdaJ5E2Gf1ZpfP3ih252fY8ZNjign_fwjN6V4,169
105
102
  basilisk/shaders/sky.vert,sha256=oAnrknEgsd9MawE_zx8P0u9nUSFEBYBg5ykBmWpqZ_g,332
106
- basilisk_engine-0.1.28.dist-info/METADATA,sha256=OQkE12NPZNgg5fQbjFOxafRJ_V7PQzOf5k6SCm9kPE0,1261
107
- basilisk_engine-0.1.28.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
108
- basilisk_engine-0.1.28.dist-info/top_level.txt,sha256=enlSYSf7CUyAly1jmUCNNGInTbaFUjGk4SKwyckZQkw,9
109
- basilisk_engine-0.1.28.dist-info/RECORD,,
103
+ basilisk_engine-0.1.29.dist-info/METADATA,sha256=DM9gt-GfjI8qpzUT8wYD_OFbyd5kcYaPIq9e7UuwvQ4,1261
104
+ basilisk_engine-0.1.29.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
105
+ basilisk_engine-0.1.29.dist-info/top_level.txt,sha256=enlSYSf7CUyAly1jmUCNNGInTbaFUjGk4SKwyckZQkw,9
106
+ basilisk_engine-0.1.29.dist-info/RECORD,,
File without changes
basilisk/input/mouse.py DELETED
@@ -1,62 +0,0 @@
1
- import pygame as pg
2
-
3
-
4
- class Mouse():
5
- def __init__(self, grab=True):
6
- self.x, self.y = pg.mouse.get_pos()
7
- self.buttons = pg.mouse.get_pressed()
8
- self.previous_buttons = pg.mouse.get_pressed()
9
- self.grab = grab
10
-
11
- def update(self, events):
12
- """
13
- Updates all mouse state variables.
14
- Checks for mouse-related events.
15
- """
16
-
17
- self.x, self.y = pg.mouse.get_pos()
18
- self.previous_buttons = self.buttons
19
- self.buttons = pg.mouse.get_pressed()
20
-
21
- for event in events:
22
- if event.type == pg.KEYUP:
23
- if event.key == pg.K_ESCAPE and self.grab:
24
- # Unlock mouse
25
- pg.event.set_grab(False)
26
- pg.mouse.set_visible(True)
27
- if event.type == pg.MOUSEBUTTONUP and self.grab:
28
- # Lock mouse
29
- pg.event.set_grab(True)
30
- pg.mouse.set_visible(False)
31
-
32
- def set_pos(self, x, y):
33
- """Set the mouse position"""
34
- pg.mouse.set_pos(x, y)
35
-
36
- @property
37
- def click(self): return self.buttons[0] and not self.previous_buttons[0]
38
- @property
39
- def left_click(self): return self.buttons[0] and not self.previous_buttons[0]
40
- @property
41
- def middle_click(self): return self.buttons[1] and not self.previous_buttons[1]
42
- @property
43
- def right_click(self): return self.buttons[2] and not self.previous_buttons[2]
44
- @property
45
- def left_down(self): return self.buttons[0]
46
- @property
47
- def middle_down(self): return self.buttons[1]
48
- @property
49
- def right_down(self): return self.buttons[2]
50
-
51
- @property
52
- def grab(self): return self._grab
53
-
54
- @grab.setter
55
- def grab(self, value):
56
- self._grab = value
57
- if self._grab:
58
- pg.event.set_grab(True)
59
- pg.mouse.set_visible(False)
60
- else:
61
- pg.event.set_grab(False)
62
- pg.mouse.set_visible(True)
basilisk/input/path.py DELETED
@@ -1,14 +0,0 @@
1
- import os
2
- import sys
3
-
4
-
5
- # Credit for function: https://stackoverflow.com/questions/7674790/bundling-data-files-with-pyinstaller-onefile
6
- def get_root():
7
- """ Get absolute path to resource, works for dev and for PyInstaller """
8
- try:
9
- # PyInstaller creates a temp folder and stores path in _MEIPASS
10
- base_path = sys._MEIPASS
11
- except Exception:
12
- base_path = os.path.abspath(".")
13
-
14
- return base_path + '/basilisk'