Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion C7/Assets
16 changes: 15 additions & 1 deletion C7/Lua/civ3/ruleset.json
Original file line number Diff line number Diff line change
Expand Up @@ -13020,5 +13020,19 @@
"distanceBetweenCivs": 24,
"numberOfCivs": 16
}
]
],
"victoryConditions": {
"allowDominationVictory": true,
"allowSpaceRaceVictory": true,
"allowDiplomaticVictory": true,
"allowConquestVictory": true,
"allowCulturalVictory": true,
"allowWonderVictory": false,
"cityElimination": false,
"regicide": false,
"massRegicide": false,
"victoryLocations": false,
"captureTheFlag": false,
"reverseCaptureTheFlag": false
}
}
18 changes: 18 additions & 0 deletions C7/Lua/civ3/textures.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ local ROOT = "Art/"
local ADVISORS = "Art/Advisors/"

local BUTTONS = "Art/buttonsFINAL.pcx"
local CHECKBOXES = "Art/3checkboxes-USE.pcx"
local EXIT_BOX = "Art/exitBox-backgroundStates.pcx"
local INTERFACE = "Art/interface/"
local X_O = "Art/X-o_ALLstates-sprite.pcx"
Expand Down Expand Up @@ -185,6 +186,23 @@ textures.ui = {
shadows = false,
},
},
checkbox = {
inactive = {
path = CHECKBOXES,
crop_region = { 1, 1, 15, 15 },
shadows = false,
},
hover = {
path = CHECKBOXES,
crop_region = { 17, 1, 15, 15 },
shadows = false,
},
pressed = {
path = CHECKBOXES,
crop_region = { 33, 1, 15, 15 },
shadows = false,
},
},
confirm = {
normal = {
path = X_O,
Expand Down
2 changes: 2 additions & 0 deletions C7/Lua/standalone/textures.lua
Original file line number Diff line number Diff line change
Expand Up @@ -113,8 +113,10 @@ local c7_texture_list = {
"Art/Advisors/culture.png",
"Art/Advisors/demographics.png",
"Art/Advisors/wonders_background.png",
"Art/Advisors/domestic_plusminus.png",
"Art/histograph-win5_final.png",
"Art/histograph-top5_final.png",
"Art/3checkboxes-USE.png"
}

--- For ease of editing, we define the civ colors as hex codes, not 1x1 px images
Expand Down
170 changes: 170 additions & 0 deletions C7/UIElements/Civ3Checkbox.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
using Godot;
using System;

// The standard civ3 checkbox with text attached.
[GlobalClass]
[Tool]
public partial class Civ3Checkbox : CheckBox {
public enum TextPosition {
TextLeftOfIcon,
TextRightOfIcon,
TextAboveIcon,
TextBelowIcon
}

private Texture2D normalTexture = TextureLoader.Load("ui.checkbox.inactive");
private Texture2D hoverTexture = TextureLoader.Load("ui.checkbox.hover");
private Texture2D pressedTexture = TextureLoader.Load("ui.checkbox.pressed");

private string _text;
[Export]
public string Text {
get => _text;
set {
_text = value;
if (label != null) {
label.Text = _text;
}
}
}
private int _fontSize;
[Export]
public int FontSize {
get => _fontSize;
set {
_fontSize = value;
if (label != null) {
label.AddThemeFontSizeOverride("font_size", _fontSize);
}
}
}
private TextPosition _textPosition;
[Export]
public TextPosition textPosition {
get => _textPosition;
set {
_textPosition = value;
if (label != null && textureRect != null) {
SetUpLayout();
}
}
}

private Color fontColor;
private Color hoverColor;
private Color pressedColor;

private Label label;
private TextureRect textureRect;
private BoxContainer boxContainer;

private bool hovered = false;

public Civ3Checkbox(TextPosition textPosition = TextPosition.TextRightOfIcon) {
this.textPosition = textPosition;

Flat = true;
FontSize = 12;
SizeFlagsHorizontal = SizeFlags.Expand;
SizeFlagsVertical = SizeFlags.ShrinkCenter;
}

public override void _Ready() {
fontColor = GetThemeColor("font_color", "Button");
hoverColor = GetThemeColor("font_hover_color", "Button");
pressedColor = GetThemeColor("font_pressed_color", "Button");

// Set up the label and texture.
label = new() {
Text = Text,
MouseFilter = MouseFilterEnum.Pass,
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center,
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter,
};
label.AddThemeFontSizeOverride("font_size", FontSize);

textureRect = new() {
Texture = normalTexture,
MouseFilter = MouseFilterEnum.Pass,
CustomMinimumSize = new Vector2(normalTexture.GetWidth(), normalTexture.GetHeight()),
ExpandMode = TextureRect.ExpandModeEnum.KeepSize,
SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
SizeFlagsVertical = SizeFlags.ShrinkCenter,
};

SetUpLayout();

// Hook up our code to the button signals.
MouseEntered += () => {
hovered = true;
UpdateVisuals();
};
MouseExited += () => {
hovered = false;
UpdateVisuals();
};
Pressed += UpdateVisuals;
Toggled += (bool toggledOn) => { UpdateVisuals(); };

UpdateVisuals();
}

private void SetUpLayout() {
if (boxContainer != null) {
boxContainer.RemoveChild(label);
boxContainer.RemoveChild(textureRect);
RemoveChild(boxContainer);
boxContainer.QueueFree();
}

// Depending on the text positioning, add the label and texture as children
// of the appropriate layout.
if (textPosition == TextPosition.TextAboveIcon || textPosition == TextPosition.TextBelowIcon) {
boxContainer = new VBoxContainer();
} else {
boxContainer = new HBoxContainer() {
Alignment = (textPosition == TextPosition.TextLeftOfIcon) ? BoxContainer.AlignmentMode.End : BoxContainer.AlignmentMode.Begin,
};
}
boxContainer.SetAnchorsPreset(LayoutPreset.FullRect);
boxContainer.MouseFilter = MouseFilterEnum.Pass;
AddChild(boxContainer);

if (textPosition == TextPosition.TextAboveIcon || textPosition == TextPosition.TextLeftOfIcon) {
boxContainer.AddChild(label);
boxContainer.AddChild(textureRect);
} else {
boxContainer.AddChild(textureRect);
boxContainer.AddChild(label);
}
}

// Expand the size of the button to contain the texture and the label.
public override Vector2 _GetMinimumSize() {
if (boxContainer == null) {
return base._GetMinimumSize();
}
return boxContainer.GetCombinedMinimumSize();
}

public void UpdateVisuals() {
Texture2D currentTexture = normalTexture;
Color currentTextColor = fontColor;

// ButtonPressed is true if ToggleMode is on and button is selected
bool isEffectivelyPressed = (ToggleMode && ButtonPressed);

if (isEffectivelyPressed) {
currentTexture = pressedTexture;
currentTextColor = pressedColor;
} else if (hovered) {
currentTexture = hoverTexture;
currentTextColor = hoverColor;
}

textureRect.Texture = currentTexture;
label.AddThemeColorOverride("font_color", currentTextColor);
}
}
1 change: 1 addition & 0 deletions C7/UIElements/Civ3Checkbox.cs.uid
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
uid://b4grm7mhaqgri
121 changes: 117 additions & 4 deletions C7/UIElements/GameViews/VictoryStatusView.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
using System.Collections.Generic;
using System.Linq;
using C7Engine;
using C7GameData;
using Godot;
Expand All @@ -7,15 +9,23 @@
public partial class VictoryStatusView : Control {

[Export] public TextureRect background;
[Export] public GridContainer gridHeader;
[Export] public GridContainer grid;
[Export] public float LabelColumnWidth = 185f;
[Export] public float ValueColumnWidth = 40f;

private TextureButton _close;

private const int GridHeaderColumns = 3;
private const int GridColumns = 6;

public VictoryStatusView() {
MouseFilter = MouseFilterEnum.Stop;
}

public override void _Ready() {
this.CreateUI();
CreateUI();
ConfigureGrid();
}

private void CreateUI() {
Expand All @@ -28,12 +38,115 @@ private void CreateUI() {
AdvisorUtils.CreateAdvisorTitle(background, background.Texture.GetWidth(), "VICTORY STATUS");
}

private void ConfigureGrid() {
gridHeader.Columns = GridHeaderColumns;
gridHeader.AddThemeConstantOverride("h_separation", 0); // horizontal gap between columns
gridHeader.AddThemeConstantOverride("v_separation", 5);

grid.Columns = GridColumns;
grid.AddThemeConstantOverride("h_separation", 0); // horizontal gap between columns
grid.AddThemeConstantOverride("v_separation", 5);
}

public void ShowView() {
Show();

EngineStorage.ReadGameData((GameData gameData) => {
Player player = gameData.GetFirstHumanPlayer();
EngineStorage.ReadGameData(DrawGrid);
}

private void DrawGrid(GameData gameData) {
ClearGrid();

Player player = gameData.GetFirstHumanPlayer();
List<Player> rivals = gameData.GetKnownRivals(player);

// Render

AddTitleRow("To Win", player.civilization.name, "Top Rival");

foreach (IVictory vc in gameData.victories) {
ProcessVictoryCondition(vc, gameData, player, rivals);
}
}

private void ProcessVictoryCondition(IVictory dv, GameData gameData, Player player, List<Player> rivals) {
VictoryStatus status = dv.Evaluate(player, gameData);
List<VictoryStatus> rivalStatuses = rivals.Select(r => dv.Evaluate(r, gameData)).ToList();

AddHeaderRow(dv.Header());

foreach (string[] output in dv.GenerateStatusRows(status, rivalStatuses)) {
AddDataRow(output);
}
}

private void ClearGrid() {
foreach (Node child in gridHeader.GetChildren())
child.QueueFree();

foreach (Node child in grid.GetChildren())
child.QueueFree();
}

// TODO: Make more use of Godot UI instead of character-base dynamic hackery

private const string HeaderPadding = " ";
Comment thread
ajhalme marked this conversation as resolved.
private const string Padding = " ";

/// Titles; column headers
public void AddTitleRow(params string[] values) {
for (int i = 0; i < GridHeaderColumns; i++) {
var label = MakeLabel(values[i] + HeaderPadding, ValueColumnWidth, HorizontalAlignment.Right);
label.SizeFlagsHorizontal = SizeFlags.ExpandFill;
label.AddThemeFontSizeOverride("font_size", 18);
gridHeader.AddChild(label);
}
}

/// A bold, full-width section header row (e.g. "Domination", "Cultural").
public void AddHeaderRow(string text) {
var label = MakeLabel(text, LabelColumnWidth, HorizontalAlignment.Left);
label.AddThemeFontSizeOverride("font_size", 20);
grid.AddChild(label);

for (int i = 1; i < GridColumns; i++) {
bool isLabelCol = i % 2 == 0;
grid.AddChild(MakeSpacer(isLabelCol ? LabelColumnWidth : ValueColumnWidth));
}
}

private Label MakeLabel(string text, float width, HorizontalAlignment align) {
var label = new Label
{
Text = text,
HorizontalAlignment = align,
CustomMinimumSize = new Vector2(width, 0),
SizeFlagsHorizontal = SizeFlags.ShrinkBegin // don't stretch beyond min width
};
return label;
}

private Control MakeSpacer(float width) {
return new Control { CustomMinimumSize = new Vector2(width, 0) };
}

/// A data row: label, value; label, value; label, value
public void AddDataRow(params string[] values) {
for (int i = 0; i < GridColumns; i++) {
string valueText = i < values.Length ? values[i] : "";
bool isLabelCol = i % 2 == 0;

var valueNode = new Label
{
Text = isLabelCol ? valueText : valueText + Padding,
HorizontalAlignment = isLabelCol ? HorizontalAlignment.Left : HorizontalAlignment.Right,
SizeFlagsHorizontal = SizeFlags.ExpandFill
};
if (isLabelCol) {
valueNode.AutowrapMode = TextServer.AutowrapMode.WordSmart;
}

});
grid.AddChild(valueNode);
}
}
}
Loading
Loading