Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/gtk/OgreConfigDialog.cpp @ 3

Last change on this file since 3 was 3, checked in by anonymous, 17 years ago

=update

File size: 10.4 KB
Line 
1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2006 Torus Knot Software Ltd
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29#include "OgreConfigDialog.h"
30#include "OgreException.h"
31#include "OgreLogManager.h"
32
33#include <gtk/gtk.h>
34
35namespace Ogre {
36
37/**
38Backdrop image. This is an arbitrary PNG file encoded into a C array.
39
40You can easily generate your own backdrop with the following python script:
41
42#!/usr/bin/python
43import sys
44pngstring=open(sys.argv[2], "rb").read()
45print "static uint8 %s[%i]={%s};" % (sys.argv[1],len(pngstring), ",".join([str(ord(x)) for x in pngstring]))
46
47Call this with
48$ bintoheader.py GLX_backdrop_data GLX_backdrop.png > GLX_backdrop.h
49*/
50#include "GLX_backdrop.h"
51
52/*
53 * A GTK+2 dialog window, making it possible to configure OGRE
54 * in a graphical way. It uses plain C gtk+ bindings since gtk-- is not
55 * part of most standard distributions while gtk+ itself is present
56 * in every Linux distribution I ever seen.
57 */
58
59bool _OgrePrivate __gtk_init_once ()
60{
61    static bool gtk_already_initialized = false;
62    if (gtk_already_initialized)
63        return true;
64
65    gtk_already_initialized = true;
66
67    // Initialize gtk+
68    int argc = 0;
69    char **argv = NULL;
70    // Avoid gtk calling setlocale() otherwise
71    // scanf("%f") won't work on some locales etc.
72    // Leave this on application developer's responsability.
73    gtk_disable_setlocale ();
74    return gtk_init_check (&argc, &argv);
75}
76
77ConfigDialog::ConfigDialog ()
78{
79}
80
81void ConfigDialog::rendererChanged (GtkComboBox *widget, gpointer data)
82{
83    ConfigDialog *This = static_cast<ConfigDialog *> (data);
84
85    gchar *renderer = gtk_combo_box_get_active_text (widget);
86
87    RenderSystemList *renderers = Root::getSingleton ().getAvailableRenderers ();
88    for (RenderSystemList::iterator r = renderers->begin(); r != renderers->end (); r++)
89        if (strcmp (renderer, (*r)->getName ().c_str ()) == 0)
90        {
91            This->mSelectedRenderSystem = *r;
92            This->setupRendererParams ();
93        }
94}
95
96void ConfigDialog::optionChanged (GtkComboBox *widget, gpointer data)
97{
98    ConfigDialog *This = static_cast<ConfigDialog *> (data);
99    GtkWidget *ro_label = static_cast<GtkWidget *> (
100        g_object_get_data (G_OBJECT (widget), "renderer-option"));
101
102    This->mSelectedRenderSystem->setConfigOption (
103        gtk_label_get_text (GTK_LABEL (ro_label)),
104        gtk_combo_box_get_active_text (widget));
105}
106
107static void remove_all_callback (GtkWidget *widget, gpointer data)
108{
109    GtkWidget *container = static_cast<GtkWidget *> (data);
110    gtk_container_remove (GTK_CONTAINER (container), widget);
111}
112
113void ConfigDialog::setupRendererParams ()
114{
115    // Remove all existing child widgets
116    gtk_container_forall (GTK_CONTAINER (mParamTable),
117                          remove_all_callback, mParamTable);
118
119    ConfigOptionMap options = mSelectedRenderSystem->getConfigOptions ();
120
121    // Resize the table to hold as many options as we have
122    gtk_table_resize (GTK_TABLE (mParamTable), options.size (), 2);
123
124    uint row = 0;
125    for (ConfigOptionMap::iterator i = options.begin (); i != options.end (); i++, row++)
126    {
127        GtkWidget *ro_label = gtk_label_new (i->second.name.c_str ());
128        gtk_widget_show (ro_label);
129        gtk_table_attach (GTK_TABLE (mParamTable), ro_label, 0, 1, row, row + 1,
130                          GtkAttachOptions (GTK_EXPAND | GTK_FILL),
131                          GtkAttachOptions (0), 5, 0);
132        gtk_label_set_justify (GTK_LABEL (ro_label), GTK_JUSTIFY_RIGHT);
133        gtk_misc_set_alignment (GTK_MISC (ro_label), 1, 0.5);
134
135        GtkWidget *ro_cb = gtk_combo_box_new_text ();
136        gtk_widget_show (ro_cb);
137        gtk_table_attach (GTK_TABLE (mParamTable), ro_cb, 1, 2, row, row + 1,
138                          GtkAttachOptions (GTK_EXPAND | GTK_FILL),
139                          GtkAttachOptions (0), 5, 0);
140
141        // Set up a link from the combobox to the label
142        g_object_set_data (G_OBJECT (ro_cb), "renderer-option", ro_label);
143
144        StringVector::iterator opt_it;
145        uint idx = 0;
146        for (opt_it = i->second.possibleValues.begin ();
147             opt_it != i->second.possibleValues.end (); opt_it++, idx++)
148        {
149            gtk_combo_box_append_text (GTK_COMBO_BOX (ro_cb),
150                                       (*opt_it).c_str ());
151            if (strcmp (i->second.currentValue.c_str (), (*opt_it).c_str ()) == 0)
152                gtk_combo_box_set_active (GTK_COMBO_BOX (ro_cb), idx);
153        }
154
155        g_signal_connect (G_OBJECT (ro_cb), "changed",
156                          G_CALLBACK (optionChanged), this);
157    }
158}
159
160static void backdrop_destructor (guchar *pixels, gpointer data)
161{
162    free (pixels);
163}
164
165bool ConfigDialog::createWindow ()
166{
167    // Create the dialog window
168    mDialog = gtk_dialog_new_with_buttons (
169        "OGRE Engine Setup", NULL, GTK_DIALOG_MODAL,
170        GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
171        GTK_STOCK_OK, GTK_RESPONSE_OK,
172        NULL);
173    gtk_window_set_position (GTK_WINDOW (mDialog), GTK_WIN_POS_CENTER);
174    gtk_window_set_resizable (GTK_WINDOW (mDialog), FALSE);
175    gtk_widget_show (GTK_DIALOG (mDialog)->vbox);
176
177    GtkWidget *vbox = gtk_vbox_new (FALSE, 5);
178    gtk_widget_show (vbox);
179    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (mDialog)->vbox), vbox, TRUE, TRUE, 0);
180
181    // Unpack the image and create a GtkImage object from it
182    try
183    {
184        static String imgType ("png");
185        Image img;
186        MemoryDataStream *imgStream;
187        DataStreamPtr imgStreamPtr;
188
189        imgStream = new MemoryDataStream (GLX_backdrop_data, sizeof (GLX_backdrop_data), false);
190        imgStreamPtr = DataStreamPtr (imgStream);
191        img.load (imgStreamPtr, imgType);
192
193        PixelBox src = img.getPixelBox (0, 0);
194
195        size_t width = img.getWidth ();
196        size_t height = img.getHeight ();
197
198        // Convert and copy image -- must be allocated with malloc
199        uint8 *data = (uint8 *)malloc (width * height * 4);
200        // Keep in mind that PixelBox does not free the data - this is ok
201        // as gtk takes pixel data ownership in gdk_pixbuf_new_from_data
202        PixelBox dst (src, PF_A8B8G8R8, data);
203
204        PixelUtil::bulkPixelConversion (src, dst);
205
206        GdkPixbuf *pixbuf = gdk_pixbuf_new_from_data (
207            (const guchar *)dst.data, GDK_COLORSPACE_RGB,
208            true, 8, width, height, width * 4,
209            backdrop_destructor, NULL);
210        GtkWidget *ogre_logo = gtk_image_new_from_pixbuf (pixbuf);
211
212        gdk_pixbuf_unref (pixbuf);
213
214        gtk_widget_show (ogre_logo);
215        gtk_box_pack_start (GTK_BOX (vbox), ogre_logo, FALSE, FALSE, 0);
216    }
217    catch (Exception &e)
218    {
219        // Could not decode image; never mind
220        LogManager::getSingleton().logMessage("WARNING: Failed to decode Ogre logo image");
221    }
222
223    GtkWidget *rs_hbox = gtk_hbox_new (FALSE, 0);
224    gtk_box_pack_start (GTK_BOX (vbox), rs_hbox, FALSE, TRUE, 0);
225
226    GtkWidget *rs_label = gtk_label_new ("Rendering subsystem:");
227    gtk_widget_show (rs_label);
228    gtk_box_pack_start (GTK_BOX (rs_hbox), rs_label, TRUE, TRUE, 5);
229    gtk_label_set_justify (GTK_LABEL (rs_label), GTK_JUSTIFY_RIGHT);
230    gtk_misc_set_alignment (GTK_MISC (rs_label), 1, 0.5);
231
232    GtkWidget *rs_cb = gtk_combo_box_new_text ();
233    gtk_widget_show (rs_cb);
234    gtk_box_pack_start (GTK_BOX (rs_hbox), rs_cb, TRUE, TRUE, 5);
235
236    g_signal_connect (G_OBJECT (rs_cb), "changed", G_CALLBACK (rendererChanged), this);
237
238    // Add all available renderers to the combo box
239    RenderSystemList *renderers = Root::getSingleton ().getAvailableRenderers ();
240    uint idx = 0, sel_renderer_idx = 0;
241    for (RenderSystemList::iterator r = renderers->begin(); r != renderers->end (); r++, idx++)
242    {
243        gtk_combo_box_append_text (GTK_COMBO_BOX (rs_cb), (*r)->getName ().c_str ());
244        if (mSelectedRenderSystem == *r)
245            sel_renderer_idx = idx;
246    }
247    // Don't show the renderer choice combobox if there's just one renderer
248    if (idx > 1)
249        gtk_widget_show (rs_hbox);
250 
251    GtkWidget *ro_frame = gtk_frame_new (NULL);
252    gtk_widget_show (ro_frame);
253    gtk_box_pack_start (GTK_BOX (vbox), ro_frame, TRUE, TRUE, 0);
254
255    GtkWidget *ro_label = gtk_label_new ("Renderer options:");
256    gtk_widget_show (ro_label);
257    gtk_frame_set_label_widget (GTK_FRAME (ro_frame), ro_label);
258    gtk_label_set_use_markup (GTK_LABEL (ro_label), TRUE);
259
260    mParamTable = gtk_table_new (0, 0, FALSE);
261    gtk_widget_show (mParamTable);
262    gtk_container_add (GTK_CONTAINER (ro_frame), mParamTable);
263
264    gtk_combo_box_set_active (GTK_COMBO_BOX (rs_cb), sel_renderer_idx);
265
266    return true;
267}
268
269bool ConfigDialog::display ()
270{
271    if (!__gtk_init_once ())
272        return false;
273
274    /* Select previously selected rendersystem */
275    mSelectedRenderSystem = Root::getSingleton ().getRenderSystem ();
276
277    /* Attempt to create the window */
278    if (!createWindow ())
279        OGRE_EXCEPT (Exception::ERR_INTERNAL_ERROR, "Could not create configuration dialog",
280                     "ConfigDialog::display");
281
282    // Modal loop
283    gint result = gtk_dialog_run (GTK_DIALOG (mDialog));
284    gtk_widget_destroy (mDialog);
285
286    // Wait for all gtk events to be consumed ...
287    while (gtk_events_pending ())
288        gtk_main_iteration_do (FALSE);
289
290    if (result != GTK_RESPONSE_OK)
291        return false;
292
293    Root::getSingleton ().setRenderSystem (mSelectedRenderSystem);
294
295    return true;
296}
297
298}
Note: See TracBrowser for help on using the repository browser.