diff --git a/a_maze_ing.py b/a_maze_ing.py index 1fbd39a..9f44212 100644 --- a/a_maze_ing.py +++ b/a_maze_ing.py @@ -1,24 +1,19 @@ import os -from src.amaz_lib import Maze -from src.amaz_lib import MazeGenerator -import src.amaz_lib as g +from src.AMazeIng import AMazeIng +from src.parsing import Parsing -def main(maze_gen: MazeGenerator) -> None: - # try: - maze = Maze(maze=None) - for alg in maze_gen.generator(21, 21): - maze.set_maze(alg) - os.system("clear") - maze.ascii_print() - maze.ascii_print() - # solver = AStar((1, 1), (14, 18)) - # print(solver.solve(maze)) - - -# except Exception as err: -# print(err) +def main() -> None: + try: + config = Parsing.DataMaze.get_data_maze("config.txt") + print(config) + amazing = AMazeIng(**config) + for gen in amazing.generate(): + os.system("clear") + amazing.maze.ascii_print() + except Exception as err: + print(err) if __name__ == "__main__": - main(g.Kruskal()) + main() diff --git a/config.txt b/config.txt index 748b11e..0319c42 100644 --- a/config.txt +++ b/config.txt @@ -1,6 +1,8 @@ -WIDTH=200 -HEIGHT=100 +WIDTH=30 +HEIGHT=30 ENTRY=0,0 EXIT=19,14 OUTPUT_FILE=maze.txt -PERFECT=True \ No newline at end of file +PERFECT=True +GENERATOR=Kruskal +SOLVER=AStar diff --git a/mlx-2.2-py3-ubuntu-any.whl b/mlx-2.2-py3-ubuntu-any.whl new file mode 100644 index 0000000..03cae81 Binary files /dev/null and b/mlx-2.2-py3-ubuntu-any.whl differ diff --git a/mlx/__init__.py b/mlx/__init__.py new file mode 100644 index 0000000..e10af51 --- /dev/null +++ b/mlx/__init__.py @@ -0,0 +1,2 @@ +# src/mlx/__init__.py +from .mlx import * diff --git a/mlx/docs/mlx.3 b/mlx/docs/mlx.3 new file mode 100644 index 0000000..d2e3155 --- /dev/null +++ b/mlx/docs/mlx.3 @@ -0,0 +1,136 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Simple Window Interface Library for students +.SH SYNOPSYS +#include + +.nf +.I void * +.fi +.B mlx_init +(); + +.nf +.I int +.fi +.B mlx_release +(void *mlx_ptr); + +.SH DESCRIPTION +MiniLibX is an easy way to create graphical software, +without any X-Window/Wayland/Vulkan programming knowledge under Unix/Linux, +nor any AppKit programming knowledge under MacOS. It provides +simple window creation, a drawing tool, image and basic events +management. + +.SH Unix/Linux: HISTORICAL X-WINDOW CONCEPT + +X-Window is a network-oriented graphical system for Unix. +It is based on two main parts: +.br +On one side, your software wants to draw something on the screen and/or +get keyboard & mouse entries. +.br +On the other side, the X-Server manages the screen, keyboard and mouse +(It is often referred to as a "display"). +.br +A network connection must be established between these two entities to send +drawing orders (from the software to the X-Server), and keyboard/mouse +events (from the X-Server to the software). +.br +Nowadays, most of the time, both run on the same computer. + +.SH Unix/Linux: MODERN GRAPHICAL APPROACH + +Modern computers come with a powerful GPU that is directly accessed by applications. +Along GPU libraries like Vulkan or OpenGL, the Wayland protocol ensure communication +with the compositor program that manages the various windows on screen and the user +input events. +For your own application: +.br +The Vulkan or OpenGL library allow you to directly draw any content into your window. +.br +The Wayland compositor handles the place of your window on screen and send you back +the keyboard and mouse inputs from the user. +.br +Unfortunately, this gain of graphical power through GPU access removes the networking aspects +that exist with X-Window. It is not possible for a program to access a remote GPU and show its +window on a remote display. But current software architectures are more likely based on a local +display application that gets data in JSON through a web API. + +.SH MacOS: WINDOW SERVER AND GPU + +Your software interacts directly with the Window server who handles the +cohabitation on the screen with other software and the event system, +and interacts with the GPU to handle all drawing commands. + +.SH INCLUDE FILE +.B mlx.h +should be included for a correct use of the MiniLibX API. +It only contains function prototypes, no structure is needed. + +.SH LIBRARY FUNCTIONS +.P +First of all, you need to initialize the connection +between your software and the graphic and user sub-systems. +Once this completed, you'll be able to use other MiniLibX +functions to send and receive the messages from +the display, like "I want to draw a yellow pixel in this window" or +"did the user hit a key?". +.P +The +.B mlx_init +function will create this connection. No parameters are needed, ant it will +return a +.I "void *" +identifier, used for further calls to the library routines. The +.B mlx_release +function can be used at the end of the program to disconnect from the graphic +system and release resources. +.P +All other MiniLibX functions are described in the following man pages: + +.TP 20 +.B mlx_new_window +: manage windows +.TP 20 +.B mlx_pixel_put +: draw inside a window +.TP 20 +.B mlx_new_image +: manipulate images +.TP 20 +.B mlx_loop +: handle keyboard or mouse events +.TP 20 +.B mlx_extra +: extra functions available in the MinilibX + +.SH LINKING MiniLibX +To use MiniLibX functions, you may -or not- need to link +your software with several libraries, including the MiniLibX library itself. +On Unix/Linux, depending on the specific operating system, either just using +.B -lmlx +works, or you need to add +.B -lxcb -lxcb-keysyms -lvulkan -lz -lbsd +\&. +On MacOS, the dynamic Metal library will find on its own the missing components: +.B -lmlx +\&. + +You may also need to specify the path to these libraries, using the +.B -L +flag. + + +.SH RETURN VALUES +If +.B mlx_init() +fails to set up the connection to the display, it will return NULL, otherwise +a non-null pointer is returned as a connection identifier. + +.SH SEE ALSO +mlx_new_window(3), mlx_pixel_put(3), mlx_new_image(3), mlx_loop(3), mlx_extra(3) + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/docs/mlx.h b/mlx/docs/mlx.h new file mode 100644 index 0000000..baf0d12 --- /dev/null +++ b/mlx/docs/mlx.h @@ -0,0 +1,209 @@ +/* +** mlx.h for MinilibX in +** +** Made by Charlie Root +** Login +** +** Started on Mon Jul 31 16:37:50 2000 Olivier Crouzet +** Last update Tue Jun 25 16:23:28 2025 Olivier Crouzet +*/ + +/* +** MinilibX - Please report bugs +*/ + + +/* mlx_CLXV version 2.2 */ + +/* +** +** This library is a simple framework to help 42 students +** create simple graphical apps. +** It only provides the minimum functions, it's students' job +** to create the missing pieces for their own project :) +** +** Current XCB-Vulkan requirements for Linux: +** libxcb, libxcb-keysyms, libvulkan, +** libz, libbsd +** You also need glslc to re-compile shaders if needed. +** At 42, on current Ubuntu 22.04 dump in cluster, you need to get +** libxcb-keysyms source for the include file and compile the .a library. +** +** The MinilibX can load XPM and PNG images. +** Please note that both image loaders are incomplete, some +** image may not load. Also, image loaders only work for little endian hosts. +** +** Historically, the alpha byte did represent transparency +** instead of opacity. It's not the case anymore. MLX matches GPUs standards. +** +** MLX_CLXV API changes: +** - mlx_get_data_addr now provides the image format instead of the + endian, and returns an 'unsigned char' pointer. +** - 'unsigned int' replace 'int' in many calls. +** - mlx_get_color_value() is now deprecated. +** - adding mlx_loop_exit(). +** +** With recent X11 implementation and default configuration, the Expose event is only +** received once at the program launch. This is often due to X server saving the +** content of the window. +** With Wayland, there is no such thing like Expose event, and the compositor saves +** the window's content. +** +*/ + + +#ifndef MLX_H + +#define MLX_H + + +/* +** mlx_init() is needed before everything else. +** mlx_init() returns 'void *0' in case of failure. +** mlx_release() returns 0 on success. +*/ +void *mlx_init(); +int mlx_release(void *mlx_ptr); + + +/* +** Window actions +*/ +void *mlx_new_window(void *mlx_ptr, unsigned int width, + unsigned int height, const char *title); +int mlx_clear_window(void *mlx_ptr, void *win_ptr); +int mlx_pixel_put(void *mlx_ptr, void *win_ptr, + unsigned int x, unsigned int y, unsigned int color); +int mlx_destroy_window(void *mlx_ptr, void *win_ptr); +/* +** mlx_new_window() returns 'void *0' if failed. +** Other functions return 0 on success. +** Origin for x & y is top left corner of the window, y down is positive. +** x and y must fit into the size of the window, values are not controled +** Color byte order is B8G8R8A8, which could be 0xAARRGGBB or 0xBBGGRRAA +** depending on local endianess. +*/ + + +/* +** Images +*/ +void *mlx_new_image(void *mlx_ptr, unsigned int width, unsigned int height); +unsigned char *mlx_get_data_addr(void *img_ptr, unsigned int *bits_per_pixel, + unsigned int *size_line, + unsigned int *format); +int mlx_put_image_to_window(void *mlx_ptr, void *win_ptr, void *img_ptr, + int x, int y); +int mlx_destroy_image(void *mlx_ptr, void *img_ptr); +/* +** mlx_new_image() returns 'void *0' in case of failure. +** mlx_get_data_addr() returns a pointer to a height * size_line bytes buffer +** that holds the pixel values. +** Other functions return 0 on success. +** 'format' can be: 0 = B8G8R8A8; 1 = A8R8G8B8; (byte order). +** Carefully consider the format, it can be reversed in some cases, like a remote graphic server +*/ + + +/* +** deprecated function - format of image allows conversion on student's side +** unsigned int mlx_get_color_value(void *mlx_ptr, int color); +** +*/ + + +/* +** main loop & dealing with events +*/ +typedef int (*mlx_mouse_callback)(unsigned int, unsigned int, unsigned int, void*); +typedef int (*mlx_key_callback)(unsigned int, void *); +typedef int (*mlx_expose_callback)(void *); +typedef int (*mlx_loop_callback)(void *); +typedef int (*mlx_hook_callback)(void *); + +int mlx_loop(void *mlx_ptr); +int mlx_loop_exit(void *mlx_ptr); +int mlx_mouse_hook(void *win_ptr, mlx_mouse_callback funct_ptr, void *param); +int mlx_key_hook(void *win_ptr, mlx_key_callback funct_ptr, void *param); +int mlx_expose_hook(void *win_ptr, mlx_expose_callback funct_ptr, void *param); +int mlx_loop_hook(void *mlx_ptr, mlx_loop_callback funct_ptr, void *param); +/* +** Functions return 0 on success. +** Key event is triggered on KeyRelease, not KeyPressed. +** Mouse event is triggered on clic. +** +** hook functions are called as follow: +** expose_hook(void *param); +** key_hook(unsigned int keycode, void *param); +** mouse_hook(unsigned int button, unsigned int x, unsigned int y, +** void *param); +** loop_hook(void *param); +*/ + +/* +** Generic hook system for all events, and minilibX functions that +** can be hooked. Some macro and defines from X11/X.h are needed here. +** Warning: you may need to cast your function pointer for key and mouse events +** as there will be extra parameters. +*/ +int mlx_hook(void *win_ptr, unsigned int x_event, unsigned int x_mask, + mlx_hook_callback funct_ptr, void *param); + + +/* +** Convenience functions +** mlx_string_put() display may vary in size between OS and between +** mlx implementations +** mlx_string_put() returns 0 on success. +** Other functions return an image (like mlx_new_image()) or 'void *0'. +** +*/ +int mlx_string_put(void *mlx_ptr, void *win_ptr, + unsigned int x, unsigned int y, + unsigned int color, char *string); +void *mlx_xpm_to_image(void *mlx_ptr, const char **xpm_data, + unsigned int *width, unsigned int *height); +void *mlx_xpm_file_to_image(void *mlx_ptr, const char *filename, + unsigned int *width, unsigned int *height); +void *mlx_png_file_to_image(void *mlx_ptr, const char *filename, + unsigned int *width, unsigned int *height); + + + +/* +** Convenience functions +** All functions return 0 on success. +*/ +int mlx_mouse_hide(void *mlx_ptr); +int mlx_mouse_show(void *mlx_ptr); +int mlx_mouse_move(void *win_ptr, int x, int y); +int mlx_mouse_get_pos(void *win_ptr, int *x, int *y); +int mlx_do_key_autorepeatoff(void *mlx_ptr); +int mlx_do_key_autorepeaton(void *mlx_ptr); +int mlx_get_screen_size(void *mlx_ptr, + unsigned int *width, unsigned int *height); + + +/* +** Flush & Sync +*/ +int mlx_do_sync(void *mlx_ptr); +#define MLX_SYNC_IMAGE_WRITABLE 1 +#define MLX_SYNC_WIN_FLUSH 2 +#define MLX_SYNC_WIN_COMPLETED 3 +int mlx_sync(void *mlx_ptr, int cmd, void *param); +/* +** Functions return 0 on success. +** mlx_do_sync() will *flush* (not sync) all requests and wait for completion. +** Note: mlx_loop() always flush requests. +** mlx_sync() 'cmd' commands are: +** - 'image_writable' returns when image data can be written again. +** - 'win_flush' returns when all pending requests are sent to server. +** - 'win_completed' returns after flush and completion. +** 'param' is image pointer or window pointer, according to the command. +** mlx_do_sync() equals 'win_flush' for all windows. +** +*/ + + +#endif /* MLX_H */ diff --git a/mlx/docs/mlx_extra.3 b/mlx/docs/mlx_extra.3 new file mode 100644 index 0000000..7849011 --- /dev/null +++ b/mlx/docs/mlx_extra.3 @@ -0,0 +1,121 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Extra functions +.SH SYNOPSYS + +.nf +.I int +.fi +.B mlx_mouse_hide +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_mouse_show +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_mouse_move +( +.I void *mlx_ptr, int x, int y +); + +.nf +.I int +.fi +.B mlx_mouse_get_pos +( +.I void *win_ptr, int *x, int *y +); + +.nf +.I int +.fi +.B mlx_do_key_autorepeatoff +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_do_key_autorepeaton +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_get_screen_size +( +.I void *mlx_ptr, unsigned int *width, unsigned int *height +); + +.nf +.I int +.fi +.B mlx_do_sync +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_sync +( +.I void *mlx_ptr, int cmd, void *param +); + +.SH MOUSE EXTRA FUNCTIONS + +It is possible to show / hide the mouse, and get its current position without user click or +force its position inside a window. + +.SH KEYBOARD EXTRA FUNCTIONS + +The auto-repeat mode of the keyboard can be controlled. By default, auto-repeat is on: +multiple "key pressed" events are generated every second until the key is released. + +.SH SCREEN EXTRA FUNCTION + +It is possible to retrieve the size of the current screen, even before the first +window is created. + +.SH FLUSH AND SYNC FUNCTIONS + +The +.B mlx_do_sync +function will flush the pending commands to the graphic subsystems, ensuring nothing +is cached on your software's side. On return, there is no guarantee that your +commands have been processed. +.br +With +.B mlx_sync +you have more detailed control over the synchronisation mechanisms. Three different commands +are available: +.br +#define MLX_SYNC_IMAGE_WRITABLE 1 +.br +#define MLX_SYNC_WIN_FLUSH 2 +.br +#define MLX_SYNC_WIN_COMPLETED 3 +.br +The third parameter +.I param +can be either the image identifier (command #1) or the window identifier (commands #2 and #3). + + +.SH SEE ALSO +mlx(3), mlx_new_window(3), mlx_pixel_put(3), mlx_new_image(3), mlx_loop(3) + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/docs/mlx_loop.3 b/mlx/docs/mlx_loop.3 new file mode 100644 index 0000000..7ac4d77 --- /dev/null +++ b/mlx/docs/mlx_loop.3 @@ -0,0 +1,154 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Handle events +.SH SYNOPSYS + +.nf +.I int +.fi +.B mlx_loop +( +.I void *mlx_ptr +); + +.nf +.I int +.fi +.B mlx_key_hook +( +.I void *win_ptr, int (*funct_ptr)(), void *param +); + +.nf +.I int +.fi +.B mlx_mouse_hook +( +.I void *win_ptr, int (*funct_ptr)(), void *param +); + +.nf +.I int +.fi +.B mlx_expose_hook +( +.I void *win_ptr, int (*funct_ptr)(), void *param +); + +.nf +.I int +.fi +.B mlx_loop_hook +( +.I void *mlx_ptr, int (*funct_ptr)(), void *param +); + +.nf +.I int +.fi +.B mlx_loop_exit +( +.I void *mlx_ptr +); + +.SH EVENTS + +The graphical system is bi-directional. On one hand, the program sends orders to +the screen to display pixels, images, and so on. On the other hand, +it can get information from the keyboard and mouse associated to +the screen. To do so, the program receives "events" from the keyboard or the +mouse. + +.SH DESCRIPTION + +To receive events, you must use +.B mlx_loop +(). This function never returns, unless +.B mlx_loop_exit +is called. It is an +infinite loop that waits for an event, and then calls a user-defined +function associated with this event. A single parameter is needed, +the connection identifier +.I mlx_ptr +(see the +.B mlx manual). + +You can assign different functions to the three following events: +.br +- A key is released +.br +- The mouse button is pressed +.br +- A part of the window should be re-drawn +(this is called an "expose" event, and it is your program's job to handle it in the +Unix/Linux X11 environment, but at the opposite it never happens on Unix/Linux Wayland-Vulkan nor on MacOS). +.br + +Each window can define a different function for the same event. + +The three functions +.B mlx_key_hook +(), +.B mlx_mouse_hook +() and +.B mlx_expose_hook +() work exactly the same way. +.I funct_ptr +is a pointer to the function you want to be called +when an event occurs. This assignment is specific to the window defined by the +.I win_ptr +identifier. The +.I param +address will be passed back to your function every time it is called, and should be +used to store the parameters it might need. + +The syntax for the +.B mlx_loop_hook +() function is similar to the previous ones, but the given function will be +called when no event occurs, and is not bound to a specific window. + +When it catches an event, the MiniLibX calls the corresponding function +with fixed parameters: +.nf + + expose_hook(void *param); + key_hook(unsigned int keycode, void *param); + mouse_hook(unsigned int button, unsigned int x, unsigned int y, void *param); + loop_hook(void *param); + +.fi +These function names are arbitrary. They here are used to distinguish +parameters according to the event. These functions are NOT part of the +MiniLibX. + +.I param +is the address specified in the mlx_*_hook calls. This address is never +used nor modified by the MiniLibX. On key and mouse events, additional +information is passed: +.I keycode +tells you which key is pressed (just try to find out :) ), +( +.I x +, +.I y +) are the coordinates of the mouse click in the window, and +.I button +tells you which mouse button was pressed. + +.SH GOING FURTHER WITH EVENTS +The MiniLibX provides a much generic access to other available events. The +.I mlx.h +include define +.B mlx_hook() +in the same manner mlx_*_hook functions work. The event and mask values +will be taken from the historical X11 include file "X.h". Some Wayland and MacOS events are mapped +to these values when it makes sense, and the mask may not be used in some configurations. + +See source code of the MiniLibX to find out how it will +call your own function for a specific event. + +.SH SEE ALSO +mlx(3), mlx_new_window(3), mlx_pixel_put(3), mlx_new_image(3), mlx_extra(3) + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/docs/mlx_new_image.3 b/mlx/docs/mlx_new_image.3 new file mode 100644 index 0000000..0d5eccd --- /dev/null +++ b/mlx/docs/mlx_new_image.3 @@ -0,0 +1,180 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Manipulating images +.SH SYNOPSYS + +.nf +.I void * +.fi +.B mlx_new_image +( +.I void *mlx_ptr, unsigned int width, unsigned int height +); + +.nf +.I unsigned char * +.fi +.B mlx_get_data_addr +( +.I void *img_ptr, unsigned int *bits_per_pixel, unsigned int *size_line, unsigned int *format +); + +.nf +.I int +.fi +.B mlx_put_image_to_window +( +.I void *mlx_ptr, void *win_ptr, void *img_ptr, int x, int y +); + +.nf +.I void * +.fi +.B mlx_xpm_to_image +( +.I void *mlx_ptr, const char **xpm_data, unsigned int *width, unsigned int *height +); + +.nf +.I void * +.fi +.B mlx_xpm_file_to_image +( +.I void *mlx_ptr, const char *filename, unsigned int *width, unsigned int *height +); + +.nf +.I void * +.fi +.B mlx_png_file_to_image +( +.I void *mlx_ptr, const char *filename, unsigned int *width, unsigned int *height +); + +.nf +.I int +.fi +.B mlx_destroy_image +( +.I void *mlx_ptr, void *img_ptr +); + + +.SH DESCRIPTION + +.B mlx_new_image +() creates a new image in memory. It returns a +.I void * +identifier needed to manipulate this image later. It only needs +the size of the image to be created, using the +.I width +and +.I height +parameters, and the +.I mlx_ptr +connection identifier (see the +.B mlx +manual). + +The user can draw inside the image (see below), and +can dump the image inside a specified window at any time to +display it on the screen. This is done using +.B mlx_put_image_to_window +(). Three identifiers are needed here, for the connection to the +display, the window to use, and the image (respectively +.I mlx_ptr +, +.I win_ptr +and +.I img_ptr +). The ( +.I x +, +.I y +) coordinates define where the image should be placed in the window. + +.B mlx_get_data_addr +() returns information about the created image, allowing a user +to modify it later. The +.I img_ptr +parameter specifies the image to use. The three next parameters should +be the addresses of three different valid unsigned integers. +.I bits_per_pixel +will be filled with the number of bits needed to represent a pixel colour +(also called the depth of the image). +.I size_line +is the number of bytes used to store one line of the image in memory. +This information is needed to move from one line to another in the image. +.I format +tells you how each pixel colour in the image is structured. Currently only 2 values are defined: +.P +0 means format B8G8R8A8 +.P +1 means format A8R8G8B8 + +.B mlx_get_data_addr +returns an +.I unsigned char * +address that represents the beginning of the memory area where the image +is stored. From this address, the first +.I bits_per_pixel +bits represent the colour of the first pixel in the first line of +the image. The second group of +.I bits_per_pixel +bits represent the second pixel of the first line, and so on. +Add +.I size_line +to the address to get the beginning of the second line. You can reach any +pixels of the image that way. + +.B mlx_destroy_image +destroys the given image ( +.I img_ptr +). + +.SH STORING COLOURS INSIDE IMAGES + +Depending on the graphic system, the number of bits used to store a pixel colour +used to be different from one hardware to another. Today, the way the user usually +represents a colour, in the ARGB mode, almost always matches the hardware capabilities +on modern computers. + +Keep in mind that packing the 4-byte ARGB into an unsigned int depends on the local +computer's endian. Adjust your code accordingly. + +.SH XPM AND PNG IMAGES + +The +.B mlx_xpm_to_image +() , +.B mlx_xpm_file_to_image +() and +.B mlx_png_file_to_image +() functions will create a new image the same way. +They will fill it using the specified +.I xpm_data +or +.I filename +, depending on which function is used. +Note that MiniLibX does not use the standard +Xpm and png libraries to deal with xpm and png images. You may not be able to +read all types of xpm and png images. It however handles transparency. + +.SH RETURN VALUES +The four functions that create images, +.B mlx_new_image() +, +.B mlx_xpm_to_image() +, +.B mlx_xpm_file_to_image() +and +.B mlx_png_file_to_image() +, will return NULL if an error occurs. Otherwise they return a non-null pointer +as an image identifier. + + +.SH SEE ALSO +mlx(3), mlx_new_window(3), mlx_pixel_put(3), mlx_loop(3), mlx_extra(3) + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/docs/mlx_new_window.3 b/mlx/docs/mlx_new_window.3 new file mode 100644 index 0000000..5619965 --- /dev/null +++ b/mlx/docs/mlx_new_window.3 @@ -0,0 +1,79 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Managing windows +.SH SYNOPSYS + +.nf +.I void * +.fi +.B mlx_new_window +( +.I void *mlx_ptr, unsigned int width, unsigned int height, const char *title +); + +.nf +.I int +.fi +.B mlx_clear_window +( +.I void *mlx_ptr, void *win_ptr +); + +.nf +.I int +.fi +.B mlx_destroy_window +( +.I void *mlx_ptr, void *win_ptr +); + + +.SH DESCRIPTION +The +.B mlx_new_window +() function creates a new window on the screen, using the +.I width +and +.I height +parameters to determine its size, and +.I title +as the text that should be displayed in the window's title bar. +The +.I mlx_ptr +parameter is the connection identifier returned by +.B mlx_init +() (see the +.B mlx +man page). +.B mlx_new_window +() returns a +.I void * +window identifier that can be used by other MiniLibX calls. +Note that the MiniLibX +can handle an arbitrary number of separate windows. + +.B mlx_clear_window +() and +.B mlx_destroy_window +() respectively clear (in black) and destroy the given window. They both have +the same parameters: +.I mlx_ptr +is the screen connection identifier, and +.I win_ptr +is a window identifier. + +.SH RETURN VALUES +If +.B mlx_new_window() +fails to create a new window (whatever the reason), it will return NULL, +otherwise a non-null pointer is returned as a window identifier. +.B mlx_clear_window +and +.B mlx_destroy_window +return nothing. + +.SH SEE ALSO +mlx(3), mlx_pixel_put(3), mlx_new_image(3), mlx_loop(3), mlx_extra(3) + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/docs/mlx_pixel_put.3 b/mlx/docs/mlx_pixel_put.3 new file mode 100644 index 0000000..6aed6e9 --- /dev/null +++ b/mlx/docs/mlx_pixel_put.3 @@ -0,0 +1,83 @@ +.TH MiniLibX 3 "September 19, 2002" +.SH NAME +MiniLibX - Drawing inside windows +.SH SYNOPSYS + +.nf +.I int +.fi +.B mlx_pixel_put +( +.I void *mlx_ptr, void *win_ptr, unsigned int x, unsigned int y, unsigned int color +); + +.nf +.I int +.fi +.B mlx_string_put +( +.I void *mlx_ptr, void *win_ptr, unsigned int x, unsigned int y, unsigned int color, char *string +); + + +.SH DESCRIPTION +The +.B mlx_pixel_put +() function draws a defined pixel in the window +.I win_ptr +using the ( +.I x +, +.I y +) coordinates, and the specified +.I color +\&. The origin (0,0) is the upper left corner of the window, the x and y axis +respectively pointing right and down. The connection +identifier, +.I mlx_ptr +, is needed (see the +.B mlx +man page). + +Parameters for +.B mlx_string_put +() have the same meaning. Instead of a simple pixel, the specified +.I string +will be displayed at ( +.I x +, +.I y +). + +Both functions will discard any display outside the window. This makes +.B mlx_pixel_put +slow. Consider using images instead. + +.SH COLOUR MANAGEMENT +The +.I color +parameter has an unsigned integer type. The displayed colour needs to be encoded +in this integer, following a defined scheme. All displayable colours +can be split in 3 basic colours: red, green and blue. Three associated +values, in the 0-255 range, represent how much of each colour is mixed up +to create the original colour. The fourth byte represent transparency, +where 0 is fully transparent and 255 opaque. Theses four values must be set inside the +unsigned integer to display the right colour. The bytes of +this integer are filled as shown in the picture below: + +.nf + | B | G | R | A | colour integer + +---+---+---+---+ +.fi + +While filling the integer, make sure you avoid endian problems. Example: +the "blue" byte will be the least significant byte inside the integer on a +little endian machine. + + +.SH SEE ALSO +mlx(3), mlx_new_window(3), mlx_new_image(3), mlx_loop(3), mlx_extra(3) + + +.SH AUTHOR +Copyright ol@ - 2002-2025 - Olivier Crouzet diff --git a/mlx/mlx.py b/mlx/mlx.py new file mode 100644 index 0000000..2b79693 --- /dev/null +++ b/mlx/mlx.py @@ -0,0 +1,268 @@ +# MLX python wrapper for Mlx C library +# See mlx manuals and mlx.h from C library for function usage +# C Functions that require addresses to pass back info are converted to +# Pythod methods that return a tuple + + +from ctypes import * +import os + +class Mlx: + + def __init__(self): + module_dir = os.path.dirname(os.path.abspath(__file__)) + self.so_file = os.path.join(module_dir, "libmlx.so") + self.mlx_func = CDLL(self.so_file) + self._python_ref_std = {} + self._python_ref_gen = {} + self._img_height = {} + +# Initialisation + def mlx_init(self): + self.mlx_func.mlx_init.restype = c_void_p + return self.mlx_func.mlx_init() + + def mlx_release(self, mlx_ptr): + self.mlx_func.mlx_release.argtypes = [c_void_p] + self.mlx_func.mlx_release.restypes = [c_int] + return self.mlx_func.mlx_release(mlx_ptr) + +# Windows + def mlx_new_window(self, mlx_ptr, width, height, title): + self.mlx_func.mlx_new_window.argtypes = [c_void_p, c_uint, c_uint, c_char_p] + self.mlx_func.mlx_new_window.restype = c_void_p + return self.mlx_func.mlx_new_window(mlx_ptr, width, height, title.encode('utf-8')) + + def mlx_clear_window(self, mlx_ptr, win_ptr): + self.mlx_func.mlx_clear_window.argtypes = [c_void_p, c_void_p] + self.mlx_func.mlx_clear_window.restype = c_int + return self.mlx_func.mlx_clear_window(mlx_ptr, win_ptr) + + def mlx_pixel_put(self, mlx_ptr, win_ptr, x, y, color): + self.mlx_func.mlx_pixel_put.argtypes = [c_void_p, c_void_p, c_uint, c_uint, c_uint] + self.mlx_func.mlx_pixel_put.restype = c_int + return self.mlx_func.mlx_pixel_put(mlx_ptr, win_ptr, x, y, color) + + def mlx_destroy_window(self, mlx_ptr, win_ptr): + self.mlx_func.mlx_destroy_window.argtypes = [c_void_p, c_void_p] + self.mlx_func.mlx_destroy_window.restype = c_int + return self.mlx_func.mlx_destroy_window(mlx_ptr, win_ptr) + +# Images + def mlx_new_image(self, mlx_ptr, width, height): + self.mlx_func.mlx_new_image.argtypes = [c_void_p, c_uint, c_uint] + self.mlx_func.mlx_new_image.restype = c_void_p + ret = self.mlx_func.mlx_new_image(mlx_ptr, width, height) + if ret is not None: + self._img_height[str(ret)] = height + return ret + +# API break, returns tuple + def mlx_get_data_addr(self, img_ptr): + bits_per_pixel = c_uint() + size_line = c_uint() + theformat = c_uint() + data = POINTER(c_char) + self.mlx_func.mlx_get_data_addr.argtypes = [c_void_p, POINTER(c_uint), POINTER(c_uint), POINTER(c_uint)] + self.mlx_func.mlx_get_data_addr.restype = POINTER(c_char) + data = self.mlx_func.mlx_get_data_addr(img_ptr, byref(bits_per_pixel), byref(size_line), byref(theformat)) + data_array = c_char * (self._img_height[str(img_ptr)] * size_line.value) + data_view = data_array.from_address(addressof(data.contents)) + return (memoryview(data_view).cast('B'), bits_per_pixel.value, size_line.value, theformat.value) + + def mlx_put_image_to_window(self, mlx_ptr, win_ptr, img_ptr, x, y): + self.mlx_func.mlx_put_image_to_window.argtypes = [c_void_p, c_void_p, c_void_p, c_int, c_int] + self.mlx_func.mlx_put_image_to_window.restype = c_int + return self.mlx_func.mlx_put_image_to_window(mlx_ptr, win_ptr, img_ptr, x, y) + + def mlx_destroy_image(self, mlx_ptr, img_ptr): + self._img_height.pop(str(img_ptr)) + self.mlx_func.mlx_destroy_image.argtypes = [c_void_p, c_void_p] + self.mlx_func.mlx_destroy_image.restype = c_int + return self.mlx_func.mlx_destroy_image(mlx_ptr, img_ptr) + +# Events & main loop +# Note: Python can't catch C^-C from keyboard during mlx_loop execution. +# Use C^-\ to kill your program. + + def mlx_loop(self, mlx_ptr): + self.mlx_func.mlx_loop.argtypes = [c_void_p] + self.mlx_func.mlx_loop.restype = c_int + return self.mlx_func.mlx_loop(mlx_ptr) + + def mlx_loop_exit(self, mlx_ptr): + self.mlx_func.mlx_loop_exit.argtypes = [c_void_p] + self.mlx_func.mlx_loop_exit.restype = c_int + return self.mlx_func.mlx_loop_exit(mlx_ptr) + + def mlx_mouse_hook(self, win_ptr, callback, param): + self.mlx_func.mlx_mouse_hook.restype = c_int + if not callback: + self._python_ref_std[str(win_ptr)+"_mouse_f"] = None + self._python_ref_std[str(win_ptr)+"_mouse_p"] = None + self.mlx_func.mlx_mouse_hook.argtypes = [c_void_p, c_void_p, c_void_p] + return self.mlx_func.mlx_mouse_hook(win_ptr, None, None) + callback_type = CFUNCTYPE(None, c_uint, c_uint, c_uint, py_object) + self.mlx_func.mlx_mouse_hook.argtypes = [c_void_p, callback_type, py_object] + callback_ref = callback_type(callback) + self._python_ref_std[str(win_ptr)+"_mouse_f"] = callback_ref + self._python_ref_std[str(win_ptr)+"_mouse_p"] = param + return self.mlx_func.mlx_mouse_hook(win_ptr, callback_ref, param) + + def mlx_key_hook(self, win_ptr, callback, param): + self.mlx_func.mlx_key_hook.restype = c_int + if not callback: + self._python_ref_std[str(win_ptr)+"_key_f"] = None + self._python_ref_std[str(win_ptr)+"_key_p"] = None + self.mlx_func.mlx_key_hook.argtypes = [c_void_p, c_void_p, c_void_p] + return self.mlx_func.mlx_key_hook(win_ptr, None, None) + callback_type = CFUNCTYPE(None, c_uint, py_object) + self.mlx_func.mlx_key_hook.argtypes = [c_void_p, callback_type, py_object] + callback_ref = callback_type(callback) + self._python_ref_std[str(win_ptr)+"_key_f"] = callback_ref + self._python_ref_std[str(win_ptr)+"_key_p"] = param + return self.mlx_func.mlx_key_hook(win_ptr, callback_ref, param) + + def mlx_expose_hook(self, win_ptr, callback, param): + self.mlx_func.mlx_expose_hook.restype = c_int + if not callback: + self._python_ref_std[str(win_ptr)+"_expose_f"] = None + self._python_ref_std[str(win_ptr)+"_expose_p"] = None + self.mlx_func.mlx_expose_hook.argtypes = [c_void_p, c_void_p, c_void_p] + return self.mlx_func.mlx_expose_hook(win_ptr, None, None) + callback_type = CFUNCTYPE(None, py_object) + self.mlx_func.mlx_expose_hook.argtypes = [c_void_p, callback_type, py_object] + callback_ref = callback_type(callback) + self._python_ref_std[str(win_ptr)+"_expose_f"] = callback_ref + self._python_ref_std[str(win_ptr)+"_expose_p"] = param + return self.mlx_func.mlx_expose_hook(win_ptr, callback_ref, param) + + def mlx_loop_hook(self, mlx_ptr, callback, param): + self.mlx_func.mlx_loop_hook.restype = c_int + if not callback: + self._python_ref_std["loop_f"] = None + self._python_ref_std["loop_p"] = None + self.mlx_func.mlx_loop_hook.argtypes = [c_void_p, c_void_p, c_void_p] + return self.mlx_func.mlx_loop_hook(mlx_ptr, None, None) + callback_type = CFUNCTYPE(None, py_object) + self.mlx_func.mlx_loop_hook.argtypes = [c_void_p, callback_type, py_object] + callback_ref = callback_type(callback) + self._python_ref_std["loop_f"] = callback_ref + self._python_ref_std["loop_p"] = param + return self.mlx_func.mlx_loop_hook(mlx_ptr, callback_ref, param) + + def mlx_hook(self, win_ptr, x_event, x_mask, callback, param): + x_event_key = [2, 3] + x_event_mouse = [4, 5] + x_event_motion = [6] + self.mlx_func.mlx_hook.restype = c_int + if not callback: + self._python_ref_gen[str(win_ptr)+"_f_"+str(x_event)] = None + self._python_ref_gen[str(win_ptr)+"_p_"+str(x_event)] = None + self.mlx_func.mlx_hook.argtypes = [c_void_p, c_uint, c_uint, c_void_p, c_void_p] + return self.mlx_func.mlx_hook(win_ptr, 0, 0, None, None) + if x_event in x_event_key: + callback_type = CFUNCTYPE(None, c_uint, py_object) + elif x_event in x_event_mouse: + callback_type = CFUNCTYPE(None, c_uint, c_uint, c_uint, py_object) + elif x_event in x_event_motion: + callback_type = CFUNCTYPE(None, c_uint, c_uint, py_object) + else: + callback_type = CFUNCTYPE(None, py_object) + + self.mlx_func.mlx_hook.argtypes = [c_void_p, c_uint, c_uint, callback_type, py_object] + callback_ref = callback_type(callback) + self._python_ref_gen[str(win_ptr)+"_f_"+str(x_event)] = callback_ref + self._python_ref_gen[str(win_ptr)+"_p_"+str(x_event)] = param + return self.mlx_func.mlx_hook(win_ptr, x_event, x_mask, callback_ref, param) + +# Misc. + + def mlx_string_put(self, mlx_ptr, win_ptr, x, y, color, string): + self.mlx_func.mlx_string_put.argtypes = [c_void_p, c_void_p, c_uint, c_uint, c_uint, c_char_p] + self.mlx_func.mlx_string_put.restype = c_int + return self.mlx_func.mlx_string_put(mlx_ptr, win_ptr, x, y, color, string.encode('utf-8')) + +# API break, returns tuple + def mlx_xpm_file_to_image(self, mlx_ptr, filename): + width = c_uint() + height = c_uint() + self.mlx_func.mlx_xpm_file_to_image.argtypes = [c_void_p, c_char_p, c_void_p, c_void_p] + self.mlx_func.mlx_xpm_file_to_image.restype = c_void_p + img = self.mlx_func.mlx_xpm_file_to_image(mlx_ptr, filename.encode('utf8'), byref(width), byref(height)) + if img is not None: + self._img_height[str(img)] = height.value + return (img, width.value, height.value) + +# API break, returns tuple + def mlx_png_file_to_image(self, mlx_ptr, filename): + width = c_uint() + height = c_uint() + self.mlx_func.mlx_png_file_to_image.argtypes = [c_void_p, c_char_p, c_void_p, c_void_p] + self.mlx_func.mlx_png_file_to_image.restype = c_void_p + img = self.mlx_func.mlx_png_file_to_image(mlx_ptr, filename.encode('utf8'), byref(width), byref(height)) + if img is not None: + self._img_height[str(img)] = height.value + return (img, width.value, height.value) + +# not really usefull in Python context +#void *mlx_xpm_to_image(void *mlx_ptr, const char **xpm_data, +# unsigned int *width, unsigned int *height); + + def mlx_mouse_hide(self, mlx_ptr): + self.mlx_func.mlx_mouse_hide.argtypes = [c_void_p] + self.mlx_func.mlx_mouse_hide.restype = c_int + return self.mlx_func.mlx_mouse_hide(mlx_ptr) + + def mlx_mouse_show(self, mlx_ptr): + self.mlx_func.mlx_mouse_show.argtypes = [c_void_p] + self.mlx_func.mlx_mouse_show.restype = c_int + return self.mlx_func.mlx_mouse_show(mlx_ptr) + + def mlx_mouse_move(self, mlx_ptr, x, y): + self.mlx_func.mlx_mouse_move.argtypes = [c_void_p, c_int, c_int] + self.mlx_func.mlx_mouse_move.restype = c_int + return self.mlx_func.mlx_mouse_move(mlx_ptr, x, y) + +# API break, returns tuple + def mlx_mouse_get_pos(self, mlx_ptr): + x = c_int() + y = c_int() + self.mlx_func.mlx_mouse_get_pos.argtypes = [c_void_p, c_void_p, c_void_p] + self.mlx_func.mlx_mouse_get_pos.restype = c_int + val = self.mlx_func.mlx_mouse_get_pos(mlx_ptr, byref(x), byref(y)) + return (val, x.value, y.value) + + def mlx_do_key_autorepeatoff(self, mlx_ptr): + self.mlx_func.mlx_do_key_autorepeatoff.argtypes = [c_void_p] + self.mlx_func.mlx_do_key_autorepeatoff.restype = c_int + return self.mlx_func.mlx_do_key_autorepeatoff(mlx_ptr) + + def mlx_do_key_autorepeaton(self, mlx_ptr): + self.mlx_func.mlx_do_key_autorepeaton.argtypes = [c_void_p] + self.mlx_func.mlx_do_key_autorepeaton.restype = c_int + return self.mlx_func.mlx_do_key_autorepeaton(mlx_ptr) + +# API break, returns tuple + def mlx_get_screen_size(self, mlx_ptr): + w = c_uint() + h = c_uint() + self.mlx_func.mlx_get_screen_size.argtypes = [c_void_p, POINTER(c_uint), POINTER(c_uint)] + self.mlx_func.mlx_get_screen_size.restype = c_int + val = self.mlx_func.mlx_get_screen_size(mlx_ptr, byref(w), byref(h)) + return (val, w.value, h.value) + +# Sync funct + def mlx_do_sync(self, mlx_ptr): + self.mlx_func.mlx_do_sync.argtypes = [c_void_p] + self.mlx_func.mlx_do_sync.restype = c_int + return self.mlx_func.mlx_do_sync(mlx_ptr) + + def mlx_sync(self, mlx_ptr, cmd, img_or_win_ptr): + self.mlx_func.mlx_sync.argtypes = [c_void_p, c_int, c_void_p] + self.mlx_func.mlx_sync.restype = c_int + return self.mlx_func.mlx_sync(mlx_ptr, cmd, img_or_win_ptr) + + SYNC_IMAGE_WRITABLE = 1 + SYNC_WIN_FLUSH = 2 + SYNC_WIN_COMPLETED = 3 diff --git a/mlx/test/Dont_panic.png b/mlx/test/Dont_panic.png new file mode 100644 index 0000000..f823ff8 Binary files /dev/null and b/mlx/test/Dont_panic.png differ diff --git a/mlx/test/Dont_panic.xpm b/mlx/test/Dont_panic.xpm new file mode 100644 index 0000000..100c67a --- /dev/null +++ b/mlx/test/Dont_panic.xpm @@ -0,0 +1,250 @@ +/* XPM */ +static char *Dont_panic[] = { +/* columns rows colors chars-per-pixel */ +"64 64 180 2 ", +" c #000000", +". c #020D03", +"X c #0D0E0A", +"o c #090906", +"O c #130F02", +"+ c #031505", +"@ c #051B06", +"# c #12120E", +"$ c #181814", +"% c #370D03", +"& c #002304", +"* c #012D06", +"= c #07280B", +"- c #04360A", +"; c #0C3F11", +": c #113F16", +"> c #20201B", +", c #37372D", +"< c #3E3E33", +"1 c #4E1205", +"2 c #5E1706", +"3 c #691A07", +"4 c #73240F", +"5 c #034A0B", +"6 c #005C0B", +"7 c #01640D", +"8 c #006E0D", +"9 c #15670D", +"0 c #00710D", +"q c #096815", +"w c #047512", +"e c #097A16", +"r c #0D7D1A", +"t c #077414", +"y c #107D1C", +"u c #11681B", +"i c #1B4420", +"p c #057E25", +"a c #0A7B22", +"s c #05772A", +"d c #057A2B", +"f c #047723", +"g c #197B24", +"h c #276E2E", +"j c #49580C", +"k c #6A4D0D", +"l c #53601A", +"z c #44443C", +"x c #4B4C3D", +"c c #504F41", +"v c #535345", +"b c #58584D", +"n c #5C5C53", +"m c #5C6153", +"M c #666859", +"N c #7B7B6C", +"B c #767764", +"V c #AE3A0E", +"C c #B9370E", +"Z c #C52F0C", +"A c #C6300D", +"S c #C8320E", +"D c #CB3511", +"F c #CF3A14", +"G c #C93C18", +"H c #D33C16", +"J c #D23E18", +"K c #B65726", +"L c #98662B", +"P c #D3431C", +"I c #DC451C", +"U c #DC491E", +"Y c #D54C1E", +"T c #E14A1F", +"R c #DC4C24", +"E c #D94C26", +"W c #DC5A33", +"Q c #E14D22", +"! c #E05A32", +"~ c #DF6039", +"^ c #E3643D", +"/ c #E56B43", +"( c #E5724A", +") c #05861E", +"_ c #0F801B", +"` c #068A1C", +"' c #068F1A", +"] c #11821E", +"[ c #07921B", +"{ c #08941D", +"} c #058322", +"| c #068922", +" . c #098D24", +".. c #05842C", +"X. c #068B2C", +"o. c #088426", +"O. c #158421", +"+. c #198926", +"@. c #1D8D29", +"#. c #1A8626", +"$. c #0A9224", +"%. c #0D952A", +"&. c #0E9A2C", +"*. c #0A9528", +"=. c #109C2E", +"-. c #068D31", +";. c #068730", +":. c #069433", +">. c #069A35", +",. c #079E38", +"<. c #119D32", +"1. c #22882D", +"2. c #22922E", +"3. c #269532", +"4. c #299435", +"5. c #299936", +"6. c #2D9D39", +"7. c #2B9739", +"8. c #308A3A", +"9. c #07A63B", +"0. c #14A235", +"q. c #15A339", +"w. c #32A23E", +"e. c #36A541", +"r. c #3AA746", +"t. c #3AA946", +"y. c #3EAD49", +"u. c #63985E", +"i. c #40AE4B", +"p. c #43A64E", +"a. c #43B24E", +"s. c #46B451", +"d. c #49B654", +"f. c #4AB956", +"g. c #4EBD59", +"h. c #50BF5B", +"j. c #50B158", +"k. c #6F9266", +"l. c #61A862", +"z. c #63B667", +"x. c #66B76B", +"c. c #52C15E", +"v. c #56C461", +"b. c #58C763", +"n. c #5BC966", +"m. c #5ECD69", +"M. c #61CF6C", +"N. c #64C66C", +"B. c #63D16E", +"V. c #76C57B", +"C. c #66D471", +"Z. c #68D773", +"A. c #6BD976", +"S. c #6EDC79", +"D. c #70DE7B", +"F. c #72E07D", +"G. c #8D927F", +"H. c #7FC381", +"J. c #76E481", +"K. c #79E783", +"L. c #7CEA86", +"P. c #7FEC89", +"I. c #969986", +"U. c #8BBF8C", +"Y. c #9BAF93", +"T. c #A8AA9A", +"R. c #A3B59A", +"E. c #ADB1A2", +"W. c #B5B7A9", +"Q. c #83C286", +"!. c #96C998", +"~. c #81EE8B", +"^. c #84F28F", +"/. c #86F491", +"(. c #8CF996", +"). c #8BF895", +"_. c #ABC9A8", +"`. c #C5C6BB", +"'. c #CACAC0", +"]. c None", +/* pixels */ +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].;.].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].,.>.].-.;.].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].]...].].-.,.].-.,.].]...].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].:.].]...X.].-.-.].:.:.].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].o.].].} p p o.p ].>.-.].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].p ].} ) ].} p ].p ..].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].) | ) ) ) ) } p p ].].].].].].].].].].@.3.3.4.7.].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].]. .&.<.%.` ) ) } p ].].].].].].].+.@.3.3.5.6.6.e.e.e.e.e.].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].| <.q.<.0.&.) ) | ].].].].].g +.@.2.3.5.6.6.e.t.e.t.t.t.y.y.t.].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].]. .<.<.[ $.0.$.) ].].].].].] +.@.@.5.6.6.e.e.y.y.y.a.a.s.s.s.a.a.i.].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].| <.<.' [ =.$.` | >.>.].O.+.@.2.5.5.w.e.t.y.y.y.s.d.f.f.f.f.f.f.s.s.].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].| %.q.<.0.0. .) | o.o.O.+.@.2.5.6.w.e.y.y.s.s.f.g.c.c.c.c.c.c.h.g.g.d.].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].| .&.&.` ` ].].e r O.+.2.3.5.w.e.y.y.s.f.g.c.v.v.b.n.n.n.b.b.v.c.h.f.].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].| | ) ` ].].].].r ] +.@.3.5.6.e.y.y.s.f.g.v.v.n.m.M.B.B.M.M.m.n.b.v.h.d.].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].o.} ].].].].].e _ O.@.2.5.6.e.y.y.s.g.g.v.b.m.B.B.C.Z.A.Z.Z.C.M.m.n.v.h.d.].].].].].].].].].].].].].].].].].].", +"].].].].].].].].X.-.].].].].].].e ] +.@.3.5.w.e.y.y.d.g.v.b.m.B.Z.A.S.D.D.D.S.A.Z.B.m.n.v.g.].].].].].].].].].].].].].].].].].].", +"].].].].].].].].:.].].].].].].t r O.+.2.3.6.w.t.y.s.g.c.b.m.C.Z.S.F.J.J.K.J.J.D.S.Z.B.m.b.c.d.].].].].].].].].].].].].].].].].].", +"].].].].].].].:.-.].].].].].].t _ O.@.2.7.6.e.t.s.d.g.v.b.B.C.A.F.J.L.P.~.P.K.J.F.A.C.M.n.v.g.].].].].].].].].].].].].].].].].].", +"].].].].].].:.:.].].].].].].w e ] O.@.2.7.w.e.y.s.d.c.v.m.C.Z.F.J.L.~././.^.~.L.J.S.Z.B.n.v.g.].].].].].].].].].].].].].].].].].", +"].].].].].;.-.d ].].].].].].w e ] +.@.1.4.w.r.y.s.f.c.v.m.C.A.F.J.P./.).(.).^.P.J.D.A.B.m.v.h.d.].].].].].].].].].].].].].].].].", +"].].].]...-.d ].].].].].].].w e ] u = + @ h r.y.s.f.v.v.m.C.A.F.K.~./.).(./.^.L.J.D.Z.B.n.v.h.d.].].].].].].].].].].].].].].].].", +"].].].].d d d d ;.:.9.9.,.e w e q + o M U.y.s.d.c.v.m.B.Z.F.J.P.^.^./.^.P.K.F.S.Z.M.n.c.g.d.].].].].].].].].].].].].].].].].", +"].].].].d d s d d d ;.-.:.d w e - X B E.l.y.d.c.v.m.B.Z.S.F.J.K.P.~.P.K.J.D.A.C.m.b.c.g.s.].].].].].].].].].].].].].].].].", +"].].].].].].].].].d s d d f w t + $ v I.x.s.g.c.b.m.C.Z.S.F.J.J.J.J.F.D.A.C.M.n.v.h.f.a.].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].8 w 7 . c `._.f.f.c.v.b.B.B.A.A.S.D.D.D.A.A.C.M.m.v.c.g.s.i.].].].].].].].:.-.].].].].].].].", +"].].].].].].].].].].].].].].w 7 . $ B N u.d.g.c.c.n.B.B.C.C.C.A.C.C.B.m.n.v.c.g.f.s.y.].].].].].].;.9.].].-.].].].].].", +"].].].].].].].].].].].].].].8 8 + o o , E.Q.j.c.c.c.c.n.m.M.M.M.N.V.H.z.h.c.g.f.a.y.e.].].].].].].X.;.].:.,.].].].].].", +"].].].].].].].].].].].].].].0 0 * z `._.u.j.f.c.c.c.b.n.M.U.k.W.`.m i p.f.a.y.t.e.].].].].].p p ]...:.:.].].].].].", +"].].].].].].].].].].].].].].0 0 5 # n b v R.!.l.z.V.x.u.R.T.c M m $ i a.y.t.w.5.o.:.].].p } ].p ....].>.:.].].].", +"].].].].].].].].].].].].].].8 0 8 @ < T.E.M G.`.I., v x X . 8.t.e.6.].].X.X.].) } ) p p ]...:.].].].].", +"].].].].].].].].].].].].].].].0 0 5 X < < # x N x o h w.6.7.].].} } ) ) ) ) ) ].p p p ].].].].", +"].].].].].].].].].].].].].].].8 0 8 * o X o 1.5.5.].].].| | %.%.` ` ) ) } o.].].].].].", +"].].].].].].].].].].].].].].].].0 0 8 & : 3.3.2.].].].| <.0.0.<. .` ) } ].].].].].].", +"].].].].].].].].].].].].].].].].8 8 0 7 @ = g 3.@.].].].]. .0.&.{ =.<.| ) ].| :.-.].].].", +"].].].].].].].].].].].].].].].].].8 0 0 7 & = g 2.#.].].].].].$.0.*.' [ 0.&.) } X.>.].].].].", +"].].].].].].].].].].].].].].].].].].8 0 0 8 - + o 5 g +.O.O.].].].].]. .&.$.' ' =.<.| } ].].].].].].", +"].].].].].].].].].].].].].].].].].].].0 0 0 0 6 * O 1 3 3 3 3 % . = u O.] ] y ].].].].].].| ) ) ' ' ` .].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].8 0 0 0 0 9 k C P E J G 4 O * 5 q y _ a a a ].].].].].].].| | ) ` ` ].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].8 0 0 0 8 j G / ^ R ~ l w e e e t f d ;.].].].].].].X.o.].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].8 0 0 9 V W / R ^ L 0 w 0 0 ].].d -.:.].].].].:...].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].0 9 V J Q U E K 9 ].].].].].d ..,.].].].>.;.].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].S H I T Y I ].].].].].].].d :.,.].].;.d ].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].A S I T Y I ].].].].].].].s d -.]...d ].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z S J Q E U ].].].].].].].].s d d d d ].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z H I U U I ].].].].].].].].d d d ].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z S J I T R P ].].].].].].].d s s ].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z Z H R R ! ! G ].].].].].].].d ].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z D E ^ ( W D ].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z A F J D Z ].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].Z Z S ].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].", +"].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].].]." +}; diff --git a/mlx/test/mlxtest.py b/mlx/test/mlxtest.py new file mode 100644 index 0000000..b146e6a --- /dev/null +++ b/mlx/test/mlxtest.py @@ -0,0 +1,276 @@ +# Mlx large test + +import sys +from mlx import Mlx # Import Mlx class + +class ImgData: + """Structure for image data""" + def __init__(self): + self.img = None + self.width = 0 + self.height = 0 + self.data = None + self.sl = 0 # size line + self.bpp = 0 # bits per pixel + self.iformat = 0 + +class XVar: + """Structure for main vars""" + def __init__(self): + self.mlx = None + self.mlx_ptr = None + self.screen_w = 0 + self.screen_h = 0 + self.win_1 = None + self.win_2 = None + self.img_1 = ImgData() + self.img_2 = ImgData() + self.img_png = ImgData() + self.img_xpm = ImgData() + self.imgidx = 0 + +def draw_colormap(xvar): + """Draw the colormap""" + print("Drawing colormap...") + for i in range(400): + for j in range(400): + r = int((0xFF * i) / 400) + g = int((0xFF * j) / 400) + b = int((0xFF * (400 - (i + j) // 2)) / 400) + col = 0xFF000000 | (r << 16) | (g << 8) | b + xvar.mlx.mlx_pixel_put(xvar.mlx_ptr, xvar.win_1, i, j, col) + +def gere_key_press(key, xvar): + print(f"Pressed key {key}") + +def gere_key(key, xvar): + print(f"Got key {key}: ", end="") + + if key == 113: # 'q' + xvar.mlx.mlx_do_key_autorepeatoff(xvar.mlx_ptr) + print("key repeat off") + return 0 + elif key == 119: # 'w' + xvar.mlx.mlx_do_key_autorepeaton(xvar.mlx_ptr) + print("key repeat on") + return 0 + elif key == 101: # 'e' + draw_colormap(xvar) + print("colormap") + return 0 + elif key == 114: # 'r' + xvar.mlx.mlx_mouse_hide(xvar.mlx_ptr) + print("mouse hide") + return 0 + elif key == 116: # 't' + xvar.mlx.mlx_mouse_show(xvar.mlx_ptr) + print("mouse show") + return 0 + elif key == 121: # 'y' + xvar.mlx.mlx_mouse_move(xvar.win_1, 200, 200) + print("mouse move") + return 0 + elif key == 117: # 'u' + ret, x, y = xvar.mlx.mlx_mouse_get_pos(xvar.win_1) + print(f"current mouse pos is {x} x {y}") + return 0 + elif key == 105: # 'i' + xvar.mlx.mlx_sync(xvar.mlx_ptr, Mlx.SYNC_IMAGE_WRITABLE, xvar.img_2.img) + # fill image in white + for offset in range(0, xvar.img_2.sl * 100, 4): + xvar.img_2.data[offset:offset+4] = (0xFFFFFFFF).to_bytes(4, 'little') + + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_2.img, 50, 50) + + # update in red + for offset in range(0, xvar.img_2.sl * 100, 4): + xvar.img_2.data[offset:offset+4] = (0xFFFF0000).to_bytes(4, 'little') + + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_2.img, 250, 250) + print("update image without sync - most likely 2 red squares") + return 0 + elif key == 111: # 'o' + xvar.mlx.mlx_sync(xvar.mlx_ptr, Mlx.SYNC_IMAGE_WRITABLE, xvar.img_2.img) + # fill image in white + for offset in range(0, xvar.img_2.sl * 100, 4): + xvar.img_2.data[offset:offset+4] = (0xFFFFFFFF).to_bytes(4, 'little') + + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_2.img, 50, 50) + xvar.mlx.mlx_sync(xvar.mlx_ptr, Mlx.SYNC_IMAGE_WRITABLE, xvar.img_2.img) + + # update in red + for offset in range(0, xvar.img_2.sl * 100, 4): + xvar.img_2.data[offset:offset+4] = (0xFFFF0000).to_bytes(4, 'little') + + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_2.img, 250, 250) + print("update image with sync - white and red squares") + return 0 + + # Default + print("clear and string put") + xvar.mlx.mlx_clear_window(xvar.mlx_ptr, xvar.win_1) + xvar.mlx.mlx_string_put(xvar.mlx_ptr, xvar.win_1, 20, 20, 0xFFFF00FF, "Hello MLX!") + + +def gere_expose(xvar): + print("Expose !") + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_1.img, 0, 0) + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, xvar.win_1, xvar.img_1.img, 201, 201) + +def gere_mouse(button, x, y, xvar, win): + print(f"Got mouse : {button} at {x}x{y}") + + if button == 1: + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, win, xvar.img_1.img, 100, 100) + return 0 + + if button == 3: # right click + if xvar.imgidx % 2: + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, win, xvar.img_png.img, x, y) + else: + xvar.mlx.mlx_put_image_to_window(xvar.mlx_ptr, win, xvar.img_xpm.img, x, y) + xvar.imgidx += 1 + +def gere_mouse_1(button, x, y, xvar): + gere_mouse(button, x, y, xvar, xvar.win_1) + +def gere_mouse_2(button, x, y, xvar): + gere_mouse(button, x, y, xvar, xvar.win_2) + +def gere_close_1(xvar): + xvar.mlx.mlx_loop_exit(xvar.mlx_ptr) + +def gere_close_2(xvar): + xvar.mlx.mlx_destroy_window(xvar.mlx_ptr, xvar.win_2) + xvar.win_2 = None + +def main(): + xvar = XVar() + # Mlx Initialisation + try: + xvar.mlx = Mlx() + except Exception as e: + print(f"Error: Can't initialize MLX: {e}", file=sys.stderr) + sys.exit(1) + + xvar.mlx_ptr = xvar.mlx.mlx_init() + + ret, xvar.screen_w, xvar.screen_h = xvar.mlx.mlx_get_screen_size(xvar.mlx_ptr) + print(f"Screen size: {xvar.screen_w} x {xvar.screen_h}") + + # Windows creation + try: + xvar.win_1 = xvar.mlx.mlx_new_window(xvar.mlx_ptr, 400, 400, "MLX main win") + if not xvar.win_1: + raise Exception("Can't create main window") + + xvar.win_2 = xvar.mlx.mlx_new_window(xvar.mlx_ptr, 150, 150, "Secondary window") + if not xvar.win_2: + raise Exception("Can't create secondary window") + except Exception as e: + print(f"Error Win create: {e}", file=sys.stderr) + sys.exit(1) + + # Image #1 + xvar.img_1.img = xvar.mlx.mlx_new_image(xvar.mlx_ptr, 200, 200) + if not xvar.img_1.img: + raise Exception("Can't create image 1") + + xvar.img_1.width = 200 + xvar.img_1.height = 200 + xvar.img_1.data, xvar.img_1.bpp, xvar.img_1.sl, xvar.img_1.iformat = \ + xvar.mlx.mlx_get_data_addr(xvar.img_1.img) + + # Fill image #1 + for i in range(xvar.img_1.sl * 200): + xvar.img_1.data[i] = 0x80 + + for i in range(xvar.img_1.sl * 100): + xvar.img_1.data[i] = 0xFF + + try: + # Add some red pixels + pixel_positions = [ + 0 * 200 * 4, # top left + (1 * 200 + 1) * 4, # top left + 1 + (199 * 200 + 199) * 4, # bottom right + (198 * 200 + 198) * 4 # bottom right - 1 + ] + + for pos in pixel_positions: + if pos < len(xvar.img_1.data) - 3: + xvar.img_1.data[pos:pos+4] = (0xFFFF0000).to_bytes(4, 'little') + except Exception as e: + print(f"Error img1: {e}", file=sys.stderr) + sys.exit(1) + + # Image #2 + try: + xvar.img_2.img = xvar.mlx.mlx_new_image(xvar.mlx_ptr, 100, 100) + if not xvar.img_2.img: + raise Exception("Can't create image 2") + + xvar.img_2.width = 100 + xvar.img_2.height = 100 + xvar.img_2.data, xvar.img_2.bpp, xvar.img_2.sl, xvar.img_2.iformat = \ + xvar.mlx.mlx_get_data_addr(xvar.img_2.img) + except Exception as e: + print(f"Error img2: {e}", file=sys.stderr) + sys.exit(1) + + # Load PNG & XPM + result = xvar.mlx.mlx_png_file_to_image(xvar.mlx_ptr, "puffy_small.png") + if not result: + raise Exception("Can't load PNG") + xvar.img_png.img, xvar.img_png.width, xvar.img_png.height = result + if not xvar.img_png.img: + raise Exception("Can't create png") + xvar.img_png.data, xvar.img_png.bpp, xvar.img_png.sl, xvar.img_png.iformat = \ + xvar.mlx.mlx_get_data_addr(xvar.img_png.img) + + result = xvar.mlx.mlx_xpm_file_to_image(xvar.mlx_ptr, "Dont_panic.xpm") + if not result: + raise Exception("Can't load XPM") + xvar.img_xpm.img, xvar.img_xpm.width, xvar.img_xpm.height = result + xvar.img_xpm.data, xvar.img_xpm.bpp, xvar.img_xpm.sl, xvar.img_xpm.iformat = \ + xvar.mlx.mlx_get_data_addr(xvar.img_xpm.img) + + # event hooks + xvar.mlx.mlx_key_hook(xvar.win_1, gere_key, xvar) + xvar.mlx.mlx_hook(xvar.win_2, 2, 1, gere_key_press, xvar) # KeyPress event + xvar.mlx.mlx_expose_hook(xvar.win_1, gere_expose, xvar) + xvar.mlx.mlx_mouse_hook(xvar.win_1, gere_mouse_1, xvar) + xvar.mlx.mlx_mouse_hook(xvar.win_2, gere_mouse_2, xvar) + xvar.mlx.mlx_hook(xvar.win_1, 33, 0, gere_close_1, xvar) # WM_DELETE_WINDOW + xvar.mlx.mlx_hook(xvar.win_2, 33, 0, gere_close_2, xvar) # WM_DELETE_WINDOW + + # User Instructions + print("On main window:") + print(" mouse button 1: place white/gray image in 0x0 and 200x200") + print(" mouse button 2: place png image and xpm image, alternatively") + print(" try keys QWERTYUIO and others") + print(" click window's X button to end the program") + print("On secondary window (smaller):") + print(" show key pressed for auto repeat") + print(" click window's X button to close it") + + # Main loop + xvar.mlx.mlx_loop(xvar.mlx_ptr) + + # Cleaning resources + print("destroy xpm") + xvar.mlx.mlx_destroy_image(xvar.mlx_ptr, xvar.img_xpm.img) + print("destroy png") + xvar.mlx.mlx_destroy_image(xvar.mlx_ptr, xvar.img_png.img) + print("destroy imgs") + xvar.mlx.mlx_destroy_image(xvar.mlx_ptr, xvar.img_1.img) + xvar.mlx.mlx_destroy_image(xvar.mlx_ptr, xvar.img_2.img) + print("destroy win(s)") + xvar.mlx.mlx_destroy_window(xvar.mlx_ptr, xvar.win_1) + if xvar.win_2: + xvar.mlx.mlx_destroy_window(xvar.mlx_ptr, xvar.win_2) + print("destroy mlx") + xvar.mlx.mlx_release(xvar.mlx_ptr) + +if __name__ == "__main__": + main() diff --git a/mlx/test/puffy.png b/mlx/test/puffy.png new file mode 100644 index 0000000..eb2eec6 Binary files /dev/null and b/mlx/test/puffy.png differ diff --git a/mlx/test/puffy_small.png b/mlx/test/puffy_small.png new file mode 100644 index 0000000..d70dfeb Binary files /dev/null and b/mlx/test/puffy_small.png differ diff --git a/mlx/test/simple_test.py b/mlx/test/simple_test.py new file mode 100644 index 0000000..f0607db --- /dev/null +++ b/mlx/test/simple_test.py @@ -0,0 +1,29 @@ + +from mlx import Mlx + +def mymouse(button, x, y, mystuff): + print(f"Got mouse event! button {button} at {x},{y}.") + +def mykey(keynum, mystuff): + print(f"Got key {keynum}, and got my stuff back:") + print(mystuff) + if keynum == 32: + m.mlx_mouse_hook(win_ptr, None, None) + +def gere_close(dummy): + m.mlx_loop_exit(mlx_ptr) + +m = Mlx() +mlx_ptr = m.mlx_init() +win_ptr = m.mlx_new_window(mlx_ptr, 200, 200, "win title") +m.mlx_clear_window(mlx_ptr, win_ptr) +m.mlx_string_put(mlx_ptr, win_ptr, 20, 20, 255, "Hello PyMlx!") +(ret, w, h) = m.mlx_get_screen_size(mlx_ptr) +print(f"Got screen size: {w} x {h} .") + +stuff = [1, 2] +m.mlx_mouse_hook(win_ptr, mymouse, None) +m.mlx_key_hook(win_ptr, mykey, stuff) +m.mlx_hook(win_ptr, 33, 0, gere_close, None) + +m.mlx_loop(mlx_ptr) diff --git a/src/AMazeIng.py b/src/AMazeIng.py index 7389b0b..3e1f951 100644 --- a/src/AMazeIng.py +++ b/src/AMazeIng.py @@ -1,22 +1,20 @@ -from dataclasses import field -from os import eventfd_read from typing import Generator -import numpy from typing_extensions import Self -from pydantic import AfterValidator, BaseModel, Field, model_validator +from pydantic import BaseModel, Field, model_validator, ConfigDict -from amaz_lib import Maze, MazeGenerator, MazeSolver -from amaz_lib.Cell import Cell +from src.amaz_lib import Maze, MazeGenerator, MazeSolver class AMazeIng(BaseModel): + model_config = ConfigDict(arbitrary_types_allowed=True) + width: int = Field(ge=3) height: int = Field(ge=3) entry: tuple[int, int] exit: tuple[int, int] output_file: str = Field(min_length=3) perfect: bool = Field(default=True) - maze: Maze = Field(default=Maze(maze=numpy.array([]))) + maze: Maze = Field(default=Maze(None)) generator: MazeGenerator solver: MazeSolver diff --git a/src/amaz_lib/MazeGenerator.py b/src/amaz_lib/MazeGenerator.py index 636c1bd..f07fc23 100644 --- a/src/amaz_lib/MazeGenerator.py +++ b/src/amaz_lib/MazeGenerator.py @@ -8,7 +8,7 @@ import math class MazeGenerator(ABC): @abstractmethod def generator( - self, height: int, width: int, seed: int = None + self, height: int, width: int, seed: int | None = None ) -> Generator[np.ndarray, None, np.ndarray]: ... @staticmethod @@ -113,7 +113,7 @@ class Kruskal(MazeGenerator): return s1 in cells_ft or s2 in cells_ft def generator( - self, height: int, width: int, seed: int = None + self, height: int, width: int, seed: int | None = None ) -> Generator[np.ndarray, None, np.ndarray]: cells_ft = None if height > 10 and width > 10: diff --git a/src/parsing/Parsing.py b/src/parsing/Parsing.py index fc1fbcc..97bf839 100644 --- a/src/parsing/Parsing.py +++ b/src/parsing/Parsing.py @@ -1,3 +1,7 @@ +from src.amaz_lib.MazeGenerator import DepthFirstSearch, Kruskal +from src.amaz_lib.MazeSolver import AStar + + class DataMaze: @staticmethod @@ -11,28 +15,30 @@ class DataMaze: @staticmethod def transform_data(data: str) -> dict: tmp = data.split("\n") - tmp2 = [ - value.split("=", 1) for value in tmp - ] - data_t = { - value[0]: value[1] for value in tmp2 - } + tmp2 = [value.split("=", 1) for value in tmp if "=" in value] + data_t = {value[0]: value[1] for value in tmp2} return data_t @staticmethod def verif_key_data(data: dict) -> None: key_test = { - "WIDTH", "HEIGHT", "ENTRY", "EXIT", "OUTPUT_FILE", "PERFECT" - } - set_key = { - key for key in data.keys() + "WIDTH", + "HEIGHT", + "ENTRY", + "EXIT", + "OUTPUT_FILE", + "PERFECT", + "GENERATOR", + "SOLVER", } + set_key = {key for key in data.keys()} if len(set_key) != len(key_test): raise KeyError("Missing some data the len do not correspond") res_key = {key for key in set_key if key not in key_test} if len(res_key) != 0: - raise KeyError("Some Key " - f"do not correspond the keys: {res_key}") + raise KeyError( + "Some Key " f"do not correspond the keys: {res_key}" + ) @staticmethod def convert_values(data: dict): @@ -47,8 +53,44 @@ class DataMaze: for key in key_bool: res.update({key: DataMaze.convert_bool(data[key])}) res.update({"OUTPUT_FILE": data["OUTPUT_FILE"]}) + res.update( + DataMaze.get_solver_generator(data, res["ENTRY"], res["EXIT"]) + ) return res + @staticmethod + def get_solver_generator(data: dict, entry: int, exit: int) -> dict: + available_generator = { + "Kruskal": Kruskal, + "DFS": DepthFirstSearch, + } + available_solver = { + "AStar": AStar, + } + res = {} + res["GENERATOR"] = available_generator[data["GENERATOR"]]() + res["SOLVER"] = available_solver[data["SOLVER"]](entry, exit) + return res + + @staticmethod + def convert_tuple(data: str) -> tuple: + data_t = data.split(",") + if len(data_t) != 2: + raise ValueError( + "There is too much " "argument in the coordinate given" + ) + x, y = data_t + tup = (int(x), int(y)) + return tup + + @staticmethod + def convert_bool(data: str) -> bool: + if data != "True" and data != "False": + raise ValueError("This is not True or False") + if data == "True": + return True + return False + @staticmethod def get_data_maze(name_file: str) -> dict: try: @@ -56,7 +98,7 @@ class DataMaze: data_dict = DataMaze.transform_data(data_str) DataMaze.verif_key_data(data_dict) data_maze = DataMaze.convert_values(data_dict) - return data_maze + return {k.lower(): v for k, v in data_maze.items()} except FileNotFoundError: print("The file do not exist") exit() @@ -70,28 +112,11 @@ class DataMaze: print(f"Error on the key in the file: {e}") exit() except IndexError as e: - print("In the function transform Data some data cannot " - f"be splited by '=' because '=' was not present: {e}") + print( + "In the function transform Data some data cannot " + f"be splited by '=' because '=' was not present: {e}" + ) exit() except AttributeError as e: - print("Error on the " - f"funciton get_data_maze : {e}") + print("Error on the " f"funciton get_data_maze : {e}") exit() - - @staticmethod - def convert_tuple(data: str) -> tuple: - data_t = data.split(",") - if len(data_t) != 2: - raise ValueError("There is too much " - "argument in the coordinate given") - x, y = data_t - tup = (int(x), int(y)) - return tup - - @staticmethod - def convert_bool(data: str) -> bool: - if data != "True" and data != "False": - raise ValueError("This is not True or False") - if data == "True": - return True - return False