part: implement some functions (windows & display)
part:
- remove mlx3ds_3dskey.h, instead use hid.h
- add definitions of:
- mlx_init()
- mlx_new_window()
- mlx_clear_window()
- mlx_destroy_window()
- mlx_pixel_put()
- mlx_new_image()
- mlx_get_data_addr()
- mlx_put_image_to_window()
- mlx_destroy_image()
dev:
- Makefile: add rule check_headers
- Makefile: add variable FLAGS
(call 'make rule FLAGS=flags'
to add flags to compilation)
- add /dev/norm.sh: nicer norminette
- add tester in main(), and related utilsconsole.*
docs:
- make clear mlx_get_data_addr() docs
This commit is contained in:
parent
c7d0dba4fd
commit
13b93106ee
19 changed files with 766 additions and 141 deletions
205
source/main.cpp
205
source/main.cpp
|
|
@ -1,25 +1,182 @@
|
|||
#include <3ds.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
gfxInitDefault();
|
||||
consoleInit(GFX_TOP, NULL);
|
||||
|
||||
printf("Test Code::Blocks project!");
|
||||
extern "C" {
|
||||
#include "mlx.h"
|
||||
#include "3ds.h"
|
||||
}
|
||||
#include <iostream>
|
||||
#include <string.h>
|
||||
#include "utilsconsole.hpp"
|
||||
|
||||
printf("\x1b[20;15HPress Start to exit.");
|
||||
|
||||
while(aptMainLoop()) {
|
||||
gspWaitForVBlank();
|
||||
hidScanInput();
|
||||
|
||||
if(hidKeysDown() & KEY_START)
|
||||
break;
|
||||
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
|
||||
gfxExit();
|
||||
return 0;
|
||||
}
|
||||
using namespace std;
|
||||
|
||||
static void draw_rainbow_image(t_mlx mlx, t_win win, int x, int y)
|
||||
{
|
||||
cout << "Draw rainbow image at (" << x << "," << y << ")..." << endl;
|
||||
uc_pause();
|
||||
{
|
||||
static const u32 red = 0xFF0000;
|
||||
static const u32 green = 0x00FF00;
|
||||
static const u32 blue = 0x0000FF;
|
||||
t_image img = mlx_new_image(mlx, 30, 30);
|
||||
char *img_data = mlx_get_data_addr(img, NULL, NULL, NULL);
|
||||
for (int x = 0; x < 30; x++)
|
||||
{
|
||||
for (int y = 0; y < 20; y++)
|
||||
{
|
||||
if (x < 10)
|
||||
memcpy(img_data + 3 * (y * 30 + x), &red, 3);
|
||||
else if (x < 20)
|
||||
memcpy(img_data + 3 * (y * 30 + x), &green, 3);
|
||||
else
|
||||
memcpy(img_data + 3 * (y * 30 + x), &blue, 3);
|
||||
}
|
||||
}
|
||||
mlx_put_image_to_window(mlx, win, img, x, y);
|
||||
mlx_destroy_image(mlx, img);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
void *const mlx = mlx_init();
|
||||
void *win;
|
||||
|
||||
// MENU
|
||||
{
|
||||
switch (uc_menu_quick("pixels", "images", "quit", NULL))
|
||||
{
|
||||
case 0:
|
||||
goto pixels;
|
||||
break;
|
||||
case 1:
|
||||
goto images;
|
||||
break;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
pixels:
|
||||
cout << "create window..." << endl;
|
||||
uc_pause();
|
||||
win = mlx_new_window(mlx, 400, 240, "hey");
|
||||
|
||||
cout << "clear window..." << endl;
|
||||
uc_pause();
|
||||
mlx_clear_window(mlx, win);
|
||||
|
||||
cout
|
||||
<< "Put pixels for red green and blue" << endl
|
||||
<< "at the top-left corner..." << endl;
|
||||
uc_pause();
|
||||
{
|
||||
int block_y = 20;
|
||||
for (
|
||||
int block_x = 20, color = 0xFF0000;
|
||||
block_x <= 60;
|
||||
block_x += 20, color = color >> 8
|
||||
)
|
||||
for (int x = 0; x < 10; x++)
|
||||
for (int y = 0; y < 10; y++)
|
||||
mlx_pixel_put(mlx, win, block_x + x, block_y + y, color);
|
||||
}
|
||||
|
||||
cout << "clear window..." << endl;
|
||||
uc_pause();
|
||||
mlx_clear_window(mlx, win);
|
||||
|
||||
cout << "destroy window..." << endl;
|
||||
uc_pause();
|
||||
mlx_destroy_window(mlx, win);
|
||||
|
||||
goto end;
|
||||
|
||||
images:
|
||||
cout << "create window..." << endl;
|
||||
uc_pause();
|
||||
win = mlx_new_window(mlx, 400, 240, "hoi");
|
||||
|
||||
cout << "clear window..." << endl;
|
||||
uc_pause();
|
||||
mlx_clear_window(mlx, win);
|
||||
|
||||
draw_rainbow_image(mlx, win, 185, 110);
|
||||
draw_rainbow_image(mlx, win, -15, 100);
|
||||
draw_rainbow_image(mlx, win, 385, 120);
|
||||
draw_rainbow_image(mlx, win, 170, -10);
|
||||
draw_rainbow_image(mlx, win, 200, 230);
|
||||
draw_rainbow_image(mlx, win, -15, -10);
|
||||
draw_rainbow_image(mlx, win, 385, -10);
|
||||
draw_rainbow_image(mlx, win, -15, 230);
|
||||
draw_rainbow_image(mlx, win, 385, 230);
|
||||
|
||||
cout << "Draw RG image at (20,10)..." << endl;
|
||||
uc_pause();
|
||||
{
|
||||
t_image img = mlx_new_image(mlx, 30, 20);
|
||||
char *img_data = mlx_get_data_addr(img, NULL, NULL, NULL);
|
||||
for (int x = 0; x < 30; x++)
|
||||
{
|
||||
for (int y = 0; y < 20; y++)
|
||||
{
|
||||
u32 color =
|
||||
((0xFF0000 * x / 30) & 0xFF0000)
|
||||
| ((0x00FF00 * y / 20) & 0x00FF00);
|
||||
memcpy(img_data + 3 * (y * 30 + x), &color, 3);
|
||||
}
|
||||
}
|
||||
mlx_put_image_to_window(mlx, win, img, 20, 10);
|
||||
mlx_destroy_image(mlx, img);
|
||||
}
|
||||
|
||||
cout << "Draw GB image at (50,0)..." << endl;
|
||||
uc_pause();
|
||||
{
|
||||
t_image img = mlx_new_image(mlx, 10, 50);
|
||||
char *img_data = mlx_get_data_addr(img, NULL, NULL, NULL);
|
||||
for (int x = 0; x < 10; x++)
|
||||
{
|
||||
for (int y = 0; y < 50; y++)
|
||||
{
|
||||
u32 color =
|
||||
((0x00FF00 * x / 10) & 0x00FF00)
|
||||
| ((0x0000FF * y / 50) & 0x0000FF);
|
||||
memcpy(img_data + 3 * (y * 10 + x), &color, 3);
|
||||
}
|
||||
}
|
||||
mlx_put_image_to_window(mlx, win, img, 50, 0);
|
||||
mlx_destroy_image(mlx, img);
|
||||
}
|
||||
|
||||
cout << "Draw BR image at (200,100)..." << endl;
|
||||
uc_pause();
|
||||
{
|
||||
t_image img = mlx_new_image(mlx, 100, 100);
|
||||
char *img_data = mlx_get_data_addr(img, NULL, NULL, NULL);
|
||||
for (int x = 0; x < 100; x++)
|
||||
{
|
||||
for (int y = 0; y < 100; y++)
|
||||
{
|
||||
u32 color =
|
||||
((0x0000FF * x / 100) & 0x0000FF)
|
||||
| ((0xFF0000 * y / 100) & 0xFF0000);
|
||||
memcpy(img_data + 3 * (y * 100 + x), &color, 3);
|
||||
}
|
||||
}
|
||||
mlx_put_image_to_window(mlx, win, img, 200, 100);
|
||||
mlx_destroy_image(mlx, img);
|
||||
}
|
||||
|
||||
cout << "clear window..." << endl;
|
||||
uc_pause();
|
||||
mlx_clear_window(mlx, win);
|
||||
|
||||
cout << "destroy window..." << endl;
|
||||
uc_pause();
|
||||
mlx_destroy_window(mlx, win);
|
||||
|
||||
goto end;
|
||||
|
||||
end:
|
||||
cout << "Exit..." << endl;
|
||||
uc_pause();
|
||||
|
||||
gfxExit();
|
||||
}
|
||||
|
|
|
|||
123
source/mlx_image.c
Normal file
123
source/mlx_image.c
Normal file
|
|
@ -0,0 +1,123 @@
|
|||
/**
|
||||
* mlx_image.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "mlx_image.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "mlx_internal.h"
|
||||
#include "mlx_inline.c"
|
||||
|
||||
t_image mlx_new_image(void *mlx_ptr, int width, int height)
|
||||
{
|
||||
t_internal_image *r;
|
||||
|
||||
(void)mlx_ptr;
|
||||
r = NULL;
|
||||
r = malloc(sizeof(t_internal_image));
|
||||
if (!r)
|
||||
goto error;
|
||||
r->data = NULL;
|
||||
r->data = malloc(width * height * 3 * sizeof(u8));
|
||||
if (!r->data)
|
||||
goto error;
|
||||
r->width = width;
|
||||
r->height = height;
|
||||
return (r);
|
||||
|
||||
error:
|
||||
free(r);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
int mlx_destroy_image(t_mlx mlx_ptr, t_image img_ptr)
|
||||
{
|
||||
if (img_ptr)
|
||||
free(((t_internal_image *)img_ptr)->data);
|
||||
free(img_ptr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
char *mlx_get_data_addr(t_image img_ptr, int *bits_per_pixel,
|
||||
int *size_line, int *endian)
|
||||
{
|
||||
if (bits_per_pixel)
|
||||
*bits_per_pixel = 24;
|
||||
if (size_line)
|
||||
*size_line = 3 * ((t_internal_image *)img_ptr)->width;
|
||||
if (endian)
|
||||
*endian = 1;
|
||||
return ((char *)((t_internal_image *)img_ptr)->data);
|
||||
}
|
||||
|
||||
/// @brief Return the minimum between a and b.
|
||||
/// @param a Number a.
|
||||
/// @param b Number b.
|
||||
/// @return The result.
|
||||
static inline int min(int a, int b)
|
||||
{
|
||||
return (a < b ? a : b);
|
||||
}
|
||||
|
||||
/// @brief Return the maximum between a and b.
|
||||
/// @param a Number a.
|
||||
/// @param b Number b.
|
||||
/// @return The result.
|
||||
static inline int max(int a, int b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
int mlx_put_image_to_window(t_mlx mlx_ptr, t_win win_ptr, t_image img_ptr,
|
||||
int x, int y)
|
||||
{
|
||||
// buffers
|
||||
u8 *frame_data, *img_data;
|
||||
int // dimensions
|
||||
frame_width, frame_height, img_width, img_height,
|
||||
// interval of pixels to draw, to avoid drawing outside of the buffer
|
||||
min_x_on_screen, max_x_on_screen, min_y_on_screen, max_y_on_screen,
|
||||
// position relative to frame
|
||||
x_on_screen, y_on_screen;
|
||||
// variables that contain results of constant expressions
|
||||
int a, b;
|
||||
u8 *c, *d, *e, *f;
|
||||
|
||||
mlx3ds_internal_drawstart(mlx_ptr, win_ptr);
|
||||
frame_data = ((t_internal_win *)win_ptr)->framebuffer;
|
||||
frame_width = ((t_internal_win *)win_ptr)->framebuffer_width;
|
||||
frame_height = ((t_internal_win *)win_ptr)->framebuffer_height;
|
||||
img_data = ((t_internal_image *)img_ptr)->data;
|
||||
img_width = ((t_internal_image *)img_ptr)->width;
|
||||
img_height = ((t_internal_image *)img_ptr)->height;
|
||||
min_x_on_screen = max(x, 0);
|
||||
max_x_on_screen = min(x + img_width, frame_width);
|
||||
min_y_on_screen = max(y, 0);
|
||||
max_y_on_screen = min(y + img_height, frame_height);
|
||||
a = 3 * img_width;
|
||||
b = 3 * frame_height;
|
||||
c = img_data - 3 * x - a * y;
|
||||
d = frame_data - 3 + b;
|
||||
|
||||
x_on_screen = min_x_on_screen;
|
||||
while (x_on_screen < max_x_on_screen)
|
||||
{
|
||||
e = c + 3 * x_on_screen;
|
||||
f = d + b * x_on_screen;
|
||||
|
||||
y_on_screen = min_y_on_screen;
|
||||
while (y_on_screen < max_y_on_screen)
|
||||
{
|
||||
mlx_inline_drawcolor(
|
||||
f - 3 * y_on_screen,
|
||||
e + a * y_on_screen);
|
||||
y_on_screen++;
|
||||
}
|
||||
x_on_screen++;
|
||||
}
|
||||
mlx3ds_internal_drawend(mlx_ptr, win_ptr);
|
||||
return (0);
|
||||
}
|
||||
29
source/mlx_init.c
Normal file
29
source/mlx_init.c
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* mlx_init.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "mlx_init.h"
|
||||
|
||||
#include "mlx_internal.h"
|
||||
#include <stdlib.h>
|
||||
#include "3ds.h"
|
||||
|
||||
static t_internal_mlx g_internal_mlx = {
|
||||
.is_init_called = false,
|
||||
.top_window = NULL,
|
||||
};
|
||||
|
||||
t_mlx mlx_init(void)
|
||||
{
|
||||
if (g_internal_mlx.is_init_called)
|
||||
mlx3ds_internal_fatalerror("mlx_init() must be called only once");
|
||||
g_internal_mlx.is_init_called = true;
|
||||
gfxInitDefault();
|
||||
gfxSetDoubleBuffering(GFX_TOP, false);
|
||||
gfxSetDoubleBuffering(GFX_BOTTOM, false);
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
return (&g_internal_mlx);
|
||||
}
|
||||
31
source/mlx_inline.c
Normal file
31
source/mlx_inline.c
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/**
|
||||
* mlx_inline.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "3ds.h"
|
||||
|
||||
/// @brief Write a color at a specific location of the memory,
|
||||
/// the 3 color values will be in the same order.
|
||||
/// It's basically a memcpy of 3 bytes.
|
||||
/// @param dest Address to the first color value of the destination.
|
||||
/// @param src Address to the first color value of the source.
|
||||
inline void mlx_inline_drawcolor(u8 *dest, u8 *src)
|
||||
{
|
||||
dest[0] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[2] = src[2];
|
||||
}
|
||||
|
||||
/// @brief Write a color at a specific location of the memory,
|
||||
/// the 3 color values will be in opposite order.
|
||||
/// @param dest Address to the first color value of the destination.
|
||||
/// @param src Address to the first color value of the source.
|
||||
inline void mlx_inline_drawcolor_invert(u8 *dest, u8 *src)
|
||||
{
|
||||
dest[2] = src[0];
|
||||
dest[1] = src[1];
|
||||
dest[0] = src[2];
|
||||
}
|
||||
35
source/mlx_internal.cpp
Normal file
35
source/mlx_internal.cpp
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* mlx_internal.cpp
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "utilsconsole.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "mlx_internal.h"
|
||||
#include "3ds.h"
|
||||
|
||||
void mlx3ds_internal_fatalerror(const char *msg)
|
||||
{
|
||||
consoleInit(GFX_BOTTOM, NULL);
|
||||
printf("\e[0;31m[mlx3ds] Fatal error:\e[0m\n%s\n", msg);
|
||||
uc_pause();
|
||||
}
|
||||
|
||||
void mlx3ds_internal_drawstart(
|
||||
t_internal_mlx *mlx_ptr, t_internal_win *win_ptr)
|
||||
{
|
||||
win_ptr->framebuffer = gfxGetFramebuffer(GFX_TOP, GFX_LEFT,
|
||||
&win_ptr->framebuffer_height, &win_ptr->framebuffer_width);
|
||||
gspWaitForVBlank();
|
||||
}
|
||||
|
||||
void mlx3ds_internal_drawend(
|
||||
t_internal_mlx *mlx_ptr, t_internal_win *win_ptr)
|
||||
{
|
||||
gfxFlushBuffers();
|
||||
gfxSwapBuffers();
|
||||
}
|
||||
}
|
||||
71
source/mlx_internal.h
Normal file
71
source/mlx_internal.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* mlx_internal.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
/**
|
||||
* Internal utils of the mlx3ds.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "3ds.h"
|
||||
|
||||
/// @brief Write an error message and exit the program.
|
||||
///
|
||||
/// @param msg Message to write. Must use less than 38 colons.
|
||||
void mlx3ds_internal_fatalerror(const char *msg);
|
||||
|
||||
typedef struct s_internal_win t_internal_win;
|
||||
|
||||
/// @brief Content of the mlx connection identifier.
|
||||
typedef struct s_internal_mlx
|
||||
{
|
||||
/// @brief is true after mlx_init() was called, is false before.
|
||||
bool is_init_called;
|
||||
/// @brief Window displayed on the top screen.
|
||||
t_internal_win *top_window;
|
||||
} t_internal_mlx;
|
||||
|
||||
/// @brief Represents a window.
|
||||
typedef struct s_internal_win
|
||||
{
|
||||
/// @brief mlx connection identifier
|
||||
t_internal_mlx *mlx;
|
||||
/// @brief Width of the window
|
||||
int width;
|
||||
/// @brief Height of the window
|
||||
int height;
|
||||
/// @brief Buffer of the screen.
|
||||
u8 *framebuffer;
|
||||
/// @brief Width of the screen (on x).
|
||||
u16 framebuffer_width;
|
||||
/// @brief Height of the screen (on y).
|
||||
u16 framebuffer_height;
|
||||
} t_internal_win;
|
||||
|
||||
/// @brief Represents an image in memory.
|
||||
typedef struct s_internal_image
|
||||
{
|
||||
/// @brief Width of the image
|
||||
int width;
|
||||
/// @brief Height of the image
|
||||
int height;
|
||||
/// @brief Address of the image data. Returned by mlx_get_data_addr().
|
||||
u8 *data;
|
||||
} t_internal_image;
|
||||
|
||||
/// @brief To call before drawing. Init winptr->framebuffer.
|
||||
///
|
||||
/// @param mlx_ptr mlx connection identifier
|
||||
/// @param win_ptr Reference to the window to draw on.
|
||||
void mlx3ds_internal_drawstart(
|
||||
t_internal_mlx *mlx_ptr, t_internal_win *win_ptr);
|
||||
|
||||
/// @brief To call when finish drawing. Flush and swap buffers.
|
||||
///
|
||||
/// @param mlx_ptr mlx connection identifier
|
||||
/// @param win_ptr Reference to the window to draw on.
|
||||
void mlx3ds_internal_drawend(
|
||||
t_internal_mlx *mlx_ptr, t_internal_win *win_ptr);
|
||||
32
source/mlx_put.c
Normal file
32
source/mlx_put.c
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
* mlx_put.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "mlx_put.h"
|
||||
|
||||
#include "mlx_internal.h"
|
||||
#include "mlx_inline.c"
|
||||
|
||||
int mlx_pixel_put(t_mlx mlx_ptr, t_win win_ptr, int x, int y, int color)
|
||||
{
|
||||
u8 *frame;
|
||||
|
||||
mlx3ds_internal_drawstart(mlx_ptr, win_ptr);
|
||||
|
||||
if (x < 0 || x >= ((t_internal_win *)win_ptr)->framebuffer_width
|
||||
|| y < 0 || y >= ((t_internal_win *)win_ptr)->framebuffer_height)
|
||||
return (0);
|
||||
frame = ((t_internal_win *)win_ptr)->framebuffer;
|
||||
mlx_inline_drawcolor(
|
||||
frame + 3 * (
|
||||
(x + 1) * ((t_internal_win *)win_ptr)->framebuffer_height - y - 1
|
||||
),
|
||||
(u8 *)&color);
|
||||
|
||||
mlx3ds_internal_drawend(mlx_ptr, win_ptr);
|
||||
|
||||
return (0);
|
||||
}
|
||||
52
source/mlx_window.c
Normal file
52
source/mlx_window.c
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/**
|
||||
* mlx_window.c
|
||||
* for the project "MinilibX for 3DS"
|
||||
* by Zy
|
||||
* at https://github.com/frzysk/mlx3ds
|
||||
*/
|
||||
|
||||
#include "mlx_window.h"
|
||||
|
||||
#include "3ds.h"
|
||||
#include "mlx_internal.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
t_win mlx_new_window(t_mlx mlx_ptr, int size_x, int size_y, const char *title)
|
||||
{
|
||||
t_internal_win *r;
|
||||
|
||||
(void)title;
|
||||
if (size_x > GSP_SCREEN_HEIGHT_TOP || size_y > GSP_SCREEN_WIDTH)
|
||||
mlx3ds_internal_fatalerror("Window too big for the screen");
|
||||
r = malloc(sizeof(t_internal_win));
|
||||
if (!r)
|
||||
return (NULL);
|
||||
r->mlx = mlx_ptr;
|
||||
r->width = size_x;
|
||||
r->height = size_y;
|
||||
r->framebuffer = NULL;
|
||||
return (r);
|
||||
}
|
||||
|
||||
int mlx_clear_window(t_mlx mlx_ptr, t_win win_ptr)
|
||||
{
|
||||
u8 *frame_i;
|
||||
u8 *frame;
|
||||
|
||||
mlx3ds_internal_drawstart(mlx_ptr, win_ptr);
|
||||
frame = ((t_internal_win *)win_ptr)->framebuffer;
|
||||
frame_i = frame
|
||||
+ 3 * ((t_internal_win *)win_ptr)->framebuffer_width
|
||||
* ((t_internal_win *)win_ptr)->framebuffer_height;
|
||||
while (--frame_i >= frame)
|
||||
*frame_i = 0x00;
|
||||
mlx3ds_internal_drawend(mlx_ptr, win_ptr);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int mlx_destroy_window(t_mlx mlx_ptr, t_win win_ptr)
|
||||
{
|
||||
((t_internal_mlx *)mlx_ptr)->top_window = NULL;
|
||||
free(win_ptr);
|
||||
return (0);
|
||||
}
|
||||
93
source/utilsconsole.cpp
Normal file
93
source/utilsconsole.cpp
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/**
|
||||
* utilsconsole.cpp
|
||||
* by Zy
|
||||
*/
|
||||
|
||||
#include "utilsconsole.hpp"
|
||||
|
||||
#include <3ds.h>
|
||||
#include <iostream>
|
||||
#include <stdarg.h>
|
||||
|
||||
int uc_menu(vector<s_uc_menu_element> &elements) {
|
||||
static void *lastElements = NULL;
|
||||
static size_t selected = 0;
|
||||
|
||||
bool confirmed = false;
|
||||
|
||||
if (&elements != lastElements) {
|
||||
// init if new menu
|
||||
consoleClear();
|
||||
lastElements = &elements;
|
||||
selected = 0;
|
||||
}
|
||||
else {
|
||||
// read inputs
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_UP) {
|
||||
if (selected-- == 0)
|
||||
selected += elements.size();
|
||||
}
|
||||
else if (hidKeysDown() & KEY_DOWN) {
|
||||
if (++selected >= elements.size())
|
||||
selected -= elements.size();
|
||||
}
|
||||
else if (!elements[selected].is_number_prompt) {
|
||||
if (hidKeysDown() & KEY_A) {
|
||||
confirmed = true;
|
||||
lastElements = NULL;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (hidKeysDown() & KEY_LEFT)
|
||||
if (*elements[selected].value > elements[selected].min)
|
||||
(*elements[selected].value)--;
|
||||
if (hidKeysDown() & KEY_RIGHT)
|
||||
if (*elements[selected].value < elements[selected].max)
|
||||
(*elements[selected].value)++;
|
||||
}
|
||||
}
|
||||
|
||||
// display
|
||||
cout << "\e[H\e[0m";
|
||||
for (size_t i = 0; i < elements.size(); i++) {
|
||||
cout << (i == selected && !confirmed ? "\e[7m" : "")
|
||||
<< elements[i].name << "\e[0m";
|
||||
if (elements[i].is_number_prompt)
|
||||
cout
|
||||
<< ((*(elements[i].value) == elements[i].min) ? " " : " <")
|
||||
<< *(elements[i].value)
|
||||
<< ((*(elements[i].value) == elements[i].max) ? " " : ">");
|
||||
cout << "\e[0K" << endl;
|
||||
}
|
||||
if (!confirmed)
|
||||
cout << "\e[2m" << "[Up/Down] Move / "
|
||||
<< (elements[selected].is_number_prompt ?
|
||||
"[Left/Right] Modify" : "(A) Confirm") << "\e[0K" << endl;
|
||||
else
|
||||
cout << "\e[2mOK.\e[0K\e[0m" << endl;
|
||||
|
||||
return confirmed ? selected : -1;
|
||||
}
|
||||
|
||||
int uc_menu_quick(const char *str, ...) {
|
||||
va_list arguments;
|
||||
auto elements = vector<s_uc_menu_element>();
|
||||
for (va_start(arguments, str); str; str = va_arg(arguments, const char *))
|
||||
elements.push_back({str, false, NULL, 0, 0});
|
||||
|
||||
int r = -1;
|
||||
while (r < 0 && aptMainLoop())
|
||||
r = uc_menu(elements);
|
||||
return r;
|
||||
}
|
||||
|
||||
void uc_pause(void) {
|
||||
cout << "\e[0;2mPress (A) to continue...\e[0m" << endl;
|
||||
while (aptMainLoop()) {
|
||||
hidScanInput();
|
||||
if (hidKeysDown() & KEY_A)
|
||||
break;
|
||||
gfxFlushBuffers();
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue