Update to v080r07 release.

byuu says:

- fixed a long-standing crash: when you have a device index above the
  range permitted by another port, the app would crash (eg Controller
  Port 2 -> Mouse, then switch to Hotkeys)
- Qt bug workaround: have to use currentItemChanged signal instead of
  itemSelectionChanged signal for QTreeWidget, otherwise scrolling with
  mouse gives you the previous item with currentItem() ...
- added support for toggling the Xfce compositor
- added support for detecting if the compositor is enabled in the first
  place on Windows, so that it won't get turned on when you had it off
  permanently
- added advanced setting to toggle behavior (never disable, disable only
  in fullscreen mode, disable whenever emulator is open)
- worked around GTK+ ../... button height issue
- worked around Windows slider position issue when attaching to a new
  window (need to research this one more)
- fixed up input settings window more: closing window ends assignment,
  custom mapping buttons hidden by default

Some of those bugs have been there since the phoenix port began, good
times.
This commit is contained in:
Tim Allen 2011-08-08 22:02:51 +10:00
parent 564e38ea9f
commit e88ab60663
26 changed files with 237 additions and 402 deletions

View File

@ -5,8 +5,7 @@ profile := accuracy
ui := ui
# phoenix := gtk
options :=
# debugger
# options += debugger
# compiler
c := $(compiler) -std=gnu99

View File

