Skip to content

Commit

Permalink
Add "shape": "diamond" to map locations
Browse files Browse the repository at this point in the history
  • Loading branch information
black-sliver committed Jul 29, 2024
1 parent ef85151 commit eb92d9c
Show file tree
Hide file tree
Showing 15 changed files with 187 additions and 16 deletions.
2 changes: 2 additions & 0 deletions doc/PACKS.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ Maps are referenced by name in layouts.
"name": "map_identifier",
"location_size": 24, // size of locations on the map, unit is pixels of img
"location_border_thickness": 2, // border around the locations
"location_shape": "rect", // or "diamond", since 0.26.2
"img": "path/to/img.png"
},
...
Expand Down Expand Up @@ -393,6 +394,7 @@ Locations define drops on maps, rules to have them accessible as well as the loo
"y": 234,
"size": 24, // override map default, since 0.21.1
"border_thickness": 2, // override map default, since 0.21.1
"shape": "rect", // override map default, since 0.26.2
"restrict_visibility_rules": [
... // additional visibility rules for individual map locations, since 0.26
],
Expand Down
1 change: 1 addition & 0 deletions examples/rules_test/maps/maps.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"name": "example2",
"location_size": 24,
"location_border_thickness": 2,
"location_shape": "diamond",
"img": "images/maps/example.png"
}
]
6 changes: 4 additions & 2 deletions examples/rules_test/var_at/locations/locations.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
{
"map": "example",
"x": 100,
"y": 300
"y": 300,
"shape": "diamond"
}
],
"sections": [
Expand Down Expand Up @@ -110,7 +111,8 @@
{
"map": "example2",
"x": 300,
"y": 250
"y": 250,
"shape": "rect"
}
],
"sections": [
Expand Down
4 changes: 4 additions & 0 deletions schema/packs/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -282,6 +282,10 @@
}
]
},
"shape": {
"description": "Overrides the location shape defined on the map.",
"enum": [null, "rect", "diamond"]
},
"restrict_visibility_rules": {
"example": [
"rule1,rule2",
Expand Down
5 changes: 5 additions & 0 deletions schema/packs/maps.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
}
]
},
"location_shape": {
"description": "Shape of the map locations.",
"enum": ["rect", "diamond"],
"default": "rect"
},
"img": {
"description": "Image of the map.",
"type": "string"
Expand Down
1 change: 1 addition & 0 deletions schema/packs/strict/locations.json
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,7 @@
"type": "number",
"minimum": -1
},
"shape": true,
"restrict_visibility_rules": {
"example": [
"rule1,rule2",
Expand Down
1 change: 1 addition & 0 deletions schema/packs/strict/maps.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"type": "number",
"minimum": 0
},
"location_shape": true,
"img": true
},
"additionalProperties": false
Expand Down
1 change: 1 addition & 0 deletions src/core/location.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@ Location::MapLocation Location::MapLocation::FromJSON(json& j)
maploc._y = to_int(j["y"],0);
maploc._size = to_int(j["size"],-1);
maploc._borderThickness = to_int(j["border_thickness"],-1);
maploc._shape = Location::MapLocation::ShapeFromString(to_string(j["shape"], ""));

