429 lines
11 KiB
ActionScript
429 lines
11 KiB
ActionScript
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;
|
|
}
|
|
}
|
|
}
|
|
// }}}
|