@ -10,8 +10,8 @@
namespace nall {
struct bmp {
static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height);
static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, bool alpha = false);
inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height);
inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, bool alpha = false);
};
bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) {

79
bsnes/nall/compositor.hpp Executable file
View File

@ -0,0 +1,79 @@
#ifndef NALL_COMPOSITOR_HPP
#define NALL_COMPOSITOR_HPP
#include <nall/detect.hpp>
namespace nall {
struct compositor {
inline static bool enabled();
inline static bool enable(bool status);
};
#if defined(PLATFORM_X)
bool compositor::enabled() {
FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r");
if(fp == 0) return false;
char buffer[512];
if(fgets(buffer, sizeof buffer, fp) == 0) return false;
if(!memcmp(buffer, "true", 4)) return true;
return false;
}
bool compositor::enable(bool status) {
FILE *fp;
if(status) {
fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r");
} else {
fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'false'", "r");
}
if(fp == 0) return false;
pclose(fp);
return true;
}
#elif defined(PLATFORM_WIN)
bool compositor::enabled() {
HMODULE module = GetModuleHandleW(L"dwmapi");
if(module == 0) module = LoadLibraryW(L"dwmapi");
if(module == 0) return false;
auto pDwmIsCompositionEnabled = (HRESULT (WINAPI*)(BOOL*))GetProcAddress(module, "DwmIsCompositionEnabled");
if(pDwmIsCompositionEnabled == 0) return false;
BOOL result;
if(pDwmIsCompositionEnabled(&result) != S_OK) return false;
return result;
}
bool compositor::enable(bool status) {
HMODULE module = GetModuleHandleW(L"dwmapi");
if(module == 0) module = LoadLibraryW(L"dwmapi");
if(module == 0) return false;
auto pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition");
if(pDwmEnableComposition == 0) return false;
if(pDwmEnableComposition(status) != S_OK) return false;
return true;
}
#else
bool compositor::enabled() {
return false;
}
bool compositor::enable(bool) {
return false;
}
#endif
}
#endif

View File

@ -1,34 +0,0 @@
#ifndef NALL_WINDOWS_COMPOSITOR_HPP
#define NALL_WINDOWS_COMPOSITOR_HPP
#ifdef _WIN32
namespace nall {
struct compositor {
static bool enable(bool status);
static void initialize();
private:
static HMODULE module;
static HRESULT (WINAPI *pDwmEnableComposition)(UINT);
};
HMODULE compositor::module = 0;
HRESULT (WINAPI *compositor::pDwmEnableComposition)(UINT) = 0;
bool compositor::enable(bool enable) {
initialize();
if(pDwmEnableComposition) return pDwmEnableComposition(enable) == S_OK;
return false;
}
void compositor::initialize() {
module = LoadLibraryA("dwmapi");
if(module) {
pDwmEnableComposition = (HRESULT (WINAPI*)(UINT))GetProcAddress(module, "DwmEnableComposition");
}
}
}
#endif
#endif

View File

@ -1,7 +1,7 @@
/****************************************************************************
** Meta object code from reading C++ file 'qt.moc.hpp'
**
** Created: Sat Aug 6 18:13:30 2011
** Created: Mon Aug 8 00:07:23 2011
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
**
** WARNING! All changes made in this file will be lost!

View File

@ -100,7 +100,7 @@ void pListView::constructor() {
qtListView->setRootIsDecorated(false);
connect(qtListView, SIGNAL(itemActivated(QTreeWidgetItem*, int)), SLOT(onActivate()));
connect(qtListView, SIGNAL(itemSelectionChanged()), SLOT(onChange()));
connect(qtListView, SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), SLOT(onChange()));
connect(qtListView, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(onTick(QTreeWidgetItem*)));
}

View File

@ -1,7 +1,7 @@
namespace SNES {
namespace Info {
static const char Name[] = "bsnes";
static const char Version[] = "080.06";
static const char Version[] = "080.07";
static const unsigned SerializerVersion = 21;
}
}

View File

@ -1,6 +1,7 @@
#include <snes/snes.hpp>
#include <nall/base64.hpp>
#include <nall/compositor.hpp>
#include <nall/config.hpp>
#include <nall/directory.hpp>
#include <nall/filemap.hpp>
@ -41,6 +42,7 @@ struct Application {
Font proportionalFontBold;
Font monospaceFont;
Font titleFont;
bool compositorActive;
bool pause;
bool quit;

View File

@ -45,6 +45,7 @@ void Configuration::create() {
attach(settings.startFullScreen = false, "settings.startFullScreen", "Start in full screen mode for front-end use");
attach(settings.focusPolicy = 0, "settings.focusPolicy");
attach(settings.compositorPolicy = 1, "settings.compositorPolicy");
attach(controller.port1 = 1, "controller.port1");
attach(controller.port2 = 1, "controller.port2");

View File

@ -32,6 +32,7 @@ struct Configuration : public configuration {
struct Settings {
bool startFullScreen;
unsigned focusPolicy;
unsigned compositorPolicy;
} settings;
struct Controller {

View File

@ -3,7 +3,9 @@ FileBrowser fileBrowser;
void FileBrowser::create() {
application.addWindow(this, "FileBrowser", "160,160");
browseButton.setFont(application.proportionalFont);
browseButton.setText("...");
upButton.setFont(application.proportionalFont);
upButton.setText("..");
const unsigned sq = browseButton.minimumGeometry().height;

View File

@ -252,108 +252,111 @@ void MainWindow::create() {
setMenuVisible(true);
setStatusVisible(true);
systemLoadCartridge.onTick = []() {
systemLoadCartridge.onTick = [] {
fileBrowser.fileOpen(FileBrowser::Mode::Cartridge, [](string filename) {
cartridge.loadNormal(filename);
});
};
systemLoadCartridgeBsxSlotted.onTick = []() { singleSlotLoader.loadCartridgeBsxSlotted(); };
systemLoadCartridgeBsx.onTick = []() { singleSlotLoader.loadCartridgeBsx(); };
systemLoadCartridgeSufamiTurbo.onTick = []() { doubleSlotLoader.loadCartridgeSufamiTurbo(); };
systemLoadCartridgeSuperGameBoy.onTick = []() { singleSlotLoader.loadCartridgeSuperGameBoy(); };
systemLoadCartridgeBsxSlotted.onTick = [] { singleSlotLoader.loadCartridgeBsxSlotted(); };
systemLoadCartridgeBsx.onTick = [] { singleSlotLoader.loadCartridgeBsx(); };
systemLoadCartridgeSufamiTurbo.onTick = [] { doubleSlotLoader.loadCartridgeSufamiTurbo(); };
systemLoadCartridgeSuperGameBoy.onTick = [] { singleSlotLoader.loadCartridgeSuperGameBoy(); };
systemPower.onTick = []() {
systemPower.onTick = [] {
SNES::system.power();
utility.showMessage("System was power cycled");
};
systemReset.onTick = []() {
systemReset.onTick = [] {
SNES::system.reset();
utility.showMessage("System was reset");
};
systemPort1None.onTick = []() { config.controller.port1 = 0; utility.setControllers(); };
systemPort1Gamepad.onTick = []() { config.controller.port1 = 1; utility.setControllers(); };
systemPort1Multitap.onTick = []() { config.controller.port1 = 2; utility.setControllers(); };
systemPort1Mouse.onTick = []() { config.controller.port1 = 3; utility.setControllers(); };
systemPort1None.onTick = [] { config.controller.port1 = 0; utility.setControllers(); };
systemPort1Gamepad.onTick = [] { config.controller.port1 = 1; utility.setControllers(); };
systemPort1Multitap.onTick = [] { config.controller.port1 = 2; utility.setControllers(); };
systemPort1Mouse.onTick = [] { config.controller.port1 = 3; utility.setControllers(); };
systemPort2None.onTick = []() { config.controller.port2 = 0; utility.setControllers(); };
systemPort2Gamepad.onTick = []() { config.controller.port2 = 1; utility.setControllers(); };
systemPort2Multitap.onTick = []() { config.controller.port2 = 2; utility.setControllers(); };
systemPort2Mouse.onTick = []() { config.controller.port2 = 3; utility.setControllers(); };
systemPort2SuperScope.onTick = []() { config.controller.port2 = 4; utility.setControllers(); };
systemPort2Justifier.onTick = []() { config.controller.port2 = 5; utility.setControllers(); };
systemPort2Justifiers.onTick = []() { config.controller.port2 = 6; utility.setControllers(); };
systemPort2Serial.onTick = []() { config.controller.port2 = 7; utility.setControllers(); };
systemPort2None.onTick = [] { config.controller.port2 = 0; utility.setControllers(); };
systemPort2Gamepad.onTick = [] { config.controller.port2 = 1; utility.setControllers(); };
systemPort2Multitap.onTick = [] { config.controller.port2 = 2; utility.setControllers(); };
systemPort2Mouse.onTick = [] { config.controller.port2 = 3; utility.setControllers(); };
systemPort2SuperScope.onTick = [] { config.controller.port2 = 4; utility.setControllers(); };
systemPort2Justifier.onTick = [] { config.controller.port2 = 5; utility.setControllers(); };
systemPort2Justifiers.onTick = [] { config.controller.port2 = 6; utility.setControllers(); };
systemPort2Serial.onTick = [] { config.controller.port2 = 7; utility.setControllers(); };
settingsVideoMode1x.onTick = []() { utility.setScale(1); };
settingsVideoMode2x.onTick = []() { utility.setScale(2); };
settingsVideoMode3x.onTick = []() { utility.setScale(3); };
settingsVideoMode4x.onTick = []() { utility.setScale(4); };
settingsVideoMode5x.onTick = []() { utility.setScale(5); };
settingsVideoMode1x.onTick = [] { utility.setScale(1); };
settingsVideoMode2x.onTick = [] { utility.setScale(2); };
settingsVideoMode3x.onTick = [] { utility.setScale(3); };
settingsVideoMode4x.onTick = [] { utility.setScale(4); };
settingsVideoMode5x.onTick = [] { utility.setScale(5); };
settingsVideoModeAspectRatioCorrection.onTick = []() {
settingsVideoModeAspectRatioCorrection.onTick = [] {
config.video.aspectRatioCorrection = mainWindow.settingsVideoModeAspectRatioCorrection.checked();
utility.setScale();
};
settingsVideoModeSmoothVideo.onTick = []() {
settingsVideoModeSmoothVideo.onTick = [] {
config.video.smooth = mainWindow.settingsVideoModeSmoothVideo.checked();
video.set(Video::Filter, (unsigned)config.video.smooth);
};
settingsVideoModeNTSC.onTick = []() { config.video.region = 0; utility.setScale(); };
settingsVideoModePAL.onTick = []() { config.video.region = 1; utility.setScale(); };
settingsVideoModeNTSC.onTick = [] { config.video.region = 0; utility.setScale(); };
settingsVideoModePAL.onTick = [] { config.video.region = 1; utility.setScale(); };
settingsVideoFilterNone.onTick = []() {
settingsVideoFilterNone.onTick = [] {
config.video.filter = "";
utility.setFilter();
};
settingsVideoShaderNone.onTick = []() {
settingsVideoShaderNone.onTick = [] {
config.video.shader = "";
utility.setShader();
};
settingsSynchronizeVideo.onTick = []() {
settingsSynchronizeVideo.onTick = [] {
config.video.synchronize = mainWindow.settingsSynchronizeVideo.checked();
video.set(Video::Synchronize, config.video.synchronize);
};
settingsSynchronizeAudio.onTick = []() {
settingsSynchronizeAudio.onTick = [] {
config.audio.synchronize = mainWindow.settingsSynchronizeAudio.checked();
audio.set(Audio::Synchronize, config.audio.synchronize);
};
settingsMuteAudio.onTick = []() { config.audio.mute = mainWindow.settingsMuteAudio.checked(); };
settingsMuteAudio.onTick = [] { config.audio.mute = mainWindow.settingsMuteAudio.checked(); };
settingsConfiguration.onTick = []() { settingsWindow.setVisible(); };
settingsConfiguration.onTick = [] {
settingsWindow.setVisible();
settingsWindow.panel.setFocused();
};
toolsStateSave1.onTick = []() { utility.saveState(1); };
toolsStateSave2.onTick = []() { utility.saveState(2); };
toolsStateSave3.onTick = []() { utility.saveState(3); };
toolsStateSave4.onTick = []() { utility.saveState(4); };
toolsStateSave5.onTick = []() { utility.saveState(5); };
toolsStateSave1.onTick = [] { utility.saveState(1); };
toolsStateSave2.onTick = [] { utility.saveState(2); };
toolsStateSave3.onTick = [] { utility.saveState(3); };
toolsStateSave4.onTick = [] { utility.saveState(4); };
toolsStateSave5.onTick = [] { utility.saveState(5); };
toolsStateLoad1.onTick = []() { utility.loadState(1); };
toolsStateLoad2.onTick = []() { utility.loadState(2); };
toolsStateLoad3.onTick = []() { utility.loadState(3); };
toolsStateLoad4.onTick = []() { utility.loadState(4); };
toolsStateLoad5.onTick = []() { utility.loadState(5); };
toolsStateLoad1.onTick = [] { utility.loadState(1); };
toolsStateLoad2.onTick = [] { utility.loadState(2); };
toolsStateLoad3.onTick = [] { utility.loadState(3); };
toolsStateLoad4.onTick = [] { utility.loadState(4); };
toolsStateLoad5.onTick = [] { utility.loadState(5); };
toolsCheatEditor.onTick = []() { cheatEditor.setVisible(); };
toolsStateManager.onTick = []() { stateManager.setVisible(); };
toolsCheatEditor.onTick = [] { cheatEditor.setVisible(); };
toolsStateManager.onTick = [] { stateManager.setVisible(); };
#if defined(DEBUGGER)
toolsDebugger.onTick = []() { debugger.setVisible(); };
toolsDebugger.onTick = [] { debugger.setVisible(); };
#endif
helpAbout.onTick = []() {
helpAbout.onTick = [] {
aboutWindow.show();
};
onClose = []() {
onClose = [] {
application.quit = true;
};

View File

@ -5,8 +5,10 @@ void SingleSlotLoader::create() {
application.addWindow(this, "SingleSlotLoader", "160,160");
baseLabel.setText("Base:");
baseBrowse.setFont(application.proportionalFont);
baseBrowse.setText("...");
slotLabel.setText("Slot:");
slotBrowse.setFont(application.proportionalFont);
slotBrowse.setText("...");
okButton.setText("Ok");
@ -98,10 +100,13 @@ void DoubleSlotLoader::create() {
application.addWindow(this, "DoubleSlotLoader", "160,160");
baseLabel.setText("Base:");
baseBrowse.setFont(application.proportionalFont);
baseBrowse.setText("...");
slotALabel.setText("Slot A:");
slotABrowse.setFont(application.proportionalFont);
slotABrowse.setText("...");
slotBLabel.setText("Slot B:");
slotBBrowse.setFont(application.proportionalFont);
slotBBrowse.setText("...");
okButton.setText("Ok");

View File

@ -7,6 +7,9 @@ void Application::main(int argc, char **argv) {
#if defined(PLATFORM_WIN)
utf8_args(argc, argv);
#endif
compositorActive = compositor::enabled();
config.create();
inputMapper.create();
@ -31,8 +34,8 @@ void Application::main(int argc, char **argv) {
monospaceFont.setFamily("Lucida Console");
monospaceFont.setSize(8);
titleFont.setFamily("Tahoma");
titleFont.setSize(14);
titleFont.setFamily("Segoe Print");
titleFont.setSize(16);
titleFont.setBold();
#else
proportionalFont.setFamily("Sans");
@ -46,8 +49,9 @@ void Application::main(int argc, char **argv) {
monospaceFont.setSize(8);
titleFont.setFamily("Sans");
titleFont.setSize(14);
titleFont.setSize(16);
titleFont.setBold();
titleFont.setItalic();
#endif
SNES::system.init(&interface);
@ -151,6 +155,8 @@ void Application::main(int argc, char **argv) {
video.term();
audio.term();
input.term();
if(compositorActive) compositor::enable(true);
}
void Application::addWindow(TopLevelWindow *window, const string &name, const string &position) {

View File

@ -1,230 +0,0 @@
InputSettings inputSettings;
static InputMapper::AbstractInput *activeInput = 0;
void InputSettings::create() {
setTitle("Input Settings");
application.addWindow(this, "InputSettings", "160,160");
setStatusFont(application.proportionalFontBold);
setStatusVisible();
activeInput = 0;
activeMouse = 0;
portLabel.setText("Port:");
portBox.append(inputMapper.port1.name);
portBox.append(inputMapper.port2.name);
portBox.append(inputMapper.hotkeys.name);
deviceLabel.setText("Device:");
mappingList.setHeaderText("Name", "Mapping");
mappingList.setHeaderVisible(true);
clearButton.setText("Clear");
mouseXaxis.setText("Mouse X-axis");
mouseYaxis.setText("Mouse Y-axis");
mouseLeft.setText("Mouse Left");
mouseMiddle.setText("Mouse Middle");
mouseRight.setText("Mouse Right");
layout.setMargin(5);
selectionLayout.append(portLabel, 0, 0, 5);
selectionLayout.append(portBox, ~0, 0, 5);
selectionLayout.append(deviceLabel, 0, 0, 5);
selectionLayout.append(deviceBox, ~0, 0 );
layout.append(selectionLayout, 5);
layout.append(mappingList, ~0, ~0, 5);
mapLayout.append(spacer, ~0, 0 );
mapLayout.append(clearButton, 80, 0 );
layout.append(mapLayout);
axisLayout.setMargin(5);
axisLayout.append(axisSpacer, ~0, ~0 );
axisControlLayout.append(mouseXaxis, 100, 0, 5);
axisControlLayout.append(mouseYaxis, 100, 0, 5);
axisLayout.append(axisControlLayout);
buttonLayout.setMargin(5);
buttonLayout.append(buttonSpacer, ~0, ~0 );
buttonControlLayout.append(mouseLeft, 100, 0, 5);
buttonControlLayout.append(mouseMiddle, 100, 0, 5);
buttonControlLayout.append(mouseRight, 100, 0, 5);
buttonLayout.append(buttonControlLayout);
append(layout);
append(axisLayout);
append(buttonLayout);
setGeometry({ 0, 0, 480, layout.minimumGeometry().height + 250 });
axisLayout.setVisible(false);
buttonLayout.setVisible(false);
portChanged();
portBox.onChange = { &InputSettings::portChanged, this };
deviceBox.onChange = { &InputSettings::deviceChanged, this };
mappingList.onActivate = { &InputSettings::assignInput, this };
mouseXaxis.onTick = []() { inputSettings.setMapping(Scancode::encode(mouse(inputSettings.activeMouse)[Mouse::Xaxis])); };
mouseYaxis.onTick = []() { inputSettings.setMapping(Scancode::encode(mouse(inputSettings.activeMouse)[Mouse::Yaxis])); };
mouseLeft.onTick = []() { inputSettings.setMapping(Scancode::encode(mouse(inputSettings.activeMouse)[Mouse::Button0])); };
mouseMiddle.onTick = []() { inputSettings.setMapping(Scancode::encode(mouse(inputSettings.activeMouse)[Mouse::Button1])); };
mouseRight.onTick = []() { inputSettings.setMapping(Scancode::encode(mouse(inputSettings.activeMouse)[Mouse::Button2])); };
clearButton.onTick = { &InputSettings::clearInput, this };
onClose = []() { inputSettings.endAssignment(); };
}
void InputSettings::portChanged() {
deviceBox.reset();
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
/*portBox.selection() == 2*/ (InputMapper::ControllerPort&)inputMapper.hotkeys
);
for(unsigned i = 0; i < port.size(); i++) deviceBox.append(port[i]->name);
deviceChanged();
}
void InputSettings::deviceChanged() {
mappingList.reset();
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
/*portBox.selection() == 2*/ (InputMapper::ControllerPort&)inputMapper.hotkeys
);
InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()];
for(unsigned i = 0; i < controller.size(); i++) {
string mapping = controller[i]->mapping;
if(mapping == "") mapping = "None";
mappingList.append(controller[i]->name, mapping);
}
mappingList.autoSizeColumns();
}
void InputSettings::mappingChanged() {
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
/*portBox.selection() == 2*/ (InputMapper::ControllerPort&)inputMapper.hotkeys
);
InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()];
for(unsigned i = 0; i < controller.size(); i++) {
string mapping = controller[i]->mapping;
if(mapping == "") mapping = "None";
mappingList.modify(i, controller[i]->name, mapping);
}
mappingList.autoSizeColumns();
}
void InputSettings::assignInput() {
if(mappingList.selected() == false) return;
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
/*portBox.selection() == 2*/ (InputMapper::ControllerPort&)inputMapper.hotkeys
);
InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()];
portBox.setEnabled(false);
deviceBox.setEnabled(false);
mappingList.setEnabled(false);
inputMapper.poll(); //flush any pending keypresses
activeInput = controller[mappingList.selection()];
setStatusText({ "Set assignment for [", activeInput->name, "] ..." });
if(dynamic_cast<InputMapper::AnalogInput*>(activeInput)) {
axisLayout.setVisible(true);
buttonLayout.setVisible(false);
} else {
axisLayout.setVisible(false);
buttonLayout.setVisible(true);
}
}
void InputSettings::clearInput() {
if(mappingList.selected() == false) return;
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
/*portBox.selection() == 2*/ (InputMapper::ControllerPort&)inputMapper.hotkeys
);
InputMapper::Controller &controller = (InputMapper::Controller&)*port[deviceBox.selection()];
controller[mappingList.selection()]->mapping = "";
inputMapper.bind();
endAssignment();
}
void InputSettings::setMapping(const string &mapping) {
activeInput->mapping = mapping;
inputMapper.bind();
endAssignment();
}
void InputSettings::endAssignment() {
activeInput = 0;
portBox.setEnabled(true);
deviceBox.setEnabled(true);
mappingList.setEnabled(true);
setStatusText("");
axisLayout.setVisible(false);
buttonLayout.setVisible(false);
mappingChanged();
mappingList.setFocused();
}
void InputSettings::inputEvent(uint16_t scancode, int16_t value) {
if(activeInput == 0) return; //not remapping any keys right now?
string mapping = Scancode::encode(scancode);
if(auto position = strpos(mapping, "::Escape")) return setMapping("");
if(dynamic_cast<InputMapper::AnalogInput*>(activeInput)) {
} else if(dynamic_cast<InputMapper::DigitalInput*>(activeInput)) {
if(Keyboard::isAnyKey(scancode) && value) {
setMapping(mapping);
} else if(Mouse::isAnyButton(scancode) && value) {
activeMouse = Mouse::numberDecode(scancode);
} else if(Joypad::isAnyHat(scancode) && value) {
if(value == Joypad::HatUp) setMapping({ mapping, ".Up" });
else if(value == Joypad::HatDown) setMapping({ mapping, ".Down" });
else if(value == Joypad::HatLeft) setMapping({ mapping, ".Left" });
else if(value == Joypad::HatRight) setMapping({ mapping, ".Right" });
} else if(Joypad::isAnyAxis(scancode)) {
if(joypadsCalibrated == false) return calibrateJoypads();
unsigned joypadNumber = Joypad::numberDecode(scancode);
unsigned axisNumber = Joypad::axisDecode(scancode);
int16_t calibration = joypadCalibration[joypadNumber][axisNumber];
if(calibration > -12288 && calibration < +12288 && value < -24576) setMapping({ mapping, ".Lo" });
else if(calibration > -12288 && calibration < +12288 && value > +24576) setMapping({ mapping, ".Hi" });
else if(calibration <= -12288 && value >= +12288) setMapping({ mapping, ".Hi" });
else if(calibration >= +12288 && value <= -12288) setMapping({ mapping, ".Lo" });
} else if(Joypad::isAnyButton(scancode) && value) {
setMapping(mapping);
}
}
}
void InputSettings::calibrateJoypads() {
if(joypadsCalibrating == true) return;
joypadsCalibrating = true;
MessageWindow::information(*this,
"Analog joypads must be calibrated prior to use.\n\n"
"Please move all analog axes, and press all analog buttons.\n"
"Please do this for every controller you wish to use.\n"
"Once finished, please let go of all axes and buttons, and press OK."
);
inputMapper.poll();
for(unsigned j = 0; j < Joypad::Count &&j<2; j++) {
for(unsigned a = 0; a < Joypad::Axes; a++) {
joypadCalibration[j][a] = inputMapper.value(joypad(j).axis(a));
}
}
joypadsCalibrating = false;
joypadsCalibrated = true;
}
InputSettings::InputSettings() {
joypadsCalibrated = false;
joypadsCalibrating = false;
}