if (j["restrict_visibility_rules"].is_array()) {
for (const auto& v : j["restrict_visibility_rules"]) {
Expand Down
22 changes: 22 additions & 0 deletions src/core/location.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,21 @@ class Location final : public LuaInterface<Location> {
class MapLocation final {
public:
static MapLocation FromJSON(nlohmann::json& j);

enum class Shape {
UNSPECIFIED,
RECT,
DIAMOND,
};

static Shape ShapeFromString(const std::string& s) {
if (s == "rect")
return Shape::RECT;
if (s == "diamond")
return Shape::DIAMOND;
return Shape::UNSPECIFIED;
}

protected:
std::string _mapName;
int _x = 0; // TODO: point ?
Expand All @@ -87,13 +102,20 @@ class Location final : public LuaInterface<Location> {
int _borderThickness = -1;
std::list<std::list<std::string> > _visibilityRules;
std::list<std::list<std::string> > _invisibilityRules;
Shape _shape = Shape::UNSPECIFIED;

public:
// getters
const std::string& getMap() const { return _mapName; }
int getX() const { return _x; }
int getY() const { return _y; }
int getSize(int parent) const { return _size < 1 ? parent : _size; }
int getBorderThickness(int parent) const { return _borderThickness < 0 ? parent : _borderThickness; }
Shape getShape(Shape parent) const
{
return _shape == Shape::UNSPECIFIED ? parent : _shape;
}

const std::list<std::list<std::string>>& getVisibilityRules() const { return _visibilityRules; }
const std::list<std::list<std::string>>& getInvisibilityRules() const { return _invisibilityRules; }
};
Expand Down
1 change: 1 addition & 0 deletions src/core/map.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Map Map::FromJSON(json& j)
Map map;
map._locationSize = to_int(j["location_size"], map._locationSize);
map._locationBorderThickness = to_int(j["location_border_thickness"], map._locationBorderThickness);
map._locationShape = ::Location::MapLocation::ShapeFromString(to_string(j["location_shape"], ""));
map._img = to_string(j["img"], "");
return map;
}
9 changes: 9 additions & 0 deletions src/core/map.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@

#include <nlohmann/json.hpp>
#include <string>
#include "location.h"


class Map final {
public:
typedef ::Location::MapLocation::Shape LocationShape;

static Map FromJSON(nlohmann::json& j);
static Map FromJSON(nlohmann::json&& j);
static Map FromJSONString(const std::string& json);

protected:
int _locationSize=65;
int _locationBorderThickness=8;
LocationShape _locationShape = LocationShape::UNSPECIFIED;
std::string _img;

public:
int getLocationSize() const { return _locationSize; }
int getLocationBorderThickness() const { return _locationBorderThickness; }
LocationShape getLocationShape() const
{
return _locationShape;
}
const std::string& getImage() const { return _img; }
};

Expand Down
24 changes: 16 additions & 8 deletions src/ui/mapwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -198,32 +198,40 @@ void MapWidget::render(Renderer renderer, int offX, int offY)
if (state == 0 && _hideClearedLocations) continue;
if (state == 2 && _hideUnreachableLocations) continue;


if (!SplitRects || state<0 || state>=countOf(triangleValues)) {
const Widget::Color& c = (state<0 || state>=countOf(StateColors)) ?
StateColors[countOf(StateColors)-1] : StateColors[state];
drawRect(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
c, c, c, c);
if (pos.shape == Shape::DIAMOND)
drawDiamond(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
c, c, c, c);
else
drawRect(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
c, c, c, c);
} else {
const int* values = triangleValues[state];
const Widget::Color& topC = StateColors[values[0]];
const Widget::Color& leftC = StateColors[values[1]];
const Widget::Color& botC = StateColors[values[2]];
const Widget::Color& rightC = StateColors[values[3]];
drawRect(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
topC, leftC, botC, rightC);

if (pos.shape == Shape::DIAMOND)
drawDiamond(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
topC, leftC, botC, rightC);
else
drawRect(renderer, {innerx, innery}, {locScreenInnerW, locScreenInnerH}, borderScreenSize,
topC, leftC, botC, rightC);
}
}
}
}

void MapWidget::addLocation(const std::string& id, int x, int y, int size, int borderThickness, int state)
void MapWidget::addLocation(const std::string& id, int x, int y, int size, int borderThickness, Shape shape, int state)
{
auto it = _locations.find(id);
if (it != _locations.end()) {
it->second.pos.push_back( {x, y, size, borderThickness, state} );
it->second.pos.push_back( {x, y, size, borderThickness, shape, state} );
} else {
_locations[id] = { { {x, y, size, borderThickness, state} } };
_locations[id] = { { {x, y, size, borderThickness, shape, state} } };
}
}

Expand Down
16 changes: 10 additions & 6 deletions src/ui/mapwidget.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,34 @@
#define _UI_MAPWIDGET_H

#include "../uilib/image.h"
#include "../core/location.h"
#include <map>
#include <vector>

