forked from townforge/townforge
game: new better selection render code
This commit is contained in:
parent
a0151f3322
commit
ba37b600e1
@ -440,63 +440,33 @@ void CityMeshSection::setHighlight(const Selection &selection, const std::shared
|
||||
rebuild_flags.insert(map->get_flag(under_construction_flag_id));
|
||||
under_construction_flag_id = id;
|
||||
}
|
||||
Selection local_selection = selection;
|
||||
local_selection.set_intersection(vx0, vy0, vx1, vy1);
|
||||
if (local_selection != current_selection)
|
||||
{
|
||||
if (!current_selection.is_empty())
|
||||
{
|
||||
std::set<std::shared_ptr<Flag>> res;
|
||||
map->get_flags(current_selection.x0, current_selection.y0, current_selection.x1, current_selection.y1, res);
|
||||
for (const std::shared_ptr<Flag> &flag: res)
|
||||
rebuild_flags.insert(flag);
|
||||
}
|
||||
current_selection = local_selection;
|
||||
if (!current_selection.is_empty())
|
||||
{
|
||||
std::set<std::shared_ptr<Flag>> res;
|
||||
map->get_flags(current_selection.x0, current_selection.y0, current_selection.x1, current_selection.y1, res);
|
||||
for (const std::shared_ptr<Flag> &flag: res)
|
||||
rebuild_flags.insert(flag);
|
||||
}
|
||||
if (selected_flag)
|
||||
rebuild_flags.insert(selected_flag);
|
||||
}
|
||||
if (!rebuild_flags.empty())
|
||||
{
|
||||
RebuildFlags(rebuild_flags, false);
|
||||
RebuildFlags(rebuild_flags, local_selection, false);
|
||||
}
|
||||
|
||||
if (!forceHighlightRefresh && !flagUnderConstruction)
|
||||
if (selection == current_selection)
|
||||
return;
|
||||
|
||||
ResourceCache* cache = node->GetSubsystem<ResourceCache>();
|
||||
std::set<std::shared_ptr<Flag>> flags;
|
||||
map->get_flags(vx0, vy0, vx1, vy1, flags);
|
||||
for (const std::shared_ptr<Flag> &flag: flags)
|
||||
{
|
||||
const bool ignore = game->ignore_flag(flag->id);
|
||||
|
||||
const uint32_t fy0 = std::max(flag->y0, vy0);
|
||||
const uint32_t fy1 = std::min(flag->y1, vy1);
|
||||
for (uint32_t y = fy0; y <= fy1; ++y)
|
||||
{
|
||||
const uint32_t fx0 = std::max(flag->x0, vx0);
|
||||
const uint32_t fx1 = std::min(flag->x1, vx1);
|
||||
for (uint32_t x = fx0; x <= fx1; ++x)
|
||||
{
|
||||
const bool was_selected = current_selection.is_selected(x, y);
|
||||
const bool selected = selection.is_selected(x, y);
|
||||
if (was_selected == selected && !forceHighlightRefresh)
|
||||
continue;
|
||||
|
||||
const uint16_t th = ignore ? 0u : flag->get_tile_height(x, y);
|
||||
for (uint32_t h = 0; h < th; ++h)
|
||||
{
|
||||
auto &tile = nodes[y - vy0][x - vx0].blocks[h];
|
||||
if (!tile.node)
|
||||
continue;
|
||||
StaticModel *model = tile.node->GetComponent<BlockModel>();
|
||||
if (!model)
|
||||
continue;
|
||||
{
|
||||
SharedPtr<Material> material;
|
||||
|
||||
const uint8_t type = flag->get_tile_type(x, y, h);
|
||||
MaterialVersion mv = selected ? MVSelected : MVNormal;
|
||||
if (!selected && tile.is_new)
|
||||
{
|
||||
mv = MVNew;
|
||||
flagsWithNew.insert(flag->id);
|
||||
}
|
||||
material = resources.materials[mv][get_material_for_block(flag, type, h)];
|
||||
model->SetMaterial(material);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
current_selection = selection;
|
||||
forceHighlightRefresh = false;
|
||||
}
|
||||
|
||||
@ -525,7 +495,7 @@ void CityMeshSection::buildMap()
|
||||
|
||||
std::set<std::shared_ptr<Flag>> flags;
|
||||
game->map.get_flags(vx0, vy0, vx1, vy1, flags);
|
||||
RebuildFlags(flags, false);
|
||||
RebuildFlags(flags, {}, false);
|
||||
|
||||
blocksNode->SetParent(selectableNode);
|
||||
|
||||
@ -657,14 +627,6 @@ static StaticModel *create_area(Node *node, Material *material, uint32_t fx0, ui
|
||||
return model;
|
||||
}
|
||||
|
||||
static bool is_selection_in_flag(const Selection &sel, const std::shared_ptr<Flag> &flag)
|
||||
{
|
||||
if (!flag || sel.is_empty())
|
||||
return false;
|
||||
uint32_t d = cc::get_distance(flag->x0, flag->y0, flag->x1, flag->y1, sel.x0, sel.y0, sel.x1, sel.y1);
|
||||
return d == 0;
|
||||
}
|
||||
|
||||
void CityMeshSection::GetFlags(std::set<uint32_t> &flags) const
|
||||
{
|
||||
for (const auto &e: blockNodes)
|
||||
@ -692,7 +654,7 @@ void CityMeshSection::ClearFlags(const std::set<uint32_t> &flags)
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
void CityMeshSection::RebuildFlags(const C &flags, const Selection &selection, bool highlight_new)
|
||||
{
|
||||
if (!game)
|
||||
return;
|
||||
@ -782,31 +744,15 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
const uint32_t fx1 = std::min(flag->x1, vx1);
|
||||
const bool origin_in_section = fx0 == flag->x0 && fy0 == flag->y0;
|
||||
|
||||
auto check_new_blocks = [fx0, fy0, fx1, fy1, &flag, this](bool highlight_new)
|
||||
{
|
||||
for (uint32_t y = fy0; y <= fy1; ++y)
|
||||
{
|
||||
for (uint32_t x = fx0; x <= fx1; ++x)
|
||||
{
|
||||
const uint16_t th = flag->get_tile_height(x, y);
|
||||
const uint16_t prevth = nodes[y - vy0][x - vx0].blocks.size();
|
||||
const bool is_new = th > prevth;
|
||||
if (highlight_new && is_new)
|
||||
return true;
|
||||
for (const auto &e: nodes[y - vy0][x - vx0].blocks)
|
||||
if (e.is_new)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
bool has_new = check_new_blocks(highlight_new);
|
||||
const uint32_t tile_width = flag->x1 - flag->x0 + 1;
|
||||
const uint32_t w = fx1 - fx0 + 1;
|
||||
const uint32_t h = fy1 - fy0 + 1;
|
||||
const ::Tile* tiles = flag->get_raw_tiles();
|
||||
const uint32_t dx0 = fx0 - flag->x0;
|
||||
const uint32_t dx1 = flag->x1 - fx1;
|
||||
const uint32_t dy0 = fy0 - flag->y0;
|
||||
|
||||
RenderMode flagRenderMode = renderMode;
|
||||
if (has_new)
|
||||
flagRenderMode = RenderCubeModels;
|
||||
else if (flag->owner == game->playerState.id && ((!!under_construction_flag_id && under_construction_flag_id == flag->id) || !under_construction_flag_id) && is_selection_in_flag(current_selection, flag))
|
||||
flagRenderMode = RenderCubeModels;
|
||||
const RenderMode flagRenderMode = renderMode;
|
||||
|
||||
SharedPtr<Node> parent;
|
||||
auto it = blockNodes.find(flag->id);
|
||||
@ -847,14 +793,17 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
}
|
||||
|
||||
std::vector<std::vector<uint8_t>> front_spans, back_spans, left_spans, right_spans, bottom_spans, top_spans;
|
||||
std::vector<std::vector<uint8_t>> sel_front_spans, sel_back_spans, sel_left_spans, sel_right_spans, sel_bottom_spans, sel_top_spans;
|
||||
std::vector<std::vector<uint8_t>> new_front_spans, new_back_spans, new_left_spans, new_right_spans, new_bottom_spans, new_top_spans;
|
||||
uint32_t max_height = 0;
|
||||
if (flagRenderMode == RenderSpanningColumns || flagRenderMode == RenderSpanningRectangles)
|
||||
{
|
||||
for (uint32_t y = fy0; y <= fy1; ++y)
|
||||
uint32_t tile_idx = dx0 + dy0 * tile_width;
|
||||
for (uint32_t y = fy0; y <= fy1; ++y, tile_idx += dx0 + dx1)
|
||||
{
|
||||
for (uint32_t x = fx0; x <= fx1; ++x)
|
||||
for (uint32_t x = fx0; x <= fx1; ++x, ++tile_idx)
|
||||
{
|
||||
const uint16_t th = flag->get_tile_height(x, y);
|
||||
const uint16_t th = tiles[tile_idx].get_height();
|
||||
if (th > max_height)
|
||||
max_height = th;
|
||||
}
|
||||
@ -867,69 +816,91 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
right_spans.resize(width);
|
||||
bottom_spans.resize(max_height);
|
||||
top_spans.resize(max_height);
|
||||
sel_front_spans.resize(height);
|
||||
sel_back_spans.resize(height);
|
||||
sel_left_spans.resize(width);
|
||||
sel_right_spans.resize(width);
|
||||
sel_bottom_spans.resize(max_height);
|
||||
sel_top_spans.resize(max_height);
|
||||
new_front_spans.resize(height);
|
||||
new_back_spans.resize(height);
|
||||
new_left_spans.resize(width);
|
||||
new_right_spans.resize(width);
|
||||
new_bottom_spans.resize(max_height);
|
||||
new_top_spans.resize(max_height);
|
||||
}
|
||||
|
||||
const bool ignore = game->ignore_flag(flag->id);
|
||||
|
||||
for (uint32_t y = fy0; y <= fy1; ++y)
|
||||
uint32_t tile_idx = dx0 + dy0 * tile_width;
|
||||
for (uint32_t y = fy0; y <= fy1; ++y, tile_idx += dx0 + dx1)
|
||||
{
|
||||
for (uint32_t x = fx0; x <= fx1; ++x)
|
||||
for (uint32_t x = fx0; x <= fx1; ++x, ++tile_idx)
|
||||
{
|
||||
const uint16_t th = ignore ? 0u : flag->get_tile_height(x, y);
|
||||
const uint16_t prevth = nodes[y - vy0][x - vx0].blocks.size();
|
||||
auto &node = nodes[y - vy0][x - vx0];
|
||||
const uint16_t th = ignore ? 0u : tiles[tile_idx].get_height();
|
||||
const uint16_t prevth = node.blocks.size();
|
||||
if (highlight_new && th > prevth)
|
||||
has_new = true;
|
||||
maxh = std::max(maxh, th);
|
||||
if (th < prevth)
|
||||
{
|
||||
for (uint32_t h = th; h < prevth; ++h)
|
||||
if (nodes[y - vy0][x - vx0].blocks[h].node)
|
||||
nodes[y - vy0][x - vx0].blocks[h].node->Remove();
|
||||
if (node.blocks[h].node)
|
||||
node.blocks[h].node->Remove();
|
||||
}
|
||||
nodes[y - vy0][x - vx0].blocks.resize(th);
|
||||
node.blocks.resize(th);
|
||||
const bool is_selected = selection.is_selected(x, y);
|
||||
for (uint32_t h = 0; h < th; ++h)
|
||||
{
|
||||
++n_total;
|
||||
const uint8_t type = flag->get_tile_type(x, y, h);
|
||||
const uint8_t type = tiles[tile_idx].get_type(h);
|
||||
const uint16_t material_type = get_material_for_block(flag, type, h);
|
||||
bool hidden = type == 0;
|
||||
bool bottom_hidden = false, top_hidden = false, left_hidden = false, right_hidden = false, front_hidden = false, back_hidden = false;
|
||||
if (!hidden)
|
||||
{
|
||||
bottom_hidden = h == 0 || flag->get_tile_type(x, y, h-1) != 0;
|
||||
top_hidden = h+1 < th && flag->get_tile_type(x, y, h+1) != 0;
|
||||
left_hidden = x > flag->x0 && flag->get_tile_height(x-1, y) > h && flag->get_tile_type(x-1, y, h) != 0;
|
||||
right_hidden = x < flag->x1 && flag->get_tile_height(x+1, y) > h && flag->get_tile_type(x+1, y, h) != 0;
|
||||
front_hidden = y > flag->y0 && flag->get_tile_height(x, y-1) > h && flag->get_tile_type(x, y-1, h) != 0;
|
||||
back_hidden = y < flag->y1 && flag->get_tile_height(x, y+1) > h && flag->get_tile_type(x, y+1, h) != 0;
|
||||
bottom_hidden = h == 0 || tiles[tile_idx].get_type(h-1) != 0;
|
||||
top_hidden = h+1 < th && tiles[tile_idx].get_type(h+1) != 0;
|
||||
left_hidden = x > flag->x0 && tiles[tile_idx-1].get_height() > h && tiles[tile_idx-1].get_type(h) != 0;
|
||||
right_hidden = x < flag->x1 && tiles[tile_idx+1].get_height() > h && tiles[tile_idx+1].get_type(h) != 0;
|
||||
front_hidden = y > flag->y0 && tiles[tile_idx - tile_width].get_height() > h && tiles[tile_idx - tile_width].get_type(h) != 0;
|
||||
back_hidden = y < flag->y1 && tiles[tile_idx + tile_width].get_height() > h && tiles[tile_idx + tile_width].get_type(h) != 0;
|
||||
hidden = bottom_hidden && top_hidden && left_hidden && right_hidden && front_hidden && back_hidden;
|
||||
}
|
||||
|
||||
if (node.blocks[h].is_new)
|
||||
has_new = true;
|
||||
|
||||
if (hidden)
|
||||
{
|
||||
++n_hidden;
|
||||
if (nodes[y - vy0][x - vx0].blocks[h].node)
|
||||
nodes[y - vy0][x - vx0].blocks[h].node->Remove();
|
||||
nodes[y - vy0][x - vx0].blocks[h] = {NULL, type, false};
|
||||
if (node.blocks[h].node)
|
||||
node.blocks[h].node->Remove();
|
||||
node.blocks[h] = {NULL, type, false};
|
||||
continue;
|
||||
}
|
||||
|
||||
if (flagRenderMode == RenderCubeModels)
|
||||
{
|
||||
if (nodes[y - vy0][x - vx0].blocks[h].material == type && nodes[y - vy0][x - vx0].blocks[h].node)
|
||||
if (node.blocks[h].material == type && node.blocks[h].node)
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (nodes[y - vy0][x - vx0].blocks[h].node)
|
||||
if (node.blocks[h].node)
|
||||
{
|
||||
nodes[y - vy0][x - vx0].blocks[h].node->Remove();
|
||||
nodes[y - vy0][x - vx0].blocks[h].node = NULL;
|
||||
node.blocks[h].node->Remove();
|
||||
node.blocks[h].node = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
const bool is_new = highlight_new && h >= prevth;
|
||||
if (is_new)
|
||||
has_new = true;
|
||||
const MaterialVersion mv = is_new ? MVNew : MVNormal;
|
||||
SharedPtr<BlockModel> blockObject;
|
||||
if (!nodes[y - vy0][x - vx0].blocks[h].node)
|
||||
if (!node.blocks[h].node)
|
||||
{
|
||||
switch (flagRenderMode)
|
||||
{
|
||||
@ -1013,28 +984,28 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
blockObject = blockNode->CreateComponent<BlockModel>();
|
||||
blockObject->SetModel(resources.block8Model, true);
|
||||
blockObject->SetMaterial(resources.materials[mv][material_type]);
|
||||
nodes[y - vy0][x - vx0].blocks[h].node = std::move(blockNode);
|
||||
node.blocks[h].node = std::move(blockNode);
|
||||
break;
|
||||
}
|
||||
case RenderSpanningColumns:
|
||||
case RenderSpanningRectangles:
|
||||
{
|
||||
if (!front_hidden) add_span(front_spans, x - fx0, y - fy0, h, fx1-fx0+1, max_height, material_type);
|
||||
if (!left_hidden) add_span(left_spans, y - fy0, x - fx0, h, fy1-fy0+1, max_height, material_type);
|
||||
if (!back_hidden) add_span(back_spans, x - fx0, y - fy0, h, fx1-fx0+1, max_height, material_type);
|
||||
if (!right_hidden) add_span(right_spans, y - fy0, x - fx0, h, fy1-fy0+1, max_height, material_type);
|
||||
if (!bottom_hidden) add_span(bottom_spans, y - fy0, h, x - fx0, fy1-fy0+1, fx1-fx0+1, material_type);
|
||||
if (!top_hidden) add_span(top_spans, y - fy0, h, x - fx0, fy1-fy0+1, fx1-fx0+1, material_type);
|
||||
if (!front_hidden) add_span(is_new ? new_front_spans : is_selected ? sel_front_spans : front_spans, x - fx0, y - fy0, h, fx1-fx0+1, max_height, material_type);
|
||||
if (!left_hidden) add_span(is_new ? new_left_spans : is_selected ? sel_left_spans : left_spans, y - fy0, x - fx0, h, fy1-fy0+1, max_height, material_type);
|
||||
if (!back_hidden) add_span(is_new ? new_back_spans : is_selected ? sel_back_spans : back_spans, x - fx0, y - fy0, h, fx1-fx0+1, max_height, material_type);
|
||||
if (!right_hidden) add_span(is_new ? new_right_spans : is_selected ? sel_right_spans : right_spans, y - fy0, x - fx0, h, fy1-fy0+1, max_height, material_type);
|
||||
if (!bottom_hidden) add_span(is_new ? new_bottom_spans : is_selected ? sel_bottom_spans : bottom_spans, y - fy0, h, x - fx0, fy1-fy0+1, fx1-fx0+1, material_type);
|
||||
if (!top_hidden) add_span(is_new ? new_top_spans : is_selected ? sel_top_spans : top_spans, y - fy0, h, x - fx0, fy1-fy0+1, fx1-fx0+1, material_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
blockObject = nodes[y - vy0][x - vx0].blocks[h].node->GetComponent<BlockModel>();
|
||||
blockObject = node.blocks[h].node->GetComponent<BlockModel>();
|
||||
if (blockObject)
|
||||
blockObject->SetMaterial(resources.materials[mv][material_type]);
|
||||
nodes[y - vy0][x - vx0].blocks[h].material = material_type;
|
||||
nodes[y - vy0][x - vx0].blocks[h].is_new = is_new;
|
||||
node.blocks[h].material = material_type;
|
||||
node.blocks[h].is_new = is_new;
|
||||
if (blockObject)
|
||||
blockObject->SetCastShadows(true);
|
||||
|
||||
@ -1046,19 +1017,24 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
if (flagRenderMode == RenderSpanningRectangles || flagRenderMode == RenderSpanningColumns)
|
||||
{
|
||||
std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> rectangles;
|
||||
const struct
|
||||
struct span_t
|
||||
{
|
||||
const char *name;
|
||||
const std::vector<std::vector<uint8_t>> &spans;
|
||||
const std::vector<std::vector<uint8_t>> &sel_spans;
|
||||
const std::vector<std::vector<uint8_t>> &new_spans;
|
||||
std::function<bool(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, bool,
|
||||
const std::vector<uint8_t>&, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>>&)> rectanglizer;
|
||||
std::function<void(std::vector<float>&, std::vector<uint32_t>&,
|
||||
uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, float)> add_face;
|
||||
} spans[] =
|
||||
};
|
||||
const span_t spans[] =
|
||||
{
|
||||
{
|
||||
"Front",
|
||||
front_spans,
|
||||
sel_front_spans,
|
||||
new_front_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fx1 - fx0 + 1;
|
||||
@ -1077,6 +1053,8 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
{
|
||||
"Left",
|
||||
left_spans,
|
||||
sel_left_spans,
|
||||
new_left_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fy1 - fy0 + 1;
|
||||
@ -1095,6 +1073,8 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
{
|
||||
"Back",
|
||||
back_spans,
|
||||
sel_back_spans,
|
||||
new_back_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fx1 - fx0 + 1;
|
||||
@ -1113,6 +1093,8 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
{
|
||||
"Right",
|
||||
right_spans,
|
||||
sel_right_spans,
|
||||
new_right_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fy1 - fy0 + 1;
|
||||
@ -1131,6 +1113,8 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
{
|
||||
"Bottom",
|
||||
bottom_spans,
|
||||
sel_bottom_spans,
|
||||
new_bottom_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fy1 - fy0 + 1;
|
||||
@ -1149,6 +1133,8 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
{
|
||||
"Top",
|
||||
top_spans,
|
||||
sel_top_spans,
|
||||
new_top_spans,
|
||||
[](uint32_t fx0, uint32_t fy0, uint32_t fx1, uint32_t fy1, uint32_t max_height, bool vertical_only,
|
||||
const std::vector<uint8_t> &span, std::vector<std::tuple<uint32_t, uint32_t, uint32_t, uint32_t, uint8_t>> &rectangles) {
|
||||
const uint32_t span_width = fy1 - fy0 + 1;
|
||||
@ -1166,24 +1152,15 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
},
|
||||
};
|
||||
|
||||
for (const auto &e: spans)
|
||||
auto process_span = [&](const span_t &e, size_t i, const std::vector<uint8_t> &span, MaterialVersion material_version)
|
||||
{
|
||||
for (size_t i = 0; i < e.spans.size(); ++i)
|
||||
{
|
||||
const auto &span = e.spans[i];
|
||||
if (span.empty())
|
||||
continue;
|
||||
uint32_t n_tiles = 0;
|
||||
for (const auto &hit: span)
|
||||
if (hit)
|
||||
++n_tiles;
|
||||
if (!e.rectanglizer(fx0, fy0, fx1, fy1, max_height, flagRenderMode == RenderSpanningColumns, span, rectangles))
|
||||
printf("Rectanglizer failure !!!\n");
|
||||
for (const auto &r: rectangles)
|
||||
{
|
||||
const uint8_t material_type = std::get<4>(r);
|
||||
std::vector<float> &vdata = vertex_data[material_type][MVNormal];
|
||||
std::vector<uint32_t> &idata = index_data[material_type][MVNormal];
|
||||
std::vector<float> &vdata = vertex_data[material_type][material_version];
|
||||
std::vector<uint32_t> &idata = index_data[material_type][material_version];
|
||||
const uint32_t rx0 = std::get<0>(r);
|
||||
const uint32_t ry0 = std::get<1>(r);
|
||||
const uint32_t rx_span = std::get<2>(r);
|
||||
@ -1192,7 +1169,19 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
if (vdata.size() > 65535)
|
||||
indices_fit_in_16_bits = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (const auto &e: spans)
|
||||
{
|
||||
for (size_t i = 0; i < e.spans.size(); ++i)
|
||||
if (!e.spans[i].empty())
|
||||
process_span(e, i, e.spans[i], MVNormal);
|
||||
for (size_t i = 0; i < e.sel_spans.size(); ++i)
|
||||
if (!e.sel_spans[i].empty())
|
||||
process_span(e, i, e.sel_spans[i], MVSelected);
|
||||
for (size_t i = 0; i < e.new_spans.size(); ++i)
|
||||
if (!e.new_spans[i].empty())
|
||||
process_span(e, i, e.new_spans[i], MVNew);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1246,7 +1235,7 @@ void CityMeshSection::RebuildFlags(const C &flags, bool highlight_new)
|
||||
MINFO("Mesh with " << ncubes << " cubes: generated in " << (t1-t0)/1e6 << " seconds for render mode " << renderMode << " (" << n_hidden << "/" << n_total << " hidden blocks");
|
||||
}
|
||||
|
||||
void CityMeshSection::Update(float timeStep, bool mark_new_block)
|
||||
void CityMeshSection::Update(float timeStep, const Selection &selection, bool mark_new_block)
|
||||
{
|
||||
if (mark_new_block)
|
||||
{
|
||||
@ -1303,7 +1292,7 @@ void CityMeshSection::Update(float timeStep, bool mark_new_block)
|
||||
}
|
||||
}
|
||||
if (!rebuild_flags.empty())
|
||||
RebuildFlags(rebuild_flags, false);
|
||||
RebuildFlags(rebuild_flags, selection, false);
|
||||
flagsWithNew.clear();
|
||||
}
|
||||
}
|
||||
@ -1537,7 +1526,7 @@ void CityMeshSection::updateHeightMap()
|
||||
*/
|
||||
}
|
||||
|
||||
void CityMeshUrho3D::Update(float timeStep, bool mark_new_block)
|
||||
void CityMeshUrho3D::Update(float timeStep, const Selection &selection, bool mark_new_block)
|
||||
{
|
||||
time += timeStep;
|
||||
float pulseIntensity = (sinf(time * 10) + 1) / 2;
|
||||
@ -1563,7 +1552,7 @@ void CityMeshUrho3D::Update(float timeStep, bool mark_new_block)
|
||||
for (int y = 0; y < NUM_CITY_SECTIONS; ++y)
|
||||
for (int x = 0; x < NUM_CITY_SECTIONS; ++x)
|
||||
if (sections[x][y])
|
||||
sections[x][y]->Update(timeStep, mark_new_block);
|
||||
sections[x][y]->Update(timeStep, selection, mark_new_block);
|
||||
}
|
||||
|
||||
void CityMeshUrho3D::SetView(const Vector3 &pos)
|
||||
@ -1690,7 +1679,7 @@ void CityMeshUrho3D::ClearFlags(const std::set<uint32_t> &flags)
|
||||
}
|
||||
|
||||
template<typename C>
|
||||
void CityMeshUrho3D::RebuildFlags(const C &flags, bool highlight_new)
|
||||
void CityMeshUrho3D::RebuildFlags(const C &flags, const Selection &selection, bool highlight_new)
|
||||
{
|
||||
if (!game || flags.empty())
|
||||
return;
|
||||
@ -1700,7 +1689,7 @@ void CityMeshUrho3D::RebuildFlags(const C &flags, bool highlight_new)
|
||||
for (int y = 0; y < NUM_CITY_SECTIONS; ++y)
|
||||
for (int x = 0; x < NUM_CITY_SECTIONS; ++x)
|
||||
if (sections[x][y])
|
||||
sections[x][y]->RebuildFlags(flags, highlight_new);
|
||||
sections[x][y]->RebuildFlags(flags, selection, highlight_new);
|
||||
|
||||
const uint64_t t1 = get_us();
|
||||
MINFO(flags.size() << " flags rebuilt in " << (t1-t0)/1e6<< " seconds");
|
||||
@ -1735,7 +1724,7 @@ void CityMeshUrho3D::GetBlockTextures(std::map<uint8_t, std::map<uint16_t, std::
|
||||
}
|
||||
}
|
||||
|
||||
template void CityMeshSection::RebuildFlags(const std::deque<std::shared_ptr<Flag>> &flags, bool highlight_new);
|
||||
template void CityMeshUrho3D::RebuildFlags(const std::deque<std::shared_ptr<Flag>> &flags, bool highlight_new);
|
||||
template void CityMeshSection::RebuildFlags(const std::set<std::shared_ptr<Flag>> &flags, bool highlight_new);
|
||||
template void CityMeshUrho3D::RebuildFlags(const std::set<std::shared_ptr<Flag>> &flags, bool highlight_new);
|
||||
template void CityMeshSection::RebuildFlags(const std::deque<std::shared_ptr<Flag>> &flags, const Selection &selection, bool highlight_new);
|
||||
template void CityMeshUrho3D::RebuildFlags(const std::deque<std::shared_ptr<Flag>> &flags, const Selection &selection, bool highlight_new);
|
||||
template void CityMeshSection::RebuildFlags(const std::set<std::shared_ptr<Flag>> &flags, const Selection &selection, bool highlight_new);
|
||||
template void CityMeshUrho3D::RebuildFlags(const std::set<std::shared_ptr<Flag>> &flags, const Selection &selection, bool highlight_new);
|
||||
|
@ -85,12 +85,12 @@ public:
|
||||
void setDisplayMode(DisplayMode mode);
|
||||
void setRenderMode(RenderMode mode);
|
||||
void setGroundMode(GroundMode mode);
|
||||
void Update(float timeStep, bool mark_new_block);
|
||||
void Update(float timeStep, const Selection &selection, bool mark_new_block);
|
||||
void setView(uint32_t vx0, uint32_t vy0, uint32_t vx1, uint32_t vy1);
|
||||
void setCameraPos(const Urho3D::Vector3 &pos);
|
||||
void GetFlags(std::set<uint32_t> &flags) const;
|
||||
void ClearFlags(const std::set<uint32_t> &flags);
|
||||
template<typename C> void RebuildFlags(const C &flags, bool highlight_new);
|
||||
template<typename C> void RebuildFlags(const C &flags, const Selection &selection, bool highlight_new);
|
||||
bool hasFlagsWithNew() const { return !flagsWithNew.empty(); }
|
||||
|
||||
private:
|
||||
@ -149,11 +149,11 @@ public:
|
||||
void setHighlight(const Selection &selection, const std::shared_ptr<Flag> &hoverFlag, const std::shared_ptr<Flag> &selectedFlag, const boost::optional<std::tuple<uint32_t, std::vector<uint16_t>, std::vector<std::vector<uint8_t>>>> &flagUnderConstruction, uint32_t mouse_x, uint32_t mouse_y, uint32_t mouse_h, uint32_t top_x, uint32_t top_y, uint32_t top_h);
|
||||
void setDisplayMode(DisplayMode mode);
|
||||
void setRenderMode(RenderMode mode);
|
||||
void Update(float timeStep, bool mark_new_block = false);
|
||||
void Update(float timeStep, const Selection &selection, bool mark_new_block = false);
|
||||
void SetView(const Urho3D::Vector3 &pos);
|
||||
void GetFlags(std::set<uint32_t> &flags) const;
|
||||
void ClearFlags(const std::set<uint32_t> &flags);
|
||||
template<typename C> void RebuildFlags(const C &flags, bool highlight_new);
|
||||
template<typename C> void RebuildFlags(const C &flags, const Selection &selection, bool highlight_new);
|
||||
DisplayMode getDisplayMode() const { return displayMode; }
|
||||
RenderMode getRenderMode() const { return renderMode; }
|
||||
bool hasFlagsWithNew() const;
|
||||
|
@ -981,7 +981,6 @@ void CryptoCityUrho3D::HandleMouseButtonDown(StringHash eventType, VariantMap& e
|
||||
}
|
||||
selection.set_rectangle(sx0, sy0, sx1, sy1);
|
||||
hasSelection_ = true;
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
|
||||
if (camera_)
|
||||
camera_->set_target(point);
|
||||
@ -990,7 +989,6 @@ void CryptoCityUrho3D::HandleMouseButtonDown(StringHash eventType, VariantMap& e
|
||||
{
|
||||
selection.clear();
|
||||
hasSelection_ = false;
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1046,7 +1044,6 @@ void CryptoCityUrho3D::UpdateTargetting()
|
||||
selection.set_rectangle(sx0, sy0, sx1, sy1);
|
||||
if (editMode == EM_SELECT_ELLIPSE)
|
||||
selection.make_circular();
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), hover_flag, GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
if (!hover_flag)
|
||||
{
|
||||
@ -1387,7 +1384,7 @@ void CryptoCityUrho3D::RebuildMap()
|
||||
current_flags.erase(f->id);
|
||||
if (!current_flags.empty())
|
||||
cityMesh->ClearFlags(current_flags);
|
||||
cityMesh->RebuildFlags(res, false);
|
||||
cityMesh->RebuildFlags(res, GetEffectiveSelection(), false);
|
||||
gameState.clear_dirty_flags();
|
||||
mark_new_block = true;
|
||||
}
|
||||
@ -1655,13 +1652,11 @@ void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
// Take the frame time step, which is stored as a float
|
||||
float timeStep = eventData[P_TIMESTEP].GetFloat();
|
||||
|
||||
// Move the camera, scale movement with time step
|
||||
MoveCamera(timeStep);
|
||||
|
||||
cityMesh->SetView(cameraNode_->GetWorldPosition());
|
||||
cityMesh->Update(timeStep, mark_new_block);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
|
||||
UpdateSky();
|
||||
|
||||
auto* input = GetSubsystem<Input>();
|
||||
cityMesh->Update(timeStep, GetEffectiveSelection(), mark_new_block);
|
||||
|
||||
{
|
||||
auto dirty_flags = gameState.get_dirty_flags();
|
||||
@ -1700,14 +1695,11 @@ void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
|
||||
if (!clear_flags.empty())
|
||||
cityMesh->ClearFlags(clear_flags);
|
||||
cityMesh->RebuildFlags(dirty_flags, true);
|
||||
cityMesh->RebuildFlags(dirty_flags, GetEffectiveSelection(), true);
|
||||
gameState.clear_dirty_flags();
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
// Move the camera, scale movement with time step
|
||||
MoveCamera(timeStep);
|
||||
|
||||
Node *zoneNode = scene_->GetChild("Zone");
|
||||
if (zoneNode)
|
||||
{
|
||||
@ -1716,6 +1708,8 @@ void CryptoCityUrho3D::HandleUpdate(StringHash eventType, VariantMap& eventData)
|
||||
zoneNode->SetPosition(pos);
|
||||
}
|
||||
|
||||
UpdateSky();
|
||||
|
||||
clouds.Update(timeStep, cameraNode_->GetPosition());
|
||||
horizon.Update(timeStep, cameraNode_->GetPosition());
|
||||
|
||||
@ -2766,8 +2760,7 @@ void CryptoCityUrho3D::AddBlock(bool use_selection)
|
||||
undo.Push({map.get_flag_tiles(flag->id)});
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, false);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
cityMesh->RebuildFlags(flags, GetEffectiveSelection(), false);
|
||||
}
|
||||
flag->budget = flag_budget;
|
||||
}
|
||||
@ -2942,8 +2935,7 @@ void CryptoCityUrho3D::RemoveBlock(bool use_selection, bool top_level)
|
||||
undo.Push({map.get_flag_tiles(flag->id)});
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, false);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
cityMesh->RebuildFlags(flags, GetEffectiveSelection(), false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -3124,10 +3116,7 @@ void CryptoCityUrho3D::Undo()
|
||||
}
|
||||
auto state = undo.Undo();
|
||||
map.set_flag_tiles(std::get<0>(*flagUnderConstruction), state.tiles);
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, false);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
gameState.add_dirty_flag(flag);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleRedo(StringHash eventType, VariantMap& eventData)
|
||||
@ -3153,10 +3142,7 @@ void CryptoCityUrho3D::Redo()
|
||||
}
|
||||
auto state = undo.Redo();
|
||||
map.set_flag_tiles(std::get<0>(*flagUnderConstruction), state.tiles);
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, true);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
gameState.add_dirty_flag(flag);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleLoadModel(StringHash eventType, VariantMap& eventData)
|
||||
@ -3298,10 +3284,7 @@ void CryptoCityUrho3D::HandleLoadModel(StringHash eventType, VariantMap& eventDa
|
||||
new MessageBox(context_, msg.c_str(), ok ? String(partial ? "Partial model loaded" : "Model loaded") : String("Error placing model"));
|
||||
|
||||
undo.Push({map.get_flag_tiles(flag->id)});
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, false);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
gameState.add_dirty_flag(flag);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleSaveModel(StringHash eventType, VariantMap& eventData)
|
||||
@ -3813,10 +3796,7 @@ void CryptoCityUrho3D::RestoreFlagUnderConstruction()
|
||||
flag->palette = std::get<1>(*flagUnderConstruction);
|
||||
map.set_flag_tiles(std::get<0>(*flagUnderConstruction), original_tiles);
|
||||
SetNoFlagUnderConstruction();
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, false);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
gameState.add_dirty_flag(flag);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleExit(StringHash eventType, VariantMap& eventData)
|
||||
@ -4059,10 +4039,7 @@ void CryptoCityUrho3D::HandleNewSnapshot(StringHash eventType, VariantMap& event
|
||||
if (flag)
|
||||
{
|
||||
flag->set_tiles(tiles); // reset to under construction state
|
||||
std::deque<std::shared_ptr<Flag>> flags;
|
||||
flags.push_back(flag);
|
||||
cityMesh->RebuildFlags(flags, true);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
gameState.add_dirty_flag(flag);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -4592,14 +4569,12 @@ void CryptoCityUrho3D::HandleExtendSelection(StringHash eventType, VariantMap& e
|
||||
const int32_t dy1 = eventData[SelectExtend::P_DY1].GetInt();
|
||||
|
||||
selection.extend(dx0, dy0, dx1, dy1);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleGrowSelection(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
UnsetFocus();
|
||||
selection.grow();
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleSelectWholeFlag(StringHash eventType, VariantMap& eventData)
|
||||
@ -4626,22 +4601,18 @@ void CryptoCityUrho3D::HandleSelectWholeFlag(StringHash eventType, VariantMap& e
|
||||
new MessageBox(context_, "First select part of the desired flag");
|
||||
return;
|
||||
}
|
||||
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleShrinkSelection(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
UnsetFocus();
|
||||
selection.shrink();
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleSelectEdge(StringHash eventType, VariantMap& eventData)
|
||||
{
|
||||
UnsetFocus();
|
||||
selection.make_edge();
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleGoToFlag(StringHash eventType, VariantMap& eventData)
|
||||
@ -4670,7 +4641,6 @@ void CryptoCityUrho3D::HandleGoToFlag(StringHash eventType, VariantMap& eventDat
|
||||
UITBWindow::CloseModal();
|
||||
|
||||
selection = Selection(flag->x0, flag->y0, flag->x1, flag->y1);
|
||||
cityMesh->setHighlight(GetEffectiveSelection(), GetHoverFlag(), GetSelectedFlag(), flagUnderConstruction, mouse_x, mouse_y, mouse_h, top_x, top_y, top_h);
|
||||
}
|
||||
|
||||
void CryptoCityUrho3D::HandleGetGameUpdateEvents(StringHash eventType, VariantMap& eventData)
|
||||
@ -5098,10 +5068,7 @@ void CryptoCityUrho3D::HandleSetIgnoreSettings(StringHash eventType, VariantMap&
|
||||
wallet->get_ignored_flag_ids(ids);
|
||||
for (uint32_t id: ids)
|
||||
if (auto f = map.get_flag(id))
|
||||
res.insert(f);
|
||||
|
||||
if (!res.empty())
|
||||
cityMesh->RebuildFlags(res, false);
|
||||
gameState.add_dirty_flag(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,20 +102,6 @@ void Tile::pop()
|
||||
}
|
||||
--height;
|
||||
}
|
||||
|
||||
uint8_t Tile::get_type(uint16_t h) const
|
||||
{
|
||||
if (h >= height)
|
||||
throw std::runtime_error("Height overflow");
|
||||
if (height <= 8)
|
||||
{
|
||||
return local_blocks[h];
|
||||
}
|
||||
else
|
||||
{
|
||||
return remote_blocks[h];
|
||||
}
|
||||
}
|
||||
|
||||
void Tile::set_type(uint16_t h, uint8_t type)
|
||||
{
|
||||
|
@ -40,7 +40,7 @@ public:
|
||||
uint16_t get_height() const { return height; }
|
||||
void push(uint8_t type);
|
||||
void pop();
|
||||
uint8_t get_type(uint16_t h) const;
|
||||
uint8_t get_type(uint16_t h) const { return height <= 8 ? local_blocks[h] : remote_blocks[h]; }
|
||||
void set_type(uint16_t h, uint8_t type);
|
||||
|
||||
private:
|
||||
@ -90,6 +90,7 @@ public:
|
||||
void resize(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, uint8_t stability);
|
||||
const Tile &tile(uint32_t x, uint32_t y) const { return tiles[(y - y0) * (x1 - x0 + 1) + x - x0]; }
|
||||
Tile &tile(uint32_t x, uint32_t y) { return tiles[(y - y0) * (x1 - x0 + 1) + x - x0]; }
|
||||
const Tile* get_raw_tiles() const { return tiles; }
|
||||
uint8_t get_tile_type(uint32_t x, uint32_t y, uint16_t h) const;
|
||||
uint16_t get_tile_height(uint32_t x, uint32_t y) const;
|
||||
uint16_t get_max_height() const;
|
||||
|
@ -16,6 +16,7 @@ public:
|
||||
Selection(uint32_t x0, uint32_t y0, uint32_t x1, uint32_t y1, const std::vector<uint8_t> &selected);
|
||||
|
||||
bool operator==(const Selection &s) const;
|
||||
bool operator!=(const Selection &s) const { return !operator==(s); }
|
||||
|
||||
bool is_selected(uint32_t x, uint32_t y) const;
|
||||
bool is_empty() const;
|
||||
|
Loading…
Reference in New Issue
Block a user