root/OpenSceneGraph/trunk/examples/osgviewerGTK/osgviewerGTK.cpp @ 8294

Revision 8294, 6.9 kB (checked in by robert, 7 years ago)

From Jeremy Moles, fixed window resize problem

Line 
1#include <iostream>
2#include <string>
3#include <osg/Stats>
4#include <osgDB/ReadFile>
5
6#include "osggtkdrawingarea.h"
7
8const char* HELP_TEXT =
9    "Use CTRL or SHIFT plus right-click to pull up a fake menu.\n"
10    "Use the standard TrackballManipulator keys to rotate the loaded\n"
11    "model (with caveats; the model won't keep rotating).\n"
12    "\n"
13    "<b>OpenSceneGraph Project, 2008</b>"
14;
15
16// If you want to see how to connect class method to callbacks, take a look at the
17// implementation of OSGGTKDrawingArea. It's dirty, but it's the only way I could
18// come up with.
19bool activate(GtkWidget* widget, gpointer) {
20    GtkWidget* label = gtk_bin_get_child(GTK_BIN(widget));
21
22    std::cout << "MENU: " << gtk_label_get_label(GTK_LABEL(label)) << std::endl;
23
24    return true;
25}
26
27// Our derived OSGGTKDrawingArea "widget." Redraws occur while the mouse buttons
28// are held down and mouse motion is detected.
29//
30// This is the easiest way to demonstrate the use of OSGGTKDrawingArea. We override
31// a few of the event methods to setup our menu and to issue redraws. Note that an
32// unmodified OSGGTKDrawingArea never calls queueDraw, so OSG is never asked to render
33// itself.
34class ExampleOSGGTKDrawingArea : public OSGGTKDrawingArea {
35    GtkWidget* _menu;
36   
37    unsigned int _tid;
38
39    // A helper function to easily setup our menu entries.
40    void _menuAdd(const std::string& title) {
41        GtkWidget* item = gtk_menu_item_new_with_label(title.c_str());
42       
43        gtk_menu_shell_append(GTK_MENU_SHELL(_menu), item);
44
45        g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(activate), 0);
46    }
47
48    bool _clicked(GtkWidget* widget) {
49        const char* text = gtk_label_get_label(
50            GTK_LABEL(gtk_bin_get_child(GTK_BIN(widget)))
51        );
52
53        if(not std::strncmp(text, "Close", 5)) gtk_main_quit();
54   
55        else if(not std::strncmp(text, "Open File", 9)) {
56            GtkWidget* of = gtk_file_chooser_dialog_new(
57                "Please select an OSG file...",
58                GTK_WINDOW(gtk_widget_get_toplevel(getWidget())),
59                GTK_FILE_CHOOSER_ACTION_OPEN,
60                GTK_STOCK_CANCEL,
61                GTK_RESPONSE_CANCEL,
62                GTK_STOCK_OPEN,
63                GTK_RESPONSE_ACCEPT,
64                NULL
65            );
66
67            if(gtk_dialog_run(GTK_DIALOG(of)) == GTK_RESPONSE_ACCEPT) {
68                char* file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(of));
69
70                osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(file);
71
72                if(model.valid()) {
73                    setSceneData(model.get());
74               
75                    queueDraw();
76                }
77
78                g_free(file);
79            }
80           
81            gtk_widget_destroy(of);
82        }
83
84        // Assume we're wanting FPS toggling.
85        else {
86            if(not _tid) {
87                _tid = g_timeout_add(
88                    15,
89                    (GSourceFunc)(ExampleOSGGTKDrawingArea::timeout),
90                    this
91                );
92
93                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (off)");
94            }
95
96            else {
97                g_source_remove(_tid);
98                gtk_button_set_label(GTK_BUTTON(widget), "Toggle 60 FPS (on)");
99
100                _tid = 0;
101            }
102        }
103
104        return true;
105    }
106
107protected:
108    // Check right-click release to see if we need to popup our menu.
109    bool gtkButtonRelease(double, double, unsigned int button) {
110        if(button == 3 and (stateControl() or stateShift())) gtk_menu_popup(
111            GTK_MENU(_menu),
112            0,
113            0,
114            0,
115            0,
116            button,
117            0
118        );
119
120        return true;
121    }
122
123    // Our "main" drawing pump. Since our app is just a model viewer, we use
124    // click+motion as our criteria for issuing OpenGL refreshes.
125    bool gtkMotionNotify(double, double) {
126        if(stateButton()) queueDraw();
127
128        return true;
129    }
130
131public:
132    ExampleOSGGTKDrawingArea():
133    OSGGTKDrawingArea (),
134    _menu             (gtk_menu_new()),
135    _tid              (0) {
136        _menuAdd("Option");
137        _menuAdd("Another Option");
138        _menuAdd("Still More Options");
139
140        gtk_widget_show_all(_menu);
141
142        getCamera()->setStats(new osg::Stats("omg"));
143    }
144
145    ~ExampleOSGGTKDrawingArea() {}
146
147    // Public so that we can use this as a callback in main().
148    static bool clicked(GtkWidget* widget, gpointer self) {
149        return static_cast<ExampleOSGGTKDrawingArea*>(self)->_clicked(widget);
150    }
151
152    //static gboolean timeout(GtkWidget* widget) {
153    static bool timeout(void* self) {
154        static_cast<ExampleOSGGTKDrawingArea*>(self)->queueDraw();
155
156        return true;
157    }
158};
159
160// Our main() function! FINALLY! Most of this code is GTK stuff, so it's mostly boilerplate.
161// If we wanted to get real jiggy with it we could use Glade and cut down about 20 lines of
162// code or so.
163int main(int argc, char** argv) {
164    gtk_init(&argc, &argv);
165    gtk_gl_init(&argc, &argv);
166
167    ExampleOSGGTKDrawingArea da;
168
169    if(da.createWidget(640, 480)) {
170        if(argc >= 2) {
171            osg::ref_ptr<osg::Node> model = osgDB::readNodeFile(argv[1]);
172
173            if(model.valid()) da.setSceneData(model.get());
174        }
175
176        GtkWidget* window    = gtk_window_new(GTK_WINDOW_TOPLEVEL);
177        GtkWidget* vbox1     = gtk_vbox_new(false, 3);
178        GtkWidget* vbox2     = gtk_vbox_new(false, 3);
179        GtkWidget* hbox      = gtk_hbox_new(false, 3);
180        GtkWidget* label     = gtk_label_new("");
181        GtkWidget* buttons[] = {
182            gtk_button_new_with_label("Open File"),
183            gtk_button_new_with_label("Toggle 60 FPS (on)"),
184            gtk_button_new_with_label("Close")
185        };
186
187        gtk_label_set_use_markup(GTK_LABEL(label), true);
188        gtk_label_set_label(GTK_LABEL(label), HELP_TEXT);
189
190        for(unsigned int i = 0; i < sizeof(buttons) / sizeof(GtkWidget*); i++) {
191            gtk_box_pack_start(
192                GTK_BOX(vbox2),
193                buttons[i],
194                false,
195                false,
196                0
197            );
198
199            g_signal_connect(
200                G_OBJECT(buttons[i]),
201                "clicked",
202                G_CALLBACK(ExampleOSGGTKDrawingArea::clicked),
203                &da
204            );
205        }
206
207        gtk_window_set_title(GTK_WINDOW(window), "osgviewerGTK");
208
209        gtk_box_pack_start(GTK_BOX(hbox), vbox2, true, true, 2);
210        gtk_box_pack_start(GTK_BOX(hbox), label, true, true, 2);
211
212        gtk_box_pack_start(GTK_BOX(vbox1), da.getWidget(), true, true, 2);
213        gtk_box_pack_start(GTK_BOX(vbox1), hbox, false, false, 2);
214
215        gtk_container_set_reallocate_redraws(GTK_CONTAINER(window), true);
216        gtk_container_add(GTK_CONTAINER(window), vbox1);
217
218        g_signal_connect(
219            G_OBJECT(window),
220            "delete_event",
221            G_CALLBACK(gtk_main_quit),
222            0
223        );
224
225        gtk_widget_show_all(window);
226        gtk_main();
227    }
228
229    else return 1;
230
231    return 0;
232}
Note: See TracBrowser for help on using the browser.