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