bsnes/hiro/windows/widget/canvas.cpp

193 lines
4.8 KiB
C++
Raw Normal View History

#if defined(Hiro_Canvas)
namespace hiro {
auto pCanvas::construct() -> void {
hwnd = CreateWindow(L"hiroWidget", L"", WS_CHILD, 0, 0, 0, 0, _parentHandle(), nullptr, GetModuleHandle(0), 0);
pWidget::construct();
update();
}
auto pCanvas::destruct() -> void {
DestroyWindow(hwnd);
}
auto pCanvas::minimumSize() const -> Size {
if(auto& icon = state().icon) return {(int)icon.width(), (int)icon.height()};
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
return {0, 0};
}
auto pCanvas::setAlignment(Alignment) -> void {
update();
}
auto pCanvas::setColor(Color color) -> void {
update();
}
auto pCanvas::setDroppable(bool droppable) -> void {
DragAcceptFiles(hwnd, droppable);
}
auto pCanvas::setFocusable(bool focusable) -> void {
//handled by windowProc()
}
auto pCanvas::setGeometry(Geometry geometry) -> void {
pWidget::setGeometry(geometry);
update();
}
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
auto pCanvas::setGradient(Gradient gradient) -> void {
update();
}
auto pCanvas::setIcon(const image& icon) -> void {
update();
}
auto pCanvas::update() -> void {
_rasterize();
_redraw();
}
//
auto pCanvas::doMouseLeave() -> void {
return self().doMouseLeave();
}
auto pCanvas::doMouseMove(int x, int y) -> void {
return self().doMouseMove({x, y});
}
auto pCanvas::windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) -> maybe<LRESULT> {
if(msg == WM_DROPFILES) {
if(auto paths = DropPaths(wparam)) self().doDrop(paths);
return false;
}
if(msg == WM_KEYDOWN || msg == WM_SYSKEYDOWN || msg == WM_KEYUP || msg == WM_SYSKEYUP) {
if(self().focusable()) return true;
}
if(msg == WM_GETDLGCODE) {
return DLGC_STATIC | DLGC_WANTCHARS;
}
if(msg == WM_ERASEBKGND || msg == WM_PAINT) {
_paint();
return msg == WM_ERASEBKGND;
}
if(msg == WM_LBUTTONDOWN) {
if(self().focusable()) setFocused();
}
return pWidget::windowProc(hwnd, msg, wparam, lparam);
}
//
auto pCanvas::_paint() -> void {
PAINTSTRUCT ps;
BeginPaint(hwnd, &ps);
int sx = 0, sy = 0, dx = 0, dy = 0;
int width = this->width;
int height = this->height;
auto geometry = self().geometry();
auto alignment = state().alignment ? state().alignment : Alignment{0.5, 0.5};
if(width <= geometry.width()) {
sx = 0;
dx = (geometry.width() - width) * alignment.horizontal();
} else {
sx = (width - geometry.width()) * alignment.horizontal();
dx = 0;
width = geometry.width();
}
if(height <= geometry.height()) {
sy = 0;
dy = (geometry.height() - height) * alignment.vertical();
} else {
sy = (height - geometry.height()) * alignment.vertical();
dy = 0;
height = geometry.height();
}
HDC hdc = CreateCompatibleDC(ps.hdc);
BITMAPINFO bmi{};
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biWidth = width;
bmi.bmiHeader.biHeight = -height; //GDI stores bitmaps upside now; negative height flips bitmap
bmi.bmiHeader.biSizeImage = width * height * sizeof(uint32_t);
void* bits = nullptr;
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
HBITMAP bitmap = CreateDIBSection(hdc, &bmi, DIB_RGB_COLORS, &bits, nullptr, 0);
if(bits) {
for(uint y : range(height)) {
auto source = (const uint8_t*)pixels.data() + (sy + y) * this->width * sizeof(uint32_t) + sx * sizeof(uint32_t);
auto target = (uint8_t*)bits + y * width * sizeof(uint32_t);
for(uint x : range(width)) {
target[0] = (source[0] * source[3]) / 255;
target[1] = (source[1] * source[3]) / 255;
target[2] = (source[2] * source[3]) / 255;
target[3] = (source[3]);
source += 4, target += 4;
}
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
}
}
SelectObject(hdc, bitmap);
RECT rc;
GetClientRect(hwnd, &rc);
DrawThemeParentBackground(hwnd, ps.hdc, &rc);
BLENDFUNCTION bf{AC_SRC_OVER, 0, (BYTE)255, AC_SRC_ALPHA};
AlphaBlend(ps.hdc, dx, dy, width, height, hdc, 0, 0, width, height, bf);
DeleteObject(bitmap);
DeleteDC(hdc);
EndPaint(hwnd, &ps);
}
auto pCanvas::_rasterize() -> void {
if(auto& icon = state().icon) {
width = icon.width();
height = icon.height();
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
} else {
width = self().geometry().width();
height = self().geometry().height();
}
if(width <= 0 || height <= 0) return;
pixels.reset();
pixels.resize(width * height);
if(auto& icon = state().icon) {
memory::copy<uint32_t>(pixels.data(), icon.data(), width * height);
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
} else if(auto& gradient = state().gradient) {
auto& colors = gradient.state.colors;
image fill;
fill.allocate(width, height);
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
memory::copy(pixels.data(), fill.data(), fill.size());
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
} else {
uint32_t color = state().color.value();
Update to v094r43 release. byuu says: Updated to compile with all of the new hiro changes. My next step is to write up hiro API documentation, and move the API from alpha (constantly changing) to beta (rarely changing), in preparation for the first stable release (backward-compatible changes only.) Added "--fullscreen" command-line option. I like this over a configuration file option. Lets you use the emulator in both modes without having to modify the config file each time. Also enhanced the command-line game loading. You can now use any of these methods: higan /path/to/game-folder.sfc higan /path/to/game-folder.sfc/ higan /path/to/game-folder.sfc/program.rom The idea is to support launchers that insist on loading files only. Technically, the file can be any name (manifest.bml also works); the only criteria is that the file actually exists and is a file, and not a directory. This is a requirement to support the first version (a directory lacking the trailing / identifier), because I don't want my nall::string class to query the file system to determine if the string is an actual existing file or directory for its pathname() / dirname() functions. Anyway, every game folder I've made so far has program.rom, and that's very unlikely to change, so this should be fine. Now, of course, if you drop a regular "game.sfc" file on the emulator, it won't even try to load it, unless it's in a folder that ends in .fc, .sfc, etc. In which case, it'll bail out immediately by being unable to produce a manifest for what is obviously not really a game folder.
2015-08-30 02:08:26 +00:00
for(auto& pixel : pixels) pixel = color;
}
}
auto pCanvas::_redraw() -> void {
InvalidateRect(hwnd, 0, false);
}
}
#endif