namespace Ui {

class MapWidget final : public Image {
public:
typedef ::Location::MapLocation::Shape Shape;

MapWidget(int x, int y, int w, int h, const char* filename);
MapWidget(int x, int y, int w, int h, const void* data, size_t len);

struct Point {
int x=0;
int y=0;
int size=0;
int borderThickness=0;
int state=1;
int x = 0;
int y = 0;
int size = 0;
int borderThickness = 0;
Shape shape = Shape::UNSPECIFIED;
int state = 1;
};

struct Location {
std::vector<Point> pos;
};

// TODO: enum location state
void addLocation(const std::string& name, int x, int y, int size, int borderThickness, int state=1);
void addLocation(const std::string& name, int x, int y, int size, int borderThickness, Shape shape, int state=1);
void setLocationState(const std::string& name, int state, size_t n);

// FIXME: this does not work if name is not unique
Expand Down
1 change: 1 addition & 0 deletions src/ui/trackerview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ bool TrackerView::addLayoutNode(Container* container, const LayoutNode& node, si
w->addLocation(pair.first, pair.second.getX(), pair.second.getY(),
pair.second.getSize(map.getLocationSize()),
pair.second.getBorderThickness(map.getLocationBorderThickness()),
pair.second.getShape(map.getLocationShape()),
state);
}
#ifndef NDEBUG
Expand Down
109 changes: 109 additions & 0 deletions src/uilib/drawhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,4 +106,113 @@ void drawRect(Renderer renderer, Position pos, Size size, int borderWidth,
}
}

void drawDiamond(Renderer renderer, Position pos, Size size, int borderWidth,
Widget::Color tlC, Widget::Color blC, Widget::Color brC, Widget::Color trC)
{
bool hasAlpha = tlC.a != 0xff || blC.a != 0xff || brC.a != 0xff || trC.a != 0xff;

float il = pos.left;
float it = pos.top;
float iw = size.width;
float ih = size.height;

float ol = il - borderWidth;
float ot = it - borderWidth;
float ow = iw + 2 * borderWidth;
float oh = ih + 2 * borderWidth;

if (hasAlpha) {
// we have to draw 4 individual lines for border
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
float x1 = ol, x2 = ol + borderWidth, x3 = ol + ow/2, x4 = ol + ow - borderWidth, x5 = ol + ow;
float y1 = ot, y2 = ot + borderWidth, y3 = ot + oh/2, y4 = ot + oh - borderWidth, y5 = ot + oh;
SDL_Color borderColor = {0, 0, 0, 255};
SDL_Vertex verts[] = {
{{x1, y3}, borderColor, {0, 0}},
{{x2, y3}, borderColor, {0, 0}},
{{x3, y2}, borderColor, {0, 0}},
{{x3, y1}, borderColor, {0, 0}},
{{x4, y3}, borderColor, {0, 0}},
{{x5, y3}, borderColor, {0, 0}},
{{x3, y4}, borderColor, {0, 0}},
{{x3, y5}, borderColor, {0, 0}},
};
int indices[] = {
0, 1, 2,
0, 2, 3,
2, 4, 3,
3, 4, 5,
4, 6, 5,
5, 6, 7,
1, 7, 6,
7, 1, 0,
};
SDL_RenderGeometry(renderer, nullptr, verts, 8, indices, 24);
} else {
// border as bigger background rect
float x1 = ol, x2 = ol + ow/2, x3 = ol + ow;
float y1 = ot, y2 = ot + oh/2, y3 = ot + oh;
SDL_Color borderColor = {0, 0, 0, 255};
SDL_Vertex verts[] = {
{{x1, y2}, borderColor, {0, 0}},
{{x2, y3}, borderColor, {0, 0}},
{{x2, y1}, borderColor, {0, 0}},
{{x3, y2}, borderColor, {0, 0}},
};
int indices[] = {
0, 1, 2,
2, 1, 3
};
SDL_RenderGeometry(renderer, nullptr, verts, 4, indices, 6);
}

{
float x1 = il, x2 = il + iw/2, x3 = il + iw;
float y1 = it, y2 = it + ih/2, y3 = it + ih;
if (tlC == blC) {
SDL_Color leftColor = {tlC.r, tlC.g, tlC.b, tlC.a};
SDL_Vertex verts[] = {
{{x1, y2}, leftColor, {0, 0}},
{{x2, y3}, leftColor, {0, 0}},
{{x2, y1}, leftColor, {0, 0}},
};
SDL_RenderGeometry(renderer, nullptr, verts, 3, nullptr, 0);
} else {
SDL_Color tlColor = {tlC.r, tlC.g, tlC.b, tlC.a};
SDL_Color blColor = {blC.r, blC.g, blC.b, blC.a};
SDL_Vertex verts[] = {
{{x2, y2}, tlColor, {0, 0}},
{{x2, y1}, tlColor, {0, 0}},
{{x1, y2}, tlColor, {0, 0}},
{{x1, y2}, blColor, {0, 0}},
{{x2, y3}, blColor, {0, 0}},
{{x2, y2}, blColor, {0, 0}},
};
SDL_RenderGeometry(renderer, nullptr, verts, 6, nullptr, 0);
}

if (brC == trC) {
SDL_Color rightColor = {trC.r, trC.g, trC.b, trC.a};
SDL_Vertex verts[] = {
{{x2, y1}, rightColor, {0, 0}},
{{x2, y3}, rightColor, {0, 0}},
{{x3, y2}, rightColor, {0, 0}},
};
SDL_RenderGeometry(renderer, nullptr, verts, 3, nullptr, 0);
} else {
SDL_Color trColor = {trC.r, trC.g, trC.b, trC.a};
SDL_Color brColor = {brC.r, brC.g, brC.b, brC.a};
SDL_Vertex verts[] = {
{{x2, y1}, trColor, {0, 0}},
{{x2, y2}, trColor, {0, 0}},
{{x3, y2}, trColor, {0, 0}},
{{x3, y2}, brColor, {0, 0}},
{{x2, y2}, brColor, {0, 0}},
{{x2, y3}, brColor, {0, 0}},
};
SDL_RenderGeometry(renderer, nullptr, verts, 6, nullptr, 0);
}
}
}

} // namespace Ui

0 comments on commit eb92d9c

Please sign in to comment.