View File

@ -1,46 +0,0 @@
struct InputSettings : TopLevelWindow {
VerticalLayout layout;
HorizontalLayout selectionLayout;
Label portLabel;
ComboBox portBox;
Label deviceLabel;
ComboBox deviceBox;
ListView mappingList;
HorizontalLayout mapLayout;
Label spacer;
Button clearButton;
VerticalLayout axisLayout;
Widget axisSpacer;
HorizontalLayout axisControlLayout;
Button mouseXaxis;
Button mouseYaxis;
VerticalLayout buttonLayout;
Widget buttonSpacer;
HorizontalLayout buttonControlLayout;
Button mouseLeft;
Button mouseMiddle;
Button mouseRight;
void inputEvent(uint16_t scancode, int16_t value);
void calibrateJoypads();
void create();
InputSettings();
private:
bool joypadsCalibrated;
bool joypadsCalibrating;
int16_t joypadCalibration[Joypad::Count][Joypad::Axes];
unsigned activeMouse;
void portChanged();
void deviceChanged();
void mappingChanged();
void setMapping(const string &mapping);
void assignInput();
void clearInput();
void endAssignment();
};
extern InputSettings inputSettings;

View File

@ -1 +0,0 @@
#include "../base.hpp"

View File

@ -9,7 +9,7 @@ void AdvancedSettings::create() {
videoDriverLabel.setText("Video:");
audioDriverLabel.setText("Audio:");
inputDriverLabel.setText("Input:");
focusPolicyLabel.setText("Focus Policy:");
focusPolicyLabel.setText("When emulation window lacks focus:");
focusPolicyLabel.setFont(application.proportionalFontBold);
focusPolicyPause.setText("Pause emulator");
focusPolicyIgnore.setText("Ignore input");
@ -18,6 +18,16 @@ void AdvancedSettings::create() {
if(config.settings.focusPolicy == 0) focusPolicyPause.setChecked();
if(config.settings.focusPolicy == 1) focusPolicyIgnore.setChecked();
if(config.settings.focusPolicy == 2) focusPolicyAllow.setChecked();
compositorPolicyLabel.setText("Disable Compositor:");
compositorPolicyLabel.setFont(application.proportionalFontBold);
compositorPolicyNever.setText("Never");
compositorPolicyFullScreen.setText("Fullscreen");
compositorPolicyAlways.setText("Always");
RadioBox::group(compositorPolicyNever, compositorPolicyFullScreen, compositorPolicyAlways);
if(config.settings.compositorPolicy == 0) compositorPolicyNever.setChecked();
if(config.settings.compositorPolicy == 1) compositorPolicyFullScreen.setChecked();
if(config.settings.compositorPolicy == 2) compositorPolicyAlways.setChecked();
if(config.settings.compositorPolicy == 2) compositor::enable(false);
panelLayout.setMargin(5);
panelLayout.append(panel, SettingsWindow::PanelWidth, ~0, 5);
@ -25,21 +35,27 @@ void AdvancedSettings::create() {
layout.append(title, ~0, 0, 5);
layout.append(driverSelectionLabel, ~0, 0 );
driverLayout.append(videoDriverLabel, 0, 0, 5);
driverLayout.append(videoDriverBox, ~0, 0, 5);
driverLayout.append(audioDriverLabel, 0, 0, 5);
driverLayout.append(audioDriverBox, ~0, 0, 5);
driverLayout.append(inputDriverLabel, 0, 0, 5);
driverLayout.append(inputDriverBox, ~0, 0 );
layout.append(driverLayout, 5);
layout.append(focusPolicyLabel, ~0, 0 );
focusPolicyLayout.append(focusPolicyPause, ~0, 0, 5);
layout.append(driverSelectionLabel, ~0, 0);
driverLayout.append(videoDriverLabel, 0, 0, 5);
driverLayout.append(videoDriverBox, ~0, 0, 5);
driverLayout.append(audioDriverLabel, 0, 0, 5);
driverLayout.append(audioDriverBox, ~0, 0, 5);
driverLayout.append(inputDriverLabel, 0, 0, 5);
driverLayout.append(inputDriverBox, ~0, 0 );
layout.append(driverLayout, 5);
layout.append(focusPolicyLabel, ~0, 0 );
focusPolicyLayout.append(focusPolicyPause, ~0, 0, 5);
focusPolicyLayout.append(focusPolicyIgnore, ~0, 0, 5);
focusPolicyLayout.append(focusPolicyAllow, ~0, 0);
layout.append(focusPolicyLayout);
focusPolicyLayout.append(focusPolicyAllow, ~0, 0);
layout.append(focusPolicyLayout, 5);
layout.append(compositorPolicyLabel, ~0, 0);
compositorPolicyLayout.append(compositorPolicyNever, ~0, 0, 5);
compositorPolicyLayout.append(compositorPolicyFullScreen, ~0, 0, 5);
compositorPolicyLayout.append(compositorPolicyAlways, ~0, 0);
layout.append(compositorPolicyLayout);
layout.append(spacer, ~0, ~0);
settingsWindow.append(panelLayout);
lstring list;
@ -79,7 +95,11 @@ void AdvancedSettings::create() {
config.input.driver = list[inputDriverBox.selection()];
};
focusPolicyPause.onTick = []() { config.settings.focusPolicy = 0; };
focusPolicyIgnore.onTick = []() { config.settings.focusPolicy = 1; };
focusPolicyAllow.onTick = []() { config.settings.focusPolicy = 2; };
focusPolicyPause.onTick = [] { config.settings.focusPolicy = 0; };
focusPolicyIgnore.onTick = [] { config.settings.focusPolicy = 1; };
focusPolicyAllow.onTick = [] { config.settings.focusPolicy = 2; };
compositorPolicyNever.onTick = [] { config.settings.compositorPolicy = 0; compositor::enable(application.compositorActive); };
compositorPolicyFullScreen.onTick = [] { config.settings.compositorPolicy = 1; };
compositorPolicyAlways.onTick = [] { config.settings.compositorPolicy = 2; compositor::enable(false); };
}

View File

@ -16,11 +16,16 @@ struct AdvancedSettings {
Label focusPolicyLabel;
HorizontalLayout focusPolicyLayout;
RadioBox focusPolicyPause;
RadioBox focusPolicyIgnore;
RadioBox focusPolicyAllow;
Label compositorPolicyLabel;
HorizontalLayout compositorPolicyLayout;
RadioBox compositorPolicyNever;
RadioBox compositorPolicyFullScreen;
RadioBox compositorPolicyAlways;
Widget spacer;
void create();

View File

@ -26,14 +26,15 @@ void AudioSettings::create() {
layout.append(frequencyLayout);
layout.append(spacer, ~0, ~0);
settingsWindow.append(panelLayout);
volumeSlider.onChange = [this]() {
volumeSlider.onChange = [this] {
config.audio.volume = volumeSlider.position();
audio.set(Audio::Volume, config.audio.volume);
volumeValue.setText({ config.audio.volume, "%" });
};
frequencySlider.onChange = [this]() {
frequencySlider.onChange = [this] {
config.audio.inputFrequency = frequencySlider.position() + 31000;
audio.set(Audio::ResampleRatio, (double)config.audio.inputFrequency / (double)config.audio.outputFrequency);
frequencyValue.setText({ config.audio.inputFrequency, "hz" });

View File

@ -5,6 +5,7 @@ void InputSettings::create() {
title.setText("Input Settings");
title.setFont(application.titleFont);
locked = false;
activeInput = 0;
activeMouse = 0;
joypadsCalibrated = false;
@ -41,6 +42,8 @@ void InputSettings::create() {
controlLayout.append(clearButton, 100, 0);
layout.append(controlLayout);
settingsWindow.append(panelLayout);
portBox.onChange = { &InputSettings::portChanged, this };
deviceBox.onChange = { &InputSettings::deviceChanged, this };
@ -54,7 +57,15 @@ void InputSettings::create() {
portChanged();
}
void InputSettings::focus() {
mappingList.autoSizeColumns();
customButton1.setVisible(false);
customButton2.setVisible(false);
customButton3.setVisible(false);
}
void InputSettings::portChanged() {
locked = true;
deviceBox.reset();
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
@ -63,10 +74,13 @@ void InputSettings::portChanged() {
);
for(unsigned i = 0; i < port.size(); i++) deviceBox.append(port[i]->name);
locked = false;
deviceChanged();
}
void InputSettings::deviceChanged() {
if(locked) return;
locked = true;
mappingList.reset();
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
@ -81,9 +95,12 @@ void InputSettings::deviceChanged() {
mappingList.append(controller[i]->name, mapping);
}
mappingList.autoSizeColumns();
locked = false;
}
void InputSettings::mappingChanged() {
if(locked) return;
locked = true;
InputMapper::ControllerPort &port = (
portBox.selection() == 0 ? (InputMapper::ControllerPort&)inputMapper.port1 :
portBox.selection() == 1 ? (InputMapper::ControllerPort&)inputMapper.port2 :
@ -97,6 +114,7 @@ void InputSettings::mappingChanged() {
mappingList.modify(i, controller[i]->name, mapping);
}
mappingList.autoSizeColumns();
locked = false;
}
void InputSettings::assignInput() {

View File

@ -20,9 +20,12 @@ struct InputSettings {
Button clearButton;
void create();
void focus();
//
bool locked;
bool joypadsCalibrated;
bool joypadsCalibrating;
int16_t joypadCalibration[Joypad::Count][Joypad::Axes];

View File

@ -26,14 +26,11 @@ void SettingsWindow::create() {
inputSettings.create();
advancedSettings.create();
append(videoSettings.panelLayout);
append(audioSettings.panelLayout);
append(inputSettings.panelLayout);
append(advancedSettings.panelLayout);
panel.onChange = { &SettingsWindow::change, this };
panel.setSelection(0);
panel.setSelection(2);
change();
onClose = [] { inputSettings.endAssignment(); };
}
void SettingsWindow::change() {
@ -42,4 +39,5 @@ void SettingsWindow::change() {
audioSettings.panelLayout.setVisible(selection == 1);
inputSettings.panelLayout.setVisible(selection == 2);
advancedSettings.panelLayout.setVisible(selection == 3);
if(selection == 2) inputSettings.focus();
}

View File

@ -47,6 +47,7 @@ void VideoSettings::create() {
layout.append(fullscreenLayout);
layout.append(spacer, ~0, ~0);
settingsWindow.append(panelLayout);
brightnessSlider.setPosition(config.video.brightness);
brightnessValue.setText({ config.video.brightness, "%" });
@ -68,10 +69,11 @@ void VideoSettings::create() {
contrastSlider.onChange = brightnessSlider.onChange = gammaSlider.onChange = gammaRampCheck.onTick =
{ &VideoSettings::adjust, this };
fullscreenCenter.onTick = []() { config.video.fullscreenScale = 0; };
fullscreenScale.onTick = []() { config.video.fullscreenScale = 1; };
fullscreenStretch.onTick = []() { config.video.fullscreenScale = 2; };
fullscreenCenter.onTick = [] { config.video.fullscreenScale = 0; };
fullscreenScale.onTick = [] { config.video.fullscreenScale = 1; };
fullscreenStretch.onTick = [] { config.video.fullscreenScale = 2; };
adjust();
}
void VideoSettings::adjust() {

View File

@ -132,10 +132,11 @@ void Utility::setFullScreen(bool fullScreen) {
mainWindow.viewport.setGeometry({ viewportX, viewportY, viewportWidth, viewportHeight });
}
#if defined(PLATFORM_WINDOWS)
//compositor interferes with Vsync; disable in fullscreen mode where it is not needed
compositor::enable(fullscreen == false);
#endif
if(application.compositorActive) {
if(advancedSettings.compositorPolicyFullScreen.checked()) {
compositor::enable(fullScreen == false);
}
}
}
void Utility::setFilter() {