mirror of
https://github.com/melonDS-emu/melonDS.git
synced 2025-07-25 07:10:00 -06:00
integrate LAN into the UI better
also fix the MPInterface destructor
This commit is contained in:
@ -49,7 +49,7 @@ LANStartHostDialog::LANStartHostDialog(QWidget* parent) : QDialog(parent), ui(ne
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
MPInterface::Set(MPInterface_LAN);
|
setMPInterface(MPInterface_LAN);
|
||||||
|
|
||||||
// TODO: remember the last setting? so this doesn't suck massively
|
// TODO: remember the last setting? so this doesn't suck massively
|
||||||
// we could also remember the player name (and auto-init it from the firmware name or whatever)
|
// we could also remember the player name (and auto-init it from the firmware name or whatever)
|
||||||
@ -85,7 +85,7 @@ void LANStartHostDialog::done(int r)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
MPInterface::Set(MPInterface_Local);
|
setMPInterface(MPInterface_Local);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog::done(r);
|
QDialog::done(r);
|
||||||
@ -97,7 +97,7 @@ LANStartClientDialog::LANStartClientDialog(QWidget* parent) : QDialog(parent), u
|
|||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
MPInterface::Set(MPInterface_LAN);
|
setMPInterface(MPInterface_LAN);
|
||||||
|
|
||||||
QStandardItemModel* model = new QStandardItemModel();
|
QStandardItemModel* model = new QStandardItemModel();
|
||||||
ui->tvAvailableGames->setModel(model);
|
ui->tvAvailableGames->setModel(model);
|
||||||
@ -213,7 +213,7 @@ void LANStartClientDialog::done(int r)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
lan().EndDiscovery();
|
lan().EndDiscovery();
|
||||||
MPInterface::Set(MPInterface_Local);
|
setMPInterface(MPInterface_Local);
|
||||||
}
|
}
|
||||||
|
|
||||||
QDialog::done(r);
|
QDialog::done(r);
|
||||||
@ -293,10 +293,26 @@ LANDialog::~LANDialog()
|
|||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LANDialog::on_btnLeaveGame_clicked()
|
||||||
|
{
|
||||||
|
done(QDialog::Accepted);
|
||||||
|
}
|
||||||
|
|
||||||
void LANDialog::done(int r)
|
void LANDialog::done(int r)
|
||||||
{
|
{
|
||||||
// ???
|
bool showwarning = true;
|
||||||
// TODO handle this situation, and provide the user a way to reopen this dialog
|
if (lan().GetNumPlayers() < 2)
|
||||||
|
showwarning = false;
|
||||||
|
|
||||||
|
if (showwarning)
|
||||||
|
{
|
||||||
|
if (QMessageBox::warning(this, "melonDS", "Really leave this LAN game?",
|
||||||
|
QMessageBox::Yes | QMessageBox::No, QMessageBox::No) == QMessageBox::No)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
lan().EndSession();
|
||||||
|
setMPInterface(MPInterface_Local);
|
||||||
|
|
||||||
QDialog::done(r);
|
QDialog::done(r);
|
||||||
}
|
}
|
||||||
|
@ -104,6 +104,7 @@ protected:
|
|||||||
void timerEvent(QTimerEvent* event) override;
|
void timerEvent(QTimerEvent* event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void on_btnLeaveGame_clicked();
|
||||||
void done(int r);
|
void done(int r);
|
||||||
|
|
||||||
void doUpdatePlayerList();
|
void doUpdatePlayerList();
|
||||||
|
@ -11,15 +11,35 @@
|
|||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
<string>LAN SHITO</string>
|
<string>LAN game - melonDS</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="lblStatus">
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
<property name="text">
|
<property name="leftMargin">
|
||||||
<string>STATUS PLACEHOLDER</string>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnLeaveGame">
|
||||||
|
<property name="text">
|
||||||
|
<string>Leave game</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QTreeView" name="tvPlayerList"/>
|
<widget class="QTreeView" name="tvPlayerList"/>
|
||||||
|
@ -749,6 +749,8 @@ MainWindow::MainWindow(int id, EmuInstance* inst, QWidget* parent) :
|
|||||||
|
|
||||||
QObject::connect(qApp, &QApplication::applicationStateChanged, this, &MainWindow::onAppStateChanged);
|
QObject::connect(qApp, &QApplication::applicationStateChanged, this, &MainWindow::onAppStateChanged);
|
||||||
onUpdateInterfaceSettings();
|
onUpdateInterfaceSettings();
|
||||||
|
|
||||||
|
updateMPInterface(MPInterface::GetType());
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
@ -1712,6 +1714,19 @@ void MainWindow::onNPTest()
|
|||||||
//Netplay::StartGame();
|
//Netplay::StartGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindow::updateMPInterface(MPInterfaceType type)
|
||||||
|
{
|
||||||
|
// MP interface was changed, reflect it in the UI
|
||||||
|
|
||||||
|
bool enable = (type == MPInterface_Local);
|
||||||
|
actMPNewInstance->setEnabled(enable);
|
||||||
|
actLANStartHost->setEnabled(enable);
|
||||||
|
actLANStartClient->setEnabled(enable);
|
||||||
|
actNPStartHost->setEnabled(enable);
|
||||||
|
actNPStartClient->setEnabled(enable);
|
||||||
|
actNPTest->setEnabled(enable);
|
||||||
|
}
|
||||||
|
|
||||||
bool MainWindow::lanWarning(bool host)
|
bool MainWindow::lanWarning(bool host)
|
||||||
{
|
{
|
||||||
if (numEmuInstances() < 2)
|
if (numEmuInstances() < 2)
|
||||||
|
@ -35,6 +35,7 @@
|
|||||||
|
|
||||||
#include "Screen.h"
|
#include "Screen.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "MPInterface.h"
|
||||||
|
|
||||||
|
|
||||||
class EmuInstance;
|
class EmuInstance;
|
||||||
@ -125,6 +126,9 @@ public:
|
|||||||
|
|
||||||
void osdAddMessage(unsigned int color, const char* msg);
|
void osdAddMessage(unsigned int color, const char* msg);
|
||||||
|
|
||||||
|
// called when the MP interface is changed
|
||||||
|
void updateMPInterface(melonDS::MPInterfaceType type);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void keyPressEvent(QKeyEvent* event) override;
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
void keyReleaseEvent(QKeyEvent* event) override;
|
void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
|
@ -205,6 +205,28 @@ void pathInit()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void setMPInterface(MPInterfaceType type)
|
||||||
|
{
|
||||||
|
// switch to the requested MP interface
|
||||||
|
MPInterface::Set(type);
|
||||||
|
|
||||||
|
// set receive timeout
|
||||||
|
// TODO: different settings per interface?
|
||||||
|
MPInterface::Get().SetRecvTimeout(Config::GetGlobalTable().GetInt("MP.RecvTimeout"));
|
||||||
|
|
||||||
|
// update UI appropriately
|
||||||
|
// TODO: decide how to deal with multi-window when it becomes a thing
|
||||||
|
for (int i = 0; i < kMaxEmuInstances; i++)
|
||||||
|
{
|
||||||
|
EmuInstance* inst = emuInstances[i];
|
||||||
|
if (!inst) continue;
|
||||||
|
|
||||||
|
MainWindow* win = inst->getMainWindow();
|
||||||
|
if (win) win->updateMPInterface(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
MelonApplication::MelonApplication(int& argc, char** argv)
|
MelonApplication::MelonApplication(int& argc, char** argv)
|
||||||
: QApplication(argc, argv)
|
: QApplication(argc, argv)
|
||||||
@ -313,8 +335,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
// default MP interface type is local MP
|
// default MP interface type is local MP
|
||||||
// this will be changed if a LAN or netplay session is initiated
|
// this will be changed if a LAN or netplay session is initiated
|
||||||
MPInterface::Set(MPInterface_Local);
|
setMPInterface(MPInterface_Local);
|
||||||
MPInterface::Get().SetRecvTimeout(Config::GetGlobalTable().GetInt("MP.RecvTimeout"));
|
|
||||||
|
|
||||||
NetInit();
|
NetInit();
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#include "Window.h"
|
#include "Window.h"
|
||||||
#include "EmuThread.h"
|
#include "EmuThread.h"
|
||||||
#include "ScreenLayout.h"
|
#include "ScreenLayout.h"
|
||||||
|
#include "MPInterface.h"
|
||||||
|
|
||||||
class MelonApplication : public QApplication
|
class MelonApplication : public QApplication
|
||||||
{
|
{
|
||||||
@ -49,4 +50,6 @@ void deleteEmuInstance(int id);
|
|||||||
void deleteAllEmuInstances(int first = 0);
|
void deleteAllEmuInstances(int first = 0);
|
||||||
int numEmuInstances();
|
int numEmuInstances();
|
||||||
|
|
||||||
|
void setMPInterface(melonDS::MPInterfaceType type);
|
||||||
|
|
||||||
#endif // MAIN_H
|
#endif // MAIN_H
|
||||||
|
@ -17,10 +17,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <queue>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#ifdef __WIN32__
|
#ifdef __WIN32__
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
@ -107,46 +104,25 @@ LAN::LAN() noexcept : Inited(false)
|
|||||||
// TODO make this somewhat nicer
|
// TODO make this somewhat nicer
|
||||||
if (enet_initialize() != 0)
|
if (enet_initialize() != 0)
|
||||||
{
|
{
|
||||||
printf("enet shat itself :(\n");
|
Platform::Log(Platform::LogLevel::Error, "LAN: failed to initialize enet\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("enet init OK\n");
|
Platform::Log(Platform::LogLevel::Info, "LAN: enet initialized\n");
|
||||||
Inited = true;
|
Inited = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LAN::~LAN() noexcept
|
LAN::~LAN() noexcept
|
||||||
{
|
{
|
||||||
if (DiscoverySocket)
|
EndSession();
|
||||||
{
|
|
||||||
closesocket(DiscoverySocket);
|
|
||||||
DiscoverySocket = INVALID_SOCKET;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!RXQueue.empty())
|
|
||||||
{
|
|
||||||
ENetPacket* packet = RXQueue.front();
|
|
||||||
RXQueue.pop();
|
|
||||||
enet_packet_destroy(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 16; i++)
|
|
||||||
{
|
|
||||||
if (i == MyPlayer.ID) continue;
|
|
||||||
|
|
||||||
if (RemotePeers[i])
|
|
||||||
enet_peer_disconnect(RemotePeers[i], 0);
|
|
||||||
|
|
||||||
RemotePeers[i] = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
enet_host_destroy(Host);
|
|
||||||
Host = nullptr;
|
|
||||||
|
|
||||||
|
Inited = false;
|
||||||
enet_deinitialize();
|
enet_deinitialize();
|
||||||
|
|
||||||
Platform::Mutex_Free(DiscoveryMutex);
|
Platform::Mutex_Free(DiscoveryMutex);
|
||||||
Platform::Mutex_Free(PlayersMutex);
|
Platform::Mutex_Free(PlayersMutex);
|
||||||
|
|
||||||
|
Platform::Log(Platform::LogLevel::Info, "LAN: enet deinitialized\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,9 +257,6 @@ bool LAN::StartHost(const char* playername, int numplayers)
|
|||||||
Active = true;
|
Active = true;
|
||||||
IsHost = true;
|
IsHost = true;
|
||||||
|
|
||||||
//if (lanDlg)
|
|
||||||
// lanDlg->updatePlayerList();
|
|
||||||
|
|
||||||
StartDiscovery();
|
StartDiscovery();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -398,6 +371,35 @@ bool LAN::StartClient(const char* playername, const char* host)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LAN::EndSession()
|
||||||
|
{
|
||||||
|
if (!Active) return;
|
||||||
|
if (IsHost) EndDiscovery();
|
||||||
|
|
||||||
|
Active = false;
|
||||||
|
|
||||||
|
while (!RXQueue.empty())
|
||||||
|
{
|
||||||
|
ENetPacket* packet = RXQueue.front();
|
||||||
|
RXQueue.pop();
|
||||||
|
enet_packet_destroy(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
if (i == MyPlayer.ID) continue;
|
||||||
|
|
||||||
|
if (RemotePeers[i])
|
||||||
|
enet_peer_disconnect(RemotePeers[i], 0);
|
||||||
|
|
||||||
|
RemotePeers[i] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
enet_host_destroy(Host);
|
||||||
|
Host = nullptr;
|
||||||
|
IsHost = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void LAN::ProcessDiscovery()
|
void LAN::ProcessDiscovery()
|
||||||
{
|
{
|
||||||
@ -631,7 +633,6 @@ void LAN::ProcessHostEvent(ENetEvent& event)
|
|||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
//printf("HOST: PLAYER CONNECT %p\n", player);
|
|
||||||
if (!player) break;
|
if (!player) break;
|
||||||
|
|
||||||
ConnectedBitmask |= (1 << player->ID);
|
ConnectedBitmask |= (1 << player->ID);
|
||||||
@ -642,7 +643,6 @@ void LAN::ProcessHostEvent(ENetEvent& event)
|
|||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
//printf("HOST: PLAYER DISCONNECT %p\n", player);
|
|
||||||
if (!player) break;
|
if (!player) break;
|
||||||
|
|
||||||
ConnectedBitmask &= ~(1 << player->ID);
|
ConnectedBitmask &= ~(1 << player->ID);
|
||||||
@ -757,7 +757,6 @@ void LAN::ProcessClientEvent(ENetEvent& event)
|
|||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
//printf("CLIENT: PLAYER CONNECT %p\n", player);
|
|
||||||
if (!player) break;
|
if (!player) break;
|
||||||
|
|
||||||
ConnectedBitmask |= (1 << player->ID);
|
ConnectedBitmask |= (1 << player->ID);
|
||||||
@ -768,7 +767,6 @@ void LAN::ProcessClientEvent(ENetEvent& event)
|
|||||||
{
|
{
|
||||||
if (event.packet->dataLength != 1) break;
|
if (event.packet->dataLength != 1) break;
|
||||||
Player* player = (Player*)event.peer->data;
|
Player* player = (Player*)event.peer->data;
|
||||||
//printf("CLIENT: PLAYER DISCONNECT %p\n", player);
|
|
||||||
if (!player) break;
|
if (!player) break;
|
||||||
|
|
||||||
ConnectedBitmask &= ~(1 << player->ID);
|
ConnectedBitmask &= ~(1 << player->ID);
|
||||||
@ -796,7 +794,6 @@ void LAN::ProcessEvent(ENetEvent& event)
|
|||||||
void LAN::ProcessLAN(int type)
|
void LAN::ProcessLAN(int type)
|
||||||
{
|
{
|
||||||
if (!Host) return;
|
if (!Host) return;
|
||||||
//printf("Process(%d): %d %d\n", type, RXQueue.empty(), RXQueue.size());
|
|
||||||
|
|
||||||
u32 time_last = (u32)Platform::GetMSCount();
|
u32 time_last = (u32)Platform::GetMSCount();
|
||||||
|
|
||||||
@ -842,7 +839,7 @@ void LAN::ProcessLAN(int type)
|
|||||||
if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == Chan_MP)
|
if (event.type == ENET_EVENT_TYPE_RECEIVE && event.channelID == Chan_MP)
|
||||||
{
|
{
|
||||||
MPPacketHeader* header = (MPPacketHeader*)&event.packet->data[0];
|
MPPacketHeader* header = (MPPacketHeader*)&event.packet->data[0];
|
||||||
//printf("- enet_host_service: (%d) got MP frame, len=%d type=%08X fc=%04X\n", type, event.packet->dataLength, header->Type, *(u16*)&event.packet->data[sizeof(MPPacketHeader)+12]);
|
|
||||||
bool good = true;
|
bool good = true;
|
||||||
if (event.packet->dataLength < sizeof(MPPacketHeader))
|
if (event.packet->dataLength < sizeof(MPPacketHeader))
|
||||||
good = false;
|
good = false;
|
||||||
@ -870,7 +867,6 @@ void LAN::ProcessLAN(int type)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//printf("- enet_host_service: got something else, time=%d\n", SDL_GetTicks()-time_last);
|
|
||||||
ProcessEvent(event);
|
ProcessEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1053,7 +1049,6 @@ u16 LAN::RecvReplies(int inst, u8* packets, u64 timestamp, u16 aidmask)
|
|||||||
if (RXQueue.empty())
|
if (RXQueue.empty())
|
||||||
{
|
{
|
||||||
// no more replies available
|
// no more replies available
|
||||||
//printf("RecvMPReplies timeout, ret=%04X myinstmask=%04X conn=%04X aidmask=%04X\n", ret, myinstmask, ConnectedBitmask, aidmask);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ public:
|
|||||||
void EndDiscovery();
|
void EndDiscovery();
|
||||||
bool StartHost(const char* player, int numplayers);
|
bool StartHost(const char* player, int numplayers);
|
||||||
bool StartClient(const char* player, const char* host);
|
bool StartClient(const char* player, const char* host);
|
||||||
|
void EndSession();
|
||||||
|
|
||||||
std::map<u32, DiscoveryData> GetDiscoveryList();
|
std::map<u32, DiscoveryData> GetDiscoveryList();
|
||||||
std::vector<Player> GetPlayerList();
|
std::vector<Player> GetPlayerList();
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
std::unique_ptr<MPInterface> MPInterface::Current(std::make_unique<DummyMP>());
|
std::unique_ptr<MPInterface> MPInterface::Current(std::make_unique<DummyMP>());
|
||||||
|
MPInterfaceType MPInterface::CurrentType = MPInterface_Dummy;
|
||||||
|
|
||||||
|
|
||||||
void MPInterface::Set(MPInterfaceType type)
|
void MPInterface::Set(MPInterfaceType type)
|
||||||
@ -60,6 +61,8 @@ void MPInterface::Set(MPInterfaceType type)
|
|||||||
Current = std::make_unique<DummyMP>();
|
Current = std::make_unique<DummyMP>();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CurrentType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -46,7 +46,10 @@ struct MPPacketHeader
|
|||||||
class MPInterface
|
class MPInterface
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual ~MPInterface() = default;
|
||||||
|
|
||||||
static MPInterface& Get() { return *Current; }
|
static MPInterface& Get() { return *Current; }
|
||||||
|
static MPInterfaceType GetType() { return CurrentType; }
|
||||||
static void Set(MPInterfaceType type);
|
static void Set(MPInterfaceType type);
|
||||||
|
|
||||||
[[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; }
|
[[nodiscard]] int GetRecvTimeout() const noexcept { return RecvTimeout; }
|
||||||
@ -70,6 +73,7 @@ protected:
|
|||||||
int RecvTimeout = 25;
|
int RecvTimeout = 25;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static MPInterfaceType CurrentType;
|
||||||
static std::unique_ptr<MPInterface> Current;
|
static std::unique_ptr<MPInterface> Current;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user