gem-graph-client/graph_area.c

314 lines
8.8 KiB
C

/*
* 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 "contain.h"
#include "graph_area.h"
#include "callback.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_set_visible (label, TRUE);
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_set_visible (slider, TRUE);
gtk_widget_set_visible (box, TRUE);
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_set_visible (GTK_WIDGET (gl_area), TRUE);
// Create sliders
for(int i = 0; i < N_AXIS; i++)
gtk_box_append(GTK_BOX(target_widget), create_axis_slider(i));
return true;
}