Files
oboe/src/scenedit/scen.locpicker.cpp
Celtic Minstrel 3d48cb14e7 Add an SDF picker for selecting a stuff done flag and optionally giving it a name.
In effect, this is a combination of two of the previous pickers:
the location picker, and the editable string picker.

This required quite a significant rework of how the tilemap places its children.

Currently it's only used in special node editing.
I plan to add its use in many other places too though.
2025-03-02 19:13:01 -05:00

131 lines
3.7 KiB
C++

//
// scen.locpicker.cpp
// BoE
//
// Created by Celtic Minstrel on 2025-02-28.
//
#include "scen.locpicker.hpp"
#include "dialogxml/widgets/pict.hpp"
#include "dialogxml/widgets/tilemap.hpp"
#include "scenario/area.hpp"
#include "scenario/scenario.hpp"
#include "fileio/resmgr/res_dialog.hpp"
extern cScenario scenario;
cLocationPicker::cLocationPicker(location loc, cArea& area, const std::string& title, cDialog* parent)
: initial_loc(loc)
, chosen_loc(loc)
, area(&area)
, dlog(*ResMgr::dialogs.get("choose-location"), parent)
{
clamp_loc();
map = dynamic_cast<cTilemap*>(&dlog["map"]);
fill_terrain();
handle_scroll(""); // Hide unusable scroll buttons
dlog["switch"].hide();
setTitle(title);
using namespace std::placeholders;
dlog.attachClickHandlers(std::bind(&cLocationPicker::handle_close, this, _2), {"done", "cancel"});
dlog.attachClickHandlers(std::bind(&cLocationPicker::handle_scroll, this, _2), {"up", "down", "left", "right"});
map->attachClickHandlers(std::bind(&cLocationPicker::handle_select, this, _2), "");
}
void cLocationPicker::clamp_loc() {
chosen_loc.x = minmax(0, area->max_dim - 1, chosen_loc.x);
chosen_loc.y = minmax(0, area->max_dim - 1, chosen_loc.y);
viewport.x = 18 * floor(chosen_loc.x / 18.0);
viewport.y = 18 * floor(chosen_loc.y / 18.0);
}
void cLocationPicker::setArea(cArea& newArea) {
area = &newArea;
clamp_loc();
fill_terrain();
}
void cLocationPicker::setTitle(const std::string& title) {
dlog["prompt"].setText(title);
}
void cLocationPicker::fill_terrain() {
for(int x = 0; x < 18; x++) {
for(int y = 0; y < 18; y++) {
auto& pict = dynamic_cast<cPict&>(map->getChild(x, y));
location ter_loc = viewport;
ter_loc.x += x;
ter_loc.y += y;
if(ter_loc.x >= area->max_dim || ter_loc.y >= area->max_dim) pict.setPict(74);
else {
ter_num_t ter = area->terrain[ter_loc.x][ter_loc.y];
pict.setPict(scenario.ter_types[ter].map_pic);
}
}
}
place_pointer();
}
void cLocationPicker::place_pointer() {
if(chosen_loc.x >= viewport.x && chosen_loc.x < viewport.x + 18 && chosen_loc.y >= viewport.y && chosen_loc.y < viewport.y + 18) {
location relative_loc = chosen_loc;
relative_loc.x -= viewport.x;
relative_loc.y -= viewport.y;
location ctrlPos = map->getCellPos(relative_loc.x, relative_loc.y);
ctrlPos.x += 3;
ctrlPos.y += 3;
dlog["zpointer"].relocate(ctrlPos);
dlog["zpointer"].show();
} else {
dlog["zpointer"].hide();
}
}
bool cLocationPicker::handle_close(std::string item_hit) {
dlog.toast(item_hit == "done");
return true;
}
bool cLocationPicker::handle_scroll(std::string item_hit) {
if(item_hit == "up") {
if(viewport.y > 0) viewport.y -= 9;
} else if(item_hit == "down") {
if(viewport.y < area->max_dim - 18) viewport.y += 9;
} else if(item_hit == "left") {
if(viewport.x > 0) viewport.x -= 9;
} else if(item_hit == "right") {
if(viewport.x < area->max_dim - 18) viewport.x += 9;
}
if(viewport.x == 0) dlog["left"].hide();
else dlog["left"].show();
if(viewport.y == 0) dlog["up"].hide();
else dlog["up"].show();
if(viewport.x >= area->max_dim - 18) dlog["right"].hide();
else dlog["right"].show();
if(viewport.y >= area->max_dim - 18) dlog["down"].hide();
else dlog["down"].show();
fill_terrain();
return true;
}
bool cLocationPicker::handle_select(std::string item_hit) {
location clickedLoc = map->getCellIdx(dlog[item_hit]);
location check{viewport.x + clickedLoc.x, viewport.y + clickedLoc.y};
if(check.x < area->max_dim && check.y < area->max_dim) {
chosen_loc = check;
place_pointer();
}
return true;
}
location cLocationPicker::run() {
dlog.run();
if(dlog.accepted()) return chosen_loc;
return initial_loc;
}
cDialog* cLocationPicker::operator->() {
return &dlog;
}