Add item description and testing framework for Owniverse

- Introduced `item_description.gd` to handle item descriptions with localization support.
- Implemented a testing script `test_descriptions.gd` to validate item description rendering and localization.
- Added a new template file for Russian localization.
- Included a large package file `owniverse.0.6.29-145.pck` for game assets.
- Ensured proper memory management in tests with fixture and dispose functions.
This commit is contained in:
Kirill
2026-09-15 22:01:45 +03:00
parent 5f5cc6f894
commit cc2700d507
14 changed files with 1470 additions and 48 deletions
+24 -7
View File
@@ -29,14 +29,30 @@ func get_localized_item_description(item_id: String, item: String) -> String:
return "" return ""
# Russian templates include the class; legacy English keys omit it.
func get_template(id: String, category: String, field: String) -> Dictionary:
var rows: Dictionary = Templates.get(Locale, {})
for key in [id + "." + category + "." + field, id + "." + field]:
if rows.has(key):
return rows[key]
return {}
func render_template(row: Dictionary, variables: Dictionary) -> String:
var result: String = str(row.get("text", ""))
for i in range(5):
var variable: String = str(row.get("value" + str(i), "")).strip_edges()
var value: String = str(variables.get(variable, "—")) if variable != "" else ""
result = result.replace("%value" + str(i) + "%", value)
return result.replace("<br>", "\n").replace("[p]", "\n")
func get_description(item_id: String, items: Array = []) -> String: func get_description(item_id: String, items: Array = []) -> String:
if !Templates[Locale].has(item_id): var row: Dictionary = Templates.get(Locale, {}).get(item_id, {})
return "" var variables: Dictionary = {}
var description: String = Templates[Locale][item_id]["text"] for i in mini(items.size(), 5):
var value = 0 variables[str(row.get("value" + str(i), ""))] = items[i]
for item in items: return render_template(row, variables)
description.replace("value" + str(value), str(item))
return description
func format_number(value: float, digits: int = 0) -> String: func format_number(value: float, digits: int = 0) -> String:
@@ -58,6 +74,7 @@ func _ready() -> void:
Locales["ru"] = _read_from_csv("res://data/locale.ru.txt") Locales["ru"] = _read_from_csv("res://data/locale.ru.txt")
Templates["en"] = _read_from_csv("res://data/templates.en.txt") Templates["en"] = _read_from_csv("res://data/templates.en.txt")
Templates["ru"] = _read_from_csv("res://data/templates.ru.txt")
func _read_from_csv(file_path: String) -> Dictionary: func _read_from_csv(file_path: String) -> Dictionary:
+2 -2
View File
@@ -725,7 +725,7 @@ Aggression.Description|Evolution and competition.[p]%value0%: %value1%|scale|amo
Trends.Description|Actions of advanced civilizations.[p]Antitheism: %value0%[p]Integration: %value1%[p]Xenocide: %value2%[p]Reconstruction: %value3%[p]Spirituality: %value4%[p]|antitheism|integration|xenocide|reconstruction|spirituality Trends.Description|Actions of advanced civilizations.[p]Antitheism: %value0%[p]Integration: %value1%[p]Xenocide: %value2%[p]Reconstruction: %value3%[p]Spirituality: %value4%[p]|antitheism|integration|xenocide|reconstruction|spirituality
S.Description|%value0%[p]Voids: %value1%[p]Needed for placing objects.|amount|voids||| S.Description|%value0%[p]Voids: %value1%[p]Needed for placing objects.|amount|voids|||
H.Description|%value0%[p]Used to create clouds and stars.|amount|||| H.Description|%value0%[p]Used to create clouds and stars.|amount||||
He.Description|%value0%[p]Saves hydrogen.%value1%|amount he / h|||| He.Description|%value0%[p]Saves hydrogen.%value1%|amount|he / h|||
Met.Description|%value0%[p]Needed to create planets.[p]Metallicity: %value1%|amount|metallicity||| Met.Description|%value0%[p]Needed to create planets.[p]Metallicity: %value1%|amount|metallicity|||
N.Description|%value0%[p]Produces hydrogen.[p]%value2%[p]Baseline lifespan: %value3%|amount||colored costs|lifespan| N.Description|%value0%[p]Produces hydrogen.[p]%value2%[p]Baseline lifespan: %value3%|amount||colored costs|lifespan|
G.Description|%value0%[p]Produces more hydrogen.[p]%value2%[p]Baseline lifespan: %value3%|amount||colored costs|lifespan| G.Description|%value0%[p]Produces more hydrogen.[p]%value2%[p]Baseline lifespan: %value3%|amount||colored costs|lifespan|
@@ -1183,4 +1183,4 @@ Type1Civilizations.Path|GameHelp/en/Type1Civilizations|||||
Type2Civilizations.Path|GameHelp/en/Type2Civilizations||||| Type2Civilizations.Path|GameHelp/en/Type2Civilizations|||||
Type3Civilizations.Path|GameHelp/en/Type3Civilizations||||| Type3Civilizations.Path|GameHelp/en/Type3Civilizations|||||
Type4Civilizations.Path|GameHelp/en/Type4Civilizations||||| Type4Civilizations.Path|GameHelp/en/Type4Civilizations|||||
ButtonAbout.Image|Path/To/en/ButtonAbout.webp||||| ButtonAbout.Image|Path/To/en/ButtonAbout.webp|||||
File diff suppressed because it is too large Load Diff
+3
View File
@@ -0,0 +1,3 @@
[remap]
importer="skip"
+2 -2
View File
@@ -11,7 +11,7 @@ custom_features=""
export_filter="all_resources" export_filter="all_resources"
include_filter="" include_filter=""
exclude_filter="" exclude_filter=""
export_path="../../Documents/Owad/Owniverse.I/Builds/owniverse.0.6.28-144.exe" export_path="../../../Documents/Owad/Owniverse.I/Builds/owniverse.0.6.29-145.console.exe"
patches=PackedStringArray() patches=PackedStringArray()
patch_delta_encoding=false patch_delta_encoding=false
patch_delta_compression_level_zstd=19 patch_delta_compression_level_zstd=19
@@ -112,7 +112,7 @@ architectures/armeabi-v7a=false
architectures/arm64-v8a=true architectures/arm64-v8a=true
architectures/x86=false architectures/x86=false
architectures/x86_64=false architectures/x86_64=false
version/code=144 version/code=145
version/name="" version/name=""
package/unique_name="com.KIDGameProduction.Owniverse" package/unique_name="com.KIDGameProduction.Owniverse"
package/name="Owniverse" package/name="Owniverse"
Binary file not shown.
+1 -1
View File
@@ -15,7 +15,7 @@ general/updates_per_second=10
[application] [application]
config/name="Owniverse" config/name="Owniverse"
config/version="0.6.28" config/version="0.6.29"
run/main_scene="uid://bv384dpmvjv8o" run/main_scene="uid://bv384dpmvjv8o"
config/features=PackedStringArray("4.7", "Mobile") config/features=PackedStringArray("4.7", "Mobile")
boot_splash/show_image=false boot_splash/show_image=false
+38 -11
View File
@@ -4,6 +4,12 @@ const OWNIVERSE_ITEM = preload("uid://d3xjfxwe3w16v")
const SPEED_TEXTURE_NAME_TEMPLATE = "res://ui/topmenu/time&speed/time%s.png" const SPEED_TEXTURE_NAME_TEMPLATE = "res://ui/topmenu/time&speed/time%s.png"
const ItemDescription = preload("res://world/owniverse/item_description.gd")
var description_targets: Dictionary = {}
var description_samples: Dictionary = {}
var description_rates: Dictionary = {}
var description_elapsed: float = 0.0
const PAGE_COUNT = 5 const PAGE_COUNT = 5
const RESOURCE_PAGE = 1 const RESOURCE_PAGE = 1
const PAGE_WIDTH = 1080 const PAGE_WIDTH = 1080
@@ -123,20 +129,40 @@ func _on_indicator_pressed(indicator_name: String, page: int = 0):
func _set_item_description(item: OwniverseItem) -> void: func _set_item_description(item: OwniverseItem) -> void:
var description: String = "[b]" \ var category: String = "Entity" if owniverse.entities.has(item.item_id) else "Force"
+ Global.get_localized_item_description(item.item_name, "label") \ var id: String = item.item_id if category == "Entity" else item.item_name.capitalize()
+"[/b]" \ var page: int = clampi(item.item_page, 0, 4)
+"\n" \ if description_targets.get(page, {}).get("id", "") != id:
+ Global.get_localized_item_description(item.item_name, "description") description_samples.erase(id)
var desc_page = clamp(item.item_page, 0, 4) description_rates.erase(id)
g_item_descriptions[desc_page].text = description description_targets[page] = {"id": id, "category": category}
_refresh_descriptions()
func _set_description(item_name: String, page: int) -> void: func _set_description(item_name: String, page: int) -> void:
var description = Global.get_description(item_name + ".Name") description_targets[page] = {"id": item_name, "category": "Indicator"}
description += "\n" _refresh_descriptions()
description += Global.get_description(item_name + ".Description")
g_item_descriptions[page].text = description
func _refresh_descriptions() -> void:
for page in description_targets:
var target: Dictionary = description_targets[page]
var label: RichTextLabel = g_item_descriptions[page]
label.bbcode_enabled = true
label.text = ItemDescription.render(owniverse, Global, target.id, target.category, description_rates.get(target.id, 0.0))
func _update_descriptions(delta: float) -> void:
description_elapsed += delta
if description_elapsed < 0.25:
return
for page in description_targets:
var id: String = description_targets[page].id
var total: float = ItemDescription.quantities(owniverse, id).total
description_rates[id] = (total - description_samples[id]) / description_elapsed if description_samples.has(id) else 0.0
description_samples[id] = total
description_elapsed = 0.0
_refresh_descriptions()
func _control_page(item: OwniverseItem) -> void: func _control_page(item: OwniverseItem) -> void:
@@ -299,6 +325,7 @@ func _ready() -> void:
func _process(delta: float) -> void: func _process(delta: float) -> void:
owniverse.evolute(delta) owniverse.evolute(delta)
_update_descriptions(delta)
set_owniverse_item_value() set_owniverse_item_value()
set_datetime(owniverse.state.time.year) set_datetime(owniverse.state.time.year)
+12
View File
@@ -34,3 +34,15 @@ godot --headless --path Owniverse.GI --script res://tests/test_stellar_rules.gd
Создание планет подключено к ручному и автоматическому производству звёзд. Бласты обрабатываются как события, а не ресурс. Выжившие планеты переходят преемнику звезды пропорционально числу реально полученных преемников; при отсутствии преемника освобождаются. Локальное разрушение выполняется перед передачей. Создание планет подключено к ручному и автоматическому производству звёзд. Бласты обрабатываются как события, а не ресурс. Выжившие планеты переходят преемнику звезды пропорционально числу реально полученных преемников; при отсутствии преемника освобождаются. Локальное разрушение выполняется перед передачей.
Дополнительно проверяются частичная передача, альтернативные преемники, уровни разрушения 1/2, накопление слабых бластов, сохранения, ручное/автоматическое создание планет и несколько поколений за длинный шаг. Правила и формулы описаны в `../simulation_rules.md`. Дополнительно проверяются частичная передача, альтернативные преемники, уровни разрушения 1/2, накопление слабых бластов, сохранения, ручное/автоматическое создание планет и несколько поколений за длинный шаг. Правила и формулы описаны в `../simulation_rules.md`.
## Описания выбранных объектов
```sh
godot --headless --path Owniverse.GI --script res://tests/test_descriptions.gd
```
Источник текста — `Global.Templates[Global.Locale]`. Заголовок берётся из `Name`, основной текст — из `Description`. Поддерживаются ключи с классом (`RD.Entity.Description`) и старые ключи без класса (`RD.Description`).
`%valueN%` заменяется значением переменной, имя которой записано в поле `valueN` этой строки. Поддерживаются `amount`, `colored costs`, `lifespan`, `voids`, `he / h`, `metallicity`, показатели энергии, плотности и скорости времени. `amount1`–`amount4` сил пока отображаются как `—`; неизвестные непустые обозначения тоже дают `—`, пустые поля — пустую строку. `[p]` превращается в разделение абзацев, цветовые BBCode-теги сохраняются.
Доступные требования зелёные, недоступные красные. Для объектов со связанными экземплярами выводится доступное количество и серым общее; для планет — общее количество. Скорость изменения вычисляется по реальному времени и обновляется раз в 0,25 секунды. Доли He/H вычисляются из текущих свободных запасов; при пустой смеси показывается `—`. Металличность и плотность используют расчёт среды GI. Счётчики исходной материи и этики Unity в текущей GI отсутствуют и здесь не добавляются.
+88
View File
@@ -0,0 +1,88 @@
extends SceneTree
const Clock = preload("res://world/owniverse/simulation_time.gd")
var checks: int = 0
var failures: int = 0
func _initialize() -> void:
call_deferred("run")
func check(condition: bool, message: String) -> void:
checks += 1
if not condition:
failures += 1
push_error(message)
func fixture():
var world = load("res://world/owniverse/owniverse.gd").new()
var global: Node = root.get_node("Global")
for id in global.OwniverseEntities:
var entity = load("res://world/owniverse/owniverse_entity.gd").new(global.OwniverseEntities[id])
world.entities[id] = entity
world.state.amount[id] = 0.0
world.state.stats.total_amount[id] = 0.0
if entity.group_as != "":
world.state.amount[entity.group_as] = 0.0
world.state.stats.total_amount[entity.group_as] = 0.0
world.entities["N"].life_product = {}
world.entities["N"].product_per_year_type = "H"
world.entities["N"].product_per_year_amount = 10.0
world.entities["N"].auto = 0.0
world.state.amount.N = 1.0
return world
func dispose(world) -> void:
for entity in world.entities.values():
entity.free()
world.free()
func run() -> void:
var global: Node = root.get_node("Global")
var description = load("res://world/owniverse/item_description.gd")
var world = fixture()
world.state.amount.H = 8.0
world.state.amount.He = 2.0
for locale in ["en", "ru"]:
global.Locale = locale
var text: String = description.render(world, global, "RD")
check(text.contains("[b]") and not text.contains("%value"), "Localized template resolved: " + locale)
check(text.contains("#40cc40"), "Affordable cost green: " + locale)
check(text.contains("4.0000E+10"), "Lifespan substituted: " + locale)
text = description.render(world, global, "He")
check(text.contains("He: 20.00% / H: 80.00%") and not text.contains("%value"), "Helium metadata and mixture: " + locale)
text = description.render(world, global, "Shovelin", "Force")
check(text.count("]—[/color]") == 4, "Missing force levels use dash: " + locale)
text = description.render(world, global, "YD")
check(text.contains("#ff6060"), "Insufficient cost red: " + locale)
var reordered: Dictionary = {"text": "%value0% / %value1%", "value0": "lifespan", "value1": "amount"}
check(global.render_template(reordered, {"amount": "12", "lifespan": "99"}) == "99 / 12", "Metadata chooses variables, not fixed argument positions")
world.state.amount.RD = 2.0
world.state.binds.G = {"RD": 3.0, "HP": 7.0}
var values: Dictionary = description.variables(world, global, "RD", -2.0)
check(values.amount.contains("2") and values.amount.contains("(5)") and values.amount.contains("#888888"), "Free and total counts with gray binding total")
check(values.amount.contains("#ff6060") and values.amount.contains("−2.0"), "Real-time decrease red")
values = description.variables(world, global, "HP")
check(values.amount == "7", "Planet description includes bound planets")
values = description.variables(world, global, "RD", 2.0)
check(values.amount.contains("#40cc40") and values.amount.contains("+2.0"), "Increase green")
var stage_script = load("res://stage/stage.gd")
check(stage_script.can_instantiate(), "Stage integration compiles")
var stage = stage_script.new()
stage.owniverse.free()
stage.owniverse = world
var label: RichTextLabel = RichTextLabel.new()
stage.g_item_descriptions = [label]
stage.description_targets[0] = {"id": "RD", "category": "Entity"}
stage._refresh_descriptions()
check(label.bbcode_enabled and label.text.contains("Красный карлик"), "Stage displays localized rich text")
stage._update_descriptions(0.25)
world.state.amount.RD += 1.0
stage._update_descriptions(0.25)
check(label.text.contains("+4.0"), "Selected description refreshes with rate per real second")
global.Locale = "en"
stage._update_descriptions(0.25)
check(label.text.contains("Red Dwarf"), "Selected description follows locale changes")
label.free()
stage.free()
dispose(world)
print("Descriptions: %d checks, %d failures" % [checks, failures])
quit(0 if failures == 0 else 1)
+1
View File
@@ -0,0 +1 @@
uid://b1efrwyimgle7
+87
View File
@@ -0,0 +1,87 @@
extends RefCounted
const GREEN = "#40cc40"
const RED = "#ff6060"
const GREY = "#888888"
static func number(value: float, digits: int = 0) -> String:
if not is_finite(value):
return "—"
if absf(value) >= 1e5:
var exponent: int = int(floor(log(absf(value)) / log(10.0)))
return "%.4fE%+d" % [value / pow(10.0, exponent), exponent]
return "%.*f" % [digits, value]
static func colored(text: String, color: String) -> String:
return "[color=" + color + "]" + text + "[/color]"
static func matches(world, id: String) -> Array:
var result: Array = []
for key in world.entities:
var entity = world.entities[key]
if key == id or entity.count_as == id or entity.group_as == id:
if not world._is_group(key):
result.append(key)
return result
static func quantities(world, id: String) -> Dictionary:
var free: float = 0.0
var total: float = 0.0
var physical: Dictionary = world._physical_amounts(world.state)
for key in matches(world, id):
free += world.state.amount.get(key, 0.0)
total += physical.get(key, 0.0)
if id == "SMBH":
free = world.state.amount.get(id, 0.0)
total = free
return {"free": free, "total": total}
static func costs(world, global: Node, id: String) -> String:
if not world.entities.has(id):
return ""
var lines: PackedStringArray = []
for requirements in [world.entities[id].cost, world.entities[id].bind]:
for resource in requirements:
var required: float = requirements[resource]
if required < 0.0:
continue
var available: float = floorf(world._available(world.state, resource))
var name: String = str(global.get_template(resource, "Entity", "Name").get("text", resource))
lines.append(colored(name + ": " + number(required) + " (" + number(available) + ")", GREEN if available >= required else RED))
return "\n".join(lines)
static func variables(world, global: Node, id: String, rate: float = 0.0) -> Dictionary:
var counts: Dictionary = quantities(world, id)
var show_total: bool = false
for key in matches(world, id):
show_total = show_total or world.entities[key].group_as == "Planet"
var amount: String = number(counts.total if show_total else counts.free) if world.entities.has(id) else "—"
if not show_total and counts.total > counts.free:
amount += " " + colored("(" + number(counts.total) + ")", GREY)
if rate != 0.0:
amount += " | " + colored(("−" if rate < 0.0 else "+") + number(absf(rate), 1), RED if rate < 0.0 else GREEN)
var physical: Dictionary = world._physical_amounts(world.state)
var voids: float = 0.0
for key in physical:
voids += physical[key] * world.entities[key].voids
var he: float = world.state.amount.get("He", 0.0)
var h: float = world.state.amount.get("H", 0.0)
var mixture: String = "—"
if he + h > 0.0:
mixture = "He: " + number(100.0 * he / (he + h), 2) + "% / H: " + number(100.0 * h / (he + h), 2) + "%"
var environment: Dictionary = world.stellar_environment(world.state)
return {
"amount": amount, "colored costs": costs(world, global, id),
"lifespan": number(world.entities[id].lifespan) if world.entities.has(id) else "—",
"voids": number(voids), "he / h": "\n" + mixture,
"metallicity": number(environment.metallicity * 100.0, 2) + "%",
"энергия": number(world.state.energy), "плотность": number(environment.density, 6),
"лет в секунду": number(world.state.speed_in_year),
"amount1": "—", "amount2": "—", "amount3": "—", "amount4": "—",
}
static func render(world, global: Node, id: String, category: String = "Entity", rate: float = 0.0) -> String:
var values: Dictionary = variables(world, global, id, rate)
var title: String = global.render_template(global.get_template(id, category, "Name"), values)
var body: String = global.render_template(global.get_template(id, category, "Description"), values)
return "[b]" + (title if title != "" else id) + "[/b]\n" + body
+1
View File
@@ -0,0 +1 @@
uid://dumnryq20c2ij
+25 -25
View File
@@ -227,11 +227,11 @@ theme_override_fonts/normal_font = ExtResource("14_o7xkw")
theme_override_fonts/bold_font = ExtResource("7_gwdna") theme_override_fonts/bold_font = ExtResource("7_gwdna")
theme_override_fonts/bold_italics_font = ExtResource("15_bfrib") theme_override_fonts/bold_italics_font = ExtResource("15_bfrib")
theme_override_fonts/italics_font = ExtResource("16_mip0j") theme_override_fonts/italics_font = ExtResource("16_mip0j")
theme_override_font_sizes/normal_font_size = 42 theme_override_font_sizes/normal_font_size = 34
theme_override_font_sizes/bold_font_size = 54 theme_override_font_sizes/bold_font_size = 34
theme_override_font_sizes/bold_italics_font_size = 42 theme_override_font_sizes/bold_italics_font_size = 34
theme_override_font_sizes/italics_font_size = 42 theme_override_font_sizes/italics_font_size = 34
theme_override_font_sizes/mono_font_size = 42 theme_override_font_sizes/mono_font_size = 34
bbcode_enabled = true bbcode_enabled = true
horizontal_alignment = 1 horizontal_alignment = 1
@@ -370,11 +370,11 @@ theme_override_fonts/normal_font = ExtResource("14_o7xkw")
theme_override_fonts/bold_font = ExtResource("7_gwdna") theme_override_fonts/bold_font = ExtResource("7_gwdna")
theme_override_fonts/bold_italics_font = ExtResource("15_bfrib") theme_override_fonts/bold_italics_font = ExtResource("15_bfrib")
theme_override_fonts/italics_font = ExtResource("16_mip0j") theme_override_fonts/italics_font = ExtResource("16_mip0j")
theme_override_font_sizes/normal_font_size = 42 theme_override_font_sizes/normal_font_size = 34
theme_override_font_sizes/bold_font_size = 54 theme_override_font_sizes/bold_font_size = 34
theme_override_font_sizes/bold_italics_font_size = 42 theme_override_font_sizes/bold_italics_font_size = 34
theme_override_font_sizes/italics_font_size = 42 theme_override_font_sizes/italics_font_size = 34
theme_override_font_sizes/mono_font_size = 42 theme_override_font_sizes/mono_font_size = 34
bbcode_enabled = true bbcode_enabled = true
horizontal_alignment = 1 horizontal_alignment = 1
@@ -498,11 +498,11 @@ theme_override_fonts/normal_font = ExtResource("14_o7xkw")
theme_override_fonts/bold_font = ExtResource("7_gwdna") theme_override_fonts/bold_font = ExtResource("7_gwdna")
theme_override_fonts/bold_italics_font = ExtResource("15_bfrib") theme_override_fonts/bold_italics_font = ExtResource("15_bfrib")
theme_override_fonts/italics_font = ExtResource("16_mip0j") theme_override_fonts/italics_font = ExtResource("16_mip0j")
theme_override_font_sizes/normal_font_size = 42 theme_override_font_sizes/normal_font_size = 34
theme_override_font_sizes/bold_font_size = 54 theme_override_font_sizes/bold_font_size = 34
theme_override_font_sizes/bold_italics_font_size = 42 theme_override_font_sizes/bold_italics_font_size = 34
theme_override_font_sizes/italics_font_size = 42 theme_override_font_sizes/italics_font_size = 34
theme_override_font_sizes/mono_font_size = 42 theme_override_font_sizes/mono_font_size = 34
bbcode_enabled = true bbcode_enabled = true
text = "Stars" text = "Stars"
horizontal_alignment = 1 horizontal_alignment = 1
@@ -639,11 +639,11 @@ theme_override_fonts/normal_font = ExtResource("14_o7xkw")
theme_override_fonts/bold_font = ExtResource("7_gwdna") theme_override_fonts/bold_font = ExtResource("7_gwdna")
theme_override_fonts/bold_italics_font = ExtResource("15_bfrib") theme_override_fonts/bold_italics_font = ExtResource("15_bfrib")
theme_override_fonts/italics_font = ExtResource("16_mip0j") theme_override_fonts/italics_font = ExtResource("16_mip0j")
theme_override_font_sizes/normal_font_size = 42 theme_override_font_sizes/normal_font_size = 34
theme_override_font_sizes/bold_font_size = 54 theme_override_font_sizes/bold_font_size = 34
theme_override_font_sizes/bold_italics_font_size = 42 theme_override_font_sizes/bold_italics_font_size = 34
theme_override_font_sizes/italics_font_size = 42 theme_override_font_sizes/italics_font_size = 34
theme_override_font_sizes/mono_font_size = 42 theme_override_font_sizes/mono_font_size = 34
bbcode_enabled = true bbcode_enabled = true
text = "Structures" text = "Structures"
horizontal_alignment = 1 horizontal_alignment = 1
@@ -787,11 +787,11 @@ theme_override_fonts/normal_font = ExtResource("14_o7xkw")
theme_override_fonts/bold_font = ExtResource("7_gwdna") theme_override_fonts/bold_font = ExtResource("7_gwdna")
theme_override_fonts/bold_italics_font = ExtResource("15_bfrib") theme_override_fonts/bold_italics_font = ExtResource("15_bfrib")
theme_override_fonts/italics_font = ExtResource("16_mip0j") theme_override_fonts/italics_font = ExtResource("16_mip0j")
theme_override_font_sizes/normal_font_size = 42 theme_override_font_sizes/normal_font_size = 34
theme_override_font_sizes/bold_font_size = 54 theme_override_font_sizes/bold_font_size = 34
theme_override_font_sizes/bold_italics_font_size = 42 theme_override_font_sizes/bold_italics_font_size = 34
theme_override_font_sizes/italics_font_size = 42 theme_override_font_sizes/italics_font_size = 34
theme_override_font_sizes/mono_font_size = 42 theme_override_font_sizes/mono_font_size = 34
bbcode_enabled = true bbcode_enabled = true
text = "Planets" text = "Planets"
horizontal_alignment = 1 horizontal_alignment = 1