Open source Star Ruler 2 source code!
This commit is contained in:
@@ -0,0 +1,371 @@
|
||||
import tabs.Tab;
|
||||
import elements.GuiAccordion;
|
||||
import elements.GuiPanel;
|
||||
import elements.GuiButton;
|
||||
import elements.GuiText;
|
||||
import elements.GuiSprite;
|
||||
import elements.GuiMarkupText;
|
||||
from elements.Gui3DObject import Gui3DObject, ObjectAction;
|
||||
from elements.GuiResources import GuiResources;
|
||||
import planet_types;
|
||||
import planet_levels;
|
||||
import resources;
|
||||
import systems;
|
||||
import util.formatting;
|
||||
from obj_selection import selectObject;
|
||||
import overlays.Popup;
|
||||
from overlays.PlanetPopup import PlanetPopup;
|
||||
|
||||
from overlays.ContextMenu import openContextMenu;
|
||||
from tabs.tabbar import get_ActiveTab, browseTab, popTab;
|
||||
import void zoomTabTo(Object@ obj) from "tabs.GalaxyTab";
|
||||
import void openOverlay(Object@ obj) from "tabs.GalaxyTab";
|
||||
|
||||
const vec2i SIZE_PER_PX(5.0, 8.0);
|
||||
|
||||
final class SystemBox {
|
||||
SystemDesc@ desc;
|
||||
recti pos;
|
||||
};
|
||||
|
||||
final class LineBox {
|
||||
SystemBox@ from;
|
||||
SystemBox@ to;
|
||||
vec2i fromPos;
|
||||
vec2i toPos;
|
||||
recti area;
|
||||
};
|
||||
|
||||
array<SystemBox> systemBoxes;
|
||||
array<LineBox@> systemLines;
|
||||
void createSystemBoxes() {
|
||||
uint sysCnt = systemCount;
|
||||
systemBoxes.length = sysCnt;
|
||||
for(uint i = 0,cnt = sysCnt; i < cnt; ++i) {
|
||||
SystemDesc@ desc = getSystem(i);
|
||||
vec2i pos = vec2i(desc.position.x / SIZE_PER_PX.x, desc.position.z / SIZE_PER_PX.y);
|
||||
vec2i size = vec2i(desc.object.planetCount*160+40, 220);
|
||||
|
||||
SystemBox@ box = systemBoxes[i];
|
||||
@box.desc = desc;
|
||||
box.pos = recti_area(pos-(size/2), size);
|
||||
|
||||
for(uint j = 0, jcnt = desc.adjacent.length; j < jcnt; ++j) {
|
||||
uint adj = desc.adjacent[j];
|
||||
if(adj < i) {
|
||||
LineBox line;
|
||||
@line.from = box;
|
||||
@line.to = systemBoxes[adj];
|
||||
line.fromPos = line.from.pos.center;
|
||||
line.toPos = line.to.pos.center;
|
||||
|
||||
line.area.topLeft.x = min(line.fromPos.x - 5, line.toPos.x - 5);
|
||||
line.area.topLeft.y = min(line.fromPos.y - 5, line.toPos.y - 5);
|
||||
line.area.botRight.x = max(line.fromPos.x + 5, line.toPos.x + 5);
|
||||
line.area.botRight.y = max(line.fromPos.y + 5, line.toPos.y + 5);
|
||||
|
||||
systemLines.insertLast(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class SystemTab : Tab {
|
||||
Region@ sys;
|
||||
const SystemDesc@ desc;
|
||||
|
||||
array<PlanetPopup@> popups;
|
||||
|
||||
bool heldLeft = false;
|
||||
bool dragging = false;
|
||||
bool moved = false;
|
||||
vec2d scroll;
|
||||
vec2i dragStart;
|
||||
vec2i prevScroll;
|
||||
|
||||
set_int instantiated;
|
||||
|
||||
SystemTab() {
|
||||
super();
|
||||
title = locale::SYSTEM_TAB;
|
||||
if(systemBoxes.length == 0)
|
||||
createSystemBoxes();
|
||||
}
|
||||
|
||||
void display(Object@ system) {
|
||||
for(uint i = 0, cnt = systemBoxes.length; i < cnt; ++i) {
|
||||
SystemBox@ box = systemBoxes[i];
|
||||
if(system is box.desc.object) {
|
||||
scroll = vec2d(box.pos.center);
|
||||
prevScroll = vec2i(scroll);
|
||||
moved = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateAbsolutePosition() {
|
||||
Tab::updateAbsolutePosition();
|
||||
}
|
||||
|
||||
Color get_activeColor() {
|
||||
return Color(0xfcb44eff);
|
||||
}
|
||||
|
||||
Color get_inactiveColor() {
|
||||
return Color(0xff9600ff);
|
||||
}
|
||||
|
||||
Color get_seperatorColor() {
|
||||
return Color(0x8c642bff);
|
||||
}
|
||||
|
||||
TabCategory get_category() {
|
||||
return TC_Galaxy;
|
||||
}
|
||||
|
||||
void instantiate(const recti& relArea, SystemBox@ box) {
|
||||
instantiated.insert(box.desc.index);
|
||||
|
||||
vec2i startPos = box.pos.topLeft - relArea.topLeft + vec2i(20, 36);
|
||||
uint plCnt = box.desc.object.planetCount;
|
||||
|
||||
for(uint i = 0; i < plCnt; ++i) {
|
||||
Planet@ pl = box.desc.object.planets[i];
|
||||
PlanetPopup pop(this);
|
||||
pop.set(pl);
|
||||
pop.mouseLinked = false;
|
||||
pop.isSelectable = true;
|
||||
pop.update();
|
||||
|
||||
pop.visible = pl.visible;
|
||||
pop.position = startPos + vec2i(160*i, 0);
|
||||
popups.insertLast(pop);
|
||||
}
|
||||
}
|
||||
|
||||
void deinstantiate(SystemBox@ box) {
|
||||
instantiated.erase(box.desc.index);
|
||||
for(int i = popups.length - 1; i >= 0; --i) {
|
||||
if(popups[i].pl.region is box.desc.object) {
|
||||
popups[i].remove();
|
||||
popups.removeAt(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void movePopups() {
|
||||
vec2i roundedScroll(scroll);
|
||||
if(prevScroll == roundedScroll)
|
||||
return;
|
||||
|
||||
vec2i moveBy = prevScroll - roundedScroll;
|
||||
prevScroll = roundedScroll;
|
||||
for(uint i = 0, cnt = popups.length; i < cnt; ++i) {
|
||||
PlanetPopup@ pop = popups[i];
|
||||
pop.move(moveBy);
|
||||
}
|
||||
}
|
||||
|
||||
void updatePopups() {
|
||||
for(uint i = 0, cnt = popups.length; i < cnt; ++i) {
|
||||
popups[i].visible = popups[i].pl.visible;
|
||||
if(popups[i].visible)
|
||||
popups[i].update();
|
||||
}
|
||||
}
|
||||
|
||||
IGuiElement@ elementFromPosition(const vec2i& pos) {
|
||||
if(dragging) {
|
||||
//Cannot access inner elements while dragging,
|
||||
if(AbsoluteClipRect.isWithin(pos))
|
||||
return this;
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return Tab::elementFromPosition(pos);
|
||||
}
|
||||
}
|
||||
|
||||
bool onGuiEvent(const GuiEvent& evt) {
|
||||
switch(evt.type) {
|
||||
case GUI_Clicked: {
|
||||
PlanetPopup@ pop = cast<PlanetPopup>(evt.caller);
|
||||
if(pop !is null && pop.parent is this) {
|
||||
switch(evt.value) {
|
||||
case PA_Select:
|
||||
selectObject(pop.pl, shiftKey);
|
||||
return true;
|
||||
case PA_Manage:
|
||||
popTab(this);
|
||||
zoomTabTo(pop.pl);
|
||||
openOverlay(pop.pl);
|
||||
return true;
|
||||
case PA_Zoom:
|
||||
popTab(this);
|
||||
zoomTabTo(pop.pl);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return Tab::onGuiEvent(evt);
|
||||
}
|
||||
|
||||
bool onKeyEvent(const KeyboardEvent& event, IGuiElement@ source) {
|
||||
switch(event.type) {
|
||||
case KET_Key_Down:
|
||||
if(event.key == KEY_ESC)
|
||||
return true;
|
||||
break;
|
||||
case KET_Key_Up:
|
||||
if(event.key == KEY_ESC) {
|
||||
if(previous !is null) {
|
||||
popTab(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return Tab::onKeyEvent(event, source);
|
||||
}
|
||||
|
||||
bool onMouseEvent(const MouseEvent& event, IGuiElement@ source) {
|
||||
if(event.type == MET_Button_Up) {
|
||||
if(event.button == 1) {
|
||||
if(previous !is null) {
|
||||
popTab(this);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(source is this) {
|
||||
switch(event.type) {
|
||||
case MET_Button_Down:
|
||||
if(event.button == 0) {
|
||||
heldLeft = true;
|
||||
dragStart = vec2i(event.x, event.y);
|
||||
}
|
||||
break;
|
||||
case MET_Moved: {
|
||||
vec2i mouse = vec2i(event.x, event.y);
|
||||
vec2i d = mouse - dragStart;
|
||||
|
||||
if(dragging) {
|
||||
scroll -= vec2d(double(d.x), double(d.y));
|
||||
dragStart = mouse;
|
||||
moved = true;
|
||||
}
|
||||
else if(heldLeft) {
|
||||
if(abs(d.x) >= 5 || abs(d.y) >= 5) {
|
||||
dragging = true;
|
||||
moved = true;
|
||||
scroll -= vec2d(double(d.x), double(d.y));
|
||||
dragStart = mouse;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case MET_Button_Up:
|
||||
if(event.button == 0) {
|
||||
if(!dragging) {
|
||||
//Do stuff
|
||||
}
|
||||
heldLeft = false;
|
||||
dragging = false;
|
||||
dragStart = vec2i();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return Tab::onMouseEvent(event, source);
|
||||
}
|
||||
|
||||
void tick(double time) {
|
||||
if(!visible)
|
||||
return;
|
||||
|
||||
if(moved) {
|
||||
movePopups();
|
||||
moved = false;
|
||||
|
||||
recti relArea = recti_area(vec2i(scroll) - (size/2), size);
|
||||
for(uint i = 0, cnt = systemBoxes.length; i < cnt; ++i) {
|
||||
SystemBox@ box = systemBoxes[i];
|
||||
bool inst = instantiated.contains(i);
|
||||
|
||||
if(box.pos.overlaps(relArea)) {
|
||||
if(!inst)
|
||||
instantiate(relArea, box);
|
||||
}
|
||||
else {
|
||||
if(inst)
|
||||
deinstantiate(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updatePopups();
|
||||
}
|
||||
|
||||
void drawSystemLine(const recti& relArea, LineBox@ box) {
|
||||
Color col(0xffffff30);
|
||||
vec2i from = box.fromPos - relArea.topLeft + AbsolutePosition.topLeft;
|
||||
vec2i to = box.toPos - relArea.topLeft + AbsolutePosition.topLeft;
|
||||
|
||||
bool canTrade = (box.to.desc.object.TradeMask & playerEmpire.mask) != 0
|
||||
|| (box.from.desc.object.TradeMask & playerEmpire.mask) != 0;
|
||||
if(canTrade) {
|
||||
col = playerEmpire.color;
|
||||
col.a = 0x60;
|
||||
}
|
||||
|
||||
drawLine(from, to, col, 10);
|
||||
}
|
||||
|
||||
void drawSystemBox(const recti& relArea, SystemBox@ box) {
|
||||
recti bpos = box.pos - relArea.topLeft + AbsolutePosition.topLeft;
|
||||
const Font@ ft = skin.getFont(FT_Medium);
|
||||
Color col;
|
||||
|
||||
Empire@ prim = box.desc.object.visiblePrimaryEmpire;
|
||||
if(prim !is null)
|
||||
col = prim.color;
|
||||
|
||||
skin.draw(SS_SystemPanel, SF_Normal, bpos, col);
|
||||
ft.draw(bpos.topLeft+vec2i(8, 5), box.desc.name);
|
||||
}
|
||||
|
||||
void draw() {
|
||||
skin.draw(SS_SystemListBG, SF_Normal, AbsolutePosition);
|
||||
|
||||
recti relArea = recti_area(vec2i(scroll) - (size/2), size);
|
||||
|
||||
//Draw the lines
|
||||
for(uint i = 0, cnt = systemLines.length; i < cnt; ++i) {
|
||||
LineBox@ box = systemLines[i];
|
||||
if(box.area.overlaps(relArea))
|
||||
drawSystemLine(relArea, box);
|
||||
}
|
||||
|
||||
//Draw the boxes
|
||||
for(uint i = 0, cnt = systemBoxes.length; i < cnt; ++i) {
|
||||
SystemBox@ box = systemBoxes[i];
|
||||
if(box.pos.overlaps(relArea))
|
||||
drawSystemBox(relArea, box);
|
||||
}
|
||||
|
||||
Tab::draw();
|
||||
}
|
||||
};
|
||||
|
||||
Tab@ createSystemTab() {
|
||||
return SystemTab();
|
||||
}
|
||||
|
||||
Tab@ createSystemTab(Object@ system) {
|
||||
SystemTab tab;
|
||||
tab.display(system);
|
||||
|
||||
return tab;
|
||||
}
|
||||
Reference in New Issue
Block a user