#section disable menu import elements.BaseGuiElement; import planet_types; import orbitals; import pickups; import artifacts; import civilians; #section gui from nodes.PlanetNode import getPlanetMaterial; #section all from planets.PlanetSurface import preparePlanetShader; from util.draw_model import drawLitModel; export Gui3DDisplay; export ObjectAction; export Gui3DObject; export Draw3D, makeDrawMode; int ringworldType = -1; void init() { auto@ rw = getPlanetType("Ringworld"); if(rw !is null) ringworldType = rw.id; } interface Draw3D { void preRender(Object@ obj); void draw(const recti &in pos, quaterniond rotation); }; class DrawModel : Draw3D { const Material@ mat; const Model@ model; quaterniond extraRotation; DrawModel(const Model@ Model, const Material@ Mat) { @mat = Mat; @model = Model; } DrawModel(const Model@ Model, const Material@ Mat, const quaterniond& rot) { @mat = Mat; @model = Model; extraRotation = rot; } void preRender(Object@ obj) { } void draw(const recti &in pos, quaterniond rotation) { drawLitModel(model, mat, pos, extraRotation * rotation); } }; class DrawPlanet : Draw3D { const Material@ mat, atmos; Planet@ pl; Node@ node; DrawPlanet(Planet@ pl) { const PlanetType@ type = getPlanetType(cast(pl).PlanetType); @mat = type.emptyMat; @atmos = type.atmosMat; @this.pl = pl; @node = pl.getNode(); } void preRender(Object@ obj) { } void draw(const recti &in pos, quaterniond rotation) { @renderingNode = node; #section gui auto@ dyntex = getPlanetMaterial(pl, mat); auto@ material = dyntex.material; if(material is null) return; auto@ plType = getPlanetType(pl.PlanetType); preparePlanetShader(pl); if(atmos !is null) drawLitModel(plType.model, material, pos, rotation, 1/1.025); else drawLitModel(plType.model, material, pos, rotation); if(atmos !is null) { shader::MODEL_SCALE = double(min(pos.height, pos.width)) / 2 / 1.025; quaterniond atmosRot; if(settings::bRotateUIObjects) atmosRot = quaterniond_fromAxisAngle(vec3d_up(), fraction(gameTime / 120.0) * twopi); drawLitModel(model::Sphere_max, material::FlatAtmosphere, pos, rotation * atmosRot); } @renderingNode = null; #section all } }; class DrawRingworld : Draw3D { DrawRingworld(Planet@ pl) { } void preRender(Object@ obj) { } void draw(const recti &in pos, quaterniond rotation) { quaterniond outerRot; outerRot *= quaterniond_fromAxisAngle(vec3d_front(), -0.25 * pi); outerRot *= rotation; drawLitModel(model::RingworldOuter, material::GenericPBR_RingworldOuter, pos, outerRot); quaterniond innerRot; innerRot *= quaterniond_fromAxisAngle(vec3d_front(), -0.25 * pi); innerRot *= rotation.inverted(); drawLitModel(model::RingworldInner, material::GenericPBR_RingworldInner, pos, innerRot); drawLitModel(model::RingworldLiving, material::RingworldSurface, pos, outerRot); // drawLitModel(model::RingworldAtmosphere, material::RingworldAtmo, pos, outerRot); } }; class DrawBlackhole : Draw3D { Node@ node; DrawBlackhole(Star@ star) { @node = star.getNode(); } void preRender(Object@ obj) { } void draw(const recti &in pos, quaterniond rotation) { @renderingNode = node; recti square = pos.aspectAligned(1.0); square = square.padded(-square.width*0.2, -square.height*0.2); model::Sphere_max.draw(material::Blackhole, square, rotation, 0.3); @renderingNode = null; } }; class DrawStar : Draw3D { Node@ node; double temp; DrawStar(Star@ star) { temp = star.temperature; @node = star.getNode(); } void preRender(Object@ obj) { shader::STAR_TEMP = temp; } void draw(const recti &in pos, quaterniond rotation) { @renderingNode = node; recti square = pos.aspectAligned(1.0); square = square.padded(-square.width*0.2, -square.height*0.2); model::Sphere_max.draw(material::PopupStarSurface, square, rotation, 1/1.5); material::Corona.draw(square); @renderingNode = null; } }; class Gui3DDisplay : BaseGuiElement { Draw3D@ drawMode; quaterniond rotation; Gui3DDisplay(BaseGuiElement@ parent, recti pos) { super(parent, pos); } Gui3DDisplay(BaseGuiElement@ parent, Alignment@ pos) { super(parent, pos); } void draw() { if(drawMode !is null) drawMode.draw(AbsolutePosition, rotation); BaseGuiElement::draw(); } }; enum ObjectAction { OA_LeftClick, OA_RightClick, OA_DoubleClick, OA_MiddleClick, }; Draw3D@ makeDrawMode(Object@ obj) { if(obj is null || !obj.valid || !obj.initialized) return null; switch(obj.type) { case OT_Planet: { Planet@ pl = cast(obj); if(pl.PlanetType == ringworldType) return DrawRingworld(pl); else return DrawPlanet(pl); } case OT_Orbital: { const OrbitalModule@ def = getOrbitalModule(cast(obj).coreModule); return DrawModel(def.model, def.material); } case OT_Ship: { const Hull@ hull = cast(obj).blueprint.design.hull; return DrawModel(hull.model, hull.material); } case OT_ColonyShip: { const Model@ model; const Material@ material; const Shipset@ ss = obj.owner.shipset; const ShipSkin@ skin; if(ss !is null) @skin = ss.getSkin("Colonizer"); if(obj.owner.ColonizerModel.length != 0) { @model = getModel(obj.owner.ColonizerModel); @material = getMaterial(obj.owner.ColonizerMaterial); } else if(skin !is null) { @model = skin.model; @material = skin.material; } else { @model = model::ColonyShip; @material = material::VolkurGenericPBR; } return DrawModel(model, material); } case OT_Freighter: { const Model@ model = model::Fighter; const Material@ material = material::Ship10; const Shipset@ ss = obj.owner.shipset; if(ss !is null) { auto@ skin = ss.getSkin(cast(obj).skin); if(skin !is null) { @model = skin.model; @material = skin.material; } } return DrawModel(model, material); } case OT_Asteroid: { const Model@ model; const Material@ material; switch(obj.id % 4) { case 0: @model = model::Asteroid1; break; case 1: @model = model::Asteroid2; break; case 2: @model = model::Asteroid3; break; case 3: @model = model::Asteroid4; break; } switch(obj.id % 3) { case 0: @material = material::AsteroidPegmatite; break; case 1: @material = material::AsteroidMagnetite; break; case 2: @material = material::AsteroidTonalite; break; } return DrawModel(model, material); } case OT_Anomaly: { Anomaly@ anom = cast(obj); return DrawModel(getModel(anom.model), getMaterial(anom.material)); } case OT_Artifact: { Artifact@ art = cast(obj); auto@ type = getArtifactType(art.ArtifactType); return DrawModel(type.model, type.material, quaterniond_fromAxisAngle(vec3d_up(), 0.5*pi)); } case OT_Star: { Star@ star = cast(obj); if(star.temperature > 0) return DrawStar(star); else return DrawBlackhole(star); } case OT_Pickup: { const PickupType@ type = getPickupType(cast(obj).PickupType); return DrawModel(type.model, type.material); } case OT_Civilian: { uint type = cast(obj).getCivilianType(); return DrawModel(getCivilianModel(obj.owner, type, obj.radius), getCivilianMaterial(obj.owner, type, obj.radius)); } } return null; } class Gui3DObject : Gui3DDisplay { Object@ obj; double dblClick = 0; quaterniond internalRotation; bool objectRotation = settings::bRotateUIObjects; Gui3DObject(BaseGuiElement@ parent, recti pos, Object@ Obj = null) { super(parent, pos); @object = Obj; } Gui3DObject(BaseGuiElement@ parent, Alignment@ pos, Object@ Obj = null) { super(parent, pos); @object = Obj; } void set_object(Object@ Obj) { if(Obj is obj) return; @obj = Obj; @drawMode = makeDrawMode(Obj); } Object@ get_object() { return obj; } void draw() { if(obj is null) return; //Update from object values if(objectRotation) { rotation = internalRotation * obj.node_rotation; rotation.normalize(); } else { rotation = internalRotation; } if(drawMode !is null) drawMode.preRender(obj); Empire@ owner = obj.owner; if(owner !is null) NODE_COLOR = owner.color; Gui3DDisplay::draw(); } bool onMouseEvent(const MouseEvent& evt, IGuiElement@ source) { switch(evt.type) { case MET_Button_Up: if(evt.button == 0) { if(frameTime < dblClick) { emitClicked(OA_DoubleClick); } else { emitClicked(OA_LeftClick); dblClick = frameTime + 0.2; } return true; } else if(evt.button == 1) { emitClicked(OA_RightClick); return true; } else if(evt.button == 2) { emitClicked(OA_MiddleClick); return true; } break; } return BaseGuiElement::onMouseEvent(evt, source); } };