diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-09-21 22:16:54 -0400 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-09-23 00:54:28 -0400 |
commit | 50725b67ac0037c00949dc92d7ed4d23a6f85c3a (patch) | |
tree | b0dae883ecb6d536dfa97650adf724aae274aff0 /demos/gtk-demo/gltransition.c | |
parent | aeae3522b683fbc84641e5084d0935391c0f7026 (diff) | |
download | gtk+-matthiasc/gltransition-demo.tar.gz |
Add another shader node demomatthiasc/gltransition-demo
This one does stack-like transitions, using
some examples from gl-transitions.com.
Diffstat (limited to 'demos/gtk-demo/gltransition.c')
-rw-r--r-- | demos/gtk-demo/gltransition.c | 250 |
1 files changed, 250 insertions, 0 deletions
diff --git a/demos/gtk-demo/gltransition.c b/demos/gtk-demo/gltransition.c new file mode 100644 index 0000000000..f29731b9a3 --- /dev/null +++ b/demos/gtk-demo/gltransition.c @@ -0,0 +1,250 @@ +/* OpenGL/Transitions + * #Keywords: OpenGL, shader + * + * Create transitions between pages using a custom fragment shader. + * The examples here are taken from gl-transitions.com. + * + * Click to start a transition. + */ + +#include <math.h> +#include <gtk/gtk.h> +#include "gtkshaderstack.h" + +static GtkWidget *demo_window = NULL; + +static void +close_window (GtkWidget *widget) +{ + /* Reset the state */ + demo_window = NULL; +} + +static GskGLShader * +gsk_shader_new_from_resource (const char *resource_path) +{ + GBytes *shader_b; + GskGLShader *shader; + + shader_b = g_resources_lookup_data (resource_path, 0, NULL); + shader = gsk_glshader_new ((const char *)g_bytes_get_data (shader_b, NULL)); + gsk_glshader_set_n_required_sources (shader, 2); + gsk_glshader_add_uniform (shader, "progress", GSK_GLUNIFORM_TYPE_FLOAT); + g_bytes_unref (shader_b); + + return shader; +} + +static void +text_changed (GtkTextBuffer *buffer, + GtkWidget *button) +{ + gtk_widget_show (button); +} + +static void +apply_text (GtkWidget *button, + GtkTextBuffer *buffer) +{ + GtkWidget *stack; + GskGLShader *shader; + GtkTextIter start, end; + char *text; + + stack = gtk_widget_get_ancestor (button, GTK_TYPE_SHADER_STACK); + + gtk_text_buffer_get_bounds (buffer, &start, &end); + text = gtk_text_buffer_get_text (buffer, &start, &end, TRUE); + + shader = gsk_glshader_new (text); + gsk_glshader_set_n_required_sources (shader, 2); + gsk_glshader_add_uniform (shader, "progress", GSK_GLUNIFORM_TYPE_FLOAT); + + gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader); + + g_object_unref (shader); + g_free (text); + + gtk_widget_hide (button); +} + +static void +clicked_cb (GtkGestureClick *gesture, + guint n_pressed, + double x, + double y, + gpointer data) +{ + gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_CLAIMED); +} + +static GtkWidget * +make_shader_stack (const char *name, + const char *resource_path, + GtkWidget *scale) +{ + GtkWidget *stack, *child, *widget; + GtkWidget *label, *button, *tv; + GskGLShader *shader; + GObjectClass *class; + GParamSpecFloat *pspec; + GtkAdjustment *adjustment; + GtkTextBuffer *buffer; + GBytes *bytes; + GtkEventController *controller; + GtkCssProvider *provider; + + stack = gtk_shader_stack_new (); + shader = gsk_shader_new_from_resource (resource_path); + gtk_shader_stack_set_shader (GTK_SHADER_STACK (stack), shader); + g_object_unref (shader); + + child = gtk_picture_new_for_resource ("/css_pixbufs/background.jpg"); + gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE); + gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); + + child = gtk_picture_new_for_resource ("/transparent/portland-rose.jpg"); + gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE); + gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); + + child = gtk_picture_new_for_resource ("/css_blendmodes/ducky.png"); + gtk_picture_set_can_shrink (GTK_PICTURE (child), TRUE); + gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); + + child = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + + widget = gtk_center_box_new (); + label = gtk_label_new (name); + gtk_widget_add_css_class (label, "title-4"); + gtk_widget_set_size_request (label, -1, 26); + gtk_center_box_set_center_widget (GTK_CENTER_BOX (widget), label); + + button = gtk_button_new_from_icon_name ("view-refresh-symbolic"); + provider = gtk_css_provider_new (); + gtk_css_provider_load_from_data (provider, "button.small { padding: 0; }", -1); + gtk_style_context_add_provider (gtk_widget_get_style_context (button), + GTK_STYLE_PROVIDER (provider), + GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_object_unref (provider); + gtk_widget_set_halign (button, GTK_ALIGN_CENTER); + gtk_widget_set_valign (button, GTK_ALIGN_CENTER); + gtk_widget_add_css_class (button, "small"); + gtk_widget_hide (button); + gtk_center_box_set_end_widget (GTK_CENTER_BOX (widget), button); + + gtk_box_append (GTK_BOX (child), widget); + + class = g_type_class_ref (GTK_TYPE_SHADER_STACK); + pspec = G_PARAM_SPEC_FLOAT (g_object_class_find_property (class, "duration")); + + adjustment = gtk_range_get_adjustment (GTK_RANGE (scale)); + if (gtk_adjustment_get_lower (adjustment) == 0.0 && + gtk_adjustment_get_upper (adjustment) == 0.0) + { + gtk_adjustment_configure (adjustment, + pspec->default_value, + pspec->minimum, + pspec->maximum, + 0.1, 0.5, 0); + } + + g_type_class_unref (class); + + g_object_bind_property (adjustment, "value", + stack, "duration", + G_BINDING_DEFAULT); + + widget = gtk_scrolled_window_new (); + gtk_scrolled_window_set_has_frame (GTK_SCROLLED_WINDOW (widget), TRUE); + gtk_widget_set_hexpand (widget, TRUE); + gtk_widget_set_vexpand (widget, TRUE); + + controller = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ()); + gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (controller), 0); + g_signal_connect (controller, "released", G_CALLBACK (clicked_cb), NULL); + gtk_event_controller_set_propagation_phase (controller, GTK_PHASE_BUBBLE); + gtk_widget_add_controller (GTK_WIDGET (widget), controller); + + tv = gtk_text_view_new (); + gtk_text_view_set_left_margin (GTK_TEXT_VIEW (tv), 4); + gtk_text_view_set_right_margin (GTK_TEXT_VIEW (tv), 4); + gtk_text_view_set_top_margin (GTK_TEXT_VIEW (tv), 4); + gtk_text_view_set_bottom_margin (GTK_TEXT_VIEW (tv), 4); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv)); + bytes = g_resources_lookup_data (resource_path, 0, NULL); + gtk_text_buffer_set_text (buffer, + (const char *)g_bytes_get_data (bytes, NULL), + g_bytes_get_size (bytes)); + g_bytes_unref (bytes); + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (widget), tv); + + g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), button); + g_signal_connect (button, "clicked", G_CALLBACK (apply_text), buffer); + + gtk_box_append (GTK_BOX (child), widget); + + gtk_shader_stack_add_child (GTK_SHADER_STACK (stack), child); + + return stack; +} + +static GtkWidget * +create_gltransition_window (GtkWidget *do_widget) +{ + GtkWidget *window, *headerbar, *scale, *grid; + + window = gtk_window_new (); + gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); + gtk_window_set_title (GTK_WINDOW (window), "Transitions"); + headerbar = gtk_header_bar_new (); + scale = gtk_scale_new (GTK_ORIENTATION_HORIZONTAL, NULL); + gtk_scale_set_draw_value (GTK_SCALE (scale), FALSE); + gtk_widget_set_size_request (scale, 100, -1); + gtk_header_bar_pack_end (GTK_HEADER_BAR (headerbar), scale); + gtk_window_set_titlebar (GTK_WINDOW (window), headerbar); + gtk_window_set_default_size (GTK_WINDOW (window), 400, 400); + g_signal_connect (window, "destroy", G_CALLBACK (close_window), NULL); + + grid = gtk_grid_new (); + gtk_window_set_child (GTK_WINDOW (window), grid); + + gtk_widget_set_halign (grid, GTK_ALIGN_CENTER); + gtk_widget_set_valign (grid, GTK_ALIGN_CENTER); + gtk_widget_set_margin_start (grid, 12); + gtk_widget_set_margin_end (grid, 12); + gtk_widget_set_margin_top (grid, 12); + gtk_widget_set_margin_bottom (grid, 12); + gtk_grid_set_row_spacing (GTK_GRID (grid), 6); + gtk_grid_set_column_spacing (GTK_GRID (grid), 6); + gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE); + gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE); + + gtk_grid_attach (GTK_GRID (grid), + make_shader_stack ("Wind", "/gltransition/transition1.glsl", scale), + 0, 0, 1, 1); + gtk_grid_attach (GTK_GRID (grid), + make_shader_stack ("Radial", "/gltransition/transition2.glsl", scale), + 1, 0, 1, 1); + gtk_grid_attach (GTK_GRID (grid), + make_shader_stack ("Crosswarp", "/gltransition/transition3.glsl", scale), + 0, 1, 1, 1); + gtk_grid_attach (GTK_GRID (grid), + make_shader_stack ("Kaleidoscope", "/gltransition/transition4.glsl", scale), + 1, 1, 1, 1); + + return window; +} + +GtkWidget * +do_gltransition (GtkWidget *do_widget) +{ + if (!demo_window) + demo_window = create_gltransition_window (do_widget); + + if (!gtk_widget_get_visible (demo_window)) + gtk_widget_show (demo_window); + else + gtk_window_destroy (GTK_WINDOW (demo_window)); + + return demo_window; +} |