Open source Star Ruler 2 source code!

This commit is contained in:
Lucas de Vries
2018-07-17 14:15:37 +02:00
commit cc307720ff
4342 changed files with 2365070 additions and 0 deletions
+440
View File
@@ -0,0 +1,440 @@
import targeting.targeting;
from obj_selection import selectedObjects, getSelectionPosition, selectedObject;
from navigation.elevation import getElevationIntersect;
import targeting.PointTarget;
import movement;
import ftl;
enum MoveMode {
MM_Normal,
MM_Facing,
MM_Height,
};
const double VECTOR_DELAY = 0.2;
const double VECTOR_PROGRESS_DELAY = 0.1;
const int VECTOR_RADIAL_SIZE = 24;
const int FACING_LENGTH = 200;
const Color VECTOR_RADIAL_COLOR(0x39a086aa);
class MoveTarget : PointTarget {
MoveMode mode = MM_Normal;
vec3d destination;
bool hasFacing = false;
bool hasHeight = false;
double origHeight = 0;
vec3d facingDestination;
vec2i startAt = mousePos;
vec2i dragPos = startAt;
double startTime = frameTime;
vec3d get_origin() {
if(shiftKey) {
Object@ obj = selectedObject;
return obj.finalMoveDestination;
}
else {
return getSelectionPosition(true);
}
}
quaterniond get_facing() {
return quaterniond_fromVecToVec(vec3d_front(), facingDestination - destination);
}
bool hover(const vec2i& mpos) override {
if(mode == MM_Facing || mode == MM_Height)
return true;
PointTarget::hover(mpos);
destination = hovered;
//Keep height if in the same region
if(!ctrlKey) {
vec3d orig = origin;
Region@ targRegion = getRegion(destination);
Region@ curRegion = getRegion(orig);
if(curRegion !is null && targRegion is curRegion) {
double hdiff = orig.y - curRegion.position.y;
line3dd ray = activeCamera.screenToRay(mpos);
ray.start.y -= hdiff;
ray.end.y -= hdiff;
if(getElevationIntersect(ray, destination))
destination.y += hdiff;
}
}
return true;
}
bool onMouseButton(int button, bool pressed) override {
if(!pressed) {
if(button == 0) {
mode = MM_Height;
if(!hasHeight)
origHeight = destination.y;
return true;
}
else if(button == 1) {
targetingClick();
return true;
}
}
else {
if(button == 0) {
mode = MM_Facing;
return true;
}
}
return false;
}
bool onMouseDragged(int buttons, int x, int y, int dx, int dy) override {
if(buttons == 0x2) {
dragPos.x += dx;
dragPos.y -= dy;
if(mode == MM_Normal) {
double curTime = frameTime;
if(curTime - startTime > VECTOR_DELAY) {
mode = MM_Height;
if(!hasHeight)
origHeight = destination.y;
}
else if(dragPos.distanceTo(startAt) < 4)
return true;
}
if(mode == MM_Height) {
double delta = double(dy) * 0.5;
destination.y += delta;
hasHeight = true;
if(hasFacing)
facingDestination.y += delta;
return true;
}
}
else if(buttons == 0x3) {
dragPos.x += dx;
dragPos.y -= dy;
if(mode == MM_Facing) {
if(dragPos.distanceTo(startAt) > FACING_LENGTH)
dragPos = startAt + (dragPos - startAt).normalize(FACING_LENGTH);
PointTarget::hover(dragPos);
facingDestination = hovered;
facingDestination.y = destination.y;
hasFacing = true;
return true;
}
}
cancelTargeting();
return false;
}
bool onMouseDragEnd(int buttons) override {
if(mode == MM_Height) {
targetingClick();
return true;
}
else if(mode == MM_Facing) {
mode = MM_Height;
return true;
}
cancelTargeting();
return false;
}
bool click() override {
if(playerEmpire.ForbidDeepSpace != 0) {
if(getRegion(destination) is null) {
cancelTargeting();
return false;
}
}
return true;
}
vec3d get_position() override {
return destination;
}
};
class MoveVisuals : TargetVisuals {
BeamNode@ moveBeam;
BeamNode@ facingBeam;
BeamNode@ heightBeam;
BeamNode@ lengthBeam;
BeamNode@ destHeightBeam;
MoveVisuals() {
@moveBeam = BeamNode(material::MoveBeam, 0.001f, vec3d(), vec3d(), true);
moveBeam.color = Color(0x00ff00ff);
moveBeam.visible = false;
@facingBeam = BeamNode(material::MoveBeam, 0.001f, vec3d(), vec3d(), true);
facingBeam.color = Color(0x00adffff);
facingBeam.visible = false;
@heightBeam = BeamNode(material::MoveBeam, 0.001f, vec3d(), vec3d(), true);
heightBeam.color = Color(0xaaaaaaff);
heightBeam.visible = false;
@destHeightBeam = BeamNode(material::MoveBeam, 0.001f, vec3d(), vec3d(), true);
destHeightBeam.color = Color(0xaaaaaaff);
destHeightBeam.visible = false;
@lengthBeam = BeamNode(material::MoveBeam, 0.001f, vec3d(), vec3d(), true);
lengthBeam.color = Color(0xaaaaaaff);
lengthBeam.visible = false;
}
~MoveVisuals() {
moveBeam.markForDeletion();
facingBeam.markForDeletion();
heightBeam.markForDeletion();
destHeightBeam.markForDeletion();
lengthBeam.markForDeletion();
}
void render(TargetMode@ mode) override {
MoveTarget@ mt = cast<MoveTarget>(mode);
if(mt is null)
return;
vec3d dest = mt.destination;
vec3d origin = mt.origin;
if(mt.hasHeight) {
double origHeight = mt.origHeight;
vec3d flatDest = dest;
flatDest.y = origHeight;
vec3d flatOrigin = origin;
flatOrigin.y = origHeight;
heightBeam.visible = true;
heightBeam.abs_position = flatDest;
heightBeam.endPosition = dest;
lengthBeam.visible = true;
lengthBeam.abs_position = flatOrigin;
lengthBeam.endPosition = flatDest;
}
if(mt.mode != MM_Normal || frameTime - mt.startTime > VECTOR_DELAY) {
moveBeam.visible = true;
moveBeam.abs_position = origin;
moveBeam.endPosition = dest;
}
if(mt.hasFacing) {
vec3d facing = mt.facingDestination;
facingBeam.visible = true;
facingBeam.abs_position = dest;
facingBeam.endPosition = facing;
if(mt.hasHeight) {
vec3d flatFacing = facing;
flatFacing.y = mt.origHeight;
destHeightBeam.visible = true;
destHeightBeam.abs_position = facing;
destHeightBeam.endPosition = flatFacing;
}
}
}
void draw(TargetMode@ mode) override {
MoveTarget@ mt = cast<MoveTarget>(mode);
if(mt is null)
return;
//Draw facing progress radial
if(mt.mode == MM_Normal) {
double curTime = frameTime;
double time = curTime - mt.startTime;
if(time > VECTOR_PROGRESS_DELAY && time < VECTOR_DELAY) {
shader::PROGRESS = float(
min(time - VECTOR_PROGRESS_DELAY,
VECTOR_DELAY - VECTOR_PROGRESS_DELAY))
/ float(VECTOR_DELAY - VECTOR_PROGRESS_DELAY);
vec2i pos = mousePos;
material::RadialProgress.draw(recti_area(
pos - vec2i(VECTOR_RADIAL_SIZE / 2, VECTOR_RADIAL_SIZE / 2),
vec2i(VECTOR_RADIAL_SIZE, VECTOR_RADIAL_SIZE)),
VECTOR_RADIAL_COLOR);
}
}
}
};
class MoveCallback : TargetCallback {
void call(TargetMode@ mode) override {
MoveTarget@ mt = cast<MoveTarget>(mode);
if(mt is null)
return;
Object@[]@ selection = selectedObjects;
if(selection.length == 0)
return;
if(selection[0].hasSupportAI) {
//Movement targeting for supports
Object@[] supports;
double maxRad = 0.0;
Empire@ owner;
for(uint i = 0, cnt = selection.length; i < cnt; ++i) {
Object@ obj = selection[i];
if(obj.owner !is null)
@owner = obj.owner;
if(obj.hasSupportAI && obj.owner.controlled) {
supports.insertLast(obj);
if(obj.radius > maxRad)
maxRad = obj.radius;
}
}
if(supports.length == 0)
return;
//Find fleet to transfer to
Object@ fleet = cast<Ship>(selection[0]).Leader;
if(fleet is null || mode.position.distanceTo(fleet.position) > fleet.getFormationRadius()) {
if(owner !is null)
@fleet = owner.getFleetFromPosition(mode.position);
}
if(fleet is null)
return;
//Calculate formation
double formRad = fleet.getFormationRadius();
uint edge = ceil(sqrt(double(supports.length)));
double spacing = max(maxRad, 1.0) * 8;
vec3d boxSize(edge * spacing, 0, edge * spacing);
double boxRad = sqrt(boxSize.x * boxSize.x / 4.0 + boxSize.z * boxSize.z / 4.0);
vec3d boxCenter = (mode.position - fleet.position);
//Reverse entire fleet rotation
Ship@ leadership = cast<Ship>(fleet);
if(leadership !is null)
boxCenter = leadership.formationDest.inverted() * boxCenter;
//Keep entire box within bounds
if(boxCenter.length + boxRad > formRad)
boxCenter.length = formRad - boxRad;
//Get the spacing vectors
vec3d right = vec3d_right();
vec3d front = vec3d_front();
if(mt.hasFacing) {
quaterniond facing = mt.facing;
right = facing * right;
front = facing * front;
}
if(leadership !is null) {
right = leadership.formationDest.inverted() * right;
front = leadership.formationDest.inverted() * front;
}
right.length = spacing;
front.length = spacing;
//Transfer ships to fleet
for(uint i = 0, cnt = supports.length; i < cnt; ++i) {
uint x = (i % edge);
uint y = i / edge;
//Calculate position in formation
vec3d pos = boxCenter;
if(x % 2 == 0)
pos += right * double(x / 2);
else
pos -= right * double(x / 2 + 1);
if(y % 2 == 0)
pos += front * double(y / 2);
else
pos -= front * double(y / 2 + 1);
//Transfer and form up
Ship@ ship = cast<Ship>(supports[i]);
if(ship.Leader !is fleet)
supports[i].transferTo(fleet, pos);
else
supports[i].setFleetOffset(pos);
}
}
else {
//Movement order targeting
if(selection.length == 1) {
Object@ from = selection[0];
if(from.owner.controlled && from.hasMover && canMoveIndependently(from)) {
sound::order_move.play(priority=true);
if(mt.hasFacing)
orderMove(from, mode.position, mt.facing, shiftKey);
else
orderMove(from, mode.position, shiftKey);
}
}
else if(selection.length > 0) {
array<Object@> orderObjs;
//Get center to organize from
vec3d center;
double spacing = 1;
for(int i = selection.length - 1; i >= 0; --i) {
Object@ obj = selection[i];
if(canMoveIndependently(obj)) {
orderObjs.insertLast(obj);
center += obj.position;
double size = obj.radius;
if(obj.hasLeaderAI)
size = obj.getFormationRadius();
if(size > spacing)
spacing = size;
}
}
if(orderObjs.length == 1) {
sound::order_move.play(priority=true);
if(mt.hasFacing)
orderMove(orderObjs[0], mode.position, mt.facing, shiftKey);
else
orderMove(orderObjs[0], mode.position, shiftKey);
}
else {
center /= double(orderObjs.length);
spacing *= 2.5;
//Get center of target organization
vec3d dest = mode.position;
sound::order_move.play(priority=true);
//Form the objects up
auto@ positions = getFleetTargetPositions(orderObjs, dest, mt.facing, !mt.hasFacing);
for(uint i = 0, cnt = orderObjs.length; i < cnt; ++i) {
if(mt.hasFacing)
orderMove(orderObjs[i], positions[i], mt.facing, shiftKey);
else
orderMove(orderObjs[i], positions[i], shiftKey);
}
}
}
}
}
};
void targetMovement() {
MoveTarget targ;
MoveCallback cb;
MoveVisuals vis;
startTargeting(targ, vis, cb);
}
bool isExtendedMoveTarget() {
MoveTarget@ targ = cast<MoveTarget>(mode);
if(targ is null)
return false;
return frameTime - targ.startTime > VECTOR_DELAY;
}