Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,428 @@
|
||||
import elements.BaseGuiElement;
|
||||
import elements.Gui3DObject;
|
||||
import elements.GuiOverlay;
|
||||
import elements.GuiSkinElement;
|
||||
import elements.GuiText;
|
||||
import elements.GuiSprite;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiListbox;
|
||||
import elements.GuiPanel;
|
||||
import elements.GuiMarkupText;
|
||||
import elements.MarkupTooltip;
|
||||
import elements.GuiResources;
|
||||
import elements.GuiIconGrid;
|
||||
import orbitals;
|
||||
import util.formatting;
|
||||
import icons;
|
||||
import buildings;
|
||||
import resources;
|
||||
import tile_resources;
|
||||
import overlays.Construction;
|
||||
from gui import animate_time;
|
||||
|
||||
const double ANIM1_TIME = 0.15;
|
||||
const double ANIM2_TIME = 0.001;
|
||||
const uint BORDER = 20;
|
||||
const uint WIDTH = 500;
|
||||
const uint R_HEIGHT = 256;
|
||||
|
||||
// {{{ Overlay
|
||||
class OrbitalOverlay : GuiOverlay, ConstructionParent {
|
||||
Gui3DObject@ objView;
|
||||
Orbital@ obj;
|
||||
bool closing = false;
|
||||
|
||||
ResourceDisplay@ resources;
|
||||
ModuleDisplay@ modules;
|
||||
ConstructionDisplay@ construction;
|
||||
|
||||
Alignment@ objTarget;
|
||||
|
||||
OrbitalRequirements reqs;
|
||||
array<OrbitalSection> sections;
|
||||
array<Resource> resList;
|
||||
|
||||
OrbitalOverlay(IGuiElement@ parent, Orbital@ Obj) {
|
||||
super(parent);
|
||||
fade.a = 0;
|
||||
@obj = Obj;
|
||||
|
||||
vec2i parSize = parent.size;
|
||||
@objView = Gui3DObject(this, recti_area(vec2i(-456, parSize.y-228), vec2i(912, 912)));
|
||||
objView.internalRotation = quaterniond_fromAxisAngle(vec3d(0.0, 0.0, 1.0), -0.25*pi);
|
||||
@objView.object = obj;
|
||||
|
||||
int plSize = parSize.x * 2;
|
||||
@objTarget = Alignment(Left+0.5f-plSize/2, Top+0.5f, Width=plSize, Height=plSize);
|
||||
recti targPos = objTarget.resolve(parSize);
|
||||
animate_time(objView, targPos, ANIM1_TIME);
|
||||
|
||||
updateAbsolutePosition();
|
||||
|
||||
vec2i origin = targPos.center;
|
||||
@resources = ResourceDisplay(this, origin, Alignment(Left+0.5f-BORDER/2-WIDTH,
|
||||
Top+BORDER, Left+0.5f-BORDER/2, Top+BORDER+R_HEIGHT));
|
||||
resources.visible = false;
|
||||
@modules = ModuleDisplay(this, origin, Alignment(Left+0.5f-BORDER/2-WIDTH,
|
||||
Top+BORDER, Left+0.5f-BORDER/2, Bottom-BORDER));
|
||||
|
||||
@construction = ConstructionDisplay(this, origin, Alignment(Right-0.5f+BORDER/2,
|
||||
Top+BORDER, Right-0.5f+BORDER/2+WIDTH, Bottom-BORDER));
|
||||
}
|
||||
|
||||
IGuiElement@ elementFromPosition(const vec2i& pos) override {
|
||||
IGuiElement@ elem = BaseGuiElement::elementFromPosition(pos);
|
||||
if(elem is objView)
|
||||
return this;
|
||||
return elem;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) override {
|
||||
switch(evt.type) {
|
||||
case GUI_Animation_Complete:
|
||||
if(evt.caller is objView) {
|
||||
if(closing) {
|
||||
GuiOverlay::close();
|
||||
return true;
|
||||
}
|
||||
|
||||
//Make sure the object view stays in the right position
|
||||
@objView.alignment = objTarget;
|
||||
|
||||
//Start showing all the data
|
||||
resources.animate();
|
||||
modules.animate();
|
||||
construction.animate();
|
||||
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case GUI_Confirmed:
|
||||
triggerUpdate();
|
||||
break;
|
||||
}
|
||||
return GuiOverlay::onGuiEvent(evt);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& evt, IGuiElement@ source) override {
|
||||
return GuiOverlay::onMouseEvent(evt, source);
|
||||
}
|
||||
|
||||
void close() override {
|
||||
if(parent is null)
|
||||
return;
|
||||
closing = true;
|
||||
@objView.alignment = null;
|
||||
|
||||
modules.visible = false;
|
||||
resources.visible = false;
|
||||
construction.visible = false;
|
||||
|
||||
vec2i parSize = parent.size;
|
||||
recti targPos = recti_area(vec2i(-456, parSize.y-228), vec2i(912, 912));
|
||||
animate_time(objView, targPos, ANIM1_TIME);
|
||||
}
|
||||
|
||||
void startBuild(const BuildingType@ type) {
|
||||
}
|
||||
|
||||
Object@ get_object() {
|
||||
return obj;
|
||||
}
|
||||
|
||||
Object@ get_slaved() {
|
||||
return null;
|
||||
}
|
||||
|
||||
void updateData() {
|
||||
resList.syncFrom(obj.getAllResources());
|
||||
sections.syncFrom(obj.getSections());
|
||||
|
||||
reqs.init(resList);
|
||||
for(uint i = 0, cnt = sections.length; i < cnt; ++i) {
|
||||
if(sections[i].enabled)
|
||||
reqs.add(sections[i].type);
|
||||
}
|
||||
|
||||
for(uint i = 0, cnt = construction.modulesList.items.length; i < cnt; ++i) {
|
||||
GuiListbox@ list = cast<GuiListbox>(construction.modulesList.items[i]);
|
||||
for(uint n = 0, ncnt = list.itemCount; n < ncnt; ++n) {
|
||||
auto@ item = cast<BuildElement>(list.getItemElement(n));
|
||||
if(item !is null && item.orb !is null) {
|
||||
item.incomplete = !reqs.check(item.orb);
|
||||
item.update(construction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double updateTimer = 0.0;
|
||||
void update(double time) {
|
||||
construction.update(time);
|
||||
|
||||
updateTimer -= time;
|
||||
if(updateTimer <= 0 || construction.longTimer == 5.0) {
|
||||
updateData();
|
||||
updateTimer = 1.0;
|
||||
}
|
||||
|
||||
resources.update(time);
|
||||
modules.update(time);
|
||||
}
|
||||
|
||||
void triggerUpdate() {
|
||||
updateData();
|
||||
updateTimer = 0.0;
|
||||
resources.updateTimer = 0.0;
|
||||
modules.updateTimer = 0.0;
|
||||
construction.updateTimer = 0.0;
|
||||
construction.longTimer = 0.0;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
if(!settings::bGalaxyBG && objView.Alignment !is null)
|
||||
material::Skybox.draw(AbsolutePosition);
|
||||
GuiOverlay::draw();
|
||||
}
|
||||
};
|
||||
|
||||
class DisplayBox : BaseGuiElement {
|
||||
OrbitalOverlay@ overlay;
|
||||
Alignment@ targetAlign;
|
||||
|
||||
DisplayBox(OrbitalOverlay@ ov, vec2i origin, Alignment@ target) {
|
||||
@overlay = ov;
|
||||
@targetAlign = target;
|
||||
super(overlay, recti_area(origin, vec2i(1,1)));
|
||||
visible = false;
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void animate() {
|
||||
visible = true;
|
||||
animate_time(this, targetAlign.resolve(overlay.size), ANIM2_TIME);
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) override {
|
||||
switch(evt.type) {
|
||||
case GUI_Animation_Complete:
|
||||
@alignment = targetAlign;
|
||||
return true;
|
||||
}
|
||||
return BaseGuiElement::onGuiEvent(evt);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& evt, IGuiElement@ source) override {
|
||||
switch(evt.type) {
|
||||
case MET_Button_Down:
|
||||
if(evt.button == 0)
|
||||
return true;
|
||||
break;
|
||||
case MET_Button_Up:
|
||||
if(evt.button == 0)
|
||||
return true;
|
||||
break;
|
||||
}
|
||||
|
||||
return BaseGuiElement::onMouseEvent(evt, source);
|
||||
}
|
||||
|
||||
void remove() override {
|
||||
@overlay = null;
|
||||
BaseGuiElement::remove();
|
||||
}
|
||||
|
||||
void update(double time) {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
skin.draw(SS_OverlayBox, SF_Normal, AbsolutePosition, Color(0x888888ff));
|
||||
BaseGuiElement::draw();
|
||||
}
|
||||
};
|
||||
//}}}
|
||||
|
||||
// {{{ Resources
|
||||
class ResourceDisplay : DisplayBox {
|
||||
GuiText@ resourceLabel;
|
||||
GuiSkinElement@ resourceBox;
|
||||
GuiResources@ resources;
|
||||
|
||||
GuiText@ affinityLabel;
|
||||
GuiSpriteGrid@ affinities;
|
||||
|
||||
ResourceDisplay(OrbitalOverlay@ ov, vec2i origin, Alignment@ target) {
|
||||
super(ov, origin, target);
|
||||
|
||||
@resourceLabel = GuiText(this, Alignment(Left+8, Top+8, Right-8, Top+30), locale::LAB_RESOURCES);
|
||||
resourceLabel.font = FT_Bold;
|
||||
|
||||
@resourceBox = GuiSkinElement(this, Alignment(Left+20, Top+34, Right-20, Top+78), SS_PlainOverlay);
|
||||
@resources = GuiResources(resourceBox, Alignment().fill());
|
||||
resources.horizAlign = 0.0;
|
||||
@resources.drawFrom = overlay.obj;
|
||||
|
||||
@affinityLabel = GuiText(this, Alignment(Left+8, Top+88, Right-8, Top+110), locale::LAB_AVAIL_AFFINITIES);
|
||||
affinityLabel.font = FT_Bold;
|
||||
|
||||
@affinities = GuiSpriteGrid(this, Alignment(Left+20, Top+114, Right-20, Bottom-8), vec2i(40, 40));
|
||||
affinities.horizAlign = 0.0;
|
||||
affinities.vertAlign = 0.0;
|
||||
}
|
||||
|
||||
void updateData() {
|
||||
resources.resources = overlay.resList;
|
||||
|
||||
affinities.clear();
|
||||
for(uint i = 0, cnt = overlay.reqs.available.length; i < cnt; ++i) {
|
||||
if(overlay.reqs.used[i])
|
||||
continue;
|
||||
auto@ res = overlay.reqs.available[i];
|
||||
for(uint n = 0, ncnt = res.affinities.length; n < ncnt; ++n)
|
||||
affinities.add(getAffinitySprite(res.affinities[n]));
|
||||
}
|
||||
affinityLabel.visible = affinities.sprites.length != 0;
|
||||
}
|
||||
|
||||
double updateTimer = 0.0;
|
||||
void update(double time) override {
|
||||
updateTimer -= time;
|
||||
if(updateTimer <= 0) {
|
||||
updateData();
|
||||
updateTimer = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
|
||||
// {{{ Modules
|
||||
class ModuleElement : BaseGuiElement {
|
||||
Orbital@ obj;
|
||||
OrbitalSection section;
|
||||
|
||||
GuiSprite@ icon;
|
||||
GuiText@ name;
|
||||
GuiMarkupText@ blurb;
|
||||
GuiMarkupText@ data;
|
||||
Color color;
|
||||
GuiButton@ removeButton;
|
||||
|
||||
ModuleElement(IGuiElement@ disp, OrbitalSection@ section, Orbital@ obj) {
|
||||
super(disp, Alignment(Left+8, Top, Right-8, Top+76));
|
||||
@icon = GuiSprite(this, recti_area(8, 13, 50, 50));
|
||||
@name = GuiText(this, Alignment(Left+70, Top+4, Right-4, Top+28));
|
||||
name.font = FT_Bold;
|
||||
@blurb = GuiMarkupText(this, Alignment(Left+68, Top+26, Right-4, Top+48));
|
||||
@data = GuiMarkupText(this, Alignment(Left+68, Top+48, Right-4, Bottom-4));
|
||||
data.defaultFont = FT_Italic;
|
||||
@removeButton = GuiButton(this, Alignment(Right-40, Bottom-26, Right, Bottom), "-");
|
||||
removeButton.color = colors::Red;
|
||||
|
||||
set(section, obj);
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
int prevY = 0;
|
||||
void setPos(int y) {
|
||||
alignment.top.pixels = y;
|
||||
alignment.bottom.pixels = y + 76;
|
||||
if(prevY != y)
|
||||
updateAbsolutePosition();
|
||||
prevY = y;
|
||||
}
|
||||
|
||||
void set(OrbitalSection@ section, Orbital@ obj) {
|
||||
@this.obj = obj;
|
||||
this.section = section;
|
||||
icon.desc = section.type.icon;
|
||||
name.text = section.type.name;
|
||||
blurb.text = section.type.blurb;
|
||||
data.text = section.getData(obj);
|
||||
if(section.enabled) {
|
||||
color = colors::White;
|
||||
name.color = colors::White;
|
||||
}
|
||||
else {
|
||||
color = colors::Red;
|
||||
name.color = colors::Red;
|
||||
}
|
||||
setMarkupTooltip(this, section.type.getTooltip());
|
||||
removeButton.visible = !section.type.isCore && !obj.isContested;
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) override {
|
||||
if(evt.caller is removeButton) {
|
||||
if(evt.type == GUI_Clicked) {
|
||||
obj.destroyModule(section.id);
|
||||
emitConfirmed();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return BaseGuiElement::onGuiEvent(evt);
|
||||
}
|
||||
|
||||
void draw() override {
|
||||
skin.draw(SS_PlainOverlay, SF_Normal, AbsolutePosition, color=color);
|
||||
BaseGuiElement::draw();
|
||||
|
||||
int x = AbsolutePosition.width - 32;
|
||||
for(uint i = 0; i < TR_COUNT; ++i) {
|
||||
for(uint n = 0, ncnt = section.type.affinities[i]; n < ncnt; ++n) {
|
||||
getTileResourceSprite(i).draw(
|
||||
recti_area(AbsolutePosition.topLeft + vec2i(x, 4), vec2i(26, 26)));
|
||||
x -= 30;
|
||||
}
|
||||
}
|
||||
for(uint i = 0, cnt = section.type.requirements.length; i < cnt; ++i) {
|
||||
section.type.requirements[i].icon.draw(
|
||||
recti_area(vec2i(x, 4)+AbsolutePosition.topLeft, vec2i(26, 26)));
|
||||
x -= 30;
|
||||
}
|
||||
if(section.type.maintenance != 0) {
|
||||
x -= 60;
|
||||
skin.getFont(FT_Bold).draw(
|
||||
pos=recti_area(vec2i(x, 4)+AbsolutePosition.topLeft, vec2i(86, 26)),
|
||||
text=formatMoney(section.type.maintenance),
|
||||
color=Color(0xd1cb6aff),
|
||||
horizAlign=1.0);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ModuleDisplay : DisplayBox {
|
||||
GuiPanel@ panel;
|
||||
array<ModuleElement@> modules;
|
||||
|
||||
ModuleDisplay(OrbitalOverlay@ ov, vec2i origin, Alignment@ target) {
|
||||
super(ov, origin, target);
|
||||
@panel = GuiPanel(this, Alignment().fill());
|
||||
updateAbsolutePosition();
|
||||
}
|
||||
|
||||
void updateData() {
|
||||
uint oldCnt = modules.length;
|
||||
uint newCnt = overlay.sections.length;
|
||||
for(uint i = newCnt; i < oldCnt; ++i)
|
||||
modules[i].remove();
|
||||
modules.length = newCnt;
|
||||
int y = 8;
|
||||
for(uint i = 0; i < newCnt; ++i) {
|
||||
if(modules[i] is null)
|
||||
@modules[i] = ModuleElement(panel, overlay.sections[i], overlay.obj);
|
||||
else
|
||||
modules[i].set(overlay.sections[i], overlay.obj);
|
||||
modules[i].setPos(y);
|
||||
y += 80;
|
||||
}
|
||||
}
|
||||
|
||||
double updateTimer = 0.0;
|
||||
void update(double time) override {
|
||||
updateTimer -= time;
|
||||
if(updateTimer <= 0) {
|
||||
updateData();
|
||||
updateTimer = 1.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
// }}}
|
||||
Reference in New Issue
Block a user