Browse Source

add main menu

master
Alexandros Theodotou 2 years ago
parent
commit
76572a8d19
Signed by: alex GPG Key ID: 022EAE42313D70F3
  1. 19
      data/glsl/unchanged.frag
  2. 19
      data/glsl/unchanged.vert
  3. 83
      inc/gui/button_with_text.h
  4. 24
      inc/gui/drawable.h
  5. 23
      inc/gui/main_menu.h
  6. 10
      inc/gui/skin.h
  7. 23
      src/game/ion_world.c
  8. 147
      src/gui/button_with_text.c
  9. 31
      src/gui/drawable.c
  10. 145
      src/gui/main_menu.c
  11. 1
      src/gui/meson.build
  12. 70
      src/gui/skin.c
  13. 2
      src/gui/skin_manager.c

19
data/glsl/unchanged.frag

@ -1,3 +1,22 @@
/*
* Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Ion
*
* Ion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Ion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#version 430
/* this is the currently bound texture */

19
data/glsl/unchanged.vert

@ -1,3 +1,22 @@
/*
* Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Ion
*
* Ion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Ion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#version 430
/* screen size we can use to convert the coordinates

83
inc/gui/button_with_text.h

@ -0,0 +1,83 @@
/*
* Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Ion
*
* Ion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Ion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
/**
* \file
*
* Themable button with text.
*/
#ifndef __GUI_BUTTON_WITH_TEXT_H__
#define __GUI_BUTTON_WITH_TEXT_H__
#include "gui/cursor.h"
#include "gui/rgba.h"
typedef struct Texture Texture;
typedef struct IonDrawable IonDrawable;
/**
* @addtogroup gui
*
* @{
*/
typedef struct ButtonWithText
{
/** Text to show. */
char * text;
/** If themable, the button will use the button
* background of the skin. */
int themable;
/** These are used if themable. */
IonDrawable * left_drawable;
IonDrawable * middle_drawable;
IonDrawable * right_drawable;
/** The text rendered as a texture. */
IonDrawable * text_drawable;
} ButtonWithText;
ButtonWithText *
button_with_text_new (
const char * text,
int themable);
/**
* Updates the position.
*
* Must be called at least once before drawing.
*/
void
button_with_text_update_position (
ButtonWithText * self,
float x,
float y);
void
button_with_text_draw (
ButtonWithText * self);
/**
* @}
*/
#endif

24
inc/gui/drawable.h

