GlobalOptionsDialog::GlobalOptionsDialog() : OptionsDialog(Common::ConfigManager::kApplicationDomain, "globaloptions") { // The tab widget TabWidget *tab = new TabWidget(this, "globaloptions_tabwidget"); tab->setHints(THEME_HINT_FIRST_DRAW | THEME_HINT_SAVE_BACKGROUND); // // 1) The graphics tab // tab->addTab("Graphics"); addGraphicControls(tab, "globaloptions_"); // // 2) The audio tab // tab->addTab("Audio"); addAudioControls(tab, "globaloptions_"); int volControlPos = g_gui.evaluator()->getVar("volumeControlsInAudio", true); if (volControlPos) addVolumeControls(tab, "globaloptions_"); addSubtitleControls(tab, "globaloptions_"); if (!volControlPos) { tab->addTab("Volume"); addVolumeControls(tab, "globaloptions_"); } // TODO: cd drive setting // // 3) The MIDI tab // tab->addTab("MIDI"); addMIDIControls(tab, "globaloptions_"); // // 4) The miscellaneous tab // tab->addTab("Paths"); #if !( defined(__DC__) || defined(__GP32__) ) // These two buttons have to be extra wide, or the text will be // truncated in the small version of the GUI. // Save game path new ButtonWidget(tab, "globaloptions_savebutton", "Save Path: ", kChooseSaveDirCmd, 0); _savePath = new StaticTextWidget(tab, "globaloptions_savepath", "/foo/bar"); new ButtonWidget(tab, "globaloptions_themebutton", "Theme Path:", kChooseThemeDirCmd, 0); _themePath = new StaticTextWidget(tab, "globaloptions_themepath", "None"); new ButtonWidget(tab, "globaloptions_extrabutton", "Extra Path:", kChooseExtraDirCmd, 0); _extraPath = new StaticTextWidget(tab, "globaloptions_extrapath", "None"); #endif #ifdef SMALL_SCREEN_DEVICE new ButtonWidget(tab, "globaloptions_keysbutton", "Keys", kChooseKeyMappingCmd, 0); #endif // TODO: joystick setting // Activate the first tab tab->setActiveTab(0); // Add OK & Cancel buttons new ButtonWidget(this, "globaloptions_cancel", "Cancel", kCloseCmd, 0); new ButtonWidget(this, "globaloptions_ok", "OK", kOKCmd, 0); #ifdef SMALL_SCREEN_DEVICE _keysDialog = new KeysDialog(); #endif }
ExampleApplication() : nanogui::Screen(Eigen::Vector2i(1024, 768), "NanoGUI Test") { using namespace nanogui; Window *window = new Window(this, "Button demo"); window->setPosition(Vector2i(15, 15)); window->setLayout(new GroupLayout()); /* No need to store a pointer, the data structure will be automatically freed when the parent window is deleted */ new Label(window, "Push buttons", "sans-bold"); Button *b = new Button(window, "Plain button"); b->setCallback([] { cout << "pushed!" << endl; }); /* Alternative construction notation using variadic template */ b = window->add<Button>("Styled", ENTYPO_ICON_ROCKET); b->setBackgroundColor(Color(0, 0, 255, 25)); b->setCallback([] { cout << "pushed!" << endl; }); new Label(window, "Toggle buttons", "sans-bold"); b = new Button(window, "Toggle me"); b->setFlags(Button::ToggleButton); b->setChangeCallback([](bool state) { cout << "Toggle button state: " << state << endl; }); new Label(window, "Radio buttons", "sans-bold"); b = new Button(window, "Radio button 1"); b->setFlags(Button::RadioButton); b = new Button(window, "Radio button 2"); b->setFlags(Button::RadioButton); new Label(window, "A tool palette", "sans-bold"); Widget *tools = new Widget(window); tools->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 6)); b = new ToolButton(tools, ENTYPO_ICON_CLOUD); b = new ToolButton(tools, ENTYPO_ICON_FF); b = new ToolButton(tools, ENTYPO_ICON_COMPASS); b = new ToolButton(tools, ENTYPO_ICON_INSTALL); new Label(window, "Popup buttons", "sans-bold"); PopupButton *popupBtn = new PopupButton(window, "Popup", ENTYPO_ICON_EXPORT); Popup *popup = popupBtn->popup(); popup->setLayout(new GroupLayout()); new Label(popup, "Arbitrary widgets can be placed here"); new CheckBox(popup, "A check box"); popupBtn = new PopupButton(popup, "Recursive popup", ENTYPO_ICON_FLASH); popup = popupBtn->popup(); popup->setLayout(new GroupLayout()); new CheckBox(popup, "Another check box"); window = new Window(this, "Basic widgets"); window->setPosition(Vector2i(200, 15)); window->setLayout(new GroupLayout()); new Label(window, "Message dialog", "sans-bold"); tools = new Widget(window); tools->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 6)); b = new Button(tools, "Info"); b->setCallback([&] { auto dlg = new MessageDialog(this, MessageDialog::Type::Information, "Title", "This is an information message"); dlg->setCallback([](int result) { cout << "Dialog result: " << result << endl; }); }); b = new Button(tools, "Warn"); b->setCallback([&] { auto dlg = new MessageDialog(this, MessageDialog::Type::Warning, "Title", "This is a warning message"); dlg->setCallback([](int result) { cout << "Dialog result: " << result << endl; }); }); b = new Button(tools, "Ask"); b->setCallback([&] { auto dlg = new MessageDialog(this, MessageDialog::Type::Warning, "Title", "This is a question message", "Yes", "No", true); dlg->setCallback([](int result) { cout << "Dialog result: " << result << endl; }); }); std::vector<std::pair<int, std::string>> icons = loadImageDirectory(mNVGContext, "icons"); new Label(window, "Image panel & scroll panel", "sans-bold"); PopupButton *imagePanelBtn = new PopupButton(window, "Image Panel"); imagePanelBtn->setIcon(ENTYPO_ICON_FOLDER); popup = imagePanelBtn->popup(); VScrollPanel *vscroll = new VScrollPanel(popup); ImagePanel *imgPanel = new ImagePanel(vscroll); imgPanel->setImages(icons); popup->setFixedSize(Vector2i(245, 150)); auto img_window = new Window(this, "Selected image"); img_window->setPosition(Vector2i(710, 15)); img_window->setLayout(new GroupLayout()); auto img = new ImageView(img_window); img->setPolicy(ImageView::SizePolicy::Expand); img->setFixedSize(Vector2i(275, 275)); img->setImage(icons[0].first); imgPanel->setCallback([&, img, imgPanel, imagePanelBtn](int i) { img->setImage(imgPanel->images()[i].first); cout << "Selected item " << i << endl; }); auto img_cb = new CheckBox(img_window, "Expand", [img](bool state) { if (state) img->setPolicy(ImageView::SizePolicy::Expand); else img->setPolicy(ImageView::SizePolicy::Fixed); }); img_cb->setChecked(true); new Label(window, "File dialog", "sans-bold"); tools = new Widget(window); tools->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 6)); b = new Button(tools, "Open"); b->setCallback([&] { cout << "File dialog result: " << file_dialog( { {"png", "Portable Network Graphics"}, {"txt", "Text file"} }, false) << endl; }); b = new Button(tools, "Save"); b->setCallback([&] { cout << "File dialog result: " << file_dialog( { {"png", "Portable Network Graphics"}, {"txt", "Text file"} }, true) << endl; }); new Label(window, "Combo box", "sans-bold"); new ComboBox(window, { "Combo box item 1", "Combo box item 2", "Combo box item 3"}); new Label(window, "Check box", "sans-bold"); CheckBox *cb = new CheckBox(window, "Flag 1", [](bool state) { cout << "Check box 1 state: " << state << endl; } ); cb->setChecked(true); cb = new CheckBox(window, "Flag 2", [](bool state) { cout << "Check box 2 state: " << state << endl; } ); new Label(window, "Progress bar", "sans-bold"); mProgress = new ProgressBar(window); new Label(window, "Slider and text box", "sans-bold"); Widget *panel = new Widget(window); panel->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 20)); Slider *slider = new Slider(panel); slider->setValue(0.5f); slider->setFixedWidth(80); TextBox *textBox = new TextBox(panel); textBox->setFixedSize(Vector2i(60, 25)); textBox->setValue("50"); textBox->setUnits("%"); slider->setCallback([textBox](float value) { textBox->setValue(std::to_string((int) (value * 100))); }); slider->setFinalCallback([&](float value) { cout << "Final slider value: " << (int) (value * 100) << endl; }); textBox->setFixedSize(Vector2i(60,25)); textBox->setFontSize(20); textBox->setAlignment(TextBox::Alignment::Right); window = new Window(this, "Misc. widgets"); window->setPosition(Vector2i(425,15)); window->setLayout(new GroupLayout()); TabWidget* tabWidget = window->add<TabWidget>(); Widget* layer = tabWidget->createTab("Color Wheel"); layer->setLayout(new GroupLayout()); // Use overloaded variadic add to fill the tab widget with Different tabs. layer->add<Label>("Color wheel widget", "sans-bold"); layer->add<ColorWheel>(); layer = tabWidget->createTab("Function Graph"); layer->setLayout(new GroupLayout()); layer->add<Label>("Function graph widget", "sans-bold"); Graph *graph = layer->add<Graph>("Some Function"); graph->setHeader("E = 2.35e-3"); graph->setFooter("Iteration 89"); VectorXf &func = graph->values(); func.resize(100); for (int i = 0; i < 100; ++i) func[i] = 0.5f * (0.5f * std::sin(i / 10.f) + 0.5f * std::cos(i / 23.f) + 1); // Dummy tab used to represent the last tab button. tabWidget->createTab("+"); // A simple counter. int counter = 1; tabWidget->setCallback([tabWidget, this, counter] (int index) mutable { if (index == (tabWidget->tabCount()-1)) { // When the "+" tab has been clicked, simply add a new tab. string tabName = "Dynamic " + to_string(counter); Widget* layerDyn = tabWidget->createTab(index, tabName); layerDyn->setLayout(new GroupLayout()); layerDyn->add<Label>("Function graph widget", "sans-bold"); Graph *graphDyn = layerDyn->add<Graph>("Dynamic function"); graphDyn->setHeader("E = 2.35e-3"); graphDyn->setFooter("Iteration " + to_string(index*counter)); VectorXf &funcDyn = graphDyn->values(); funcDyn.resize(100); for (int i = 0; i < 100; ++i) funcDyn[i] = 0.5f * std::abs((0.5f * std::sin(i / 10.f + counter) + 0.5f * std::cos(i / 23.f + 1 + counter))); ++counter; // We must invoke perform layout from the screen instance to keep everything in order. // This is essential when creating tabs dynamically. performLayout(); // Ensure that the newly added header is visible on screen tabWidget->ensureTabVisible(index); } }); tabWidget->setActiveTab(0); // A button to go back to the first tab and scroll the window. panel = window->add<Widget>(); panel->add<Label>("Jump to tab: "); panel->setLayout(new BoxLayout(Orientation::Horizontal, Alignment::Middle, 0, 6)); auto ib = panel->add<IntBox<int>>(); ib->setEditable(true); b = panel->add<Button>("", ENTYPO_ICON_FORWARD); b->setFixedSize(Vector2i(22, 22)); ib->setFixedHeight(22); b->setCallback([tabWidget, ib] { int value = ib->value(); if (value >= 0 && value < tabWidget->tabCount()) { tabWidget->setActiveTab(value); tabWidget->ensureTabVisible(value); } }); window = new Window(this, "Grid of small widgets"); window->setPosition(Vector2i(425, 300)); GridLayout *layout = new GridLayout(Orientation::Horizontal, 2, Alignment::Middle, 15, 5); layout->setColAlignment( { Alignment::Maximum, Alignment::Fill }); layout->setSpacing(0, 10); window->setLayout(layout); { new Label(window, "Floating point :", "sans-bold"); textBox = new TextBox(window); textBox->setEditable(true); textBox->setFixedSize(Vector2i(100, 20)); textBox->setValue("50"); textBox->setUnits("GiB"); textBox->setDefaultValue("0.0"); textBox->setFontSize(16); textBox->setFormat("[-]?[0-9]*\\.?[0-9]+"); } { new Label(window, "Positive integer :", "sans-bold"); auto intBox = new IntBox<int>(window); intBox->setEditable(true); intBox->setFixedSize(Vector2i(100, 20)); intBox->setValue(50); intBox->setUnits("Mhz"); intBox->setDefaultValue("0"); intBox->setFontSize(16); intBox->setFormat("[1-9][0-9]*"); intBox->setSpinnable(true); intBox->setMinValue(1); intBox->setValueIncrement(2); } { new Label(window, "Checkbox :", "sans-bold"); cb = new CheckBox(window, "Check me"); cb->setFontSize(16); cb->setChecked(true); } new Label(window, "Combo box :", "sans-bold"); ComboBox *cobo = new ComboBox(window, { "Item 1", "Item 2", "Item 3" }); cobo->setFontSize(16); cobo->setFixedSize(Vector2i(100,20)); new Label(window, "Color button :", "sans-bold"); popupBtn = new PopupButton(window, "", 0); popupBtn->setBackgroundColor(Color(255, 120, 0, 255)); popupBtn->setFontSize(16); popupBtn->setFixedSize(Vector2i(100, 20)); popup = popupBtn->popup(); popup->setLayout(new GroupLayout()); ColorWheel *colorwheel = new ColorWheel(popup); colorwheel->setColor(popupBtn->backgroundColor()); Button *colorBtn = new Button(popup, "Pick"); colorBtn->setFixedSize(Vector2i(100, 25)); Color c = colorwheel->color(); colorBtn->setBackgroundColor(c); colorwheel->setCallback([colorBtn](const Color &value) { colorBtn->setBackgroundColor(value); }); colorBtn->setChangeCallback([colorBtn, popupBtn](bool pushed) { if (pushed) { popupBtn->setBackgroundColor(colorBtn->backgroundColor()); popupBtn->setPushed(false); } }); performLayout(); /* All NanoGUI widgets are initialized at this point. Now create an OpenGL shader to draw the main window contents. NanoGUI comes with a simple Eigen-based wrapper around OpenGL 3, which eliminates most of the tedious and error-prone shader and buffer object management. */ mShader.init( /* An identifying name */ "a_simple_shader", /* Vertex shader */ "#version 330\n" "uniform mat4 modelViewProj;\n" "in vec3 position;\n" "void main() {\n" " gl_Position = modelViewProj * vec4(position, 1.0);\n" "}", /* Fragment shader */ "#version 330\n" "out vec4 color;\n" "uniform float intensity;\n" "void main() {\n" " color = vec4(vec3(intensity), 1.0);\n" "}" ); MatrixXu indices(3, 2); /* Draw 2 triangles */ indices.col(0) << 0, 1, 2; indices.col(1) << 2, 3, 0; MatrixXf positions(3, 4); positions.col(0) << -1, -1, 0; positions.col(1) << 1, -1, 0; positions.col(2) << 1, 1, 0; positions.col(3) << -1, 1, 0; mShader.bind(); mShader.uploadIndices(indices); mShader.uploadAttrib("position", positions); mShader.setUniform("intensity", 0.5f); }
EditGameDialog::EditGameDialog(const String &domain, const String &desc) : OptionsDialog(domain, "GameOptions") { // Retrieve all game specific options. const EnginePlugin *plugin = 0; // To allow for game domains without a gameid. // TODO: Is it intentional that this is still supported? String gameId(ConfMan.get("gameid", domain)); if (gameId.empty()) gameId = domain; // Retrieve the plugin, since we need to access the engine's MetaEngine // implementation. EngineMan.findGame(gameId, &plugin); if (plugin) { _engineOptions = (*plugin)->getExtraGuiOptions(domain); } else { warning("Plugin for target \"%s\" not found! Game specific settings might be missing", domain.c_str()); } // GAME: Path to game data (r/o), extra data (r/o), and save data (r/w) String gamePath(ConfMan.get("path", _domain)); String extraPath(ConfMan.get("extrapath", _domain)); String savePath(ConfMan.get("savepath", _domain)); // GAME: Determine the description string String description(ConfMan.get("description", domain)); if (description.empty() && !desc.empty()) { description = desc; } // GUI: Add tab widget TabWidget *tab = new TabWidget(this, "GameOptions.TabWidget"); // // 1) The game tab // tab->addTab(_("Game")); // GUI: Label & edit widget for the game ID if (g_system->getOverlayWidth() > 320) new StaticTextWidget(tab, "GameOptions_Game.Id", _("ID:"), _("Short game identifier used for referring to saved games and running the game from the command line")); else new StaticTextWidget(tab, "GameOptions_Game.Id", _c("ID:", "lowres"), _("Short game identifier used for referring to saved games and running the game from the command line")); _domainWidget = new DomainEditTextWidget(tab, "GameOptions_Game.Domain", _domain, _("Short game identifier used for referring to saved games and running the game from the command line")); // GUI: Label & edit widget for the description if (g_system->getOverlayWidth() > 320) new StaticTextWidget(tab, "GameOptions_Game.Name", _("Name:"), _("Full title of the game")); else new StaticTextWidget(tab, "GameOptions_Game.Name", _c("Name:", "lowres"), _("Full title of the game")); _descriptionWidget = new EditTextWidget(tab, "GameOptions_Game.Desc", description, _("Full title of the game")); // Language popup _langPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.LangPopupDesc", _("Language:"), _("Language of the game. This will not turn your Spanish game version into English")); _langPopUp = new PopUpWidget(tab, "GameOptions_Game.LangPopup", _("Language of the game. This will not turn your Spanish game version into English")); _langPopUp->appendEntry(_("<default>"), (uint32)Common::UNK_LANG); _langPopUp->appendEntry("", (uint32)Common::UNK_LANG); const Common::LanguageDescription *l = Common::g_languages; for (; l->code; ++l) { if (checkGameGUIOptionLanguage(l->id, _guioptionsString)) _langPopUp->appendEntry(l->description, l->id); } // Platform popup if (g_system->getOverlayWidth() > 320) _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _("Platform:"), _("Platform the game was originally designed for")); else _platformPopUpDesc = new StaticTextWidget(tab, "GameOptions_Game.PlatformPopupDesc", _c("Platform:", "lowres"), _("Platform the game was originally designed for")); _platformPopUp = new PopUpWidget(tab, "GameOptions_Game.PlatformPopup", _("Platform the game was originally designed for")); _platformPopUp->appendEntry(_("<default>")); _platformPopUp->appendEntry(""); const Common::PlatformDescription *p = Common::g_platforms; for (; p->code; ++p) { _platformPopUp->appendEntry(p->description, p->id); } // // 2) The engine tab (shown only if there are custom engine options) // if (_engineOptions.size() > 0) { tab->addTab(_("Engine")); addEngineControls(tab, "GameOptions_Engine.", _engineOptions); } // // 3) The graphics tab // _graphicsTabId = tab->addTab(g_system->getOverlayWidth() > 320 ? _("Graphics") : _("GFX")); if (g_system->getOverlayWidth() > 320) _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _("Override global graphic settings"), 0, kCmdGlobalGraphicsOverride); else _globalGraphicsOverride = new CheckboxWidget(tab, "GameOptions_Graphics.EnableTabCheckbox", _c("Override global graphic settings", "lowres"), 0, kCmdGlobalGraphicsOverride); addGraphicControls(tab, "GameOptions_Graphics."); // // 4) The audio tab // tab->addTab(_("Audio")); if (g_system->getOverlayWidth() > 320) _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _("Override global audio settings"), 0, kCmdGlobalAudioOverride); else _globalAudioOverride = new CheckboxWidget(tab, "GameOptions_Audio.EnableTabCheckbox", _c("Override global audio settings", "lowres"), 0, kCmdGlobalAudioOverride); addAudioControls(tab, "GameOptions_Audio."); addSubtitleControls(tab, "GameOptions_Audio."); // // 5) The volume tab // if (g_system->getOverlayWidth() > 320) tab->addTab(_("Volume")); else tab->addTab(_c("Volume", "lowres")); if (g_system->getOverlayWidth() > 320) _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _("Override global volume settings"), 0, kCmdGlobalVolumeOverride); else _globalVolumeOverride = new CheckboxWidget(tab, "GameOptions_Volume.EnableTabCheckbox", _c("Override global volume settings", "lowres"), 0, kCmdGlobalVolumeOverride); addVolumeControls(tab, "GameOptions_Volume."); // // 6) The MIDI tab // _globalMIDIOverride = NULL; if (!_guioptions.contains(GUIO_NOMIDI)) { tab->addTab(_("MIDI")); if (g_system->getOverlayWidth() > 320) _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _("Override global MIDI settings"), 0, kCmdGlobalMIDIOverride); else _globalMIDIOverride = new CheckboxWidget(tab, "GameOptions_MIDI.EnableTabCheckbox", _c("Override global MIDI settings", "lowres"), 0, kCmdGlobalMIDIOverride); addMIDIControls(tab, "GameOptions_MIDI."); } // // 7) The MT-32 tab // _globalMT32Override = NULL; if (!_guioptions.contains(GUIO_NOMIDI)) { tab->addTab(_("MT-32")); if (g_system->getOverlayWidth() > 320) _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _("Override global MT-32 settings"), 0, kCmdGlobalMT32Override); else _globalMT32Override = new CheckboxWidget(tab, "GameOptions_MT32.EnableTabCheckbox", _c("Override global MT-32 settings", "lowres"), 0, kCmdGlobalMT32Override); addMT32Controls(tab, "GameOptions_MT32."); } // // 8) The Paths tab // if (g_system->getOverlayWidth() > 320) tab->addTab(_("Paths")); else tab->addTab(_c("Paths", "lowres")); // These buttons have to be extra wide, or the text will be truncated // in the small version of the GUI. // GUI: Button + Label for the game path if (g_system->getOverlayWidth() > 320) new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _("Game Path:"), 0, kCmdGameBrowser); else new ButtonWidget(tab, "GameOptions_Paths.Gamepath", _c("Game Path:", "lowres"), 0, kCmdGameBrowser); _gamePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.GamepathText", gamePath); // GUI: Button + Label for the additional path if (g_system->getOverlayWidth() > 320) new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _("Extra Path:"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser); else new ButtonWidget(tab, "GameOptions_Paths.Extrapath", _c("Extra Path:", "lowres"), _("Specifies path to additional data used by the game"), kCmdExtraBrowser); _extraPathWidget = new StaticTextWidget(tab, "GameOptions_Paths.ExtrapathText", extraPath, _("Specifies path to additional data used by the game")); _extraPathClearButton = addClearButton(tab, "GameOptions_Paths.ExtraPathClearButton", kCmdExtraPathClear); // GUI: Button + Label for the save path if (g_system->getOverlayWidth() > 320) new ButtonWidget(tab, "GameOptions_Paths.Savepath", _("Save Path:"), _("Specifies where your saved games are put"), kCmdSaveBrowser); else new ButtonWidget(tab, "GameOptions_Paths.Savepath", _c("Save Path:", "lowres"), _("Specifies where your saved games are put"), kCmdSaveBrowser); _savePathWidget = new StaticTextWidget(tab, "GameOptions_Paths.SavepathText", savePath, _("Specifies where your saved games are put")); _savePathClearButton = addClearButton(tab, "GameOptions_Paths.SavePathClearButton", kCmdSavePathClear); // Activate the first tab tab->setActiveTab(0); _tabWidget = tab; // Add OK & Cancel buttons new ButtonWidget(this, "GameOptions.Cancel", _("Cancel"), 0, kCloseCmd); new ButtonWidget(this, "GameOptions.Ok", _("OK"), 0, kOKCmd); }