2024-06-04 21:36:05 +02:00
|
|
|
/*
|
|
|
|
* 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>
|
|
|
|
|
2024-06-04 22:40:15 +02:00
|
|
|
#include "contain.h"
|
|
|
|
#include "graph_area.h"
|
2024-06-06 22:49:43 +02:00
|
|
|
#include "callback.h"
|
2024-06-04 21:36:05 +02:00
|
|
|
|
|
|
|
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) {
|
2024-06-06 09:41:08 +02:00
|
|
|
stack_index[i].stack_id = graphics_init(&error_buffer);
|
2024-06-04 21:36:05 +02:00
|
|
|
//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) {
|
2024-06-06 09:41:08 +02:00
|
|
|
if (graphics_shutdown(stack_index[i].stack_id,
|
|
|
|
&error_buffer) == false) {
|
|
|
|
return false;
|
|
|
|
}
|
2024-06-04 21:36:05 +02:00
|
|
|
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) {
|
2024-06-06 09:41:08 +02:00
|
|
|
////////////////////////// graphics_draw (stack_index[i].stack_id);
|
2024-06-04 21:36:05 +02:00
|
|
|
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) {
|
2024-06-06 09:41:08 +02:00
|
|
|
graphic_stack[stack_index[i].stack_id].rotation_angles[axis] = value;
|
2024-06-04 21:36:05 +02:00
|
|
|
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++) {
|
2024-06-06 09:41:08 +02:00
|
|
|
graphics_shutdown(stack_index[i].stack_id, NULL);
|
2024-06-04 21:36:05 +02:00
|
|
|
}
|
|
|
|
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);
|
2024-06-06 23:23:25 +02:00
|
|
|
g_signal_connect (adj, "value-changed", G_CALLBACK(on_axis_value_change), (gpointer) label);
|
2024-06-04 21:36:05 +02:00
|
|
|
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
|
2024-06-06 22:49:43 +02:00
|
|
|
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);
|
2024-06-04 21:36:05 +02:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|