Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,902 @@
|
||||
#section disable menu
|
||||
import elements.BaseGuiElement;
|
||||
import elements.GuiText;
|
||||
import elements.MarkupTooltip;
|
||||
import elements.GuiIconGrid;
|
||||
import resources;
|
||||
import util.formatting;
|
||||
import planet_levels;
|
||||
|
||||
export GuiResources, GuiResourceRequirements;
|
||||
export GuiResourceGrid, GuiResourceReqGrid;
|
||||
export drawResource, drawSmallResource;
|
||||
export getAutoImportIcon;
|
||||
export getRequirementIcon;
|
||||
|
||||
const ResourceClass@ foodClass;
|
||||
const ResourceClass@ waterClass;
|
||||
const ResourceType@ waterType;
|
||||
const ResourceClass@ scalableClass;
|
||||
void init() {
|
||||
@foodClass = getResourceClass("Food");
|
||||
@scalableClass = getResourceClass("Scalable");
|
||||
@waterClass = getResourceClass("WaterType");
|
||||
@waterType = getResource("Water");
|
||||
}
|
||||
|
||||
void drawResource(const ResourceType@ type, const recti& pos) {
|
||||
type.icon.draw(pos);
|
||||
|
||||
//Affinities
|
||||
uint affCnt = type.affinities.length;
|
||||
for(uint i = 0; i < affCnt; ++i) {
|
||||
recti affPos = recti_area(vec2i(pos.topLeft.x, pos.botRight.y-i*20-20), vec2i(20, 20));
|
||||
getAffinitySprite(type.affinities[i]).draw(affPos);
|
||||
}
|
||||
|
||||
//Resource level icon
|
||||
if(type.level > 0 && type.level <= 3)
|
||||
spritesheet::ResourceIconsMods.draw(2+type.level, pos);
|
||||
|
||||
//Resource class icon
|
||||
else if(type.cls is foodClass)
|
||||
spritesheet::ResourceIconsMods.draw(6, pos);
|
||||
}
|
||||
|
||||
void drawResource(const Resource@ r, const recti& pos, Object@ drawFrom = null, const Font@ ft = null) {
|
||||
const ResourceType@ type = r.type;
|
||||
|
||||
//Origin underlay
|
||||
if(r.origin is drawFrom && r.origin !is null) {
|
||||
spritesheet::ResourceIconsMods.draw(0, pos);
|
||||
|
||||
//Rarity
|
||||
if(type.rarity > 0)
|
||||
spritesheet::ResourceIconsMods.draw(6+type.rarity, pos);
|
||||
}
|
||||
|
||||
drawResource(r.type, pos);
|
||||
|
||||
if(r.origin is null || r.origin.owner is playerEmpire) {
|
||||
//Disabled overlay
|
||||
if(!r.usable)
|
||||
spritesheet::ResourceIconsMods.draw(2, pos);
|
||||
}
|
||||
|
||||
//Export tick
|
||||
if(r.origin is drawFrom && r.exportedTo !is null && r.origin !is null && drawFrom.visible)
|
||||
spritesheet::ResourceIconsMods.draw(1, pos);
|
||||
|
||||
//Vanish timer
|
||||
if(r.type.vanishMode != VM_Never && drawFrom !is null) {
|
||||
double timeLeft = r.type.vanishTime - r.vanishTime;
|
||||
if(r.exportedTo !is null)
|
||||
timeLeft /= r.exportedTo.resourceVanishRate;
|
||||
else if(r.origin !is null)
|
||||
timeLeft /= r.origin.resourceVanishRate;
|
||||
font::DroidSans_11_Bold.draw(pos.topLeft+vec2i(4, 4),
|
||||
formatShortTime(timeLeft),
|
||||
Color(0xffbb00ff));
|
||||
}
|
||||
}
|
||||
|
||||
void drawSmallResource(const ResourceType@ type, const Resource@ r, const recti& pos, Object@ drawFrom = null, bool onPlanet = false) {
|
||||
if(r !is null) {
|
||||
//Origin underlay
|
||||
if(r.origin is drawFrom && r.origin !is null && !onPlanet) {
|
||||
spritesheet::ResourceIconsSmallMods.draw(0, pos.padded(-2));
|
||||
|
||||
//Rarity
|
||||
if(type.rarity > 0)
|
||||
spritesheet::ResourceIconsSmallMods.draw(10, pos.padded(-2), getResourceRarityColor(type.rarity));
|
||||
}
|
||||
|
||||
if(drawFrom !is null && !r.usable && r.origin is null) {
|
||||
if(r.type.cls is foodClass) {
|
||||
FOOD_REQ.draw(pos);
|
||||
}
|
||||
else if(r.type.cls is waterClass) {
|
||||
WATER_REQ.draw(pos);
|
||||
}
|
||||
else if(r.type.level < LEVEL_REQ.length) {
|
||||
LEVEL_REQ[r.type.level].draw(pos);
|
||||
}
|
||||
else {
|
||||
UNKNOWN_REQ.draw(pos);
|
||||
}
|
||||
}
|
||||
else {
|
||||
type.smallIcon.draw(pos);
|
||||
}
|
||||
|
||||
bool lowPop = false;
|
||||
if(drawFrom !is null) {
|
||||
if(!r.usable) {
|
||||
if(r.origin is null) {
|
||||
//Queued auto-import
|
||||
spritesheet::ResourceIconsSmallMods.draw(13, pos.padded(-2), Color(0xf800ffff));
|
||||
}
|
||||
else if(drawFrom.owner is playerEmpire || drawFrom !is r.origin) {
|
||||
if(r.origin.owner !is playerEmpire) {
|
||||
//Queued import
|
||||
spritesheet::ResourceIconsSmallMods.draw(13, pos.padded(-2), Color(0xffe400ff));
|
||||
}
|
||||
else {
|
||||
if(r.origin.hasSurfaceComponent && r.origin.resourceLevel >= r.type.level &&
|
||||
r.origin.population < getPlanetLevelRequiredPop(r.origin, r.type.level)) {
|
||||
//Insufficient population
|
||||
spritesheet::ResourceIconsSmallMods.draw(13, pos.padded(-4), Color(0xff6300ff));
|
||||
lowPop = true;
|
||||
}
|
||||
else {
|
||||
//Disabled
|
||||
spritesheet::ResourceIconsSmallMods.draw(2, pos.padded(-4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(r.origin is drawFrom && r.origin.hasSurfaceComponent) {
|
||||
lowPop = r.origin.resourceLevel > r.origin.level;
|
||||
if(lowPop && !r.type.artificial) {
|
||||
//Insufficient population
|
||||
spritesheet::ResourceIconsSmallMods.draw(13, pos.padded(-4), Color(0xff6300ff));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Resource level icon
|
||||
if(type.level > 0 && type.level <= 3)
|
||||
spritesheet::ResourceIconsSmallMods.draw(3+type.level, pos.padded(-2));
|
||||
|
||||
//Resource class icon
|
||||
else if(type.cls is foodClass)
|
||||
spritesheet::ResourceIconsSmallMods.draw(7, pos.padded(-2));
|
||||
else if(type.cls is scalableClass)
|
||||
spritesheet::ResourceIconsSmallMods.draw(16, pos.padded(-2));
|
||||
|
||||
//Export tick
|
||||
if(r.origin !is null && r.origin is drawFrom && r.exportedTo !is null && drawFrom.visible)
|
||||
spritesheet::ResourceIconsSmallMods.draw(1, pos.padded(-2));
|
||||
|
||||
//Excess tick
|
||||
if(r.exportedTo is null && r.origin !is null && r.usable && !lowPop) {
|
||||
if(r.origin.owner is playerEmpire && r.origin.hasSurfaceComponent && !r.type.isMaterial(r.origin.level) && r.origin.exportEnabled)
|
||||
spritesheet::ResourceIconsSmallMods.draw(3, pos.padded(-2));
|
||||
}
|
||||
|
||||
//Lock icon
|
||||
if(drawFrom is null || r.origin is drawFrom) {
|
||||
if(r.locked)
|
||||
spritesheet::ResourceIconsSmallMods.draw(15, pos.padded(-2));
|
||||
else if(type.willLock)
|
||||
spritesheet::ResourceIconsSmallMods.draw(14, pos.padded(-2));
|
||||
}
|
||||
}
|
||||
else {
|
||||
type.smallIcon.draw(pos);
|
||||
|
||||
//Resource level icon
|
||||
if(type.level > 0 && type.level <= 3)
|
||||
spritesheet::ResourceIconsSmallMods.draw(3+type.level, pos.padded(-2));
|
||||
|
||||
//Resource class icon
|
||||
else if(type.cls is foodClass)
|
||||
spritesheet::ResourceIconsSmallMods.draw(7, pos.padded(-2));
|
||||
else if(type.cls is scalableClass)
|
||||
spritesheet::ResourceIconsSmallMods.draw(16, pos.padded(-2));
|
||||
|
||||
//Lock icon
|
||||
if(type.willLock)
|
||||
spritesheet::ResourceIconsSmallMods.draw(14, pos.padded(-2));
|
||||
}
|
||||
}
|
||||
|
||||
class GuiResourceRequirements : BaseGuiElement {
|
||||
GuiText@[] text;
|
||||
GuiResources@[] resources;
|
||||
|
||||
GuiResourceRequirements(IGuiElement@ ParentElement, Alignment@ align) {
|
||||
super(ParentElement, align);
|
||||
}
|
||||
|
||||
GuiResourceRequirements(IGuiElement@ ParentElement, const recti& pos) {
|
||||
super(ParentElement, pos);
|
||||
}
|
||||
|
||||
void set(const ResourceRequirements@ reqs, const Resources@ available = null, bool allowUniversal = true) {
|
||||
//Do calculations
|
||||
array<int>@ remaining = null;
|
||||
if(available !is null) {
|
||||
@remaining = array<int>();
|
||||
reqs.satisfiedBy(available, null, allowUniversal, remaining);
|
||||
}
|
||||
|
||||
//Remove previous
|
||||
for(uint i = 0, cnt = resources.length; i < cnt; ++i)
|
||||
resources[i].remove();
|
||||
resources.length = 0;
|
||||
for(uint i = 0, cnt = text.length; i < cnt; ++i)
|
||||
text[i].remove();
|
||||
text.length = 0;
|
||||
|
||||
//Add all groups
|
||||
uint rCnt = reqs.reqs.length;
|
||||
int x = 0;
|
||||
int rsize = size.height - 15;
|
||||
for(uint i = 0; i < rCnt; ++i) {
|
||||
const ResourceRequirement@ req = reqs.reqs[i];
|
||||
int amount = req.amount;
|
||||
if(remaining !is null)
|
||||
amount = remaining[i];
|
||||
if(amount == 0)
|
||||
continue;
|
||||
|
||||
GuiResources r(this, recti());
|
||||
string caption;
|
||||
|
||||
//Find which resources and caption to display
|
||||
switch(req.type) {
|
||||
case RRT_Resource:
|
||||
r.types.insertLast(req.resource);
|
||||
caption = toString(amount)+"x";
|
||||
break;
|
||||
case RRT_Class:
|
||||
for(uint i = 0, cnt = req.cls.types.length; i < cnt; ++i) {
|
||||
const ResourceType@ restype = req.cls.types[i];
|
||||
if(!restype.exportable || restype.mode != RM_Normal || !restype.requirementDisplay)
|
||||
continue;
|
||||
r.types.insertLast(restype);
|
||||
}
|
||||
if(r.types.length == 1)
|
||||
caption = toString(amount)+"x";
|
||||
else
|
||||
caption = format(locale::RESOURCES_OF, toString(amount));
|
||||
break;
|
||||
case RRT_Class_Types:
|
||||
for(uint i = 0, cnt = req.cls.types.length; i < cnt; ++i) {
|
||||
const ResourceType@ restype = req.cls.types[i];
|
||||
if(!restype.exportable || restype.mode != RM_Normal || !restype.requirementDisplay)
|
||||
continue;
|
||||
if(available !is null && available.getAmount(restype) != 0)
|
||||
continue;
|
||||
r.types.insertLast(restype);
|
||||
}
|
||||
if(r.types.length == 1)
|
||||
caption = toString(amount)+"x";
|
||||
else
|
||||
caption = format(locale::TYPES_OF, toString(amount));
|
||||
break;
|
||||
case RRT_Level:
|
||||
for(uint i = 0, cnt = getResourceCount(); i < cnt; ++i) {
|
||||
const ResourceType@ res = getResource(i);
|
||||
if(!res.exportable || res.mode != RM_Normal || !res.requirementDisplay)
|
||||
continue;
|
||||
if(res.level == req.level)
|
||||
r.types.insertLast(res);
|
||||
}
|
||||
if(r.types.length == 1)
|
||||
caption = toString(amount)+"x";
|
||||
else
|
||||
caption = format(locale::RESOURCES_OF, toString(amount));
|
||||
break;
|
||||
case RRT_Level_Types:
|
||||
for(uint i = 0, cnt = getResourceCount(); i < cnt; ++i) {
|
||||
const ResourceType@ res = getResource(i);
|
||||
if(res.level != req.level)
|
||||
continue;
|
||||
if(!res.exportable || res.mode != RM_Normal || !res.requirementDisplay)
|
||||
continue;
|
||||
if(available !is null && available.getAmount(res) != 0)
|
||||
continue;
|
||||
r.types.insertLast(res);
|
||||
}
|
||||
if(r.types.length == 1)
|
||||
caption = toString(amount)+"x";
|
||||
else
|
||||
caption = format(locale::TYPES_OF, toString(amount));
|
||||
break;
|
||||
}
|
||||
|
||||
if(r.types.length == 0) {
|
||||
r.remove();
|
||||
continue;
|
||||
}
|
||||
|
||||
//Scrunch icons if multiple
|
||||
int w = 0;
|
||||
if(r.types.length == 1)
|
||||
w = rsize;
|
||||
else
|
||||
w = (float(rsize) * 0.9f) * float(r.types.length);
|
||||
|
||||
//Create the caption
|
||||
GuiText ctext(this, Alignment(Left+x, Top, Left+x+w, Top+15));
|
||||
ctext.horizAlign = 0.5;
|
||||
ctext.font = FT_Small;
|
||||
ctext.text = caption;
|
||||
text.insertLast(ctext);
|
||||
|
||||
//Position the resources element
|
||||
r.typeMode = true;
|
||||
@r.alignment = Alignment(Left+x, Top+15, Left+x+w, Bottom);
|
||||
resources.insertLast(r);
|
||||
x += w+16;
|
||||
}
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void draw() {
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class GuiResources : BaseGuiElement {
|
||||
Object@ drawFrom;
|
||||
array<const ResourceType@> types;
|
||||
Resource[] resources;
|
||||
bool typeMode = false;
|
||||
bool vertical = false;
|
||||
bool shrink = false;
|
||||
double horizAlign = 0.5;
|
||||
double vertAlign = 0.5;
|
||||
int spacing = 0;
|
||||
int hovered = -1;
|
||||
|
||||
GuiResources(IGuiElement@ ParentElement, Alignment@ align) {
|
||||
super(ParentElement, align);
|
||||
_GuiResources();
|
||||
}
|
||||
|
||||
GuiResources(IGuiElement@ ParentElement, const recti& pos) {
|
||||
super(ParentElement, pos);
|
||||
_GuiResources();
|
||||
}
|
||||
|
||||
void _GuiResources() {
|
||||
MarkupTooltip tt(350, 0.f, true, true);
|
||||
tt.Lazy = true;
|
||||
tt.LazyUpdate = false;
|
||||
tt.Padding = 4;
|
||||
@tooltipObject = tt;
|
||||
}
|
||||
|
||||
uint get_length() {
|
||||
if(typeMode)
|
||||
return types.length;
|
||||
else
|
||||
return resources.length;
|
||||
}
|
||||
|
||||
string get_tooltip() {
|
||||
if(hovered < 0 || hovered >= int(length))
|
||||
return "";
|
||||
|
||||
Resource@ r;
|
||||
const ResourceType@ type;
|
||||
if(typeMode) {
|
||||
@type = types[hovered];
|
||||
}
|
||||
else {
|
||||
@r = resources[hovered];
|
||||
@type = r.type;
|
||||
}
|
||||
|
||||
return getResourceTooltip(type, r, drawFrom);
|
||||
}
|
||||
|
||||
void calcOffset(vec2i& pos, vec2i& offset, vec2i& rsize) {
|
||||
uint cnt = length;
|
||||
uint isize = min(size.width, size.height);
|
||||
rsize = vec2i(isize, isize);
|
||||
pos = vec2i();
|
||||
offset = vec2i();
|
||||
|
||||
if(vertical) {
|
||||
pos.x = double(size.width - isize) * horizAlign;
|
||||
|
||||
int tot = (isize + spacing) * cnt - spacing;
|
||||
if(tot < size.height) {
|
||||
pos.y = double(size.height - tot) * vertAlign;
|
||||
offset.y = isize + spacing;
|
||||
}
|
||||
else {
|
||||
if(shrink) {
|
||||
isize = double(size.height) / double(cnt);
|
||||
rsize.x = isize;
|
||||
rsize.y = isize;
|
||||
offset.y = isize;
|
||||
}
|
||||
else if(cnt > 1) {
|
||||
offset.y = double(size.height - isize) / double(cnt - 1);
|
||||
}
|
||||
else {
|
||||
offset.y = isize;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
pos.y = double(size.height - isize) * vertAlign;
|
||||
|
||||
int tot = (isize + spacing) * cnt - spacing;
|
||||
if(tot < size.width) {
|
||||
pos.x = double(size.width - tot) * horizAlign;
|
||||
offset.x = isize + spacing;
|
||||
}
|
||||
else {
|
||||
if(shrink) {
|
||||
isize = double(size.width) / double(cnt);
|
||||
rsize.x = isize;
|
||||
rsize.y = isize;
|
||||
offset.x = isize;
|
||||
}
|
||||
else if(cnt > 1) {
|
||||
offset.x = double(size.width - isize) / double(cnt - 1);
|
||||
}
|
||||
else {
|
||||
offset.x = isize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) {
|
||||
if(event.caller is this) {
|
||||
switch(event.type) {
|
||||
case GUI_Mouse_Left:
|
||||
hovered = -1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BaseGuiElement::onGuiEvent(event);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
if(source is this) {
|
||||
switch(event.type) {
|
||||
case MET_Moved: {
|
||||
int prevHovered = hovered;
|
||||
hovered = getOffsetItem(mousePos - AbsolutePosition.topLeft);
|
||||
if(prevHovered != hovered)
|
||||
tooltipObject.update(skin, this);
|
||||
} break;
|
||||
case MET_Button_Down:
|
||||
if(hovered != -1)
|
||||
return true;
|
||||
break;
|
||||
case MET_Button_Up:
|
||||
if(hovered != -1) {
|
||||
if(event.button == 2 && uint(hovered) < resources.length)
|
||||
zoomTo(resources[hovered].origin);
|
||||
emitClicked(event.button);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BaseGuiElement::onMouseEvent(event, source);
|
||||
}
|
||||
|
||||
int getOffsetItem(const vec2i& off) {
|
||||
vec2i pos, ioff, rsize, offset = off;
|
||||
calcOffset(pos, ioff, rsize);
|
||||
|
||||
offset -= pos;
|
||||
if(offset.x < 0 || offset.y < 0)
|
||||
return -1;
|
||||
|
||||
int num = 0;
|
||||
if(vertical) {
|
||||
num = floor(double(offset.y) / double(ioff.y));
|
||||
if(offset.y - (num * ioff.y) > rsize.y)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
num = floor(double(offset.x) / double(ioff.x));
|
||||
if(offset.y - (num * ioff.y) > rsize.y)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(num >= int(length))
|
||||
return -1;
|
||||
return num;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
vec2i pos, offset, rsize;
|
||||
calcOffset(pos, offset, rsize);
|
||||
|
||||
vec2i hovPos;
|
||||
const Font@ ft = skin.getFont(FT_Normal);
|
||||
if(rsize.width < 32)
|
||||
@ft = skin.getFont(FT_Small);
|
||||
|
||||
//Draw everything but the hovered resource
|
||||
for(uint i = 0, cnt = length; i < cnt; ++i) {
|
||||
if(hovered != int(i)) {
|
||||
if(typeMode)
|
||||
drawResource(types[i], recti_area(pos + AbsolutePosition.topLeft, rsize));
|
||||
else
|
||||
drawResource(resources[i], recti_area(pos + AbsolutePosition.topLeft, rsize), drawFrom, ft);
|
||||
}
|
||||
else
|
||||
hovPos = pos;
|
||||
pos += offset;
|
||||
}
|
||||
|
||||
//Draw hovered last so it's on top
|
||||
if(hovered != -1 && uint(hovered) < this.length) {
|
||||
if(typeMode)
|
||||
drawResource(types[hovered], recti_area(hovPos + AbsolutePosition.topLeft, rsize));
|
||||
else
|
||||
drawResource(resources[hovered], recti_area(hovPos + AbsolutePosition.topLeft, rsize), drawFrom, ft);
|
||||
}
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class GuiResourceGrid : GuiIconGrid {
|
||||
Object@ drawFrom;
|
||||
array<const ResourceType@> types;
|
||||
Resource[] resources;
|
||||
bool typeMode = false;
|
||||
bool singleMode = false;
|
||||
|
||||
GuiResourceGrid(IGuiElement@ ParentElement, Alignment@ align) {
|
||||
super(ParentElement, align);
|
||||
_GuiResourceGrid();
|
||||
}
|
||||
|
||||
GuiResourceGrid(IGuiElement@ ParentElement, const recti& pos) {
|
||||
super(ParentElement, pos);
|
||||
_GuiResourceGrid();
|
||||
}
|
||||
|
||||
void _GuiResourceGrid() {
|
||||
iconSize = vec2i(21, 21);
|
||||
spacing = vec2i(5, 5);
|
||||
MarkupTooltip tt(350, 0.f, true, true);
|
||||
tt.Lazy = true;
|
||||
tt.LazyUpdate = false;
|
||||
tt.Padding = 4;
|
||||
@tooltipObject = tt;
|
||||
}
|
||||
|
||||
uint get_length() override {
|
||||
if(typeMode)
|
||||
return types.length;
|
||||
else
|
||||
return resources.length;
|
||||
}
|
||||
|
||||
void setSingleMode(bool mode = true, double align = 0.5) {
|
||||
singleMode = mode && length == 1;
|
||||
forceHover = singleMode;
|
||||
horizAlign = singleMode ? 0.0 : align;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& event) override {
|
||||
if(event.caller is this) {
|
||||
switch(event.type) {
|
||||
case GUI_Clicked:
|
||||
if(uint(hovered) < resources.length) {
|
||||
if(event.value == 2) {
|
||||
zoomTo(resources[hovered].origin);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return BaseGuiElement::onGuiEvent(event);
|
||||
}
|
||||
|
||||
string get_tooltip() override {
|
||||
if(hovered < 0 || hovered >= int(length))
|
||||
return "";
|
||||
|
||||
Resource@ r;
|
||||
const ResourceType@ type;
|
||||
if(typeMode) {
|
||||
@type = types[hovered];
|
||||
}
|
||||
else {
|
||||
@r = resources[hovered];
|
||||
@type = r.type;
|
||||
}
|
||||
|
||||
return getResourceTooltip(type, r, drawFrom);
|
||||
}
|
||||
|
||||
void drawElement(uint i, const recti& pos) override {
|
||||
clearClip();
|
||||
if(typeMode)
|
||||
drawSmallResource(types[i], null, pos, drawFrom);
|
||||
else
|
||||
drawSmallResource(resources[i].type, resources[i], pos, drawFrom);
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
GuiIconGrid::draw();
|
||||
|
||||
if(singleMode && length == 1) {
|
||||
Resource@ r;
|
||||
const ResourceType@ type;
|
||||
if(typeMode) {
|
||||
@type = types[0];
|
||||
}
|
||||
else {
|
||||
@r = resources[0];
|
||||
@type = r.type;
|
||||
}
|
||||
if(typeMode || drawFrom is null || r.origin is drawFrom) {
|
||||
uint affCnt = type.affinities.length;
|
||||
|
||||
Color textColor;
|
||||
if(!typeMode && !r.usable && r.origin.owner is playerEmpire) {
|
||||
if(r.exportedTo !is null) {
|
||||
float pct = abs((frameTime % 1.0) - 0.5f) * 2.f;
|
||||
textColor = colors::Red.interpolate(colors::Orange, pct);
|
||||
}
|
||||
else {
|
||||
textColor = colors::Red;
|
||||
}
|
||||
}
|
||||
|
||||
const Font@ ft = skin.getFont(FT_Bold);
|
||||
recti pos = AbsolutePosition.padded(34, 0, 0, 0);
|
||||
ft.draw(text=type.name, ellipsis=locale::ELLIPSIS,
|
||||
pos=pos.padded(0, 0, affCnt*28, 0), vertAlign=0.5, color=textColor);
|
||||
|
||||
int x = 28;
|
||||
for(uint i = 0; i < affCnt; ++i) {
|
||||
uint aff = type.affinities[i];
|
||||
getAffinitySprite(aff).draw(recti_area(vec2i(pos.botRight.x-x, pos.topLeft.y), vec2i(24, 24)));
|
||||
x += 28;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const Sprite FOOD_REQ(spritesheet::ResourceClassIcons, 3);
|
||||
const Sprite WATER_REQ(spritesheet::ResourceClassIcons, 4);
|
||||
const Sprite UNKNOWN_REQ(spritesheet::ResourceClassIcons, 5);
|
||||
const Sprite[] LEVEL_REQ = {
|
||||
Sprite(),
|
||||
Sprite(spritesheet::ResourceClassIcons, 0),
|
||||
Sprite(spritesheet::ResourceClassIcons, 1),
|
||||
Sprite(spritesheet::ResourceClassIcons, 2)
|
||||
};
|
||||
|
||||
Sprite getAutoImportIcon(const AutoImportDesc& desc) {
|
||||
if(desc.type !is null) {
|
||||
if(desc.type is waterType)
|
||||
return WATER_REQ;
|
||||
return desc.type.smallIcon;
|
||||
}
|
||||
else if(desc.cls !is null) {
|
||||
if(desc.cls is foodClass)
|
||||
return FOOD_REQ;
|
||||
else if(desc.cls is waterClass)
|
||||
return WATER_REQ;
|
||||
return Sprite();
|
||||
}
|
||||
else if(desc.level != -1 && uint(desc.level) < LEVEL_REQ.length) {
|
||||
return LEVEL_REQ[desc.level];
|
||||
}
|
||||
return UNKNOWN_REQ;
|
||||
}
|
||||
|
||||
Sprite getRequirementIcon(const ResourceRequirement@ req) {
|
||||
switch(req.type) {
|
||||
case RRT_Resource:
|
||||
if(req.resource is waterType)
|
||||
return WATER_REQ;
|
||||
else
|
||||
return req.resource.smallIcon;
|
||||
case RRT_Class:
|
||||
case RRT_Class_Types:
|
||||
if(req.cls is foodClass)
|
||||
return FOOD_REQ;
|
||||
else if(req.cls is waterClass)
|
||||
return WATER_REQ;
|
||||
else
|
||||
return UNKNOWN_REQ;
|
||||
case RRT_Level:
|
||||
case RRT_Level_Types:
|
||||
if(req.level < LEVEL_REQ.length)
|
||||
return LEVEL_REQ[req.level];
|
||||
else
|
||||
return UNKNOWN_REQ;
|
||||
}
|
||||
return Sprite();
|
||||
}
|
||||
|
||||
class GuiResourceReqGrid : GuiIconGrid {
|
||||
Sprite[] sprites;
|
||||
string[] tooltips;
|
||||
|
||||
GuiResourceReqGrid(IGuiElement@ ParentElement, Alignment@ align) {
|
||||
super(ParentElement, align);
|
||||
MarkupTooltip tt(350, 0.f, true, true);
|
||||
tt.Lazy = true;
|
||||
tt.LazyUpdate = false;
|
||||
tt.Padding = 4;
|
||||
@tooltipObject = tt;
|
||||
iconSize = vec2i(26,26);
|
||||
padding = vec2i(-2);
|
||||
spacing = vec2i(1);
|
||||
noClip = true;
|
||||
}
|
||||
|
||||
GuiResourceReqGrid(IGuiElement@ ParentElement, const recti& pos) {
|
||||
super(ParentElement, pos);
|
||||
MarkupTooltip tt(350, 0.f, true, true);
|
||||
tt.Lazy = true;
|
||||
tt.LazyUpdate = false;
|
||||
tt.Padding = 4;
|
||||
@tooltipObject = tt;
|
||||
iconSize = vec2i(26,26);
|
||||
padding = vec2i(-2);
|
||||
spacing = vec2i(1);
|
||||
noClip = true;
|
||||
}
|
||||
|
||||
string get_tooltip() override {
|
||||
if(hovered < 0 || uint(hovered) >= tooltips.length)
|
||||
return "";
|
||||
return tooltips[hovered];
|
||||
}
|
||||
|
||||
uint get_length() override {
|
||||
return sprites.length;
|
||||
}
|
||||
|
||||
void drawElement(uint i, const recti& pos) override {
|
||||
sprites[i].draw(pos.padded(-2));
|
||||
}
|
||||
|
||||
void set(const ResourceRequirements@ reqs, const Resources@ available = null, bool allowUniversal = true) {
|
||||
//Do calculations
|
||||
array<int>@ remaining = null;
|
||||
if(available !is null) {
|
||||
@remaining = array<int>();
|
||||
reqs.satisfiedBy(available, null, allowUniversal, remaining);
|
||||
}
|
||||
|
||||
sprites.length = 0;
|
||||
tooltips.length = 0;
|
||||
|
||||
//Add all groups
|
||||
uint rCnt = reqs.reqs.length;
|
||||
for(uint i = 0; i < rCnt; ++i) {
|
||||
const ResourceRequirement@ req = reqs.reqs[i];
|
||||
int amount = req.amount;
|
||||
if(remaining !is null)
|
||||
amount = remaining[i];
|
||||
if(amount == 0)
|
||||
continue;
|
||||
|
||||
//Find which icon to display
|
||||
switch(req.type) {
|
||||
case RRT_Resource:
|
||||
for(int i = 0; i < amount; ++i) {
|
||||
if(req.resource is waterType)
|
||||
sprites.insertLast(WATER_REQ);
|
||||
else
|
||||
sprites.insertLast(req.resource.smallIcon);
|
||||
tooltips.insertLast(req.resource.name);
|
||||
}
|
||||
break;
|
||||
case RRT_Class: {
|
||||
Sprite sprt;
|
||||
|
||||
if(req.cls is foodClass)
|
||||
sprt = FOOD_REQ;
|
||||
else if(req.cls is waterClass)
|
||||
sprt = WATER_REQ;
|
||||
else
|
||||
sprt = UNKNOWN_REQ;
|
||||
|
||||
string tip = format(locale::REQ_TYPE, req.cls.name, getSpriteDesc(sprt))+"\n";
|
||||
for(uint i = 0, cnt = req.cls.types.length; i < cnt; ++i) {
|
||||
const ResourceType@ restype = req.cls.types[i];
|
||||
if(!restype.exportable || restype.mode != RM_Normal || !restype.requirementDisplay)
|
||||
continue;
|
||||
if(restype.frequency == 0.0 || restype.rarity >= RR_Rare)
|
||||
continue;
|
||||
tip += format("[img=$1;28/]", getSpriteDesc(restype.smallIcon));
|
||||
}
|
||||
|
||||
for(int i = 0; i < amount; ++i) {
|
||||
sprites.insertLast(sprt);
|
||||
tooltips.insertLast(tip);
|
||||
}
|
||||
} break;
|
||||
case RRT_Class_Types: {
|
||||
Sprite sprt;
|
||||
if(req.cls is foodClass)
|
||||
sprt = FOOD_REQ;
|
||||
else if(req.cls is waterClass)
|
||||
sprt = WATER_REQ;
|
||||
else
|
||||
sprt = UNKNOWN_REQ;
|
||||
|
||||
string tip = format(locale::REQ_TYPE_UNIQUE, req.cls.name, getSpriteDesc(sprt))+"\n";
|
||||
for(uint i = 0, cnt = req.cls.types.length; i < cnt; ++i) {
|
||||
const ResourceType@ restype = req.cls.types[i];
|
||||
if(!restype.exportable || restype.mode != RM_Normal || !restype.requirementDisplay)
|
||||
continue;
|
||||
if(restype.frequency == 0.0 || restype.rarity >= RR_Rare)
|
||||
continue;
|
||||
if(available !is null && available.getAmount(restype) != 0)
|
||||
continue;
|
||||
tip += format("[img=$1;28/]", getSpriteDesc(restype.smallIcon));
|
||||
}
|
||||
|
||||
for(int i = 0; i < amount; ++i) {
|
||||
sprites.insertLast(sprt);
|
||||
tooltips.insertLast(tip);
|
||||
}
|
||||
} break;
|
||||
case RRT_Level: {
|
||||
Sprite sprt;
|
||||
if(req.level < LEVEL_REQ.length)
|
||||
sprt = LEVEL_REQ[req.level];
|
||||
else
|
||||
sprt = UNKNOWN_REQ;
|
||||
|
||||
string tip = format(locale::REQ_LEVEL, toString(req.level), getSpriteDesc(sprt))+"\n";
|
||||
for(uint i = 0, cnt = getResourceCount(); i < cnt; ++i) {
|
||||
const ResourceType@ res = getResource(i);
|
||||
if(res.level != req.level)
|
||||
continue;
|
||||
if(res.frequency == 0.0 || res.rarity >= RR_Rare)
|
||||
continue;
|
||||
if(!res.exportable || res.mode != RM_Normal || !res.requirementDisplay)
|
||||
continue;
|
||||
tip += format("[img=$1;28/]", getSpriteDesc(res.smallIcon));
|
||||
}
|
||||
|
||||
for(int i = 0; i < amount; ++i) {
|
||||
sprites.insertLast(sprt);
|
||||
tooltips.insertLast(tip);
|
||||
}
|
||||
} break;
|
||||
case RRT_Level_Types: {
|
||||
Sprite sprt;
|
||||
if(req.level < LEVEL_REQ.length)
|
||||
sprt = LEVEL_REQ[req.level];
|
||||
else
|
||||
sprt = UNKNOWN_REQ;
|
||||
|
||||
string tip = format(locale::REQ_LEVEL_UNIQUE, toString(req.level), getSpriteDesc(sprt))+"\n";
|
||||
for(uint i = 0, cnt = getResourceCount(); i < cnt; ++i) {
|
||||
const ResourceType@ res = getResource(i);
|
||||
if(res.level != req.level)
|
||||
continue;
|
||||
if(!res.exportable || res.mode != RM_Normal || !res.requirementDisplay)
|
||||
continue;
|
||||
if(res.frequency == 0.0 || res.rarity >= RR_Rare)
|
||||
continue;
|
||||
if(available !is null && available.getAmount(res) != 0)
|
||||
continue;
|
||||
tip += format("[img=$1;28/]", getSpriteDesc(res.smallIcon));
|
||||
}
|
||||
|
||||
for(int i = 0; i < amount; ++i) {
|
||||
sprites.insertLast(sprt);
|
||||
tooltips.insertLast(tip);
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
};
|
||||
|
||||
#section game
|
||||
import void zoomTo(Object@ obj) from "tabs.GalaxyTab";
|
||||
#section menu
|
||||
void zoomTo(Object@ obj) {}
|
||||
#section all
|
||||
Reference in New Issue
Block a user