@ -91,6 +91,13 @@ typedef struct IonDrawable
unsigned int indices[6];
} IonDrawable;
/**
* Creates a new drawable with a texture.
*
* @param position Position to start drawing at.
* @param size Size of the drawable, independent
* of the texture.
*/
IonDrawable *
drawable_new_with_texture (
ShaderType shader_type,
@ -98,6 +105,13 @@ drawable_new_with_texture (
Vector2f * position,
Vector2f * size);
/**
* Updates the position and size of the drawable.
*
* @param position Position to start drawing at.
* @param size Size of the drawable, independent
* of the texture.
*/
void
drawable_update_position (
IonDrawable * self,
@ -108,6 +122,16 @@ void
drawable_draw (
IonDrawable * self);
/**
* Returns if the drawable is hit by the given
* x,y positions.
*/
int
drawable_hit (
IonDrawable * self,
double x,
double y);
void
drawable_free (
IonDrawable * self);

23
inc/gui/main_menu.h

@ -21,6 +21,7 @@
#define __GUI_MAIN_MENU_H__
typedef struct Texture Texture;
typedef struct ButtonWithText ButtonWithText;
/**
* @addtogroup gui
@ -29,12 +30,32 @@ typedef struct Texture Texture;
*/
/**
* A drawable logo, as part of a Skin.
* Main menu options.
*/
typedef struct MainMenu
{
/** 1 if currently showing options (play, options,
* etc). */
int showing_options;
ButtonWithText * play;
ButtonWithText * options;
ButtonWithText * exit;
} MainMenu;
/**
* Creates the main menu.
*/
MainMenu *
main_menu_new (void);
/**
* Updates the main menu before drawing.
*/
void
main_menu_update (
MainMenu * self);
void
main_menu_draw (
MainMenu * self);

10
inc/gui/skin.h

@ -39,6 +39,11 @@ typedef struct IonDrawable IonDrawable;
* @{
*/
#define CURRENT_SKIN \
(ION_WORLD->skin_manager->current_skin)
#define CURRENT_LOGO \
(CURRENT_SKIN->logo)
typedef enum SkinFormatVersion
{
SKIN_FORMAT_VERSION_1_0,
@ -66,6 +71,11 @@ typedef struct Skin
IonDrawable * logo;
IonDrawable * menu_bg;
Texture * button_left;
Texture * button_middle;
Texture * button_right;
Texture * selection_mod_autoplay;
Texture * selection_mod_cinema;
Texture * selection_mod_doubletime;

23
src/game/ion_world.c

@ -75,6 +75,8 @@ ion_world_load_skin (
{
self->skin_manager =
skin_manager_new (self->skins_dir);
self->main_menu = main_menu_new ();
}
#if 0
@ -138,25 +140,22 @@ ion_world_render_scene (
break;
case ION_WORLD_SCREEN_MAIN_MENU:
{
/* draw bg stretched */
drawable_draw (
self->skin_manager->current_skin->
menu_bg);
drawable_draw (
self->skin_manager->current_skin->
logo);
/* update variables */
main_menu_update (
self->main_menu);
/* draw */
main_menu_draw (self->main_menu);
/* draw cursor */
cursor_draw (
&self->skin_manager->current_skin->cursor);
}
break;
default:
break;
}
/* draw cursor */
cursor_draw (
&self->skin_manager->current_skin->cursor);
self->last_draw_time = glfwGetTime ();
}

147
src/gui/button_with_text.c

@ -0,0 +1,147 @@
/*
* Copyright (C) 2019 Alexandros Theodotou <alex at zrythm dot org>
*
* This file is part of Ion
*
* Ion is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* Ion is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU General Affero Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdlib.h>
#include <glib.h>
#include "game/ion_world.h"
#include "gui/button_with_text.h"
#include "gui/drawable.h"
#include "gui/shader.h"
#include "gui/skin.h"
#include "gui/skin_manager.h"
#include "gui/texture.h"
#include "math/vector.h"
#include "utils/pango.h"
ButtonWithText *
button_with_text_new (
const char * text,
int themable)
{
ButtonWithText * self =
calloc (1, sizeof (ButtonWithText));
self->themable = themable;
self->text = g_strdup (text);
Vector2f pos = { 0.f, 0.f };
Vector2f size;
if (themable)
{
size.x =
(float) CURRENT_SKIN->button_left->width;
size.y =
(float) CURRENT_SKIN->button_left->height;
self->left_drawable =
drawable_new_with_texture (
SHADER_TYPE_UNCHANGED,
CURRENT_SKIN->button_left,
&pos, &size);
size.x =
(float) CURRENT_SKIN->button_middle->width;
size.y =
(float) CURRENT_SKIN->button_middle->height;
self->middle_drawable =
drawable_new_with_texture (
SHADER_TYPE_UNCHANGED,
CURRENT_SKIN->button_middle,
&pos, &size);
size.x =
(float) CURRENT_SKIN->button_right->width;
size.y =
(float) CURRENT_SKIN->button_right->height;
self->right_drawable =
drawable_new_with_texture (
SHADER_TYPE_UNCHANGED,
CURRENT_SKIN->button_right,
&pos, &size);
}
Texture * text_texture =
ion_pango_render_text_to_texture (
"Sans 24", text);
size.x =
(float) text_texture->width;
size.y =
(float) text_texture->height;
self->text_drawable =
drawable_new_with_texture (
SHADER_TYPE_UNCHANGED, text_texture,
&pos, &size);
return self;
}
/**
* Updates the position.
*
* Must be called at least once before drawing.
*/
void
button_with_text_update_position (
ButtonWithText * self,
float x,
float y)
{
Vector2f pos = { x, y };
Vector2f size = { 0.f, 0.f };
/* left */
drawable_update_position (
self->left_drawable, &pos,
&self->left_drawable->size);
/* middle */
pos.x = x + self->left_drawable->size.x;
pos.y = y;
size.x = self->text_drawable->size.x + 4.f;
size.y = self->middle_drawable->size.y;
drawable_update_position (
self->middle_drawable, &pos, &size);
/* right */
pos.x =
x + self->left_drawable->size.x +
self->middle_drawable->size.x;
pos.y = y;
drawable_update_position (
self->right_drawable, &pos,
&self->right_drawable->size);
/* text */
pos.x = x + self->left_drawable->size.x + 2.f;
pos.y = y;
size.x = self->text_drawable->size.x;
size.y = self->text_drawable->size.y;
drawable_update_position (
self->text_drawable, &pos,
&self->text_drawable->size);
}
void
button_with_text_draw (
ButtonWithText * self)
{
drawable_draw (self->left_drawable);
drawable_draw (self->middle_drawable);
drawable_draw (self->right_drawable);
drawable_draw (self->text_drawable);
}

31
src/gui/drawable.c

@ -26,6 +26,13 @@
#include "gui/shader.h"
#include "gui/texture.h"
/**
* Creates a new drawable with a texture.
*
* @param position Position to start drawing at.
* @param size Size of the drawable, independent
* of the texture.
*/
IonDrawable *
drawable_new_with_texture (
ShaderType shader_type,
@ -85,6 +92,13 @@ drawable_new_with_texture (
return self;
}
/**
* Updates the position and size of the drawable.
*
* @param position Position to start drawing at.
* @param size Size of the drawable, independent
* of the texture.
*/
void
drawable_update_position (
IonDrawable * self,
@ -167,6 +181,23 @@ drawable_draw (
glBindVertexArray (0);
}
/**
* Returns if the drawable is hit by the given
* x,y positions.
*/
int
drawable_hit (
IonDrawable * self,
double x,
double y)
{
return
x >= self->position.x &&
x < self->position.x + self->size.x &&
y >= self->position.y &&
y < self->position.y + self->size.y;
}
void
drawable_free (
IonDrawable * self)

145
src/gui/main_menu.c

@ -22,6 +22,8 @@
#include <glib.h>
#include "game/ion_world.h"
#include "gui/button_with_text.h"
#include "gui/drawable.h"
#include "gui/main_menu.h"
#include "gui/shader.h"
#include "gui/shader_manager.h"
@ -29,48 +31,121 @@
#include "gui/skin.h"
#include "gui/texture.h"
/**
* Updates the main menu before drawing.
*/
void
main_menu_update (
MainMenu * self)
{
double xpos, ypos;
glfwGetCursorPos (
ION_WORLD->window, &xpos, &ypos);
int state =
glfwGetMouseButton (
ION_WORLD->window, GLFW_MOUSE_BUTTON_LEFT);
if (state == GLFW_PRESS &&
drawable_hit (CURRENT_LOGO, xpos, ypos))
{
self->showing_options = 1;
}
float logo_transition = 24.f;
if (self->showing_options)
{
/* move logo */
Vector2f new_pos = CURRENT_LOGO->position;
new_pos.x =
MAX (40.f, new_pos.x - logo_transition);
drawable_update_position (
CURRENT_LOGO, &new_pos,
&CURRENT_LOGO->size);
/* move options positions */
int y_pad = 4.f;
button_with_text_update_position (
self->play,
CURRENT_LOGO->position.x +
CURRENT_LOGO->size.x,
(CURRENT_LOGO->position.y +
CURRENT_LOGO->size.y / 2.f) +
(self->play->left_drawable->size.y +
y_pad) * 3.f);
button_with_text_update_position (
self->options,
CURRENT_LOGO->position.x +
CURRENT_LOGO->size.x,
(CURRENT_LOGO->position.y +
CURRENT_LOGO->size.y / 2.f) +
(self->play->left_drawable->size.y +
y_pad) * 2.f);
button_with_text_update_position (
self->exit,
CURRENT_LOGO->position.x +
CURRENT_LOGO->size.x,
(CURRENT_LOGO->position.y +
CURRENT_LOGO->size.y / 2.f) +
(self->play->left_drawable->size.y +
y_pad) * 1.f);
}
else
{
/* move logo */
Vector2f new_pos = CURRENT_LOGO->position;
new_pos.x =
MIN (
CURRENT_LOGO->size.x / 2.f,
new_pos.x + logo_transition);
drawable_update_position (
CURRENT_LOGO, &new_pos,
&CURRENT_LOGO->size);
}
}
static void
draw_options (
MainMenu * self)
{
button_with_text_draw (self->play);
button_with_text_draw (self->options);
button_with_text_draw (self->exit);
}
void
main_menu_draw (
MainMenu * self)
{
int fb_width, fb_height;
glfwGetFramebufferSize (
ION_WORLD->window, &fb_width, &fb_height);
/* draw bg stretched */
drawable_draw (CURRENT_SKIN->menu_bg);
#if 0
/* draw options */
if (self->showing_options)
{
draw_options (self);
}
/* ---- draw logo ----- */
unsigned int program =
ION_WORLD->shader_manager->unchanged_shader->
program_id;
Texture * texture =
ION_WORLD->skin_manager->current_skin->logo;
GLint baseImageLoc =
glGetUniformLocation (program, "baseImage");
GLint normalMapLoc =
glGetUniformLocation(program, "normalMap");
GLint shadowMapLoc =
glGetUniformLocation(program, "shadowMap");
/* draw logo */
drawable_draw (CURRENT_LOGO);
}
glUseProgram (program);
glUniform1i(baseImageLoc, 0); // Texture unit 0 is for base images.
glUniform1i(normalMapLoc, 2); // Texture unit 2 is for normal maps.
glUniform1i(shadowMapLoc, 4); // Texture unit 4 is for shadow maps.
/**
* Creates the main menu.
*/
MainMenu *
main_menu_new (void)
{
MainMenu * self = calloc (1, sizeof (MainMenu));
// When rendering an objectwith this program.
glActiveTexture(GL_TEXTURE0 + 0);
glBindTexture(GL_TEXTURE_2D, texture->id);
self->play =
button_with_text_new (
"Play", 1);
self->options =
button_with_text_new (
"Options", 1);
self->exit =
button_with_text_new (
"Exit", 1);
glPushMatrix ();
glTranslatef (
400.f, 20.f, 0.f);
texture_draw (
texture,
(float) fb_width / 2.f -
(float) texture->width / 2.f,
(float) fb_height / 2.f -
(float) texture->height / 2.f,
0.f, 1.f);
glPopMatrix ();
#endif
return self;
}

1
src/gui/meson.build

@ -16,6 +16,7 @@
# along with Ion. If not, see <https://www.gnu.org/licenses/>.
ion_srcs += files ([
'button_with_text.c',
'cursor.c',
'drawable.c',
'gl.c',

70
src/gui/skin.c

@ -17,6 +17,7 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <GLFW/glfw3.h>
#include <glib.h>
#include "game/ion_world.h"
@ -31,6 +32,9 @@
#define CURSOR_SMOKE_FILE "cursor-smoke.png"
#define CURSOR_TRAIL_FILE "cursortrail.png"
#define MENU_BG_FILE "menu-background.jpg"
#define BUTTON_LEFT_FILE "button-left.png"
#define BUTTON_MIDDLE_FILE "button-middle.png"
#define BUTTON_RIGHT_FILE "button-right.png"
/**
* @param width Set to negative to use the texture's.
@ -73,39 +77,71 @@ set_all_textures (
g_build_filename (
ION_WORLD->skins_dir, "myskin", NULL);
#define SET_TEXTURE(x,file,shader,w,h) \
#define GET_FULL_PATH(file) \
char * full_path = \
g_build_filename (path, file, NULL); \
if (!g_file_test ( \
full_path, G_FILE_TEST_EXISTS)) \
{ \
g_free (full_path); \
full_path = \
g_build_filename ( \
default_path, file, NULL); \
}
#define SET_TEXTURE_AS_DRAWABLE(x,file,shader,w,h) \
{ \
char * full_path = \
g_build_filename (path, file, NULL); \
if (!g_file_test ( \
full_path, G_FILE_TEST_EXISTS)) \
{ \
g_free (full_path); \
full_path = \
g_build_filename ( \
default_path, file, NULL); \
} \
GET_FULL_PATH(file); \
set_texture ( \
&self->x, full_path, SHADER_TYPE_##shader, \
w, h); \
g_free (full_path); \
}
SET_TEXTURE (
#define SET_TEXTURE(x,file) \
{ \
GET_FULL_PATH(file); \
self->x = texture_new_from_file (full_path); \
g_free (full_path); \
}
SET_TEXTURE_AS_DRAWABLE (
logo, LOGO_FILE, UNCHANGED, 960.f, 960.f);
SET_TEXTURE (
cursor.cursor, CURSOR_FILE, UNCHANGED, -1.f, -1.f);
button_left, BUTTON_LEFT_FILE);
SET_TEXTURE (
button_middle, BUTTON_MIDDLE_FILE);
SET_TEXTURE (
button_right, BUTTON_RIGHT_FILE);
SET_TEXTURE_AS_DRAWABLE (
cursor.cursor, CURSOR_FILE, UNCHANGED, -1.f, -1.f);
SET_TEXTURE_AS_DRAWABLE (
cursor.cursor_middle, CURSOR_MIDDLE_FILE,
UNCHANGED, -1.f, -1.f);
SET_TEXTURE (
SET_TEXTURE_AS_DRAWABLE (
cursor.cursor_smoke, CURSOR_SMOKE_FILE,
UNCHANGED, -1.f, -1.f);
SET_TEXTURE (
SET_TEXTURE_AS_DRAWABLE (
cursor.cursor_trail, CURSOR_TRAIL_FILE,
UNCHANGED, -1.f, -1.f);
SET_TEXTURE (
menu_bg, MENU_BG_FILE, UNCHANGED, 1920.f, 1080.f);
SET_TEXTURE_AS_DRAWABLE (
menu_bg, MENU_BG_FILE, UNCHANGED,
1920.f, 1080.f);
int fb_width, fb_height;
glfwGetFramebufferSize (
ION_WORLD->window, &fb_width, &fb_height);
/* set logo to middle */
Vector2f pos;
pos.x =
(float) fb_width / 2.f -
self->logo->size.x / 2.f;
pos.y =
(float) fb_height / 2.f -
self->logo->size.y / 2.f;
drawable_update_position (
self->logo, &pos, &self->logo->size);
}
/**

2
src/gui/skin_manager.c

@ -52,7 +52,7 @@ skin_manager_new (
}
self->current_skin =
self->available_skins[2];
self->available_skins[1];
return self;
}
Loading…
Cancel
Save