const IBox View::computeCursor(const int2 &start, const int2 &end, const int3 &bbox, int height, int offset) const { float2 height_off = worldToScreen(float3(0, height, 0)); int3 gbox(cellSize(), 1, cellSize()); int3 start_pos = asXZ((int2)( screenToWorld(float2(start + pos()) - height_off) + float2(0.5f, 0.5f))); int3 end_pos = asXZ((int2)( screenToWorld(float2(end + pos()) - height_off) + float2(0.5f, 0.5f))); start_pos.y = end_pos.y = height + offset; { int apos1 = start_pos.x % gbox.x; int apos2 = apos1 - gbox.x + bbox.x; start_pos.x -= apos1 < gbox.x - apos1 || bbox.x >= gbox.x? apos1 : apos2; } { int apos1 = start_pos.z % gbox.z; int apos2 = apos1 - gbox.z + bbox.z; start_pos.z -= apos1 < gbox.z - apos1 || bbox.z >= gbox.z? apos1 : apos2; } if(end == start) end_pos = start_pos; int3 dir(end_pos.x >= start_pos.x? 1 : -1, 1, end_pos.z >= start_pos.z? 1 : -1); int3 size(::abs(end_pos.x - start_pos.x), 1, ::abs(end_pos.z - start_pos.z)); size += bbox - int3(1, 1, 1); size.x -= size.x % bbox.x; size.z -= size.z % bbox.z; size = max(bbox, size); if(dir.x < 0) start_pos.x += bbox.x; if(dir.z < 0) start_pos.z += bbox.z; end_pos = start_pos + dir * size; if(start_pos.x > end_pos.x) swap(start_pos.x, end_pos.x); if(start_pos.z > end_pos.z) swap(start_pos.z, end_pos.z); int2 dims = m_tile_map.dimensions(); start_pos = asXZY(clamp(start_pos.xz(), int2(0, 0), dims), start_pos.y); end_pos = asXZY(clamp( end_pos.xz(), int2(0, 0), dims), end_pos.y); return IBox(start_pos, end_pos); }
void EntitiesEditor::computeCursor(int2 start, int2 end, bool floor_mode) { float2 height_off = worldToScreen(int3(0, 0, 0)); start += m_view.pos(); end += m_view.pos(); Ray ray = screenRay(start); Flags::Type flags = Flags::all; if(floor_mode) flags = flags & ~(Flags::wall_tile | Flags::object_tile); auto isect = m_tile_map.trace(ray, -1, flags | Flags::visible); float3 pos = isect.first == -1? (float3)asXZ(screenToWorld(start)) : ray.at(isect.second); m_cursor_pos = (float3)round(pos); m_selection = IRect(min(start, end), max(start, end)); }