cleaning
This commit is contained in:
parent
d687c3089d
commit
7620e30514
323
gg/GtkGLArea.c
323
gg/GtkGLArea.c
|
@ -1,323 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include <glib-2.0/glib.h>
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
struct stack_index_t {
|
||||
long stack_id;
|
||||
void *container_widget;
|
||||
void *gl_area;
|
||||
};
|
||||
|
||||
static struct stack_index_t *stack_index = NULL;
|
||||
size_t stack_index_size = 0;
|
||||
|
||||
|
||||
/*
|
||||
* Look for stack entry and returns stack_id
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns stack_id
|
||||
*/
|
||||
long ui_get_graphic_stack(void *container_widget)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
return stack_index[i].stack_id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for stack entry and returns stack_id
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns stack_id
|
||||
*/
|
||||
long ui_is_graphic_stack_ready(void *container_widget)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
return stack_index[i].stack_id;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for stack entry and initializes OpenGL for it
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_init_graphic_stack(void *container_widget, GError *error_buffer)
|
||||
{
|
||||
//g_printerr("[debug] ui_init_graphic_stack()\n");
|
||||
|
||||
//g_printerr("[debug] ui_init_graphic_stack() : target is %p\n", container_widget);
|
||||
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
//g_printerr("[debug] ui_init_graphic_stack() : i is %d\n", i);
|
||||
//g_printerr("[debug] ui_init_graphic_stack() : target would be %p\n",
|
||||
//stack_index[i].container_widget);
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
stack_index[i].stack_id = graphics_init(&error_buffer);
|
||||
//g_printerr("[debug] ui_init_graphic_stack() : stack_id is %d\n",
|
||||
//stack_index[i].stack_id);
|
||||
if (stack_index[i].stack_id >= 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for stack entry and shutdowns OpenGL for it
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_shutdown_graphic_stack(void *container_widget, GError *error_buffer)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
if (graphics_shutdown(stack_index[i].stack_id,
|
||||
&error_buffer) == false) {
|
||||
return false;
|
||||
}
|
||||
stack_index[i].stack_id = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void ui_clean_stack_index(void)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
stack_index[i].stack_id = 0;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for stack entry and triggers OpenGL for drawing
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_render_stack(GtkWidget *container_widget)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
graphics_draw(stack_index[i].stack_id);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for stack entry and triggers OpenGL for drawing
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_update_axis_stack(GtkWidget *container_widget, int axis, int value)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)container_widget) {
|
||||
graphic_stack[stack_index[i].stack_id].rotation_angles[axis] = value;
|
||||
gtk_widget_queue_draw((GtkWidget*)(stack_index[i].gl_area));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Look for every stack entry and shutdowns OpenGL for it
|
||||
*
|
||||
* @params void
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
void ui_shutdown_all_graphic_stacks(void)
|
||||
{
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
graphics_shutdown(stack_index[i].stack_id, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a slider widget
|
||||
*
|
||||
* @params axis, meaning which axis we're building (for label)
|
||||
*
|
||||
* @returns GtkWidget*, pointer to the new widget
|
||||
*/
|
||||
GtkWidget *create_axis_slider(int axis)
|
||||
{
|
||||
GtkWidget *box, *label, *slider;
|
||||
GtkAdjustment *adj;
|
||||
const char *text;
|
||||
|
||||
box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 0);
|
||||
|
||||
switch (axis) {
|
||||
case X_AXIS:
|
||||
text = "X";
|
||||
break;
|
||||
|
||||
case Y_AXIS:
|
||||
text = "Y";
|
||||
break;
|
||||
|
||||
case Z_AXIS:
|
||||
text = "Z";
|
||||
break;
|
||||
|
||||
default:
|
||||
g_assert_not_reached();
|
||||
}
|
||||
|
||||
label = gtk_label_new(text);
|
||||
gtk_box_append(GTK_BOX(box), label);
|
||||
gtk_widget_show(label);
|
||||
|
||||
adj = gtk_adjustment_new(0.0, 0.0, 360.0, 1.0, 12.0, 0.0);
|
||||
g_signal_connect(adj, "value-changed",
|
||||
G_CALLBACK(on_axis_value_change),
|
||||
(gpointer) label);
|
||||
slider = gtk_scale_new(GTK_ORIENTATION_HORIZONTAL, adj);
|
||||
gtk_box_append(GTK_BOX(box), slider);
|
||||
gtk_widget_set_hexpand(slider, TRUE);
|
||||
gtk_widget_show(slider);
|
||||
|
||||
gtk_widget_show(box);
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates GLArea and indexes it
|
||||
*
|
||||
* @params target_mode, meaning which ui_stack we're on
|
||||
* target_widget, meaning the box that will host the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_setup_glarea(int target_mode, GtkWidget *target_widget)
|
||||
{
|
||||
GtkWidget *gl_area;
|
||||
|
||||
////g_printerr("[debug] ui_setup_glarea()\n");
|
||||
|
||||
assert(target_widget);
|
||||
|
||||
////g_printerr("[debug] ui_setup_glarea() : target is %p\n", target_widget);
|
||||
|
||||
if (stack_index == NULL) {
|
||||
stack_index = g_malloc(sizeof(struct stack_index_t));
|
||||
stack_index_size = 1;
|
||||
} else {
|
||||
// look for stack_index entry
|
||||
for (int i = 0; i < stack_index_size; i++) {
|
||||
if (stack_index[i].container_widget == (void *)target_widget) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// create entry
|
||||
stack_index =
|
||||
g_realloc(stack_index,
|
||||
++stack_index_size * sizeof(struct stack_index_t));
|
||||
}
|
||||
|
||||
gl_area = GTK_WIDGET(gtk_gl_area_new());
|
||||
assert(gl_area);
|
||||
|
||||
//gtk_widget_set_size_request(gl_area, 1000, 1000);
|
||||
gtk_gl_area_set_auto_render(GTK_GL_AREA(gl_area), true);
|
||||
gtk_widget_set_hexpand(gl_area, TRUE);
|
||||
gtk_widget_set_vexpand(gl_area, TRUE);
|
||||
//gtk_widget_set_halign(gl_area, GTK_ALIGN_CENTER);
|
||||
//gtk_widget_set_valign(gl_area, GTK_ALIGN_CENTER);
|
||||
|
||||
// The main "draw" call for GtkGLArea
|
||||
g_signal_connect(GTK_GL_AREA(gl_area),
|
||||
"render",
|
||||
G_CALLBACK(on_glarea_render), NULL);
|
||||
|
||||
g_signal_connect(gl_area,
|
||||
"realize",
|
||||
G_CALLBACK(on_glarea_realize), NULL);
|
||||
|
||||
g_signal_connect(gl_area,
|
||||
"unrealize",
|
||||
G_CALLBACK(on_glarea_unrealize), NULL);
|
||||
|
||||
stack_index[stack_index_size-1].container_widget =
|
||||
(void*)target_widget;
|
||||
|
||||
stack_index[stack_index_size-1].gl_area = (void*)gl_area;
|
||||
|
||||
////g_printerr("[debug] ui_setup_glarea() : set target to %p\n", target_widget);
|
||||
|
||||
////g_printerr("[debug] ui_setup_glarea() : stack_index (@0x%p) had %ld elements\n",
|
||||
//stack_index,
|
||||
//stack_index_size);
|
||||
|
||||
gtk_box_append(GTK_BOX(target_widget), gl_area);
|
||||
gtk_widget_show(GTK_WIDGET(gl_area));
|
||||
|
||||
// Create sliders
|
||||
for(int i = 0; i < N_AXIS; i++)
|
||||
gtk_box_append(GTK_BOX(target_widget), create_axis_slider(i));
|
||||
|
||||
return true;
|
||||
}
|
150
gg/application.c
150
gg/application.c
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
|
||||
struct _GemGraphClientApplication
|
||||
{
|
||||
GtkApplication parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GemGraphClientApplication,
|
||||
gem_graph_client_application,
|
||||
GTK_TYPE_APPLICATION)
|
||||
|
||||
|
||||
static GemGraphClientApplication *application;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ui_enable_action(const char *name) {
|
||||
g_simple_action_set_enabled(
|
||||
(GSimpleAction *)g_action_map_lookup_action(
|
||||
G_ACTION_MAP(application),
|
||||
name),
|
||||
true);
|
||||
}
|
||||
|
||||
void ui_disable_action(const char *name) {
|
||||
g_simple_action_set_enabled(
|
||||
(GSimpleAction *)g_action_map_lookup_action(
|
||||
G_ACTION_MAP(application),
|
||||
name),
|
||||
false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Window actual presentation on screen
|
||||
*
|
||||
*/
|
||||
static void gem_graph_client_application_activate(GApplication *app)
|
||||
{
|
||||
GtkWindow *window;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(app));
|
||||
|
||||
window = gtk_application_get_active_window(GTK_APPLICATION (app));
|
||||
if (window == NULL)
|
||||
window = g_object_new(GEM_GRAPH_CLIENT_TYPE_WINDOW,
|
||||
"application", app,
|
||||
NULL);
|
||||
|
||||
ui_set_stack(HOME_MODE);
|
||||
|
||||
gtk_window_present(window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Action records are registered here
|
||||
*
|
||||
*/
|
||||
static void gem_graph_client_application_init(GemGraphClientApplication *self)
|
||||
{
|
||||
g_action_map_add_action_entries(G_ACTION_MAP(self),
|
||||
app_actions,
|
||||
G_N_ELEMENTS(app_actions),
|
||||
self);
|
||||
|
||||
// Setup shortcuts
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.quit",
|
||||
(const char *[]) { "<primary>q", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.editmode",
|
||||
(const char *[]) { "<primary>e", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.runmode",
|
||||
(const char *[]) { "<primary>r", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.presentmode",
|
||||
(const char *[]) { "<primary>p", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.savefile",
|
||||
(const char *[]) { "<primary>s", NULL });
|
||||
|
||||
application = self;
|
||||
|
||||
//
|
||||
// Disable unneeded/inoperant actions
|
||||
//
|
||||
ui_disable_action("savefile");
|
||||
ui_disable_action("closefile");
|
||||
ui_disable_action("editmode");
|
||||
ui_disable_action("runmode");
|
||||
ui_disable_action("presentmode");
|
||||
ui_disable_action("togglesidebar");
|
||||
}
|
||||
|
||||
void ui_send_notification(const char *message)
|
||||
{
|
||||
g_print("NOTIFICATION: %s\n", message);
|
||||
|
||||
g_application_send_notification(G_APPLICATION(application),
|
||||
"notification",
|
||||
g_notification_new(message)
|
||||
);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void gem_graph_client_application_class_init(
|
||||
GemGraphClientApplicationClass *klass)
|
||||
{
|
||||
GApplicationClass *app_class = G_APPLICATION_CLASS(klass);
|
||||
|
||||
app_class->activate = gem_graph_client_application_activate;
|
||||
}
|
||||
|
||||
GemGraphClientApplication *gem_graph_client_application_new(
|
||||
const char *application_id,
|
||||
GApplicationFlags flags)
|
||||
{
|
||||
g_return_val_if_fail(application_id != NULL, NULL);
|
||||
|
||||
return g_object_new(GEM_GRAPH_CLIENT_TYPE_APPLICATION,
|
||||
"application-id", application_id,
|
||||
"flags", flags,
|
||||
NULL);
|
||||
}
|
285
gg/arrows.c
285
gg/arrows.c
|
@ -1,285 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: OpenGL utils header
|
||||
*
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
* Copyright (C) 2023 Arien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
/* I'm standing on Earth (any planet or star or spinning spheroid, in fact)
|
||||
* and looking towards its North pole
|
||||
*
|
||||
* X - X = EAST - WEST = rouge - cyan
|
||||
* Y - Y = ZENITH - NADIR = vert - magenta
|
||||
* Z - Z = NORTH - SOUTH = bleu - jaune
|
||||
*/
|
||||
|
||||
int draw_one_arrow_vertex (const int stack_id,
|
||||
int space_X_int,
|
||||
int space_Y_int,
|
||||
int space_Z_int,
|
||||
int weight,
|
||||
int site,
|
||||
int arrow_x,
|
||||
int arrow_y,
|
||||
int arrow_z)
|
||||
{
|
||||
float max = fmax(space_X_int, space_Y_int);
|
||||
max = fmax(max, space_Z_int);
|
||||
|
||||
float i = arrow_x, j = arrow_y, k = arrow_z;
|
||||
|
||||
float vx = (2 * i / space_X_int - 1) * space_X_int / max + (1 / max),
|
||||
vy = (2 * j / space_Y_int - 1) * space_Y_int / max + (1 / max),
|
||||
vz = (2 * k / space_Z_int - 1) * space_Z_int / max + (1 / max);
|
||||
|
||||
graphics_draw_vertex(stack_id, vx, vy, vz);
|
||||
graphics_draw_color(stack_id, 0.4f, 0.4f, 0.4f);
|
||||
|
||||
// réduit légèrement les longueurs des flèches
|
||||
// pour qu'elles s'arrêtent avant les faces des cubes
|
||||
GLfloat arrow_tip_padding = (1 / max) / 10;
|
||||
|
||||
switch(site){
|
||||
case EAST:
|
||||
graphics_draw_vertex (stack_id, vx - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vy, vz);
|
||||
graphics_draw_color (stack_id, 1.0f, 0.0f, 0.0f);
|
||||
break;
|
||||
case WEST:
|
||||
graphics_draw_vertex (stack_id, vx - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vy, vz);
|
||||
graphics_draw_color (stack_id, 0.0f, 1.0f, 1.0f);
|
||||
break;
|
||||
case ZENITH:
|
||||
graphics_draw_vertex (stack_id, vx, vy - (site % 2 - 1) * (1 / max) + (site % 2 - 1) * arrow_tip_padding, vz);
|
||||
graphics_draw_color(stack_id, 0.0f, 0.6f, 0.1f);
|
||||
break;
|
||||
case NADIR:
|
||||
graphics_draw_vertex (stack_id, vx, vy - (site % 2) * (1 / max) + (site % 2) * arrow_tip_padding, vz);
|
||||
graphics_draw_color(stack_id, 0.6f, 0.1f, 0.7f);
|
||||
break;
|
||||
case SOUTH:
|
||||
graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 + 1) * (1 / max) + (site % 2 + 1) * arrow_tip_padding);
|
||||
graphics_draw_color(stack_id, 0.05f, 0.4f, 1.0f);
|
||||
break;
|
||||
case NORTH:
|
||||
graphics_draw_vertex (stack_id, vx, vy, vz - (site % 2 - 2) * (1 / max) + (site % 2 - 2) * arrow_tip_padding);
|
||||
graphics_draw_color(stack_id, 1.0f, 1.0f, 0.0f);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
return 2*3;
|
||||
}
|
||||
|
||||
|
||||
int draw_one_arrow_line(const int stack_id, int offset_vertex)
|
||||
{
|
||||
graphics_draw_line (stack_id, offset_vertex + 0, offset_vertex + 1);
|
||||
return 2;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Depends on set_arrow()
|
||||
* Exchanges current and required site values
|
||||
* when the address of the arrow to be set is already occupied
|
||||
*/
|
||||
static int rewrite_arrow (const int stack_id,
|
||||
int address,
|
||||
int load,
|
||||
int site,
|
||||
int x,
|
||||
int y,
|
||||
int z)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
printf("WARNING in rewrite_arrow() <> address or address / 5 ? (et pourquoi ?)\n");
|
||||
stack->arrows_ptr[address].load = load;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Depends on set_arrow()
|
||||
* Creates the arrow to be set with the required load at the required address
|
||||
*/
|
||||
static inline int create_arrow (int stack_id,
|
||||
int arrows_nb,
|
||||
int space_X,
|
||||
int space_Y,
|
||||
int space_Z,
|
||||
int load,
|
||||
int site,
|
||||
int x,
|
||||
int y,
|
||||
int z)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
void *newptr = g_realloc(stack->arrows_ptr, (arrows_nb + 1) * sizeof(struct arrow_t));
|
||||
|
||||
if (newptr)
|
||||
stack->arrows_ptr = newptr;
|
||||
else
|
||||
perror("In create arrow, can't allocate new arrow buffer !\n");
|
||||
|
||||
stack->arrows_ptr[arrows_nb].load = load;
|
||||
stack->arrows_ptr[arrows_nb].site = site;
|
||||
stack->arrows_ptr[arrows_nb].x = x;
|
||||
stack->arrows_ptr[arrows_nb].y = y;
|
||||
stack->arrows_ptr[arrows_nb].z = z;
|
||||
|
||||
draw_one_arrow_vertex(stack_id, space_X, space_Y, space_Z, load, site, x, y, z);
|
||||
draw_one_arrow_line (stack_id, stack->buffer_vertex_size / 3 - 2);
|
||||
|
||||
arrows_nb ++;
|
||||
|
||||
return arrows_nb;
|
||||
}
|
||||
|
||||
/*
|
||||
* Depends on set_arrow()
|
||||
* Erases the arrow at the required address
|
||||
*/
|
||||
static inline int erase_arrow (const int stack_id,
|
||||
int arrows_nb,
|
||||
int arrow_address_in_list,
|
||||
GLuint site,
|
||||
GLint x,
|
||||
GLint y,
|
||||
GLint z)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
if (arrows_nb == 0) assert (stack->buffer_lines_size ==
|
||||
stack->buffer_lines_0_arrow);
|
||||
if (arrows_nb == 0) {
|
||||
stack->buffer_lines_size =
|
||||
stack->buffer_lines_0_arrow;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert (arrows_nb);
|
||||
arrows_nb --;
|
||||
|
||||
if (arrow_address_in_list < arrows_nb)
|
||||
{
|
||||
stack->arrows_ptr[arrow_address_in_list].load =
|
||||
stack->arrows_ptr[arrows_nb].load;
|
||||
stack->arrows_ptr[arrow_address_in_list].site =
|
||||
stack->arrows_ptr[arrows_nb].site;
|
||||
stack->arrows_ptr[arrow_address_in_list].x =
|
||||
stack->arrows_ptr[arrows_nb].x;
|
||||
stack->arrows_ptr[arrow_address_in_list].y =
|
||||
stack->arrows_ptr[arrows_nb].y;
|
||||
stack->arrows_ptr[arrow_address_in_list].z =
|
||||
stack->arrows_ptr[arrows_nb].z;
|
||||
}
|
||||
|
||||
for (long i = 0; i < 6; i++)
|
||||
stack->buffer_vertex_origin [stack->buffer_vertex_0_arrow + arrow_address_in_list * 6 + i]
|
||||
= stack->buffer_vertex_origin [stack->buffer_vertex_size - 6 + i];
|
||||
|
||||
for (long i = 0; i < 6; i++)
|
||||
stack->buffer_colors_origin [stack->buffer_colors_0_arrow + arrow_address_in_list * 6 + i]
|
||||
= stack->buffer_colors_origin [stack->buffer_colors_size - 6 + i];
|
||||
|
||||
stack->buffer_vertex_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_vertex()
|
||||
stack->buffer_colors_size -= 6; // <<< l'inverse de ce qui est fait dans : graphics_draw_colors()
|
||||
stack->buffer_lines_size -= 2; // <<< l'inverse de ce qui est fait dans : graphics_draw_line()
|
||||
|
||||
void *new_arrows_vertex_ptr = g_realloc(stack->buffer_vertex_origin, stack->buffer_vertex_size * sizeof(GLfloat));
|
||||
if (new_arrows_vertex_ptr) stack->buffer_vertex_origin = new_arrows_vertex_ptr;
|
||||
else perror("In graphics.erase_arrow(), can't re_allocate for arrows vertex buffer.\n");
|
||||
|
||||
void *new_arrows_colors_ptr = g_realloc(stack->buffer_colors_origin, stack->buffer_colors_size * sizeof(GLfloat));
|
||||
if (new_arrows_colors_ptr) stack->buffer_colors_origin = new_arrows_colors_ptr;
|
||||
else perror("In graphics.erase_arrow(), can't re_allocate for arrows colors buffer.\n");
|
||||
|
||||
/* Il ne faut pas réécrire ce qui suit: ces lignes dessinent maintenant à partir d'autres vertex */
|
||||
/* void *new_arrows_lines_ptr = g_realloc(stack->buffer_lines_origin, stack->buffer_lines_size * sizeof(GLfloat)); */
|
||||
/* if (new_arrows_lines_ptr) stack->buffer_lines_origin = new_arrows_lines_ptr; */
|
||||
/* else perror("In graphics.erase_arrow(), can't re_allocate for arrows lines buffer.\n"); */
|
||||
|
||||
return arrows_nb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Creates or deletes an arrow or modify the load of an existing one
|
||||
* Acts both by writing the list of arrows : (struct arrow_t *arrows_ptr, int arrows_nb)
|
||||
* and by drawing in the global space
|
||||
*
|
||||
* @param arrows_ptr and arrows_nb before operation,
|
||||
* required load and address (site, x, y, z)
|
||||
*
|
||||
* IF there is no arrow at the required address,
|
||||
* AND IF the load is > 0, an arrow will be created.
|
||||
*
|
||||
* IF there is an arrow at the required address
|
||||
* AND IF the load is = 0, the existing arrow will be deleted.
|
||||
*
|
||||
* IF there is an arrow at the required address
|
||||
* AND IF the load is > 0, the load of the existing arrow will be modified.
|
||||
*
|
||||
* May not call any of these three functions IF :
|
||||
* - Current_weight of an arrow located at the requested address == requested_weight
|
||||
* - No arrow was found at the requested addres AND current_weight == requested_weight
|
||||
*
|
||||
* @return arrows_nb after operation
|
||||
*/
|
||||
int set_arrow (int stack_id,
|
||||
int arrows_nb,
|
||||
int space_X,
|
||||
int space_Y,
|
||||
int space_Z,
|
||||
int requested_weight,
|
||||
int site,
|
||||
int arrow_x,
|
||||
int arrow_y,
|
||||
int arrow_z)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
int address = -1, current_weight = -1;
|
||||
|
||||
for (int i = 0; i < arrows_nb; i++)
|
||||
if ((site == stack->arrows_ptr[i].site)
|
||||
&& (arrow_x == stack->arrows_ptr[i].x)
|
||||
&& (arrow_y == stack->arrows_ptr[i].y)
|
||||
&& (arrow_z == stack->arrows_ptr[i].z))
|
||||
{
|
||||
address = i;
|
||||
current_weight = stack->arrows_ptr[i].load;
|
||||
break;
|
||||
}
|
||||
assert (address <= arrows_nb);
|
||||
|
||||
if (address == -1 && requested_weight > 0)
|
||||
return create_arrow (stack_id, arrows_nb, space_X, space_Y, space_Z, requested_weight, site, arrow_x, arrow_y, arrow_z);
|
||||
if (address >= 0 && requested_weight == 0) // address >= 0 if and only if arrows_nb > 0
|
||||
return erase_arrow(stack_id, arrows_nb, address, site, arrow_x, arrow_y, arrow_z);
|
||||
if (address >= 0 && current_weight != requested_weight) {
|
||||
rewrite_arrow(stack_id, address, requested_weight, site, arrow_x, arrow_y, arrow_z);
|
||||
return arrows_nb;
|
||||
}
|
||||
|
||||
return arrows_nb;
|
||||
}
|
||||
|
119
gg/base.h
119
gg/base.h
|
@ -1,119 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: Base header
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <glib-2.0/glib.h>
|
||||
//#define G_APPLICATION_DEFAULT_FLAGS 0
|
||||
|
||||
// Graphical axis
|
||||
enum
|
||||
{
|
||||
X_AXIS,
|
||||
Y_AXIS,
|
||||
Z_AXIS,
|
||||
|
||||
N_AXIS
|
||||
};
|
||||
|
||||
// Gem-graph modes
|
||||
enum
|
||||
{
|
||||
HOME_MODE,
|
||||
RUN_MODE,
|
||||
EDIT_MODE,
|
||||
PRESENTATION_MODE,
|
||||
|
||||
N_MODE
|
||||
};
|
||||
|
||||
/*
|
||||
* Structure describing an arrow
|
||||
*/
|
||||
struct arrow_t {
|
||||
uint load;
|
||||
uint site;
|
||||
uint x;
|
||||
uint y;
|
||||
uint z;
|
||||
};
|
||||
|
||||
/*
|
||||
* Read a file from filename into a provided buffer
|
||||
*
|
||||
* @param filename, file name
|
||||
* contents, target ptr
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static inline char *read_file(char *filename)
|
||||
{
|
||||
int fd;
|
||||
int filesize;
|
||||
char *contents;
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if(fd < 0) {
|
||||
printf("Couldn't read file: %s\n",filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
filesize = lseek(fd, 0, SEEK_END) + 1 ;
|
||||
contents = g_malloc(filesize * sizeof(char));
|
||||
assert (contents);
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
read(fd,contents,filesize);
|
||||
|
||||
contents[filesize-1] = '\0';
|
||||
|
||||
close(fd);
|
||||
|
||||
return contents;
|
||||
}
|
||||
|
||||
/* I'm standing on Earth (any planet or star or spinning spheroid, in fact)
|
||||
* and looking towards its North pole
|
||||
*
|
||||
* X - X = EAST - WEST = rouge - cyan
|
||||
* Y - Y = ZENITH - NADIR = vert - magenta
|
||||
* Z - Z = NORTH - SOUTH = bleu - jaune
|
||||
*/
|
||||
|
||||
#define EAST 0 // + x rouge
|
||||
#define WEST 1 // - x cyan
|
||||
#define ZENITH 2 // + y vert
|
||||
#define NADIR 3 // - y magenta
|
||||
#define SOUTH 4 // + z bleu
|
||||
#define NORTH 5 // - z jaune
|
295
gg/displays.c
295
gg/displays.c
|
@ -1,295 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: GL functions
|
||||
*
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
/* Prints the arrows[] array
|
||||
*
|
||||
* For each arrow the following parameters are displayed :
|
||||
* - rank in the array
|
||||
* - load (or weight)
|
||||
* - coordinates in space (site, x, y, z)
|
||||
*/
|
||||
void print_arrows_array (struct arrow_t *arrows, int arrows_nb, int invoked_by)
|
||||
{
|
||||
printf(" [rank] load | site x y z (");
|
||||
switch (invoked_by) {
|
||||
case 0: printf("after deletion) arrows_nb : %d", arrows_nb); break;
|
||||
case 1: printf("after creation) arrows_nb : %d", arrows_nb); break;
|
||||
case 2: printf("after modification) arrows_nb : %d", arrows_nb); break;
|
||||
case 3: printf("address >= 0 && current_weight == requested_weight)"); break;
|
||||
case 4: printf("address == -1 && requested_weight == 0)"); break;
|
||||
case 5: printf("print_user_choices)"); break;
|
||||
case 6: printf("print_evolution)"); break;
|
||||
case 7: printf("before deletion) arrows_nb : %d", arrows_nb); break;
|
||||
}
|
||||
for (int i = 0; i < arrows_nb; i++)
|
||||
printf("\n [%4d] = %2d | %2d, %2d, %2d, %2d", i, arrows[i].load,\
|
||||
arrows[i].site, arrows[i].x, arrows[i].y, arrows[i].z);
|
||||
if (arrows_nb == 0) printf("\n [NULL] ---- | ---- --- --- ---");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/* Prints the initial user choices :
|
||||
* - space dimension size and appearance (grids)
|
||||
* - arrows[] array
|
||||
* NB The space may be empty or saturated with arrows or any value in between
|
||||
* Only one arrow per possible coordinates with a load max equal to ? TODO
|
||||
*/
|
||||
void print_user_choices(struct arrow_t *arrows, int max_arrows_nb, int arrows_nb,
|
||||
int space_size_x, int space_size_y, int space_size_z,
|
||||
int show_array, int show_space_design)
|
||||
{
|
||||
printf("model + user constraints :\tspace size x,y,z (%d,%d,%d)\tinitial (max) arrows nb : %d",\
|
||||
space_size_x, space_size_y, space_size_z, max_arrows_nb);
|
||||
|
||||
if (show_space_design) printf(" (grilles alternées)");
|
||||
printf("\n");
|
||||
|
||||
if (show_array) print_arrows_array (arrows, arrows_nb, 5);
|
||||
}
|
||||
|
||||
/* Prints the evolution after adding / removing arrows :
|
||||
* - arrows[] array
|
||||
* NB The space may be empty or saturated with arrows or any value in between
|
||||
* Only one arrow per possible coordinates with a load max equal to ? TODO
|
||||
*
|
||||
*
|
||||
* print_evolution (arrows, added, mem, deleted, print_arrows_data);
|
||||
*/
|
||||
void print_evolution (struct arrow_t *arrows, int arrows_nb, int modified, int deleted, int show_array)
|
||||
{
|
||||
printf("evolution\t\t\t\t\t\t\tarrows nb > %6d\t (%d added / %d deleted) (modified : %d)\n",\
|
||||
arrows_nb + modified - deleted * 2, modified - deleted, deleted, modified);
|
||||
if (show_array) print_arrows_array (arrows, arrows_nb, 6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints the arrows[] array
|
||||
*
|
||||
* For each arrow the following parameters are displayed :
|
||||
* - rank in the array
|
||||
* - weight (or load)
|
||||
* - coordinates in space (site, x, y, z)
|
||||
*/
|
||||
void show_arrows_array_head(int one_batch_size, long nb_batches_specified, int verbose) {
|
||||
printf("\n [rank] load | site x y z");
|
||||
if (verbose) printf(" one batch size = %d nb_batches_specified = %ld",\
|
||||
one_batch_size, nb_batches_specified);
|
||||
}
|
||||
void show_one_arrow_in_array(struct arrow_t *arrows, int i) {
|
||||
printf("\n [%4d] = %2d | %2d, %2d, %2d, %2d",\
|
||||
i, arrows[i].load, arrows[i].site, arrows[i].x, arrows[i].y, arrows[i].z);
|
||||
}
|
||||
void show_empty_arrows_array() {printf("\n [NULL] ---- | ---- --- --- ---");}
|
||||
|
||||
void show_arrows_array (struct arrow_t *arrows, int arrows_nb, int x, int y, int z)
|
||||
{
|
||||
show_arrows_array_head (0,0,0);
|
||||
for (int i = 0; i < arrows_nb; i++)
|
||||
show_one_arrow_in_array(arrows, i);
|
||||
if (arrows_nb == 0) show_empty_arrows_array();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Prints the initial user choices :
|
||||
* - space dimension size and appearance (grids)
|
||||
* - arrows[] array
|
||||
* NB The space may be empty or saturated with arrows or any value in between
|
||||
* To assert : Only one arrow per possible coordinates with a load max equal to ?
|
||||
*/
|
||||
void show_user_choices(long copy_nb_arrows_specified,
|
||||
int space_size_x, int space_size_y, int space_size_z,
|
||||
int prefer, int arbitrary, int one_batch_size)
|
||||
{
|
||||
printf("\nnb arrows specified = %ld", copy_nb_arrows_specified);
|
||||
printf(" space size (x,y,z) = (%d,%d,%d)", space_size_x, space_size_y, space_size_z);
|
||||
printf(" arbitrary = %d one_batch_size = %d", arbitrary, one_batch_size);
|
||||
if (prefer == 0) printf(" prefer = %d <> show all grids", prefer);
|
||||
if (prefer == 1) printf(" prefer = %d <> show no grid", prefer);
|
||||
if (prefer > 1) printf(" show grids according rule (%d)", prefer);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Prints the result of the function set_arrow()
|
||||
* and indicates the reasons of the choice (call) this function makes (see this function)
|
||||
*/
|
||||
#define TEST 0
|
||||
void show_user_action(struct arrow_t *arrows, int arrows_nb, int address, int requested_weight,
|
||||
int current_weight, int site, int x, int y, int z)
|
||||
{
|
||||
if (address == -1 && requested_weight > 0) { // *(arrows + i * 5 + 0)
|
||||
printf("no such arrow found (%2d,%2d,%2d,%2d)", site, x, y, z); //arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4]);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> CREATE"); return;}
|
||||
|
||||
if (address >= 0 && requested_weight == 0) {
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d; current_weight = %2d;", site, x, y, z, address, current_weight); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5, current_weight);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> ERASE"); return;}
|
||||
|
||||
if (address >= 0 && current_weight != requested_weight) {
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d; current_weight = %2d;", site, x, y, z, address, current_weight); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5, current_weight);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> MODIFY"); return;}
|
||||
|
||||
if (address >= 0 && current_weight == requested_weight){
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d;", site, x, y, z, address); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("requested_weight == current_weight => END"); return;}
|
||||
|
||||
if (address == -1 && requested_weight == 0) {
|
||||
printf("no such arrow found (%2d,%2d,%2d,%2d)", site, x, y, z); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4]);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> END"); return;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Prints vertex and lines buffers_states (sizes) at major one_batch_sizes and at the end of a session.
|
||||
* Major one_batch_sizes are creation of grids and creation of arrows
|
||||
* Arithmetic verification is provided at each one_batch_size
|
||||
*/
|
||||
void show_buffers_states(int space_X, int space_Y, int space_Z,
|
||||
long nb_batches_specified, int one_batch_size,
|
||||
int offset_after_grids, int buffer_vertex_size,
|
||||
int buffer_lines_size_after_cubes, int buffer_lines_size)
|
||||
{
|
||||
int offset_after_arrows = buffer_vertex_size / 3, difference = offset_after_arrows - offset_after_grids;
|
||||
|
||||
printf("\n - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
|
||||
|
||||
printf("\n buffer_vertex_offset_after grids = %9d\t%9d = (x+1)*(y+1)*(z+1); <--> (x,y,z = %d,%d,%d)",\
|
||||
offset_after_grids, (space_X + 1)*(space_Y + 1)*(space_Z + 1), space_X, space_Y, space_Z);
|
||||
|
||||
printf("\n buffer_vertex_offset_after arrows = %9d\t%9d = %d + %d; <--> %d = 12 x %d (%d cubes)",\
|
||||
offset_after_arrows, offset_after_arrows, offset_after_grids,\
|
||||
difference, difference, difference / 12, difference / 12);
|
||||
|
||||
printf("\n buffer_lines_offset after cubes = %9d\t%9d = 2 * (%dx%d + %dx%d + %dx%d); <--> 2 * (x*y + x*z + y*z)",\
|
||||
buffer_lines_size_after_cubes, ((space_X+1) * (space_Y+1) + (space_X+1) * (space_Z+1) + (space_Y+1) * (space_Z+1)) * 2,
|
||||
space_X+1, space_Y+1, space_X+1, space_Z+1, space_Y+1, space_Z+1);
|
||||
|
||||
printf("\n buffer_lines_offset after arrows = %9d\t%9d = %d + %d; <--> %d = 14 x %d (%d arrows drawned)",\
|
||||
buffer_lines_size, buffer_lines_size, buffer_lines_size_after_cubes,\
|
||||
buffer_lines_size - buffer_lines_size_after_cubes,\
|
||||
buffer_lines_size - buffer_lines_size_after_cubes, (buffer_lines_size - buffer_lines_size_after_cubes) / 14,\
|
||||
(buffer_lines_size - buffer_lines_size_after_cubes) / 14);
|
||||
|
||||
if (nb_batches_specified * one_batch_size == 0) printf("\n");
|
||||
else printf("\n WARNING Arrows of the same address, whatever their weight, are drawn in superimposition. Check their list.");
|
||||
|
||||
printf("\n It happens that NOT all the specified arrows (%ld) = (%ld x %d) are drawned (%d) ! WHY ? (d = %ld)\n",\
|
||||
nb_batches_specified * one_batch_size, nb_batches_specified, one_batch_size, (buffer_lines_size - buffer_lines_size_after_cubes) / 14,\
|
||||
nb_batches_specified * one_batch_size - (buffer_lines_size - buffer_lines_size_after_cubes) / 14);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Prints the result of the function set_arrow()
|
||||
* and indicates the reasons of the choice (call) this function makes (see this function)
|
||||
*/
|
||||
void print_user_action(struct arrow_t *arrows, int arrows_nb, int address, int requested_weight,
|
||||
int current_weight, int site, int x, int y, int z)
|
||||
{
|
||||
if (address == -1 && requested_weight > 0) { // *(arrows + i * 5 + 0)
|
||||
printf("no such arrow found (%2d,%2d,%2d,%2d)", site, x, y, z); //arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4]);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> CREATE"); return;}
|
||||
|
||||
if (address >= 0 && requested_weight == 0) {
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d; current_weight = %2d;", site, x, y, z, address, current_weight); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5, current_weight);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> ERASE"); return;}
|
||||
|
||||
if (address >= 0 && current_weight != requested_weight) {
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d; current_weight = %2d;", site, x, y, z, address, current_weight); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5, current_weight);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> MODIFY"); return;}
|
||||
|
||||
if (address >= 0 && current_weight == requested_weight){
|
||||
printf("arrow (%2d,%2d,%2d,%2d) found at address %2d;", site, x, y, z, address); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4], address/5);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("requested_weight == current_weight => END"); return;}
|
||||
|
||||
if (address == -1 && requested_weight == 0) {
|
||||
printf("no such arrow found (%2d,%2d,%2d,%2d)", site, x, y, z); // arrows[address + 1], arrows[address + 2], arrows[address + 3], arrows[address + 4]);
|
||||
if (! TEST) printf("\n "); else printf(" ");
|
||||
printf("=> END"); return;}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static inline void print_buffers_array_head () {printf(" [rank] load | site x y z [address] buffer-vertex-1 buffer-vertex-2 buffer-lines\n");}
|
||||
static inline void print_empty_buffers_array () {printf(" [NULL] ---- | ---- --- --- --- -1 --- --- ---\n");}
|
||||
|
||||
static void print_one_arrow_in_buffers (struct arrow_t *arrows,
|
||||
GLfloat *buffer_vertex_origin, long buffer_vertex_0_arrow,
|
||||
GLfloat *buffer_lines_origin, long buffer_lines_0_arrow,
|
||||
int i, int arrows_nb, int address)
|
||||
{
|
||||
printf(" [%4d] = %2d | %2d, %2d, %2d, %2d, (%2d) %6.2f %6.2f %6.2f %6.2f %6.2f %6.2f %4f %4f\n",\
|
||||
i,
|
||||
arrows[i].load, arrows[i].site, arrows[i].x, arrows[i].y, arrows[i].z,
|
||||
address,
|
||||
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 0],
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 1],
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 2],
|
||||
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 3],
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 4],
|
||||
buffer_vertex_origin [buffer_vertex_0_arrow + i * 6 + 5],
|
||||
|
||||
buffer_lines_origin [buffer_lines_0_arrow + i * 2 + 0],
|
||||
buffer_lines_origin [buffer_lines_0_arrow + i * 2 + 1]);
|
||||
}
|
||||
|
||||
void print_vertex_and_lines_buffers (struct arrow_t *arrows_ptr, int arrows_nb,
|
||||
GLfloat *buffer_vertex_origin, long buffer_vertex_0_arrow,
|
||||
GLfloat *buffer_lines_origin, long buffer_lines_0_arrow,
|
||||
int address, int requested_weight, int current_weight, int site, int x, int y, int z)
|
||||
{
|
||||
/* for (int i = 0; i < 6; i++) printf("%5.2f ", buffer_vertex_origin [buffer_vertex_0_arrow + i]); printf("\n"); */
|
||||
/* for (int i = 0; i < 6; i++) printf("%5.2f ", buffer_lines_origin [buffer_lines_0_arrow + i]); printf("\n"); */
|
||||
print_buffers_array_head ();
|
||||
for (int i = 0; i < arrows_nb; i++)
|
||||
print_one_arrow_in_buffers(arrows_ptr, buffer_vertex_origin, buffer_vertex_0_arrow,
|
||||
buffer_lines_origin, buffer_lines_0_arrow, i, arrows_nb, address);
|
||||
if (arrows_nb == 0) print_empty_buffers_array();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
207
gg/draw.c
207
gg/draw.c
|
@ -1,207 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: GL functions
|
||||
*
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Writes values to describe a vertex at (x,y,z) intoq the vertex buffer
|
||||
*
|
||||
* @param coords GLfloat(x,y,z)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <cglm/cglm.h>
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
void graphics_draw_vertex (const int stack_id,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat z)
|
||||
{
|
||||
//g_printerr("stack_id is %d\n", stack_id);
|
||||
//g_printerr("stack_id is %d\n", stack_id);
|
||||
//g_printerr("graphic_stack is at %p\n", graphic_stack);
|
||||
//g_printerr("graphic_stack[stack_id] is at %p\n", graphic_stack + stack_id);
|
||||
volatile struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
//g_printerr("Currently stack->buffer_vertex_origin @ %p\n", stack->buffer_vertex_origin);
|
||||
|
||||
//assert (stack->buffer_vertex_origin);
|
||||
|
||||
stack->buffer_vertex_origin =
|
||||
g_realloc (stack->buffer_vertex_origin,
|
||||
(stack->buffer_vertex_size + 3) * sizeof(GLfloat));
|
||||
//print_stack(stack_id);
|
||||
|
||||
stack->buffer_vertex_origin[stack->buffer_vertex_size + 0] = x;
|
||||
stack->buffer_vertex_origin[stack->buffer_vertex_size + 1] = y;
|
||||
stack->buffer_vertex_origin[stack->buffer_vertex_size + 2] = z;
|
||||
|
||||
stack->buffer_vertex_size += 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes values to describe a color (r,g,b) into the color buffer
|
||||
*
|
||||
* @param color GLfloat(r,g,b)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_color (const int stack_id,
|
||||
GLfloat r,
|
||||
GLfloat g,
|
||||
GLfloat b)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
stack->buffer_colors_origin = g_realloc (stack->buffer_colors_origin,
|
||||
(stack->buffer_colors_size + 3) * sizeof(GLfloat));
|
||||
|
||||
assert (stack->buffer_colors_origin);
|
||||
|
||||
stack->buffer_colors_origin[stack->buffer_colors_size + 0] = r;
|
||||
stack->buffer_colors_origin[stack->buffer_colors_size + 1] = g;
|
||||
stack->buffer_colors_origin[stack->buffer_colors_size + 2] = b;
|
||||
|
||||
stack->buffer_colors_size += 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes values to describe a line from a to b into the line buffer
|
||||
*
|
||||
* @param coords GLuint (a,b)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_line (const int stack_id,
|
||||
GLuint a,
|
||||
GLuint b)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
stack->buffer_lines_origin = g_realloc (stack->buffer_lines_origin,
|
||||
(stack->buffer_lines_size + 2) * sizeof(GLuint));
|
||||
|
||||
assert (stack->buffer_lines_origin);
|
||||
|
||||
stack->buffer_lines_origin[stack->buffer_lines_size + 0] = a;
|
||||
stack->buffer_lines_origin[stack->buffer_lines_size + 1] = b;
|
||||
|
||||
stack->buffer_lines_size += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes values to describe an (a,b,c) plan (triangle) into the plan buffer
|
||||
*
|
||||
* @param coords GLuint (a,b,c)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_plan (const int stack_id,
|
||||
GLuint a,
|
||||
GLuint b,
|
||||
GLuint c)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
stack->buffer_plans_origin = g_realloc (stack->buffer_plans_origin,
|
||||
(stack->buffer_plans_size + 3) * sizeof(GLuint));
|
||||
|
||||
assert (stack->buffer_plans_origin);
|
||||
|
||||
stack->buffer_plans_origin[stack->buffer_plans_size + 0] = a;
|
||||
stack->buffer_plans_origin[stack->buffer_plans_size + 1] = b;
|
||||
stack->buffer_plans_origin[stack->buffer_plans_size + 2] = c;
|
||||
|
||||
stack->buffer_plans_size += 3;
|
||||
}
|
||||
|
||||
/*
|
||||
* Draws the current buffer to a gl_area
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw(const int stack_id)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
//g_printerr("[debug] graphics_draw() started\n");
|
||||
|
||||
//print_stack(stack_id);
|
||||
|
||||
GLint cur_viewport[4];
|
||||
glGetIntegerv(GL_VIEWPORT, cur_viewport);
|
||||
|
||||
mat4 m = GLM_MAT4_IDENTITY_INIT;
|
||||
glm_rotate_x(m, glm_rad(stack->rotation_angles[X_AXIS]), m);
|
||||
glm_rotate_y(m, glm_rad(stack->rotation_angles[Y_AXIS]), m);
|
||||
glm_rotate_z(m, glm_rad(stack->rotation_angles[Z_AXIS]), m);
|
||||
|
||||
mat4 v = GLM_MAT4_IDENTITY_INIT; // XXX define zoom and translations here ?
|
||||
|
||||
mat4 p = GLM_MAT4_IDENTITY_INIT;
|
||||
//glm_ortho(-1.0f, +1.0f, -1.0f, +1.0f, -1.0f, +1.0f, p);
|
||||
glm_ortho_default((float)cur_viewport[2] / (float)cur_viewport[3], p);
|
||||
//glm_perspective_default((float)cur_viewport[2] / (float)cur_viewport[3], p);
|
||||
|
||||
/* Use our shaders */
|
||||
glUseProgram(stack->program);
|
||||
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/* Update the "mvp" matrix we use in the shader */
|
||||
glUniformMatrix4fv(stack->m, 1, GL_FALSE, (float *)m);
|
||||
glUniformMatrix4fv(stack->v, 1, GL_FALSE, (float *)v);
|
||||
glUniformMatrix4fv(stack->p, 1, GL_FALSE, (float *)p);
|
||||
|
||||
/* Use the vertices in our buffer */
|
||||
glEnableVertexAttribArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, stack->position_buffer);
|
||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0,(void*)0);
|
||||
|
||||
// couleurs
|
||||
glEnableVertexAttribArray(1);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, stack->color_buffer);
|
||||
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0,(void*)0);
|
||||
|
||||
//glEnable(GL_DEPTH_TEST);
|
||||
|
||||
glDrawElements(GL_LINES, stack->buffer_lines_size, GL_UNSIGNED_INT, stack->buffer_lines_origin);
|
||||
glDrawElements(GL_TRIANGLES, stack->buffer_plans_size, GL_UNSIGNED_INT, stack->buffer_plans_origin);
|
||||
|
||||
/* We finished using the buffers and program */
|
||||
glDisableVertexAttribArray(0);
|
||||
glDisableVertexAttribArray(1);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glUseProgram(0);
|
||||
|
||||
glFlush();
|
||||
//g_printerr("[debug] graphics_draw() ended\n");
|
||||
}
|
369
gg/events.c
369
gg/events.c
|
@ -1,369 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/graphics.h"
|
||||
#include "../../include/parsing.h"
|
||||
#include "../../include/ui.h"
|
||||
|
||||
|
||||
|
||||
void on_about_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
static const char *authors[] = { "Adrien Bourmault (neox@a-lec.org)",
|
||||
"Jean Sirmai (jean@a-lec.org)",
|
||||
"Arthur Menges (arthur.menges@a-lec.org)",
|
||||
NULL};
|
||||
GemGraphClientApplication *self = user_data;
|
||||
GtkWindow *window = NULL;
|
||||
|
||||
g_assert (GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
window = gtk_application_get_active_window(GTK_APPLICATION (self));
|
||||
|
||||
gtk_show_about_dialog(window,
|
||||
"program-name", "Gem-graph",
|
||||
"logo-icon-name", "application-x-executable",
|
||||
"authors", authors,
|
||||
"version", "0.1.0",
|
||||
"copyright", "Copyright © 2023 Libre en Communs",
|
||||
NULL);
|
||||
}
|
||||
|
||||
void on_quit_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
g_application_quit(G_APPLICATION(self));
|
||||
}
|
||||
|
||||
void on_preferences_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_send_internal_notification("Not implemented !");
|
||||
}
|
||||
|
||||
void on_togglesidebar_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_toggle_sidebar();
|
||||
}
|
||||
|
||||
void on_editmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_set_stack(EDIT_MODE);
|
||||
}
|
||||
|
||||
void on_runmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_set_stack(RUN_MODE);
|
||||
}
|
||||
|
||||
void on_presentmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_set_stack(PRESENTATION_MODE);
|
||||
}
|
||||
|
||||
void on_openfile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
// Create a new file selection dialog, using the "open" mode
|
||||
GtkFileChooserNative *native =
|
||||
gtk_file_chooser_native_new("Open File",
|
||||
GTK_WINDOW(self),
|
||||
GTK_FILE_CHOOSER_ACTION_OPEN,
|
||||
"_Open",
|
||||
"_Cancel");
|
||||
|
||||
// Connect the "response" signal of the file selection dialog;
|
||||
// this signal is emitted when the user selects a file, or when
|
||||
// they cancel the operation
|
||||
g_signal_connect (native,
|
||||
"response",
|
||||
G_CALLBACK(on_openfile_response),
|
||||
self);
|
||||
|
||||
// Present the dialog to the user
|
||||
gtk_native_dialog_show (GTK_NATIVE_DIALOG (native));
|
||||
}
|
||||
|
||||
void on_closefile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
model_shutdown();
|
||||
|
||||
ui_disable_action("closefile");
|
||||
ui_disable_action("savefile");
|
||||
ui_disable_action("runmode");
|
||||
ui_disable_action("editmode");
|
||||
ui_disable_action("presentmode");
|
||||
ui_disable_action("togglesidebar");
|
||||
ui_set_stack(HOME_MODE);
|
||||
}
|
||||
|
||||
void on_savefile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
}
|
||||
|
||||
void on_toast_close_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data)
|
||||
{
|
||||
GemGraphClientApplication *self = user_data;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(self));
|
||||
|
||||
ui_close_internal_notification();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Graphical/view related events
|
||||
*/
|
||||
|
||||
void on_axis_value_change(GtkAdjustment *adjustment, gpointer data)
|
||||
{
|
||||
|
||||
GtkWidget *slider = gtk_widget_get_parent(GTK_WIDGET(data));
|
||||
GtkWidget *container_widget = gtk_widget_get_parent(GTK_WIDGET(slider));
|
||||
|
||||
const gchar *label_text = gtk_label_get_label(GTK_LABEL(data));
|
||||
|
||||
// THANKS ASCIIIII/Unicode/Whateverrr !
|
||||
int axis = label_text[0] - 'X';
|
||||
|
||||
g_assert(axis >= 0 && axis < N_AXIS);
|
||||
|
||||
/* Update the rotation angle */
|
||||
ui_update_axis_stack(container_widget,
|
||||
axis,
|
||||
gtk_adjustment_get_value(adjustment));
|
||||
|
||||
/* Update the contents of the GL drawing area */
|
||||
}
|
||||
|
||||
gboolean on_glarea_render(GtkGLArea *area, GdkGLContext *context)
|
||||
{
|
||||
// Check if the widget is a glarea
|
||||
if(gtk_gl_area_get_error(area) != NULL) {
|
||||
ui_send_internal_notification("An OpenGL error occured !");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ui_render_stack(gtk_widget_get_parent(GTK_WIDGET(area))) == false) {
|
||||
ui_send_internal_notification(
|
||||
"Failed to render corresponding graphic stack !");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/* We need to set up our state when we realize the GtkGLArea widget */
|
||||
void on_glarea_realize(GtkWidget *widget)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
|
||||
// Make the GL context current to be able to call the GL API
|
||||
gtk_gl_area_make_current(GTK_GL_AREA(widget));
|
||||
|
||||
// Check if the widget is a glarea
|
||||
if(gtk_gl_area_get_error(GTK_GL_AREA(widget)) != NULL) {
|
||||
ui_send_internal_notification("An OpenGL error occured !");
|
||||
return;
|
||||
}
|
||||
|
||||
// Link graphical stack to widget
|
||||
if (ui_init_graphic_stack(gtk_widget_get_parent(widget),
|
||||
internal_error) == false) {
|
||||
ui_send_internal_notification(
|
||||
"Failed to link the graphic stack to widgets !");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_gl_area_set_auto_render(GTK_GL_AREA(widget), true);
|
||||
}
|
||||
|
||||
/* We should tear down the state when unrealizing */
|
||||
void on_glarea_unrealize(GtkWidget *widget)
|
||||
{
|
||||
GError *internal_error = NULL;
|
||||
|
||||
// Make the GL context current to be able to call the GL API
|
||||
gtk_gl_area_make_current(GTK_GL_AREA(widget));
|
||||
|
||||
// Check if the widget is a glarea
|
||||
if(gtk_gl_area_get_error(GTK_GL_AREA(widget)) != NULL) {
|
||||
ui_send_internal_notification("An OpenGL error occured !");
|
||||
return;
|
||||
}
|
||||
|
||||
// Destroy graphic stack
|
||||
if (ui_shutdown_graphic_stack(gtk_widget_get_parent(widget),
|
||||
internal_error) == false) {
|
||||
ui_send_internal_notification(
|
||||
"Failed to shutdown the graphic stack !");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void on_close_window(GtkWidget *widget)
|
||||
{
|
||||
|
||||
ui_shutdown_all_graphic_stacks();
|
||||
ui_clean_stack_index();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Responses
|
||||
*/
|
||||
void on_openfile_response(GtkNativeDialog *native,
|
||||
int response,
|
||||
GemGraphClientWindow *self)
|
||||
{
|
||||
g_autoptr(GFile) file;
|
||||
GtkFileChooser *chooser;
|
||||
|
||||
if (response == GTK_RESPONSE_ACCEPT) {
|
||||
chooser = GTK_FILE_CHOOSER(native);
|
||||
file = gtk_file_chooser_get_file(chooser);
|
||||
|
||||
// Load asynchroneously not to block control flow
|
||||
g_file_load_contents_async (file,
|
||||
NULL,
|
||||
(GAsyncReadyCallback)ui_model_loading,
|
||||
self);
|
||||
}
|
||||
|
||||
g_object_unref(native);
|
||||
}
|
||||
|
||||
void ui_model_loading(GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
GemGraphClientWindow *self)
|
||||
{
|
||||
GFile *file = G_FILE(source_object);
|
||||
|
||||
char *content = NULL;
|
||||
size_t length = 0;
|
||||
|
||||
GError *error = NULL;
|
||||
char *basename = g_file_get_basename(file);
|
||||
|
||||
// Gives you the contents of the file as a byte array, or
|
||||
// set the error argument
|
||||
g_file_load_contents_finish(file,
|
||||
result,
|
||||
&content,
|
||||
&length,
|
||||
NULL,
|
||||
&error);
|
||||
|
||||
// In case of error, print a warning to the standard error output
|
||||
if (error != NULL) {
|
||||
g_printerr("Unable to open “%s”: %s\n",
|
||||
g_file_peek_path(file),
|
||||
error->message);
|
||||
ui_send_internal_notification("Unable to open file !");
|
||||
g_free(error);
|
||||
g_free(basename);
|
||||
g_free(content);
|
||||
return;
|
||||
}
|
||||
|
||||
if (model_init(content, length, basename) == false) {
|
||||
ui_send_internal_notification("Error while loading the model");
|
||||
g_free(basename);
|
||||
g_free(content);
|
||||
return;
|
||||
}
|
||||
|
||||
ui_enable_action("closefile");
|
||||
ui_enable_action("savefile");
|
||||
ui_enable_action("runmode");
|
||||
ui_enable_action("editmode");
|
||||
ui_enable_action("presentmode");
|
||||
ui_enable_action("togglesidebar");
|
||||
ui_set_stack(RUN_MODE);
|
||||
|
||||
g_free(basename);
|
||||
g_free(content);
|
||||
}
|
||||
|
328
gg/graphics.c
328
gg/graphics.c
|
@ -1,328 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: GL functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
#include "../../include/parsing.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
#define TEST 0
|
||||
|
||||
struct graphic_stack_t *graphic_stack = NULL;
|
||||
size_t graphic_stack_size = 0;
|
||||
int *free_stack_slot = NULL;
|
||||
size_t free_stack_slot_size = 0;
|
||||
|
||||
/*
|
||||
* Prints verbose human-readable debug messages
|
||||
*
|
||||
* @param source, XXX
|
||||
* type, XXX
|
||||
* id, XXX
|
||||
* severity, XXX
|
||||
* length, XXX
|
||||
* msg, XXX
|
||||
* data, XXX
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void graphics_debug_callback(GLenum source, GLenum type, GLuint id,
|
||||
GLenum severity, GLsizei length,
|
||||
const GLchar *msg, const void *data)
|
||||
{
|
||||
const char *errsource;
|
||||
const char *errtype;
|
||||
const char *errseverity;
|
||||
const GLubyte *string;
|
||||
GLenum code;
|
||||
|
||||
switch (source) {
|
||||
case GL_DEBUG_SOURCE_API: errsource = "API"; break;
|
||||
case GL_DEBUG_SOURCE_WINDOW_SYSTEM: errsource = "WINDOW SYSTEM"; break;
|
||||
case GL_DEBUG_SOURCE_SHADER_COMPILER: errsource = "SHADER COMPILER"; break;
|
||||
case GL_DEBUG_SOURCE_THIRD_PARTY: errsource = "THIRD PARTY"; break;
|
||||
case GL_DEBUG_SOURCE_APPLICATION: errsource = "APPLICATION"; break;
|
||||
case GL_DEBUG_SOURCE_OTHER: errsource = "UNKNOWN"; break;
|
||||
default: errsource = "UNKNOWN"; break;
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case GL_DEBUG_TYPE_ERROR: errtype = "ERROR"; break;
|
||||
case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR: errtype = "DEPRECATED BEHAVIOR";break;
|
||||
case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR: errtype = "UNDEFINED BEHAVIOR"; break;
|
||||
case GL_DEBUG_TYPE_PORTABILITY: errtype = "PORTABILITY"; break;
|
||||
case GL_DEBUG_TYPE_PERFORMANCE: errtype = "PERFORMANCE"; break;
|
||||
case GL_DEBUG_TYPE_OTHER: errtype = "OTHER"; break;
|
||||
case GL_DEBUG_TYPE_MARKER: errtype = "MARKER"; break;
|
||||
default: errtype = "UNKNOWN"; break;
|
||||
}
|
||||
|
||||
switch (severity) {
|
||||
case GL_DEBUG_SEVERITY_HIGH: errseverity = "CRITICAL"; break;
|
||||
case GL_DEBUG_SEVERITY_MEDIUM: errseverity = "ERROR"; break;
|
||||
case GL_DEBUG_SEVERITY_LOW: errseverity = "WARNING"; break;
|
||||
case GL_DEBUG_SEVERITY_NOTIFICATION: errseverity = "INFO"; break;
|
||||
default: errseverity = "UNKNOWN"; break;
|
||||
}
|
||||
|
||||
code = glGetError();
|
||||
string = gluErrorString(code);
|
||||
|
||||
g_printerr("[%s] %s (%s) from %s: %s\n",
|
||||
errseverity, string, errtype, errsource, msg);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
/*
|
||||
* Initializes graphical stack
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return id if initialized
|
||||
*/
|
||||
int graphics_init(void *error_buffer)
|
||||
{
|
||||
int cur_id = 0;
|
||||
struct graphic_stack_t *stack;
|
||||
|
||||
/* g_printerr("[debug] graphics_init()\n"); */
|
||||
|
||||
if (graphic_stack == NULL) {
|
||||
graphic_stack = g_malloc0(sizeof(struct graphic_stack_t));
|
||||
graphic_stack_size = 1;
|
||||
/* g_printerr("[debug] graphics_init(): init graphic_stack @ %p\n", graphic_stack); */
|
||||
} else {
|
||||
// Check if there are free slots
|
||||
if (free_stack_slot_size) {
|
||||
// We get the last free slot registered
|
||||
cur_id = free_stack_slot[free_stack_slot_size-1];
|
||||
// Unregister it (ofc)
|
||||
free_stack_slot = g_realloc(free_stack_slot,
|
||||
free_stack_slot_size-- *
|
||||
sizeof(int));
|
||||
} else {
|
||||
cur_id = graphic_stack_size;
|
||||
graphic_stack = g_realloc(graphic_stack,
|
||||
++graphic_stack_size *
|
||||
sizeof(struct graphic_stack_t));
|
||||
}
|
||||
}
|
||||
|
||||
memset(&graphic_stack[cur_id], 0, sizeof(struct graphic_stack_t));
|
||||
|
||||
/* g_printerr("[debug] graphics_init() : graphic_stack (@0x%p) has %ld elements\n", */
|
||||
/* graphic_stack, */
|
||||
/* graphic_stack_size); */
|
||||
|
||||
stack = &graphic_stack[cur_id];
|
||||
stack->id = cur_id;
|
||||
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
glEnable(GL_MULTISAMPLE);
|
||||
|
||||
if (!graphics_init_shaders(cur_id))
|
||||
return -1;
|
||||
|
||||
//print_stack(cur_id);
|
||||
|
||||
graphics_init_buffers(cur_id);
|
||||
|
||||
glDebugMessageCallback(graphics_debug_callback, NULL);
|
||||
|
||||
//print_stack(cur_id);
|
||||
|
||||
return cur_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdowns a gl_area
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return true if success
|
||||
*/
|
||||
bool graphics_shutdown(const int id, void *error_buffer)
|
||||
{
|
||||
struct graphic_stack_t *stack;
|
||||
|
||||
if (id >= graphic_stack_size ||
|
||||
graphic_stack_size == 0 ||
|
||||
graphic_stack == NULL)
|
||||
return false;
|
||||
|
||||
stack = &graphic_stack[id];
|
||||
|
||||
//XXX
|
||||
free(stack->arrows_ptr);
|
||||
stack->arrows_ptr = NULL;
|
||||
stack->arrows_nb = 0;
|
||||
|
||||
glDeleteBuffers(1, &stack->position_buffer);
|
||||
glDeleteBuffers(1, &stack->color_buffer);
|
||||
glDeleteProgram(stack->program);
|
||||
|
||||
g_free(stack->buffer_vertex_origin);
|
||||
g_free(stack->buffer_colors_origin);
|
||||
g_free(stack->buffer_lines_origin);
|
||||
g_free(stack->buffer_plans_origin);
|
||||
|
||||
if (graphic_stack_size == 1) {
|
||||
free(graphic_stack);
|
||||
graphic_stack = NULL;
|
||||
graphic_stack_size = 0;
|
||||
} else {
|
||||
memset(&graphic_stack[id], 0, sizeof(struct graphic_stack_t));
|
||||
free_stack_slot = g_realloc(free_stack_slot,
|
||||
++free_stack_slot_size *
|
||||
sizeof(int));
|
||||
free_stack_slot[free_stack_slot_size-1] = id;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* TODO
|
||||
* #pragma omp parallel schedule(static, 12)
|
||||
* void __attribute__((optimize("no-unroll-loops"))) main_test_graphics (void) {}
|
||||
*
|
||||
// assert : space dimensions (x,y,z) > 0
|
||||
// assert : arrows localization within space and sites
|
||||
// assert : no more than one arrow per address
|
||||
// notify : weights are replaced, NOT added (could be !)
|
||||
*
|
||||
* Init space and arrows (= initial state)
|
||||
* and allows ulterior creations, suppressions or modifications of the arrows[] array
|
||||
*
|
||||
* draws the space()
|
||||
* triggers set_arrows() that modifies the list () and draws arrows
|
||||
*
|
||||
* Initialisation du générateur pseudo-aléatoire
|
||||
* Attention, les vertex centraux de chaque unité d'espace (cube)
|
||||
* peuvent être redondants (max 6)
|
||||
*/
|
||||
void graphics_model_setup (const int stack_id)
|
||||
{
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* I N I T I A L D A T A S P E C I F I C A T I O N */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
char dimension;
|
||||
long space_X;
|
||||
long space_Y;
|
||||
long space_Z;
|
||||
long announced_arrows_nb;
|
||||
int density_max;
|
||||
char multiplicity;
|
||||
|
||||
dimension = model_get_dim();
|
||||
|
||||
g_print("[GRAPH DEBUG] dim = %d\n", dimension);
|
||||
|
||||
space_X = 1;
|
||||
space_Y = 1;
|
||||
space_Z = 1;
|
||||
|
||||
switch(dimension) {
|
||||
case 3:
|
||||
space_Z = model_get_dim_value("z");
|
||||
case 2:
|
||||
space_Y = model_get_dim_value("y");
|
||||
|
||||
// even in 1D, we must be able to see a grid
|
||||
if (!space_Y)
|
||||
space_Y = 1;
|
||||
case 1:
|
||||
space_X = model_get_dim_value("x");
|
||||
if (!space_X)
|
||||
space_X = 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
g_print("[GRAPH DEBUG] x = %ld\n", space_X);
|
||||
g_print("[GRAPH DEBUG] y = %ld\n", space_Y);
|
||||
g_print("[GRAPH DEBUG] z = %ld\n", space_Z);
|
||||
|
||||
density_max = space_X * space_Y * space_Z;
|
||||
stack->arrows_nb = 0;
|
||||
|
||||
multiplicity = model_get_multiplicity();
|
||||
g_print("[GRAPH DEBUG] site_multiplicity = %ld\n", multiplicity);
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* S P A C E D R A W I N G */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
draw_space_ridges_vertex (stack_id, stack->buffer_vertex_size,
|
||||
space_X, space_Y, space_Z);
|
||||
draw_space_ridges_lines (stack_id);
|
||||
draw_grids_on_space_faces_vertex (stack_id, space_X, space_Y, space_Z);
|
||||
draw_grids_on_space_faces_lines (stack_id, stack->buffer_lines_size,
|
||||
space_X, space_Y, space_Z);
|
||||
|
||||
stack->buffer_vertex_0_arrow = stack->buffer_vertex_size;
|
||||
stack->buffer_colors_0_arrow = stack->buffer_colors_size;
|
||||
stack->buffer_lines_0_arrow = stack->buffer_lines_size;
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
/* A R R O W S D R A W I N G */
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
|
||||
char state_id[30] = {0};
|
||||
struct arrow_t arrow = {0};
|
||||
|
||||
assert(model_get_next_state(&state_id));
|
||||
|
||||
g_print("[GRAPH DEBUG] first state is = %s\n", state_id);
|
||||
|
||||
announced_arrows_nb = model_get_state_arrows_count(state_id);
|
||||
|
||||
g_print("[GRAPH DEBUG] announced_arrows_nb is = %ld\n", announced_arrows_nb);
|
||||
|
||||
while (model_get_next_arrow(&arrow, &state_id, dimension)) {
|
||||
g_print("[GRAPH DEBUG] cur arrow has x = %d\n", arrow.x);
|
||||
stack->arrows_nb =
|
||||
set_arrow (stack_id, stack->arrows_nb, space_X, space_Y, space_Z,
|
||||
arrow.load, // load
|
||||
arrow.site, // site
|
||||
arrow.x, // x
|
||||
arrow.y, // y
|
||||
arrow.z); // z
|
||||
}
|
||||
|
||||
if (stack->arrows_nb != announced_arrows_nb)
|
||||
g_printerr("ARGH : all the arrows have not been parsed !\n");
|
||||
}
|
314
gg/graphics.h
314
gg/graphics.h
|
@ -1,314 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: OpenGL utils header
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "base.h"
|
||||
#include <unistd.h>
|
||||
#include <stdbool.h>
|
||||
#include <epoxy/gl.h>
|
||||
#include <GL/glu.h>
|
||||
#include <GL/glext.h>
|
||||
#include <cglm/cglm.h>
|
||||
|
||||
#define VERTEX_SHADER_FILE "src/graphics/shaders/shader.vert"
|
||||
#define FRAG_SHADER_FILE "src/graphics/shaders/shader.frag"
|
||||
#define GL_TARGET_MAJOR_VERSION 0
|
||||
#define GL_TARGET_MINOR_VERSION 4
|
||||
|
||||
/*
|
||||
* Structure describing a gl_area and its parameters, used to create a table
|
||||
* of Gem-graph client current gl_areas
|
||||
*/
|
||||
struct graphic_stack_t {
|
||||
|
||||
int id;
|
||||
int mode;
|
||||
|
||||
float rotation_angles[N_AXIS]; // Rotation angles on each axis
|
||||
|
||||
GLuint vao; // init_buffers
|
||||
GLuint position_buffer; // shutdown, draw
|
||||
GLuint color_buffer; // shutdown, draw
|
||||
GLuint program; // shutdown, init_shaders, draw
|
||||
GLuint m; // init_shaders, draw
|
||||
GLuint v; // init_shaders, draw
|
||||
GLuint p; // init_shaders, draw
|
||||
|
||||
struct arrow_t *arrows_ptr;
|
||||
long arrows_nb;
|
||||
|
||||
GLfloat *buffer_vertex_origin;
|
||||
GLfloat *buffer_colors_origin;
|
||||
GLuint *buffer_lines_origin;
|
||||
GLuint *buffer_plans_origin;
|
||||
|
||||
long buffer_vertex_size;
|
||||
long buffer_colors_size;
|
||||
long buffer_lines_size;
|
||||
long buffer_plans_size;
|
||||
|
||||
long buffer_vertex_0_arrow;
|
||||
long buffer_colors_0_arrow;
|
||||
long buffer_lines_0_arrow;
|
||||
long buffer_plans_0_arrow;
|
||||
};
|
||||
|
||||
/*
|
||||
* Dynamic array of ptrs to dynamically allocated gl_area_entry
|
||||
*/
|
||||
extern struct graphic_stack_t *graphic_stack;
|
||||
|
||||
/*
|
||||
* Initializes a gl_area
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return true if initialized
|
||||
*/
|
||||
int graphics_init(void *error_buffer);
|
||||
|
||||
/*
|
||||
* Draws the current buffer to a gl_area
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw(const int stack_id);
|
||||
|
||||
/*
|
||||
* Shutdowns a gl_area
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return true if success
|
||||
*/
|
||||
bool graphics_shutdown(const int stack_id, void *error_buffer);
|
||||
|
||||
/*
|
||||
* Initializes the shaders of a gl_area and link them to a program
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return true if initialized
|
||||
*/
|
||||
bool graphics_init_shaders(const int stack_id);
|
||||
|
||||
/* Initializes the buffer of a gl_area
|
||||
* Calls according to the user preferences
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
* @return void
|
||||
*/
|
||||
void graphics_init_buffers(const int stack_id);
|
||||
|
||||
/*
|
||||
* Draws a vertex (x, y, z)
|
||||
* if (console) prints (x, y, z) values to console
|
||||
*
|
||||
* @param GLfloat x, GLfloat y, GLfloat z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_vertex (const int stack_id,
|
||||
GLfloat x,
|
||||
GLfloat y,
|
||||
GLfloat z);
|
||||
|
||||
/*
|
||||
* Draws the color (r, g, b) associated to a vertex
|
||||
* if (console) prints (r, g, b) values to console
|
||||
*
|
||||
* @param GLfloat r, GLfloat g, GLfloat b
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_color (const int stack_id, GLfloat r, GLfloat g, GLfloat b);
|
||||
|
||||
/*
|
||||
* Writes values to describe a line from a to b into the line buffer
|
||||
*
|
||||
* @param coords GLuint (a,b)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_line (const int stack_id, GLuint a, GLuint b);
|
||||
|
||||
/*
|
||||
* Writes values to describe an (a,b,c) plan (triangle) into the plan buffer
|
||||
*
|
||||
* @param coords GLuint (a,b,c)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
void graphics_draw_plan (const int stack_id, GLuint a, GLuint b, GLuint c);
|
||||
|
||||
/*
|
||||
* Created and compile a shader
|
||||
*
|
||||
* @param type, shader type
|
||||
* src, source code of shader
|
||||
*
|
||||
* @return shader id
|
||||
*/
|
||||
static inline GLuint create_shader(const int stack_id, int type, const char *src)
|
||||
{
|
||||
GLuint shader;
|
||||
int status;
|
||||
|
||||
shader = glCreateShader(type);
|
||||
glShaderSource(shader, 1, &src, NULL);
|
||||
glCompileShader(shader);
|
||||
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
|
||||
if(status == GL_FALSE) {
|
||||
int log_len;
|
||||
char *buffer;
|
||||
|
||||
glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc(log_len + 1);
|
||||
assert (buffer);
|
||||
glGetShaderInfoLog(shader, log_len, NULL, buffer);
|
||||
|
||||
g_warning("Compile failure in %s shader:\n%s",
|
||||
type == GL_VERTEX_SHADER ? "vertex" : "fragment",
|
||||
buffer);
|
||||
|
||||
g_free(buffer);
|
||||
|
||||
glDeleteShader(shader);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
static inline void print_stack(int stack_id)
|
||||
{
|
||||
static int n = 0;
|
||||
|
||||
printf("\n[n=%d]***************", n);
|
||||
|
||||
printf("id = %d\tmode = %d\n",
|
||||
graphic_stack[stack_id].id,
|
||||
graphic_stack[stack_id].mode);
|
||||
|
||||
printf("rotation_angles = ");
|
||||
for (int i = 0; i < N_AXIS; i++) {
|
||||
printf("%f\t", graphic_stack[stack_id].rotation_angles[i]); // Rotation angles on each axis
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
printf("vao = %d\n", graphic_stack[stack_id].vao);
|
||||
printf("position_buffer = %d\n", graphic_stack[stack_id].position_buffer);
|
||||
printf("color_buffer = %d\n", graphic_stack[stack_id].color_buffer);
|
||||
printf("program = %d\n", graphic_stack[stack_id].program);
|
||||
printf("m = %d\n", graphic_stack[stack_id].m);
|
||||
printf("v = %d\n", graphic_stack[stack_id].v);
|
||||
printf("p = %d\n", graphic_stack[stack_id].p);
|
||||
|
||||
printf("arrows_ptr = %p\n", graphic_stack[stack_id].arrows_ptr);
|
||||
printf("arrows_nb = %ld\n", graphic_stack[stack_id].arrows_nb);
|
||||
|
||||
printf("buffer_vertex_origin = %p\n", graphic_stack[stack_id].buffer_vertex_origin);
|
||||
printf("buffer_colors_origin = %p\n", graphic_stack[stack_id].buffer_colors_origin);
|
||||
printf("buffer_lines_origin = %p\n", graphic_stack[stack_id].buffer_lines_origin);
|
||||
printf("buffer_plans_origin = %p\n", graphic_stack[stack_id].buffer_plans_origin);
|
||||
|
||||
printf("buffer_vertex_size = %ld\n", graphic_stack[stack_id].buffer_vertex_size);
|
||||
printf("buffer_colors_size = %ld\n", graphic_stack[stack_id].buffer_colors_size);
|
||||
printf("buffer_lines_size = %ld\n", graphic_stack[stack_id].buffer_lines_size);
|
||||
printf("buffer_plans_size = %ld\n", graphic_stack[stack_id].buffer_plans_size);
|
||||
|
||||
printf("buffer_vertex_0_arrow = %p\n", graphic_stack[stack_id].buffer_vertex_0_arrow);
|
||||
printf("buffer_colors_0_arrow = %p\n", graphic_stack[stack_id].buffer_colors_0_arrow);
|
||||
printf("buffer_lines_0_arrow = %p\n", graphic_stack[stack_id].buffer_lines_0_arrow);
|
||||
printf("buffer_plans_0_arrow = %p\n", graphic_stack[stack_id].buffer_plans_0_arrow);
|
||||
|
||||
printf("********************\n");
|
||||
n++;
|
||||
}
|
||||
|
||||
|
||||
void graphics_model_setup (const int stack_id);
|
||||
|
||||
int draw_one_arrow_vertex (const int stack_id,
|
||||
int space_X,
|
||||
int space_Y,
|
||||
int space_Z,
|
||||
int weight,
|
||||
int site,
|
||||
int x,
|
||||
int y,
|
||||
int z);
|
||||
|
||||
int draw_one_arrow_line(const int stack_id,
|
||||
int offset_vertex);
|
||||
|
||||
/*
|
||||
* Writes grid ridges to vertex and color buffers
|
||||
*
|
||||
* @param coords long (x,y,z), step_x, step_y, step_z
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
int draw_space_ridges_vertex (const int stack_id,
|
||||
long offset_vertex,
|
||||
long x,
|
||||
long y,
|
||||
long z);
|
||||
|
||||
int draw_space_ridges_lines (const int stack_id);
|
||||
|
||||
/*
|
||||
* Writes grid lines on space faces
|
||||
*
|
||||
* @param coords long (x,y,z)
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
long draw_grids_on_space_faces_vertex (const int stack_id,
|
||||
long x,
|
||||
long y,
|
||||
long z);
|
||||
|
||||
long draw_grids_on_space_faces_lines (const int stack_id,
|
||||
long offset_vertex,
|
||||
long x,
|
||||
long y,
|
||||
long z);
|
||||
|
||||
int set_arrow (int stack_id,
|
||||
int arrows_nb,
|
||||
int space_X,
|
||||
int space_Y,
|
||||
int space_Z,
|
||||
int requested_weight,
|
||||
int site,
|
||||
int arrow_x,
|
||||
int arrow_y,
|
||||
int arrow_z);
|
||||
|
162
gg/grid.c
162
gg/grid.c
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* Gem-graph
|
||||
*
|
||||
* Desc: OpenGL grid functions
|
||||
*
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
int draw_space_ridges_vertex (const int stack_id,
|
||||
long offset_vertex,
|
||||
long x,
|
||||
long y,
|
||||
long z)
|
||||
{
|
||||
GLfloat max = fmax(x, y); max = fmax(max, z);
|
||||
|
||||
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, - z / max);
|
||||
|
||||
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, - z / max);
|
||||
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, - z / max);
|
||||
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex - y / max, + z / max);
|
||||
|
||||
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex + y / max, - z / max);
|
||||
graphics_draw_vertex (stack_id, offset_vertex + x / max, offset_vertex - y / max, + z / max);
|
||||
graphics_draw_vertex (stack_id, offset_vertex - x / max, offset_vertex + y / max, + z / max);
|
||||
|
||||
graphics_draw_vertex (stack_id, offset_vertex + x / max, + y / max, + z / max);
|
||||
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
graphics_draw_color (stack_id, 0.8f, 0.6f, 0.5f);
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
int draw_space_ridges_lines (const int stack_id)
|
||||
{
|
||||
graphics_draw_line (stack_id, 0, 1); graphics_draw_line (stack_id, 7, 4);
|
||||
graphics_draw_line (stack_id, 0, 2); graphics_draw_line (stack_id, 7, 5);
|
||||
graphics_draw_line (stack_id, 0, 3); graphics_draw_line (stack_id, 7, 6);
|
||||
|
||||
graphics_draw_line (stack_id, 1, 4); graphics_draw_line (stack_id, 2, 4);
|
||||
graphics_draw_line (stack_id, 1, 5); graphics_draw_line (stack_id, 3, 5);
|
||||
graphics_draw_line (stack_id, 2, 6); graphics_draw_line (stack_id, 3, 6);
|
||||
|
||||
return 12;
|
||||
}
|
||||
|
||||
long draw_grids_on_space_faces_vertex (const int stack_id,
|
||||
long x,
|
||||
long y,
|
||||
long z)
|
||||
{
|
||||
float i, max = fmax(x, y); max = fmax(max, z);
|
||||
|
||||
for (i = 1; i < x; i++) {
|
||||
|
||||
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, - z / max);
|
||||
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, - y / max, z / max);
|
||||
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, z / max);
|
||||
graphics_draw_vertex (stack_id, (2 * i / x - 1) * x / max, y / max, - z / max);
|
||||
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
}
|
||||
|
||||
/* offset_vertex += (x - 1) * 4; */ /* offset_colors += (x - 1) * 4; */
|
||||
|
||||
for (i = 1; i < y; i++) {
|
||||
|
||||
graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, - z / max);
|
||||
graphics_draw_vertex (stack_id, - x / max, (2 * i / y - 1) * y / max, z / max);
|
||||
graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, z / max);
|
||||
graphics_draw_vertex (stack_id, x / max, (2 * i / y - 1) * y / max, - z / max);
|
||||
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
}
|
||||
|
||||
/* offset_vertex += (y - 1) * 4; */ /* offset_colors += (y - 1) * 4; */
|
||||
|
||||
for (i = 1; i < z; i++) {
|
||||
|
||||
graphics_draw_vertex (stack_id, - x / max, - y / max, (2 * i / z - 1) * z / max);
|
||||
graphics_draw_vertex (stack_id, - x / max, y / max, (2 * i / z - 1) * z / max);
|
||||
graphics_draw_vertex (stack_id, x / max, y / max, (2 * i / z - 1) * z / max);
|
||||
graphics_draw_vertex (stack_id, x / max, - y / max, (2 * i / z - 1) * z / max);
|
||||
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
graphics_draw_color (stack_id, 0.55f, 0.55f, 0.55f);
|
||||
}
|
||||
|
||||
return (x + y + z - 3) * 3;
|
||||
}
|
||||
|
||||
|
||||
long draw_grids_on_space_faces_lines (const int stack_id,
|
||||
long offset_vertex,
|
||||
long x,
|
||||
long y,
|
||||
long z)
|
||||
{
|
||||
offset_vertex = offset_vertex / 3;
|
||||
|
||||
for (int i = 0; i < x - 1; i ++) {
|
||||
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 1, offset_vertex + i * 4 + 2);
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
|
||||
}
|
||||
|
||||
offset_vertex += (x - 1) * 4;
|
||||
|
||||
for (int i = 0; i < y - 1; i ++) {
|
||||
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 2, offset_vertex + i * 4 + 3);
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
|
||||
}
|
||||
|
||||
offset_vertex += (y - 1) * 4;
|
||||
|
||||
for (int i = 0; i < z - 1; i ++) {
|
||||
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 0, offset_vertex + i * 4 + 1);
|
||||
graphics_draw_line (stack_id, offset_vertex + i * 4 + 3, offset_vertex + i * 4 + 0);
|
||||
}
|
||||
|
||||
return (x + y + z - 3) * 4;
|
||||
}
|
||||
|
175
gg/init.c
175
gg/init.c
|
@ -1,175 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: GL functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
#include "../../include/graphics.h"
|
||||
|
||||
/* Initializes the buffer of a gl_area
|
||||
* Calls according to the user preferences
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
* @return void
|
||||
*/
|
||||
void graphics_init_buffers(const int stack_id)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
|
||||
//XXX
|
||||
graphics_model_setup(stack_id);
|
||||
|
||||
GLuint vao, vertex_buffer, color_buffer;
|
||||
|
||||
glGenBuffers(1, &vertex_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
stack->buffer_vertex_size *
|
||||
sizeof(stack->buffer_vertex_origin[0]),
|
||||
stack->buffer_vertex_origin,
|
||||
GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
|
||||
// colors
|
||||
glGenBuffers(1, &color_buffer);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, color_buffer);
|
||||
glBufferData(GL_ARRAY_BUFFER, stack->buffer_colors_size *
|
||||
sizeof(stack->buffer_colors_origin[0]),
|
||||
stack->buffer_colors_origin,
|
||||
GL_STATIC_DRAW);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
|
||||
// We only use one VAO, so we always keep it bound
|
||||
glGenVertexArrays(1, &vao);
|
||||
glBindVertexArray(vao);
|
||||
|
||||
stack->vao = vao;
|
||||
stack->position_buffer = vertex_buffer;
|
||||
stack->color_buffer = color_buffer;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the shaders of a gl_area and link them to a program
|
||||
*
|
||||
* @param gl_area, ptr to the gl_area widget
|
||||
*
|
||||
* @return true if initialized
|
||||
*/
|
||||
bool graphics_init_shaders(const int stack_id)
|
||||
{
|
||||
struct graphic_stack_t *stack = &graphic_stack[stack_id];
|
||||
char *vertex_shader;
|
||||
char *fragment_shader;
|
||||
int status;
|
||||
GLuint vertex, fragment;
|
||||
GLuint program = 0;
|
||||
GLuint m = 0;
|
||||
GLuint v = 0;
|
||||
GLuint p = 0;
|
||||
|
||||
// Load vertex shader file
|
||||
vertex_shader = read_file(VERTEX_SHADER_FILE);
|
||||
if (vertex_shader == NULL)
|
||||
return false;
|
||||
vertex = create_shader(stack_id, GL_VERTEX_SHADER, vertex_shader);
|
||||
|
||||
if(vertex == 0) {
|
||||
stack->program = 0;
|
||||
g_free(vertex_shader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load fragment shader file
|
||||
fragment_shader = read_file(FRAG_SHADER_FILE);
|
||||
if (fragment_shader == NULL)
|
||||
return false;
|
||||
fragment = create_shader(stack_id, GL_FRAGMENT_SHADER, fragment_shader);
|
||||
|
||||
if(fragment == 0) {
|
||||
glDeleteShader(vertex);
|
||||
stack->program = 0;
|
||||
g_free(vertex_shader);
|
||||
g_free(fragment_shader);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Link shaders to program
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vertex);
|
||||
glAttachShader(program, fragment);
|
||||
|
||||
glLinkProgram(program);
|
||||
|
||||
glGetProgramiv(program, GL_LINK_STATUS, &status);
|
||||
|
||||
if(status == GL_FALSE) {
|
||||
int log_len;
|
||||
char *buffer;
|
||||
|
||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &log_len);
|
||||
|
||||
buffer = g_malloc(log_len + 1);
|
||||
assert(buffer);
|
||||
glGetProgramInfoLog(program, log_len, NULL, buffer);
|
||||
|
||||
g_warning("Linking failure:\n%s", buffer);
|
||||
|
||||
g_free(buffer);
|
||||
|
||||
glDeleteProgram(program);
|
||||
program = 0;
|
||||
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
|
||||
g_free(vertex_shader);
|
||||
g_free(fragment_shader);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get the location of the "mvp" uniform */
|
||||
m = glGetUniformLocation(program, "model_matrix");
|
||||
v = glGetUniformLocation(program, "view_matrix");
|
||||
p = glGetUniformLocation(program, "projection_matrix");
|
||||
|
||||
glDetachShader(program, vertex);
|
||||
glDetachShader(program, fragment);
|
||||
|
||||
glDeleteShader(vertex);
|
||||
glDeleteShader(fragment);
|
||||
|
||||
stack->program = program;
|
||||
stack->m = m;
|
||||
stack->v = v;
|
||||
stack->p = p;
|
||||
|
||||
g_free(vertex_shader);
|
||||
g_free(fragment_shader);
|
||||
|
||||
return true;
|
||||
}
|
483
gg/parsing.c
483
gg/parsing.c
|
@ -1,483 +0,0 @@
|
|||
/*
|
||||
* Gem-graph client
|
||||
*
|
||||
* Desc: Model parsing functions
|
||||
*
|
||||
* Copyright (C) 2023 Jean Sirmai <jean@a-lec.org>
|
||||
* Copyright (C) 2024 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/xmlreader.h> // http://xmlsoft.org/examples/#parse1.c
|
||||
// https://gnome.pages.gitlab.gnome.org/libxml2/devhelp/general.html
|
||||
|
||||
#include "../../include/base.h"
|
||||
|
||||
#define READ_SITE 1 << 0
|
||||
#define READ_WEIGHT 1 << 1
|
||||
#define READ_X 1 << 2
|
||||
#define READ_Y 1 << 3
|
||||
#define READ_Z 1 << 4
|
||||
#define SUCCESSFUL_READ_ARROW_X (READ_SITE | READ_WEIGHT | READ_X)
|
||||
#define SUCCESSFUL_READ_ARROW_XY (READ_SITE | READ_WEIGHT | READ_X | READ_Y)
|
||||
#define SUCCESSFUL_READ_ARROW_XYZ (READ_SITE | READ_WEIGHT | READ_X | READ_Y | READ_Z)
|
||||
|
||||
static xmlDocPtr model;
|
||||
static xmlHashTablePtr model_hashtable;
|
||||
|
||||
bool model_init(const char *content, size_t length, const char *basename)
|
||||
{
|
||||
xmlNode *node;
|
||||
|
||||
/*
|
||||
* this initialize the library and check potential ABI mismatches
|
||||
* between the version it was compiled for and the actual shared
|
||||
* library used.
|
||||
*/
|
||||
LIBXML_TEST_VERSION
|
||||
|
||||
model = xmlReadMemory(content, length, basename, NULL, 0);
|
||||
|
||||
if (model == NULL ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
node = xmlDocGetRootElement(model);
|
||||
|
||||
if (node == NULL) {
|
||||
g_printerr("Empty XML model !\n");
|
||||
xmlFreeDoc(model);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (xmlStrcmp(node->name, (xmlChar *) "gem-graph-model")) {
|
||||
g_printerr("document of the wrong type, root node != gem-graph-model\n");
|
||||
xmlFreeDoc(model);
|
||||
return false;
|
||||
}
|
||||
|
||||
model_hashtable = xmlHashCreate(0);
|
||||
|
||||
if (model_hashtable == NULL) {
|
||||
g_printerr("Can't create model hash table !\n");
|
||||
xmlFreeDoc(model);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool model_shutdown(void)
|
||||
{
|
||||
xmlFreeDoc(model);
|
||||
xmlHashFree(model_hashtable, NULL);
|
||||
|
||||
// Cleanup function for the XML library
|
||||
xmlCleanupParser();
|
||||
|
||||
// This is to debug memory for regression tests
|
||||
xmlMemoryDump();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static inline xmlNodePtr getNextChild(xmlNodePtr node, xmlChar *last)
|
||||
{
|
||||
while (node != NULL && xmlStrcmp(node->name, last)) {
|
||||
// //printf(" <>--- line n°%lu <%s>\n", xmlGetLineNo(node), node->name);
|
||||
node = node->next;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
static inline xmlChar* splitStrAtSlash(xmlChar *toSplit)
|
||||
{
|
||||
toSplit = (xmlChar *)xmlStrchr(toSplit, '/');
|
||||
toSplit = xmlStrsub (toSplit, 1, xmlStrlen(toSplit));
|
||||
return toSplit;
|
||||
}
|
||||
|
||||
static inline xmlChar* getFirstTag(xmlChar *path)
|
||||
{
|
||||
xmlChar *preop = path;
|
||||
path = (xmlChar *)xmlStrchr(path, '/');
|
||||
path = xmlStrsub (path, 1, xmlStrlen(path));
|
||||
|
||||
//printf("%s = %s + / + %s\n", preop,\
|
||||
xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1), path);
|
||||
|
||||
return xmlStrsub (preop, 0, xmlStrlen(preop) - xmlStrlen(path) - 1);
|
||||
}
|
||||
|
||||
static inline xmlChar* getLastTag(xmlChar *path)
|
||||
{
|
||||
while ((ulong)xmlStrchr (path, '/'))
|
||||
path = splitStrAtSlash((xmlChar *)path);
|
||||
|
||||
// //printf("last tag in the path = <%s>\n", path);
|
||||
return path; // which is no more the given path but only its last tag !
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static xmlNodePtr model_get_node(xmlChar *path)
|
||||
{
|
||||
xmlNodePtr node;
|
||||
xmlChar *extrait;
|
||||
xmlChar *reste, *last, *affich;
|
||||
|
||||
// Lookup for node from path in hash table
|
||||
node = xmlHashLookup(model_hashtable, path);
|
||||
|
||||
// Found a node in hash table
|
||||
if (node) {
|
||||
return node;
|
||||
|
||||
// no node found in hash table
|
||||
} else {
|
||||
reste = path;
|
||||
affich = reste;
|
||||
last = getLastTag(reste);
|
||||
node = xmlDocGetRootElement(model);
|
||||
|
||||
while (xmlStrchr (reste, '/')) {
|
||||
extrait = getFirstTag(reste);
|
||||
reste = splitStrAtSlash((xmlChar *)reste);
|
||||
node = node->xmlChildrenNode;
|
||||
node = getNextChild(node, extrait);
|
||||
}
|
||||
|
||||
if(node && xmlStrcmp(node->name, last)) {
|
||||
node = node->xmlChildrenNode;
|
||||
|
||||
while (node && xmlStrcmp(node->name, last)) {
|
||||
node = node->next;
|
||||
}
|
||||
xmlHashAddEntry (model_hashtable, path, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
static inline long model_get_node_long_attrib(xmlNodePtr node, char *id)
|
||||
{
|
||||
xmlAttr *attribute;
|
||||
xmlChar* value;
|
||||
long ret_value;
|
||||
|
||||
if (node && node->properties) {
|
||||
attribute = node->properties;
|
||||
while(attribute && attribute->name && attribute->children) {
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
|
||||
value = xmlNodeListGetString(node->doc, attribute->children, 1);
|
||||
ret_value = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
return ret_value;
|
||||
}
|
||||
attribute = attribute->next;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool model_get_node_str_attrib(xmlNodePtr node,
|
||||
char *id,
|
||||
char *dest)
|
||||
{
|
||||
xmlAttr *attribute;
|
||||
xmlChar* value;
|
||||
|
||||
if (node && node->properties) {
|
||||
attribute = node->properties;
|
||||
while(attribute && attribute->name && attribute->children) {
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)id)) {
|
||||
value = xmlNodeListGetString(node->doc, attribute->children, 1);
|
||||
strcpy(dest, value);
|
||||
xmlFree(value);
|
||||
return true;
|
||||
}
|
||||
attribute = attribute->next;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
char model_get_dim(void)
|
||||
{
|
||||
xmlAttr *attribute;
|
||||
xmlChar* value;
|
||||
xmlNodePtr node = model_get_node(
|
||||
(xmlChar *)"parameters/space-param/dimension");
|
||||
|
||||
if (xmlHasProp (node, (xmlChar *) "z")) return 3;
|
||||
if (xmlHasProp (node, (xmlChar *) "y")) return 2;
|
||||
if (xmlHasProp (node, (xmlChar *) "x")) return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
long model_get_dim_value(const char *axis)
|
||||
{
|
||||
xmlAttr *attribute;
|
||||
xmlChar *value;
|
||||
long ret_value;
|
||||
xmlNodePtr node = model_get_node(
|
||||
(xmlChar *)"parameters/space-param/dimension");
|
||||
|
||||
return model_get_node_long_attrib(node, axis);
|
||||
}
|
||||
|
||||
char model_get_multiplicity(void)
|
||||
{
|
||||
xmlAttr *attribute;
|
||||
xmlChar* value;
|
||||
xmlNodePtr node = model_get_node(
|
||||
(xmlChar *)"parameters/space-param/site_multiplicity");
|
||||
|
||||
if (node->children)
|
||||
if (node->children->content)
|
||||
return (char)strtol((char *)node->children->content, NULL, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool model_get_next_state(char *new_state_id)
|
||||
{
|
||||
static xmlNodePtr cur_node = NULL;
|
||||
xmlAttr *attribute;
|
||||
xmlChar *value;
|
||||
|
||||
if (cur_node == NULL) {
|
||||
// Get first state
|
||||
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||
|
||||
} else {
|
||||
// Get next state
|
||||
if (cur_node->next)
|
||||
cur_node = cur_node->next;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Lookup in properties
|
||||
if (model_get_node_str_attrib(cur_node, "id", new_state_id))
|
||||
return true;
|
||||
|
||||
cur_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
long model_get_state_arrows_count(const char *state_id)
|
||||
{
|
||||
xmlNodePtr cur_node = NULL;
|
||||
xmlAttr *attribute;
|
||||
long value = 0;
|
||||
bool found = false;
|
||||
char temp_char[25];
|
||||
uint check = 0; // bit field checker
|
||||
|
||||
//printf("NEW CALL : cur_node = %p\n", cur_node);
|
||||
|
||||
assert(state_id);
|
||||
|
||||
// Get first state node
|
||||
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||
|
||||
// Lookup in properties
|
||||
while (cur_node && cur_node->properties) {
|
||||
attribute = cur_node->properties;
|
||||
|
||||
// Look for the id attribute
|
||||
if (model_get_node_str_attrib(cur_node, "id", &temp_char)) {
|
||||
if (!xmlStrcmp(temp_char, (const xmlChar *)state_id)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_node = cur_node->next;
|
||||
}
|
||||
|
||||
// Check if the state has been found
|
||||
if (!found) {
|
||||
cur_node = NULL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// Count arrows
|
||||
if (cur_node->children) {
|
||||
cur_node = cur_node->children;
|
||||
while (cur_node) {
|
||||
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow"))
|
||||
value++;
|
||||
cur_node = cur_node->next;
|
||||
}
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool model_get_next_arrow(struct arrow_t *new_arrow,
|
||||
const char *state_id,
|
||||
char dimension)
|
||||
{
|
||||
static xmlNodePtr cur_node = NULL;
|
||||
xmlAttr *attribute;
|
||||
xmlChar *value;
|
||||
bool found = false;
|
||||
char temp_char[25];
|
||||
uint check = 0; // bit field checker
|
||||
|
||||
//printf("NEW CALL : cur_node = %p\n", cur_node);
|
||||
|
||||
assert(new_arrow);
|
||||
assert(state_id);
|
||||
|
||||
if (cur_node == NULL) {
|
||||
// Get first state node
|
||||
cur_node = model_get_node((xmlChar *)"savedstates/state");
|
||||
|
||||
// Lookup in properties
|
||||
while (cur_node && cur_node->properties) {
|
||||
attribute = cur_node->properties;
|
||||
|
||||
// Look for the id attribute
|
||||
if (model_get_node_str_attrib(cur_node, "id", &temp_char)) {
|
||||
if (!xmlStrcmp(temp_char, (const xmlChar *)state_id)) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
cur_node = cur_node->next;
|
||||
}
|
||||
|
||||
// Check if the state has been found
|
||||
if (!found) {
|
||||
cur_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get first arrow
|
||||
if (cur_node->children) {
|
||||
cur_node = cur_node->children;
|
||||
|
||||
found = false;
|
||||
while (cur_node && cur_node->name) {
|
||||
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
cur_node = cur_node->next;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the state has been found
|
||||
if (!found) {
|
||||
cur_node = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Get next arrow
|
||||
found = false;
|
||||
while (cur_node->next) {
|
||||
cur_node = cur_node->next;
|
||||
if (!xmlStrcmp(cur_node->name, (const xmlChar *)"arrow")) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the state has been found
|
||||
if (!found) {
|
||||
cur_node = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//printf("DURING CALL : cur_node = %p\n", cur_node);
|
||||
//printf("DURING CALL : cur_node->name = %s\n", cur_node->name);
|
||||
|
||||
// Lookup in properties
|
||||
if (cur_node && cur_node->properties) {
|
||||
attribute = cur_node->properties;
|
||||
|
||||
while(attribute && attribute->name && attribute->children) {
|
||||
//printf("attr name : %s\n", attribute->name);
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)"site")) {
|
||||
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||
new_arrow->site = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
check |= READ_SITE;
|
||||
}
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)"weight")) {
|
||||
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||
new_arrow->load = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
check |= READ_WEIGHT;
|
||||
}
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)"x")) {
|
||||
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||
new_arrow->x = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
check |= READ_X;
|
||||
}
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)"y")) {
|
||||
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||
new_arrow->y = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
check |= READ_Y;
|
||||
}
|
||||
if (!xmlStrcmp(attribute->name, (const xmlChar *)"z")) {
|
||||
value = xmlNodeListGetString(cur_node->doc, attribute->children, 1);
|
||||
new_arrow->z = strtol((char *)value, NULL, 0);
|
||||
xmlFree(value);
|
||||
check |= READ_Z;
|
||||
}
|
||||
attribute = attribute->next;
|
||||
}
|
||||
|
||||
switch(dimension) {
|
||||
case 3:
|
||||
return (bool)(check & SUCCESSFUL_READ_ARROW_XYZ);
|
||||
case 2:
|
||||
return (bool)(check & SUCCESSFUL_READ_ARROW_XY);
|
||||
case 1:
|
||||
return (bool)(check & SUCCESSFUL_READ_ARROW_X);
|
||||
}
|
||||
}
|
||||
cur_node = NULL;
|
||||
return false;
|
||||
}
|
39
gg/parsing.h
39
gg/parsing.h
|
@ -1,39 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: Model parsing header
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../include/base.h"
|
||||
|
||||
bool model_init(const char *content, size_t length, const char *basename);
|
||||
bool model_shutdown(void);
|
||||
|
||||
char model_get_dim(void);
|
||||
long model_get_dim_value(const char *axis);
|
||||
char model_get_multiplicity(void);
|
||||
bool model_get_next_state(char *new_state_id);
|
||||
bool model_get_next_arrow(struct arrow_t *new_arrow,
|
||||
const char *state_id,
|
||||
char dimension);
|
|
@ -1,118 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<gem-graph-model version="0.2.1">
|
||||
|
||||
<identity>
|
||||
<name>Modèle de test</name>
|
||||
|
||||
<owner>Léontine Patinette</owner>
|
||||
|
||||
<owner_id>2</owner_id>
|
||||
|
||||
<date>1630000000</date>
|
||||
|
||||
<version>1.0</version>
|
||||
|
||||
<g_ref id="Cause" date="1630000000" author="toujours" lang="en">Ref</g_ref>
|
||||
</identity>
|
||||
|
||||
<parameters id="texte" date="0" author="Léontine Trottine.">
|
||||
<simulation>
|
||||
<max_thread>0</max_thread>
|
||||
<max_cycles>9</max_cycles>
|
||||
|
||||
</simulation>
|
||||
|
||||
<space-param>
|
||||
<!-- loop_on_zero="true" anything moved before zero reenters at the end of space-->
|
||||
<!-- loop_on_zero="false" anything moved before zero is lost-->
|
||||
<!-- loop_on_max="true" anything moved beyond max reenters at the zero of space-->
|
||||
<!-- loop_on_max="false" anything moved beyond max is lost-->
|
||||
|
||||
<dimension x="29"/>
|
||||
|
||||
<!-- Site_multiplicity = number of sites in a space unit. -->
|
||||
<!-- Each site points towards a neighbouring space unit. -->
|
||||
<!-- Several arrows can be stacked in the same site. -->
|
||||
|
||||
<site_multiplicity>3</site_multiplicity>
|
||||
|
||||
</space-param>
|
||||
|
||||
</parameters>
|
||||
|
||||
<!-- Model objects definition -->
|
||||
|
||||
<objects id="only dimers in this model" date="1630000000" author="inanimés,... âme ?">
|
||||
<object id="a dimer" date="1630000000" author="Alphonse">
|
||||
<arrow site="1" weight="1" x="0"/>
|
||||
<arrow site="2" weight="1" x="1"/>
|
||||
</object>
|
||||
|
||||
</objects>
|
||||
|
||||
|
||||
<!-- Saved space description (initial space is sequence 0) -->
|
||||
|
||||
<savedstates id="texte" date="1630000000" author="Qui courrait dans l'herbe'">
|
||||
<state id="initial" date="1630000000" author="Une souris verte">
|
||||
<arrow site="0" weight="1" x="0"/>
|
||||
<arrow site="1" weight="1" x="1"/>
|
||||
<arrow site="0" weight="1" x="10"/>
|
||||
<arrow site="1" weight="1" x="11"/>
|
||||
<arrow site="0" weight="1" x="20"/>
|
||||
<arrow site="1" weight="1" x="21"/>
|
||||
|
||||
<!-- Three dimers 1-1 are drawn in the global space
|
||||
at locations (0,1) (10,11) and (20,21) -->
|
||||
|
||||
</state>
|
||||
|
||||
</savedstates>
|
||||
|
||||
<!-- Model transitions definition (rules) -->
|
||||
<!-- In this version : <xs:sequence minOccurs="0" maxOccurs="unbounded">-->
|
||||
<!-- Transitions should be edited by hand and written in a 'human-readable' format -->
|
||||
|
||||
<conditions id="random walk of dimers" date="1630000000" author="Zazard le lézard !">
|
||||
|
||||
<condition site="1" weight="1" node_id="1" parent="0" x="0"/>
|
||||
<condition site="2" weight="1" node_id="2" parent="1" x="1"/>
|
||||
<!-- as soon as conditions 1 and 2 are satisfied, a dimer is identified at atation (0,1). -->
|
||||
|
||||
<condition site="1" weight="0" node_id="3" parent="2" x="2"/>
|
||||
<!-- as soon as condition 3 is satisfied,
|
||||
the neighbouring space unit to East of the dimer is empty
|
||||
and the dimer identified by conditions (1,2) can be moved to East. -->
|
||||
|
||||
<condition site="2" weight="0" node_id="4" parent="2" x="-1"/>
|
||||
<!-- as soon as condition 4 is satisfied,
|
||||
the neighbouring space unit to West of the dimer is empty
|
||||
and the dimer identified by conditions (1,2) can be moved to West. -->
|
||||
|
||||
</conditions>
|
||||
|
||||
<transitions>
|
||||
|
||||
<transition id="move_a_dimer_to_east" date="1630000000" author="Pas moi..."
|
||||
parent="3" probability="1">
|
||||
|
||||
<arrow site="1" weight="0" x="0"/>
|
||||
<arrow site="2" weight="0" x="1"/>
|
||||
<arrow site="1" weight="1" x="1"/>
|
||||
<arrow site="2" weight="1" x="2"/>
|
||||
|
||||
</transition>
|
||||
|
||||
<transition id="move_a_dimer_to_west" date="1630000000" author="Ni moi !"
|
||||
parent="4" probability="1">
|
||||
|
||||
<arrow site="1" weight="0" x="0"/>
|
||||
<arrow site="2" weight="0" x="1"/>
|
||||
<arrow site="2" weight="1" x="0"/>
|
||||
<arrow site="1" weight="1" x="1"/>
|
||||
|
||||
</transition>
|
||||
|
||||
</transitions>
|
||||
|
||||
</gem-graph-model>
|
232
gg/ui.h
232
gg/ui.h
|
@ -1,232 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface header
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <unistd.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
|
||||
#include "../include/base.h"
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEM_GRAPH_CLIENT_TYPE_WINDOW (gem_graph_client_window_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GemGraphClientWindow,
|
||||
gem_graph_client_window,
|
||||
GEM_GRAPH_CLIENT,
|
||||
WINDOW,
|
||||
GtkApplicationWindow)
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
#define GEM_GRAPH_CLIENT_TYPE_APPLICATION (gem_graph_client_application_get_type())
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GemGraphClientApplication,
|
||||
gem_graph_client_application,
|
||||
GEM_GRAPH_CLIENT,
|
||||
APPLICATION,
|
||||
GtkApplication)
|
||||
|
||||
GemGraphClientApplication *gem_graph_client_application_new(const char *application_id,
|
||||
GApplicationFlags flags);
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
|
||||
void ui_enable_action(const char *name);
|
||||
|
||||
void ui_disable_action(const char *name);
|
||||
|
||||
//
|
||||
// Actions
|
||||
//
|
||||
void on_about_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_quit_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_preferences_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_togglesidebar_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_editmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_runmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_presentmode_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_openfile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_closefile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_savefile_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
void on_toast_close_action(GSimpleAction *action,
|
||||
GVariant *parameter,
|
||||
gpointer user_data);
|
||||
|
||||
|
||||
static const GActionEntry app_actions[] = {
|
||||
{ "quit", on_quit_action, NULL, NULL, NULL },
|
||||
{ "about", on_about_action, NULL, NULL, NULL },
|
||||
{ "preferences", on_preferences_action, NULL, NULL, NULL },
|
||||
{ "togglesidebar", on_togglesidebar_action, NULL, NULL, NULL },
|
||||
{ "editmode", on_editmode_action, NULL, NULL, NULL },
|
||||
{ "runmode", on_runmode_action, NULL, NULL, NULL },
|
||||
{ "presentmode", on_presentmode_action, NULL, NULL, NULL },
|
||||
{ "openfile", on_openfile_action, NULL, NULL, NULL },
|
||||
{ "closefile", on_closefile_action, NULL, NULL, NULL },
|
||||
{ "savefile", on_savefile_action, NULL, NULL, NULL },
|
||||
{ "toastclose", on_toast_close_action, NULL, NULL, NULL },
|
||||
};
|
||||
|
||||
//
|
||||
// Actions responses
|
||||
//
|
||||
void on_openfile_response(GtkNativeDialog *native,
|
||||
int response,
|
||||
GemGraphClientWindow *self);
|
||||
|
||||
void ui_model_loading(GObject *source_object,
|
||||
GAsyncResult *result,
|
||||
GemGraphClientWindow *self);
|
||||
|
||||
//
|
||||
// General events
|
||||
//
|
||||
void on_axis_value_change(GtkAdjustment *adjustment, gpointer data);
|
||||
|
||||
gboolean on_glarea_render(GtkGLArea * area, GdkGLContext * context);
|
||||
|
||||
void on_glarea_realize(GtkWidget *widget);
|
||||
|
||||
void on_glarea_unrealize(GtkWidget *widget);
|
||||
|
||||
void on_close_window(GtkWidget *widget);
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
//
|
||||
// Window primitives
|
||||
//
|
||||
|
||||
void ui_set_stack(int mode);
|
||||
|
||||
void ui_send_internal_notification(const char *message);
|
||||
void ui_close_internal_notification(void);
|
||||
void ui_toggle_sidebar();
|
||||
|
||||
//
|
||||
// Graphical stuff
|
||||
//
|
||||
|
||||
/*
|
||||
* Creates GLArea and indexes it
|
||||
*
|
||||
* @params target_mode, meaning which ui_stack we're on
|
||||
* target_widget, meaning the box that will host the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_setup_glarea(int target_mode, GtkWidget *target_widget);
|
||||
|
||||
|
||||
/*
|
||||
* Look for stack entry and returns stack_id
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns stack_id
|
||||
*/
|
||||
long ui_get_graphic_stack(void *container_widget);
|
||||
|
||||
/*
|
||||
* Look for stack entry and initializes OpenGL for it
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_init_graphic_stack(void *container_widget, GError *error_buffer);
|
||||
|
||||
/*
|
||||
* Look for stack entry and shutdowns OpenGL for it
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_shutdown_graphic_stack(void *container_widget, GError *error_buffer);
|
||||
|
||||
|
||||
void ui_clean_stack_index(void);
|
||||
|
||||
/*
|
||||
* Look for stack entry and triggers OpenGL for drawing
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_render_stack(GtkWidget *container_widget);
|
||||
|
||||
/*
|
||||
* Look for every stack entry and shutdowns OpenGL for it
|
||||
*
|
||||
* @params void
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
void ui_shutdown_all_graphic_stacks(void);
|
||||
|
||||
/*
|
||||
* Look for stack entry and triggers OpenGL for drawing
|
||||
*
|
||||
* @params container_widget, generally the GtkBox that contains the GLArea
|
||||
*
|
||||
* @returns bool, true if success
|
||||
*/
|
||||
bool ui_update_axis_stack(GtkWidget *container_widget, int axis, int value);
|
||||
|
236
gg/window.c
236
gg/window.c
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include <glib-2.0/glib.h>
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static GemGraphClientWindow *window;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct _GemGraphClientWindow
|
||||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
/* Template widgets */
|
||||
GtkHeaderBar *main_titlebar;
|
||||
GtkStack *main_stack;
|
||||
GtkStack *side_stack;
|
||||
GtkPaned *main_paned;
|
||||
GtkMenuButton *main_button_mode;
|
||||
GtkToggleButton *main_button_sidebar;
|
||||
GtkRevealer *toast_revealer;
|
||||
GtkToggleButton *toast_close_button;
|
||||
GtkLabel *toast_text;
|
||||
GtkBox *control_zone;
|
||||
GtkBox *run_glarea_box;
|
||||
GtkBox *edition_glarea_box;
|
||||
GtkBox *presentation_glarea_box;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (GemGraphClientWindow,
|
||||
gem_graph_client_window,
|
||||
GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static void gem_graph_client_window_class_init(GemGraphClientWindowClass *klass)
|
||||
{
|
||||
gchar *contents;
|
||||
gsize len;
|
||||
GError *err;
|
||||
GBytes *bytes;
|
||||
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
|
||||
|
||||
if (g_file_get_contents("src/ui/gemgraph.ui", &contents, &len, &err) == FALSE)
|
||||
g_error("error reading gemgraph.ui: %s", err->message);
|
||||
|
||||
bytes = g_bytes_new_take(contents, len);
|
||||
gtk_widget_class_set_template(GTK_WIDGET_CLASS(klass), bytes);
|
||||
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_titlebar);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_stack);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
side_stack);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_paned);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_button_mode);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_button_sidebar);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_revealer);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_close_button);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_text);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
control_zone);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
run_glarea_box);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
edition_glarea_box);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
presentation_glarea_box);
|
||||
}
|
||||
|
||||
static void gem_graph_client_window_init(GemGraphClientWindow *self)
|
||||
{
|
||||
gtk_widget_init_template(GTK_WIDGET(self));
|
||||
window = self;
|
||||
|
||||
// Launch with sidebar off
|
||||
ui_toggle_sidebar();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ui_set_stack(int mode)
|
||||
{
|
||||
//g_printerr("[debug] ui_set_stack()\n");
|
||||
|
||||
if (window->main_stack == NULL) {
|
||||
g_printerr("Can't find self->main_stack !\n");
|
||||
return;
|
||||
}
|
||||
if (window->side_stack == NULL) {
|
||||
g_printerr("Can't find self->side_stack !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch on the first letter of the mode, because switch is soooo simple :)
|
||||
switch(mode) {
|
||||
case EDIT_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"edition",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"edition",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"document-edit-symbolic");
|
||||
ui_setup_glarea(EDIT_MODE, GTK_WIDGET(window->edition_glarea_box));
|
||||
break;
|
||||
case RUN_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"run",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"run",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"system-run-symbolic");
|
||||
ui_setup_glarea(RUN_MODE, GTK_WIDGET(window->run_glarea_box));
|
||||
break;
|
||||
case PRESENTATION_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"presentation",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"presentation",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"x-office-presentation-symbolic");
|
||||
ui_setup_glarea(PRESENTATION_MODE,
|
||||
GTK_WIDGET(window->presentation_glarea_box));
|
||||
break;
|
||||
case HOME_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"home",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"home",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_paned_set_position(window->main_paned, 0);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"user-home-symbolic");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_send_internal_notification(const char *message)
|
||||
{
|
||||
if (window->toast_revealer == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->toast_text == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_label_set_label(window->toast_text, message);
|
||||
gtk_revealer_set_reveal_child(window->toast_revealer, true);
|
||||
g_printerr("%s\n", message);
|
||||
}
|
||||
|
||||
void ui_close_internal_notification(void)
|
||||
{
|
||||
if (window->toast_revealer == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->toast_text == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_revealer_set_reveal_child(window->toast_revealer, false);
|
||||
}
|
||||
|
||||
|
||||
void ui_toggle_sidebar(void)
|
||||
{
|
||||
int position = gtk_paned_get_position(window->main_paned);
|
||||
|
||||
if (position != 0) {
|
||||
gtk_paned_set_position(window->main_paned, 0);
|
||||
} else {
|
||||
gtk_paned_set_position(window->main_paned, 400);
|
||||
}
|
||||
}
|
|
@ -1,150 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
|
||||
struct _GemGraphClientApplication
|
||||
{
|
||||
GtkApplication parent_instance;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GemGraphClientApplication,
|
||||
gem_graph_client_application,
|
||||
GTK_TYPE_APPLICATION)
|
||||
|
||||
|
||||
static GemGraphClientApplication *application;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ui_enable_action(const char *name) {
|
||||
g_simple_action_set_enabled(
|
||||
(GSimpleAction *)g_action_map_lookup_action(
|
||||
G_ACTION_MAP(application),
|
||||
name),
|
||||
true);
|
||||
}
|
||||
|
||||
void ui_disable_action(const char *name) {
|
||||
g_simple_action_set_enabled(
|
||||
(GSimpleAction *)g_action_map_lookup_action(
|
||||
G_ACTION_MAP(application),
|
||||
name),
|
||||
false);
|
||||
}
|
||||
|
||||
/*
|
||||
* Window actual presentation on screen
|
||||
*
|
||||
*/
|
||||
static void gem_graph_client_application_activate(GApplication *app)
|
||||
{
|
||||
GtkWindow *window;
|
||||
|
||||
g_assert(GEM_GRAPH_CLIENT_IS_APPLICATION(app));
|
||||
|
||||
window = gtk_application_get_active_window(GTK_APPLICATION (app));
|
||||
if (window == NULL)
|
||||
window = g_object_new(GEM_GRAPH_CLIENT_TYPE_WINDOW,
|
||||
"application", app,
|
||||
NULL);
|
||||
|
||||
ui_set_stack(HOME_MODE);
|
||||
|
||||
gtk_window_present(window);
|
||||
}
|
||||
|
||||
/*
|
||||
* Action records are registered here
|
||||
*
|
||||
*/
|
||||
static void gem_graph_client_application_init(GemGraphClientApplication *self)
|
||||
{
|
||||
g_action_map_add_action_entries(G_ACTION_MAP(self),
|
||||
app_actions,
|
||||
G_N_ELEMENTS(app_actions),
|
||||
self);
|
||||
|
||||
// Setup shortcuts
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.quit",
|
||||
(const char *[]) { "<primary>q", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.editmode",
|
||||
(const char *[]) { "<primary>e", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.runmode",
|
||||
(const char *[]) { "<primary>r", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.presentmode",
|
||||
(const char *[]) { "<primary>p", NULL });
|
||||
gtk_application_set_accels_for_action(GTK_APPLICATION(self),
|
||||
"app.savefile",
|
||||
(const char *[]) { "<primary>s", NULL });
|
||||
|
||||
application = self;
|
||||
|
||||
//
|
||||
// Disable unneeded/inoperant actions
|
||||
//
|
||||
ui_disable_action("savefile");
|
||||
ui_disable_action("closefile");
|
||||
ui_disable_action("editmode");
|
||||
ui_disable_action("runmode");
|
||||
ui_disable_action("presentmode");
|
||||
ui_disable_action("togglesidebar");
|
||||
}
|
||||
|
||||
void ui_send_notification(const char *message)
|
||||
{
|
||||
g_print("NOTIFICATION: %s\n", message);
|
||||
|
||||
g_application_send_notification(G_APPLICATION(application),
|
||||
"notification",
|
||||
g_notification_new(message)
|
||||
);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static void gem_graph_client_application_class_init(
|
||||
GemGraphClientApplicationClass *klass)
|
||||
{
|
||||
GApplicationClass *app_class = G_APPLICATION_CLASS(klass);
|
||||
|
||||
app_class->activate = gem_graph_client_application_activate;
|
||||
}
|
||||
|
||||
GemGraphClientApplication *gem_graph_client_application_new(
|
||||
const char *application_id,
|
||||
GApplicationFlags flags)
|
||||
{
|
||||
g_return_val_if_fail(application_id != NULL, NULL);
|
||||
|
||||
return g_object_new(GEM_GRAPH_CLIENT_TYPE_APPLICATION,
|
||||
"application-id", application_id,
|
||||
"flags", flags,
|
||||
NULL);
|
||||
}
|
236
junks/0_window.c
236
junks/0_window.c
|
@ -1,236 +0,0 @@
|
|||
/*
|
||||
* Gem-graph OpenGL experiments
|
||||
*
|
||||
* Desc: User interface functions
|
||||
*
|
||||
* Copyright (C) 2023 Arthur Menges <arthur.menges@a-lec.org>
|
||||
* Copyright (C) 2023 Adrien Bourmault <neox@a-lec.org>
|
||||
*
|
||||
* This file is part of Gem-graph.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* This program 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 Affero General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <gtk-4.0/gtk/gtk.h>
|
||||
#include <glib-2.0/glib.h>
|
||||
|
||||
#include "../../include/base.h"
|
||||
#include "../../include/ui.h"
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
static GemGraphClientWindow *window;
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
struct _GemGraphClientWindow
|
||||
{
|
||||
GtkApplicationWindow parent_instance;
|
||||
|
||||
/* Template widgets */
|
||||
GtkHeaderBar *main_titlebar;
|
||||
GtkStack *main_stack;
|
||||
GtkStack *side_stack;
|
||||
GtkPaned *main_paned;
|
||||
GtkMenuButton *main_button_mode;
|
||||
GtkToggleButton *main_button_sidebar;
|
||||
GtkRevealer *toast_revealer;
|
||||
GtkToggleButton *toast_close_button;
|
||||
GtkLabel *toast_text;
|
||||
GtkBox *control_zone;
|
||||
GtkBox *run_glarea_box;
|
||||
GtkBox *edition_glarea_box;
|
||||
GtkBox *presentation_glarea_box;
|
||||
};
|
||||
|
||||
G_DEFINE_FINAL_TYPE (GemGraphClientWindow,
|
||||
gem_graph_client_window,
|
||||
GTK_TYPE_APPLICATION_WINDOW)
|
||||
|
||||
static void gem_graph_client_window_class_init(GemGraphClientWindowClass *klass)
|
||||
{
|
||||
gchar *contents;
|
||||
gsize len;
|
||||
GError *err;
|
||||
GBytes *bytes;
|
||||
|
||||
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS(klass);
|
||||
|
||||
if (g_file_get_contents("src/ui/gemgraph.ui", &contents, &len, &err) == FALSE)
|
||||
g_error("error reading gemgraph.ui: %s", err->message);
|
||||
|
||||
bytes = g_bytes_new_take(contents, len);
|
||||
gtk_widget_class_set_template(GTK_WIDGET_CLASS(klass), bytes);
|
||||
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_titlebar);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_stack);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
side_stack);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_paned);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_button_mode);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
main_button_sidebar);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_revealer);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_close_button);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
toast_text);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
control_zone);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
run_glarea_box);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
edition_glarea_box);
|
||||
gtk_widget_class_bind_template_child(widget_class,
|
||||
GemGraphClientWindow,
|
||||
presentation_glarea_box);
|
||||
}
|
||||
|
||||
static void gem_graph_client_window_init(GemGraphClientWindow *self)
|
||||
{
|
||||
gtk_widget_init_template(GTK_WIDGET(self));
|
||||
window = self;
|
||||
|
||||
// Launch with sidebar off
|
||||
ui_toggle_sidebar();
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------------- */
|
||||
|
||||
void ui_set_stack(int mode)
|
||||
{
|
||||
//g_printerr("[debug] ui_set_stack()\n");
|
||||
|
||||
if (window->main_stack == NULL) {
|
||||
g_printerr("Can't find self->main_stack !\n");
|
||||
return;
|
||||
}
|
||||
if (window->side_stack == NULL) {
|
||||
g_printerr("Can't find self->side_stack !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// Switch on the first letter of the mode, because switch is soooo simple :)
|
||||
switch(mode) {
|
||||
case EDIT_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"edition",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"edition",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"document-edit-symbolic");
|
||||
ui_setup_glarea(EDIT_MODE, GTK_WIDGET(window->edition_glarea_box));
|
||||
break;
|
||||
case RUN_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"run",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"run",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"system-run-symbolic");
|
||||
ui_setup_glarea(RUN_MODE, GTK_WIDGET(window->run_glarea_box));
|
||||
break;
|
||||
case PRESENTATION_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"presentation",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"presentation",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"x-office-presentation-symbolic");
|
||||
ui_setup_glarea(PRESENTATION_MODE,
|
||||
GTK_WIDGET(window->presentation_glarea_box));
|
||||
break;
|
||||
case HOME_MODE:
|
||||
gtk_stack_set_visible_child_full(window->main_stack,
|
||||
"home",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_stack_set_visible_child_full(window->side_stack,
|
||||
"home",
|
||||
GTK_STACK_TRANSITION_TYPE_CROSSFADE);
|
||||
gtk_paned_set_position(window->main_paned, 0);
|
||||
gtk_menu_button_set_icon_name(window->main_button_mode,
|
||||
"user-home-symbolic");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ui_send_internal_notification(const char *message)
|
||||
{
|
||||
if (window->toast_revealer == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->toast_text == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_label_set_label(window->toast_text, message);
|
||||
gtk_revealer_set_reveal_child(window->toast_revealer, true);
|
||||
g_printerr("%s\n", message);
|
||||
}
|
||||
|
||||
void ui_close_internal_notification(void)
|
||||
{
|
||||
if (window->toast_revealer == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window->toast_text == NULL) {
|
||||
g_printerr("Can't find self->toast_overlay !\n");
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_revealer_set_reveal_child(window->toast_revealer, false);
|
||||
}
|
||||
|
||||
|
||||
void ui_toggle_sidebar(void)
|
||||
{
|
||||
int position = gtk_paned_get_position(window->main_paned);
|
||||
|
||||
if (position != 0) {
|
||||
gtk_paned_set_position(window->main_paned, 0);
|
||||
} else {
|
||||
gtk_paned_set_position(window->main_paned, 400);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue