mirror of https://github.com/mgba-emu/mgba.git
Qt: Add layer placement features
This commit is contained in:
parent
8ea524d9e6
commit
67a135e5e7
1
CHANGES
1
CHANGES
|
@ -49,6 +49,7 @@ Misc:
|
|||
- GBA Memory: 64 MiB GBA Video cartridge support
|
||||
- PSP2: Use system enter key by default
|
||||
- 3DS: Remove deprecated CSND interface
|
||||
- Qt: Options to mess around with layer placement
|
||||
|
||||
0.6.3: (2017-04-14)
|
||||
Bugfixes:
|
||||
|
|
|
@ -153,6 +153,7 @@ struct mCore {
|
|||
size_t (*listAudioChannels)(const struct mCore*, const struct mCoreChannelInfo**);
|
||||
void (*enableVideoLayer)(struct mCore*, size_t id, bool enable);
|
||||
void (*enableAudioChannel)(struct mCore*, size_t id, bool enable);
|
||||
void (*adjustVideoLayer)(struct mCore*, size_t id, int32_t x, int32_t y);
|
||||
|
||||
#ifndef MINIMAL_CORE
|
||||
void (*startVideoLog)(struct mCore*, struct mVideoLogContext*);
|
||||
|
|
|
@ -38,6 +38,13 @@ struct GBVideoSoftwareRenderer {
|
|||
GBRegisterLCDC lcdc;
|
||||
enum GBModel model;
|
||||
|
||||
int16_t objOffsetX;
|
||||
int16_t objOffsetY;
|
||||
int16_t offsetScx;
|
||||
int16_t offsetScy;
|
||||
int16_t offsetWx;
|
||||
int16_t offsetWy;
|
||||
|
||||
int sgbTransfer;
|
||||
uint8_t sgbPacket[128];
|
||||
uint8_t sgbCommandHeader;
|
||||
|
|
|
@ -44,6 +44,8 @@ struct GBAVideoSoftwareBackground {
|
|||
int32_t sy;
|
||||
int yCache;
|
||||
uint16_t mapCache[64];
|
||||
int32_t offsetX;
|
||||
int32_t offsetY;
|
||||
};
|
||||
|
||||
enum BlendEffect {
|
||||
|
@ -159,6 +161,8 @@ struct GBAVideoSoftwareRenderer {
|
|||
int oamDirty;
|
||||
int oamMax;
|
||||
struct GBAVideoSoftwareSprite sprites[128];
|
||||
int16_t objOffsetX;
|
||||
int16_t objOffsetY;
|
||||
|
||||
uint32_t scanlineDirty[5];
|
||||
uint16_t nextIo[REG_SOUND1CNT_LO];
|
||||
|
|
|
@ -791,13 +791,17 @@ static bool _GBCoreSavedataRestore(struct mCore* core, const void* sram, size_t
|
|||
|
||||
static size_t _GBCoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||
UNUSED(core);
|
||||
*info = _GBVideoLayers;
|
||||
if (info) {
|
||||
*info = _GBVideoLayers;
|
||||
}
|
||||
return sizeof(_GBVideoLayers) / sizeof(*_GBVideoLayers);
|
||||
}
|
||||
|
||||
static size_t _GBCoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||
UNUSED(core);
|
||||
*info = _GBAudioChannels;
|
||||
if (info) {
|
||||
*info = _GBAudioChannels;
|
||||
}
|
||||
return sizeof(_GBAudioChannels) / sizeof(*_GBAudioChannels);
|
||||
}
|
||||
|
||||
|
@ -832,6 +836,26 @@ static void _GBCoreEnableAudioChannel(struct mCore* core, size_t id, bool enable
|
|||
}
|
||||
}
|
||||
|
||||
static void _GBCoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
switch (id) {
|
||||
case 0:
|
||||
gbcore->renderer.offsetScx = x;
|
||||
gbcore->renderer.offsetScy = y;
|
||||
break;
|
||||
case 1:
|
||||
gbcore->renderer.offsetWx = x;
|
||||
gbcore->renderer.offsetWy = y;
|
||||
break;
|
||||
case 2:
|
||||
gbcore->renderer.objOffsetX = x;
|
||||
gbcore->renderer.objOffsetY = y;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef MINIMAL_CORE
|
||||
static void _GBCoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
||||
struct GBCore* gbcore = (struct GBCore*) core;
|
||||
|
@ -934,6 +958,7 @@ struct mCore* GBCoreCreate(void) {
|
|||
core->listAudioChannels = _GBCoreListAudioChannels;
|
||||
core->enableVideoLayer = _GBCoreEnableVideoLayer;
|
||||
core->enableAudioChannel = _GBCoreEnableAudioChannel;
|
||||
core->adjustVideoLayer = _GBCoreAdjustVideoLayer;
|
||||
#ifndef MINIMAL_CORE
|
||||
core->startVideoLog = _GBCoreStartVideoLog;
|
||||
core->endVideoLog = _GBCoreEndVideoLog;
|
||||
|
|
|
@ -198,6 +198,13 @@ static void GBVideoSoftwareRendererInit(struct GBVideoRenderer* renderer, enum G
|
|||
softwareRenderer->sgbTransfer = 0;
|
||||
softwareRenderer->sgbCommandHeader = 0;
|
||||
softwareRenderer->sgbBorders = sgbBorders;
|
||||
softwareRenderer->objOffsetX = 0;
|
||||
softwareRenderer->objOffsetY = 0;
|
||||
softwareRenderer->offsetScx = 0;
|
||||
softwareRenderer->offsetScy = 0;
|
||||
softwareRenderer->offsetWx = 0;
|
||||
softwareRenderer->offsetWy = 0;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 64; ++i) {
|
||||
softwareRenderer->lookup[i] = i;
|
||||
|
@ -471,7 +478,7 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
int wy = softwareRenderer->wy + softwareRenderer->currentWy;
|
||||
if (GBRegisterLCDCIsWindow(softwareRenderer->lcdc) && wy <= y && endX >= softwareRenderer->wx - 7) {
|
||||
if (softwareRenderer->wx - 7 > 0 && !softwareRenderer->d.disableBG) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, softwareRenderer->wx - 7, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
|
||||
}
|
||||
|
||||
maps = &softwareRenderer->d.vram[GB_BASE_MAP];
|
||||
|
@ -479,10 +486,10 @@ static void GBVideoSoftwareRendererDrawRange(struct GBVideoRenderer* renderer, i
|
|||
maps += GB_SIZE_MAP;
|
||||
}
|
||||
if (!softwareRenderer->d.disableWIN) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx, y - wy);
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, softwareRenderer->wx - 7, endX, 7 - softwareRenderer->wx - softwareRenderer->offsetWx, y - wy - softwareRenderer->offsetWy);
|
||||
}
|
||||
} else if (!softwareRenderer->d.disableBG) {
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx, softwareRenderer->scy + y);
|
||||
GBVideoSoftwareRendererDrawBackground(softwareRenderer, maps, startX, endX, softwareRenderer->scx - softwareRenderer->offsetScx, softwareRenderer->scy + y - softwareRenderer->offsetScy);
|
||||
}
|
||||
} else if (!softwareRenderer->d.disableBG) {
|
||||
memset(&softwareRenderer->row[startX], 0, endX - startX);
|
||||
|
@ -778,15 +785,16 @@ static void GBVideoSoftwareRendererDrawBackground(struct GBVideoSoftwareRenderer
|
|||
}
|
||||
|
||||
static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* renderer, struct GBObj* obj, int startX, int endX, int y) {
|
||||
int ix = obj->x - 8;
|
||||
int objX = obj->x + renderer->objOffsetX;
|
||||
int ix = objX - 8;
|
||||
if (endX < ix || startX >= ix + 8) {
|
||||
return;
|
||||
}
|
||||
if (obj->x < endX) {
|
||||
endX = obj->x;
|
||||
if (objX < endX) {
|
||||
endX = objX;
|
||||
}
|
||||
if (obj->x - 8 > startX) {
|
||||
startX = obj->x - 8;
|
||||
if (objX - 8 > startX) {
|
||||
startX = objX - 8;
|
||||
}
|
||||
if (startX < 0) {
|
||||
startX = 0;
|
||||
|
@ -794,14 +802,15 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
|||
uint8_t* data = renderer->d.vram;
|
||||
int tileOffset = 0;
|
||||
int bottomY;
|
||||
int objY = obj->y + renderer->objOffsetY;
|
||||
if (GBObjAttributesIsYFlip(obj->attr)) {
|
||||
bottomY = 7 - ((y - obj->y - 16) & 7);
|
||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y < -8) {
|
||||
bottomY = 7 - ((y - objY - 16) & 7);
|
||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY < -8) {
|
||||
++tileOffset;
|
||||
}
|
||||
} else {
|
||||
bottomY = (y - obj->y - 16) & 7;
|
||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - obj->y >= -8) {
|
||||
bottomY = (y - objY - 16) & 7;
|
||||
if (GBRegisterLCDCIsObjSize(renderer->lcdc) && y - objY >= -8) {
|
||||
++tileOffset;
|
||||
}
|
||||
}
|
||||
|
@ -825,12 +834,12 @@ static void GBVideoSoftwareRendererDrawObj(struct GBVideoSoftwareRenderer* rende
|
|||
}
|
||||
int bottomX;
|
||||
int x = startX;
|
||||
if ((x - obj->x) & 7) {
|
||||
if ((x - objX) & 7) {
|
||||
for (; x < endX; ++x) {
|
||||
if (GBObjAttributesIsXFlip(obj->attr)) {
|
||||
bottomX = (x - obj->x) & 7;
|
||||
bottomX = (x - objX) & 7;
|
||||
} else {
|
||||
bottomX = 7 - ((x - obj->x) & 7);
|
||||
bottomX = 7 - ((x - objX) & 7);
|
||||
}
|
||||
int objTile = obj->tile + tileOffset;
|
||||
uint8_t tileDataLower = data[(objTile * 8 + bottomY) * 2];
|
||||
|
|
|
@ -795,13 +795,17 @@ static bool _GBACoreSavedataRestore(struct mCore* core, const void* sram, size_t
|
|||
|
||||
static size_t _GBACoreListVideoLayers(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||
UNUSED(core);
|
||||
*info = _GBAVideoLayers;
|
||||
if (info) {
|
||||
*info = _GBAVideoLayers;
|
||||
}
|
||||
return sizeof(_GBAVideoLayers) / sizeof(*_GBAVideoLayers);
|
||||
}
|
||||
|
||||
static size_t _GBACoreListAudioChannels(const struct mCore* core, const struct mCoreChannelInfo** info) {
|
||||
UNUSED(core);
|
||||
*info = _GBAAudioChannels;
|
||||
if (info) {
|
||||
*info = _GBAAudioChannels;
|
||||
}
|
||||
return sizeof(_GBAAudioChannels) / sizeof(*_GBAAudioChannels);
|
||||
}
|
||||
|
||||
|
@ -841,6 +845,27 @@ static void _GBACoreEnableAudioChannel(struct mCore* core, size_t id, bool enabl
|
|||
}
|
||||
}
|
||||
|
||||
static void _GBACoreAdjustVideoLayer(struct mCore* core, size_t id, int32_t x, int32_t y) {
|
||||
struct GBACore* gbacore = (struct GBACore*) core;
|
||||
switch (id) {
|
||||
case 0:
|
||||
case 1:
|
||||
case 2:
|
||||
case 3:
|
||||
gbacore->renderer.bg[id].offsetX = x;
|
||||
gbacore->renderer.bg[id].offsetY = y;
|
||||
break;
|
||||
case 4:
|
||||
gbacore->renderer.objOffsetX = x;
|
||||
gbacore->renderer.objOffsetY = y;
|
||||
gbacore->renderer.oamDirty = 1;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
memset(gbacore->renderer.scanlineDirty, 0xFFFFFFFF, sizeof(gbacore->renderer.scanlineDirty));
|
||||
}
|
||||
|
||||
#ifndef MINIMAL_CORE
|
||||
static void _GBACoreStartVideoLog(struct mCore* core, struct mVideoLogContext* context) {
|
||||
struct GBACore* gbacore = (struct GBACore*) core;
|
||||
|
@ -946,6 +971,7 @@ struct mCore* GBACoreCreate(void) {
|
|||
core->listAudioChannels = _GBACoreListAudioChannels;
|
||||
core->enableVideoLayer = _GBACoreEnableVideoLayer;
|
||||
core->enableAudioChannel = _GBACoreEnableAudioChannel;
|
||||
core->adjustVideoLayer = _GBACoreAdjustVideoLayer;
|
||||
#ifndef MINIMAL_CORE
|
||||
core->startVideoLog = _GBACoreStartVideoLog;
|
||||
core->endVideoLog = _GBACoreEndVideoLog;
|
||||
|
|
|
@ -446,13 +446,13 @@
|
|||
}
|
||||
|
||||
void GBAVideoSoftwareRendererDrawBackgroundMode0(struct GBAVideoSoftwareRenderer* renderer, struct GBAVideoSoftwareBackground* background, int y) {
|
||||
int inX = (renderer->start + background->x) & 0x1FF;
|
||||
int inX = (renderer->start + background->x - background->offsetX) & 0x1FF;
|
||||
int length = renderer->end - renderer->start;
|
||||
if (background->mosaic) {
|
||||
int mosaicV = GBAMosaicControlGetBgV(renderer->mosaic) + 1;
|
||||
y -= y % mosaicV;
|
||||
}
|
||||
int inY = y + background->y;
|
||||
int inY = y + background->y - background->offsetY;
|
||||
uint16_t mapData;
|
||||
|
||||
unsigned yBase = inY & 0xF8;
|
||||
|
|
|
@ -147,6 +147,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
|||
}
|
||||
int32_t x = (uint32_t) GBAObjAttributesBGetX(sprite->b) << 23;
|
||||
x >>= 23;
|
||||
x += renderer->objOffsetX;
|
||||
uint16_t* vramBase = &renderer->d.vram[BASE_TILE >> 1];
|
||||
bool align = GBAObjAttributesAIs256Color(sprite->a) && !GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt);
|
||||
unsigned charBase = (GBAObjAttributesCGetTile(sprite->c) & ~align) * 0x20;
|
||||
|
@ -185,7 +186,7 @@ int GBAVideoSoftwareRendererPreprocessSprite(struct GBAVideoSoftwareRenderer* re
|
|||
}
|
||||
}
|
||||
|
||||
int inY = y - (int) GBAObjAttributesAGetY(sprite->a);
|
||||
int inY = y - ((int) GBAObjAttributesAGetY(sprite->a) + renderer->objOffsetY);
|
||||
int stride = GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? (width >> !GBAObjAttributesAIs256Color(sprite->a)) : 0x80;
|
||||
|
||||
uint32_t current;
|
||||
|
|
|
@ -114,6 +114,9 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
|||
softwareRenderer->mosaic = 0;
|
||||
softwareRenderer->nextY = 0;
|
||||
|
||||
softwareRenderer->objOffsetX = 0;
|
||||
softwareRenderer->objOffsetY = 0;
|
||||
|
||||
memset(softwareRenderer->scanlineDirty, 0xFFFFFFFF, sizeof(softwareRenderer->scanlineDirty));
|
||||
memset(softwareRenderer->cache, 0, sizeof(softwareRenderer->cache));
|
||||
memset(softwareRenderer->nextIo, 0, sizeof(softwareRenderer->nextIo));
|
||||
|
@ -142,6 +145,8 @@ static void GBAVideoSoftwareRendererReset(struct GBAVideoRenderer* renderer) {
|
|||
bg->sx = 0;
|
||||
bg->sy = 0;
|
||||
bg->yCache = -1;
|
||||
bg->offsetX = 0;
|
||||
bg->offsetY = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -507,8 +512,9 @@ static void _cleanOAM(struct GBAVideoSoftwareRenderer* renderer) {
|
|||
height <<= GBAObjAttributesAGetDoubleSize(obj.a);
|
||||
}
|
||||
if (GBAObjAttributesAGetY(obj.a) < VIDEO_VERTICAL_PIXELS || GBAObjAttributesAGetY(obj.a) + height >= VIDEO_VERTICAL_TOTAL_PIXELS) {
|
||||
renderer->sprites[oamMax].y = GBAObjAttributesAGetY(obj.a);
|
||||
renderer->sprites[oamMax].endY = GBAObjAttributesAGetY(obj.a) + height;
|
||||
int y = GBAObjAttributesAGetY(obj.a) + renderer->objOffsetY;
|
||||
renderer->sprites[oamMax].y = y;
|
||||
renderer->sprites[oamMax].endY = y + height;
|
||||
renderer->sprites[oamMax].obj = obj;
|
||||
++oamMax;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,7 @@ set(SOURCE_FILES
|
|||
ObjView.cpp
|
||||
OverrideView.cpp
|
||||
PaletteView.cpp
|
||||
PlacementControl.cpp
|
||||
PrinterView.cpp
|
||||
RegisterView.cpp
|
||||
ROMInfo.cpp
|
||||
|
@ -135,6 +136,7 @@ set(UI_FILES
|
|||
ObjView.ui
|
||||
OverrideView.ui
|
||||
PaletteView.ui
|
||||
PlacementControl.ui
|
||||
PrinterView.ui
|
||||
ROMInfo.ui
|
||||
SensorView.ui
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/* Copyright (c) 2013-2018 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#include "PlacementControl.h"
|
||||
|
||||
#include "CoreController.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
|
||||
#include <mgba/core/core.h>
|
||||
|
||||
using namespace QGBA;
|
||||
|
||||
PlacementControl::PlacementControl(std::shared_ptr<CoreController> controller, QWidget* parent)
|
||||
: QDialog(parent)
|
||||
, m_controller(controller)
|
||||
{
|
||||
m_ui.setupUi(this);
|
||||
|
||||
connect(m_ui.offsetX, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int x) {
|
||||
adjustLayer(-1, x, m_ui.offsetY->value());
|
||||
});
|
||||
|
||||
connect(m_ui.offsetY, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this](int y) {
|
||||
adjustLayer(-1, m_ui.offsetX->value(), y);
|
||||
});
|
||||
|
||||
QGridLayout* grid = static_cast<QGridLayout*>(layout());
|
||||
CoreController::Interrupter interrupter(m_controller);
|
||||
const mCoreChannelInfo* info;
|
||||
size_t nVideo = m_controller->thread()->core->listVideoLayers(m_controller->thread()->core, &info);
|
||||
for (size_t i = 0; i < nVideo; ++i) {
|
||||
QSpinBox* offsetX = new QSpinBox;
|
||||
QSpinBox* offsetY = new QSpinBox;
|
||||
|
||||
offsetX->setWrapping(true);
|
||||
offsetX->setMaximum(127);
|
||||
offsetX->setMinimum(-128);
|
||||
offsetX->setAccelerated(true);
|
||||
|
||||
offsetY->setWrapping(true);
|
||||
offsetY->setMaximum(127);
|
||||
offsetY->setMinimum(-128);
|
||||
offsetY->setAccelerated(true);
|
||||
|
||||
m_layers.append(qMakePair(offsetX, offsetY));
|
||||
int row = grid->rowCount();
|
||||
grid->addWidget(new QLabel(QString(info[i].visibleName)), row, 0, Qt::AlignRight);
|
||||
grid->addWidget(offsetX, row, 1);
|
||||
grid->addWidget(offsetY, row, 2);
|
||||
|
||||
connect(offsetX, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, i, offsetY](int x) {
|
||||
adjustLayer(i, x, offsetY->value());
|
||||
});
|
||||
|
||||
connect(offsetY, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), [this, i, offsetX](int y) {
|
||||
adjustLayer(i, offsetX->value(), y);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void PlacementControl::adjustLayer(int layer, int32_t x, int32_t y) {
|
||||
CoreController::Interrupter interrupter(m_controller);
|
||||
mCore* core = m_controller->thread()->core;
|
||||
size_t nVideo = core->listVideoLayers(core, nullptr);
|
||||
|
||||
if (layer < 0) {
|
||||
for (size_t i = 0; i < nVideo; ++i) {
|
||||
core->adjustVideoLayer(core, i, x + m_layers[i].first->value(), y + m_layers[i].second->value());
|
||||
}
|
||||
} else if ((size_t) layer < nVideo) {
|
||||
core->adjustVideoLayer(core, layer, x + m_ui.offsetX->value(), y + m_ui.offsetY->value());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/* Copyright (c) 2013-2018 Jeffrey Pfau
|
||||
*
|
||||
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QList>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ui_PlacementControl.h"
|
||||
|
||||
namespace QGBA {
|
||||
|
||||
class CoreController;
|
||||
|
||||
class PlacementControl : public QDialog {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
PlacementControl(std::shared_ptr<CoreController>, QWidget* parent = nullptr);
|
||||
|
||||
private:
|
||||
void adjustLayer(int layer, int32_t x, int32_t y);
|
||||
|
||||
std::shared_ptr<CoreController> m_controller;
|
||||
QList<QPair<QSpinBox*, QSpinBox*>> m_layers;
|
||||
|
||||
Ui::PlacementControl m_ui;
|
||||
};
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>PlacementControl</class>
|
||||
<widget class="QDialog" name="PlacementControl">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>202</width>
|
||||
<height>72</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Adjust placement</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="1" column="0" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>All</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="offsetX">
|
||||
<property name="wrapping">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QSpinBox" name="offsetY">
|
||||
<property name="wrapping">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="accelerated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>-128</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>127</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" alignment="Qt::AlignRight">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Offset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>X</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2" alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string>Y</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
|
@ -42,6 +42,7 @@
|
|||
#include "OverrideView.h"
|
||||
#include "ObjView.h"
|
||||
#include "PaletteView.h"
|
||||
#include "PlacementControl.h"
|
||||
#include "PrinterView.h"
|
||||
#include "ROMInfo.h"
|
||||
#include "SensorView.h"
|
||||
|
@ -1445,6 +1446,11 @@ void Window::setupMenu(QMenuBar* menubar) {
|
|||
m_audioChannels = avMenu->addMenu(tr("Audio channels"));
|
||||
m_shortcutController->addMenu(m_audioChannels, avMenu);
|
||||
|
||||
QAction* placementControl = new QAction(tr("Adjust layer placement..."), avMenu);
|
||||
connect(placementControl, &QAction::triggered, openControllerTView<PlacementControl>());
|
||||
m_gameActions.append(placementControl);
|
||||
addControlledAction(avMenu, placementControl, "placementControl");
|
||||
|
||||
QMenu* toolsMenu = menubar->addMenu(tr("&Tools"));
|
||||
m_shortcutController->addMenu(toolsMenu);
|
||||
QAction* viewLogs = new QAction(tr("View &logs..."), toolsMenu);
|
||||
|
|
Loading…
Reference in New Issue