mirror of
https://github.com/amyinspace/MagicSetEditor2.git
synced 2026-06-10 04:57:00 -04:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2f83850b60 |
@@ -54,8 +54,6 @@ menu:
|
|||||||
next card: 选择下一张卡牌 PgDn
|
next card: 选择下一张卡牌 PgDn
|
||||||
search cards: 搜索卡 Ctrl+K
|
search cards: 搜索卡 Ctrl+K
|
||||||
add card: 添加卡牌 Ctrl+Enter
|
add card: 添加卡牌 Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: 批量添加卡牌...
|
add cards: 批量添加卡牌...
|
||||||
remove card: 删除所选卡牌
|
remove card: 删除所选卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -210,8 +208,6 @@ help:
|
|||||||
next card: 选择列表中的下一张卡牌
|
next card: 选择列表中的下一张卡牌
|
||||||
search cards: 使用搜索词过滤卡片列表
|
search cards: 使用搜索词过滤卡片列表
|
||||||
add card: 添加一个新的空白卡牌到本套牌
|
add card: 添加一个新的空白卡牌到本套牌
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: 添加多张卡牌到本套牌
|
add cards: 添加多张卡牌到本套牌
|
||||||
remove card: 从本套牌中删除所选卡牌
|
remove card: 从本套牌中删除所选卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -472,8 +468,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: 添加卡牌
|
add card: 添加卡牌
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: 移除选中卡牌
|
remove card: 移除选中卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -764,8 +758,6 @@ label:
|
|||||||
installable version: 最新版本
|
installable version: 最新版本
|
||||||
installer size: 尺寸
|
installer size: 尺寸
|
||||||
installer status: 地位
|
installer status: 地位
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -898,8 +890,6 @@ button:
|
|||||||
upgrade package: 升级
|
upgrade package: 升级
|
||||||
reinstall package: 重新安装
|
reinstall package: 重新安装
|
||||||
remove package: 移除
|
remove package: 移除
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: 全部安装
|
install group: 全部安装
|
||||||
upgrade group: 全部升级
|
upgrade group: 全部升级
|
||||||
remove group: 全部移除
|
remove group: 全部移除
|
||||||
@@ -991,8 +981,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1142,9 +1130,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: 坐标混合重叠
|
coordinates for blending overlap: 坐标混合重叠
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ menu:
|
|||||||
next card: 選擇下一張卡牌 PgDn
|
next card: 選擇下一張卡牌 PgDn
|
||||||
search cards: 搜尋卡 Ctrl+K
|
search cards: 搜尋卡 Ctrl+K
|
||||||
add card: 添加卡牌 Ctrl+Enter
|
add card: 添加卡牌 Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: 批量添加卡牌...
|
add cards: 批量添加卡牌...
|
||||||
remove card: 刪除所選卡牌
|
remove card: 刪除所選卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -210,8 +208,6 @@ help:
|
|||||||
next card: 選擇列表中的下一張卡牌
|
next card: 選擇列表中的下一張卡牌
|
||||||
search cards: 使用搜尋字詞過濾卡片列表
|
search cards: 使用搜尋字詞過濾卡片列表
|
||||||
add card: 添加一個新的空白卡牌到本套牌
|
add card: 添加一個新的空白卡牌到本套牌
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: 添加多張卡牌到本套牌
|
add cards: 添加多張卡牌到本套牌
|
||||||
remove card: 從本套牌中刪除所選卡牌
|
remove card: 從本套牌中刪除所選卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -470,8 +466,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: 添加卡牌
|
add card: 添加卡牌
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: 移除選中卡牌
|
remove card: 移除選中卡牌
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -762,8 +756,6 @@ label:
|
|||||||
installable version: 最新版本
|
installable version: 最新版本
|
||||||
installer size: 尺寸
|
installer size: 尺寸
|
||||||
installer status: 地位
|
installer status: 地位
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -896,8 +888,6 @@ button:
|
|||||||
upgrade package: 昇級
|
upgrade package: 昇級
|
||||||
reinstall package: 重新安裝
|
reinstall package: 重新安裝
|
||||||
remove package: 移除
|
remove package: 移除
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: 全部安裝
|
install group: 全部安裝
|
||||||
upgrade group: 全部昇級
|
upgrade group: 全部昇級
|
||||||
remove group: 全部移除
|
remove group: 全部移除
|
||||||
@@ -989,8 +979,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1140,9 +1128,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: 坐標混合重疊
|
coordinates for blending overlap: 坐標混合重疊
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -56,8 +56,6 @@ menu:
|
|||||||
next card: Vælg &Næste Kort PgDn
|
next card: Vælg &Næste Kort PgDn
|
||||||
search cards: &Søg kort Ctrl+K
|
search cards: &Søg kort Ctrl+K
|
||||||
add card: &Tilføj Kort Ctrl+Enter
|
add card: &Tilføj Kort Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: Tilføj &Flere Kort...
|
add cards: Tilføj &Flere Kort...
|
||||||
remove card: &Slet Valgte Kort
|
remove card: &Slet Valgte Kort
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -216,8 +214,6 @@ help:
|
|||||||
next card: Vælger det næste kort i listen
|
next card: Vælger det næste kort i listen
|
||||||
search cards: Filtrer kortlisten ved hjælp af søgetermer
|
search cards: Filtrer kortlisten ved hjælp af søgetermer
|
||||||
add card: Tilføler et nyt, tomt kort til listen
|
add card: Tilføler et nyt, tomt kort til listen
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: Tilføjer flere kort til listen
|
add cards: Tilføjer flere kort til listen
|
||||||
remove card: Sletter det valgte kort fra sættet!
|
remove card: Sletter det valgte kort fra sættet!
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -481,8 +477,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Tilføj kort
|
add card: Tilføj kort
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: Fjern valgte kort
|
remove card: Fjern valgte kort
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -780,8 +774,6 @@ label:
|
|||||||
installable version: seneste version:
|
installable version: seneste version:
|
||||||
installer size: Størrelse:
|
installer size: Størrelse:
|
||||||
installer status: Status:
|
installer status: Status:
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -914,8 +906,6 @@ button:
|
|||||||
upgrade package: &Opdatér
|
upgrade package: &Opdatér
|
||||||
reinstall package: Gen&installér
|
reinstall package: Gen&installér
|
||||||
remove package: &Fjern
|
remove package: &Fjern
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: &Installér Alt
|
install group: &Installér Alt
|
||||||
upgrade group: &Opgradér Alt
|
upgrade group: &Opgradér Alt
|
||||||
remove group: &Fjern Alt
|
remove group: &Fjern Alt
|
||||||
@@ -1009,8 +999,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1166,9 +1154,7 @@ error:
|
|||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ menu:
|
|||||||
next card: Nächste Karte PgDn
|
next card: Nächste Karte PgDn
|
||||||
search cards: Suchkarten Ctrl+K
|
search cards: Suchkarten Ctrl+K
|
||||||
add card: Karte Hinzufügen Ctrl+Enter
|
add card: Karte Hinzufügen Ctrl+Enter
|
||||||
add card double: Doppelseitige Karte hinzufügen Ctrl+Shift+Enter
|
|
||||||
add cards: Mehrere Karten hinzufügen...
|
add cards: Mehrere Karten hinzufügen...
|
||||||
remove card: Markierte Entfernen Del
|
remove card: Markierte Entfernen Del
|
||||||
add card csv: Karten aus CSV oder TSV hinzufügen...
|
add card csv: Karten aus CSV oder TSV hinzufügen...
|
||||||
@@ -196,8 +195,7 @@ help:
|
|||||||
previous card: Wählt die vorherige Karte in der Liste aus
|
previous card: Wählt die vorherige Karte in der Liste aus
|
||||||
next card: Wählt die nächste Karte in der Liste aus
|
next card: Wählt die nächste Karte in der Liste aus
|
||||||
search cards: Filtert die Kartenliste anhand von Suchbegriffen
|
search cards: Filtert die Kartenliste anhand von Suchbegriffen
|
||||||
add card: Fügt eine neue, leere Karte zur Edition hinzu
|
add card: Fügt eine neue Karte zur Edition hinzu
|
||||||
add card double: Fügt eine neue, leere Karte mit Rückseite zur Edition hinzu
|
|
||||||
add cards: Fügt mehrere Karten zur Edition hinzu
|
add cards: Fügt mehrere Karten zur Edition hinzu
|
||||||
remove card: Entfernt die gewählte Karte aus der Edition
|
remove card: Entfernt die gewählte Karte aus der Edition
|
||||||
link card: Verknüpft eine oder mehrere Karten mit der ausgewählten Karte
|
link card: Verknüpft eine oder mehrere Karten mit der ausgewählten Karte
|
||||||
@@ -444,7 +442,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Karte hinzufügen
|
add card: Karte hinzufügen
|
||||||
add card double: Doppelseitige Karte hinzufügen
|
|
||||||
remove card: Gewählte Karte entfernen
|
remove card: Gewählte Karte entfernen
|
||||||
link card: Karten mit ausgewählter Karte verknüpfen
|
link card: Karten mit ausgewählter Karte verknüpfen
|
||||||
copy card and links: Ausgewählte und verknüpfte Karten kopieren
|
copy card and links: Ausgewählte und verknüpfte Karten kopieren
|
||||||
@@ -712,7 +709,6 @@ label:
|
|||||||
installable version: Letzte Version
|
installable version: Letzte Version
|
||||||
installer size: Größe
|
installer size: Größe
|
||||||
installer status: Status:
|
installer status: Status:
|
||||||
folder name: Ordnername:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
load image: Doppelklicken Sie, um ein Bild zu laden
|
load image: Doppelklicken Sie, um ein Bild zu laden
|
||||||
@@ -825,16 +821,15 @@ button:
|
|||||||
close: &Beenden
|
close: &Beenden
|
||||||
|
|
||||||
# packages window
|
# packages window
|
||||||
keep package: &Unverändert beibehalten
|
keep package: &Nicht verändern
|
||||||
don't install package: &Nicht installieren
|
don't install package: &Nicht installieren
|
||||||
install package: &Installieren
|
install package: &Installieren
|
||||||
upgrade package: &Aktualisieren
|
upgrade package: &Upgraden
|
||||||
reinstall package: Neu &installieren
|
reinstall package: Neu &installieren
|
||||||
remove package: &Entfernen
|
remove package: &Entfernen
|
||||||
keep group: Gruppe unverändert beibehalten
|
install group: &Installiere alle
|
||||||
install group: Gruppe installieren/aktualisieren
|
upgrade group: &Upgrade alle
|
||||||
upgrade group: Gruppe aktualisieren
|
remove group: &Entferne alle
|
||||||
remove group: Gruppe entfernen
|
|
||||||
|
|
||||||
############################################################## Titles in the GUI
|
############################################################## Titles in the GUI
|
||||||
title:
|
title:
|
||||||
@@ -914,7 +909,6 @@ title:
|
|||||||
action:
|
action:
|
||||||
# cards
|
# cards
|
||||||
reorder cards: Karten neu anordnen
|
reorder cards: Karten neu anordnen
|
||||||
update card: Karte aktualisieren
|
|
||||||
change link: Link ändern
|
change link: Link ändern
|
||||||
change notes: Notizen ändern
|
change notes: Notizen ändern
|
||||||
change id: ID ändern
|
change id: ID ändern
|
||||||
@@ -1053,8 +1047,7 @@ error:
|
|||||||
|
|
||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Die Koordinaten für die Überblendung überlappen sich.
|
coordinates for blending overlap: Die Koordinaten für die Überblendung überlappen sich.
|
||||||
blending different sizes: Die für die Überblendung verwendeten Bilder müssen in der Funktion '%s' die gleiche Größe haben. (Eines ist %s, das andere ist %s)
|
blending different sizes: Die für die Überblendung verwendeten Bilder müssen in der Funktion '%s' die gleiche Größe haben.
|
||||||
blending different mask: Bild und Maske, die zum Überblenden verwendet werden, müssen in der Funktion '%s' die gleiche Größe haben. (Bild ist %s, Maske ist %s)
|
|
||||||
negative image width: Bild mit Breite Null oder negativer Breite, erstellt in der Funktion '%s'
|
negative image width: Bild mit Breite Null oder negativer Breite, erstellt in der Funktion '%s'
|
||||||
negative image height: Bild mit Höhe Null oder negativer Höhe, erstellt in der Funktion '%s'
|
negative image height: Bild mit Höhe Null oder negativer Höhe, erstellt in der Funktion '%s'
|
||||||
can't load image: Bild konnte nicht geladen werden. Stelle sicher, dass das tatsächliche Format des Bildes mit der gespeicherten Dateiendung übereinstimmt.
|
can't load image: Bild konnte nicht geladen werden. Stelle sicher, dass das tatsächliche Format des Bildes mit der gespeicherten Dateiendung übereinstimmt.
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ menu:
|
|||||||
next card: Select &Next Card PgDn
|
next card: Select &Next Card PgDn
|
||||||
search cards: &Search Cards Ctrl+K
|
search cards: &Search Cards Ctrl+K
|
||||||
add card: &Add Card Ctrl+Enter
|
add card: &Add Card Ctrl+Enter
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: Add &Multiple Cards...
|
add cards: Add &Multiple Cards...
|
||||||
remove card: &Delete Selected Card
|
remove card: &Delete Selected Card
|
||||||
add card csv: Add Cards from CSV or TSV...
|
add card csv: Add Cards from CSV or TSV...
|
||||||
@@ -197,7 +196,6 @@ help:
|
|||||||
next card: Selects the next card in the list
|
next card: Selects the next card in the list
|
||||||
search cards: Filter the card list using search terms
|
search cards: Filter the card list using search terms
|
||||||
add card: Add a new, blank, card to this set
|
add card: Add a new, blank, card to this set
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: Add multiple cards to the set
|
add cards: Add multiple cards to the set
|
||||||
remove card: Delete the selected card from this set
|
remove card: Delete the selected card from this set
|
||||||
link card: Link one or more cards to the selected card
|
link card: Link one or more cards to the selected card
|
||||||
@@ -445,7 +443,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Add card
|
add card: Add card
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: Remove selected card
|
remove card: Remove selected card
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
copy card and links: Copy selected cards and linked cards
|
copy card and links: Copy selected cards and linked cards
|
||||||
@@ -711,7 +708,6 @@ label:
|
|||||||
installable version: Latest version:
|
installable version: Latest version:
|
||||||
installer size: Size:
|
installer size: Size:
|
||||||
installer status: Status:
|
installer status: Status:
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
load image: Double click to load image
|
load image: Double click to load image
|
||||||
@@ -826,16 +822,15 @@ button:
|
|||||||
close: &Close
|
close: &Close
|
||||||
|
|
||||||
# packages window
|
# packages window
|
||||||
keep package: Keep As Is
|
keep package: &Don't change
|
||||||
don't install package: &Don't Install
|
don't install package: &Don't install
|
||||||
install package: &Install
|
install package: &Install
|
||||||
upgrade package: &Update
|
upgrade package: &Update
|
||||||
reinstall package: Re&install
|
reinstall package: Re&install
|
||||||
remove package: &Remove
|
remove package: &Remove
|
||||||
keep group: Keep Group As Is
|
install group: &Install All
|
||||||
install group: &Install/Update Group
|
upgrade group: &Upgrade All
|
||||||
upgrade group: &Update Group
|
remove group: &Remove All
|
||||||
remove group: &Remove Group
|
|
||||||
|
|
||||||
############################################################## Titles in the GUI
|
############################################################## Titles in the GUI
|
||||||
title:
|
title:
|
||||||
@@ -915,7 +910,6 @@ title:
|
|||||||
action:
|
action:
|
||||||
# cards
|
# cards
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1054,8 +1048,7 @@ error:
|
|||||||
|
|
||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
negative image height: Image with zero or negative height created in function '%s'
|
negative image height: Image with zero or negative height created in function '%s'
|
||||||
can't load image: Failed to load image. Ensure the image's actual format matches its saved extension.
|
can't load image: Failed to load image. Ensure the image's actual format matches its saved extension.
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ menu:
|
|||||||
next card: Seleccionar &carta siguiente PgDn
|
next card: Seleccionar &carta siguiente PgDn
|
||||||
search cards: &Buscar Cartas Ctrl+K
|
search cards: &Buscar Cartas Ctrl+K
|
||||||
add card: &Añadir carta Ctrl+Enter
|
add card: &Añadir carta Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: Añadir &múltiples cartas...
|
add cards: Añadir &múltiples cartas...
|
||||||
remove card: &Borrar carta seleccionada
|
remove card: &Borrar carta seleccionada
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -210,8 +208,6 @@ help:
|
|||||||
next card: Selecciona la carta siguiente en la lista
|
next card: Selecciona la carta siguiente en la lista
|
||||||
search cards: Filtra la lista de cartas usando términos de búsqueda
|
search cards: Filtra la lista de cartas usando términos de búsqueda
|
||||||
add card: Añade una carta nueva, vacía, a este Set
|
add card: Añade una carta nueva, vacía, a este Set
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: Añade múltiples cartas al Set
|
add cards: Añade múltiples cartas al Set
|
||||||
remove card: Borra la carta seleccionada de este Set
|
remove card: Borra la carta seleccionada de este Set
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -472,8 +468,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Añadir carta
|
add card: Añadir carta
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: Eliminar carta seleccionada
|
remove card: Eliminar carta seleccionada
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -765,8 +759,6 @@ label:
|
|||||||
installable version: Última versión:
|
installable version: Última versión:
|
||||||
installer size: Tamaño:
|
installer size: Tamaño:
|
||||||
installer status: Estado:
|
installer status: Estado:
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -899,8 +891,6 @@ button:
|
|||||||
upgrade package: &Actualizar
|
upgrade package: &Actualizar
|
||||||
reinstall package: R&einstalar
|
reinstall package: R&einstalar
|
||||||
remove package: &Eliminar
|
remove package: &Eliminar
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: Instalar &Todos
|
install group: Instalar &Todos
|
||||||
upgrade group: A&ctualizar Todos
|
upgrade group: A&ctualizar Todos
|
||||||
remove group: Q&uitar Todos
|
remove group: Q&uitar Todos
|
||||||
@@ -992,8 +982,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1143,9 +1131,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Coordenadas para la mezcla (blending) solapada
|
coordinates for blending overlap: Coordenadas para la mezcla (blending) solapada
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
+92
-99
@@ -54,9 +54,8 @@ menu:
|
|||||||
next card: Carte &Suivante PgDn
|
next card: Carte &Suivante PgDn
|
||||||
search cards: Rechercher dans les Cartes Ctrl+K
|
search cards: Rechercher dans les Cartes Ctrl+K
|
||||||
add card: &Ajouter une Carte Ctrl+Enter
|
add card: &Ajouter une Carte Ctrl+Enter
|
||||||
add card double: Ajouter une Carte recto-verso Ctrl+Shift+Enter
|
|
||||||
add cards: Ajouter &plusieurs Cartes...
|
add cards: Ajouter &plusieurs Cartes...
|
||||||
remove card: &Supprimer la Carte sélectionnée
|
remove card: &Supprimer la carte sélectionnée
|
||||||
add card csv: Ajouter plusieurs Cartes depuis un CSV ou TSV...
|
add card csv: Ajouter plusieurs Cartes depuis un CSV ou TSV...
|
||||||
add card json: Ajouter plusieurs Cartes depuis un JSON...
|
add card json: Ajouter plusieurs Cartes depuis un JSON...
|
||||||
link card: &Lier des Cartes à la Carte sélectionnée...
|
link card: &Lier des Cartes à la Carte sélectionnée...
|
||||||
@@ -160,15 +159,15 @@ help:
|
|||||||
save set as directory: Sauver le Set en tant que dossier non compressé
|
save set as directory: Sauver le Set en tant que dossier non compressé
|
||||||
export: Exporter le Set...
|
export: Exporter le Set...
|
||||||
export html: Exporter le Set en tant que fichier HTML
|
export html: Exporter le Set en tant que fichier HTML
|
||||||
export image: Exporter la Carte selectionnée en tant qu'image
|
export image: Exporter la carte selectionnée en tant qu'image
|
||||||
export images: Exporter toutes les Cartes en tant qu'images
|
export images: Exporter toutes les cartes en tant qu'images
|
||||||
export apprentice: Exporter le Set pour être utilisé avec Apprentice
|
export apprentice: Exporter le Set pour être utilisé avec Apprentice
|
||||||
export mws: Exporter le Set pour être utilisé avec Magic Workstation
|
export mws: Exporter le Set pour être utilisé avec Magic Workstation
|
||||||
add card csv: Ajouter des Cartes depuis un fichier à Valeurs Séparées par des Virgules ou Tabulations
|
add card csv: Ajouter des Cartes depuis un fichier à Valeurs Séparées par des Virgules ou Tabulations
|
||||||
add card json: Ajouter des Cartes depuis un fichier JSON
|
add card json: Ajouter des Cartes depuis un fichier JSON
|
||||||
check updates: Ouvrir une fenêtre de mise à jour pour télécharger les nouveaux packages (Jeux, Styles, Localisations)
|
check updates: Ouvrir une fenêtre de mise à jour pour télécharger les nouveaux packages (Jeux, Styles, Localisations)
|
||||||
print preview: Voir les Cartes telles qu'elles vont être imprimées
|
print preview: Voir les cartes telles qu'elles vont être imprimées
|
||||||
print: Imprimer les Cartes de ce Set
|
print: Imprimer les cartes de ce Set
|
||||||
reload data: Recharger tous les Templates ainsi que le Set
|
reload data: Recharger tous les Templates ainsi que le Set
|
||||||
show profiler: Afficher la fenêtre du Profiler, avec la durée d'exécution des scripts; Utilisé pour l'optimisation
|
show profiler: Afficher la fenêtre du Profiler, avec la durée d'exécution des scripts; Utilisé pour l'optimisation
|
||||||
exit: Quitter Magic Set Editor; Vous demandera de sauvegarder le Set
|
exit: Quitter Magic Set Editor; Vous demandera de sauvegarder le Set
|
||||||
@@ -177,38 +176,37 @@ help:
|
|||||||
undo: Annuler la dernière action
|
undo: Annuler la dernière action
|
||||||
redo: Refaire la dernière action
|
redo: Refaire la dernière action
|
||||||
cut: Couper le texte selectionné dans le presse-papier
|
cut: Couper le texte selectionné dans le presse-papier
|
||||||
cut card: Couper la Carte selectionnée dans le presse-papier
|
cut card: Couper la carte selectionnée dans le presse-papier
|
||||||
cut keyword: Couper le Mot-clef selectionné dans le presse-papier
|
cut keyword: Couper le Mot-clef selectionné dans le presse-papier
|
||||||
copy: Copier le texte selectionné dans le presse-papier
|
copy: Copier le texte selectionné dans le presse-papier
|
||||||
copy card: Copier la Carte selectionnée dans le presse-papier
|
copy card: Copier la carte selectionnée dans le presse-papier
|
||||||
copy keyword: Copier le Mot-clef selectionné dans le presse-papier
|
copy keyword: Copier le Mot-clef selectionné dans le presse-papier
|
||||||
paste: Insérer le texte depuis le presse-papier
|
paste: Insérer le texte depuis le presse-papier
|
||||||
paste card: Insérer la Carte depuis le presse-papier
|
paste card: Insérer la carte depuis le presse-papier
|
||||||
paste keyword: Insérer le mot_clef depuis le presse-papier
|
paste keyword: Insérer le mot_clef depuis le presse-papier
|
||||||
select all: Sélectionner tout le texte
|
select all: Sélectionner tout le texte
|
||||||
find: Rechercher un bout de texte dans les Cartes
|
find: Rechercher un bout de texte dans les cartes
|
||||||
find next: Rechercher l'occurrence suivante
|
find next: Rechercher l'occurrence suivante
|
||||||
replace: Remplacer l'occurrence
|
replace: Remplacer l'occurrence
|
||||||
auto replace: Quel texte devra être automatiquement remplacé?
|
auto replace: Quel texte devra être automatiquement remplacé?
|
||||||
preferences: Changer la configuration de Magic Set Editor
|
preferences: Changer la configuration de Magic Set Editor
|
||||||
|
|
||||||
# cards menu
|
# cards menu
|
||||||
previous card: Choisir la Carte précédente dans la liste
|
previous card: Choisir la carte précédente dans la liste
|
||||||
next card: Choisir la Carte suivante dans la liste
|
next card: Choisir la carte suivante dans la liste
|
||||||
search cards: Filtrer la liste des Carte à l'aide de termes de recherche
|
search cards: Filtrer la liste des carte à l'aide de termes de recherche
|
||||||
add card: Ajouter une nouvelle Carte vierge au Set
|
add card: Ajouter une nouvelle carte vierge au Set
|
||||||
add card double: Ajouter une nouvelle Carte vierge avec un verso au Set
|
add cards: Ajouter plusieurs cartes au Set
|
||||||
add cards: Ajouter plusieurs Cartes au Set
|
remove card: Supprimer la carte sélectionnée du Set
|
||||||
remove card: Supprimer la Carte sélectionnée du Set
|
link card: Lier des cartes à la carte sélectionnée
|
||||||
link card: Lier des Cartes à la Carte sélectionnée
|
copy card and links: Copier les cartes sélectionnées ainsi que toutes leurs cartes liées
|
||||||
copy card and links: Copier les Cartes sélectionnées ainsi que toutes leurs Cartes liées
|
bulk modify: Modifier beaucoup de cartes d'un coup
|
||||||
bulk modify: Modifier beaucoup de Cartes d'un coup
|
orientation: Orientation de la carte visualisée
|
||||||
orientation: Orientation de la Carte visualisée
|
rotate card: Tourner la carte de 90° dans le sens des aiguilles d'une montre
|
||||||
rotate card: Tourner la Carte de 90° dans le sens des aiguilles d'une montre
|
rotate 0: Afficher la carte dans son sens original
|
||||||
rotate 0: Afficher la Carte dans son sens original
|
rotate 270: Afficher la carte tournée dans le sens des aiguilles d'une montre
|
||||||
rotate 270: Afficher la Carte tournée dans le sens des aiguilles d'une montre
|
rotate 90: Afficher la carte tournée dans le sens inverse des aiguilles d'une montre
|
||||||
rotate 90: Afficher la Carte tournée dans le sens inverse des aiguilles d'une montre
|
rotate 180: Afficher la carte à l'envers
|
||||||
rotate 180: Afficher la Carte à l'envers
|
|
||||||
card list columns: Choisir quelles colonnes doivent être affichées et dans quel ordre
|
card list columns: Choisir quelles colonnes doivent être affichées et dans quel ordre
|
||||||
|
|
||||||
# keywords menu
|
# keywords menu
|
||||||
@@ -233,10 +231,10 @@ help:
|
|||||||
no spelling suggestions: Il n'y a pas de suggestions pour corriger cette faute
|
no spelling suggestions: Il n'y a pas de suggestions pour corriger cette faute
|
||||||
|
|
||||||
# graph menu
|
# graph menu
|
||||||
pie: Un graphique en secteurs, l'épaisseur de la tranche indique le nombre de Cartes
|
pie: Un graphique en secteurs, l'épaisseur de la tranche indique le nombre de cartes
|
||||||
bar: Un graphique à barres, la hauteur de la barre indique le nombre de Cartes
|
bar: Un graphique à barres, la hauteur de la barre indique le nombre de cartes
|
||||||
stack: Un graphique à barres empilées
|
stack: Un graphique à barres empilées
|
||||||
scatter: Un nuage de points, la taille du point indique le nombre de Cartes
|
scatter: Un nuage de points, la taille du point indique le nombre de cartes
|
||||||
scatter pie: Un nuage de points où chaque point est un petit graphique en secteurs
|
scatter pie: Un nuage de points où chaque point est un petit graphique en secteurs
|
||||||
|
|
||||||
# console menu
|
# console menu
|
||||||
@@ -244,12 +242,12 @@ help:
|
|||||||
|
|
||||||
# window menu
|
# window menu
|
||||||
new window: Ouvrir une nouvelle fenêtre pour éditer le même Set
|
new window: Ouvrir une nouvelle fenêtre pour éditer le même Set
|
||||||
cards tab: Éditer les Cartes du Set
|
cards tab: Éditer les cartes du Set
|
||||||
set info tab: Éditer les informations du Set, son créateur, etc...
|
set info tab: Éditer les informations du Set, son créateur, etc...
|
||||||
style tab: Changer le Style des Cartes
|
style tab: Changer le Style des cartes
|
||||||
keywords tab: Définir des Mots-clefs supplémentaires pour le Set
|
keywords tab: Définir des Mots-clefs supplémentaires pour le Set
|
||||||
stats tab: Voir les statistiques des Cartes du Set
|
stats tab: Voir les statistiques des cartes du Set
|
||||||
random pack tab: Générer des boosters aléatoires de Cartes du Set
|
random pack tab: Générer des boosters aléatoires de cartes du Set
|
||||||
console tab: Afficher les messages d'erreurs et executer des scripts
|
console tab: Afficher les messages d'erreurs et executer des scripts
|
||||||
|
|
||||||
# help menu
|
# help menu
|
||||||
@@ -263,12 +261,12 @@ help:
|
|||||||
search stylesheet list control: Filtrer la liste des Styles. Utilisez - pour exclure des Styles. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
search stylesheet list control: Filtrer la liste des Styles. Utilisez - pour exclure des Styles. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
||||||
|
|
||||||
# card select / image export
|
# card select / image export
|
||||||
filename format: (Utilisez {card.name} pour le nom de la Carte ; Le type de fichier est déterminé, basé par l'extension)
|
filename format: (Utilisez {card.name} pour le nom de la carte ; Le type de fichier est déterminé, basé par l'extension)
|
||||||
|
|
||||||
# cards panel
|
# cards panel
|
||||||
collapse notes: Cacher les notes des Cartes
|
collapse notes: Cacher les notes des cartes
|
||||||
expand notes: Afficher les notes des Cartes
|
expand notes: Afficher les notes des cartes
|
||||||
search cards control: Filtrer la liste des Cartes. Utilisez - pour exclure des Cartes. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
search cards control: Filtrer la liste des cartes. Utilisez - pour exclure des cartes. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
||||||
|
|
||||||
# keywords panel
|
# keywords panel
|
||||||
search keywords control: Filtrer la liste des mots-clefs. Utilisez - pour exclure des mots-clefs. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
search keywords control: Filtrer la liste des mots-clefs. Utilisez - pour exclure des mots-clefs. Utilisez field: pour rechercher uniquement dans un champ donné. Utilisez des guillemets pour une recherche litterale. Séparez plusieurs filtres par un espace.
|
||||||
@@ -286,7 +284,7 @@ help:
|
|||||||
pour que le changement prenne effet.
|
pour que le changement prenne effet.
|
||||||
zoom export:
|
zoom export:
|
||||||
(Quand l'option est décochée, les
|
(Quand l'option est décochée, les
|
||||||
Cartes sont exportées à 100% de leur
|
cartes sont exportées à 100% de leur
|
||||||
taille et dans leur rotation normale.)
|
taille et dans leur rotation normale.)
|
||||||
|
|
||||||
# apprentice export
|
# apprentice export
|
||||||
@@ -369,7 +367,7 @@ tool:
|
|||||||
console tab: Console
|
console tab: Console
|
||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
search cards: Rechercher des Cartes (Ctrl+K)
|
search cards: Rechercher des cartes (Ctrl+K)
|
||||||
stats card counts 1: %s Au total
|
stats card counts 1: %s Au total
|
||||||
stats card counts 2: %s Dans le filtre, %s Au total
|
stats card counts 2: %s Dans le filtre, %s Au total
|
||||||
card counts 2: %s Dans la sélection, %s Au total
|
card counts 2: %s Dans la sélection, %s Au total
|
||||||
@@ -444,12 +442,11 @@ tooltip:
|
|||||||
redo: Rétablir%s
|
redo: Rétablir%s
|
||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Ajouter une Carte
|
add card: Ajouter une carte
|
||||||
add card double: Ajouter une Carte recto-verso
|
remove card: Supprimer la carte sélectionnée
|
||||||
remove card: Supprimer la Carte sélectionnée
|
link card: Lier des cartes à la carte sélectionnée
|
||||||
link card: Lier des Cartes à la Carte sélectionnée
|
copy card and links: Copier les cartes sélectionnées et leurs cartes liées
|
||||||
copy card and links: Copier les Cartes sélectionnées et leurs Cartes liées
|
rotate card: Tourner la carte
|
||||||
rotate card: Tourner la Carte
|
|
||||||
|
|
||||||
# keywords toolbar
|
# keywords toolbar
|
||||||
add keyword: Ajouter un Mot-clef
|
add keyword: Ajouter un Mot-clef
|
||||||
@@ -516,7 +513,7 @@ tooltip:
|
|||||||
label:
|
label:
|
||||||
## app window items labels
|
## app window items labels
|
||||||
# cards panel
|
# cards panel
|
||||||
card notes: Notes de Carte:
|
card notes: Notes de carte:
|
||||||
|
|
||||||
# keywords panel
|
# keywords panel
|
||||||
search keywords: Recherche dans les mots-clefs (Ctrl+K)
|
search keywords: Recherche dans les mots-clefs (Ctrl+K)
|
||||||
@@ -545,18 +542,18 @@ label:
|
|||||||
custom link selected: Générateur, Face Avant, Composant d'Assimilation, etc...
|
custom link selected: Générateur, Face Avant, Composant d'Assimilation, etc...
|
||||||
custom link linked: Jeton, Face Arrière, Résultat d'Assimilation, etc...
|
custom link linked: Jeton, Face Arrière, Résultat d'Assimilation, etc...
|
||||||
custom link undefined: Non Défini
|
custom link undefined: Non Défini
|
||||||
linked cards relation: Choisissez le type de relation entre la Carte sélectionnée ('%s') et les Cartes liées:
|
linked cards relation: Choisissez le type de relation entre la carte sélectionnée ('%s') et les cartes liées:
|
||||||
selected card: Carte sélectionnée:
|
selected card: Carte sélectionnée:
|
||||||
linked cards: Cartes liées:
|
linked cards: Cartes liées:
|
||||||
select linked cards: Choisissez jusqu’à 4 Cartes liées:
|
select linked cards: Choisissez jusqu’à 4 cartes liées:
|
||||||
|
|
||||||
# bulk modification dialog
|
# bulk modification dialog
|
||||||
bulk modify selection: Quelles Cartes doivent être modifiées:
|
bulk modify selection: Quelles cartes doivent être modifiées:
|
||||||
bulk modify all: Toutes les Cartes
|
bulk modify all: Toutes les cartes
|
||||||
bulk modify filtered: Les Cartes actuellement filtrées
|
bulk modify filtered: Les cartes actuellement filtrées
|
||||||
bulk modify selected: Les Cartes actuellement sélectionnées
|
bulk modify selected: Les cartes actuellement sélectionnées
|
||||||
bulk modify predicate: Les Cartes qui vérifient un critère
|
bulk modify predicate: Les cartes qui vérifient un critère
|
||||||
bulk modify predicate description: Quel critère doit être vérifié pour que la Carte soit modifiée:
|
bulk modify predicate description: Quel critère doit être vérifié pour que la carte soit modifiée:
|
||||||
bulk modify predicate example: Example (petites créatures de M:tG):
|
bulk modify predicate example: Example (petites créatures de M:tG):
|
||||||
bulk modify field: Quelle valeur doit être modifiée:
|
bulk modify field: Quelle valeur doit être modifiée:
|
||||||
bulk modify mod description: Que doit être la nouvelle valeur:
|
bulk modify mod description: Que doit être la nouvelle valeur:
|
||||||
@@ -575,7 +572,7 @@ label:
|
|||||||
|
|
||||||
# new set dialog
|
# new set dialog
|
||||||
game type: &Type de jeu:
|
game type: &Type de jeu:
|
||||||
style type: &Style des Carte:
|
style type: &Style des carte:
|
||||||
search game list: Filtrer les jeux
|
search game list: Filtrer les jeux
|
||||||
search stylesheet list: Filtrer les Styles
|
search stylesheet list: Filtrer les Styles
|
||||||
|
|
||||||
@@ -592,7 +589,7 @@ label:
|
|||||||
dark mode no: Mode clair
|
dark mode no: Mode clair
|
||||||
dark mode yes: Mode sombre
|
dark mode yes: Mode sombre
|
||||||
app language: Langue de l'interface utilisateur (App Language)
|
app language: Langue de l'interface utilisateur (App Language)
|
||||||
card display: Affichage des Cartes
|
card display: Affichage des cartes
|
||||||
zoom: &Zoom:
|
zoom: &Zoom:
|
||||||
import: Import
|
import: Import
|
||||||
export: &Export
|
export: &Export
|
||||||
@@ -605,7 +602,7 @@ label:
|
|||||||
external programs: Programmes externes
|
external programs: Programmes externes
|
||||||
apprentice: &Apprentice:
|
apprentice: &Apprentice:
|
||||||
apprentice exe: Executable Apprentice
|
apprentice exe: Executable Apprentice
|
||||||
export desc: Lors de l'exportation de Cartes en images:
|
export desc: Lors de l'exportation de cartes en images:
|
||||||
import desc: Lors de l'importation d'images pour les illustrations:
|
import desc: Lors de l'importation d'images pour les illustrations:
|
||||||
internal scale desc:
|
internal scale desc:
|
||||||
Taille à laquelle stocker les images en interne.
|
Taille à laquelle stocker les images en interne.
|
||||||
@@ -624,8 +621,8 @@ label:
|
|||||||
|
|
||||||
# card select / image export dialogs
|
# card select / image export dialogs
|
||||||
select cards: Cartes à exporter
|
select cards: Cartes à exporter
|
||||||
select cards print: Selectionner les Cartes à imprimer
|
select cards print: Selectionner les cartes à imprimer
|
||||||
selected card count: %s Cartes seront exportées.
|
selected card count: %s cartes seront exportées.
|
||||||
filename format: &Format:
|
filename format: &Format:
|
||||||
filename conflicts: &Gestion des doublons de fichiers:
|
filename conflicts: &Gestion des doublons de fichiers:
|
||||||
export filenames: Nom des fichiers
|
export filenames: Nom des fichiers
|
||||||
@@ -649,7 +646,7 @@ label:
|
|||||||
# JSON import dialog
|
# JSON import dialog
|
||||||
add card json type: Type de fichier JSON:
|
add card json type: Type de fichier JSON:
|
||||||
add card json custom: Fichier JSON customisé
|
add card json custom: Fichier JSON customisé
|
||||||
add card json path: Chemin vers la liste de Cartes à l'intérieur du fichier:
|
add card json path: Chemin vers la liste de cartes à l'intérieur du fichier:
|
||||||
add card json file: Chemin du fichier:
|
add card json file: Chemin du fichier:
|
||||||
|
|
||||||
# image slicer dialog
|
# image slicer dialog
|
||||||
@@ -712,18 +709,17 @@ label:
|
|||||||
installable version: Dernière version:
|
installable version: Dernière version:
|
||||||
installer size: Taille:
|
installer size: Taille:
|
||||||
installer status: État:
|
installer status: État:
|
||||||
folder name: Dossier:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
load image: Double-cliquer pour charger une image
|
load image: Double-cliquer pour charger une image
|
||||||
|
|
||||||
# print dialog
|
# print dialog
|
||||||
put space between cards: Ajouter un espace entre les Cartes?
|
put space between cards: Ajouter un espace entre les cartes?
|
||||||
spacing print: Espace entre les Cartes en millimètres
|
spacing print: Espace entre les cartes en millimètres
|
||||||
bleed print: Marge de fond perdu en millimètres
|
bleed print: Marge de fond perdu en millimètres
|
||||||
cutter lines print: Ajouter des lignes de découpe?
|
cutter lines print: Ajouter des lignes de découpe?
|
||||||
cutter lines all: Toutes
|
cutter lines all: Toutes
|
||||||
cutter lines no intersect: Si elles n'intersectent pas de Carte
|
cutter lines no intersect: Si elles n'intersectent pas de carte
|
||||||
cutter lines none: Aucune
|
cutter lines none: Aucune
|
||||||
|
|
||||||
## symbol editor
|
## symbol editor
|
||||||
@@ -736,8 +732,8 @@ button:
|
|||||||
link select: Sélectionner
|
link select: Sélectionner
|
||||||
|
|
||||||
# style panel
|
# style panel
|
||||||
use for all cards: Utiliser pour toutes les C&artes
|
use for all cards: Utiliser pour toutes les c&artes
|
||||||
use custom styling options: Options &spécifique à cette Carte
|
use custom styling options: Options &spécifique à cette carte
|
||||||
|
|
||||||
# set info panel
|
# set info panel
|
||||||
edit symbol: Éditer
|
edit symbol: Éditer
|
||||||
@@ -777,9 +773,9 @@ button:
|
|||||||
Ajoutez une marge de
|
Ajoutez une marge de
|
||||||
fond perdu grossière
|
fond perdu grossière
|
||||||
notes export:
|
notes export:
|
||||||
Exporter les notes de la Carte à
|
Exporter les notes de la carte à
|
||||||
l'intérieur des Métadonnées de l'image
|
l'intérieur des Métadonnées de l'image
|
||||||
spellcheck enabled: Afficher les fautes d'orthographe sur les Cartes
|
spellcheck enabled: Afficher les fautes d'orthographe sur les cartes
|
||||||
check now: &Vérifier maintenant
|
check now: &Vérifier maintenant
|
||||||
always: Toujours
|
always: Toujours
|
||||||
every 5 startups: Tous les 5 démarrages
|
every 5 startups: Tous les 5 démarrages
|
||||||
@@ -805,7 +801,7 @@ button:
|
|||||||
export entire set: Set complet
|
export entire set: Set complet
|
||||||
export generated packs: Packs générés
|
export generated packs: Packs générés
|
||||||
export custom cards selection: Sélection personalisée
|
export custom cards selection: Sélection personalisée
|
||||||
select cards: &Sélection des Cartes...
|
select cards: &Sélection des cartes...
|
||||||
select all: Sélectionner &toutes
|
select all: Sélectionner &toutes
|
||||||
select none: Sélectionner &aucune
|
select none: Sélectionner &aucune
|
||||||
overwrite: Ecraser les anciens fichiers
|
overwrite: Ecraser les anciens fichiers
|
||||||
@@ -828,13 +824,12 @@ button:
|
|||||||
keep package: &Ne pas modifier
|
keep package: &Ne pas modifier
|
||||||
don't install package: &Ne pas installer
|
don't install package: &Ne pas installer
|
||||||
install package: &Installer
|
install package: &Installer
|
||||||
upgrade package: &Mettre à jour
|
upgrade package: &Upgrader
|
||||||
reinstall package: Ré&installer
|
reinstall package: Ré&installer
|
||||||
remove package: &Supprimer
|
remove package: &Supprimer
|
||||||
keep group: &Ne pas modifier le groupe
|
install group: &Installer Tout
|
||||||
install group: &Installer/Mettre à jour le groupe
|
upgrade group: &Upgrader Tout
|
||||||
upgrade group: &Mettre à jour le groupe
|
remove group: &Supprimer Tout
|
||||||
remove group: &Supprimer le groupe
|
|
||||||
|
|
||||||
############################################################## Titles in the GUI
|
############################################################## Titles in the GUI
|
||||||
title:
|
title:
|
||||||
@@ -913,13 +908,12 @@ title:
|
|||||||
############################################################## Action (undo/redo) names
|
############################################################## Action (undo/redo) names
|
||||||
action:
|
action:
|
||||||
# cards
|
# cards
|
||||||
reorder cards: Réorganiser les Cartes
|
reorder cards: Réorganiser les cartes
|
||||||
update card: Mettre à jour la Carte
|
|
||||||
change link: Modifier le lien
|
change link: Modifier le lien
|
||||||
change notes: Modifier les notes
|
change notes: Modifier les notes
|
||||||
change id: Modifier l'ID
|
change id: Modifier l'ID
|
||||||
change style: Modifier le style
|
change style: Modifier le style
|
||||||
change all styles: Modifier le style (toutes les Cartes)
|
change all styles: Modifier le style (toutes les cartes)
|
||||||
use custom style: Utiliser un style personnalisé
|
use custom style: Utiliser un style personnalisé
|
||||||
show reminder text: Afficher le texte de rappel
|
show reminder text: Afficher le texte de rappel
|
||||||
hide reminder text: Masquer le texte de rappel
|
hide reminder text: Masquer le texte de rappel
|
||||||
@@ -1016,7 +1010,7 @@ error:
|
|||||||
no field with name: Impossible de trouver le champ de %s nommé '%s'
|
no field with name: Impossible de trouver le champ de %s nommé '%s'
|
||||||
styling data not map: La valeur donnée pour « %s_data » n'est pas un dictionnaire
|
styling data not map: La valeur donnée pour « %s_data » n'est pas un dictionnaire
|
||||||
styling data without stylesheet: Valeur donnée pour « %s_data » avant la définition d'un Style
|
styling data without stylesheet: Valeur donnée pour « %s_data » avant la définition d'un Style
|
||||||
cant set value: Impossible de définir la valeur de la Carte '%s', son type est incorrect
|
cant set value: Impossible de définir la valeur de la carte '%s', son type est incorrect
|
||||||
cant set image value: On ne peut définir la valeur d'une image qu'avec un nom de fichier relatif depuis le package, ou avec les fonctions import_image/download_image (dans le champ '%s')
|
cant set image value: On ne peut définir la valeur d'une image qu'avec un nom de fichier relatif depuis le package, ou avec les fonctions import_image/download_image (dans le champ '%s')
|
||||||
cant set symbol value: On ne peut définir la valeur d'un symbol qu'avec un nom de fichier relatif depuis le package (dans le champ '%s')
|
cant set symbol value: On ne peut définir la valeur d'un symbol qu'avec un nom de fichier relatif depuis le package (dans le champ '%s')
|
||||||
add card csv file not found: Impossible de trouver ou charger le fichier CSV ou TSV spécifié
|
add card csv file not found: Impossible de trouver ou charger le fichier CSV ou TSV spécifié
|
||||||
@@ -1053,15 +1047,14 @@ error:
|
|||||||
|
|
||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Les coordonnées pour le mélange sont superposées. Espacez-les.
|
coordinates for blending overlap: Les coordonnées pour le mélange sont superposées. Espacez-les.
|
||||||
blending different sizes: Les images utilisées pour le mélange doivent avoir la même taille dans la fonction '%s'. (L'une est %s, l'autre est %s)
|
blending different sizes: Les images utilisées pour le mélange doivent avoir la même taille dans la fonction '%s'.
|
||||||
blending different mask: L'image et le masque utilisés pour le mélange doivent avoir la même taille dans la fonction '%s'. (L'image est %s, le masque est %s)
|
|
||||||
negative image width: Image de largeur nulle ou négative créée par la fonction '%s'
|
negative image width: Image de largeur nulle ou négative créée par la fonction '%s'
|
||||||
negative image height: Image de hauteur nulle ou négative créée par la fonction '%s'
|
negative image height: Image de hauteur nulle ou négative créée par la fonction '%s'
|
||||||
can't load image: Échec du chargement de l'image. Assurez-vous que le format réel de l'image corresponde à son extension enregistrée.
|
can't load image: Échec du chargement de l'image. Assurez-vous que le format réel de l'image corresponde à son extension enregistrée.
|
||||||
symbol image has alpha: Pour un résultat optimal, l'image doit être en noir et blanc sans transparence.
|
symbol image has alpha: Pour un résultat optimal, l'image doit être en noir et blanc sans transparence.
|
||||||
|
|
||||||
# error from files
|
# error from files
|
||||||
no card fields: Le jeu '%s' ne contient aucun champ de Carte. Définissez au moins un champ de Carte.
|
no card fields: Le jeu '%s' ne contient aucun champ de carte. Définissez au moins un champ de carte.
|
||||||
reserved field name: '%s' est un nom de champ réservé. Veuillez utiliser un autre nom.
|
reserved field name: '%s' est un nom de champ réservé. Veuillez utiliser un autre nom.
|
||||||
duplicate field name: Le nom de champ alternatif '%s' est un doublon : il s’agit à la fois d’un nom alternatif pour '%s' et '%s'.
|
duplicate field name: Le nom de champ alternatif '%s' est un doublon : il s’agit à la fois d’un nom alternatif pour '%s' et '%s'.
|
||||||
no game specified: Pas de jeu spécifié pour le %s
|
no game specified: Pas de jeu spécifié pour le %s
|
||||||
@@ -1091,15 +1084,15 @@ error:
|
|||||||
no updates: Il n'y a pas de mises à jour disponibles.
|
no updates: Il n'y a pas de mises à jour disponibles.
|
||||||
|
|
||||||
# card linking
|
# card linking
|
||||||
not enough free links: La Carte '%s' n'a pas assez de liens disponibles. Vous pouvez former au maximum 4 liens par Carte.
|
not enough free links: La carte '%s' n'a pas assez de liens disponibles. Vous pouvez former au maximum 4 liens par carte.
|
||||||
not enough free links for copy: La Carte '%s' n'a pas assez de liens disponibles pour copier. Vous pouvez former au maximum 4 liens par Carte.
|
not enough free links for copy: La carte '%s' n'a pas assez de liens disponibles pour copier. Vous pouvez former au maximum 4 liens par carte.
|
||||||
could not link: Les Cartes suivantes n'ont pas pu être liées, elles ont déjà 4 liens:
|
could not link: Les cartes suivantes n'ont pas pu être liées, elles ont déjà 4 liens:
|
||||||
missing free links: La Carte ne contient que %s liens libres. Sélectionnez moins de Cartes.
|
missing free links: La carte ne contient que %s liens libres. Sélectionnez moins de cartes.
|
||||||
link duplicate: Nom de lien localisé dupliqué. '%s' correspond à la fois à '%s' et à '%s'.
|
link duplicate: Nom de lien localisé dupliqué. '%s' correspond à la fois à '%s' et à '%s'.
|
||||||
multiple front faces: La Carte '%s' contient plusieurs Cartes liées comme face avant.
|
multiple front faces: La carte '%s' contient plusieurs cartes liées comme face avant.
|
||||||
multiple back faces: La Carte '%s' contient plusieurs Cartes liées comme face arrière.
|
multiple back faces: La carte '%s' contient plusieurs cartes liées comme face arrière.
|
||||||
cant link to self: Impossible de lier une Carte à elle-même. (Cet assignation sera ignorée.)
|
cant link to self: Impossible de lier une carte à elle-même. (Cet assignation sera ignorée.)
|
||||||
no cards selected: Aucune Carte sélectionnée. Sélectionnez jusqu'à 4 Cartes à lier.
|
no cards selected: Aucune carte sélectionnée. Sélectionnez jusqu'à 4 cartes à lier.
|
||||||
could not find input: Carte d'input introuvable.
|
could not find input: Carte d'input introuvable.
|
||||||
could not find linked: Carte liée (linked_card) introuvable.
|
could not find linked: Carte liée (linked_card) introuvable.
|
||||||
|
|
||||||
@@ -1109,11 +1102,11 @@ error:
|
|||||||
bulk modify mod is not string: La modification doit être une chaîne de caractères, mais a été évaluée à %s.
|
bulk modify mod is not string: La modification doit être une chaîne de caractères, mais a été évaluée à %s.
|
||||||
bulk modify mod is not color: La modification doit être une couleur, mais a été évaluée à %s.
|
bulk modify mod is not color: La modification doit être une couleur, mais a été évaluée à %s.
|
||||||
bulk modify mod is not image: La modification doit être une image, mais a été évaluée à %s. Utilisez les fonctions import_image/download_image pour définir les champs d' images.
|
bulk modify mod is not image: La modification doit être une image, mais a été évaluée à %s. Utilisez les fonctions import_image/download_image pour définir les champs d' images.
|
||||||
bulk modify mod is nil: La modification est null pour la Carte '%s'. Elle ne sera pas appliquée.
|
bulk modify mod is nil: La modification est null pour la carte '%s'. Elle ne sera pas appliquée.
|
||||||
bulk modify no cards: Aucune Carte à modifier.
|
bulk modify no cards: Aucune carte à modifier.
|
||||||
bulk modify no cards verify: Aucune Carte ne correspond au critère.
|
bulk modify no cards verify: Aucune carte ne correspond au critère.
|
||||||
bulk modify nothing: Aucune Carte n'a été modifiée.
|
bulk modify nothing: Aucune carte n'a été modifiée.
|
||||||
bulk modify success: Nombre de Cartes modifiées avec succès : %s
|
bulk modify success: Nombre de cartes modifiées avec succès : %s
|
||||||
|
|
||||||
# web request
|
# web request
|
||||||
web request failed: Échec de la requête Web
|
web request failed: Échec de la requête Web
|
||||||
@@ -1174,9 +1167,9 @@ type:
|
|||||||
stylesheet: stylesheet
|
stylesheet: stylesheet
|
||||||
export template: modèle d'export
|
export template: modèle d'export
|
||||||
symbol: symbole
|
symbol: symbole
|
||||||
card: Carte
|
card: carte
|
||||||
cards: Cartes
|
cards: cartes
|
||||||
extra card: extra Carte
|
extra card: extra carte
|
||||||
field: champ
|
field: champ
|
||||||
style: style
|
style: style
|
||||||
styling: style
|
styling: style
|
||||||
@@ -1184,8 +1177,8 @@ type:
|
|||||||
keyword: mot-clef
|
keyword: mot-clef
|
||||||
keywords: mots-clefs
|
keywords: mots-clefs
|
||||||
pack: type de pack
|
pack: type de pack
|
||||||
card region: région de Carte
|
card region: région de carte
|
||||||
card regions: régions de Carte
|
card regions: régions de carte
|
||||||
|
|
||||||
# symbol editor shapes
|
# symbol editor shapes
|
||||||
shape: forme
|
shape: forme
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ menu:
|
|||||||
next card: Seleziona &carta successiva PgDn
|
next card: Seleziona &carta successiva PgDn
|
||||||
search cards: Cerca carte Ctrl+K
|
search cards: Cerca carte Ctrl+K
|
||||||
add card: &Aggiungi carta Ctrl+Enter
|
add card: &Aggiungi carta Ctrl+Enter
|
||||||
add card double: Aggiungi carta fronte-retro Ctrl+Shift+Enter
|
|
||||||
add cards: Aggiungi &carte Multiple...
|
add cards: Aggiungi &carte Multiple...
|
||||||
remove card: &Rimuovi carta Del
|
remove card: &Rimuovi carta Del
|
||||||
add card csv: Aggiungi carte da CSV o TSV...
|
add card csv: Aggiungi carte da CSV o TSV...
|
||||||
@@ -197,7 +196,6 @@ help:
|
|||||||
next card: Seleziona la prossima carta della lista
|
next card: Seleziona la prossima carta della lista
|
||||||
search cards: Filtra l'elenco delle carte utilizzando i termini di ricerca
|
search cards: Filtra l'elenco delle carte utilizzando i termini di ricerca
|
||||||
add card: Aggiunge una nuova carta vuota al set
|
add card: Aggiunge una nuova carta vuota al set
|
||||||
add card double: Aggiunge una nuova carta vuota con il retro al set
|
|
||||||
add cards: Aggiunge carte multiple al set
|
add cards: Aggiunge carte multiple al set
|
||||||
remove card: Cancella la carta selezionata dal set
|
remove card: Cancella la carta selezionata dal set
|
||||||
link card: Collega una o più carte alla carta selezionata
|
link card: Collega una o più carte alla carta selezionata
|
||||||
@@ -445,7 +443,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Aggiungi carta
|
add card: Aggiungi carta
|
||||||
add card double: Aggiungi carta fronte-retro
|
|
||||||
remove card: Rimuovi carta selezionata
|
remove card: Rimuovi carta selezionata
|
||||||
link card: Collega alcune carte alla carta selezionata
|
link card: Collega alcune carte alla carta selezionata
|
||||||
copy card and links: Copia le carte selezionate e tutte le carte collegate
|
copy card and links: Copia le carte selezionate e tutte le carte collegate
|
||||||
@@ -712,7 +709,6 @@ label:
|
|||||||
installable version: Ultima versione:
|
installable version: Ultima versione:
|
||||||
installer size: Dimesioni:
|
installer size: Dimesioni:
|
||||||
installer status: Stato:
|
installer status: Stato:
|
||||||
folder name: Nome:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
load image: Fai doppio clic per caricare un'immagine
|
load image: Fai doppio clic per caricare un'immagine
|
||||||
@@ -825,16 +821,15 @@ button:
|
|||||||
close: &Chiudi
|
close: &Chiudi
|
||||||
|
|
||||||
# packages window
|
# packages window
|
||||||
keep package: &Mantieni così com'è
|
keep package: &Non modificare
|
||||||
don't install package: &Non installare
|
don't install package: &Non installare
|
||||||
install package: &Installa
|
install package: &Installa
|
||||||
upgrade package: Aggiorna
|
upgrade package: Aggiorna (&U)
|
||||||
reinstall package: Re&installa
|
reinstall package: Re&installa
|
||||||
remove package: &Rimuovi
|
remove package: &Rimuovi
|
||||||
keep group: Mantieni il gruppo così com'è
|
install group: &Installa Tutto
|
||||||
install group: &Installa/Aggiorna il gruppo
|
upgrade group: &Upgrade Tutto
|
||||||
upgrade group: &Aggiorna il gruppo
|
remove group: &Rimuovi Tutto
|
||||||
remove group: &Rimuovi il gruppo
|
|
||||||
|
|
||||||
############################################################## Titles in the GUI
|
############################################################## Titles in the GUI
|
||||||
title:
|
title:
|
||||||
@@ -914,7 +909,6 @@ title:
|
|||||||
action:
|
action:
|
||||||
# cards
|
# cards
|
||||||
reorder cards: Riordina le carte
|
reorder cards: Riordina le carte
|
||||||
update card: Aggiorna la carta
|
|
||||||
change link: Modifica collegamento
|
change link: Modifica collegamento
|
||||||
change notes: Modifica note
|
change notes: Modifica note
|
||||||
change id: Modifica ID
|
change id: Modifica ID
|
||||||
@@ -1053,8 +1047,7 @@ error:
|
|||||||
|
|
||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Le coordinate per la fusione si sovrappongono.
|
coordinates for blending overlap: Le coordinate per la fusione si sovrappongono.
|
||||||
blending different sizes: Le immagini utilizzate per la fusione devono avere le stesse dimensioni nella funzione '%s'. (Una è %s, l'altra è %s)
|
blending different sizes: Le immagini utilizzate per la fusione devono avere le stesse dimensioni nella funzione '%s'.
|
||||||
blending different mask: L'immagine e la maschera utilizzate per la fusione devono avere le stesse dimensioni nella funzione '%s'. (L'immagine è %s, la maschera è %s)
|
|
||||||
negative image width: Immagine con larghezza zero o negativa creata nella funzione '%s'.
|
negative image width: Immagine con larghezza zero o negativa creata nella funzione '%s'.
|
||||||
negative image height: Immagine con altezza zero o negativa creata nella funzione '%s'.
|
negative image height: Immagine con altezza zero o negativa creata nella funzione '%s'.
|
||||||
can't load image: Impossibile caricare l'immagine. Assicurarsi che il formato effettivo dell'immagine corrisponda all'estensione salvata.
|
can't load image: Impossibile caricare l'immagine. Assicurarsi che il formato effettivo dell'immagine corrisponda all'estensione salvata.
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ menu:
|
|||||||
next card: 次のカードを選択 PgDn
|
next card: 次のカードを選択 PgDn
|
||||||
search cards: カードの検索 Ctrl+K
|
search cards: カードの検索 Ctrl+K
|
||||||
add card: &カードを追加 Ctrl+Enter
|
add card: &カードを追加 Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: &複数のカードを追加...
|
add cards: &複数のカードを追加...
|
||||||
remove card: &選択したカードを削除
|
remove card: &選択したカードを削除
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -210,8 +208,6 @@ help:
|
|||||||
next card: リストの次のカードを選択します。
|
next card: リストの次のカードを選択します。
|
||||||
search cards: 検索語を使用してカードリストをフィルタリングする
|
search cards: 検索語を使用してカードリストをフィルタリングする
|
||||||
add card: 新しいカードを現在のセットに加えます。
|
add card: 新しいカードを現在のセットに加えます。
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: 複数のカードを現在のセットに加えます。
|
add cards: 複数のカードを現在のセットに加えます。
|
||||||
remove card: 現在のセットから選ばれたカードを削除します。
|
remove card: 現在のセットから選ばれたカードを削除します。
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -471,8 +467,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: カードを追加
|
add card: カードを追加
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: 選択したカードを削除
|
remove card: 選択したカードを削除
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -764,8 +758,6 @@ label:
|
|||||||
installable version: 最新バージョン
|
installable version: 最新バージョン
|
||||||
installer size: サイズ
|
installer size: サイズ
|
||||||
installer status: 状態
|
installer status: 状態
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -898,8 +890,6 @@ button:
|
|||||||
upgrade package: &アップグレード
|
upgrade package: &アップグレード
|
||||||
reinstall package: 再インストール
|
reinstall package: 再インストール
|
||||||
remove package: &取り外す
|
remove package: &取り外す
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: すべてインストールする
|
install group: すべてインストールする
|
||||||
upgrade group: すべてアップグレードする
|
upgrade group: すべてアップグレードする
|
||||||
remove group: すべて削除する
|
remove group: すべて削除する
|
||||||
@@ -992,8 +982,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1143,9 +1131,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: オーバーラップを混ぜることのための座標
|
coordinates for blending overlap: オーバーラップを混ぜることのための座標
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -54,8 +54,6 @@ menu:
|
|||||||
next card: 다음 카드 PgDn
|
next card: 다음 카드 PgDn
|
||||||
search cards: &카드 검색 Ctrl+K
|
search cards: &카드 검색 Ctrl+K
|
||||||
add card: &카드 추가 Ctrl+Enter
|
add card: &카드 추가 Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: &여러 카드 추가...
|
add cards: &여러 카드 추가...
|
||||||
remove card: &카드 삭제
|
remove card: &카드 삭제
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -210,8 +208,6 @@ help:
|
|||||||
next card: 목록에서 다음 카드를 선택합니다.
|
next card: 목록에서 다음 카드를 선택합니다.
|
||||||
search cards: 검색어를 사용하여 카드 목록 필터링
|
search cards: 검색어를 사용하여 카드 목록 필터링
|
||||||
add card: 이 세트에 새로운 빈 카드를 추가하세요.
|
add card: 이 세트에 새로운 빈 카드를 추가하세요.
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: 세트에 여러 카드 추가
|
add cards: 세트에 여러 카드 추가
|
||||||
remove card: 이 세트에서 선택한 카드를 삭제하세요.
|
remove card: 이 세트에서 선택한 카드를 삭제하세요.
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -477,8 +473,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: 카드 추가
|
add card: 카드 추가
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: 선택한 카드 삭제
|
remove card: 선택한 카드 삭제
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -770,8 +764,6 @@ label:
|
|||||||
installable version: 최신 버전:
|
installable version: 최신 버전:
|
||||||
installer size: 크기:
|
installer size: 크기:
|
||||||
installer status: 상태:
|
installer status: 상태:
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -904,8 +896,6 @@ button:
|
|||||||
upgrade package: 업데이트
|
upgrade package: 업데이트
|
||||||
reinstall package: 재설치
|
reinstall package: 재설치
|
||||||
remove package: 제거하다
|
remove package: 제거하다
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: 모두 설치
|
install group: 모두 설치
|
||||||
upgrade group: 모두 업그레이드
|
upgrade group: 모두 업그레이드
|
||||||
remove group: 모두 제거
|
remove group: 모두 제거
|
||||||
@@ -998,8 +988,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1149,9 +1137,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: 블렌딩 오버랩을 위한 좌표
|
coordinates for blending overlap: 블렌딩 오버랩을 위한 좌표
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -64,8 +64,6 @@ menu:
|
|||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
search cards: &Search Cards Ctrl+K
|
search cards: &Search Cards Ctrl+K
|
||||||
add card: &Dodaj Kartę Ctrl+Enter
|
add card: &Dodaj Kartę Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: Dodaj &Wiele Kart...
|
add cards: Dodaj &Wiele Kart...
|
||||||
remove card: &Usuń Wybraną Kartę
|
remove card: &Usuń Wybraną Kartę
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -229,8 +227,6 @@ help:
|
|||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
search cards: Filter the card list using search terms
|
search cards: Filter the card list using search terms
|
||||||
add card: Dodaj nową, pustą kartę do zestawu
|
add card: Dodaj nową, pustą kartę do zestawu
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: Dodaj wiele kart do zestawu
|
add cards: Dodaj wiele kart do zestawu
|
||||||
remove card: Usuń wybraną kartę z zestawu
|
remove card: Usuń wybraną kartę z zestawu
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -506,8 +502,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Dodaj kartę
|
add card: Dodaj kartę
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: Usuń wybraną kartę
|
remove card: Usuń wybraną kartę
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -814,8 +808,6 @@ label:
|
|||||||
installable version: Najnowsza wersja:
|
installable version: Najnowsza wersja:
|
||||||
installer size: Rozmiar:
|
installer size: Rozmiar:
|
||||||
installer status: Stan:
|
installer status: Stan:
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -952,8 +944,6 @@ button:
|
|||||||
upgrade package: &Uaktualnij
|
upgrade package: &Uaktualnij
|
||||||
reinstall package: Zainstaluj &ponownie
|
reinstall package: Zainstaluj &ponownie
|
||||||
remove package: &Usuń
|
remove package: &Usuń
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: &Instaluj wszystkie
|
install group: &Instaluj wszystkie
|
||||||
upgrade group: &Uaktualnij wszystkie
|
upgrade group: &Uaktualnij wszystkie
|
||||||
remove group: &Usuń wszystkie
|
remove group: &Usuń wszystkie
|
||||||
@@ -1047,8 +1037,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1199,9 +1187,7 @@ error:
|
|||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: Współrzędne scalania (blending) nachodzą na siebie
|
coordinates for blending overlap: Współrzędne scalania (blending) nachodzą na siebie
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -54,7 +54,6 @@ menu:
|
|||||||
next card: Selecionar Próximo ca&rd PgDn
|
next card: Selecionar Próximo ca&rd PgDn
|
||||||
search cards: &Procurar Cards Ctrl+K
|
search cards: &Procurar Cards Ctrl+K
|
||||||
add card: &Adicionar Card Ctrl+Enter
|
add card: &Adicionar Card Ctrl+Enter
|
||||||
add card double: &Adicionar Card de dupla face Ctrl+Shift+Enter
|
|
||||||
add cards: Adicionar &Multiplos Cards...
|
add cards: Adicionar &Multiplos Cards...
|
||||||
remove card: &Deletar Card Selecionado
|
remove card: &Deletar Card Selecionado
|
||||||
add card csv: Adicionar Cards de um arquivo CSV ou TSV...
|
add card csv: Adicionar Cards de um arquivo CSV ou TSV...
|
||||||
@@ -195,9 +194,8 @@ help:
|
|||||||
# cards menu
|
# cards menu
|
||||||
previous card: Seleciona o Card anterior da lista.
|
previous card: Seleciona o Card anterior da lista.
|
||||||
next card: Seleciona o próximo Card da lista.
|
next card: Seleciona o próximo Card da lista.
|
||||||
search cards: Filtre a lista de Cards usando termos de pesquisa.
|
search cards: Filtre a lista de Cards usando termos de pesquisa
|
||||||
add card: Adicione um novo, em branco, Card para esta Edição.
|
add card: Adicione um novo, em branco, Card para esta Edição.
|
||||||
add card double: Adicione um novo, em branco, Card com verso para esta Edição.
|
|
||||||
add cards: Adicione multiplos Cards à esta Edição.
|
add cards: Adicione multiplos Cards à esta Edição.
|
||||||
remove card: Apaga o Card selecionado desta Edição.
|
remove card: Apaga o Card selecionado desta Edição.
|
||||||
link card: Vincular um ou mais Cards à Card selecionado
|
link card: Vincular um ou mais Cards à Card selecionado
|
||||||
@@ -446,7 +444,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Adiciona um Card
|
add card: Adiciona um Card
|
||||||
add card double: Adicionar um Card de dupla face
|
|
||||||
remove card: Remove o Card selecionado
|
remove card: Remove o Card selecionado
|
||||||
link card: Vincular Cards ao Card selecionado
|
link card: Vincular Cards ao Card selecionado
|
||||||
copy card and links: Copiar Cards selecionados e seus Cards vinculados
|
copy card and links: Copiar Cards selecionados e seus Cards vinculados
|
||||||
@@ -713,7 +710,6 @@ label:
|
|||||||
installable version: Última versão:
|
installable version: Última versão:
|
||||||
installer size: Dimenções:
|
installer size: Dimenções:
|
||||||
installer status: Status:
|
installer status: Status:
|
||||||
folder name: Nome da pasta:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
load image: Clique duas vezes para carregar uma imagem
|
load image: Clique duas vezes para carregar uma imagem
|
||||||
@@ -826,16 +822,15 @@ button:
|
|||||||
close: &Fechar
|
close: &Fechar
|
||||||
|
|
||||||
# packages window
|
# packages window
|
||||||
keep package: Manter como está
|
keep package: Não& alterar
|
||||||
don't install package: Não& instalar
|
don't install package: Não& instalar
|
||||||
install package: &Instalar
|
install package: &Instalar
|
||||||
upgrade package: &Atualizar
|
upgrade package: &Atualizações
|
||||||
reinstall package: Re&instalar
|
reinstall package: Re&instalar
|
||||||
remove package: &Remover
|
remove package: &Remover
|
||||||
keep group: &Manter o grupo como está
|
install group: &Instalar Tudo
|
||||||
install group: &Instalar/Atualizar o grupo
|
upgrade group: &Atualizar tudo
|
||||||
upgrade group: &Atualizar o grupo
|
remove group: &Remover tudo
|
||||||
remove group: &Remover o grupo
|
|
||||||
|
|
||||||
############################################################## Titles in the GUI
|
############################################################## Titles in the GUI
|
||||||
title:
|
title:
|
||||||
@@ -915,7 +910,6 @@ title:
|
|||||||
action:
|
action:
|
||||||
# cards
|
# cards
|
||||||
reorder cards: Reordenar Cards
|
reorder cards: Reordenar Cards
|
||||||
update card: Atualizar Card
|
|
||||||
change link: Alterar link
|
change link: Alterar link
|
||||||
change notes: Alterar notas
|
change notes: Alterar notas
|
||||||
change id: Alterar ID
|
change id: Alterar ID
|
||||||
@@ -1054,8 +1048,7 @@ error:
|
|||||||
|
|
||||||
# image stuff
|
# image stuff
|
||||||
coordinates for blending overlap: As coordenadas para a mistura se sobrepõem.
|
coordinates for blending overlap: As coordenadas para a mistura se sobrepõem.
|
||||||
blending different sizes: As imagens usadas para mesclagem devem ter o mesmo tamanho na função '%s'. (Uma é %s, a outra é %s)
|
blending different sizes: As imagens usadas para mesclagem devem ter o mesmo tamanho na função '%s'.
|
||||||
blending different mask: A imagem e a máscara usadas para mesclagem devem ter o mesmo tamanho na função '%s' (Imagem é %s, máscara é %s)
|
|
||||||
negative image width: Imagem com largura zero ou negativa criada na função '%s'
|
negative image width: Imagem com largura zero ou negativa criada na função '%s'
|
||||||
negative image height: Imagem com altura zero ou negativa criada na função '%s'
|
negative image height: Imagem com altura zero ou negativa criada na função '%s'
|
||||||
can't load image: Falha ao carregar a imagem. Verifique se o formato real da imagem corresponde à extensão salva.
|
can't load image: Falha ao carregar a imagem. Verifique se o formato real da imagem corresponde à extensão salva.
|
||||||
|
|||||||
@@ -55,8 +55,6 @@ menu:
|
|||||||
next card: Следующая карта PgDn
|
next card: Следующая карта PgDn
|
||||||
search cards: Найти карты Ctrl+K
|
search cards: Найти карты Ctrl+K
|
||||||
add card: Добавить карту Ctrl+Enter
|
add card: Добавить карту Ctrl+Enter
|
||||||
#TODO: Localize
|
|
||||||
add card double: &Add Double Faced Card Ctrl+Shift+Enter
|
|
||||||
add cards: Добавить несколько карт...
|
add cards: Добавить несколько карт...
|
||||||
remove card: Удалить выделенную карту
|
remove card: Удалить выделенную карту
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -221,8 +219,6 @@ help:
|
|||||||
next card: Выбрать следующую карту в списке
|
next card: Выбрать следующую карту в списке
|
||||||
search cards: Отфильтруйте список карточек с помощью условий поиска
|
search cards: Отфильтруйте список карточек с помощью условий поиска
|
||||||
add card: Добавить новую карту в текущий сет
|
add card: Добавить новую карту в текущий сет
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add a new, blank, card that has a back face to this set
|
|
||||||
add cards: Добавить несколько новых карт в текущий сет
|
add cards: Добавить несколько новых карт в текущий сет
|
||||||
remove card: Удалить выбранную карту из текущего сета
|
remove card: Удалить выбранную карту из текущего сета
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -494,8 +490,6 @@ tooltip:
|
|||||||
|
|
||||||
# cards toolbar
|
# cards toolbar
|
||||||
add card: Добавить карту
|
add card: Добавить карту
|
||||||
#TODO: Localize
|
|
||||||
add card double: Add double faced card
|
|
||||||
remove card: Удалить выделенную карту
|
remove card: Удалить выделенную карту
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
link card: Link cards to selected card
|
link card: Link cards to selected card
|
||||||
@@ -804,8 +798,6 @@ label:
|
|||||||
installable version: Последняя версия:
|
installable version: Последняя версия:
|
||||||
installer size: Размер:
|
installer size: Размер:
|
||||||
installer status: Статус:
|
installer status: Статус:
|
||||||
#TODO: Localize
|
|
||||||
folder name: Folder name:
|
|
||||||
no version: -
|
no version: -
|
||||||
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
@@ -940,8 +932,6 @@ button:
|
|||||||
upgrade package: Обновить
|
upgrade package: Обновить
|
||||||
reinstall package: Переустановить
|
reinstall package: Переустановить
|
||||||
remove package: Удалить
|
remove package: Удалить
|
||||||
#TODO: Localize
|
|
||||||
keep group: Keep Group As Is
|
|
||||||
install group: Установить все
|
install group: Установить все
|
||||||
upgrade group: Обновить все
|
upgrade group: Обновить все
|
||||||
remove group: Удалить все
|
remove group: Удалить все
|
||||||
@@ -1035,8 +1025,6 @@ action:
|
|||||||
# cards
|
# cards
|
||||||
#TODO: Localize Section
|
#TODO: Localize Section
|
||||||
reorder cards: Reorder cards
|
reorder cards: Reorder cards
|
||||||
#TODO: Localize
|
|
||||||
update card: Update card
|
|
||||||
change link: Change link
|
change link: Change link
|
||||||
change notes: Change notes
|
change notes: Change notes
|
||||||
change id: Change ID
|
change id: Change ID
|
||||||
@@ -1194,9 +1182,7 @@ error:
|
|||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
coordinates for blending overlap: Coordinates for blending overlap. Space them out.
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
blending different sizes: Images used for blending must have the same size in function '%s' (one is %s, the other is %s)
|
blending different sizes: Images used for blending must have the same size in function '%s'
|
||||||
#TODO: Localize
|
|
||||||
blending different mask: Image and mask used for blending must have the same size in function '%s' (image is %s, mask is %s)
|
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
negative image width: Image with zero or negative width created in function '%s'
|
negative image width: Image with zero or negative width created in function '%s'
|
||||||
#TODO: Localize
|
#TODO: Localize
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
Function: exists_as_package
|
|
||||||
|
|
||||||
--Usage--
|
|
||||||
> exists_as_package("package")
|
|
||||||
|
|
||||||
Check if a package exists in the data folder.
|
|
||||||
|
|
||||||
Returns the package's version number as major-minor-patch, or nil if the package does not exists.
|
|
||||||
|
|
||||||
--Parameters--
|
|
||||||
! Parameter Type Description
|
|
||||||
| @input@ [[type:string]] Full name of the package folder, including game and extension.
|
|
||||||
|
|
||||||
--Examples--
|
|
||||||
> exists_as_package("magic-modules.mse-include") == "2026-02-28"
|
|
||||||
> exists_as_package("magic-quadruple-faced-leveler.mse-style") == nil
|
|
||||||
@@ -78,7 +78,6 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
| [[fun:exclusive_choice]] Require that at most one of the given choices is selected.
|
| [[fun:exclusive_choice]] Require that at most one of the given choices is selected.
|
||||||
| [[fun:require_exclusive_choice]] Require that exactly one of the given choices is selected.
|
| [[fun:require_exclusive_choice]] Require that exactly one of the given choices is selected.
|
||||||
| [[fun:remove_choice]] Remove the given choices from a multiple choice value.
|
| [[fun:remove_choice]] Remove the given choices from a multiple choice value.
|
||||||
| [[fun:is_default]] Check if a field is in its default state.
|
|
||||||
|
|
||||||
! Images <<<
|
! Images <<<
|
||||||
| [[fun:linear_blend]] Blend two images together using a linear gradient.
|
| [[fun:linear_blend]] Blend two images together using a linear gradient.
|
||||||
@@ -109,7 +108,6 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
|
|
||||||
! Cards <<<
|
! Cards <<<
|
||||||
| [[fun:new_card]] Construct a new [[type:card]] object.
|
| [[fun:new_card]] Construct a new [[type:card]] object.
|
||||||
| [[fun:new_uid]] Construct a new uid.
|
|
||||||
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
| [[fun:add_card_to_set]] Add a [[type:card]] to a [[type:set]].
|
||||||
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
| [[fun:get_card_styling]] Get the styling data of a [[type:card]].
|
||||||
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
| [[fun:get_card_stylesheet]] Get the stylesheet of a [[type:card]].
|
||||||
@@ -138,6 +136,4 @@ These functions are built into the program, other [[type:function]]s can be defi
|
|||||||
| [[fun:assert]] Check a condition for debugging purposes.
|
| [[fun:assert]] Check a condition for debugging purposes.
|
||||||
| [[fun:warning]] Output a warning message.
|
| [[fun:warning]] Output a warning message.
|
||||||
| [[fun:error]] Output an error message.
|
| [[fun:error]] Output an error message.
|
||||||
| [[fun:version_is_older]] Checks if a version number is older than another.
|
|
||||||
| [[fun:exists_as_package]] Checks if a package exists.
|
|
||||||
| [[fun:exists_in_package]] Checks if a file exists in a package.
|
| [[fun:exists_in_package]] Checks if a file exists in a package.
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
Function: is_default
|
|
||||||
|
|
||||||
--Usage--
|
|
||||||
> is_default(some_field)
|
|
||||||
|
|
||||||
Returns true if the field is in its default state, that is, if the user hasn't modified the value yet, false otherwise.
|
|
||||||
|
|
||||||
--Parameters--
|
|
||||||
! Parameter Type Description
|
|
||||||
| @input@ [[type:field]] Field to test.
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
Function: new_uid
|
|
||||||
|
|
||||||
--Usage--
|
|
||||||
> new_uid()
|
|
||||||
|
|
||||||
Returns a new card uid, a string of 32 random digits, which is guaranteed to not exist in the set.
|
|
||||||
|
|
||||||
--Parameters--
|
|
||||||
! Parameter Type Description
|
|
||||||
| @set@ [[type:set]] The set in which to look for uid conflicts. This can be omitted since 'set' is a predefined variable.
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
Function: version_is_older
|
|
||||||
|
|
||||||
--Usage--
|
|
||||||
> version_is_older("version", than: "other version")
|
|
||||||
|
|
||||||
Check if a version number is strictly older than another.
|
|
||||||
|
|
||||||
Malformed version numbers, including nil, are treated as 0-0-0.
|
|
||||||
|
|
||||||
--Parameters--
|
|
||||||
! Parameter Type Description
|
|
||||||
| @input@ [[type:string]] Version we want to check.
|
|
||||||
| @than@ [[type:string]] Version we want to check against.
|
|
||||||
|
|
||||||
--Examples--
|
|
||||||
> version_is_older("2025-06-28", than: "2026-02-18") == true
|
|
||||||
> version_is_older("2026-02-18", than: "2026-02-18") == false
|
|
||||||
> version_is_older(nil, than: "0-0-1") == true
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 546 B |
@@ -66,7 +66,6 @@ tool/dark_reminder IMAGE "tool/dark_reminder.png"
|
|||||||
tool/no_auto IMAGE "tool/no_auto.png"
|
tool/no_auto IMAGE "tool/no_auto.png"
|
||||||
|
|
||||||
tool/card_add IMAGE "tool/card_add.png"
|
tool/card_add IMAGE "tool/card_add.png"
|
||||||
tool/card_add_double IMAGE "tool/card_add_double.png"
|
|
||||||
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
tool/card_add_multiple IMAGE "tool/card_add_multiple.png"
|
||||||
tool/card_modify_multiple IMAGE "tool/card_modify_multiple.png"
|
tool/card_modify_multiple IMAGE "tool/card_modify_multiple.png"
|
||||||
tool/card_del IMAGE "tool/card_del.png"
|
tool/card_del IMAGE "tool/card_del.png"
|
||||||
|
|||||||
+18
-40
@@ -30,6 +30,13 @@ AddCardAction::AddCardAction(AddingOrRemoving ar, Set& set, const vector<CardP>&
|
|||||||
// We always assume uid conflicts occur because a card was copy-pasted into the same set,
|
// We always assume uid conflicts occur because a card was copy-pasted into the same set,
|
||||||
// and never because two different cards randomly got assigned the same uid
|
// and never because two different cards randomly got assigned the same uid
|
||||||
if (!action.adding) return;
|
if (!action.adding) return;
|
||||||
|
// Tally existing unique ids
|
||||||
|
unordered_map<String, CardP> all_existing_cards;
|
||||||
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set.cards) {
|
||||||
|
all_existing_cards.insert({ card->uid, card });
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
// Tally added unique ids
|
// Tally added unique ids
|
||||||
unordered_map<String, CardP> all_added_uids;
|
unordered_map<String, CardP> all_added_uids;
|
||||||
for (size_t pos = 0; pos < action.steps.size(); ++pos) {
|
for (size_t pos = 0; pos < action.steps.size(); ++pos) {
|
||||||
@@ -42,7 +49,7 @@ AddCardAction::AddCardAction(AddingOrRemoving ar, Set& set, const vector<CardP>&
|
|||||||
String old_uid = added_pair.first;
|
String old_uid = added_pair.first;
|
||||||
CardP added_card = added_pair.second;
|
CardP added_card = added_pair.second;
|
||||||
// Assign new unique id if necessary
|
// Assign new unique id if necessary
|
||||||
if (set.card_uids.find(old_uid) == set.card_uids.end()) continue;
|
if (all_existing_cards.find(old_uid) == all_existing_cards.end()) continue;
|
||||||
String new_uid = generate_uid();
|
String new_uid = generate_uid();
|
||||||
added_card->uid = new_uid;
|
added_card->uid = new_uid;
|
||||||
all_added_uids.insert({ new_uid, added_card });
|
all_added_uids.insert({ new_uid, added_card });
|
||||||
@@ -51,22 +58,21 @@ AddCardAction::AddCardAction(AddingOrRemoving ar, Set& set, const vector<CardP>&
|
|||||||
FOR_EACH(linked_pair, linked_pairs) {
|
FOR_EACH(linked_pair, linked_pairs) {
|
||||||
String& linked_uid = linked_pair.first.get();
|
String& linked_uid = linked_pair.first.get();
|
||||||
if (linked_uid.empty()) continue;
|
if (linked_uid.empty()) continue;
|
||||||
// If it's an added card, update the link
|
// If it's an added card, replace the link
|
||||||
if (all_added_uids.find(linked_uid) != all_added_uids.end()) {
|
if (all_added_uids.find(linked_uid) != all_added_uids.end()) {
|
||||||
all_added_uids.at(linked_uid)->updateLinkedUID(old_uid, new_uid);
|
all_added_uids.at(linked_uid)->updateLinkedUID(old_uid, new_uid);
|
||||||
}
|
}
|
||||||
// Otherwise, if it's an existing card, create an action to copy the link
|
// Otherwise, if it's an existing card, create an action to copy the link
|
||||||
else if (set.card_uids.find(linked_uid) != set.card_uids.end()) {
|
else if (all_existing_cards.find(linked_uid) != all_existing_cards.end()) {
|
||||||
CardP linked_card = set.card_uids.at(linked_uid);
|
CardP linked_card = all_existing_cards.at(linked_uid);
|
||||||
int selected_index = linked_card->findUIDLink(old_uid);
|
int linked_index = linked_card->findFreeLink(new_uid, all_existing_uids);
|
||||||
if (selected_index < 0) continue;
|
if (linked_index < 0) {
|
||||||
int free_index = linked_card->findFreeLink(new_uid, set.card_uids);
|
|
||||||
if (free_index < 0) {
|
|
||||||
queue_message(MESSAGE_WARNING, _ERROR_1_("not enough free links", linked_card->identification()));
|
queue_message(MESSAGE_WARNING, _ERROR_1_("not enough free links", linked_card->identification()));
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
String selected_relation(linked_card->getLinkedRelation(selected_index));
|
else {
|
||||||
card_link_actions.push_back(make_intrusive<OneWayLinkCardsAction>(linked_card, new_uid, selected_relation, free_index));
|
String relation(linked_card->getLinkedRelation(linked_index));
|
||||||
|
card_link_actions.push_back(make_intrusive<OneWayLinkCardsAction>(linked_card, new_uid, relation, linked_index));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -82,33 +88,6 @@ void AddCardAction::perform(bool to_undo) {
|
|||||||
// Update card links
|
// Update card links
|
||||||
for (size_t i = 0; i < card_link_actions.size(); ++i) {
|
for (size_t i = 0; i < card_link_actions.size(); ++i) {
|
||||||
card_link_actions[i]->perform(to_undo);
|
card_link_actions[i]->perform(to_undo);
|
||||||
}
|
|
||||||
// Update uid map
|
|
||||||
set.buildUIDMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateCardAction::UpdateCardAction(Set& set, const vector<CardP>& cards_to_add, const vector<CardP>& cards_to_remove)
|
|
||||||
: CardListAction(set)
|
|
||||||
, action_add(ADD, set, cards_to_add)
|
|
||||||
, action_remove(REMOVE, set, cards_to_remove)
|
|
||||||
{}
|
|
||||||
|
|
||||||
String UpdateCardAction::getName(bool to_undo) const {
|
|
||||||
return _ACTION_("update card");
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateCardAction::perform(bool to_undo) {
|
|
||||||
if (to_undo) {
|
|
||||||
action_remove.perform(to_undo);
|
|
||||||
set.actions.tellListeners(action_remove, to_undo);
|
|
||||||
action_add.perform(to_undo);
|
|
||||||
set.actions.tellListeners(action_add, to_undo);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
action_add.perform(to_undo);
|
|
||||||
set.actions.tellListeners(action_add, to_undo);
|
|
||||||
action_remove.perform(to_undo);
|
|
||||||
set.actions.tellListeners(action_remove, to_undo);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -270,8 +249,7 @@ void ChangeCardUIDAction::perform(bool to_undo) {
|
|||||||
FOR_EACH(c, set.cards) {
|
FOR_EACH(c, set.cards) {
|
||||||
c->updateLinkedUID(card->uid, uid);
|
c->updateLinkedUID(card->uid, uid);
|
||||||
}
|
}
|
||||||
swap(card->uid, uid);
|
swap(card->uid, uid);
|
||||||
set.buildUIDMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Pack types
|
// ----------------------------------------------------------------------------- : Pack types
|
||||||
|
|||||||
@@ -50,18 +50,6 @@ public:
|
|||||||
vector<ActionP> card_link_actions;
|
vector<ActionP> card_link_actions;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Update one or more cards from a set by replacing them with other cards
|
|
||||||
class UpdateCardAction : public CardListAction {
|
|
||||||
public:
|
|
||||||
UpdateCardAction(Set& set, const vector<CardP>& cards_to_add, const vector<CardP>& cards_to_remove);
|
|
||||||
|
|
||||||
String getName(bool to_undo) const override;
|
|
||||||
void perform(bool to_undo) override;
|
|
||||||
|
|
||||||
AddCardAction action_add;
|
|
||||||
AddCardAction action_remove;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Reorder cards
|
// ----------------------------------------------------------------------------- : Reorder cards
|
||||||
|
|
||||||
/// Change the position of a card in the card list by swapping two cards
|
/// Change the position of a card in the card list by swapping two cards
|
||||||
|
|||||||
@@ -400,10 +400,8 @@ String BulkAction::getName(bool to_undo) const {
|
|||||||
return to_undo ? name_undo : name_do;
|
return to_undo ? name_undo : name_do;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulkAction::perform(bool to_undo) {
|
void BulkAction::perform(bool to_undo) {
|
||||||
size_t size = actions.size();
|
FOR_EACH(action, actions) {
|
||||||
for (size_t i = 0 ; i < size ; ++i) {
|
|
||||||
ActionP& action = actions[to_undo ? size - i - 1 : i];
|
|
||||||
action->perform(to_undo);
|
action->perform(to_undo);
|
||||||
set->actions.tellListeners(*action, to_undo);
|
set->actions.tellListeners(*action, to_undo);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,22 +25,18 @@ IMPLEMENT_REFLECTION_NO_SCRIPT(AddCardsScript) {
|
|||||||
|
|
||||||
void AddCardsScript::perform(Set& set, vector<CardP>& out) {
|
void AddCardsScript::perform(Set& set, vector<CardP>& out) {
|
||||||
// Perform script
|
// Perform script
|
||||||
Context& ctx = set.getContext();
|
Context& ctx = set.getContext();
|
||||||
if (enabled.hasBeenRead()) {
|
|
||||||
enabled.update(ctx);
|
|
||||||
if (!enabled()) return;
|
|
||||||
}
|
|
||||||
ScriptValueP result = script.invoke(ctx);
|
ScriptValueP result = script.invoke(ctx);
|
||||||
// Add cards to out
|
// Add cards to out
|
||||||
ScriptValueP it = result->makeIterator();
|
ScriptValueP it = result->makeIterator();
|
||||||
while (ScriptValueP item = it->next()) {
|
while (ScriptValueP item = it->next()) {
|
||||||
CardP new_card = from_script<CardP>(item);
|
CardP card = from_script<CardP>(item);
|
||||||
// is this a new card?
|
// is this a new card?
|
||||||
if (contains(set.cards,new_card) || contains(out,new_card)) {
|
if (contains(set.cards,card) || contains(out,card)) {
|
||||||
// make copy
|
// make copy
|
||||||
new_card = make_intrusive<Card>(&set, new_card);
|
card = make_intrusive<Card>(*card);
|
||||||
}
|
}
|
||||||
out.push_back(new_card);
|
out.push_back(card);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-126
@@ -42,38 +42,7 @@ Card::Card(Game& game)
|
|||||||
, has_styling(false)
|
, has_styling(false)
|
||||||
{
|
{
|
||||||
data.init(game.card_fields);
|
data.init(game.card_fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
Card::Card(Set* set, const CardP& card)
|
|
||||||
: game(card->game)
|
|
||||||
, time_created (wxDateTime::Now())
|
|
||||||
, time_modified(wxDateTime::Now())
|
|
||||||
, notes(card->notes)
|
|
||||||
, uid(generate_uid())
|
|
||||||
, linked_card_1(card->linked_card_1)
|
|
||||||
, linked_card_2(card->linked_card_2)
|
|
||||||
, linked_card_3(card->linked_card_3)
|
|
||||||
, linked_card_4(card->linked_card_4)
|
|
||||||
, linked_relation_1(card->linked_relation_1)
|
|
||||||
, linked_relation_2(card->linked_relation_2)
|
|
||||||
, linked_relation_3(card->linked_relation_3)
|
|
||||||
, linked_relation_4(card->linked_relation_4)
|
|
||||||
, has_styling(card->has_styling)
|
|
||||||
, stylesheet_version(card->stylesheet_version)
|
|
||||||
, stylesheet(card->stylesheet)
|
|
||||||
{
|
|
||||||
if (!stylesheet && set) {
|
|
||||||
stylesheet = set->stylesheetForP(card);
|
|
||||||
}
|
|
||||||
if (has_styling) {
|
|
||||||
styling_data.cloneFrom(card->styling_data);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (stylesheet && set) styling_data.cloneFrom(set->stylingDataFor(*stylesheet));
|
|
||||||
}
|
|
||||||
data.cloneFrom(card->data);
|
|
||||||
extra_data.cloneFrom(card->extra_data);
|
|
||||||
}
|
|
||||||
|
|
||||||
String Card::identification() const {
|
String Card::identification() const {
|
||||||
// an identifying field
|
// an identifying field
|
||||||
@@ -98,7 +67,7 @@ bool Card::contains(QuickFilterPart const& query) const {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<int> Card::findFreeLinks(vector<String>& linked_uids, const unordered_map<String, CardP>& all_existing_uids) {
|
vector<int> Card::findFreeLinks(vector<String>& linked_uids, const unordered_set<String>& all_existing_uids) {
|
||||||
vector<int> freeIndexes;
|
vector<int> freeIndexes;
|
||||||
int count = min(4, (int)linked_uids.size());
|
int count = min(4, (int)linked_uids.size());
|
||||||
LINK_PAIRS(linked_pairs, this);
|
LINK_PAIRS(linked_pairs, this);
|
||||||
@@ -140,7 +109,7 @@ vector<int> Card::findFreeLinks(vector<String>& linked_uids, const unordered_map
|
|||||||
}
|
}
|
||||||
return freeIndexes;
|
return freeIndexes;
|
||||||
}
|
}
|
||||||
int Card::findFreeLink(const String& linked_uid, const unordered_map<String, CardP>& all_existing_uids) {
|
int Card::findFreeLink(const String& linked_uid, const unordered_set<String>& all_existing_uids) {
|
||||||
vector<String> linked_uids { linked_uid };
|
vector<String> linked_uids { linked_uid };
|
||||||
return findFreeLinks(linked_uids, all_existing_uids)[0];
|
return findFreeLinks(linked_uids, all_existing_uids)[0];
|
||||||
}
|
}
|
||||||
@@ -186,26 +155,12 @@ void Card::updateLinkedUID(const String& old_uid, const String& new_uid) {
|
|||||||
if (index >= 0) getLinkedUID(index) = new_uid;
|
if (index >= 0) getLinkedUID(index) = new_uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
//vector<CardP> Card::getLinkedRelationCards(const vector<CardP>& cards, const String& linked_relation, bool erase_if_no_card) {
|
vector<CardP> Card::getLinkedRelationCards(const vector<CardP>& cards, const String& linked_relation, bool erase_if_no_card) {
|
||||||
// vector<CardP> other_cards;
|
|
||||||
// vector<int> indexes = findRelationLinks(linked_relation);
|
|
||||||
// for (size_t i = 0; i < indexes.size(); ++i) {
|
|
||||||
// String& linked_uid = getLinkedUID(indexes[i]);
|
|
||||||
// CardP other_card = getUIDCard(cards, linked_uid);
|
|
||||||
// if (other_card) other_cards.push_back(other_card);
|
|
||||||
// else if (erase_if_no_card) {
|
|
||||||
// linked_uid = _("");
|
|
||||||
// getLinkedRelation(indexes[i]) = _("");
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return other_cards;
|
|
||||||
//}
|
|
||||||
vector<CardP> Card::getLinkedRelationCards(const Set& set, const String& linked_relation, bool erase_if_no_card) {
|
|
||||||
vector<CardP> other_cards;
|
vector<CardP> other_cards;
|
||||||
vector<int> indexes = findRelationLinks(linked_relation);
|
vector<int> indexes = findRelationLinks(linked_relation);
|
||||||
for (size_t i = 0; i < indexes.size(); ++i) {
|
for (size_t i = 0; i < indexes.size(); ++i) {
|
||||||
String& linked_uid = getLinkedUID(indexes[i]);
|
String& linked_uid = getLinkedUID(indexes[i]);
|
||||||
CardP other_card = getUIDCard(set, linked_uid);
|
CardP other_card = getUIDCard(cards, linked_uid);
|
||||||
if (other_card) other_cards.push_back(other_card);
|
if (other_card) other_cards.push_back(other_card);
|
||||||
else if (erase_if_no_card) {
|
else if (erase_if_no_card) {
|
||||||
linked_uid = _("");
|
linked_uid = _("");
|
||||||
@@ -214,76 +169,51 @@ vector<CardP> Card::getLinkedRelationCards(const Set& set, const String& linked_
|
|||||||
}
|
}
|
||||||
return other_cards;
|
return other_cards;
|
||||||
}
|
}
|
||||||
|
vector<CardP> Card::getLinkedRelationCards(const Set& set, const String& linked_relation, bool erase_if_no_card) {
|
||||||
|
return getLinkedRelationCards(set.cards, linked_relation, erase_if_no_card);
|
||||||
|
}
|
||||||
|
|
||||||
//vector<pair<CardP, String>> Card::getLinkedCards(const vector<CardP>& cards) {
|
vector<pair<CardP, String>> Card::getLinkedCards(const vector<CardP>& cards) {
|
||||||
// unordered_map<String, String> links{
|
unordered_map<String, String> links{
|
||||||
// { linked_card_1, linked_relation_1 },
|
{ linked_card_1, linked_relation_1 },
|
||||||
// { linked_card_2, linked_relation_2 },
|
{ linked_card_2, linked_relation_2 },
|
||||||
// { linked_card_3, linked_relation_3 },
|
{ linked_card_3, linked_relation_3 },
|
||||||
// { linked_card_4, linked_relation_4 }
|
{ linked_card_4, linked_relation_4 }
|
||||||
// };
|
};
|
||||||
// vector<pair<CardP, String>> linked_cards;
|
|
||||||
// FOR_EACH(other_card, cards) {
|
|
||||||
// if (links.find(other_card->uid) != links.end()) {
|
|
||||||
// linked_cards.push_back(make_pair(other_card, links.at(other_card->uid)));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return linked_cards;
|
|
||||||
//}
|
|
||||||
vector<pair<CardP, String>> Card::getLinkedCards(const Set& set) {
|
|
||||||
vector<pair<CardP, String>> linked_cards;
|
vector<pair<CardP, String>> linked_cards;
|
||||||
CardP other_card_1 = getUIDCard(set, linked_card_1);
|
FOR_EACH(other_card, cards) {
|
||||||
if (other_card_1) {
|
if (links.find(other_card->uid) != links.end()) {
|
||||||
linked_cards.push_back(make_pair(other_card_1, linked_relation_1));
|
linked_cards.push_back(make_pair(other_card, links.at(other_card->uid)));
|
||||||
}
|
}
|
||||||
CardP other_card_2 = getUIDCard(set, linked_card_2);
|
|
||||||
if (other_card_2) {
|
|
||||||
linked_cards.push_back(make_pair(other_card_2, linked_relation_2));
|
|
||||||
}
|
|
||||||
CardP other_card_3 = getUIDCard(set, linked_card_3);
|
|
||||||
if (other_card_3) {
|
|
||||||
linked_cards.push_back(make_pair(other_card_3, linked_relation_3));
|
|
||||||
}
|
|
||||||
CardP other_card_4 = getUIDCard(set, linked_card_4);
|
|
||||||
if (other_card_4) {
|
|
||||||
linked_cards.push_back(make_pair(other_card_4, linked_relation_4));
|
|
||||||
}
|
}
|
||||||
return linked_cards;
|
return linked_cards;
|
||||||
}
|
}
|
||||||
|
vector<pair<CardP, String>> Card::getLinkedCards(const Set& set) {
|
||||||
|
return getLinkedCards(set.cards);
|
||||||
|
}
|
||||||
|
|
||||||
//CardP Card::getLinkedOtherFaceCard(const vector<CardP>& cards) {
|
CardP Card::getLinkedOtherFaceCard(const vector<CardP>& cards) {
|
||||||
// unordered_set<String> faces;
|
unordered_set<String> faces;
|
||||||
// if (linked_relation_1 == _("Front Face") || linked_relation_1 == _("Back Face")) faces.emplace(linked_card_1);
|
if (linked_relation_1 == _("Front Face") || linked_relation_1 == _("Back Face")) faces.emplace(linked_card_1);
|
||||||
// if (linked_relation_2 == _("Front Face") || linked_relation_2 == _("Back Face")) faces.emplace(linked_card_2);
|
if (linked_relation_2 == _("Front Face") || linked_relation_2 == _("Back Face")) faces.emplace(linked_card_2);
|
||||||
// if (linked_relation_3 == _("Front Face") || linked_relation_3 == _("Back Face")) faces.emplace(linked_card_3);
|
if (linked_relation_3 == _("Front Face") || linked_relation_3 == _("Back Face")) faces.emplace(linked_card_3);
|
||||||
// if (linked_relation_4 == _("Front Face") || linked_relation_4 == _("Back Face")) faces.emplace(linked_card_4);
|
if (linked_relation_4 == _("Front Face") || linked_relation_4 == _("Back Face")) faces.emplace(linked_card_4);
|
||||||
// FOR_EACH(other_card, cards) {
|
FOR_EACH(other_card, cards) {
|
||||||
// if (faces.find(other_card->uid) != faces.end()) return other_card;
|
if (faces.find(other_card->uid) != faces.end()) return other_card;
|
||||||
// }
|
|
||||||
// return nullptr;
|
|
||||||
//}
|
|
||||||
CardP Card::getLinkedOtherFaceCard(const Set& set) {
|
|
||||||
if (linked_relation_1 == _("Front Face") || linked_relation_1 == _("Back Face")) {
|
|
||||||
CardP other_card_1 = getUIDCard(set, linked_card_1);
|
|
||||||
if (other_card_1) return other_card_1;
|
|
||||||
}
|
|
||||||
if (linked_relation_2 == _("Front Face") || linked_relation_2 == _("Back Face")) {
|
|
||||||
CardP other_card_2 = getUIDCard(set, linked_card_2);
|
|
||||||
if (other_card_2) return other_card_2;
|
|
||||||
}
|
|
||||||
if (linked_relation_3 == _("Front Face") || linked_relation_3 == _("Back Face")) {
|
|
||||||
CardP other_card_3 = getUIDCard(set, linked_card_3);
|
|
||||||
if (other_card_3) return other_card_3;
|
|
||||||
}
|
|
||||||
if (linked_relation_4 == _("Front Face") || linked_relation_4 == _("Back Face")) {
|
|
||||||
CardP other_card_4 = getUIDCard(set, linked_card_4);
|
|
||||||
if (other_card_4) return other_card_4;
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
CardP Card::getLinkedOtherFaceCard(const Set& set) {
|
||||||
|
return getLinkedOtherFaceCard(set.cards);
|
||||||
|
}
|
||||||
|
|
||||||
void Card::addLink(const Set& set, CardP& linked_card, const String& selected_relation, const String& linked_relation) {
|
void Card::addLink(const Set& set, CardP& linked_card, const String& selected_relation, const String& linked_relation) {
|
||||||
int index = findFreeLink(linked_card->uid, set.card_uids);
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set.cards) {
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int index = findFreeLink(linked_card->uid, all_existing_uids);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
queue_message(MESSAGE_ERROR, _ERROR_1_("not enough free links", identification()));
|
queue_message(MESSAGE_ERROR, _ERROR_1_("not enough free links", identification()));
|
||||||
return;
|
return;
|
||||||
@@ -291,7 +221,7 @@ void Card::addLink(const Set& set, CardP& linked_card, const String& selected_re
|
|||||||
getLinkedUID(index) = linked_card->uid;
|
getLinkedUID(index) = linked_card->uid;
|
||||||
getLinkedRelation(index) = linked_relation;
|
getLinkedRelation(index) = linked_relation;
|
||||||
|
|
||||||
index = linked_card->findFreeLink(uid, set.card_uids);
|
index = linked_card->findFreeLink(uid, all_existing_uids);
|
||||||
if (index < 0) {
|
if (index < 0) {
|
||||||
queue_message(MESSAGE_ERROR, _ERROR_1_("not enough free links", linked_card->identification()));
|
queue_message(MESSAGE_ERROR, _ERROR_1_("not enough free links", linked_card->identification()));
|
||||||
}
|
}
|
||||||
@@ -316,19 +246,15 @@ void Card::removeLink(const CardP& linked_card)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//CardP Card::getUIDCard(const vector<CardP>& cards, const String& uid) {
|
CardP Card::getUIDCard(const vector<CardP>& cards, const String& uid) {
|
||||||
// FOR_EACH(card, cards) {
|
FOR_EACH(card, cards) {
|
||||||
// if (card->uid == uid) return card;
|
if (card->uid == uid) return card;
|
||||||
// }
|
|
||||||
// return nullptr;
|
|
||||||
//}
|
|
||||||
CardP Card::getUIDCard(const Set& set, const String& uid) {
|
|
||||||
auto it = set.card_uids.find(uid);
|
|
||||||
if (it != set.card_uids.end()) {
|
|
||||||
return it->second;
|
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
CardP Card::getUIDCard(const Set& set, const String& uid) {
|
||||||
|
return getUIDCard(set.cards, uid);
|
||||||
|
}
|
||||||
|
|
||||||
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
|
IndexMap<FieldP, ValueP>& Card::extraDataFor(const StyleSheet& stylesheet) {
|
||||||
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
|
return extra_data.get(stylesheet.name(), stylesheet.extra_card_fields);
|
||||||
@@ -375,12 +301,7 @@ void reflect_version_check(GetDefaultMember& handler, const Char* key, intrusive
|
|||||||
|
|
||||||
IMPLEMENT_REFLECTION(Card) {
|
IMPLEMENT_REFLECTION(Card) {
|
||||||
REFLECT(stylesheet);
|
REFLECT(stylesheet);
|
||||||
if (Handler::isReading) {
|
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||||
REFLECT_NO_SCRIPT(stylesheet_version);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
|
||||||
}
|
|
||||||
REFLECT(has_styling);
|
REFLECT(has_styling);
|
||||||
if (has_styling) {
|
if (has_styling) {
|
||||||
if (stylesheet) {
|
if (stylesheet) {
|
||||||
|
|||||||
+7
-11
@@ -35,8 +35,6 @@ public:
|
|||||||
Card();
|
Card();
|
||||||
/// Creates a card using the given game
|
/// Creates a card using the given game
|
||||||
Card(Game& game);
|
Card(Game& game);
|
||||||
/// Copy constructor, makes a deep copy
|
|
||||||
Card(Set* set, const CardP& card);
|
|
||||||
|
|
||||||
/// The game this card is made for
|
/// The game this card is made for
|
||||||
Game* game;
|
Game* game;
|
||||||
@@ -62,9 +60,7 @@ public:
|
|||||||
wxDateTime time_created, time_modified;
|
wxDateTime time_created, time_modified;
|
||||||
/// Alternative style to use for this card
|
/// Alternative style to use for this card
|
||||||
/** Optional; if not set use the card style from the set */
|
/** Optional; if not set use the card style from the set */
|
||||||
StyleSheetP stylesheet;
|
StyleSheetP stylesheet;
|
||||||
/// What version of the stylesheet was this card using when it was last saved?
|
|
||||||
Version stylesheet_version;
|
|
||||||
/// Alternative options to use for this card, for this card's stylesheet
|
/// Alternative options to use for this card, for this card's stylesheet
|
||||||
/** Optional; if not set use the styling data from the set.
|
/** Optional; if not set use the styling data from the set.
|
||||||
* If stylesheet is set then contains data for the this->stylesheet, otherwise for set->stylesheet
|
* If stylesheet is set then contains data for the this->stylesheet, otherwise for set->stylesheet
|
||||||
@@ -110,8 +106,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Find the index of a free link slot to write to. Returns -1 if not found.
|
/// Find the index of a free link slot to write to. Returns -1 if not found.
|
||||||
int findFreeLink (const String& linked_uid, const unordered_map<String, CardP>& all_existing_uids);
|
int findFreeLink (const String& linked_uid, const unordered_set<String>& all_existing_uids);
|
||||||
vector<int> findFreeLinks(vector<String>& linked_uids, const unordered_map<String, CardP>& all_existing_uids);
|
vector<int> findFreeLinks(vector<String>& linked_uids, const unordered_set<String>& all_existing_uids);
|
||||||
|
|
||||||
/// Find the index of a link slot that references the linked_uid. Returns -1 if not found.
|
/// Find the index of a link slot that references the linked_uid. Returns -1 if not found.
|
||||||
int findUIDLink(const String& linked_uid);
|
int findUIDLink(const String& linked_uid);
|
||||||
@@ -129,18 +125,18 @@ public:
|
|||||||
//void updateLinkedRelation(const String& old_relation, const String& new_relation);
|
//void updateLinkedRelation(const String& old_relation, const String& new_relation);
|
||||||
|
|
||||||
/// Get the card with the given uid.
|
/// Get the card with the given uid.
|
||||||
//static CardP getUIDCard(const vector<CardP>& cards, const String& uid);
|
static CardP getUIDCard(const vector<CardP>& cards, const String& uid);
|
||||||
static CardP getUIDCard(const Set& set, const String& uid);
|
static CardP getUIDCard(const Set& set, const String& uid);
|
||||||
/// Get all the cards linked to this card with the given relation.
|
/// Get all the cards linked to this card with the given relation.
|
||||||
//vector<CardP> getLinkedRelationCards(const vector<CardP>& cards, const String& linked_relation, bool erase_if_no_card = true);
|
vector<CardP> getLinkedRelationCards(const vector<CardP>& cards, const String& linked_relation, bool erase_if_no_card = true);
|
||||||
vector<CardP> getLinkedRelationCards(const Set& set, const String& linked_relation, bool erase_if_no_card = true);
|
vector<CardP> getLinkedRelationCards(const Set& set, const String& linked_relation, bool erase_if_no_card = true);
|
||||||
|
|
||||||
/// Get all the cards linked to this card.
|
/// Get all the cards linked to this card.
|
||||||
//vector<pair<CardP, String>> getLinkedCards(const vector<CardP>& cards);
|
vector<pair<CardP, String>> getLinkedCards(const vector<CardP>& cards);
|
||||||
vector<pair<CardP, String>> getLinkedCards(const Set& set);
|
vector<pair<CardP, String>> getLinkedCards(const Set& set);
|
||||||
|
|
||||||
/// Get the back face or front face of this card.
|
/// Get the back face or front face of this card.
|
||||||
//CardP getLinkedOtherFaceCard(const vector<CardP>& cards);
|
CardP getLinkedOtherFaceCard(const vector<CardP>& cards);
|
||||||
CardP getLinkedOtherFaceCard(const Set& set);
|
CardP getLinkedOtherFaceCard(const Set& set);
|
||||||
|
|
||||||
/// Link a card to this card.
|
/// Link a card to this card.
|
||||||
|
|||||||
@@ -305,10 +305,6 @@ bool Value::equals(const Value* that) {
|
|||||||
return this == that;
|
return this == that;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Value::isDefault() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Value::update(Context& ctx) {
|
bool Value::update(Context& ctx) {
|
||||||
updateAge();
|
updateAge();
|
||||||
updateSortValue(ctx);
|
updateSortValue(ctx);
|
||||||
|
|||||||
+1
-3
@@ -255,9 +255,7 @@ public:
|
|||||||
virtual ValueP clone() const = 0;
|
virtual ValueP clone() const = 0;
|
||||||
|
|
||||||
/// Convert this value to a string for use in tables
|
/// Convert this value to a string for use in tables
|
||||||
virtual String toString() const = 0;
|
virtual String toString() const = 0;
|
||||||
/// Check if this value is in the default state
|
|
||||||
virtual bool isDefault();
|
|
||||||
/// Apply scripts to this value, return true if the value has changed
|
/// Apply scripts to this value, return true if the value has changed
|
||||||
virtual bool update(Context& ctx);
|
virtual bool update(Context& ctx);
|
||||||
/// This value has been updated by an action
|
/// This value has been updated by an action
|
||||||
|
|||||||
@@ -317,12 +317,7 @@ ChoiceValue::ChoiceValue(const ChoiceFieldP& field, bool initial_first_choice)
|
|||||||
|
|
||||||
String ChoiceValue::toString() const {
|
String ChoiceValue::toString() const {
|
||||||
return value();
|
return value();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ChoiceValue::isDefault() {
|
|
||||||
return value.isDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ChoiceValue::update(Context& ctx) {
|
bool ChoiceValue::update(Context& ctx) {
|
||||||
bool change = field().default_script.invokeOnDefault(ctx, value)
|
bool change = field().default_script.invokeOnDefault(ctx, value)
|
||||||
| field(). script.invokeOn(ctx, value);
|
| field(). script.invokeOn(ctx, value);
|
||||||
|
|||||||
@@ -199,9 +199,7 @@ public:
|
|||||||
DECLARE_VALUE_TYPE(Choice, Defaultable<String>);
|
DECLARE_VALUE_TYPE(Choice, Defaultable<String>);
|
||||||
|
|
||||||
ValueType value; /// The name of the selected choice
|
ValueType value; /// The name of the selected choice
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -110,12 +110,7 @@ String ColorValue::toString() const {
|
|||||||
if (value() == c->color) return c->name;
|
if (value() == c->color) return c->name;
|
||||||
}
|
}
|
||||||
return _("<color>");
|
return _("<color>");
|
||||||
}
|
|
||||||
|
|
||||||
bool ColorValue::isDefault() {
|
|
||||||
return value.isDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ColorValue::update(Context& ctx) {
|
bool ColorValue::update(Context& ctx) {
|
||||||
bool change = field().default_script.invokeOnDefault(ctx, value)
|
bool change = field().default_script.invokeOnDefault(ctx, value)
|
||||||
| field(). script.invokeOn(ctx, value);
|
| field(). script.invokeOn(ctx, value);
|
||||||
|
|||||||
@@ -77,9 +77,7 @@ public:
|
|||||||
DECLARE_VALUE_TYPE(Color, Defaultable<Color>);
|
DECLARE_VALUE_TYPE(Color, Defaultable<Color>);
|
||||||
|
|
||||||
ValueType value; ///< The value
|
ValueType value; ///< The value
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -39,10 +39,6 @@ String ImageValue::toString() const {
|
|||||||
return filename.empty() ? _("") : _("<image>");
|
return filename.empty() ? _("") : _("<image>");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ImageValue::isDefault() {
|
|
||||||
return filename.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// custom reflection: convert to ScriptImageP for scripting
|
// custom reflection: convert to ScriptImageP for scripting
|
||||||
|
|
||||||
void ImageValue::reflect(Reader& handler) {
|
void ImageValue::reflect(Reader& handler) {
|
||||||
|
|||||||
@@ -47,9 +47,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ValueType filename; ///< Filename of the image (in the current package), or ""
|
ValueType filename; ///< Filename of the image (in the current package), or ""
|
||||||
Age last_update; ///< When was the image last changed?
|
Age last_update; ///< When was the image last changed?
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImageStyle
|
// ----------------------------------------------------------------------------- : ImageStyle
|
||||||
|
|||||||
@@ -62,12 +62,7 @@ IMPLEMENT_REFLECTION(InfoStyle) {
|
|||||||
|
|
||||||
String InfoValue::toString() const {
|
String InfoValue::toString() const {
|
||||||
return value;
|
return value;
|
||||||
}
|
|
||||||
|
|
||||||
bool InfoValue::isDefault() {
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InfoValue::update(Context& ctx) {
|
bool InfoValue::update(Context& ctx) {
|
||||||
if (value.empty()) value = field().caption.get();
|
if (value.empty()) value = field().caption.get();
|
||||||
bool change = field().script.invokeOn(ctx, value);
|
bool change = field().script.invokeOn(ctx, value);
|
||||||
|
|||||||
@@ -60,9 +60,7 @@ public:
|
|||||||
DECLARE_VALUE_TYPE(Info, String);
|
DECLARE_VALUE_TYPE(Info, String);
|
||||||
|
|
||||||
ValueType value;
|
ValueType value;
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -52,10 +52,6 @@ IMPLEMENT_REFLECTION_NAMELESS(MultipleChoiceValue) {
|
|||||||
REFLECT_BASE(ChoiceValue);
|
REFLECT_BASE(ChoiceValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultipleChoiceValue::isDefault() {
|
|
||||||
return value.isDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MultipleChoiceValue::update(Context& ctx) {
|
bool MultipleChoiceValue::update(Context& ctx) {
|
||||||
String old_value = value();
|
String old_value = value();
|
||||||
ctx.setVariable(_("last_change"), to_script(last_change));
|
ctx.setVariable(_("last_change"), to_script(last_change));
|
||||||
|
|||||||
@@ -63,9 +63,7 @@ public:
|
|||||||
|
|
||||||
/// Splits the value, stores the selected choices in the out parameter
|
/// Splits the value, stores the selected choices in the out parameter
|
||||||
void get(vector<String>& out) const;
|
void get(vector<String>& out) const;
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -62,12 +62,6 @@ PackagedP PackageChoiceValue::getPackage() const {
|
|||||||
else return package_manager.openAny(package_name, true);
|
else return package_manager.openAny(package_name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PackageChoiceValue::isDefault() {
|
|
||||||
PackageChoiceFieldP packageFieldP = boost::dynamic_pointer_cast<PackageChoiceField>(fieldP);
|
|
||||||
if (packageFieldP) return package_name == packageFieldP->initial;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool PackageChoiceValue::update(Context& ctx) {
|
bool PackageChoiceValue::update(Context& ctx) {
|
||||||
bool change = field().script.invokeOn(ctx, package_name);
|
bool change = field().script.invokeOn(ctx, package_name);
|
||||||
Value::update(ctx);
|
Value::update(ctx);
|
||||||
|
|||||||
@@ -61,9 +61,7 @@ public:
|
|||||||
|
|
||||||
/// Get the package (if it is set), otherwise return nullptr
|
/// Get the package (if it is set), otherwise return nullptr
|
||||||
PackagedP getPackage() const;
|
PackagedP getPackage() const;
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -51,10 +51,6 @@ String SymbolValue::toString() const {
|
|||||||
return filename.empty() ? _("") : _("<symbol>");
|
return filename.empty() ? _("") : _("<symbol>");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SymbolValue::isDefault() {
|
|
||||||
return filename.empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_NO_GET_MEMBER(SymbolValue) {
|
IMPLEMENT_REFLECTION_NO_GET_MEMBER(SymbolValue) {
|
||||||
if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(filename);
|
if (fieldP->save_value || !handler.isWriting) REFLECT_NAMELESS(filename);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,6 @@ public:
|
|||||||
DECLARE_VALUE_TYPE(Symbol, LocalFileName);
|
DECLARE_VALUE_TYPE(Symbol, LocalFileName);
|
||||||
|
|
||||||
ValueType filename; ///< Filename of the symbol (in the current package)
|
ValueType filename; ///< Filename of the symbol (in the current package)
|
||||||
Age last_update; ///< When was the symbol last changed?
|
Age last_update; ///< When was the symbol last changed?
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -176,12 +176,7 @@ IMPLEMENT_REFLECTION(TextStyle) {
|
|||||||
|
|
||||||
String TextValue::toString() const {
|
String TextValue::toString() const {
|
||||||
return untag_hide_sep(value());
|
return untag_hide_sep(value());
|
||||||
}
|
|
||||||
|
|
||||||
bool TextValue::isDefault() {
|
|
||||||
return value.isDefault();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TextValue::update(Context& ctx) {
|
bool TextValue::update(Context& ctx) {
|
||||||
updateAge();
|
updateAge();
|
||||||
WITH_DYNAMIC_ARG(last_update_age, last_update.get());
|
WITH_DYNAMIC_ARG(last_update_age, last_update.get());
|
||||||
|
|||||||
@@ -112,9 +112,7 @@ public:
|
|||||||
|
|
||||||
ValueType value; ///< The text of this value
|
ValueType value; ///< The text of this value
|
||||||
Age last_update; ///< When was the text last changed?
|
Age last_update; ///< When was the text last changed?
|
||||||
|
|
||||||
bool isDefault() override;
|
|
||||||
|
|
||||||
bool update(Context&) override;
|
bool update(Context&) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -61,11 +61,9 @@ IMPLEMENT_REFLECTION(WrappedCards) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
wxDataFormat CardsDataObject::format(wxString("application/x-mse-cards"));
|
wxDataFormat CardsDataObject::format(wxString("application/x-mse-cards"));
|
||||||
|
|
||||||
CardsDataObject::CardsDataObject(const SetP& set, const String& id, const vector<CardP>& cards)
|
CardsDataObject::CardsDataObject(const SetP& set, const String id, const vector<CardP>& cards) {
|
||||||
: wxCustomDataObject(format)
|
|
||||||
{
|
|
||||||
// set the stylesheet, so when deserializing we know whos style options we are reading
|
// set the stylesheet, so when deserializing we know whos style options we are reading
|
||||||
vector<bool> has_styling;
|
vector<bool> has_styling;
|
||||||
for (size_t i = 0 ; i < cards.size() ; ++i) {
|
for (size_t i = 0 ; i < cards.size() ; ++i) {
|
||||||
@@ -74,15 +72,9 @@ CardsDataObject::CardsDataObject(const SetP& set, const String& id, const vector
|
|||||||
cards[i]->stylesheet = set->stylesheet;
|
cards[i]->stylesheet = set->stylesheet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// store as raw bytes
|
|
||||||
WrappedCards data = { set->game.get(), set->game->name(), id, cards };
|
WrappedCards data = { set->game.get(), set->game->name(), id, cards };
|
||||||
String serialized = serialize_for_clipboard(*set, data);
|
SetText(serialize_for_clipboard(*set, data));
|
||||||
wxScopedCharBuffer utf8 = serialized.utf8_str();
|
// restore cards
|
||||||
buffer.assign(utf8.data(), utf8.length());
|
|
||||||
SetData(buffer.size(), buffer.data());
|
|
||||||
|
|
||||||
// restore styling
|
|
||||||
for (size_t i = 0 ; i < cards.size() ; ++i) {
|
for (size_t i = 0 ; i < cards.size() ; ++i) {
|
||||||
if (has_styling[i]) {
|
if (has_styling[i]) {
|
||||||
cards[i]->stylesheet = StyleSheetP();
|
cards[i]->stylesheet = StyleSheetP();
|
||||||
@@ -91,31 +83,22 @@ CardsDataObject::CardsDataObject(const SetP& set, const String& id, const vector
|
|||||||
SetFormat(format);
|
SetFormat(format);
|
||||||
}
|
}
|
||||||
|
|
||||||
CardsDataObject::CardsDataObject()
|
CardsDataObject::CardsDataObject() {
|
||||||
: wxCustomDataObject(format)
|
SetFormat(format);
|
||||||
{}
|
}
|
||||||
|
|
||||||
bool CardsDataObject::getCards(const SetP& set, const String& id, vector<CardP>& out) {
|
bool CardsDataObject::getCards(const SetP& set, const String id, vector<CardP>& out) {
|
||||||
size_t size = GetSize();
|
|
||||||
if (size == 0) return false;
|
|
||||||
const void* raw = GetData();
|
|
||||||
if (!raw) return false;
|
|
||||||
|
|
||||||
String text(wxString::FromUTF8(static_cast<const char*>(raw), size));
|
|
||||||
WrappedCards data = { set->game.get(), set->game->name() };
|
WrappedCards data = { set->game.get(), set->game->name() };
|
||||||
try {
|
deserialize_from_clipboard(data, *set, GetText());
|
||||||
deserialize_from_clipboard(data, *set, text);
|
|
||||||
} catch (...) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("DEBUG: Card deserialization failed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (data.cards.empty()) return false;
|
if (data.cards.empty()) return false;
|
||||||
if (!id.empty() && data.id == id) return false;
|
if (!id.empty() && data.id == id) return false;
|
||||||
if (data.game_name != set->game->name()) return false;
|
if (data.game_name == set->game->name()) {
|
||||||
// Cards are from the same game
|
// Cards are from the same game
|
||||||
out = data.cards;
|
out = data.cards;
|
||||||
return true;
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : KeywordDataObject
|
// ----------------------------------------------------------------------------- : KeywordDataObject
|
||||||
@@ -156,34 +139,28 @@ KeywordP KeywordDataObject::getKeyword(const SetP& set) {
|
|||||||
deserialize_from_clipboard(data, *set, GetText());
|
deserialize_from_clipboard(data, *set, GetText());
|
||||||
if (data.game_name != set->game->name()) return KeywordP(); // Keyword is from a different game
|
if (data.game_name != set->game->name()) return KeywordP(); // Keyword is from a different game
|
||||||
else return keyword;
|
else return keyword;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Card on clipboard
|
// ----------------------------------------------------------------------------- : Card on clipboard
|
||||||
|
|
||||||
CardsOnClipboard::CardsOnClipboard(const SetP& set, const String id, const vector<CardP>& cards) {
|
CardsOnClipboard::CardsOnClipboard(const SetP& set, const String id, const vector<CardP>& cards) {
|
||||||
wxBusyCursor busy;
|
|
||||||
// Conversion to image file
|
// Conversion to image file
|
||||||
if (cards.size() < 6) {
|
if (cards.size() < 6) {
|
||||||
Bitmap bmp;
|
|
||||||
Image img;
|
Image img;
|
||||||
if (cards.size() == 1) {
|
if (cards.size() == 1) {
|
||||||
img = export_image(set, cards[0], true, 1.0, 0.0, 0.0, &bmp);
|
img = export_image(set, cards[0]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
img = export_image(set, cards);
|
img = export_image(set, cards);
|
||||||
bmp = Bitmap(img);
|
|
||||||
}
|
}
|
||||||
//wxFileDataObject* fileData = new wxFileDataObject(); // needed for pasting on desktop, but slow
|
String temp_path = wxFileName::CreateTempFileName(_("mse")) + _(".png");
|
||||||
//String temp_path = wxFileName::CreateTempFileName(_("mse")) + _(".png");
|
img.SaveFile(temp_path, wxBITMAP_TYPE_PNG);
|
||||||
//img.SaveFile(temp_path, wxBITMAP_TYPE_PNG);
|
wxFileDataObject* fileData = new wxFileDataObject();
|
||||||
//fileData->AddFile(temp_path);
|
fileData->AddFile(temp_path);
|
||||||
//Add(fileData);
|
Add(fileData);
|
||||||
wxImageDataObject* imgData = new wxImageDataObject(); // needed for metadata
|
wxImageDataObject* imgData = new wxImageDataObject();
|
||||||
imgData->SetImage(img);
|
imgData->SetImage(img);
|
||||||
Add(imgData);
|
Add(imgData);
|
||||||
wxBitmapDataObject* bmpData = new wxBitmapDataObject(); // needed for pasting in MSPaint
|
|
||||||
bmpData->SetBitmap(bmp);
|
|
||||||
Add(bmpData);
|
|
||||||
}
|
}
|
||||||
// Conversion to serialized card format
|
// Conversion to serialized card format
|
||||||
Add(new CardsDataObject(set, id, cards), true);
|
Add(new CardsDataObject(set, id, cards), true);
|
||||||
|
|||||||
@@ -18,23 +18,20 @@ DECLARE_POINTER_TYPE(Keyword);
|
|||||||
// ----------------------------------------------------------------------------- : CardDataObject
|
// ----------------------------------------------------------------------------- : CardDataObject
|
||||||
|
|
||||||
/// The data format for cards on the clipboard
|
/// The data format for cards on the clipboard
|
||||||
class CardsDataObject : public wxCustomDataObject {
|
class CardsDataObject : public wxTextDataObject {
|
||||||
public:
|
public:
|
||||||
/// Name of the format of MSE cards
|
/// Name of the format of MSE cards
|
||||||
static wxDataFormat format;
|
static wxDataFormat format;
|
||||||
|
|
||||||
CardsDataObject();
|
CardsDataObject();
|
||||||
/// Store a card
|
/// Store a card
|
||||||
CardsDataObject(const SetP& set, const String& id, const vector<CardP>& cards);
|
CardsDataObject(const SetP& set, const String id, const vector<CardP>& cards);
|
||||||
|
|
||||||
/// Retrieve the cards, only if this is made with the same game as set
|
/// Retrieve the cards, only if this is made with the same game as set
|
||||||
/// And if this is NOT of the same id as the given one
|
/// And if this is NOT of the same id as the given one
|
||||||
/** Return true if the cards are correctly retrieved, and there is at least one card */
|
/** Return true if the cards are correctly retrieved, and there is at least one card */
|
||||||
bool getCards(const SetP& set, const String& id, vector<CardP>& out);
|
bool getCards(const SetP& set, const String id, vector<CardP>& out);
|
||||||
|
};
|
||||||
private:
|
|
||||||
std::string buffer; // keep data alive for wx
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : KeywordDataObject
|
// ----------------------------------------------------------------------------- : KeywordDataObject
|
||||||
|
|
||||||
@@ -47,7 +44,7 @@ public:
|
|||||||
KeywordDataObject();
|
KeywordDataObject();
|
||||||
/// Store a keyword
|
/// Store a keyword
|
||||||
KeywordDataObject(const SetP& set, const KeywordP& card);
|
KeywordDataObject(const SetP& set, const KeywordP& card);
|
||||||
|
|
||||||
/// Retrieve a keyword, only if it is made with the same game as set
|
/// Retrieve a keyword, only if it is made with the same game as set
|
||||||
KeywordP getKeyword(const SetP& set);
|
KeywordP getKeyword(const SetP& set);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ FileFormatP mtg_editor_file_format();
|
|||||||
// ----------------------------------------------------------------------------- : Other ways to export
|
// ----------------------------------------------------------------------------- : Other ways to export
|
||||||
|
|
||||||
/// Generate a wxImage of one or more cards
|
/// Generate a wxImage of one or more cards
|
||||||
Image export_image(const SetP& set, const CardP& card, bool write_metadata = true, double zoom = 1.0, Radians angle_radians = 0.0, double bleed_pixels = 0.0, Bitmap* out_bitmap = nullptr);
|
Image export_image(const SetP& set, const CardP& card, bool write_metadata = true, double zoom = 1.0, Radians angle_radians = 0.0, double bleed_pixels = 0.0);
|
||||||
Image export_image(const SetP& set, const vector<CardP>& cards, int padding = 2, double global_zoom = 1.0, bool use_zoom_setting = true, bool use_rotation_setting = true, bool use_bleed_setting = false);
|
Image export_image(const SetP& set, const vector<CardP>& cards, int padding = 2, double global_zoom = 1.0, bool use_zoom_setting = true, bool use_rotation_setting = true, bool use_bleed_setting = false);
|
||||||
|
|
||||||
/// Export the image of one or more cards to a given filename, using the app's zoom, rotation and bleed settings, and including metadata
|
/// Export the image of one or more cards to a given filename, using the app's zoom, rotation and bleed settings, and including metadata
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ Rotation ZoomedUnrotatedDataViewer::getRotation() const {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : wxImage export
|
// ----------------------------------------------------------------------------- : wxImage export
|
||||||
|
|
||||||
Image export_image(const SetP& set, const CardP& card, bool write_metadata, double zoom, Radians angle_radians, double bleed_pixels, Bitmap* out_bitmap) {
|
Image export_image(const SetP& set, const CardP& card, bool write_metadata, double zoom, Radians angle_radians, double bleed_pixels) {
|
||||||
if (!set) throw Error(_("no set"));
|
if (!set) throw Error(_("no set"));
|
||||||
/// create and zoom
|
/// create and zoom
|
||||||
ZoomedUnrotatedDataViewer viewer = ZoomedUnrotatedDataViewer(zoom);
|
ZoomedUnrotatedDataViewer viewer = ZoomedUnrotatedDataViewer(zoom);
|
||||||
@@ -51,9 +51,6 @@ Image export_image(const SetP& set, const CardP& card, bool write_metadata, doub
|
|||||||
viewer.draw(dc);
|
viewer.draw(dc);
|
||||||
dc.SelectObject(wxNullBitmap);
|
dc.SelectObject(wxNullBitmap);
|
||||||
Image img = bitmap.ConvertToImage();
|
Image img = bitmap.ConvertToImage();
|
||||||
|
|
||||||
/// return bitmap if needed
|
|
||||||
if (out_bitmap) *out_bitmap = std::move(bitmap);
|
|
||||||
|
|
||||||
/// rotate
|
/// rotate
|
||||||
img = rotate_image(img, angle_radians);
|
img = rotate_image(img, angle_radians);
|
||||||
@@ -221,7 +218,8 @@ void export_image(const SetP& set, const CardP& card, const String& filename) {
|
|||||||
img.SaveFile(filename);
|
img.SaveFile(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
void export_image(const SetP& set, const vector<CardP>& cards, const String& path, const String& filename_template, FilenameConflicts conflicts) {
|
void export_image(const SetP& set, const vector<CardP>& cards, const String& path, const String& filename_template, FilenameConflicts conflicts)
|
||||||
|
{
|
||||||
wxBusyCursor busy;
|
wxBusyCursor busy;
|
||||||
// Script
|
// Script
|
||||||
ScriptP filename_script = parse(filename_template, nullptr, true);
|
ScriptP filename_script = parse(filename_template, nullptr, true);
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include <boost/json.hpp>
|
#include <boost/json.hpp>
|
||||||
#include <wx/filename.h>
|
#include <wx/filename.h>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <filesystem>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Crop Rect Encoding
|
// ----------------------------------------------------------------------------- : Crop Rect Encoding
|
||||||
|
|
||||||
@@ -37,44 +36,44 @@ inline static String encodeRectInWxString(RealRect rect, int degrees) {
|
|||||||
_("</mse-crop-data>");
|
_("</mse-crop-data>");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retreive a rect encoded in a string, return true if "<mse-crop-data>" was found
|
/// Retreive a rect encoded in a string, return true if successful
|
||||||
inline static bool decodeRectFromString(const String& rectString, RealRect& rect_out, int& degrees_out) {
|
inline static bool decodeRectFromString(const String& rectString, RealRect& rect_out, int& degrees_out) {
|
||||||
size_t start = rectString.find(_("<mse-crop-data>"));
|
size_t start = rectString.find(_("<mse-crop-data>"));
|
||||||
if (start == String::npos) return false;
|
if (start == String::npos) return false;
|
||||||
size_t end = rectString.find(_("</mse-crop-data>"), start + 15);
|
size_t end = rectString.find(_("</mse-crop-data>"), start + 15);
|
||||||
if (end == String::npos) return true;
|
if (end == String::npos) return false;
|
||||||
String string = rectString.substr(start + 15, end - (start + 15));
|
String string = rectString.substr(start + 15, end - (start + 15));
|
||||||
if (string.empty()) return true;
|
if (string.empty()) return false;
|
||||||
|
|
||||||
size_t divider = string.find(_(";"));
|
size_t divider = string.find(_(";"));
|
||||||
if (divider == String::npos) return true;
|
if (divider == String::npos) return false;
|
||||||
if (divider == 0) return true;
|
if (divider == 0) return false;
|
||||||
int x;
|
int x;
|
||||||
if(!string.substr(0, divider).ToInt(&x)) return true;
|
if(!string.substr(0, divider).ToInt(&x)) return false;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
divider = string.find(_(";"));
|
divider = string.find(_(";"));
|
||||||
if (divider == String::npos) return true;
|
if (divider == String::npos) return false;
|
||||||
if (divider == 0) return true;
|
if (divider == 0) return false;
|
||||||
int y;
|
int y;
|
||||||
if(!string.substr(0, divider).ToInt(&y)) return true;
|
if(!string.substr(0, divider).ToInt(&y)) return false;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
divider = string.find(_(";"));
|
divider = string.find(_(";"));
|
||||||
if (divider == String::npos) return true;
|
if (divider == String::npos) return false;
|
||||||
if (divider == 0) return true;
|
if (divider == 0) return false;
|
||||||
int width;
|
int width;
|
||||||
if(!string.substr(0, divider).ToInt(&width)) return true;
|
if(!string.substr(0, divider).ToInt(&width)) return false;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
divider = string.find(_(";"));
|
divider = string.find(_(";"));
|
||||||
if (divider == String::npos) return true;
|
if (divider == String::npos) return false;
|
||||||
if (divider == 0) return true;
|
if (divider == 0) return false;
|
||||||
int height;
|
int height;
|
||||||
if(!string.substr(0, divider).ToInt(&height)) return true;
|
if(!string.substr(0, divider).ToInt(&height)) return false;
|
||||||
string = string.substr(divider + 1);
|
string = string.substr(divider + 1);
|
||||||
|
|
||||||
if(!string.ToInt(°rees_out)) return true;
|
if(!string.ToInt(°rees_out)) return false;
|
||||||
|
|
||||||
rect_out = RealRect(x, y, width, height);
|
rect_out = RealRect(x, y, width, height);
|
||||||
return true;
|
return true;
|
||||||
@@ -82,18 +81,17 @@ inline static bool decodeRectFromString(const String& rectString, RealRect& rect
|
|||||||
|
|
||||||
/// Retreive a rect encoded in a string, apply a transformation, then encode it back
|
/// Retreive a rect encoded in a string, apply a transformation, then encode it back
|
||||||
inline static String transformEncodedRect(const String& rectString, RectTransform transform, double param_x, double param_y, int mode) {
|
inline static String transformEncodedRect(const String& rectString, RectTransform transform, double param_x, double param_y, int mode) {
|
||||||
RealRect rect(0.0, 0.0, 0.0, 0.0);
|
RealRect rect(0,0,0,0);
|
||||||
int degrees = 0;
|
int degrees;
|
||||||
decodeRectFromString(rectString, rect, degrees);
|
if (!decodeRectFromString(rectString, rect, degrees)) return _("");
|
||||||
if (rect.width > 0.0 && rect.height > 0.0) {
|
transform(rect, degrees, param_x, param_y, mode);
|
||||||
transform(rect, degrees, param_x, param_y, mode);
|
return encodeRectInWxString(rect, degrees);
|
||||||
return encodeRectInWxString(rect, degrees);
|
|
||||||
}
|
|
||||||
return _("");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retreive all rects encoded in a string, apply a transformation, then encode them back
|
/// Retreive all rects encoded in a string, apply a transformation, then encode them back
|
||||||
inline static String transformAllEncodedRects(const String& rectString, RectTransform transform, double param_x, double param_y, int mode = 0) {
|
inline static String transformAllEncodedRects(const String& rectString, RectTransform transform, double param_x, double param_y, int mode = 0) {
|
||||||
|
RealRect rect(0,0,0,0);
|
||||||
|
int degrees;
|
||||||
size_t start = rectString.find(_("<mse-crop-data>"));
|
size_t start = rectString.find(_("<mse-crop-data>"));
|
||||||
if (start == String::npos) return rectString;
|
if (start == String::npos) return rectString;
|
||||||
size_t end = 0;
|
size_t end = 0;
|
||||||
@@ -112,70 +110,67 @@ inline static String transformAllEncodedRects(const String& rectString, RectTran
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : File to UTF8 Encoding
|
// ----------------------------------------------------------------------------- : File to UTF8 Encoding
|
||||||
|
|
||||||
inline static const char Base64Alphabet[] =
|
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
||||||
"abcdefghijklmnopqrstuvwxyz"
|
|
||||||
"0123456789+/";
|
|
||||||
|
|
||||||
inline static const std::vector<int> Base64ReverseAlphabet = [] {
|
|
||||||
std::vector<int> table(256, -1);
|
|
||||||
for (int i = 0; i < 64; i++) table[(uint8_t)Base64Alphabet[i]] = i;
|
|
||||||
return table;
|
|
||||||
}();
|
|
||||||
|
|
||||||
/// Encode a file in a string
|
/// Encode a file in a string
|
||||||
inline static std::string fileToUTF8(const std::string& filepath) {
|
inline static std::string fileToUTF8(const std::string& filepath) {
|
||||||
// Load file
|
// File to char
|
||||||
std::ifstream file(filepath, std::ios::binary);
|
std::ifstream file(filepath, std::ios::binary);
|
||||||
if (!file) {
|
file.unsetf(std::ios::skipws);
|
||||||
queue_message(MESSAGE_WARNING, _("Could not find file: ") + String(filepath));
|
std::vector<unsigned char> buffer = std::vector<unsigned char>(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
|
||||||
|
int size = buffer.size();
|
||||||
|
if (size < 2) {
|
||||||
|
queue_message(MESSAGE_WARNING, _("File too small to encode"));
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
size_t size = std::filesystem::file_size(filepath);
|
// All bytes that have a highest bit of 0 are valid UTF8 characters, so:
|
||||||
std::vector<uint8_t> data(size);
|
// Reset the highest bit of each byte, store these bits in additional bytes at the end
|
||||||
file.read(reinterpret_cast<char*>(data.data()), size);
|
const unsigned char highest_bit = 1 << 7;
|
||||||
// Base64 encode
|
unsigned char added_byte = 0;
|
||||||
std::string out;
|
for (int i = 0, b = 0 ; i < size ; ++i, ++b) {
|
||||||
out.reserve(((size + 2) / 3) * 4);
|
if (b == 7) { // Never set the highest bit of the added byte
|
||||||
int val = 0;
|
buffer.push_back(added_byte);
|
||||||
int valb = -6;
|
b = 0;
|
||||||
for (uint8_t c : data) {
|
}
|
||||||
val = (val << 8) | c;
|
unsigned char bit = 1 << b;
|
||||||
valb += 8;
|
if ((buffer[i] & highest_bit) != 0) { // The highest bit of the buffer is set
|
||||||
while (valb >= 0) {
|
buffer[i] &= ~highest_bit; // Reset the highest bit of the buffer
|
||||||
out.push_back(Base64Alphabet[(val >> valb) & 0x3F]);
|
added_byte |= bit; // Set the bit of the added byte
|
||||||
valb -= 6;
|
} else {
|
||||||
|
added_byte &= ~bit; // Reset the bit of the added byte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (valb > -6) {
|
buffer.push_back(added_byte);
|
||||||
out.push_back(Base64Alphabet[((val << 8) >> (valb + 8)) & 0x3F]);
|
// Char to string
|
||||||
}
|
return std::string(buffer.begin(), buffer.end());
|
||||||
// Pad
|
|
||||||
while (out.size() % 4) {
|
|
||||||
out.push_back('=');
|
|
||||||
}
|
|
||||||
return out;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retreive a file encoded in a string, return true if successful
|
/// Retreive a file encoded in a string, return true if successful
|
||||||
inline static bool UTF8ToFile(const std::string& filepath, std::string& data) {
|
inline static bool UTF8ToFile(const std::string& filepath, std::string& string) {
|
||||||
// Base64 decode
|
// String to char
|
||||||
std::string out;
|
std::vector<unsigned char> buffer(string.begin(), string.end());
|
||||||
out.reserve(data.size() * 3 / 4);
|
int size = buffer.size();
|
||||||
int val = 0;
|
if (size < 2) {
|
||||||
int valb = -8;
|
queue_message(MESSAGE_WARNING, _("File too small to decode"));
|
||||||
for (uint8_t c : data) {
|
return false;
|
||||||
if (c == '=') break; // padding, we're done
|
}
|
||||||
val = (val << 6) | Base64ReverseAlphabet[c];
|
// Restore the highest bit of each byte
|
||||||
valb += 6;
|
size = (size * 7) / 8;
|
||||||
if (valb >= 0) {
|
const unsigned char highest_bit = 1 << 7;
|
||||||
out.push_back(static_cast<char>((val >> valb) & 0xFF));
|
unsigned char added_byte = buffer[size];
|
||||||
valb -= 8;
|
for (int i = 0, j = size, b = 0 ; i < size ; ++i, ++b) {
|
||||||
|
if (b == 7) {
|
||||||
|
++j;
|
||||||
|
added_byte = buffer[j];
|
||||||
|
b = 0;
|
||||||
|
}
|
||||||
|
unsigned char bit = 1 << b;
|
||||||
|
if ((added_byte & bit) != 0) { // The bit of the added byte is set
|
||||||
|
buffer[i] |= highest_bit; // Set the highest bit of the buffer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Save file
|
buffer.resize(size);
|
||||||
std::ofstream file(filepath, std::ios::binary);
|
// Char to file
|
||||||
file.write(out.data(), out.size());
|
std::ofstream file(filepath, std::ios::out|std::ios::binary);
|
||||||
|
std::copy(buffer.cbegin(), buffer.cend(), std::ostream_iterator<unsigned char>(file));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,21 +184,22 @@ inline static std::string encodeImageInString(const Image& img) {
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retreive an image encoded in a string, return true if "<mse-image-data>" was found
|
/// Retreive an image encoded in a string
|
||||||
inline static bool decodeImageFromString(const String& string, Image& img_out) {
|
inline static Image decodeImageFromString(const String& string) {
|
||||||
|
Image img;
|
||||||
size_t first = string.find(_("<mse-image-data>"));
|
size_t first = string.find(_("<mse-image-data>"));
|
||||||
if (first == String::npos) return false;
|
if (first == String::npos) return img;
|
||||||
size_t last = string.find(_("</mse-image-data>"), first + 16);
|
size_t last = string.find(_("</mse-image-data>"), first + 16);
|
||||||
if (last == String::npos) return true;
|
if (last == String::npos) return img;
|
||||||
std::string s = string.substr(first + 16, last - (first + 16)).ToStdString();
|
std::string s = string.substr(first + 16, last - (first + 16)).ToStdString();
|
||||||
if (s.empty()) return true;
|
if (s.empty()) return img;
|
||||||
|
|
||||||
const std::string& temppath = (wxFileName::CreateTempFileName(_("mse")) + _(".png")).ToStdString();
|
const std::string& temppath = (wxFileName::CreateTempFileName(_("mse")) + _(".png")).ToStdString();
|
||||||
UTF8ToFile(temppath, s);
|
UTF8ToFile(temppath, s);
|
||||||
img_out.LoadFile(temppath, wxBITMAP_TYPE_PNG);
|
img.LoadFile(temppath, wxBITMAP_TYPE_PNG);
|
||||||
wxRemoveFile(temppath);
|
wxRemoveFile(temppath);
|
||||||
wxRemoveFile(temppath.substr(0, temppath.size() - 4));
|
wxRemoveFile(temppath.substr(0, temppath.size() - 4));
|
||||||
return true;
|
return img;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Metadata manipulation
|
// ----------------------------------------------------------------------------- : Metadata manipulation
|
||||||
|
|||||||
+3
-8
@@ -16,7 +16,6 @@
|
|||||||
#include <data/pack.hpp>
|
#include <data/pack.hpp>
|
||||||
#include <data/word_list.hpp>
|
#include <data/word_list.hpp>
|
||||||
#include <data/add_cards_script.hpp>
|
#include <data/add_cards_script.hpp>
|
||||||
#include <data/update_cards_script.hpp>
|
|
||||||
#include <util/io/package_manager.hpp>
|
#include <util/io/package_manager.hpp>
|
||||||
#include <script/script.hpp>
|
#include <script/script.hpp>
|
||||||
|
|
||||||
@@ -56,6 +55,7 @@ IMPLEMENT_REFLECTION(Game) {
|
|||||||
REFLECT_NO_SCRIPT(json_paths);
|
REFLECT_NO_SCRIPT(json_paths);
|
||||||
REFLECT_NO_SCRIPT(statistics_dimensions);
|
REFLECT_NO_SCRIPT(statistics_dimensions);
|
||||||
REFLECT_NO_SCRIPT(statistics_categories);
|
REFLECT_NO_SCRIPT(statistics_categories);
|
||||||
|
REFLECT_COMPAT(<308, "pack_item", pack_types);
|
||||||
REFLECT_NO_SCRIPT(pack_types);
|
REFLECT_NO_SCRIPT(pack_types);
|
||||||
REFLECT_NO_SCRIPT(keyword_match_script);
|
REFLECT_NO_SCRIPT(keyword_match_script);
|
||||||
REFLECT(has_keywords);
|
REFLECT(has_keywords);
|
||||||
@@ -63,8 +63,7 @@ IMPLEMENT_REFLECTION(Game) {
|
|||||||
REFLECT(keyword_parameter_types);
|
REFLECT(keyword_parameter_types);
|
||||||
REFLECT_NO_SCRIPT(keywords);
|
REFLECT_NO_SCRIPT(keywords);
|
||||||
REFLECT_NO_SCRIPT(word_lists);
|
REFLECT_NO_SCRIPT(word_lists);
|
||||||
REFLECT_NO_SCRIPT(add_cards_scripts);
|
REFLECT_NO_SCRIPT(add_cards_scripts);
|
||||||
REFLECT_NO_SCRIPT(update_cards_scripts);
|
|
||||||
REFLECT_NO_SCRIPT(auto_replaces);
|
REFLECT_NO_SCRIPT(auto_replaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,11 +205,7 @@ void Game::validate(Version v) {
|
|||||||
}
|
}
|
||||||
card_links_alt_names.emplace(linked_tr, linked_default);
|
card_links_alt_names.emplace(linked_tr, linked_default);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// sort the update_cards_scripts from oldest to newest
|
|
||||||
std::sort(update_cards_scripts.begin(), update_cards_scripts.end(), [](const auto& a, const auto& b) {
|
|
||||||
return *a < *b;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Game::initCardListColorScript() {
|
void Game::initCardListColorScript() {
|
||||||
|
|||||||
+21
-23
@@ -26,7 +26,6 @@ DECLARE_POINTER_TYPE(KeywordMode);
|
|||||||
DECLARE_POINTER_TYPE(Keyword);
|
DECLARE_POINTER_TYPE(Keyword);
|
||||||
DECLARE_POINTER_TYPE(WordList);
|
DECLARE_POINTER_TYPE(WordList);
|
||||||
DECLARE_POINTER_TYPE(AddCardsScript);
|
DECLARE_POINTER_TYPE(AddCardsScript);
|
||||||
DECLARE_POINTER_TYPE(UpdateCardsScript);
|
|
||||||
DECLARE_POINTER_TYPE(AutoReplace);
|
DECLARE_POINTER_TYPE(AutoReplace);
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Game
|
// ----------------------------------------------------------------------------- : Game
|
||||||
@@ -39,28 +38,27 @@ class Game : public Packaged {
|
|||||||
public:
|
public:
|
||||||
Game();
|
Game();
|
||||||
|
|
||||||
OptionalScript init_script; ///< Script of variables available to other scripts in this game
|
OptionalScript init_script; ///< Script of variables available to other scripts in this game
|
||||||
vector<FieldP> set_fields; ///< Fields for set information
|
vector<FieldP> set_fields; ///< Fields for set information
|
||||||
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
IndexMap<FieldP,StyleP> default_set_style; ///< Default style for the set fields, because it is often the same
|
||||||
vector<FieldP> card_fields; ///< Fields on each card
|
vector<FieldP> card_fields; ///< Fields on each card
|
||||||
vector<CardLinkP> card_links; ///< Possible links between cards
|
vector<CardLinkP> card_links; ///< Possible links between cards
|
||||||
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
OptionalScript card_list_color_script; ///< Script that determines the color of items in the card list
|
||||||
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
OptionalScript import_script; ///< Script applied as the last step of the new_card function
|
||||||
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
vector<String> json_paths; ///< Paths inside JSON files to find the card array
|
||||||
vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions
|
vector<StatsDimensionP> statistics_dimensions; ///< (Additional) statistics dimensions
|
||||||
vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories
|
vector<StatsCategoryP> statistics_categories; ///< (Additional) statistics categories
|
||||||
vector<PackTypeP> pack_types; ///< Types of random card packs to generate
|
vector<PackTypeP> pack_types; ///< Types of random card packs to generate
|
||||||
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
vector<WordListP> word_lists; ///< Word lists for editing with a drop down list
|
||||||
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
vector<AddCardsScriptP> add_cards_scripts; ///< Scripts for adding multiple cards to the set
|
||||||
vector<UpdateCardsScriptP> update_cards_scripts; ///< Scripts for updating cards made with an earlier version of this game
|
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
||||||
vector<AutoReplaceP> auto_replaces; ///< Things to autoreplace in textboxes
|
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
||||||
map<String,String> card_fields_alt_names; ///< Other names that fields might go by, for example in CSV files
|
map<String,String> card_links_alt_names; ///< Localized names that card links go by
|
||||||
map<String,String> card_links_alt_names; ///< Localized names that card links go by
|
bool has_keywords; ///< Does this game use keywords?
|
||||||
bool has_keywords; ///< Does this game use keywords?
|
OptionalScript keyword_match_script; ///< For the keyword editor
|
||||||
OptionalScript keyword_match_script; ///< For the keyword editor
|
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
||||||
vector<KeywordParamP> keyword_parameter_types;///< Types of keyword parameters
|
vector<KeywordModeP> keyword_modes; ///< Modes of keywords
|
||||||
vector<KeywordModeP> keyword_modes; ///< Modes of keywords
|
vector<KeywordP> keywords; ///< Keywords for use in text
|
||||||
vector<KeywordP> keywords; ///< Keywords for use in text
|
|
||||||
|
|
||||||
Dependencies dependent_scripts_cards; ///< scripts that depend on the card list
|
Dependencies dependent_scripts_cards; ///< scripts that depend on the card list
|
||||||
Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords
|
Dependencies dependent_scripts_keywords; ///< scripts that depend on the keywords
|
||||||
|
|||||||
@@ -85,6 +85,7 @@ bool Keyword::contains(QuickFilterPart const& query) const {
|
|||||||
|
|
||||||
IMPLEMENT_REFLECTION(Keyword) {
|
IMPLEMENT_REFLECTION(Keyword) {
|
||||||
REFLECT(keyword);
|
REFLECT(keyword);
|
||||||
|
if (handler.formatVersion() < 301) read_compat(handler, this);
|
||||||
REFLECT(match);
|
REFLECT(match);
|
||||||
REFLECT(reminder);
|
REFLECT(reminder);
|
||||||
REFLECT(rules);
|
REFLECT(rules);
|
||||||
|
|||||||
+9
-82
@@ -14,7 +14,6 @@
|
|||||||
#include <data/keyword.hpp>
|
#include <data/keyword.hpp>
|
||||||
#include <data/pack.hpp>
|
#include <data/pack.hpp>
|
||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
#include <data/update_cards_script.hpp>
|
|
||||||
#include <data/field/text.hpp> // for 0.2.7 fix
|
#include <data/field/text.hpp> // for 0.2.7 fix
|
||||||
#include <data/field/information.hpp>
|
#include <data/field/information.hpp>
|
||||||
#include <data/field/image.hpp>
|
#include <data/field/image.hpp>
|
||||||
@@ -23,7 +22,6 @@
|
|||||||
#include <util/tagged_string.hpp> // for 0.2.7 fix
|
#include <util/tagged_string.hpp> // for 0.2.7 fix
|
||||||
#include <util/order_cache.hpp>
|
#include <util/order_cache.hpp>
|
||||||
#include <util/delayed_index_maps.hpp>
|
#include <util/delayed_index_maps.hpp>
|
||||||
#include <util/uid.hpp>
|
|
||||||
#include <script/script_manager.hpp>
|
#include <script/script_manager.hpp>
|
||||||
#include <script/profiler.hpp>
|
#include <script/profiler.hpp>
|
||||||
#include <wx/sstream.h>
|
#include <wx/sstream.h>
|
||||||
@@ -69,16 +67,6 @@ void Set::updateStyles(const CardP& card, bool only_content_dependent) {
|
|||||||
void Set::updateDelayed() {
|
void Set::updateDelayed() {
|
||||||
script_manager->updateDelayed();
|
script_manager->updateDelayed();
|
||||||
}
|
}
|
||||||
void Set::buildUIDMap() {
|
|
||||||
card_uids.clear();
|
|
||||||
FOR_EACH(c, cards) {
|
|
||||||
while (card_uids.find(c->uid) != card_uids.end()) {
|
|
||||||
queue_message(MESSAGE_WARNING, _("Multiple cards found with same uid:\n") + c->identification() + _("\n") + card_uids[c->uid]->identification() + _("\nPlease notify someone on the Discord server."));
|
|
||||||
c->uid = generate_uid();
|
|
||||||
}
|
|
||||||
card_uids[c->uid] = c;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Context& Set::getContextForThumbnails() {
|
Context& Set::getContextForThumbnails() {
|
||||||
assert(!wxThread::IsMain());
|
assert(!wxThread::IsMain());
|
||||||
@@ -173,7 +161,7 @@ void fix_value_207(const ValueP& value) {
|
|||||||
|
|
||||||
void Set::validate(Version file_app_version) {
|
void Set::validate(Version file_app_version) {
|
||||||
Packaged::validate(file_app_version);
|
Packaged::validate(file_app_version);
|
||||||
// are the game and stylesheet defined?
|
// are the
|
||||||
if (!game) {
|
if (!game) {
|
||||||
throw Error(_ERROR_1_("no game specified",_TYPE_("set")));
|
throw Error(_ERROR_1_("no game specified",_TYPE_("set")));
|
||||||
}
|
}
|
||||||
@@ -184,9 +172,7 @@ void Set::validate(Version file_app_version) {
|
|||||||
if (stylesheet->game != game) {
|
if (stylesheet->game != game) {
|
||||||
throw Error(_ERROR_("stylesheet and set refer to different game"));
|
throw Error(_ERROR_("stylesheet and set refer to different game"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// We can probably retire this
|
|
||||||
/*
|
|
||||||
// This is our chance to fix version incompatabilities
|
// This is our chance to fix version incompatabilities
|
||||||
if (file_app_version < 207) {
|
if (file_app_version < 207) {
|
||||||
// Since 0.2.7 we use </tag> style close tags, in older versions it was </>
|
// Since 0.2.7 we use </tag> style close tags, in older versions it was </>
|
||||||
@@ -195,65 +181,14 @@ void Set::validate(Version file_app_version) {
|
|||||||
FOR_EACH(v, c->data) fix_value_207(v);
|
FOR_EACH(v, c->data) fix_value_207(v);
|
||||||
}
|
}
|
||||||
FOR_EACH(v, data) fix_value_207(v);
|
FOR_EACH(v, data) fix_value_207(v);
|
||||||
FOR_EACH(s, styleData) {
|
/* FOR_EACH(s, styleData) {
|
||||||
FOR_EACH(v, s.second->data) fix_value_207(v);
|
FOR_EACH(v, s.second->data) fix_value_207(v);
|
||||||
}
|
}
|
||||||
}
|
*/ }
|
||||||
*/
|
|
||||||
|
|
||||||
// we want at least one card
|
// we want at least one card
|
||||||
if (cards.empty()) cards.push_back(make_intrusive<Card>(*game));
|
if (cards.empty()) cards.push_back(make_intrusive<Card>(*game));
|
||||||
// update scripts
|
// update scripts
|
||||||
script_manager->updateAll();
|
script_manager->updateAll();
|
||||||
// build uid map
|
|
||||||
buildUIDMap();
|
|
||||||
// update_cards_scripts
|
|
||||||
// first apply all the stylesheet scripts that are older than the first game script
|
|
||||||
// then apply the first game script
|
|
||||||
// then apply all the stylesheet scripts that are older than the second game script
|
|
||||||
// then apply the second game script, etc...
|
|
||||||
Version previous_cutoff = Version();
|
|
||||||
Version current_cutoff = Version();
|
|
||||||
for (size_t g = 0; g < game->update_cards_scripts.size() + 1; ++g) {
|
|
||||||
bool last_iteration = g == game->update_cards_scripts.size();
|
|
||||||
UpdateCardsScriptP game_script = last_iteration ? nullptr : game->update_cards_scripts[g];
|
|
||||||
previous_cutoff = current_cutoff;
|
|
||||||
current_cutoff = last_iteration ? current_cutoff : game_script->before_version;
|
|
||||||
// Apply stylesheet scripts that are older than the current game script
|
|
||||||
for (size_t i = 0; i < cards.size(); ++i) {
|
|
||||||
CardP& card = cards[i];
|
|
||||||
StyleSheetP stylesheet = card->stylesheet ? card->stylesheet : stylesheetForP(card);
|
|
||||||
Version stylesheet_version = card->stylesheet_version.isZero() ? this->stylesheet_version : card->stylesheet_version;
|
|
||||||
for (size_t j = 0; j < stylesheet->update_cards_scripts.size(); ++j) {
|
|
||||||
UpdateCardsScriptP& script = stylesheet->update_cards_scripts[j];
|
|
||||||
if (script->before_version >= current_cutoff && !last_iteration) continue;
|
|
||||||
if (script->before_version < previous_cutoff) continue;
|
|
||||||
if (stylesheet_version >= script->before_version) continue;
|
|
||||||
vector<CardP> new_cards = script->perform(*this, card);
|
|
||||||
if (!new_cards.empty()) {
|
|
||||||
FOR_EACH(new_card, new_cards) {
|
|
||||||
// Initialize the stylesheet_version if it wasn't defined, to prevent this script from applying again
|
|
||||||
if (stylesheet == stylesheetForP(new_card) && new_card->stylesheet_version < script->before_version) {
|
|
||||||
new_card->stylesheet_version = script->before_version;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
--i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Apply current game script
|
|
||||||
if (last_iteration || game_version >= current_cutoff) continue;
|
|
||||||
size_t size = cards.size();
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
CardP& card = cards[i];
|
|
||||||
vector<CardP> new_cards = game_script->perform(*this, card);
|
|
||||||
if (!new_cards.empty()) {
|
|
||||||
--i;
|
|
||||||
--size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reflect_version_check(Reader& handler, const Char* key, intrusive_ptr<Packaged> const& package) {
|
void reflect_version_check(Reader& handler, const Char* key, intrusive_ptr<Packaged> const& package) {
|
||||||
@@ -277,23 +212,15 @@ IMPLEMENT_REFLECTION(Set) {
|
|||||||
REFLECT_IF_READING {
|
REFLECT_IF_READING {
|
||||||
data.init(game->set_fields);
|
data.init(game->set_fields);
|
||||||
}
|
}
|
||||||
if (Handler::isReading) {
|
reflect_version_check(handler, _("game_version"), game);
|
||||||
REFLECT_NO_SCRIPT(game_version);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
reflect_version_check(handler, _("game_version"), game);
|
|
||||||
}
|
|
||||||
WITH_DYNAMIC_ARG(game_for_reading, game.get());
|
WITH_DYNAMIC_ARG(game_for_reading, game.get());
|
||||||
REFLECT(stylesheet);
|
REFLECT(stylesheet);
|
||||||
if (Handler::isReading) {
|
REFLECT_COMPAT(<300, "style", stylesheet);
|
||||||
REFLECT_NO_SCRIPT(stylesheet_version);
|
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
||||||
}
|
|
||||||
else {
|
|
||||||
reflect_version_check(handler, _("stylesheet_version"), stylesheet);
|
|
||||||
}
|
|
||||||
WITH_DYNAMIC_ARG(stylesheet_for_reading, stylesheet.get());
|
WITH_DYNAMIC_ARG(stylesheet_for_reading, stylesheet.get());
|
||||||
REFLECT_N("set_info", data);
|
REFLECT_N("set_info", data);
|
||||||
if (stylesheet) {
|
if (stylesheet) {
|
||||||
|
REFLECT_COMPAT(<300, "extra_set_info", styling_data);
|
||||||
REFLECT_N("styling", styling_data);
|
REFLECT_N("styling", styling_data);
|
||||||
}
|
}
|
||||||
// Experimental: save each card to a different file
|
// Experimental: save each card to a different file
|
||||||
|
|||||||
+11
-18
@@ -45,27 +45,22 @@ public:
|
|||||||
Set(const StyleSheetP& stylesheet);
|
Set(const StyleSheetP& stylesheet);
|
||||||
~Set();
|
~Set();
|
||||||
|
|
||||||
GameP game; ///< The game this set uses
|
GameP game; ///< The game this set uses
|
||||||
StyleSheetP stylesheet; ///< The default stylesheet
|
StyleSheetP stylesheet; ///< The default stylesheet
|
||||||
/// The values on the fields of the set
|
/// The values on the fields of the set
|
||||||
/** The indices should correspond to the set_fields in the Game */
|
/** The indices should correspond to the set_fields in the Game */
|
||||||
IndexMap<FieldP, ValueP> data;
|
IndexMap<FieldP, ValueP> data;
|
||||||
/// Extra values for specific stylesheets, indexed by stylesheet name
|
/// Extra values for specific stylesheets, indexed by stylesheet name
|
||||||
DelayedIndexMaps<FieldP,ValueP> styling_data;
|
DelayedIndexMaps<FieldP,ValueP> styling_data;
|
||||||
vector<CardP> cards; ///< The cards in the set
|
vector<CardP> cards; ///< The cards in the set
|
||||||
unordered_map<String, CardP> card_uids; ///< The uids of the cards in the set
|
vector<KeywordP> keywords; ///< Additional keywords used in this set
|
||||||
vector<KeywordP> keywords; ///< Additional keywords used in this set
|
vector<PackTypeP> pack_types; ///< Additional/replacement pack types
|
||||||
vector<PackTypeP> pack_types; ///< Additional/replacement pack types
|
String apprentice_code; ///< Code to use for apprentice (magic only)
|
||||||
String apprentice_code; ///< Code to use for apprentice (magic only)
|
|
||||||
|
|
||||||
ActionStack actions; ///< Actions performed on this set and the cards in it
|
|
||||||
KeywordDatabase keyword_db; ///< Database for matching keywords, must be cleared when keywords change
|
|
||||||
VCSP vcs; ///< The version control system to use
|
|
||||||
/// What version of the game was this set using when it was last saved?
|
|
||||||
Version game_version;
|
|
||||||
/// What version of the default stylesheet was this set using when it was last saved?
|
|
||||||
Version stylesheet_version;
|
|
||||||
|
|
||||||
|
ActionStack actions; ///< Actions performed on this set and the cards in it
|
||||||
|
KeywordDatabase keyword_db; ///< Database for matching keywords, must be cleared when keywords change
|
||||||
|
VCSP vcs; ///< The version control system to use
|
||||||
|
|
||||||
/// A context for performing scripts
|
/// A context for performing scripts
|
||||||
/** Should only be used from the main thread! */
|
/** Should only be used from the main thread! */
|
||||||
Context& getContext();
|
Context& getContext();
|
||||||
@@ -76,8 +71,6 @@ public:
|
|||||||
void updateStyles(const CardP& card, bool only_content_dependent);
|
void updateStyles(const CardP& card, bool only_content_dependent);
|
||||||
/// Update scripts that were delayed
|
/// Update scripts that were delayed
|
||||||
void updateDelayed();
|
void updateDelayed();
|
||||||
/// Update uid map
|
|
||||||
void buildUIDMap();
|
|
||||||
/// A context for performing scripts
|
/// A context for performing scripts
|
||||||
/** Should only be used from the thumbnail thread! */
|
/** Should only be used from the thumbnail thread! */
|
||||||
Context& getContextForThumbnails();
|
Context& getContextForThumbnails();
|
||||||
|
|||||||
@@ -10,7 +10,6 @@
|
|||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/game.hpp>
|
#include <data/game.hpp>
|
||||||
#include <data/field.hpp>
|
#include <data/field.hpp>
|
||||||
#include <data/update_cards_script.hpp>
|
|
||||||
#include <util/io/package_manager.hpp>
|
#include <util/io/package_manager.hpp>
|
||||||
#include <gui/new_window.hpp> // for selecting stylesheets on load error
|
#include <gui/new_window.hpp> // for selecting stylesheets on load error
|
||||||
|
|
||||||
@@ -76,11 +75,7 @@ void StyleSheet::validate(Version ver) {
|
|||||||
throw Error(_ERROR_1_("no game specified",_TYPE_("stylesheet")));
|
throw Error(_ERROR_1_("no game specified",_TYPE_("stylesheet")));
|
||||||
}
|
}
|
||||||
// a stylesheet depends on the game it is made for
|
// a stylesheet depends on the game it is made for
|
||||||
requireDependency(game.get());
|
requireDependency(game.get());
|
||||||
// sort the update_cards_scripts from oldest to newest
|
|
||||||
std::sort(update_cards_scripts.begin(), update_cards_scripts.end(), [](const auto& a, const auto& b) {
|
|
||||||
return *a < *b;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -130,7 +125,6 @@ IMPLEMENT_REFLECTION(StyleSheet) {
|
|||||||
extra_card_style.init(extra_card_fields);
|
extra_card_style.init(extra_card_fields);
|
||||||
}
|
}
|
||||||
REFLECT(extra_card_style);
|
REFLECT(extra_card_style);
|
||||||
REFLECT_NO_SCRIPT(update_cards_scripts);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ DECLARE_POINTER_TYPE(StyleSheet);
|
|||||||
DECLARE_POINTER_TYPE(Field);
|
DECLARE_POINTER_TYPE(Field);
|
||||||
DECLARE_POINTER_TYPE(Style);
|
DECLARE_POINTER_TYPE(Style);
|
||||||
DECLARE_POINTER_TYPE(CardRegion);
|
DECLARE_POINTER_TYPE(CardRegion);
|
||||||
DECLARE_POINTER_TYPE(UpdateCardsScript);
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : StyleSheet
|
// ----------------------------------------------------------------------------- : StyleSheet
|
||||||
|
|
||||||
@@ -34,13 +33,12 @@ class StyleSheet : public Packaged {
|
|||||||
public:
|
public:
|
||||||
StyleSheet();
|
StyleSheet();
|
||||||
|
|
||||||
GameP game; ///< The game this stylesheet is made for
|
GameP game; ///< The game this stylesheet is made for
|
||||||
OptionalScript init_script; ///< Script of variables available to other scripts in this stylesheet
|
OptionalScript init_script; ///< Script of variables available to other scripts in this stylesheet
|
||||||
vector<UpdateCardsScriptP> update_cards_scripts; ///< Scripts for updating cards made with an earlier version of this stylesheet
|
double card_width; ///< The width of a card in pixels
|
||||||
double card_width; ///< The width of a card in pixels
|
double card_height; ///< The height of a card in pixels
|
||||||
double card_height; ///< The height of a card in pixels
|
double card_dpi; ///< The resolution of a card in dots per inch
|
||||||
double card_dpi; ///< The resolution of a card in dots per inch
|
Color card_background; ///< The background color of cards
|
||||||
Color card_background; ///< The background color of cards
|
|
||||||
vector<CardRegionP> card_regions;
|
vector<CardRegionP> card_regions;
|
||||||
/// The styling for card fields
|
/// The styling for card fields
|
||||||
/** The indices should correspond to the card_fields in the Game */
|
/** The indices should correspond to the card_fields in the Game */
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ IMPLEMENT_REFLECTION(SymbolInFont) {
|
|||||||
REFLECT(draw_text);
|
REFLECT(draw_text);
|
||||||
REFLECT(text_font);
|
REFLECT(text_font);
|
||||||
REFLECT(text_alignment);
|
REFLECT(text_alignment);
|
||||||
|
REFLECT_COMPAT(<300,"text_align",text_alignment);
|
||||||
REFLECT(text_margin_left);
|
REFLECT(text_margin_left);
|
||||||
REFLECT(text_margin_right);
|
REFLECT(text_margin_right);
|
||||||
REFLECT(text_margin_top);
|
REFLECT(text_margin_top);
|
||||||
|
|||||||
@@ -1,57 +0,0 @@
|
|||||||
//+----------------------------------------------------------------------------+
|
|
||||||
//| Description: Magic Set Editor - Program to make card games |
|
|
||||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
||||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
||||||
//+----------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Includes
|
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
|
||||||
#include <data/update_cards_script.hpp>
|
|
||||||
#include <data/action/set.hpp>
|
|
||||||
#include <data/set.hpp>
|
|
||||||
#include <data/card.hpp>
|
|
||||||
#include <data/stylesheet.hpp>
|
|
||||||
#include <data/action/value.hpp>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : UpdateCardsScript
|
|
||||||
|
|
||||||
IMPLEMENT_REFLECTION_NO_SCRIPT(UpdateCardsScript) {
|
|
||||||
REFLECT(before_version);
|
|
||||||
REFLECT(description);
|
|
||||||
REFLECT(enabled);
|
|
||||||
REFLECT(script);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void UpdateCardsScript::perform(Set& set, CardP& card, vector<CardP>& out) {
|
|
||||||
// Perform script
|
|
||||||
Context& ctx = set.getContext(card);
|
|
||||||
if (enabled.hasBeenRead()) {
|
|
||||||
enabled.update(ctx);
|
|
||||||
if (!enabled()) return;
|
|
||||||
}
|
|
||||||
ScriptValueP result = script.invoke(ctx);
|
|
||||||
// Add cards to out
|
|
||||||
ScriptValueP it = result->makeIterator();
|
|
||||||
while (ScriptValueP item = it->next()) {
|
|
||||||
CardP new_card = from_script<CardP>(item);
|
|
||||||
// is this a new card?
|
|
||||||
if (contains(set.cards,new_card) || contains(out,new_card)) {
|
|
||||||
// make copy
|
|
||||||
new_card = make_intrusive<Card>(&set, new_card);
|
|
||||||
}
|
|
||||||
out.push_back(new_card);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vector<CardP> UpdateCardsScript::perform(Set& set, CardP card) {
|
|
||||||
// Perform script
|
|
||||||
vector<CardP> cards;
|
|
||||||
perform(set, card, cards);
|
|
||||||
// Add to set
|
|
||||||
if (!cards.empty()) {
|
|
||||||
set.actions.addAction(make_unique<UpdateCardAction>(set, cards, vector<CardP>{card}), false);
|
|
||||||
}
|
|
||||||
return cards;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
//+----------------------------------------------------------------------------+
|
|
||||||
//| Description: Magic Set Editor - Program to make card games |
|
|
||||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
||||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
||||||
//+----------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Includes
|
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
|
||||||
#include <script/scriptable.hpp>
|
|
||||||
|
|
||||||
class Set;
|
|
||||||
DECLARE_POINTER_TYPE(Card);
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : UpdateCardsScript
|
|
||||||
|
|
||||||
/// A script to add one or more cards to a set
|
|
||||||
class UpdateCardsScript : public IntrusivePtrBase<UpdateCardsScript> {
|
|
||||||
public:
|
|
||||||
Version before_version;
|
|
||||||
String description;
|
|
||||||
Scriptable<bool> enabled;
|
|
||||||
OptionalScript script;
|
|
||||||
|
|
||||||
bool operator < (const UpdateCardsScript& other) const {
|
|
||||||
return before_version < other.before_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Perform the script; return the cards (if any)
|
|
||||||
void perform(Set& set, CardP& card, vector<CardP>& out);
|
|
||||||
/// Perform the script; add cards to the set
|
|
||||||
vector<CardP> perform(Set& set, CardP card); // don't use CardP& here, because set.cards may get reallocated which would invalidate the ref
|
|
||||||
|
|
||||||
DECLARE_REFLECTION();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
+17
-33
@@ -19,7 +19,7 @@ template <typename T> inline T sqr(T x) { return x * x; }
|
|||||||
void linear_blend(Image& img1, const Image& img2, double x1,double y1, double x2,double y2) {
|
void linear_blend(Image& img1, const Image& img2, double x1,double y1, double x2,double y2) {
|
||||||
int width = img1.GetWidth(), height = img1.GetHeight();
|
int width = img1.GetWidth(), height = img1.GetHeight();
|
||||||
if (img2.GetWidth() != width || img2.GetHeight() != height) {
|
if (img2.GetWidth() != width || img2.GetHeight() != height) {
|
||||||
throw Error(_ERROR_3_("blending different sizes", "linear_blend", String()<<width<<_("x")<<height, String()<<img2.GetWidth()<<_("x")<<img2.GetHeight()));
|
throw Error(_ERROR_1_("blending different sizes", "linear_blend"));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int fixed = 1<<16; // fixed point multiplier
|
const int fixed = 1<<16; // fixed point multiplier
|
||||||
@@ -82,10 +82,10 @@ void linear_blend(Image& img1, const Image& img2, double x1,double y1, double x2
|
|||||||
void mask_blend(Image& img1, const Image& img2, const Image& mask) {
|
void mask_blend(Image& img1, const Image& img2, const Image& mask) {
|
||||||
int width = img1.GetWidth(), height = img1.GetHeight();
|
int width = img1.GetWidth(), height = img1.GetHeight();
|
||||||
if (img2.GetWidth() != width || img2.GetHeight() != height) {
|
if (img2.GetWidth() != width || img2.GetHeight() != height) {
|
||||||
throw Error(_ERROR_3_("blending different sizes", "masked_blend", String()<<width<<_("x")<<height, String()<<img2.GetWidth()<<_("x")<<img2.GetHeight()));
|
throw Error(_("Images used for blending in masked_blend function must have the same size"));
|
||||||
}
|
}
|
||||||
if (mask.GetWidth() != width || mask.GetHeight() != height) {
|
if (mask.GetWidth() != width || mask.GetHeight() != height) {
|
||||||
throw Error(_ERROR_3_("blending different mask", "masked_blend", String()<<width<<_("x")<<height, String()<<mask.GetWidth()<<_("x")<<mask.GetHeight()));
|
throw Error(_("Mask used for blending in masked_blend function must have the same size as the images"));
|
||||||
}
|
}
|
||||||
|
|
||||||
UInt size = width * height;
|
UInt size = width * height;
|
||||||
@@ -124,49 +124,33 @@ void set_alpha(Image& img, const Image& img_alpha) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void set_alpha(Image& img, Byte* al, const wxSize& alpha_size) {
|
void set_alpha(Image& img, Byte* al, const wxSize& alpha_size) {
|
||||||
int width = img.GetWidth(), height = img.GetHeight();
|
if (img.GetWidth() != alpha_size.GetWidth() || img.GetHeight() != alpha_size.GetHeight()) {
|
||||||
if (width != alpha_size.GetWidth() || height != alpha_size.GetHeight()) {
|
throw Error(_("Image must have same size as mask"));
|
||||||
throw Error(_ERROR_3_("blending different mask", "set_alpha", String()<<width<<_("x")<<height, String()<<alpha_size.GetWidth()<<_("x")<<alpha_size.GetHeight()));
|
|
||||||
}
|
}
|
||||||
if (!img.HasAlpha()) {
|
if (!img.HasAlpha()) {
|
||||||
// copy
|
// copy
|
||||||
img.InitAlpha();
|
img.InitAlpha();
|
||||||
memcpy(img.GetAlpha(), al, width * height);
|
memcpy(img.GetAlpha(), al, img.GetWidth() * img.GetHeight());
|
||||||
} else{
|
} else{
|
||||||
// merge
|
// merge
|
||||||
Byte *im = img.GetAlpha();
|
Byte *im = img.GetAlpha();
|
||||||
size_t size = width * height;
|
size_t size = img.GetWidth() * img.GetHeight();
|
||||||
for (size_t i = 0 ; i < size ; ++i) {
|
for (size_t i = 0 ; i < size ; ++i) {
|
||||||
im[i] = (im[i] * al[i]) / 255;
|
im[i] = (im[i] * al[i]) / 255;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_alpha(Image& img, double alpha) {
|
void set_alpha(Image& img, double alpha) {
|
||||||
size_t size = img.GetWidth() * img.GetHeight();
|
Byte b_alpha = Byte(alpha * 255);
|
||||||
if (alpha <= 0.0) {
|
if (!img.HasAlpha()) {
|
||||||
if (!img.HasAlpha()) img.InitAlpha();
|
img.InitAlpha();
|
||||||
memset(img.GetAlpha(), Byte(0), size);
|
memset(img.GetAlpha(), b_alpha, img.GetWidth() * img.GetHeight());
|
||||||
}
|
} else {
|
||||||
else if (alpha > 1.0) {
|
Byte *im = img.GetAlpha();
|
||||||
if (!img.HasAlpha()) return;
|
size_t size = img.GetWidth() * img.GetHeight();
|
||||||
else {
|
for (size_t i = 0 ; i < size ; ++i) {
|
||||||
Byte *im = img.GetAlpha();
|
im[i] = (im[i] * b_alpha) / 255;
|
||||||
for (size_t i = 0 ; i < size ; ++i) {
|
|
||||||
im[i] = Byte(min(im[i] * alpha, 255.0));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
Byte b_alpha = Byte(alpha * 255);
|
|
||||||
if (!img.HasAlpha()) {
|
|
||||||
img.InitAlpha();
|
|
||||||
memset(img.GetAlpha(), b_alpha, size);
|
|
||||||
} else {
|
|
||||||
Byte *im = img.GetAlpha();
|
|
||||||
for (size_t i = 0 ; i < size ; ++i) {
|
|
||||||
im[i] = (im[i] * b_alpha) / 255;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -449,14 +449,13 @@ void combine_image_do(Image& a, Image b) {
|
|||||||
|
|
||||||
void combine_image(Image& a, const Image& b, ImageCombine combine) {
|
void combine_image(Image& a, const Image& b, ImageCombine combine) {
|
||||||
// Images must have same size
|
// Images must have same size
|
||||||
int width = a.GetWidth(), height = a.GetHeight();
|
if (a.GetWidth() != b.GetWidth() || a.GetHeight() != b.GetHeight()) {
|
||||||
if (b.GetWidth() != width || b.GetHeight() != height) {
|
throw Error(_ERROR_1_("blending different sizes", "combine_blend"));
|
||||||
throw Error(_ERROR_3_("blending different sizes", "combine_blend", String()<<width<<_("x")<<height, String()<<b.GetWidth()<<_("x")<<b.GetHeight()));
|
|
||||||
}
|
}
|
||||||
// Copy alpha channel?
|
// Copy alpha channel?
|
||||||
if (b.HasAlpha()) {
|
if (b.HasAlpha()) {
|
||||||
if (!a.HasAlpha()) a.InitAlpha();
|
if (!a.HasAlpha()) a.InitAlpha();
|
||||||
memcpy(a.GetAlpha(), b.GetAlpha(), width * height);
|
memcpy(a.GetAlpha(), b.GetAlpha(), a.GetWidth() * a.GetHeight());
|
||||||
}
|
}
|
||||||
// Combine image data, by dispatching to combineImageDo
|
// Combine image data, by dispatching to combineImageDo
|
||||||
switch(combine) {
|
switch(combine) {
|
||||||
|
|||||||
+35
-55
@@ -783,57 +783,32 @@ bool SetMetadataImage::operator == (const GeneratedImage& that) const {
|
|||||||
&& metadata == that2->metadata;
|
&& metadata == that2->metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ScriptedImage
|
|
||||||
|
|
||||||
ScriptedImage::ScriptedImage(Set* set, const GeneratedImageP& image) {
|
|
||||||
// get the image
|
|
||||||
Image img = image->generate(GeneratedImage::Options(0, 0, set, set));
|
|
||||||
|
|
||||||
// add the file to the set
|
|
||||||
LocalFileName new_image_file = set->newFileName(_("scripted_image"), _(".png"));
|
|
||||||
savename = new_image_file.toStringForWriting();
|
|
||||||
loadpath = savename;
|
|
||||||
img.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
|
|
||||||
}
|
|
||||||
|
|
||||||
Image ScriptedImage::generate(const Options& opt) {
|
|
||||||
auto imageInputStream = opt.local_package->openIn(savename);
|
|
||||||
Image img(*imageInputStream, wxBITMAP_TYPE_PNG);
|
|
||||||
|
|
||||||
if (!img.IsOk()) throw ScriptError(_ERROR_1_("can't import image", loadpath));
|
|
||||||
|
|
||||||
return img;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ScriptedImage::operator == (const GeneratedImage& that) const {
|
|
||||||
const ScriptedImage* that2 = dynamic_cast<const ScriptedImage*>(&that);
|
|
||||||
return that2 && that2->loadpath == loadpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImportedImage
|
// ----------------------------------------------------------------------------- : ImportedImage
|
||||||
|
|
||||||
ImportedImage::ImportedImage(Set* set, const String& filepath) {
|
ImportedImage::ImportedImage(Set* set, const String& filepath)
|
||||||
// determine save name
|
{
|
||||||
loadpath = filepath;
|
loadpath = filepath;
|
||||||
savename = normalize_internal_filename(loadpath);
|
|
||||||
savename.Replace(":", "-");
|
// has the set already been saved at least once?
|
||||||
savename.Replace("/", "-");
|
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't import image without set", loadpath));
|
||||||
|
|
||||||
// does the file pointed to by filepath exist?
|
// does the file pointed to by filepath exist?
|
||||||
if (!wxFileName(loadpath, wxPATH_UNIX).FileExists()) {
|
if (!wxFileName(loadpath, wxPATH_UNIX).FileExists()) throw ScriptError(_ERROR_1_("import not found", loadpath));
|
||||||
if (set->contains(savename)) return;
|
|
||||||
else throw ScriptError(_ERROR_1_("import not found", loadpath));
|
|
||||||
}
|
|
||||||
|
|
||||||
// is the file an image?
|
// is the file an image?
|
||||||
Image img;
|
Image img;
|
||||||
img.LoadFile(loadpath);
|
img.LoadFile(loadpath);
|
||||||
if (!img.IsOk()) throw ScriptError(_ERROR_1_("import not image", loadpath));
|
if (!img.IsOk()) throw ScriptError(_ERROR_1_("import not image", loadpath));
|
||||||
|
|
||||||
// add the file to the set
|
// add the file to the set (or overwrite it if pre-existing), save set
|
||||||
LocalFileName new_image_file = set->newFileName(savename, _(".png"));
|
savename = normalize_internal_filename(loadpath + _(".png"));
|
||||||
savename = new_image_file.toStringForWriting();
|
savename.Replace(":", "-");
|
||||||
img.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
|
savename.Replace("/", "-");
|
||||||
|
auto outStream = set->openOut(savename);
|
||||||
|
img.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
|
||||||
|
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", loadpath));
|
||||||
|
outStream->Close();
|
||||||
|
set->save(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image ImportedImage::generate(const Options& opt) {
|
Image ImportedImage::generate(const Options& opt) {
|
||||||
@@ -852,27 +827,32 @@ bool ImportedImage::operator == (const GeneratedImage& that) const {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : DownloadedImage
|
// ----------------------------------------------------------------------------- : DownloadedImage
|
||||||
|
|
||||||
DownloadedImage::DownloadedImage(Set* set, const String& url) {
|
DownloadedImage::DownloadedImage(Set* set, const String& url)
|
||||||
// determine save name
|
{
|
||||||
loadpath = url;
|
loadpath = url;
|
||||||
savename = normalize_internal_filename(loadpath);
|
|
||||||
savename.Replace(":", "-");
|
// has the set already been saved at least once?
|
||||||
savename.Replace("/", "-");
|
if (set->needSaveAs()) throw ScriptError(_ERROR_1_("can't download image without set", loadpath));
|
||||||
|
|
||||||
// can we download the data?
|
// can we download the data?
|
||||||
WebRequestWindow wnd(loadpath);
|
WebRequestWindow wnd(loadpath);
|
||||||
if (wnd.ShowModal() != wxID_OK) {
|
if (wnd.ShowModal() != wxID_OK) throw ScriptError(_ERROR_1_("can't download image", loadpath));
|
||||||
if (set->contains(savename)) return;
|
|
||||||
else throw ScriptError(_ERROR_1_("can't download image", loadpath));
|
|
||||||
}
|
|
||||||
|
|
||||||
// is the data an image?
|
// is the data an image?
|
||||||
if (!wnd.content_type.StartsWith(_("image/"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
|
const String& content_type = wnd.out.GetContentType();
|
||||||
|
if (!content_type.StartsWith(_("image"))) throw ScriptError(_ERROR_1_("download not image", loadpath));
|
||||||
// add the file to the set
|
Image img(*wnd.out.GetStream());
|
||||||
LocalFileName new_image_file = set->newFileName(savename, _(".png"));
|
if (!img.IsOk()) throw ScriptError(_ERROR_("web request corrupted"));
|
||||||
savename = new_image_file.toStringForWriting();
|
|
||||||
wnd.image_out.SaveFile(set->nameOut(new_image_file), wxBITMAP_TYPE_PNG);
|
// add the file to the set (or overwrite it if pre-existing), save set
|
||||||
|
savename = normalize_internal_filename(loadpath + _(".png"));
|
||||||
|
savename.Replace(":", "-");
|
||||||
|
savename.Replace("/", "-");
|
||||||
|
auto outStream = set->openOut(savename);
|
||||||
|
img.SaveFile(*outStream, wxBITMAP_TYPE_PNG);
|
||||||
|
if (!outStream->IsOk()) throw ScriptError(_ERROR_1_("can't write image to set", loadpath));
|
||||||
|
outStream->Close();
|
||||||
|
set->save(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Image DownloadedImage::generate(const Options& opt) {
|
Image DownloadedImage::generate(const Options& opt) {
|
||||||
|
|||||||
@@ -522,16 +522,6 @@ protected:
|
|||||||
String savename;
|
String savename;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ScriptedImage
|
|
||||||
|
|
||||||
/// Load an image from a script
|
|
||||||
class ScriptedImage : public ExternalImage {
|
|
||||||
public:
|
|
||||||
ScriptedImage(Set* set, const GeneratedImageP& image);
|
|
||||||
Image generate(const Options&) override;
|
|
||||||
bool operator == (const GeneratedImage& that) const override;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : ImportedImage
|
// ----------------------------------------------------------------------------- : ImportedImage
|
||||||
|
|
||||||
/// Load an image from the filesystem
|
/// Load an image from the filesystem
|
||||||
|
|||||||
@@ -40,7 +40,8 @@ const char* MSE_AUTHORS[] = {
|
|||||||
"Olivier Bocksberger (G-e-n-e-v-e-n-s-i-S)",
|
"Olivier Bocksberger (G-e-n-e-v-e-n-s-i-S)",
|
||||||
"Brendan Hagan (haganbmj)",
|
"Brendan Hagan (haganbmj)",
|
||||||
"Thomas Tkacz (TomTkacz)",
|
"Thomas Tkacz (TomTkacz)",
|
||||||
"CaiCai (247321453)"
|
"CaiCai (247321453)",
|
||||||
|
"Amy Markey (amyinspace)"
|
||||||
};
|
};
|
||||||
|
|
||||||
void AboutWindow::draw(DC& dc) {
|
void AboutWindow::draw(DC& dc) {
|
||||||
|
|||||||
@@ -126,7 +126,11 @@ void CardLinkWindow::onOk(wxCommandEvent&) {
|
|||||||
linked_uids.push_back(linked_cards[i]->uid);
|
linked_uids.push_back(linked_cards[i]->uid);
|
||||||
}
|
}
|
||||||
// Find free links
|
// Find free links
|
||||||
vector<int> free_link_indexes = selected_card->findFreeLinks(linked_uids, set->card_uids);
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set->cards) {
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
|
vector<int> free_link_indexes = selected_card->findFreeLinks(linked_uids, all_existing_uids);
|
||||||
int free_link_count = 0;
|
int free_link_count = 0;
|
||||||
for (size_t i = 0; i < free_link_indexes.size(); ++i) {
|
for (size_t i = 0; i < free_link_indexes.size(); ++i) {
|
||||||
if (free_link_indexes[i] >= 0) free_link_count++;
|
if (free_link_indexes[i] >= 0) free_link_count++;
|
||||||
@@ -159,7 +163,7 @@ void CardLinkWindow::onOk(wxCommandEvent&) {
|
|||||||
// Find reciprocal free slots and make actions
|
// Find reciprocal free slots and make actions
|
||||||
String& selected_uid = selected_card->uid;
|
String& selected_uid = selected_card->uid;
|
||||||
for (size_t i = 0; i < linked_cards.size(); ++i) {
|
for (size_t i = 0; i < linked_cards.size(); ++i) {
|
||||||
int free_link_index = linked_cards[i]->findFreeLink(selected_uid, set->card_uids);
|
int free_link_index = linked_cards[i]->findFreeLink(selected_uid, all_existing_uids);
|
||||||
if (free_link_index >= 0) {
|
if (free_link_index >= 0) {
|
||||||
actions.push_back(make_intrusive<OneWayLinkCardsAction>(linked_cards[i], selected_uid, selected_relation_string, free_link_index));
|
actions.push_back(make_intrusive<OneWayLinkCardsAction>(linked_cards[i], selected_uid, selected_relation_string, free_link_index));
|
||||||
}
|
}
|
||||||
|
|||||||
+108
-212
@@ -165,8 +165,7 @@ bool CardListBase::doCopy() {
|
|||||||
if (cards_to_copy.empty()) return false;
|
if (cards_to_copy.empty()) return false;
|
||||||
// put on clipboard
|
// put on clipboard
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
|
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -192,8 +191,7 @@ bool CardListBase::doCopyCardAndLinkedCards() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
|
bool ok = wxTheClipboard->SetData(new CardsOnClipboard(set, _(""), cards_to_copy)); // ignore result
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -201,8 +199,7 @@ bool CardListBase::doCopyCardAndLinkedCards() {
|
|||||||
bool CardListBase::doPaste() {
|
bool CardListBase::doPaste() {
|
||||||
if (!canPaste()) return false;
|
if (!canPaste()) return false;
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
bool ok = wxTheClipboard->GetData(*drop_target->data_object);
|
bool ok = wxTheClipboard->GetData(*drop_target->data_object);
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
if (ok) return parseData(false);
|
if (ok) return parseData(false);
|
||||||
return false;
|
return false;
|
||||||
@@ -212,15 +209,9 @@ bool CardListBase::doDelete() {
|
|||||||
// cards to delete
|
// cards to delete
|
||||||
vector<CardP> cards_to_delete;
|
vector<CardP> cards_to_delete;
|
||||||
getSelection(cards_to_delete);
|
getSelection(cards_to_delete);
|
||||||
if (cards_to_delete.empty()) return false;
|
if (cards_to_delete.empty()) return false;
|
||||||
// if there is one double faced card, select the other face to make it clear it hasn't been deleted
|
|
||||||
CardP other_face = nullptr;
|
|
||||||
if (cards_to_delete.size() == 1) {
|
|
||||||
other_face = cards_to_delete[0]->getLinkedOtherFaceCard(*set);
|
|
||||||
}
|
|
||||||
// delete cards
|
// delete cards
|
||||||
set->actions.addAction(make_unique<AddCardAction>(REMOVE, *set, cards_to_delete));
|
set->actions.addAction(make_unique<AddCardAction>(REMOVE, *set, cards_to_delete));
|
||||||
if (other_face) setCard(other_face, true);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -251,65 +242,66 @@ bool CardListBase::doBulkModification() {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardListBase::parseImageMetadata(CardP& card, const Image& image) {
|
void CardListBase::parseImageMetadata(CardP& card, const Image& image)
|
||||||
|
{
|
||||||
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
||||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||||
if (value && !value->filename.empty()) {
|
if (value && !value->filename.empty()) {
|
||||||
RealRect rect(0.0, 0.0, 0.0, 0.0);
|
RealRect rect(0.0, 0.0, 0.0, 0.0);
|
||||||
int degrees = 0;
|
int degrees = 0;
|
||||||
if (decodeRectFromString(value->filename.toStringForKey(), rect, degrees)) {
|
decodeRectFromString(value->filename.toStringForKey(), rect, degrees);
|
||||||
rect = rect.intersect(RealRect(0.0, 0.0, image.GetWidth(), image.GetHeight()));
|
rect = rect.intersect(RealRect(0.0, 0.0, image.GetWidth(), image.GetHeight()));
|
||||||
if (rect.width > 0.0 && rect.height > 0.0) {
|
if (rect.width > 0.0 && rect.height > 0.0) {
|
||||||
Image img = image.GetSubImage(rect);
|
Image img = image.GetSubImage(rect);
|
||||||
img = rotate_image(img, deg_to_rad(360 - degrees));
|
img = rotate_image(img, deg_to_rad(360 - degrees));
|
||||||
LocalFileName filename = set->newFileName(_("cropped_image"), _(".png")); // a new unique name in the package
|
LocalFileName filename = set->newFileName("cropped_image", _(".png")); // a new unique name in the package
|
||||||
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
||||||
value->filename = filename;
|
value->filename = filename;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
value->filename = LocalFileName();
|
value->filename = LocalFileName();
|
||||||
//queue_message(MESSAGE_WARNING, _("failed to recover image crop for card '") + card->identification() + _("'"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardListBase::parseImageMetadata(CardP& card) {
|
void CardListBase::parseImageMetadata(CardP& card)
|
||||||
|
{
|
||||||
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
for (IndexMap<FieldP, ValueP>::iterator it = card->data.begin(); it != card->data.end(); it++) {
|
||||||
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
ImageValue* value = dynamic_cast<ImageValue*>(it->get());
|
||||||
if (value && !value->filename.empty()) {
|
if (value) {
|
||||||
Image img;
|
Image img = decodeImageFromString(value->filename.toStringForKey());
|
||||||
if (decodeImageFromString(value->filename.toStringForKey(), img)) {
|
if (img.IsOk()) {
|
||||||
if (img.IsOk()) {
|
LocalFileName filename = set->newFileName(_("decoded_image"), _(".png")); // a new unique name in the package
|
||||||
LocalFileName filename = set->newFileName(_("decoded_image"), _(".png")); // a new unique name in the package
|
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
||||||
img.SaveFile(set->nameOut(filename), wxBITMAP_TYPE_PNG);
|
value->filename = filename;
|
||||||
value->filename = filename;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
value->filename = LocalFileName();
|
|
||||||
//queue_message(MESSAGE_WARNING, _("failed to recover image encode for card '") + card->identification() + _("'"));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
|
bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
|
||||||
size_t j = out.size();
|
size_t j = out.size();
|
||||||
size_t pos = url.find("URL=");
|
size_t pos = url.find("URL=");
|
||||||
if (pos != std::string::npos) {
|
if (pos != std::string::npos) {
|
||||||
url = url.substr(pos+4);
|
url = url.substr(pos+4);
|
||||||
}
|
}
|
||||||
if (!url.StartsWith(_("http"))) return false;
|
if (!url.StartsWith(_("http"))) return false;
|
||||||
|
|
||||||
WebRequestWindow wnd(url);
|
WebRequestWindow wnd(url);
|
||||||
if (wnd.ShowModal() == wxID_OK) {
|
if (wnd.ShowModal() == wxID_OK) {
|
||||||
if (wnd.content_type.StartsWith(_("image/"))) {
|
const String& content_type = wnd.out.GetContentType();
|
||||||
parseImage(wnd.image_out, out);
|
if (content_type.StartsWith(_("image"))) {
|
||||||
|
Image img(*wnd.out.GetStream());
|
||||||
|
if (img.IsOk()) {
|
||||||
|
parseImage(img, out);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
queue_message(MESSAGE_ERROR, _ERROR_("web request corrupted"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (wnd.content_type.StartsWith(_("text/"))) {
|
else if (content_type.StartsWith(_("text"))) {
|
||||||
String text = String(wnd.text_out.data(), wnd.text_out.size());
|
String text = wnd.out.AsString();
|
||||||
parseText(text, out);
|
parseText(text, out);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -319,26 +311,19 @@ bool CardListBase::parseUrl(String& url, vector<CardP>& out) {
|
|||||||
return j < out.size();
|
return j < out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::parseFiles(wxArrayString& filenames, vector<CardP>& out) {
|
bool CardListBase::parseFiles(wxArrayString& filenames, vector<CardP>& out) {
|
||||||
size_t j = out.size();
|
size_t j = out.size();
|
||||||
for (size_t i = 0; i < filenames.size(); i++) {
|
for (size_t i = 0; i < filenames.size(); i++) {
|
||||||
if (wxImage::CanRead(filenames[i])) {
|
// if it's an image file, try to get meta_data
|
||||||
// if it's an image file, try to get meta_data
|
Image image_file;
|
||||||
Image image_file;
|
image_file.SetLoadFlags(image_file.GetLoadFlags() & ~wxImage::Load_Verbose);
|
||||||
image_file.SetLoadFlags(image_file.GetLoadFlags() & ~wxImage::Load_Verbose);
|
if (image_file.LoadFile(filenames[i])) {
|
||||||
if (image_file.LoadFile(filenames[i])) {
|
parseImage(image_file, out);
|
||||||
parseImage(image_file, out);
|
|
||||||
}
|
|
||||||
else queue_message(MESSAGE_ERROR, _ERROR_("can't load image"));
|
|
||||||
} else {
|
} else {
|
||||||
// if it's an url, request the data
|
// if it's an url, request the data
|
||||||
std::ifstream ifs(filenames[i].ToStdString());
|
std::ifstream ifs(filenames[i].ToStdString());
|
||||||
if (ifs.bad() || ifs.fail() || !ifs.good() || !ifs.is_open()) continue;
|
if (ifs.bad() || ifs.fail() || !ifs.good() || !ifs.is_open()) continue;
|
||||||
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
std::string content((std::istreambuf_iterator<char>(ifs)), (std::istreambuf_iterator<char>()));
|
||||||
bool looks_like_text = std::all_of(content.begin(), content.end(), [](char c) {
|
|
||||||
return isprint(c) || isspace(c);
|
|
||||||
});
|
|
||||||
if (!looks_like_text) continue;
|
|
||||||
wxString text(content);
|
wxString text(content);
|
||||||
if (!parseUrl(text, out)) parseText(text, out);
|
if (!parseUrl(text, out)) parseText(text, out);
|
||||||
}
|
}
|
||||||
@@ -346,7 +331,7 @@ bool CardListBase::parseFiles(wxArrayString& filenames, vector<CardP>& out) {
|
|||||||
return j < out.size();
|
return j < out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
|
bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
|
||||||
size_t j = out.size();
|
size_t j = out.size();
|
||||||
if (image.HasOption(wxIMAGE_OPTION_PNG_DESCRIPTION)) {
|
if (image.HasOption(wxIMAGE_OPTION_PNG_DESCRIPTION)) {
|
||||||
auto text = image.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION);
|
auto text = image.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION);
|
||||||
@@ -361,30 +346,26 @@ bool CardListBase::parseImage(Image& image, vector<CardP>& out) {
|
|||||||
return j < out.size();
|
return j < out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::parseText(String& text, vector<CardP>& out) {
|
bool CardListBase::parseText(String& text, vector<CardP>& out) {
|
||||||
if (text.size() == 0) {
|
size_t j = out.size();
|
||||||
return false;
|
if (size_t pos = text.find("<mse-card-data>") != wxString::npos) {
|
||||||
}
|
text = text.substr(pos + 14, text.find("</mse-card-data>") - pos - 14);
|
||||||
size_t j = out.size();
|
|
||||||
size_t pos = text.find("<mse-card-data>");
|
|
||||||
if (pos != wxString::npos) {
|
|
||||||
text = text.substr(pos + 15, text.find("</mse-card-data>") - pos - 15);
|
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ScriptValueP sv = json_to_mse(text, set.get());
|
ScriptValueP sv = json_to_mse(text, set.get());
|
||||||
if (sv->type() == SCRIPT_COLLECTION) {
|
if (sv->type() == SCRIPT_COLLECTION) {
|
||||||
if (ScriptCustomCollection* custom = dynamic_cast<ScriptCustomCollection*>(sv.get())) {
|
if (ScriptCustomCollection* custom = dynamic_cast<ScriptCustomCollection*>(sv.get())) {
|
||||||
for (size_t i = 0; i < custom->value.size(); i++) {
|
for (size_t i = 0; i < custom->value.size(); i++) {
|
||||||
if (ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(custom->value[i].get())) {
|
if (ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(custom->value[i].get())) {
|
||||||
out.push_back(c->getValue());
|
out.push_back(make_intrusive<Card>(*c->getValue()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(sv.get())) {
|
} else if (ScriptObject<CardP>* c = dynamic_cast<ScriptObject<CardP>*>(sv.get())) {
|
||||||
out.push_back(c->getValue());
|
out.push_back(make_intrusive<Card>(*c->getValue()));
|
||||||
}
|
}
|
||||||
} catch (...) {}
|
} catch (...) {}
|
||||||
|
|
||||||
// decode images to populate image fields
|
// decode images to populate image fields
|
||||||
for (int k = j; k < out.size(); k++) {
|
for (int k = j; k < out.size(); k++) {
|
||||||
CardP& card = out[k];
|
CardP& card = out[k];
|
||||||
@@ -394,125 +375,56 @@ bool CardListBase::parseText(String& text, vector<CardP>& out) {
|
|||||||
return j < out.size();
|
return j < out.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
|
bool CardListBase::parseData(bool ignore_cards_from_own_card_list) {
|
||||||
wxBusyCursor wait;
|
wxBusyCursor wait;
|
||||||
wxDataObjectComposite* composite = drop_target->data_object;
|
wxDataFormat format = drop_target->data_object->GetReceivedFormat();
|
||||||
wxDataFormat format = composite->GetReceivedFormat();
|
wxDataObject *data = drop_target->data_object->GetObject(format);
|
||||||
vector<CardP> new_cards;
|
vector<CardP> new_cards;
|
||||||
|
|
||||||
if (format == CardsDataObject::format) {
|
if (CardsDataObject* card_data = dynamic_cast<CardsDataObject*>(data)) {
|
||||||
String id = ignore_cards_from_own_card_list ? drop_target->ignored_id : _("");
|
String id = ignore_cards_from_own_card_list ? drop_target->ignored_id : _("");
|
||||||
size_t size = composite->GetDataSize(format);
|
card_data->getCards(set, id, new_cards);
|
||||||
if (size < 1) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("DEBUG: CardsDataObject corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (size > 10000000) { // 10Mb
|
|
||||||
queue_message(MESSAGE_ERROR, _("Too much card data, paste less cards!"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
std::vector<char> buffer(size);
|
|
||||||
if (composite->GetDataHere(format, buffer.data())) {
|
|
||||||
CardsDataObject card_data;
|
|
||||||
card_data.SetData(size, buffer.data());
|
|
||||||
card_data.getCards(set, id, new_cards);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else switch (format.GetType())
|
||||||
wxDataObject *data = composite->GetObject(format);
|
{
|
||||||
|
case wxDF_FILENAME:
|
||||||
switch (format.GetType())
|
|
||||||
{
|
{
|
||||||
case wxDF_FILENAME:
|
wxFileDataObject* file_data = static_cast<wxFileDataObject*>(data);
|
||||||
{
|
wxArrayString filenames = file_data->GetFilenames();
|
||||||
wxFileDataObject* file_data = static_cast<wxFileDataObject*>(data);
|
parseFiles(filenames, new_cards);
|
||||||
wxArrayString filenames = file_data->GetFilenames();
|
}
|
||||||
parseFiles(filenames, new_cards);
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wxDF_PNG:
|
case wxDF_PNG:
|
||||||
{
|
{
|
||||||
wxImageDataObject* image_data = static_cast<wxImageDataObject*>(data);
|
wxImageDataObject* image_data = static_cast<wxImageDataObject*>(data);
|
||||||
size_t size = image_data->GetDataSize();
|
Image image = image_data->GetImage();
|
||||||
if (size < 1) {
|
parseImage(image, new_cards);
|
||||||
queue_message(MESSAGE_ERROR, _("DEBUG: ImageDataObject corrupted"));
|
}
|
||||||
return false;
|
break;
|
||||||
}
|
|
||||||
if (size > 50000000) { // 50Mb
|
|
||||||
queue_message(MESSAGE_ERROR, _("Image data too large or corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
Image image = image_data->GetImage();
|
|
||||||
if (!image.IsOk() || image.GetWidth() > 20000 || image.GetHeight() > 20000) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("Image too large or corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
parseImage(image, new_cards);
|
|
||||||
} catch (const std::bad_alloc&) {
|
|
||||||
//queue_message(MESSAGE_ERROR, _("Image couldn't be allocated"));
|
|
||||||
return false;
|
|
||||||
} catch (...) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("Image couldn't be processed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wxDF_BITMAP:
|
case wxDF_BITMAP:
|
||||||
{
|
{
|
||||||
wxBitmapDataObject* bitmap_data = static_cast<wxBitmapDataObject*>(data);
|
wxBitmapDataObject* bitmap_data = static_cast<wxBitmapDataObject*>(data);
|
||||||
size_t size = bitmap_data->GetDataSize();
|
wxBitmap bitmap = bitmap_data->GetBitmap();
|
||||||
if (size < 1) {
|
Image image = bitmap.ConvertToImage();
|
||||||
queue_message(MESSAGE_ERROR, _("DEBUG: BitmapDataObject corrupted"));
|
parseImage(image, new_cards);
|
||||||
return false;
|
}
|
||||||
}
|
break;
|
||||||
if (size > 50000000) { // 50Mb
|
|
||||||
queue_message(MESSAGE_ERROR, _("Bitmap data too large or corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
wxBitmap bitmap = bitmap_data->GetBitmap();
|
|
||||||
if (!bitmap.IsOk() || bitmap.GetWidth() > 20000 || bitmap.GetHeight() > 20000) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("Bitmap too large or corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
Image image = bitmap.ConvertToImage();
|
|
||||||
parseImage(image, new_cards);
|
|
||||||
} catch (const std::bad_alloc&) {
|
|
||||||
//queue_message(MESSAGE_ERROR, _("Bitmap or Image couldn't be allocated"));
|
|
||||||
return false;
|
|
||||||
} catch (...) {
|
|
||||||
queue_message(MESSAGE_ERROR, _("Bitmap or Image couldn't be processed"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case wxDF_UNICODETEXT:
|
case wxDF_UNICODETEXT:
|
||||||
case wxDF_TEXT:
|
case wxDF_TEXT:
|
||||||
case wxDF_HTML:
|
case wxDF_HTML:
|
||||||
{
|
{
|
||||||
wxTextDataObject* text_data = static_cast<wxTextDataObject*>(data);
|
wxTextDataObject* text_data = static_cast<wxTextDataObject*>(data);
|
||||||
size_t size = text_data->GetDataSize();
|
String text = text_data->GetText();
|
||||||
if (size < 1) {
|
if (!parseUrl(text, new_cards)) parseText(text, new_cards);
|
||||||
queue_message(MESSAGE_ERROR, _("DEBUG: TextDataObject corrupted"));
|
}
|
||||||
return false;
|
break;
|
||||||
}
|
|
||||||
if (size > 30000000) { // 30Mb
|
|
||||||
queue_message(MESSAGE_ERROR, _("Text too large or corrupted"));
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
String text = text_data->GetText();
|
|
||||||
if (!parseUrl(text, new_cards)) parseText(text, new_cards);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
{
|
{
|
||||||
queue_message(MESSAGE_ERROR, _ERROR_("unknown data format"));
|
queue_message(MESSAGE_ERROR, _ERROR_("unknown data format"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,8 +441,12 @@ bool CardListBase::canLink() const {
|
|||||||
vector<CardP> selected_cards;
|
vector<CardP> selected_cards;
|
||||||
getSelection(selected_cards);
|
getSelection(selected_cards);
|
||||||
if (selected_cards.size() != 1) return false;
|
if (selected_cards.size() != 1) return false;
|
||||||
|
unordered_set<String> all_existing_uids;
|
||||||
|
FOR_EACH(card, set->cards) {
|
||||||
|
all_existing_uids.insert(card->uid);
|
||||||
|
}
|
||||||
CardP card = selected_cards[0];
|
CardP card = selected_cards[0];
|
||||||
return card->findFreeLink(card->uid, set->card_uids) >= 0;
|
return card->findFreeLink(card->uid, all_existing_uids) >= 0;
|
||||||
}
|
}
|
||||||
bool CardListBase::doLink() {
|
bool CardListBase::doLink() {
|
||||||
CardLinkWindow wnd(this, set, getCard());
|
CardLinkWindow wnd(this, set, getCard());
|
||||||
@@ -560,23 +476,7 @@ bool CardListBase::compareItems(void* a, void* b) const {
|
|||||||
// compare sort keys
|
// compare sort keys
|
||||||
int cmp = smart_compare( va->getSortKey(), vb->getSortKey() );
|
int cmp = smart_compare( va->getSortKey(), vb->getSortKey() );
|
||||||
if (cmp != 0) return cmp < 0;
|
if (cmp != 0) return cmp < 0;
|
||||||
// equal values, compare alternate sort keys
|
// equal values, compare alternate sort key
|
||||||
if (sort_by_column2 != sort_by_column && sort_by_column2 >= 0) {
|
|
||||||
FieldP sort_field2 = column_fields[sort_by_column2];
|
|
||||||
ValueP va2 = reinterpret_cast<Card*>(a)->data[sort_field2];
|
|
||||||
ValueP vb2 = reinterpret_cast<Card*>(b)->data[sort_field2];
|
|
||||||
assert(va2 && vb2);
|
|
||||||
int cmp = smart_compare( va2->getSortKey(), vb2->getSortKey() );
|
|
||||||
if (cmp != 0) return cmp < 0;
|
|
||||||
if (sort_by_column3 != sort_by_column && sort_by_column3 != sort_by_column2 && sort_by_column3 >= 0) {
|
|
||||||
FieldP sort_field3 = column_fields[sort_by_column3];
|
|
||||||
ValueP va3 = reinterpret_cast<Card*>(a)->data[sort_field3];
|
|
||||||
ValueP vb3 = reinterpret_cast<Card*>(b)->data[sort_field3];
|
|
||||||
assert(va3 && vb3);
|
|
||||||
int cmp = smart_compare( va3->getSortKey(), vb3->getSortKey() );
|
|
||||||
if (cmp != 0) return cmp < 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (alternate_sort_field) {
|
if (alternate_sort_field) {
|
||||||
ValueP va = reinterpret_cast<Card*>(a)->data[alternate_sort_field];
|
ValueP va = reinterpret_cast<Card*>(a)->data[alternate_sort_field];
|
||||||
ValueP vb = reinterpret_cast<Card*>(b)->data[alternate_sort_field];
|
ValueP vb = reinterpret_cast<Card*>(b)->data[alternate_sort_field];
|
||||||
@@ -616,8 +516,6 @@ void CardListBase::rebuild() {
|
|||||||
GameSettings& gs = settings.gameSettingsFor(*set->game);
|
GameSettings& gs = settings.gameSettingsFor(*set->game);
|
||||||
sort_ascending = gs.sort_cards_ascending;
|
sort_ascending = gs.sort_cards_ascending;
|
||||||
sort_by_column = -1;
|
sort_by_column = -1;
|
||||||
sort_by_column2 = -1;
|
|
||||||
sort_by_column3 = -1;
|
|
||||||
long i = 0;
|
long i = 0;
|
||||||
FOR_EACH(f, column_fields) {
|
FOR_EACH(f, column_fields) {
|
||||||
if (f->name == gs.sort_cards_by) {
|
if (f->name == gs.sort_cards_by) {
|
||||||
@@ -753,8 +651,7 @@ void CardListBase::onChar(wxKeyEvent& ev) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CardListBase::onBeginDrag(wxListEvent& ev) {
|
void CardListBase::onBeginDrag(wxListEvent&) {
|
||||||
ev.Skip();
|
|
||||||
drop_timer.Start(200, wxTIMER_ONE_SHOT);
|
drop_timer.Start(200, wxTIMER_ONE_SHOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -800,7 +697,6 @@ void CardListBase::onContextMenu(wxContextMenuEvent&) {
|
|||||||
add_menu_item_tr(&m, wxID_PASTE, "paste", "paste_card");
|
add_menu_item_tr(&m, wxID_PASTE, "paste", "paste_card");
|
||||||
m.AppendSeparator();
|
m.AppendSeparator();
|
||||||
add_menu_item_tr(&m, ID_CARD_ADD, "card_add", "add card");
|
add_menu_item_tr(&m, ID_CARD_ADD, "card_add", "add card");
|
||||||
add_menu_item_tr(&m, ID_CARD_ADD_DOUBLE, "card_add_double", "add card double");
|
|
||||||
add_menu_item_tr(&m, ID_CARD_REMOVE, "card_del", "remove card");
|
add_menu_item_tr(&m, ID_CARD_REMOVE, "card_del", "remove card");
|
||||||
add_menu_item_tr(&m, ID_CARD_LINK, settings.darkModePrefix() + "card_link", "link card");
|
add_menu_item_tr(&m, ID_CARD_LINK, settings.darkModePrefix() + "card_link", "link card");
|
||||||
PopupMenu(&m);
|
PopupMenu(&m);
|
||||||
@@ -827,7 +723,7 @@ CardListDropTarget::CardListDropTarget(CardListBase* card_list)
|
|||||||
|
|
||||||
CardListDropTarget::~CardListDropTarget() {}
|
CardListDropTarget::~CardListDropTarget() {}
|
||||||
|
|
||||||
wxDragResult CardListDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) {
|
wxDragResult CardListDropTarget::OnData(wxCoord x, wxCoord y, wxDragResult defaultDragResult) {
|
||||||
if (!GetData()) return wxDragNone;
|
if (!GetData()) return wxDragNone;
|
||||||
if (!card_list->parseData(true)) return wxDragError;
|
if (!card_list->parseData(true)) return wxDragError;
|
||||||
return wxDragCopy;
|
return wxDragCopy;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
ItemList::ItemList(Window* parent, int id, long additional_style, bool multi_sel)
|
ItemList::ItemList(Window* parent, int id, long additional_style, bool multi_sel)
|
||||||
: wxListView(parent, id, wxDefaultPosition, wxDefaultSize, additional_style | wxLC_REPORT | wxLC_VIRTUAL | (multi_sel ? 0 : wxLC_SINGLE_SEL))
|
: wxListView(parent, id, wxDefaultPosition, wxDefaultSize, additional_style | wxLC_REPORT | wxLC_VIRTUAL | (multi_sel ? 0 : wxLC_SINGLE_SEL))
|
||||||
, selected_item_pos(-1)
|
, selected_item_pos(-1)
|
||||||
, sort_by_column(-1), sort_by_column2(-1), sort_by_column3(-1), sort_ascending(true)
|
, sort_by_column(-1), sort_ascending(true)
|
||||||
{
|
{
|
||||||
// create image list
|
// create image list
|
||||||
wxImageList* il = new wxImageList(18,14);
|
wxImageList* il = new wxImageList(18,14);
|
||||||
@@ -262,9 +262,7 @@ void ItemList::onColumnClick(wxListEvent& ev) {
|
|||||||
} else {
|
} else {
|
||||||
new_sort_by_column = -1; // 3rd click on same column -> don't sort
|
new_sort_by_column = -1; // 3rd click on same column -> don't sort
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sort_by_column3 = sort_by_column2;
|
|
||||||
sort_by_column2 = sort_by_column;
|
|
||||||
sort_ascending = true;
|
sort_ascending = true;
|
||||||
}
|
}
|
||||||
sortBy(new_sort_by_column, sort_ascending);
|
sortBy(new_sort_by_column, sort_ascending);
|
||||||
|
|||||||
@@ -107,8 +107,6 @@ protected:
|
|||||||
VoidP selected_item; ///< The currently selected item
|
VoidP selected_item; ///< The currently selected item
|
||||||
long selected_item_pos; ///< Position of the selected item in the sorted_list, or -1 if no card is selected
|
long selected_item_pos; ///< Position of the selected item in the sorted_list, or -1 if no card is selected
|
||||||
long sort_by_column; ///< Column to use for sorting, or -1 if not sorted
|
long sort_by_column; ///< Column to use for sorting, or -1 if not sorted
|
||||||
long sort_by_column2; ///< Previous column used for sorting, or -1 if not sorted
|
|
||||||
long sort_by_column3; ///< Previous previous column used for sorting, or -1 if not sorted (stable sort aint workin so we doing this I guess)
|
|
||||||
bool sort_ascending; ///< Sort order
|
bool sort_ascending; ///< Sort order
|
||||||
vector<VoidP> sorted_list; ///< Sorted list of items, can be considered a map: pos->item
|
vector<VoidP> sorted_list; ///< Sorted list of items, can be considered a map: pos->item
|
||||||
|
|
||||||
|
|||||||
@@ -109,7 +109,6 @@ bool KeywordList::doCopy() {
|
|||||||
if (!canCopy()) return false;
|
if (!canCopy()) return false;
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
bool ok = wxTheClipboard->SetData(new KeywordDataObject(set, getKeyword())); // ignore result
|
bool ok = wxTheClipboard->SetData(new KeywordDataObject(set, getKeyword())); // ignore result
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -126,7 +125,6 @@ bool KeywordList::doPaste() {
|
|||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
KeywordDataObject data;
|
KeywordDataObject data;
|
||||||
bool ok = wxTheClipboard->GetData(data);
|
bool ok = wxTheClipboard->GetData(data);
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
// add keyword to set
|
// add keyword to set
|
||||||
|
|||||||
@@ -16,36 +16,18 @@
|
|||||||
|
|
||||||
/// A list of installed and downloadable packages
|
/// A list of installed and downloadable packages
|
||||||
class PackageUpdateList : public TreeList {
|
class PackageUpdateList : public TreeList {
|
||||||
private:
|
|
||||||
class TreeItem;
|
|
||||||
public:
|
public:
|
||||||
typedef intrusive_ptr<TreeItem> TreeItemP;
|
|
||||||
|
|
||||||
PackageUpdateList(Window* parent, const InstallablePackages& packages, bool show_only_installable, int id = wxID_ANY);
|
PackageUpdateList(Window* parent, const InstallablePackages& packages, bool show_only_installable, int id = wxID_ANY);
|
||||||
~PackageUpdateList();
|
~PackageUpdateList();
|
||||||
|
|
||||||
inline InstallablePackageP getSelectedPackage() const {
|
inline InstallablePackageP getSelection() const {
|
||||||
TreeItem* ti = getSelectedItem();
|
return selection == NOTHING ? InstallablePackageP() : get(selection);
|
||||||
return ti ? ti->package : InstallablePackageP();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool selectionIsGroup() const {
|
inline InstallablePackageP get(size_t item) const {
|
||||||
TreeItem* ti = getSelectedItem();
|
return static_pointer_cast<TreeItem>(items[item])->package;
|
||||||
return ti && !ti->package;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void forEachSelectedPackage(const std::function<void(const InstallablePackageP&)>& fn) const {
|
|
||||||
forEachPackage(getSelectedItem(), fn);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool anySelectedPackage(const std::function<bool(const InstallablePackageP&)>& predicate) const {
|
|
||||||
return anyPackage(getSelectedItem(), predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool allSelectedPackages(const std::function<bool(const InstallablePackageP&)>& predicate) const {
|
|
||||||
return allPackages(getSelectedItem(), predicate);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// overridden methods from TreeList
|
// overridden methods from TreeList
|
||||||
void initItems() override;
|
void initItems() override;
|
||||||
@@ -56,48 +38,15 @@ protected:
|
|||||||
int columnWidth(size_t column) const override;
|
int columnWidth(size_t column) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline TreeItem* getSelectedItem() const {
|
|
||||||
return selection >= items.size() ? nullptr : static_pointer_cast<TreeItem>(items[selection]).get();
|
|
||||||
}
|
|
||||||
inline void forEachPackage(const TreeItem* item, const std::function<void(const InstallablePackageP&)>& fn) const {
|
|
||||||
if (!item) return;
|
|
||||||
if (item->package) {
|
|
||||||
fn(item->package);
|
|
||||||
}
|
|
||||||
for (const auto& child : item->children) {
|
|
||||||
forEachPackage(child.get(), fn);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
inline bool anyPackage(const TreeItem* item, const std::function<bool(const InstallablePackageP&)>& predicate) const {
|
|
||||||
if (!item) return false;
|
|
||||||
if (item->package && predicate(item->package)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
for (const auto& child : item->children) {
|
|
||||||
if (anyPackage(child.get(), predicate)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
inline bool allPackages(const TreeItem* item, const std::function<bool(const InstallablePackageP&)>& predicate) const {
|
|
||||||
if (!item) return false;
|
|
||||||
if (item->package && !predicate(item->package)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
for (const auto& child : item->children) {
|
|
||||||
if (!allPackages(child.get(), predicate)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The list of packages we are displaying
|
/// The list of packages we are displaying
|
||||||
const InstallablePackages& packages;
|
const InstallablePackages& packages;
|
||||||
/// Show only packages with an installer?
|
/// Show only packages with an installer?
|
||||||
bool show_only_installable;
|
bool show_only_installable;
|
||||||
|
|
||||||
|
class TreeItem;
|
||||||
|
public:
|
||||||
|
typedef intrusive_ptr<TreeItem> TreeItemP;
|
||||||
|
private:
|
||||||
class TreeItem : public Item {
|
class TreeItem : public Item {
|
||||||
public:
|
public:
|
||||||
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
|
TreeItem() : position_type(TYPE_OTHER), position_hint(1000000) {}
|
||||||
|
|||||||
+38
-80
@@ -86,36 +86,31 @@ void PackageInfoPanel::draw(DC& dc) {
|
|||||||
icon_w = icon.GetWidth();
|
icon_w = icon.GetWidth();
|
||||||
icon_h = icon.GetHeight();
|
icon_h = icon.GetHeight();
|
||||||
}
|
}
|
||||||
dc.DrawBitmap(icon, x+(max_size-icon_w)/2, y+(max_size-icon_h)/2 + 2);
|
dc.DrawBitmap(icon, x+(max_size-icon_w)/2, y+(max_size-icon_h)/2);
|
||||||
x += max_size;
|
x += max_size;
|
||||||
}
|
}
|
||||||
// package info
|
// package name
|
||||||
x += 7;
|
x += 7;
|
||||||
dc.SetFont(wxFont(16, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
|
dc.SetFont(wxFont(16, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
|
||||||
dc.DrawText(d.short_name, x, y);
|
dc.DrawText(d.full_name, x, y);
|
||||||
y += dc.GetCharHeight() + 7;
|
|
||||||
dc.SetFont(wxFont(12, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL, false, _("Arial")));
|
|
||||||
if (d.full_name != d.short_name) dc.DrawText(d.full_name, x, y);
|
|
||||||
y += dc.GetCharHeight() + 7;
|
y += dc.GetCharHeight() + 7;
|
||||||
|
|
||||||
|
// version
|
||||||
dc.SetFont(*wxNORMAL_FONT);
|
dc.SetFont(*wxNORMAL_FONT);
|
||||||
int dy = dc.GetCharHeight() + 3;
|
int dy = dc.GetCharHeight() + 3;
|
||||||
dc.DrawText(_LABEL_("folder name"), x, y);
|
dc.DrawText(_LABEL_("installed version"), x, y);
|
||||||
dc.DrawText(_LABEL_("installed version"), x, y + 1*dy);
|
dc.DrawText(_LABEL_("installable version"), x, y + 1*dy);
|
||||||
dc.DrawText(_LABEL_("installable version"), x, y + 2*dy);
|
|
||||||
//dc.DrawText(_LABEL_("installer size"), x, y + 2*dy);
|
//dc.DrawText(_LABEL_("installer size"), x, y + 2*dy);
|
||||||
//dc.DrawText(_LABEL_("installer status"), x, y + 3*dy);
|
//dc.DrawText(_LABEL_("installer status"), x, y + 3*dy);
|
||||||
// text size?
|
// text size?
|
||||||
int dx = 0, max_dx = 0;
|
int dx = 0, max_dx = 0;
|
||||||
dc.GetTextExtent(_LABEL_("folder name"), &dx, nullptr); max_dx = max(max_dx, dx);
|
|
||||||
dc.GetTextExtent(_LABEL_("installed version"), &dx, nullptr); max_dx = max(max_dx, dx);
|
dc.GetTextExtent(_LABEL_("installed version"), &dx, nullptr); max_dx = max(max_dx, dx);
|
||||||
dc.GetTextExtent(_LABEL_("installable version"), &dx, nullptr); max_dx = max(max_dx, dx);
|
dc.GetTextExtent(_LABEL_("installable version"), &dx, nullptr); max_dx = max(max_dx, dx);
|
||||||
//dc.GetTextExtent(_LABEL_("installer size"), &dx, nullptr); max_dx = max(max_dx, dx);
|
//dc.GetTextExtent(_LABEL_("installer size"), &dx, nullptr); max_dx = max(max_dx, dx);
|
||||||
//dc.GetTextExtent(_LABEL_("installer status"), &dx, nullptr); max_dx = max(max_dx, dx);
|
//dc.GetTextExtent(_LABEL_("installer status"), &dx, nullptr); max_dx = max(max_dx, dx);
|
||||||
x += max_dx + 5;
|
x += max_dx + 5;
|
||||||
dc.DrawText(d.name, x, y);
|
dc.DrawText(package->installed ? package->installed->version.toString() : _LABEL_("no version"), x, y);
|
||||||
dc.DrawText(package->installed ? package->installed->version.toString() : _LABEL_("no version"), x, y + 1*dy);
|
dc.DrawText(package->installer ? package->description->version.toString() : _LABEL_("no version"), x, y + 1*dy);
|
||||||
dc.DrawText(package->installer ? package->description->version.toString() : _LABEL_("no version"), x, y + 2*dy);
|
|
||||||
//dc.DrawText(_("?"), x, y + 2*dy);
|
//dc.DrawText(_("?"), x, y + 2*dy);
|
||||||
//dc.DrawText(_("?"), x, y + 3*dy);
|
//dc.DrawText(_("?"), x, y + 3*dy);
|
||||||
}
|
}
|
||||||
@@ -199,8 +194,7 @@ void PackagesWindow::init(Window* parent, bool show_only_installable) {
|
|||||||
v2->AddStretchSpacer();
|
v2->AddStretchSpacer();
|
||||||
v2->Add(keep_button, 0, wxEXPAND | wxBOTTOM, 4);
|
v2->Add(keep_button, 0, wxEXPAND | wxBOTTOM, 4);
|
||||||
v2->AddStretchSpacer();
|
v2->AddStretchSpacer();
|
||||||
v2->Add(remove_button, 0, wxEXPAND | wxBOTTOM, 0);
|
v2->Add(remove_button, 0, wxEXPAND | wxBOTTOM, 0);
|
||||||
v2->SetMinSize(wxSize(170, -1));
|
|
||||||
h->Add(v2);
|
h->Add(v2);
|
||||||
v->Add(h, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
v->Add(h, 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
wxBoxSizer* h2 = new wxBoxSizer(wxHORIZONTAL);
|
wxBoxSizer* h2 = new wxBoxSizer(wxHORIZONTAL);
|
||||||
@@ -208,7 +202,7 @@ void PackagesWindow::init(Window* parent, bool show_only_installable) {
|
|||||||
h2->AddStretchSpacer();
|
h2->AddStretchSpacer();
|
||||||
h2->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
h2->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | (wxALL & ~wxTOP), 8);
|
||||||
v->Add(h2, 0, wxEXPAND);
|
v->Add(h2, 0, wxEXPAND);
|
||||||
v->SetMinSize(820,650);
|
v->SetMinSize(800,600);
|
||||||
SetSizerAndFit(v);
|
SetSizerAndFit(v);
|
||||||
|
|
||||||
wxUpdateUIEvent::SetMode(wxUPDATE_UI_PROCESS_SPECIFIED);
|
wxUpdateUIEvent::SetMode(wxUPDATE_UI_PROCESS_SPECIFIED);
|
||||||
@@ -218,27 +212,24 @@ void PackagesWindow::init(Window* parent, bool show_only_installable) {
|
|||||||
PackagesWindow::~PackagesWindow() {
|
PackagesWindow::~PackagesWindow() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void PackagesWindow::onPackageSelect(wxCommandEvent& ev) {
|
void PackagesWindow::onPackageSelect(wxCommandEvent& ev) {
|
||||||
package_info->setPackage(package = package_list->getSelectedPackage());
|
package_info->setPackage(package = package_list->getSelection());
|
||||||
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackagesWindow::onActionChange(wxCommandEvent& ev) {
|
void PackagesWindow::onActionChange(wxCommandEvent& ev) {
|
||||||
PackageAction act = ev.GetId() == ID_INSTALL ? PACKAGE_ACT_INSTALL
|
if (package) {
|
||||||
: ev.GetId() == ID_UPGRADE ? PACKAGE_ACT_INSTALL
|
PackageAction act = ev.GetId() == ID_INSTALL ? PACKAGE_ACT_INSTALL
|
||||||
: ev.GetId() == ID_REMOVE ? PACKAGE_ACT_REMOVE
|
: ev.GetId() == ID_UPGRADE ? PACKAGE_ACT_INSTALL
|
||||||
: PACKAGE_ACT_NOTHING;
|
: ev.GetId() == ID_REMOVE ? PACKAGE_ACT_REMOVE
|
||||||
act = act | where;
|
: PACKAGE_ACT_NOTHING;
|
||||||
// set action
|
act = act | where;
|
||||||
package_list->forEachSelectedPackage(
|
// set action
|
||||||
[&](const InstallablePackageP& p) {
|
set_package_action(installable_packages, package, act);
|
||||||
if (p->can(act)) {
|
package_list->Refresh(false);
|
||||||
set_package_action(installable_packages, p, act);
|
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
);
|
|
||||||
package_list->Refresh(false);
|
|
||||||
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackagesWindow::onOk(wxCommandEvent& ev) {
|
void PackagesWindow::onOk(wxCommandEvent& ev) {
|
||||||
@@ -377,61 +368,28 @@ void PackagesWindow::onOk(wxCommandEvent& ev) {
|
|||||||
//%% NOTE: The above text is for the locale.pl program
|
//%% NOTE: The above text is for the locale.pl program
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) {
|
void PackagesWindow::onUpdateUI(wxUpdateUIEvent& ev) {
|
||||||
bool is_group = package_list->selectionIsGroup();
|
|
||||||
wxToggleButton* w = (wxToggleButton*)ev.GetEventObject();
|
wxToggleButton* w = (wxToggleButton*)ev.GetEventObject();
|
||||||
switch (ev.GetId()) {
|
switch (ev.GetId()) {
|
||||||
case ID_KEEP:
|
case ID_KEEP:
|
||||||
w->SetValue(
|
w->SetValue(package && package->has(PACKAGE_ACT_NOTHING));
|
||||||
package_list->allSelectedPackages([&](const InstallablePackageP& p) {
|
w->Enable (package && package->can(PACKAGE_ACT_NOTHING | where));
|
||||||
return p->has(PACKAGE_ACT_NOTHING);
|
w->SetLabel(package && package->installed ? _BUTTON_("keep package") : _BUTTON_("don't install package"));
|
||||||
})
|
|
||||||
);
|
|
||||||
w->Enable(
|
|
||||||
package_list->anySelectedPackage([&](const InstallablePackageP& p) {
|
|
||||||
return p->can(PACKAGE_ACT_NOTHING | where);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
w->SetLabel(is_group ? _BUTTON_("keep group") :
|
|
||||||
package && package->installed ? _BUTTON_("keep package") :
|
|
||||||
_BUTTON_("don't install package"));
|
|
||||||
break;
|
break;
|
||||||
case ID_INSTALL:
|
case ID_INSTALL:
|
||||||
w->SetValue(
|
w->SetValue(package && package->has(PACKAGE_ACT_INSTALL | where));
|
||||||
package_list->allSelectedPackages([&](const InstallablePackageP& p) {
|
w->Enable (package && package->can(PACKAGE_ACT_INSTALL | where));
|
||||||
return p->has(PACKAGE_ACT_INSTALL | where) ||
|
w->SetLabel(!(package && package->installed) ? _BUTTON_("install package")
|
||||||
(p->has(PACKAGE_INSTALLED) && !p->has(PACKAGE_ACT_REMOVE) && !p->has(PACKAGE_UPDATES));
|
: (package && package->has(PACKAGE_UPDATES)) ? _BUTTON_("upgrade package")
|
||||||
}) &&
|
: _BUTTON_("reinstall package"));
|
||||||
package_list->anySelectedPackage([&](const InstallablePackageP& p) {
|
|
||||||
return p->has(PACKAGE_ACT_INSTALL | where);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
w->Enable(
|
|
||||||
package_list->anySelectedPackage([&](const InstallablePackageP& p) {
|
|
||||||
return p->can(PACKAGE_ACT_INSTALL | where);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
w->SetLabel(is_group ? _BUTTON_("install group") :
|
|
||||||
!(package && package->installed) ? _BUTTON_("install package") :
|
|
||||||
(package && package->has(PACKAGE_UPDATES)) ? _BUTTON_("upgrade package") :
|
|
||||||
_BUTTON_("reinstall package"));
|
|
||||||
break;
|
break;
|
||||||
case ID_REMOVE:
|
case ID_REMOVE:
|
||||||
w->SetValue(
|
w->SetValue(package && package->has(PACKAGE_ACT_REMOVE | where));
|
||||||
package_list->allSelectedPackages([&](const InstallablePackageP& p) {
|
w->Enable (package && package->can(PACKAGE_ACT_REMOVE | where));
|
||||||
return p->has(PACKAGE_ACT_REMOVE | where) ||
|
//w->SetLabel(package && package->... ? _BUTTON_("remove group") : _BUTTON_("remove package"));
|
||||||
(!p->has(PACKAGE_INSTALLED) && !p->has(PACKAGE_ACT_INSTALL));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
w->Enable(
|
|
||||||
package_list->anySelectedPackage([&](const InstallablePackageP& p) {
|
|
||||||
return p->can(PACKAGE_ACT_REMOVE | where);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
w->SetLabel(is_group ? _BUTTON_("remove group") :
|
|
||||||
_BUTTON_("remove package"));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// TODO: change labels to _BUTTON_("install group"), _BUTTON_("remove group"), _BUTTON_("upgrade group")
|
||||||
}
|
}
|
||||||
|
|
||||||
void PackagesWindow::onIdle(wxIdleEvent& ev) {
|
void PackagesWindow::onIdle(wxIdleEvent& ev) {
|
||||||
@@ -451,7 +409,7 @@ bool PackagesWindow::checkInstallerList(bool refresh) {
|
|||||||
// refresh
|
// refresh
|
||||||
if (refresh) {
|
if (refresh) {
|
||||||
package_list->rebuild();
|
package_list->rebuild();
|
||||||
package_info->setPackage(package = package_list->getSelectedPackage());
|
package_info->setPackage(package = package_list->getSelection());
|
||||||
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
UpdateWindowUI(wxUPDATE_UI_RECURSE);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ void PrintJob::measure_cards() {
|
|||||||
if (already_measured_cards.find(card) != already_measured_cards.end()) continue;
|
if (already_measured_cards.find(card) != already_measured_cards.end()) continue;
|
||||||
already_measured_cards.emplace(card);
|
already_measured_cards.emplace(card);
|
||||||
card_layouts.emplace_back(measure_card(card));
|
card_layouts.emplace_back(measure_card(card));
|
||||||
CardP other_face = card->getLinkedOtherFaceCard(*set); // we assume that if you want to print one side, you also want to print the other, so we look for it in the entire set instead of just the given cards
|
CardP other_face = card->getLinkedOtherFaceCard(cards);
|
||||||
if (other_face && already_measured_cards.find(other_face) == already_measured_cards.end()) {
|
if (other_face && already_measured_cards.find(other_face) == already_measured_cards.end()) {
|
||||||
already_measured_cards.emplace(other_face);
|
already_measured_cards.emplace(other_face);
|
||||||
card_layouts.emplace_back(measure_card(other_face));
|
card_layouts.emplace_back(measure_card(other_face));
|
||||||
|
|||||||
@@ -127,14 +127,13 @@ CardsPanel::CardsPanel(Window* parent, int id)
|
|||||||
add_menu_item_tr(menuCard, ID_CARD_NEXT, nullptr, "next card");
|
add_menu_item_tr(menuCard, ID_CARD_NEXT, nullptr, "next card");
|
||||||
add_menu_item_tr(menuCard, ID_CARD_SEARCH, nullptr, "search cards");
|
add_menu_item_tr(menuCard, ID_CARD_SEARCH, nullptr, "search cards");
|
||||||
menuCard->AppendSeparator();
|
menuCard->AppendSeparator();
|
||||||
add_menu_item_tr(menuCard, ID_CARD_ADD, "card_add", "add_card");
|
|
||||||
add_menu_item_tr(menuCard, ID_CARD_ADD_DOUBLE, "card_add_double", "add_card_double");
|
|
||||||
insertManyCardsMenu = add_menu_item_tr(menuCard, ID_CARD_ADD_MULT, "card_add_multiple", "add cards");
|
insertManyCardsMenu = add_menu_item_tr(menuCard, ID_CARD_ADD_MULT, "card_add_multiple", "add cards");
|
||||||
// NOTE: space after "Del" prevents wx from making del an accellerator
|
// NOTE: space after "Del" prevents wx from making del an accellerator
|
||||||
// otherwise we delete a card when delete is pressed inside the editor
|
// otherwise we delete a card when delete is pressed inside the editor
|
||||||
// Adding a space never hurts, please keep it just to be safe.
|
// Adding a space never hurts, please keep it just to be safe.
|
||||||
add_menu_item(menuCard, ID_CARD_ADD_CSV, "card_add_multiple", _MENU_("add card csv") + _(" "), _HELP_("add card csv"));
|
add_menu_item(menuCard, ID_CARD_ADD_CSV, "card_add_multiple", _MENU_("add card csv") + _(" "), _HELP_("add card csv"));
|
||||||
add_menu_item(menuCard, ID_CARD_ADD_JSON, "card_add_multiple", _MENU_("add card json") + _(" "), _HELP_("add card json"));
|
add_menu_item(menuCard, ID_CARD_ADD_JSON, "card_add_multiple", _MENU_("add card json") + _(" "), _HELP_("add card json"));
|
||||||
|
add_menu_item_tr(menuCard, ID_CARD_ADD, "card_add", "add_card");
|
||||||
add_menu_item(menuCard, ID_CARD_REMOVE, "card_del", _MENU_("remove card")+_(" "), _HELP_("remove card"));
|
add_menu_item(menuCard, ID_CARD_REMOVE, "card_del", _MENU_("remove card")+_(" "), _HELP_("remove card"));
|
||||||
add_menu_item(menuCard, ID_CARD_LINK, settings.darkModePrefix() + "card_link", _MENU_("link card") + _(" "), _HELP_("link card"));
|
add_menu_item(menuCard, ID_CARD_LINK, settings.darkModePrefix() + "card_link", _MENU_("link card") + _(" "), _HELP_("link card"));
|
||||||
add_menu_item(menuCard, ID_CARD_AND_LINK_COPY, "card_copy", _MENU_("copy card and links") + _(" "), _HELP_("copy card and links"));
|
add_menu_item(menuCard, ID_CARD_AND_LINK_COPY, "card_copy", _MENU_("copy card and links") + _(" "), _HELP_("copy card and links"));
|
||||||
@@ -256,7 +255,7 @@ void CardsPanel::onChangeSet() {
|
|||||||
insertManyCardsMenu->SetSubMenu(makeAddCardsSubmenu(false));
|
insertManyCardsMenu->SetSubMenu(makeAddCardsSubmenu(false));
|
||||||
// re-add the menu
|
// re-add the menu
|
||||||
menuCard->Remove(ID_CARD_ADD_MULT);
|
menuCard->Remove(ID_CARD_ADD_MULT);
|
||||||
((wxMenu*)menuCard)->Insert(6,insertManyCardsMenu); // HACK: the position is hardcoded
|
((wxMenu*)menuCard)->Insert(4,insertManyCardsMenu); // HACK: the position is hardcoded
|
||||||
// also for the toolbar dropdown menu
|
// also for the toolbar dropdown menu
|
||||||
if (toolAddCard) {
|
if (toolAddCard) {
|
||||||
// Originally this was using the menu directly, but there are compatibility issues apparently.
|
// Originally this was using the menu directly, but there are compatibility issues apparently.
|
||||||
@@ -271,7 +270,6 @@ wxMenu* CardsPanel::makeAddCardsSubmenu(bool add_single_card_option) {
|
|||||||
if (add_single_card_option) {
|
if (add_single_card_option) {
|
||||||
cards_scripts_menu = new wxMenu();
|
cards_scripts_menu = new wxMenu();
|
||||||
add_menu_item_tr(cards_scripts_menu, ID_CARD_ADD, "card_add", "add_card");
|
add_menu_item_tr(cards_scripts_menu, ID_CARD_ADD, "card_add", "add_card");
|
||||||
add_menu_item_tr(cards_scripts_menu, ID_CARD_ADD_DOUBLE, "card_add_double", "add_card_double");
|
|
||||||
cards_scripts_menu->AppendSeparator();
|
cards_scripts_menu->AppendSeparator();
|
||||||
}
|
}
|
||||||
// create menu for add_cards_scripts
|
// create menu for add_cards_scripts
|
||||||
@@ -437,17 +435,6 @@ void CardsPanel::onCommand(int id) {
|
|||||||
case ID_CARD_ADD:
|
case ID_CARD_ADD:
|
||||||
set->actions.addAction(make_unique<AddCardAction>(*set));
|
set->actions.addAction(make_unique<AddCardAction>(*set));
|
||||||
break;
|
break;
|
||||||
case ID_CARD_ADD_DOUBLE: {
|
|
||||||
vector<CardP> cards;
|
|
||||||
cards.push_back(make_intrusive<Card>(*set->game));
|
|
||||||
cards.push_back(make_intrusive<Card>(*set->game));
|
|
||||||
cards[0]->linked_card_1 = cards[1]->uid;
|
|
||||||
cards[1]->linked_card_1 = cards[0]->uid;
|
|
||||||
cards[0]->linked_relation_1 = "Back Face";
|
|
||||||
cards[1]->linked_relation_1 = "Front Face";
|
|
||||||
set->actions.addAction(make_unique<AddCardAction>(ADD, *set, cards));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case ID_CARD_ADD_CSV:
|
case ID_CARD_ADD_CSV:
|
||||||
card_list->doAddCSV();
|
card_list->doAddCSV();
|
||||||
break;
|
break;
|
||||||
@@ -579,7 +566,7 @@ bool CardsPanel::canPaste() const {
|
|||||||
else return false;
|
else return false;
|
||||||
}
|
}
|
||||||
void CardsPanel::doPaste() {
|
void CardsPanel::doPaste() {
|
||||||
if (card_list->doPaste()) return;
|
if (card_list->doPaste()) return;
|
||||||
|
|
||||||
int id = focused_control(this);
|
int id = focused_control(this);
|
||||||
if (id == ID_EDITOR) editor->doPaste();
|
if (id == ID_EDITOR) editor->doPaste();
|
||||||
@@ -667,9 +654,8 @@ CardP CardsPanel::selectedCard() const {
|
|||||||
return card_list->getCard();
|
return card_list->getCard();
|
||||||
}
|
}
|
||||||
void CardsPanel::selectCard(const CardP& card) {
|
void CardsPanel::selectCard(const CardP& card) {
|
||||||
if (!set) return; // we want onChangeSet first
|
if (!set) return; // we want onChangeSet first
|
||||||
|
|
||||||
card_list->SetFocus();
|
|
||||||
card_list->setCard(card);
|
card_list->setCard(card);
|
||||||
|
|
||||||
editor->setCard(card);
|
editor->setCard(card);
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <script/functions/json.hpp>
|
|
||||||
#include <wx/splitter.h>
|
#include <wx/splitter.h>
|
||||||
#include <wx/dcbuffer.h>
|
#include <wx/dcbuffer.h>
|
||||||
#include <wx/clipbrd.h>
|
#include <wx/clipbrd.h>
|
||||||
@@ -108,7 +107,6 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
ok = wxTheClipboard->SetData(new wxTextDataObject(msg.text));
|
ok = wxTheClipboard->SetData(new wxTextDataObject(msg.text));
|
||||||
}
|
}
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -625,7 +623,7 @@ void ConsolePanel::exec(String const& command) {
|
|||||||
// type of result
|
// type of result
|
||||||
ScriptType type = result->type();
|
ScriptType type = result->type();
|
||||||
if (type == SCRIPT_IMAGE) {
|
if (type == SCRIPT_IMAGE) {
|
||||||
GeneratedImage::Options options(0,0, card->stylesheet ? card->stylesheet.get() : set->stylesheet.get(), set.get());
|
GeneratedImage::Options options(0,0, set->stylesheet.get(), set.get());
|
||||||
wxImage image = result->toImage()->generate(options);
|
wxImage image = result->toImage()->generate(options);
|
||||||
message->bitmap = wxBitmap(image);
|
message->bitmap = wxBitmap(image);
|
||||||
} else if (type == SCRIPT_COLOR) {
|
} else if (type == SCRIPT_COLOR) {
|
||||||
@@ -635,10 +633,8 @@ void ConsolePanel::exec(String const& command) {
|
|||||||
fill_image(image,color);
|
fill_image(image,color);
|
||||||
set_alpha(image, color.Alpha() / 255.0);
|
set_alpha(image, color.Alpha() / 255.0);
|
||||||
message->bitmap = wxBitmap(image);
|
message->bitmap = wxBitmap(image);
|
||||||
} else {
|
} else {
|
||||||
boost::json::value jresult = mse_to_json(result, set.get(), true);
|
message->text = result->toCode();
|
||||||
if (jresult.is_null()) message->text = result->toCode();
|
|
||||||
else message->text = json_pretty_print(jresult);
|
|
||||||
}
|
}
|
||||||
messages->add_message(message);
|
messages->add_message(message);
|
||||||
} catch (ScriptError const& e) {
|
} catch (ScriptError const& e) {
|
||||||
|
|||||||
@@ -308,8 +308,7 @@ void SetWindow::onChangeSet() {
|
|||||||
updateTitle();
|
updateTitle();
|
||||||
// make sure there is always at least one card
|
// make sure there is always at least one card
|
||||||
// some things need this
|
// some things need this
|
||||||
if (set->cards.empty()) set->cards.push_back(make_intrusive<Card>(*set->game));
|
if (set->cards.empty()) set->cards.push_back(make_intrusive<Card>(*set->game));
|
||||||
set->buildUIDMap();
|
|
||||||
// all panels view the same set
|
// all panels view the same set
|
||||||
FOR_EACH(p, panels) {
|
FOR_EACH(p, panels) {
|
||||||
p->setSet(set);
|
p->setSet(set);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ void SymbolWindow::init(Window* parent, SymbolP symbol) {
|
|||||||
add_menu_item_tr(menuTool, ID_MODE_POINTS, "mode_curve", "points", wxITEM_CHECK);
|
add_menu_item_tr(menuTool, ID_MODE_POINTS, "mode_curve", "points", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuTool, ID_MODE_SHAPES, settings.darkModePrefix() + "circle", "basic_shapes", wxITEM_CHECK);
|
add_menu_item_tr(menuTool, ID_MODE_SHAPES, settings.darkModePrefix() + "circle", "basic_shapes", wxITEM_CHECK);
|
||||||
add_menu_item_tr(menuTool, ID_MODE_SYMMETRY, "mode_symmetry", "symmetry", wxITEM_CHECK);
|
add_menu_item_tr(menuTool, ID_MODE_SYMMETRY, "mode_symmetry", "symmetry", wxITEM_CHECK);
|
||||||
//add_menu_item_tr(menuTool, ID_MODE_PAINT, settings.darkModePrefix() + "mode_paint", "paint", wxITEM_CHECK);
|
add_menu_item_tr(menuTool, ID_MODE_PAINT, settings.darkModePrefix() + "mode_paint", "paint", wxITEM_CHECK);
|
||||||
menuBar->Append(menuTool, _MENU_("tool"));
|
menuBar->Append(menuTool, _MENU_("tool"));
|
||||||
|
|
||||||
SetMenuBar(menuBar);
|
SetMenuBar(menuBar);
|
||||||
|
|||||||
@@ -92,8 +92,7 @@ bool ImageValueEditor::doCopy() {
|
|||||||
if (!image_load_file(image, *image_file)) return false;
|
if (!image_load_file(image, *image_file)) return false;
|
||||||
// set data
|
// set data
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
bool ok = wxTheClipboard->SetData(new wxBitmapDataObject(image));
|
bool ok = wxTheClipboard->SetData(new wxBitmapDataObject(image));
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
@@ -102,8 +101,7 @@ bool ImageValueEditor::doPaste() {
|
|||||||
// get bitmap
|
// get bitmap
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
wxBitmapDataObject data;
|
wxBitmapDataObject data;
|
||||||
bool ok = wxTheClipboard->GetData(data);
|
bool ok = wxTheClipboard->GetData(data);
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
// slice
|
// slice
|
||||||
|
|||||||
@@ -782,8 +782,7 @@ bool TextValueEditor::doPaste() {
|
|||||||
// get data
|
// get data
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
wxTextDataObject data;
|
wxTextDataObject data;
|
||||||
bool ok = wxTheClipboard->GetData(data);
|
bool ok = wxTheClipboard->GetData(data);
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
if (!ok) return false;
|
if (!ok) return false;
|
||||||
// paste
|
// paste
|
||||||
@@ -801,8 +800,7 @@ bool TextValueEditor::doCopy() {
|
|||||||
if (str.empty()) return false; // no data to copy
|
if (str.empty()) return false; // no data to copy
|
||||||
// set data
|
// set data
|
||||||
if (!wxTheClipboard->Open()) return false;
|
if (!wxTheClipboard->Open()) return false;
|
||||||
bool ok = wxTheClipboard->SetData(new wxTextDataObject(str));
|
bool ok = wxTheClipboard->SetData(new wxTextDataObject(str));
|
||||||
wxTheClipboard->Flush();
|
|
||||||
wxTheClipboard->Close();
|
wxTheClipboard->Close();
|
||||||
return ok;
|
return ok;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <gui/web_request_window.hpp>
|
#include <gui/web_request_window.hpp>
|
||||||
#include <util/window_id.hpp>
|
#include <util/window_id.hpp>
|
||||||
#include <wx/mstream.h>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : WebRequestWindow
|
// ----------------------------------------------------------------------------- : WebRequestWindow
|
||||||
|
|
||||||
@@ -77,50 +76,16 @@ void WebRequestWindow::onUpdate(wxWebRequestEvent& evt) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WebRequestWindow::onComplete(wxWebRequestEvent& evt) {
|
void WebRequestWindow::onComplete(wxWebRequestEvent& evt) {
|
||||||
wxWebResponse response = evt.GetResponse();
|
out = evt.GetResponse();
|
||||||
if (!response.IsOk()) {
|
if (out.IsOk()) {
|
||||||
onFail(_ERROR_("web request corrupted"));
|
EndModal(wxID_OK);
|
||||||
return;
|
|
||||||
}
|
|
||||||
wxInputStream* stream = response.GetStream();
|
|
||||||
if (!stream || !stream->IsOk()) {
|
|
||||||
onFail(_ERROR_("web request corrupted"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
content_type = response.GetContentType();
|
|
||||||
if (content_type.StartsWith("image/")) {
|
|
||||||
image_out = Image(*stream);
|
|
||||||
if (!image_out.IsOk()) {
|
|
||||||
onFail(_ERROR_("web request corrupted"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (content_type.StartsWith("text/") || content_type.Contains("json")) {
|
|
||||||
wxMemoryOutputStream mem;
|
|
||||||
char buffer[8192];
|
|
||||||
while (true) {
|
|
||||||
stream->Read(buffer, sizeof(buffer));
|
|
||||||
size_t read = stream->LastRead();
|
|
||||||
if (read > 0) mem.Write(buffer, read);
|
|
||||||
if (stream->Eof()) break;
|
|
||||||
if (stream->GetLastError() != wxSTREAM_NO_ERROR) {
|
|
||||||
onFail(_ERROR_("web request corrupted"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
text_out.resize(mem.GetSize());
|
|
||||||
mem.CopyTo(text_out.data(), mem.GetSize());
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
onFail(_ERROR_("web request unsupported format"));
|
onFail(_ERROR_("web request corrupted"));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
EndModal(wxID_OK);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void WebRequestWindow::onFail(const String& message) {
|
void WebRequestWindow::onFail(const String& message) {
|
||||||
content_type.Clear();
|
|
||||||
info->SetLabel(_ERROR_("web request failed"));
|
info->SetLabel(_ERROR_("web request failed"));
|
||||||
address->SetLabel(message);
|
address->SetLabel(message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,9 +19,7 @@ class WebRequestWindow : public wxDialog {
|
|||||||
public:
|
public:
|
||||||
WebRequestWindow(const String& url, bool sizer=true);
|
WebRequestWindow(const String& url, bool sizer=true);
|
||||||
|
|
||||||
String content_type;
|
wxWebResponse out;
|
||||||
std::string text_out;
|
|
||||||
Image image_out;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DECLARE_EVENT_TABLE();
|
DECLARE_EVENT_TABLE();
|
||||||
|
|||||||
@@ -105,40 +105,24 @@ RealRect intersect(const RealRect& a, const RealRect& b) {
|
|||||||
RealPoint tl = piecewise_max(a.topLeft(), b.topLeft());
|
RealPoint tl = piecewise_max(a.topLeft(), b.topLeft());
|
||||||
RealPoint br = piecewise_min(a.bottomRight(), b.bottomRight());
|
RealPoint br = piecewise_min(a.bottomRight(), b.bottomRight());
|
||||||
return RealRect(tl, RealSize(br - tl));
|
return RealRect(tl, RealSize(br - tl));
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextViewer::drawSelection(RotatedDC& dc, const TextStyle& style, size_t sel_start, size_t sel_end) {
|
void TextViewer::drawSelection(RotatedDC& dc, const TextStyle& style, size_t sel_start, size_t sel_end) {
|
||||||
if (sel_start == sel_end) return;
|
if (sel_start == sel_end) return;
|
||||||
if (sel_end < sel_start) swap(sel_start, sel_end);
|
if (sel_end < sel_start) swap(sel_start, sel_end);
|
||||||
#ifdef __WXMSW__
|
dc.SetBrush(*wxBLACK_BRUSH);
|
||||||
dc.SetBrush(*wxWHITE_BRUSH);
|
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||||
dc.SetPen(*wxWHITE_PEN);
|
dc.SetLogicalFunction(wxINVERT);
|
||||||
dc.SetLogicalFunction(wxXOR);
|
|
||||||
#endif
|
|
||||||
RealRect prev_rect(0,0,0,0);
|
RealRect prev_rect(0,0,0,0);
|
||||||
FOR_EACH(l, lines) {
|
FOR_EACH(l, lines) {
|
||||||
RealRect rect = l.selectionRectangle(dc, sel_start, sel_end);
|
RealRect rect = l.selectionRectangle(dc, sel_start, sel_end);
|
||||||
if (rect.height > 0) {
|
if (rect.height > 0) dc.DrawRectangle(rect);
|
||||||
#ifdef __WXMSW__
|
|
||||||
dc.DrawRectangle(rect);
|
|
||||||
#else
|
|
||||||
dc.DrawInvertRectangle(rect);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
// compensate for overlap between lines
|
// compensate for overlap between lines
|
||||||
RealRect overlap = intersect(rect, prev_rect);
|
RealRect overlap = intersect(rect, prev_rect);
|
||||||
if (overlap.height > 0 && overlap.width > 0) {
|
if (overlap.height > 0 && overlap.width > 0) dc.DrawRectangle(overlap);
|
||||||
#ifdef __WXMSW__
|
|
||||||
dc.DrawRectangle(overlap);
|
|
||||||
#else
|
|
||||||
dc.DrawInvertRectangle(overlap);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
prev_rect = rect;
|
prev_rect = rect;
|
||||||
}
|
}
|
||||||
#ifdef __WXMSW__
|
dc.SetLogicalFunction(wxCOPY);
|
||||||
dc.SetLogicalFunction(wxCOPY);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RealRect TextViewer::Line::selectionRectangle(const Rotation& rot, size_t sel_start, size_t sel_end) {
|
RealRect TextViewer::Line::selectionRectangle(const Rotation& rot, size_t sel_start, size_t sel_end) {
|
||||||
|
|||||||
@@ -116,15 +116,14 @@ Bitmap ImageValueViewer::imagePlaceholder(const Rotation& rot, UInt w, UInt h, c
|
|||||||
}
|
}
|
||||||
// Draw text
|
// Draw text
|
||||||
if (editing) {
|
if (editing) {
|
||||||
// only when in editor mode
|
// only when in editor mode
|
||||||
String label = _LABEL_("load image");
|
|
||||||
for (UInt size = 12 ; size > 2 ; --size) {
|
for (UInt size = 12 ; size > 2 ; --size) {
|
||||||
dc.SetFont(wxFont(size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
dc.SetFont(wxFont(size, wxFONTFAMILY_SWISS, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL));
|
||||||
RealSize rs = dc.GetTextExtent(label);
|
RealSize rs = dc.GetTextExtent(_LABEL_("load image"));
|
||||||
if (rs.width <= w - 10 && rs.height < h - 10) {
|
if (rs.width <= w - 10 && rs.height < h - 10) {
|
||||||
// text fits
|
// text fits
|
||||||
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
RealPoint pos = align_in_rect(ALIGN_MIDDLE_CENTER, rs, rect);
|
||||||
dc.DrawText(label, pos, Color(255,255,255), 2, Color(0,0,0), 3); // stroked
|
dc.DrawText(_LABEL_("load image"), pos, Color(255,255,255), 2, Color(0,0,0), 3); // stroked
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,22 +90,6 @@ SCRIPT_FUNCTION(error) {
|
|||||||
return script_nil;
|
return script_nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(version_is_older) {
|
|
||||||
SCRIPT_PARAM_C(String, input);
|
|
||||||
SCRIPT_PARAM(String, than);
|
|
||||||
Version input_version = Version::fromString(input);
|
|
||||||
Version than_version = Version::fromString(than);
|
|
||||||
SCRIPT_RETURN(input_version < than_version);
|
|
||||||
}
|
|
||||||
|
|
||||||
SCRIPT_FUNCTION(exists_as_package) {
|
|
||||||
SCRIPT_PARAM_C(String, input);
|
|
||||||
Version version_out;
|
|
||||||
bool result = package_manager.installedVersion(input, version_out);
|
|
||||||
if (!result) return script_nil;
|
|
||||||
SCRIPT_RETURN(version_out.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
SCRIPT_FUNCTION(exists_in_package) {
|
SCRIPT_FUNCTION(exists_in_package) {
|
||||||
SCRIPT_PARAM_C(String, input);
|
SCRIPT_PARAM_C(String, input);
|
||||||
bool result = package_manager.existsInPackage(input);
|
bool result = package_manager.existsInPackage(input);
|
||||||
@@ -1034,8 +1018,6 @@ void init_script_basic_functions(Context& ctx) {
|
|||||||
ctx.setVariable(_("trace"), script_trace);
|
ctx.setVariable(_("trace"), script_trace);
|
||||||
ctx.setVariable(_("warning"), script_warning);
|
ctx.setVariable(_("warning"), script_warning);
|
||||||
ctx.setVariable(_("error"), script_error);
|
ctx.setVariable(_("error"), script_error);
|
||||||
ctx.setVariable(_("version_is_older"), script_version_is_older);
|
|
||||||
ctx.setVariable(_("exists_as_package"), script_exists_as_package);
|
|
||||||
ctx.setVariable(_("exists_in_package"), script_exists_in_package);
|
ctx.setVariable(_("exists_in_package"), script_exists_in_package);
|
||||||
// conversion
|
// conversion
|
||||||
ctx.setVariable(_("to_string"), script_to_string);
|
ctx.setVariable(_("to_string"), script_to_string);
|
||||||
|
|||||||
@@ -19,20 +19,17 @@
|
|||||||
#include <data/game.hpp>
|
#include <data/game.hpp>
|
||||||
#include <data/stylesheet.hpp>
|
#include <data/stylesheet.hpp>
|
||||||
#include <data/card.hpp>
|
#include <data/card.hpp>
|
||||||
#include <util/uid.hpp>
|
|
||||||
#include <util/error.hpp>
|
#include <util/error.hpp>
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : new_card
|
// ----------------------------------------------------------------------------- : new_card
|
||||||
|
|
||||||
SCRIPT_FUNCTION(new_card) {
|
SCRIPT_FUNCTION(new_card) {
|
||||||
SCRIPT_PARAM(GameP, game);
|
SCRIPT_PARAM(GameP, game);
|
||||||
ScriptValueP set_ = ctx.getVariableOpt(BOOST_PP_CAT(L, "set")); // this is just SCRIPT_OPTIONAL_PARAM_(Set*, set) but the macro fails
|
|
||||||
Set* set = set_ && set_ != script_nil ? from_script<Set*>(set_, BOOST_PP_CAT(L, "set")) : nullptr;
|
|
||||||
SCRIPT_OPTIONAL_PARAM_(bool, ignore_field_not_found);
|
SCRIPT_OPTIONAL_PARAM_(bool, ignore_field_not_found);
|
||||||
SCRIPT_OPTIONAL_PARAM_(CardP, copy_from);
|
// create a new card object
|
||||||
|
CardP new_card = make_intrusive<Card>(*game);
|
||||||
|
// iterate on the given key/value pairs
|
||||||
SCRIPT_PARAM(ScriptValueP, input);
|
SCRIPT_PARAM(ScriptValueP, input);
|
||||||
// create a new card object, or a copy
|
|
||||||
CardP new_card = copy_from ? make_intrusive<Card>(set, copy_from) : make_intrusive<Card>(*game);
|
|
||||||
// check for a stylesheet first, since other things depend on it
|
// check for a stylesheet first, since other things depend on it
|
||||||
ScriptValueP it = input->makeIterator();
|
ScriptValueP it = input->makeIterator();
|
||||||
ScriptValueP key;
|
ScriptValueP key;
|
||||||
@@ -41,7 +38,7 @@ SCRIPT_FUNCTION(new_card) {
|
|||||||
if (key == script_nil || value == script_nil) continue;
|
if (key == script_nil || value == script_nil) continue;
|
||||||
String key_name = key->toString();
|
String key_name = key->toString();
|
||||||
if (set_stylesheet_container(*game, new_card, value, key_name, ignore_field_not_found)) break;
|
if (set_stylesheet_container(*game, new_card, value, key_name, ignore_field_not_found)) break;
|
||||||
}
|
}
|
||||||
// set the rest of the key/value pairs
|
// set the rest of the key/value pairs
|
||||||
it = input->makeIterator();
|
it = input->makeIterator();
|
||||||
while (ScriptValueP value = it->next(&key)) {
|
while (ScriptValueP value = it->next(&key)) {
|
||||||
@@ -100,7 +97,7 @@ SCRIPT_FUNCTION(new_card) {
|
|||||||
else {
|
else {
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// if the game has a construction script, set the card context variable to be this card, run script
|
// if the game has a construction script, set the card context variable to be this card, run script
|
||||||
if (game->import_script) {
|
if (game->import_script) {
|
||||||
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
ScriptValueP ctx_card = ctx.getVariableOpt(SCRIPT_VAR_card);
|
||||||
@@ -136,7 +133,7 @@ SCRIPT_FUNCTION(new_card) {
|
|||||||
}
|
}
|
||||||
// restore old context card
|
// restore old context card
|
||||||
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
if (ctx_card) ctx.setVariable(SCRIPT_VAR_card, ctx_card);
|
||||||
}
|
}
|
||||||
SCRIPT_RETURN(new_card);
|
SCRIPT_RETURN(new_card);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,22 +166,11 @@ SCRIPT_FUNCTION(add_card_to_set) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
SCRIPT_RETURN(false);
|
SCRIPT_RETURN(false);
|
||||||
}
|
|
||||||
|
|
||||||
SCRIPT_FUNCTION(new_uid) {
|
|
||||||
SCRIPT_PARAM_C(Set*, set);
|
|
||||||
String uid = generate_uid();
|
|
||||||
for (int i = 0; i < 100; i++) {
|
|
||||||
if (set->card_uids.find(uid) == set->card_uids.end()) break;
|
|
||||||
uid = generate_uid();
|
|
||||||
}
|
|
||||||
SCRIPT_RETURN(uid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Init
|
// ----------------------------------------------------------------------------- : Init
|
||||||
|
|
||||||
void init_script_construction_functions(Context& ctx) {
|
void init_script_construction_functions(Context& ctx) {
|
||||||
ctx.setVariable(_("new_card"), script_new_card);
|
ctx.setVariable(_("new_card"), script_new_card);
|
||||||
ctx.setVariable(_("new_uid"), script_new_uid);
|
|
||||||
ctx.setVariable(_("add_card_to_set"), script_add_card_to_set);
|
ctx.setVariable(_("add_card_to_set"), script_add_card_to_set);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,9 +62,7 @@ inline static void set_container(Value* container, ScriptValueP& value, String k
|
|||||||
cvalue->value = value->toString();
|
cvalue->value = value->toString();
|
||||||
}
|
}
|
||||||
else if (PackageChoiceValue* pvalue = dynamic_cast<PackageChoiceValue*>(container)) {
|
else if (PackageChoiceValue* pvalue = dynamic_cast<PackageChoiceValue*>(container)) {
|
||||||
String package_name = value->toString();
|
pvalue->package_name = value->toString();
|
||||||
while (package_name.starts_with(_("/"))) package_name = package_name.substr(1);
|
|
||||||
pvalue->package_name = package_name;
|
|
||||||
}
|
}
|
||||||
else if (ColorValue* cvalue = dynamic_cast<ColorValue*>(container)) {
|
else if (ColorValue* cvalue = dynamic_cast<ColorValue*>(container)) {
|
||||||
cvalue->value = value->toColor();
|
cvalue->value = value->toColor();
|
||||||
@@ -96,10 +94,7 @@ inline static bool set_stylesheet_container(const Game& game, CardP& card, Scrip
|
|||||||
if (key_name == _("style") || key_name == _("stylesheet") || key_name == _("template")) {
|
if (key_name == _("style") || key_name == _("stylesheet") || key_name == _("template")) {
|
||||||
if (!trim(value->toString()).empty()) {
|
if (!trim(value->toString()).empty()) {
|
||||||
card->stylesheet = StyleSheet::byGameAndName(game, value->toString());
|
card->stylesheet = StyleSheet::byGameAndName(game, value->toString());
|
||||||
if (card->stylesheet) {
|
if (card->stylesheet) card->styling_data.init(card->stylesheet->styling_fields);
|
||||||
card->styling_data.init(card->stylesheet->styling_fields);
|
|
||||||
card->extraDataFor(*card->stylesheet).init(card->stylesheet->extra_card_fields);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -109,14 +104,7 @@ inline static bool set_stylesheet_container(const Game& game, CardP& card, Scrip
|
|||||||
inline static bool set_builtin_container(const Game& game, CardP& card, ScriptValueP& value, String key_name, bool ignore_field_not_found) {
|
inline static bool set_builtin_container(const Game& game, CardP& card, ScriptValueP& value, String key_name, bool ignore_field_not_found) {
|
||||||
// check if the given value is for a built-in field, if found set it and return true
|
// check if the given value is for a built-in field, if found set it and return true
|
||||||
key_name = unified_form(key_name);
|
key_name = unified_form(key_name);
|
||||||
if (key_name == _("style") || key_name == _("stylesheet") || key_name == _("template")) {
|
if (key_name == _("card_notes") || key_name == _("notes") || key_name == _("note")) {
|
||||||
return true; // we already took care of this
|
|
||||||
}
|
|
||||||
else if (key_name == _("style_version") || key_name == _("stylesheet_version") || key_name == _("template_version")) {
|
|
||||||
card->stylesheet_version = Version::fromString(value->toString());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else if (key_name == _("card_notes") || key_name == _("notes") || key_name == _("note")) {
|
|
||||||
card->notes = value->toString();
|
card->notes = value->toString();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -249,7 +237,7 @@ inline static bool cards_from_table(SetP& set, vector<String>& headers, std::vec
|
|||||||
// is this a new card?
|
// is this a new card?
|
||||||
if (contains(set->cards, card) || contains(cards_out, card)) {
|
if (contains(set->cards, card) || contains(cards_out, card)) {
|
||||||
// make copy
|
// make copy
|
||||||
card = make_intrusive<Card>(set.get(), card);
|
card = make_intrusive<Card>(*card);
|
||||||
}
|
}
|
||||||
cards_out.push_back(card);
|
cards_out.push_back(card);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -187,13 +187,6 @@ SCRIPT_FUNCTION_DEPENDENCIES(combined_editor) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return dependency_dummy;
|
return dependency_dummy;
|
||||||
}
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Values
|
|
||||||
|
|
||||||
SCRIPT_FUNCTION(is_default) {
|
|
||||||
SCRIPT_PARAM_C(ValueP,input);
|
|
||||||
SCRIPT_RETURN(input->isDefault());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Choice values
|
// ----------------------------------------------------------------------------- : Choice values
|
||||||
@@ -396,7 +389,6 @@ SCRIPT_FUNCTION(count_chosen) {
|
|||||||
void init_script_editor_functions(Context& ctx) {
|
void init_script_editor_functions(Context& ctx) {
|
||||||
ctx.setVariable(_("forward_editor"), script_combined_editor); // compatability
|
ctx.setVariable(_("forward_editor"), script_combined_editor); // compatability
|
||||||
ctx.setVariable(_("combined_editor"), script_combined_editor);
|
ctx.setVariable(_("combined_editor"), script_combined_editor);
|
||||||
ctx.setVariable(_("is_default"), script_is_default);
|
|
||||||
ctx.setVariable(_("primary_choice"), script_primary_choice);
|
ctx.setVariable(_("primary_choice"), script_primary_choice);
|
||||||
ctx.setVariable(_("chosen"), script_chosen);
|
ctx.setVariable(_("chosen"), script_chosen);
|
||||||
ctx.setVariable(_("count_chosen"), script_count_chosen);
|
ctx.setVariable(_("count_chosen"), script_count_chosen);
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
// ----------------------------------------------------------------------------- : Includes
|
// ----------------------------------------------------------------------------- : Includes
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <script/functions/english_exceptions.cpp>
|
|
||||||
#include <script/functions/functions.hpp>
|
#include <script/functions/functions.hpp>
|
||||||
#include <script/functions/util.hpp>
|
#include <script/functions/util.hpp>
|
||||||
#include <util/tagged_string.hpp>
|
#include <util/tagged_string.hpp>
|
||||||
@@ -153,22 +152,8 @@ SCRIPT_FUNCTION(english_number_ordinal) {
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Singular/plural
|
// ----------------------------------------------------------------------------- : Singular/plural
|
||||||
|
|
||||||
String english_singular(const String& str) {
|
String english_singular(const String& str) {
|
||||||
if (str.empty()) return String();
|
if (str.Lower() == _("plains")) return str;
|
||||||
|
|
||||||
String lower = str.Lower();
|
|
||||||
if (english_singular_exceptions.find(lower) != english_singular_exceptions.end()) {
|
|
||||||
if (isupper(str[0])) {
|
|
||||||
if (isupper(str[str.size()-1])) {
|
|
||||||
return english_singular_exceptions[lower].Upper();
|
|
||||||
} else {
|
|
||||||
return capitalize(english_singular_exceptions[lower]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return english_singular_exceptions[lower];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.size() > 3 && is_substr(str, str.size()-3, _("ies"))) {
|
if (str.size() > 3 && is_substr(str, str.size()-3, _("ies"))) {
|
||||||
return str.substr(0, str.size() - 3) + _("y");
|
return str.substr(0, str.size() - 3) + _("y");
|
||||||
} else if (str.size() > 3 && is_substr(str, str.size()-3, _("oes"))) {
|
} else if (str.size() > 3 && is_substr(str, str.size()-3, _("oes"))) {
|
||||||
@@ -189,22 +174,8 @@ String english_singular(const String& str) {
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
String english_plural(const String& str) {
|
String english_plural(const String& str) {
|
||||||
if (str.empty()) return String();
|
if (str.Lower() == _("plains")) return str;
|
||||||
|
|
||||||
String lower = str.Lower();
|
|
||||||
if (english_plural_exceptions.find(lower) != english_plural_exceptions.end()) {
|
|
||||||
if (isupper(str[0])) {
|
|
||||||
if (isupper(str[str.size()-1])) {
|
|
||||||
return english_plural_exceptions[lower].Upper();
|
|
||||||
} else {
|
|
||||||
return capitalize(english_plural_exceptions[lower]);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return english_plural_exceptions[lower];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (str.size() > 2) {
|
if (str.size() > 2) {
|
||||||
Char a = str.GetChar(str.size() - 2);
|
Char a = str.GetChar(str.size() - 2);
|
||||||
Char b = str.GetChar(str.size() - 1);
|
Char b = str.GetChar(str.size() - 1);
|
||||||
@@ -269,9 +240,7 @@ String process_english_hints(const String& str) {
|
|||||||
String ret; ret.reserve(str.size());
|
String ret; ret.reserve(str.size());
|
||||||
// have we seen a <hint-1/2>?
|
// have we seen a <hint-1/2>?
|
||||||
// 1 for singular, 2 for plural
|
// 1 for singular, 2 for plural
|
||||||
int singplur = 0;
|
int singplur = 0;
|
||||||
int sing_found = 0;
|
|
||||||
int plur_found = 0;
|
|
||||||
for (size_t i = 0 ; i < str.size() ; ) {
|
for (size_t i = 0 ; i < str.size() ; ) {
|
||||||
Char c = str.GetChar(i);
|
Char c = str.GetChar(i);
|
||||||
if (is_substr(str, i, _("<hint-"))) {
|
if (is_substr(str, i, _("<hint-"))) {
|
||||||
@@ -290,7 +259,7 @@ String process_english_hints(const String& str) {
|
|||||||
// a -> an, where the a originates from english_number_a(1)
|
// a -> an, where the a originates from english_number_a(1)
|
||||||
size_t after_end = skip_tag(str,after+1);
|
size_t after_end = skip_tag(str,after+1);
|
||||||
if (after_end == String::npos) {
|
if (after_end == String::npos) {
|
||||||
throw ScriptError(_("Incomplete </param> tag"));
|
throw Error(_("Incomplete </param> tag"));
|
||||||
}
|
}
|
||||||
if (after_end != String::npos && after_end + 1 < str.size()
|
if (after_end != String::npos && after_end + 1 < str.size()
|
||||||
&& isSpace(str.GetChar(after_end)) && is_vowel(str.GetChar(after_end+1))) {
|
&& isSpace(str.GetChar(after_end)) && is_vowel(str.GetChar(after_end+1))) {
|
||||||
@@ -315,31 +284,23 @@ String process_english_hints(const String& str) {
|
|||||||
}
|
}
|
||||||
ret.append(str,i,min(after,str.size())-i);
|
ret.append(str,i,min(after,str.size())-i);
|
||||||
i = after;
|
i = after;
|
||||||
} else if (is_substr(str, i, _("<singular>"))) {
|
} else if (is_substr(str, i, _("<singular>"))) {
|
||||||
sing_found++;
|
|
||||||
// singular -> keep, plural -> drop
|
// singular -> keep, plural -> drop
|
||||||
size_t start = skip_tag(str, i);
|
size_t start = skip_tag(str, i);
|
||||||
size_t end = match_close_tag(str, i);
|
size_t end = match_close_tag(str, start);
|
||||||
if (end == String::npos) {
|
if (singplur == 1 && end != String::npos) {
|
||||||
throw ScriptError(_("<singular> tag found without matching closing tag."));
|
|
||||||
}
|
|
||||||
else if (singplur == 1) {
|
|
||||||
ret += str.substr(start, end - start);
|
ret += str.substr(start, end - start);
|
||||||
singplur = 0;
|
|
||||||
}
|
}
|
||||||
|
singplur = 0;
|
||||||
i = skip_tag(str, end);
|
i = skip_tag(str, end);
|
||||||
} else if (is_substr(str, i, _("<plural>"))) {
|
} else if (is_substr(str, i, _("<plural>"))) {
|
||||||
plur_found++;
|
|
||||||
// singular -> drop, plural -> keep
|
// singular -> drop, plural -> keep
|
||||||
size_t start = skip_tag(str, i);
|
size_t start = skip_tag(str, i);
|
||||||
size_t end = match_close_tag(str, i);
|
size_t end = match_close_tag(str, start);
|
||||||
if (end == String::npos) {
|
if (singplur == 2 && end != String::npos) {
|
||||||
throw ScriptError(_("<plural> tag found without matching closing tag."));
|
|
||||||
}
|
|
||||||
else if (singplur == 2) {
|
|
||||||
ret += str.substr(start, end - start);
|
ret += str.substr(start, end - start);
|
||||||
singplur = 0;
|
|
||||||
}
|
}
|
||||||
|
singplur = 0;
|
||||||
i = skip_tag(str, end);
|
i = skip_tag(str, end);
|
||||||
} else if (c == _('(') && singplur) {
|
} else if (c == _('(') && singplur) {
|
||||||
// singular -> drop (...), plural -> keep it
|
// singular -> drop (...), plural -> keep it
|
||||||
@@ -362,12 +323,6 @@ String process_english_hints(const String& str) {
|
|||||||
ret += c;
|
ret += c;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (sing_found > plur_found) {
|
|
||||||
throw ScriptError(_("<singular> tag found without matching <plural> tag."));
|
|
||||||
}
|
|
||||||
else if (sing_found < plur_found) {
|
|
||||||
throw ScriptError(_("<plural> tag found without matching <singular> tag."));
|
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,787 +0,0 @@
|
|||||||
//+----------------------------------------------------------------------------+
|
|
||||||
//| Description: Magic Set Editor - Program to make card games |
|
|
||||||
//| Copyright: (C) Twan van Laarhoven and the other MSE developers |
|
|
||||||
//| License: GNU General Public License 2 or later (see file COPYING) |
|
|
||||||
//+----------------------------------------------------------------------------+
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Includes
|
|
||||||
|
|
||||||
#include <util/prec.hpp>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Maps
|
|
||||||
|
|
||||||
inline std::unordered_map<String, String> english_plural_exceptions {
|
|
||||||
{ "plains", "plains" }
|
|
||||||
, { "advisor", "advisors" }
|
|
||||||
, { "aetherborn", "aetherborn" }
|
|
||||||
, { "alien", "aliens" }
|
|
||||||
, { "ally", "allies" }
|
|
||||||
, { "angel", "angels" }
|
|
||||||
, { "antelope", "antelopes" }
|
|
||||||
, { "ape", "apes" }
|
|
||||||
, { "archer", "archers" }
|
|
||||||
, { "archon", "archons" }
|
|
||||||
, { "armadillo", "armadillos" }
|
|
||||||
, { "army", "armies" }
|
|
||||||
, { "artificer", "artificers" }
|
|
||||||
, { "assassin", "assassins" }
|
|
||||||
, { "assembly-worker", "assembly-workers" }
|
|
||||||
, { "astartes", "astartes" }
|
|
||||||
, { "atog", "atogs" }
|
|
||||||
, { "aurochs", "aurochs" }
|
|
||||||
, { "avatar", "avatars" }
|
|
||||||
, { "azra", "azra" }
|
|
||||||
, { "badger", "badgers" }
|
|
||||||
, { "balloon", "balloons" }
|
|
||||||
, { "barbarian", "barbarians" }
|
|
||||||
, { "bard", "bards" }
|
|
||||||
, { "basilisk", "basilisks" }
|
|
||||||
, { "bat", "bats" }
|
|
||||||
, { "bear", "bears" }
|
|
||||||
, { "beast", "beasts" }
|
|
||||||
, { "beaver", "beavers" }
|
|
||||||
, { "beeble", "beebles" }
|
|
||||||
, { "beholder", "beholders" }
|
|
||||||
, { "berserker", "berserkers" }
|
|
||||||
, { "bird", "birds" }
|
|
||||||
, { "bison", "bison" }
|
|
||||||
, { "blinkmoth", "blinkmoths" }
|
|
||||||
, { "boar", "boars" }
|
|
||||||
, { "bringer", "bringers" }
|
|
||||||
, { "brushwagg", "brushwaggs" }
|
|
||||||
, { "c'tan", "c'tan" }
|
|
||||||
, { "camarid", "camarids" }
|
|
||||||
, { "camel", "camels" }
|
|
||||||
, { "capybara", "capybaras" }
|
|
||||||
, { "caribou", "caribou" }
|
|
||||||
, { "carrier", "carriers" }
|
|
||||||
, { "cat", "cats" }
|
|
||||||
, { "centaur", "centaurs" }
|
|
||||||
, { "child", "children" }
|
|
||||||
, { "chimera", "chimeras" }
|
|
||||||
, { "citizen", "citizens" }
|
|
||||||
, { "cleric", "clerics" }
|
|
||||||
, { "clown", "clowns" }
|
|
||||||
, { "cockatrice", "cockatrices" }
|
|
||||||
, { "construct", "constructs" }
|
|
||||||
, { "coward", "cowards" }
|
|
||||||
, { "coyote", "coyotes" }
|
|
||||||
, { "crab", "crabs" }
|
|
||||||
, { "crocodile", "crocodiles" }
|
|
||||||
, { "custodes", "custodes" }
|
|
||||||
, { "cyberman", "cybermen" }
|
|
||||||
, { "cyclops", "cyclopes" }
|
|
||||||
, { "dalek", "daleks" }
|
|
||||||
, { "dauthi", "dauthi" }
|
|
||||||
, { "demigod", "demigods" }
|
|
||||||
, { "demon", "demons" }
|
|
||||||
, { "deserter", "deserters" }
|
|
||||||
, { "detective", "detectives" }
|
|
||||||
, { "devil", "devils" }
|
|
||||||
, { "dinosaur", "dinosaurs" }
|
|
||||||
, { "djinn", "djinn" }
|
|
||||||
, { "doctor", "doctors" }
|
|
||||||
, { "dog", "dogs" }
|
|
||||||
, { "dragon", "dragons" }
|
|
||||||
, { "drake", "drakes" }
|
|
||||||
, { "dreadnought", "dreadnoughts" }
|
|
||||||
, { "drix", "drix" }
|
|
||||||
, { "drone", "drones" }
|
|
||||||
, { "druid", "druids" }
|
|
||||||
, { "dryad", "dryads" }
|
|
||||||
, { "dwarf", "dwarves" }
|
|
||||||
, { "echidna", "echdnas" }
|
|
||||||
, { "efreet", "efreets" }
|
|
||||||
, { "egg", "eggs" }
|
|
||||||
, { "elder", "elders" }
|
|
||||||
, { "eldrazi", "eldrazi" }
|
|
||||||
, { "elemental", "elementals" }
|
|
||||||
, { "elephant", "elephants" }
|
|
||||||
, { "elf", "elves" }
|
|
||||||
, { "elk", "elk" }
|
|
||||||
, { "employee", "employees" }
|
|
||||||
, { "eternal", "eternals" }
|
|
||||||
, { "eye", "eyes" }
|
|
||||||
, { "faerie", "faeries" }
|
|
||||||
, { "ferret", "ferrets" }
|
|
||||||
, { "fish", "fish" }
|
|
||||||
, { "flagbearer", "flagbearers" }
|
|
||||||
, { "fox", "foxes" }
|
|
||||||
, { "fractal", "fractals" }
|
|
||||||
, { "frog", "frogs" }
|
|
||||||
, { "fungus", "fungi" }
|
|
||||||
, { "gamer", "gamers" }
|
|
||||||
, { "gamma", "gamma mutates" }
|
|
||||||
, { "gargoyle", "gargoyles" }
|
|
||||||
, { "germ", "germs" }
|
|
||||||
, { "giant", "giants" }
|
|
||||||
, { "giraffe", "giraffes" }
|
|
||||||
, { "gith", "gith" }
|
|
||||||
, { "glimmer", "glimmers" }
|
|
||||||
, { "gnoll", "gnolls" }
|
|
||||||
, { "gnome", "gnomes" }
|
|
||||||
, { "goat", "goats" }
|
|
||||||
, { "goblin", "goblins" }
|
|
||||||
, { "god", "gods" }
|
|
||||||
, { "golem", "golems" }
|
|
||||||
, { "gorgon", "gorgons" }
|
|
||||||
, { "graveborn", "graveborn" }
|
|
||||||
, { "gremlin", "gremlins" }
|
|
||||||
, { "griffin", "griffins" }
|
|
||||||
, { "guest", "guests" }
|
|
||||||
, { "hag", "hags" }
|
|
||||||
, { "halfling", "halflings" }
|
|
||||||
, { "hamster", "hamsters" }
|
|
||||||
, { "harpy", "harpies" }
|
|
||||||
, { "hedgehog", "hedgehogs" }
|
|
||||||
, { "hellion", "hellions" }
|
|
||||||
, { "hero", "heroes" }
|
|
||||||
, { "hippo", "hippos" }
|
|
||||||
, { "hippogriff", "hippogriffs" }
|
|
||||||
, { "homarid", "homarids" }
|
|
||||||
, { "homunculus", "homunculi" }
|
|
||||||
, { "horror", "horrors" }
|
|
||||||
, { "horse", "horses" }
|
|
||||||
, { "human", "humans" }
|
|
||||||
, { "hydra", "hydras" }
|
|
||||||
, { "hyena", "hyenas" }
|
|
||||||
, { "illusion", "illusions" }
|
|
||||||
, { "imp", "imps" }
|
|
||||||
, { "incarnation", "incarnations" }
|
|
||||||
, { "inkling", "inklings" }
|
|
||||||
, { "inquisitor", "inquisitors" }
|
|
||||||
, { "insect", "insects" }
|
|
||||||
, { "jackal", "jackals" }
|
|
||||||
, { "jellyfish", "jellyfish" }
|
|
||||||
, { "juggernaut", "juggernauts" }
|
|
||||||
, { "kangaroo", "kangaroos" }
|
|
||||||
, { "kavu", "kavu" }
|
|
||||||
, { "kirin", "kirin" }
|
|
||||||
, { "kithkin", "kithkin" }
|
|
||||||
, { "knight", "knights" }
|
|
||||||
, { "kobold", "kobolds" }
|
|
||||||
, { "kor", "kor" }
|
|
||||||
, { "kraken", "krakens" }
|
|
||||||
, { "lamia", "lamia" }
|
|
||||||
, { "lammasu", "lammasu" }
|
|
||||||
, { "leech", "leeches" }
|
|
||||||
, { "lemur", "lemurs" }
|
|
||||||
, { "leviathan", "leviathans" }
|
|
||||||
, { "lhurgoyf", "lhurgoyfs" }
|
|
||||||
, { "licid", "licids" }
|
|
||||||
, { "lizard", "lizards" }
|
|
||||||
, { "llama", "llamas" }
|
|
||||||
, { "lobster", "lobsters" }
|
|
||||||
, { "manticore", "manticores" }
|
|
||||||
, { "masticore", "masticores" }
|
|
||||||
, { "mercenary", "mercenaries" }
|
|
||||||
, { "merfolk", "merfolk" }
|
|
||||||
, { "metathran", "metathran" }
|
|
||||||
, { "minion", "minions" }
|
|
||||||
, { "minotaur", "minotaurs" }
|
|
||||||
, { "mite", "mites" }
|
|
||||||
, { "mole", "moles" }
|
|
||||||
, { "monger", "mongers" }
|
|
||||||
, { "mongoose", "mongooses" }
|
|
||||||
, { "monk", "monks" }
|
|
||||||
, { "monkey", "monkeys" }
|
|
||||||
, { "moogle", "moogles" }
|
|
||||||
, { "moonfolk", "moonfolk" }
|
|
||||||
, { "mount", "mounts" }
|
|
||||||
, { "mouse", "mice" }
|
|
||||||
, { "mutant", "mutants" }
|
|
||||||
, { "myr", "myr" }
|
|
||||||
, { "mystic", "mystics" }
|
|
||||||
, { "nautilus", "nautiluses" }
|
|
||||||
, { "necron", "necrons" }
|
|
||||||
, { "nephilim", "nephilim" }
|
|
||||||
, { "nightmare", "nightmares" }
|
|
||||||
, { "nightstalker", "nightstalkers" }
|
|
||||||
, { "ninja", "ninja" }
|
|
||||||
, { "noble", "nobles" }
|
|
||||||
, { "noggle", "noggles" }
|
|
||||||
, { "nomad", "nomads" }
|
|
||||||
, { "nymph", "nymphs" }
|
|
||||||
, { "octopus", "octopuses" }
|
|
||||||
, { "ogre", "ogres" }
|
|
||||||
, { "ooze", "oozes" }
|
|
||||||
, { "orb", "orbs" }
|
|
||||||
, { "orc", "orcs" }
|
|
||||||
, { "orgg", "orggs" }
|
|
||||||
, { "otter", "otters" }
|
|
||||||
, { "ouphe", "ouphes" }
|
|
||||||
, { "ox", "oxen" }
|
|
||||||
, { "oyster", "oysters" }
|
|
||||||
, { "pangolin", "pangolins" }
|
|
||||||
, { "peasant", "peasants" }
|
|
||||||
, { "pegasus", "pegasi" }
|
|
||||||
, { "pentavite", "pentavites" }
|
|
||||||
, { "performer", "performers" }
|
|
||||||
, { "pest", "pests" }
|
|
||||||
, { "phelddagrif", "phelddagrifs" }
|
|
||||||
, { "phoenix", "phoenixes" }
|
|
||||||
, { "phyrexian", "phyrexians" }
|
|
||||||
, { "pilot", "pilots" }
|
|
||||||
, { "pincher", "pinchers" }
|
|
||||||
, { "pirate", "pirates" }
|
|
||||||
, { "plant", "plants" }
|
|
||||||
, { "platypus", "platypuses" }
|
|
||||||
, { "porcupine", "porcupines" }
|
|
||||||
, { "possum", "possums" }
|
|
||||||
, { "praetor", "praetors" }
|
|
||||||
, { "primarch", "primarchs" }
|
|
||||||
, { "prism", "prisms" }
|
|
||||||
, { "processor", "processors" }
|
|
||||||
, { "qu", "qu" }
|
|
||||||
, { "rabbit", "rabbits" }
|
|
||||||
, { "raccoon", "raccoons" }
|
|
||||||
, { "ranger", "rangers" }
|
|
||||||
, { "rat", "rats" }
|
|
||||||
, { "rebel", "rebels" }
|
|
||||||
, { "reflection", "reflections" }
|
|
||||||
, { "rhino", "rhinos" }
|
|
||||||
, { "rigger", "riggers" }
|
|
||||||
, { "robot", "robots" }
|
|
||||||
, { "rogue", "rogues" }
|
|
||||||
, { "sable", "sables" }
|
|
||||||
, { "salamander", "salamanders" }
|
|
||||||
, { "samurai", "samurai" }
|
|
||||||
, { "sand", "sands" }
|
|
||||||
, { "saproling", "saprolings" }
|
|
||||||
, { "satyr", "satyrs" }
|
|
||||||
, { "scarecrow", "scarecrows" }
|
|
||||||
, { "scientist", "scientists" }
|
|
||||||
, { "scion", "scions" }
|
|
||||||
, { "scorpion", "scorpions" }
|
|
||||||
, { "scout", "scouts" }
|
|
||||||
, { "sculpture", "sculptures" }
|
|
||||||
, { "seal", "seals" }
|
|
||||||
, { "serf", "serfs" }
|
|
||||||
, { "serpent", "serpents" }
|
|
||||||
, { "servo", "servos" }
|
|
||||||
, { "shade", "shades" }
|
|
||||||
, { "shaman", "shamans" }
|
|
||||||
, { "shapeshifter", "shapeshifters" }
|
|
||||||
, { "shark", "sharks" }
|
|
||||||
, { "sheep", "sheep" }
|
|
||||||
, { "siren", "sirens" }
|
|
||||||
, { "skeleton", "skeletons" }
|
|
||||||
, { "skrull", "skrulls" }
|
|
||||||
, { "skunk", "skunks" }
|
|
||||||
, { "slith", "slith" }
|
|
||||||
, { "sliver", "slivers" }
|
|
||||||
, { "sloth", "sloths" }
|
|
||||||
, { "slug", "slugs" }
|
|
||||||
, { "snail", "snails" }
|
|
||||||
, { "snake", "snakes" }
|
|
||||||
, { "soldier", "soldiers" }
|
|
||||||
, { "soltari", "soltari" }
|
|
||||||
, { "sorcerer", "sorcerers" }
|
|
||||||
, { "spawn", "spawns" }
|
|
||||||
, { "specter", "specters" }
|
|
||||||
, { "spellshaper", "spellshapers" }
|
|
||||||
, { "sphinx", "sphinxes" }
|
|
||||||
, { "spider", "spiders" }
|
|
||||||
, { "spike", "spikes" }
|
|
||||||
, { "spirit", "spirits" }
|
|
||||||
, { "splinter", "splinters" }
|
|
||||||
, { "sponge", "sponges" }
|
|
||||||
, { "spy", "spies" }
|
|
||||||
, { "squid", "squids" }
|
|
||||||
, { "squirrel", "squirrels" }
|
|
||||||
, { "starfish", "starfish" }
|
|
||||||
, { "surrakar", "surrakar" }
|
|
||||||
, { "survivor", "survivors" }
|
|
||||||
, { "symbiote", "symbiotes" }
|
|
||||||
, { "synth", "synths" }
|
|
||||||
, { "tentacle", "tentacles" }
|
|
||||||
, { "tetravite", "tetravites" }
|
|
||||||
, { "thalakos", "thalakos" }
|
|
||||||
, { "thopter", "thopters" }
|
|
||||||
, { "thrull", "thrulls" }
|
|
||||||
, { "tiefling", "tieflings" }
|
|
||||||
, { "time lord", "time lords" }
|
|
||||||
, { "toy", "toys" }
|
|
||||||
, { "treefolk", "treefolk" }
|
|
||||||
, { "trilobite", "trilobites" }
|
|
||||||
, { "triskelavite", "triskelavites" }
|
|
||||||
, { "troll", "trolls" }
|
|
||||||
, { "turtle", "turtles" }
|
|
||||||
, { "tyranid", "tyranids" }
|
|
||||||
, { "unicorn", "unicorns" }
|
|
||||||
, { "utrom", "utrom" }
|
|
||||||
, { "vampire", "vampires" }
|
|
||||||
, { "varmint", "varmints" }
|
|
||||||
, { "vedalken", "vedalken" }
|
|
||||||
, { "villain", "villains" }
|
|
||||||
, { "volver", "volvers" }
|
|
||||||
, { "wall", "walls" }
|
|
||||||
, { "walrus", "walruses" }
|
|
||||||
, { "warlock", "warlocks" }
|
|
||||||
, { "warrior", "warriors" }
|
|
||||||
, { "weasel", "weasels" }
|
|
||||||
, { "weird", "weirds" }
|
|
||||||
, { "werewolf", "werewolves" }
|
|
||||||
, { "whale", "whales" }
|
|
||||||
, { "wizard", "wizards" }
|
|
||||||
, { "wolf", "wolves" }
|
|
||||||
, { "wolverine", "wolverines" }
|
|
||||||
, { "wombat", "wombats" }
|
|
||||||
, { "worm", "worms" }
|
|
||||||
, { "wraith", "wraiths" }
|
|
||||||
, { "wurm", "wurms" }
|
|
||||||
, { "yeti", "yeti" }
|
|
||||||
, { "zombie", "zombies" }
|
|
||||||
, { "zubera", "zubera" }
|
|
||||||
, { "alicorn", "alicorns" }
|
|
||||||
, { "armored", "armored" }
|
|
||||||
, { "art", "arts" }
|
|
||||||
, { "artist", "artists" }
|
|
||||||
, { "athlete", "athletes" }
|
|
||||||
, { "attendee", "attendees" }
|
|
||||||
, { "autobot", "autobots" }
|
|
||||||
, { "aven", "aven" }
|
|
||||||
, { "boxer", "boxers" }
|
|
||||||
, { "brainiac", "brainiacs" }
|
|
||||||
, { "bureaucrat", "bureaucrats" }
|
|
||||||
, { "chameleon", "chameleons" }
|
|
||||||
, { "champion", "champions" }
|
|
||||||
, { "chef", "chefs" }
|
|
||||||
, { "chicken", "chickens" }
|
|
||||||
, { "clamfolk", "clamfolk" }
|
|
||||||
, { "cow", "cows" }
|
|
||||||
, { "cyborg", "cyborgs" }
|
|
||||||
, { "deer", "deer" }
|
|
||||||
, { "designer", "designers" }
|
|
||||||
, { "die", "dice" }
|
|
||||||
, { "donkey", "donkeys" }
|
|
||||||
, { "elemental?", "elementals?" }
|
|
||||||
, { "elves", "elves" }
|
|
||||||
, { "expansion-symbol", "expansion-symbols" }
|
|
||||||
, { "fan", "fans" }
|
|
||||||
, { "fighter", "fighters" }
|
|
||||||
, { "glass", "glass" }
|
|
||||||
, { "gorilla", "gorillas" }
|
|
||||||
, { "grandchild", "grandchildren" }
|
|
||||||
, { "gus", "gus" }
|
|
||||||
, { "half", "halves" }
|
|
||||||
, { "hatificer", "hatificers" }
|
|
||||||
, { "hawk", "hawks" }
|
|
||||||
, { "head", "heads" }
|
|
||||||
, { "human?", "humans?" }
|
|
||||||
, { "jaguar", "jaguars" }
|
|
||||||
, { "judge", "judges" }
|
|
||||||
, { "killbot", "killbots" }
|
|
||||||
, { "lady of proper etiquette", "ladies of proper etiquette" }
|
|
||||||
, { "locus", "loci" }
|
|
||||||
, { "mammoth", "mammoths" }
|
|
||||||
, { "mime", "mimes" }
|
|
||||||
, { "mummy", "mummies" }
|
|
||||||
, { "paratrooper", "paratroopers" }
|
|
||||||
, { "penguin", "penguins" }
|
|
||||||
, { "pony", "ponies" }
|
|
||||||
, { "present", "presents" }
|
|
||||||
, { "reveler", "revelers" }
|
|
||||||
, { "ship", "ships" }
|
|
||||||
, { "sketch", "sketches" }
|
|
||||||
, { "spuzzem", "spuzzem" }
|
|
||||||
, { "spy", "spies" }
|
|
||||||
, { "stained", "stained" }
|
|
||||||
, { "teddy", "teddies" }
|
|
||||||
, { "the biggest, baddest, nastiest, scariest creature you'll ever see", "the biggest, baddest, nastiest, scariest creatures you'll ever see" }
|
|
||||||
, { "townsfolk", "townsfolk" }
|
|
||||||
, { "tree", "trees" }
|
|
||||||
, { "vampyre", "vampyres" }
|
|
||||||
, { "waiter", "waiters" }
|
|
||||||
, { "windmill", "windmills" }
|
|
||||||
, { "wrestler", "wrestlers" }
|
|
||||||
, { "zonian", "zonians" }
|
|
||||||
};
|
|
||||||
|
|
||||||
inline std::unordered_map<wxString, wxString> english_singular_exceptions {
|
|
||||||
{ "plains", "plains" }
|
|
||||||
, { "advisors", "advisor" }
|
|
||||||
, { "aetherborn", "aetherborn" }
|
|
||||||
, { "aliens", "alien" }
|
|
||||||
, { "allies", "ally" }
|
|
||||||
, { "angels", "angel" }
|
|
||||||
, { "antelopes", "antelope" }
|
|
||||||
, { "apes", "ape" }
|
|
||||||
, { "archers", "archer" }
|
|
||||||
, { "archons", "archon" }
|
|
||||||
, { "armadillos", "armadillo" }
|
|
||||||
, { "armies", "army" }
|
|
||||||
, { "artificers", "artificer" }
|
|
||||||
, { "assassins", "assassin" }
|
|
||||||
, { "assembly-workers", "assembly-worker" }
|
|
||||||
, { "astartes", "astartes" }
|
|
||||||
, { "atogs", "atog" }
|
|
||||||
, { "aurochs", "aurochs" }
|
|
||||||
, { "avatars", "avatar" }
|
|
||||||
, { "azra", "azra" }
|
|
||||||
, { "badgers", "badger" }
|
|
||||||
, { "balloons", "balloon" }
|
|
||||||
, { "barbarians", "barbarian" }
|
|
||||||
, { "bards", "bard" }
|
|
||||||
, { "basilisks", "basilisk" }
|
|
||||||
, { "bats", "bat" }
|
|
||||||
, { "bears", "bear" }
|
|
||||||
, { "beasts", "beast" }
|
|
||||||
, { "beavers", "beaver" }
|
|
||||||
, { "beebles", "beeble" }
|
|
||||||
, { "beholders", "beholder" }
|
|
||||||
, { "berserkers", "berserker" }
|
|
||||||
, { "birds", "bird" }
|
|
||||||
, { "bison", "bison" }
|
|
||||||
, { "blinkmoths", "blinkmoth" }
|
|
||||||
, { "boars", "boar" }
|
|
||||||
, { "bringers", "bringer" }
|
|
||||||
, { "brushwaggs", "brushwagg" }
|
|
||||||
, { "c'tan", "c'tan" }
|
|
||||||
, { "camarids", "camarid" }
|
|
||||||
, { "camels", "camel" }
|
|
||||||
, { "capybaras", "capybara" }
|
|
||||||
, { "caribou", "caribou" }
|
|
||||||
, { "carriers", "carrier" }
|
|
||||||
, { "cats", "cat" }
|
|
||||||
, { "centaurs", "centaur" }
|
|
||||||
, { "children", "child" }
|
|
||||||
, { "chimeras", "chimera" }
|
|
||||||
, { "citizens", "citizen" }
|
|
||||||
, { "clerics", "cleric" }
|
|
||||||
, { "clowns", "clown" }
|
|
||||||
, { "cockatrices", "cockatrice" }
|
|
||||||
, { "constructs", "construct" }
|
|
||||||
, { "cowards", "coward" }
|
|
||||||
, { "coyotes", "coyote" }
|
|
||||||
, { "crabs", "crab" }
|
|
||||||
, { "crocodiles", "crocodile" }
|
|
||||||
, { "custodes", "custodes" }
|
|
||||||
, { "cybermen", "cyberman" }
|
|
||||||
, { "cyclopes", "cyclops" }
|
|
||||||
, { "daleks", "dalek" }
|
|
||||||
, { "dauthi", "dauthi" }
|
|
||||||
, { "demigods", "demigod" }
|
|
||||||
, { "demons", "demon" }
|
|
||||||
, { "deserters", "deserter" }
|
|
||||||
, { "detectives", "detective" }
|
|
||||||
, { "devils", "devil" }
|
|
||||||
, { "dinosaurs", "dinosaur" }
|
|
||||||
, { "djinn", "djinn" }
|
|
||||||
, { "doctors", "doctor" }
|
|
||||||
, { "dogs", "dog" }
|
|
||||||
, { "dragons", "dragon" }
|
|
||||||
, { "drakes", "drake" }
|
|
||||||
, { "dreadnoughts", "dreadnought" }
|
|
||||||
, { "drix", "drix" }
|
|
||||||
, { "drones", "drone" }
|
|
||||||
, { "druids", "druid" }
|
|
||||||
, { "dryads", "dryad" }
|
|
||||||
, { "dwarves", "dwarf" }
|
|
||||||
, { "echdnas", "echidna" }
|
|
||||||
, { "efreets", "efreet" }
|
|
||||||
, { "eggs", "egg" }
|
|
||||||
, { "elders", "elder" }
|
|
||||||
, { "eldrazi", "eldrazi" }
|
|
||||||
, { "elementals", "elemental" }
|
|
||||||
, { "elephants", "elephant" }
|
|
||||||
, { "elves", "elf" }
|
|
||||||
, { "elk", "elk" }
|
|
||||||
, { "employees", "employee" }
|
|
||||||
, { "eternals", "eternal" }
|
|
||||||
, { "eyes", "eye" }
|
|
||||||
, { "faeries", "faerie" }
|
|
||||||
, { "ferrets", "ferret" }
|
|
||||||
, { "fish", "fish" }
|
|
||||||
, { "flagbearers", "flagbearer" }
|
|
||||||
, { "foxes", "fox" }
|
|
||||||
, { "fractals", "fractal" }
|
|
||||||
, { "frogs", "frog" }
|
|
||||||
, { "fungi", "fungus" }
|
|
||||||
, { "gamers", "gamer" }
|
|
||||||
, { "gamma mutates", "gamma" }
|
|
||||||
, { "gargoyles", "gargoyle" }
|
|
||||||
, { "germs", "germ" }
|
|
||||||
, { "giants", "giant" }
|
|
||||||
, { "giraffes", "giraffe" }
|
|
||||||
, { "gith", "gith" }
|
|
||||||
, { "glimmers", "glimmer" }
|
|
||||||
, { "gnolls", "gnoll" }
|
|
||||||
, { "gnomes", "gnome" }
|
|
||||||
, { "goats", "goat" }
|
|
||||||
, { "goblins", "goblin" }
|
|
||||||
, { "gods", "god" }
|
|
||||||
, { "golems", "golem" }
|
|
||||||
, { "gorgons", "gorgon" }
|
|
||||||
, { "graveborn", "graveborn" }
|
|
||||||
, { "gremlins", "gremlin" }
|
|
||||||
, { "griffins", "griffin" }
|
|
||||||
, { "guests", "guest" }
|
|
||||||
, { "hags", "hag" }
|
|
||||||
, { "halflings", "halfling" }
|
|
||||||
, { "hamsters", "hamster" }
|
|
||||||
, { "harpies", "harpy" }
|
|
||||||
, { "hedgehogs", "hedgehog" }
|
|
||||||
, { "hellions", "hellion" }
|
|
||||||
, { "heroes", "hero" }
|
|
||||||
, { "hippos", "hippo" }
|
|
||||||
, { "hippogriffs", "hippogriff" }
|
|
||||||
, { "homarids", "homarid" }
|
|
||||||
, { "homunculi", "homunculus" }
|
|
||||||
, { "horrors", "horror" }
|
|
||||||
, { "horses", "horse" }
|
|
||||||
, { "humans", "human" }
|
|
||||||
, { "hydras", "hydra" }
|
|
||||||
, { "hyenas", "hyena" }
|
|
||||||
, { "illusions", "illusion" }
|
|
||||||
, { "imps", "imp" }
|
|
||||||
, { "incarnations", "incarnation" }
|
|
||||||
, { "inklings", "inkling" }
|
|
||||||
, { "inquisitors", "inquisitor" }
|
|
||||||
, { "insects", "insect" }
|
|
||||||
, { "jackals", "jackal" }
|
|
||||||
, { "jellyfish", "jellyfish" }
|
|
||||||
, { "juggernauts", "juggernaut" }
|
|
||||||
, { "kangaroos", "kangaroo" }
|
|
||||||
, { "kavu", "kavu" }
|
|
||||||
, { "kirin", "kirin" }
|
|
||||||
, { "kithkin", "kithkin" }
|
|
||||||
, { "knights", "knight" }
|
|
||||||
, { "kobolds", "kobold" }
|
|
||||||
, { "kor", "kor" }
|
|
||||||
, { "krakens", "kraken" }
|
|
||||||
, { "lamia", "lamia" }
|
|
||||||
, { "lammasu", "lammasu" }
|
|
||||||
, { "leeches", "leech" }
|
|
||||||
, { "lemurs", "lemur" }
|
|
||||||
, { "leviathans", "leviathan" }
|
|
||||||
, { "lhurgoyfs", "lhurgoyf" }
|
|
||||||
, { "licids", "licid" }
|
|
||||||
, { "lizards", "lizard" }
|
|
||||||
, { "llamas", "llama" }
|
|
||||||
, { "lobsters", "lobster" }
|
|
||||||
, { "manticores", "manticore" }
|
|
||||||
, { "masticores", "masticore" }
|
|
||||||
, { "mercenaries", "mercenary" }
|
|
||||||
, { "merfolk", "merfolk" }
|
|
||||||
, { "metathran", "metathran" }
|
|
||||||
, { "minions", "minion" }
|
|
||||||
, { "minotaurs", "minotaur" }
|
|
||||||
, { "mites", "mite" }
|
|
||||||
, { "moles", "mole" }
|
|
||||||
, { "mongers", "monger" }
|
|
||||||
, { "mongooses", "mongoose" }
|
|
||||||
, { "monks", "monk" }
|
|
||||||
, { "monkeys", "monkey" }
|
|
||||||
, { "moogles", "moogle" }
|
|
||||||
, { "moonfolk", "moonfolk" }
|
|
||||||
, { "mounts", "mount" }
|
|
||||||
, { "mice", "mouse" }
|
|
||||||
, { "mutants", "mutant" }
|
|
||||||
, { "myr", "myr" }
|
|
||||||
, { "mystics", "mystic" }
|
|
||||||
, { "nautiluses", "nautilus" }
|
|
||||||
, { "necrons", "necron" }
|
|
||||||
, { "nephilim", "nephilim" }
|
|
||||||
, { "nightmares", "nightmare" }
|
|
||||||
, { "nightstalkers", "nightstalker" }
|
|
||||||
, { "ninja", "ninja" }
|
|
||||||
, { "nobles", "noble" }
|
|
||||||
, { "noggles", "noggle" }
|
|
||||||
, { "nomads", "nomad" }
|
|
||||||
, { "nymphs", "nymph" }
|
|
||||||
, { "octopuses", "octopus" }
|
|
||||||
, { "ogres", "ogre" }
|
|
||||||
, { "oozes", "ooze" }
|
|
||||||
, { "orbs", "orb" }
|
|
||||||
, { "orcs", "orc" }
|
|
||||||
, { "orggs", "orgg" }
|
|
||||||
, { "otters", "otter" }
|
|
||||||
, { "ouphes", "ouphe" }
|
|
||||||
, { "oxen", "ox" }
|
|
||||||
, { "oysters", "oyster" }
|
|
||||||
, { "pangolins", "pangolin" }
|
|
||||||
, { "peasants", "peasant" }
|
|
||||||
, { "pegasi", "pegasus" }
|
|
||||||
, { "pentavites", "pentavite" }
|
|
||||||
, { "performers", "performer" }
|
|
||||||
, { "pests", "pest" }
|
|
||||||
, { "phelddagrifs", "phelddagrif" }
|
|
||||||
, { "phoenixes", "phoenix" }
|
|
||||||
, { "phyrexians", "phyrexian" }
|
|
||||||
, { "pilots", "pilot" }
|
|
||||||
, { "pinchers", "pincher" }
|
|
||||||
, { "pirates", "pirate" }
|
|
||||||
, { "plants", "plant" }
|
|
||||||
, { "platypuses", "platypus" }
|
|
||||||
, { "porcupines", "porcupine" }
|
|
||||||
, { "possums", "possum" }
|
|
||||||
, { "praetors", "praetor" }
|
|
||||||
, { "primarchs", "primarch" }
|
|
||||||
, { "prisms", "prism" }
|
|
||||||
, { "processors", "processor" }
|
|
||||||
, { "qu", "qu" }
|
|
||||||
, { "rabbits", "rabbit" }
|
|
||||||
, { "raccoons", "raccoon" }
|
|
||||||
, { "rangers", "ranger" }
|
|
||||||
, { "rats", "rat" }
|
|
||||||
, { "rebels", "rebel" }
|
|
||||||
, { "reflections", "reflection" }
|
|
||||||
, { "rhinos", "rhino" }
|
|
||||||
, { "riggers", "rigger" }
|
|
||||||
, { "robots", "robot" }
|
|
||||||
, { "rogues", "rogue" }
|
|
||||||
, { "sables", "sable" }
|
|
||||||
, { "salamanders", "salamander" }
|
|
||||||
, { "samurai", "samurai" }
|
|
||||||
, { "sands", "sand" }
|
|
||||||
, { "saprolings", "saproling" }
|
|
||||||
, { "satyrs", "satyr" }
|
|
||||||
, { "scarecrows", "scarecrow" }
|
|
||||||
, { "scientists", "scientist" }
|
|
||||||
, { "scions", "scion" }
|
|
||||||
, { "scorpions", "scorpion" }
|
|
||||||
, { "scouts", "scout" }
|
|
||||||
, { "sculptures", "sculpture" }
|
|
||||||
, { "seals", "seal" }
|
|
||||||
, { "serfs", "serf" }
|
|
||||||
, { "serpents", "serpent" }
|
|
||||||
, { "servos", "servo" }
|
|
||||||
, { "shades", "shade" }
|
|
||||||
, { "shamans", "shaman" }
|
|
||||||
, { "shapeshifters", "shapeshifter" }
|
|
||||||
, { "sharks", "shark" }
|
|
||||||
, { "sheep", "sheep" }
|
|
||||||
, { "sirens", "siren" }
|
|
||||||
, { "skeletons", "skeleton" }
|
|
||||||
, { "skrulls", "skrull" }
|
|
||||||
, { "skunks", "skunk" }
|
|
||||||
, { "slith", "slith" }
|
|
||||||
, { "slivers", "sliver" }
|
|
||||||
, { "sloths", "sloth" }
|
|
||||||
, { "slugs", "slug" }
|
|
||||||
, { "snails", "snail" }
|
|
||||||
, { "snakes", "snake" }
|
|
||||||
, { "soldiers", "soldier" }
|
|
||||||
, { "soltari", "soltari" }
|
|
||||||
, { "sorcerers", "sorcerer" }
|
|
||||||
, { "spawns", "spawn" }
|
|
||||||
, { "specters", "specter" }
|
|
||||||
, { "spellshapers", "spellshaper" }
|
|
||||||
, { "sphinxes", "sphinx" }
|
|
||||||
, { "spiders", "spider" }
|
|
||||||
, { "spikes", "spike" }
|
|
||||||
, { "spirits", "spirit" }
|
|
||||||
, { "splinters", "splinter" }
|
|
||||||
, { "sponges", "sponge" }
|
|
||||||
, { "spies", "spy" }
|
|
||||||
, { "squids", "squid" }
|
|
||||||
, { "squirrels", "squirrel" }
|
|
||||||
, { "starfish", "starfish" }
|
|
||||||
, { "surrakar", "surrakar" }
|
|
||||||
, { "survivors", "survivor" }
|
|
||||||
, { "symbiotes", "symbiote" }
|
|
||||||
, { "synths", "synth" }
|
|
||||||
, { "tentacles", "tentacle" }
|
|
||||||
, { "tetravites", "tetravite" }
|
|
||||||
, { "thalakos", "thalakos" }
|
|
||||||
, { "thopters", "thopter" }
|
|
||||||
, { "thrulls", "thrull" }
|
|
||||||
, { "tieflings", "tiefling" }
|
|
||||||
, { "time lords", "time lord" }
|
|
||||||
, { "toys", "toy" }
|
|
||||||
, { "treefolk", "treefolk" }
|
|
||||||
, { "trilobites", "trilobite" }
|
|
||||||
, { "triskelavites", "triskelavite" }
|
|
||||||
, { "trolls", "troll" }
|
|
||||||
, { "turtles", "turtle" }
|
|
||||||
, { "tyranids", "tyranid" }
|
|
||||||
, { "unicorns", "unicorn" }
|
|
||||||
, { "utrom", "utrom" }
|
|
||||||
, { "vampires", "vampire" }
|
|
||||||
, { "varmints", "varmint" }
|
|
||||||
, { "vedalken", "vedalken" }
|
|
||||||
, { "villains", "villain" }
|
|
||||||
, { "volvers", "volver" }
|
|
||||||
, { "walls", "wall" }
|
|
||||||
, { "walruses", "walrus" }
|
|
||||||
, { "warlocks", "warlock" }
|
|
||||||
, { "warriors", "warrior" }
|
|
||||||
, { "weasels", "weasel" }
|
|
||||||
, { "weirds", "weird" }
|
|
||||||
, { "werewolves", "werewolf" }
|
|
||||||
, { "whales", "whale" }
|
|
||||||
, { "wizards", "wizard" }
|
|
||||||
, { "wolves", "wolf" }
|
|
||||||
, { "wolverines", "wolverine" }
|
|
||||||
, { "wombats", "wombat" }
|
|
||||||
, { "worms", "worm" }
|
|
||||||
, { "wraiths", "wraith" }
|
|
||||||
, { "wurms", "wurm" }
|
|
||||||
, { "yeti", "yeti" }
|
|
||||||
, { "zombies", "zombie" }
|
|
||||||
, { "zubera", "zubera" }
|
|
||||||
, { "alicorns", "alicorn" }
|
|
||||||
, { "armored", "armored" }
|
|
||||||
, { "arts", "art" }
|
|
||||||
, { "artists", "artist" }
|
|
||||||
, { "athletes", "athlete" }
|
|
||||||
, { "attendees", "attendee" }
|
|
||||||
, { "autobots", "autobot" }
|
|
||||||
, { "aven", "aven" }
|
|
||||||
, { "boxers", "boxer" }
|
|
||||||
, { "brainiacs", "brainiac" }
|
|
||||||
, { "bureaucrats", "bureaucrat" }
|
|
||||||
, { "chameleons", "chameleon" }
|
|
||||||
, { "champions", "champion" }
|
|
||||||
, { "chefs", "chef" }
|
|
||||||
, { "chickens", "chicken" }
|
|
||||||
, { "clamfolk", "clamfolk" }
|
|
||||||
, { "cows", "cow" }
|
|
||||||
, { "cyborgs", "cyborg" }
|
|
||||||
, { "deer", "deer" }
|
|
||||||
, { "designers", "designer" }
|
|
||||||
, { "dice", "die" }
|
|
||||||
, { "donkeys", "donkey" }
|
|
||||||
, { "elementals?", "elemental?" }
|
|
||||||
, { "elves", "elves" }
|
|
||||||
, { "expansion-symbols", "expansion-symbol" }
|
|
||||||
, { "fans", "fan" }
|
|
||||||
, { "fighters", "fighter" }
|
|
||||||
, { "glass", "glass" }
|
|
||||||
, { "gorillas", "gorilla" }
|
|
||||||
, { "grandchildren", "grandchild" }
|
|
||||||
, { "gus", "gus" }
|
|
||||||
, { "halves", "half" }
|
|
||||||
, { "hatificers", "hatificer" }
|
|
||||||
, { "hawks", "hawk" }
|
|
||||||
, { "heads", "head" }
|
|
||||||
, { "humans?", "human?" }
|
|
||||||
, { "jaguars", "jaguar" }
|
|
||||||
, { "judges", "judge" }
|
|
||||||
, { "killbots", "killbot" }
|
|
||||||
, { "ladies of proper etiquette", "lady of proper etiquette" }
|
|
||||||
, { "loci", "locus" }
|
|
||||||
, { "mammoths", "mammoth" }
|
|
||||||
, { "mimes", "mime" }
|
|
||||||
, { "mummies", "mummy" }
|
|
||||||
, { "paratroopers", "paratrooper" }
|
|
||||||
, { "penguins", "penguin" }
|
|
||||||
, { "ponies", "pony" }
|
|
||||||
, { "presents", "present" }
|
|
||||||
, { "revelers", "reveler" }
|
|
||||||
, { "ships", "ship" }
|
|
||||||
, { "sketches", "sketch" }
|
|
||||||
, { "spuzzem", "spuzzem" }
|
|
||||||
, { "spies", "spy" }
|
|
||||||
, { "stained", "stained" }
|
|
||||||
, { "teddies", "teddy" }
|
|
||||||
, { "the biggest, baddest, nastiest, scariest creatures you'll ever see", "the biggest, baddest, nastiest, scariest creature you'll ever see" }
|
|
||||||
, { "townsfolk", "townsfolk" }
|
|
||||||
, { "trees", "tree" }
|
|
||||||
, { "vampyres", "vampyre" }
|
|
||||||
, { "waiters", "waiter" }
|
|
||||||
, { "windmills", "windmill" }
|
|
||||||
, { "wrestlers", "wrestler" }
|
|
||||||
, { "zonians", "zonian" }
|
|
||||||
};
|
|
||||||
@@ -51,15 +51,9 @@ SCRIPT_FUNCTION(to_card_image) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(import_image) {
|
SCRIPT_FUNCTION(import_image) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM_C(ScriptValueP, input);
|
SCRIPT_PARAM(String, input);
|
||||||
if (input->type() == SCRIPT_IMAGE) {
|
return make_intrusive<ImportedImage>(set, input);
|
||||||
return make_intrusive<ScriptedImage>(set, input->toImage());
|
|
||||||
}
|
|
||||||
else if (input->type() == SCRIPT_STRING) {
|
|
||||||
return make_intrusive<ImportedImage>(set, input->toString());
|
|
||||||
}
|
|
||||||
throw ScriptErrorConversion(input->typeName(), _TYPE_("image"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(download_image) {
|
SCRIPT_FUNCTION(download_image) {
|
||||||
@@ -73,9 +67,9 @@ SCRIPT_FUNCTION(download_image) {
|
|||||||
|
|
||||||
SCRIPT_FUNCTION(get_metadata) {
|
SCRIPT_FUNCTION(get_metadata) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set, set));
|
Image img = input->generate(GeneratedImage::Options(0, 0, set));
|
||||||
SCRIPT_RETURN(image.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION));
|
SCRIPT_RETURN(img.GetOption(wxIMAGE_OPTION_PNG_DESCRIPTION));
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(set_metadata) {
|
SCRIPT_FUNCTION(set_metadata) {
|
||||||
@@ -87,22 +81,28 @@ SCRIPT_FUNCTION(set_metadata) {
|
|||||||
|
|
||||||
SCRIPT_FUNCTION(width_of) {
|
SCRIPT_FUNCTION(width_of) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(CardP, card);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set, set));
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
|
StyleSheet* stylesheet = card && card->stylesheet ? card->stylesheet.get() : set->stylesheet.get();
|
||||||
|
Image image = input->generate(GeneratedImage::Options(0, 0, stylesheet));
|
||||||
SCRIPT_RETURN(image.GetWidth());
|
SCRIPT_RETURN(image.GetWidth());
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(height_of) {
|
SCRIPT_FUNCTION(height_of) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(CardP, card);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set, set));
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
|
StyleSheet* stylesheet = card && card->stylesheet ? card->stylesheet.get() : set->stylesheet.get();
|
||||||
|
Image image = input->generate(GeneratedImage::Options(0, 0, stylesheet));
|
||||||
SCRIPT_RETURN(image.GetHeight());
|
SCRIPT_RETURN(image.GetHeight());
|
||||||
}
|
}
|
||||||
|
|
||||||
SCRIPT_FUNCTION(dimensions_of) {
|
SCRIPT_FUNCTION(dimensions_of) {
|
||||||
SCRIPT_PARAM(Set*, set);
|
SCRIPT_PARAM(Set*, set);
|
||||||
SCRIPT_PARAM(GeneratedImageP, input);
|
SCRIPT_PARAM(CardP, card);
|
||||||
Image image = input->generate(GeneratedImage::Options(0, 0, set, set));
|
SCRIPT_PARAM(GeneratedImageP, input);
|
||||||
|
StyleSheet* stylesheet = card && card->stylesheet ? card->stylesheet.get() : set->stylesheet.get();
|
||||||
|
Image image = input->generate(GeneratedImage::Options(0, 0, stylesheet));
|
||||||
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
ScriptCustomCollectionP ret(new ScriptCustomCollection());
|
||||||
ret->value.push_back(to_script(image.GetWidth()));
|
ret->value.push_back(to_script(image.GetWidth()));
|
||||||
ret->value.push_back(to_script(image.GetHeight()));
|
ret->value.push_back(to_script(image.GetHeight()));
|
||||||
|
|||||||
+266
-296
@@ -112,25 +112,13 @@ void pretty_print(std::ostream& os, const boost::json::value& jv, std::string* i
|
|||||||
String json_pretty_print(const boost::json::value& jv, std::string* indent) {
|
String json_pretty_print(const boost::json::value& jv, std::string* indent) {
|
||||||
std::ostringstream stream;
|
std::ostringstream stream;
|
||||||
pretty_print(stream, jv, indent);
|
pretty_print(stream, jv, indent);
|
||||||
std::string stdstring = stream.str();
|
String string = wxString(stream.str().c_str());
|
||||||
const char* data = stdstring.data();
|
return string;
|
||||||
size_t size = stdstring.size();
|
|
||||||
String wxstring = String::FromUTF8(data, size);
|
|
||||||
if (wxstring.empty() && size > 0) {
|
|
||||||
wxstring = String(data, wxConvWhateverWorks, size);
|
|
||||||
}
|
|
||||||
return wxstring;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String json_ugly_print(const boost::json::value& jv) {
|
String json_ugly_print(const boost::json::value& jv) {
|
||||||
std::string stdstring = boost::json::serialize(jv);
|
String string = wxString(boost::json::serialize(jv).c_str());
|
||||||
const char* data = stdstring.data();
|
return string;
|
||||||
size_t size = stdstring.size();
|
|
||||||
String wxstring = String::FromUTF8(data, size);
|
|
||||||
if (wxstring.empty() && size > 0) {
|
|
||||||
wxstring = String(data, wxConvWhateverWorks, size);
|
|
||||||
}
|
|
||||||
return wxstring;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : JSON to MSE
|
// ----------------------------------------------------------------------------- : JSON to MSE
|
||||||
@@ -140,33 +128,23 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set);
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
void read(T& out, boost::json::object& jv, const char value_name[]) {
|
void read(T& out, boost::json::object& jv, const char value_name[]) {
|
||||||
if (!jv.contains(value_name)) return;
|
if (!jv.contains(value_name)) return;
|
||||||
boost::json::string jstring = jv[value_name].as_string();
|
else {
|
||||||
const char* data = jstring.data();
|
wxStringInputStream stream = {_("")};
|
||||||
size_t size = jstring.size();
|
Reader reader(stream, nullptr, _(""));
|
||||||
String wxstring = String::FromUTF8(data, size);
|
reader.setValue(wxString(jv[value_name].as_string().c_str()));
|
||||||
if (wxstring.empty() && size > 0) {
|
reader.handle(out);
|
||||||
wxstring = String(data, wxConvWhateverWorks, size);
|
|
||||||
}
|
}
|
||||||
wxStringInputStream stream(wxstring);
|
|
||||||
Reader reader(stream, nullptr, _(""), false, true);
|
|
||||||
reader.setValue(wxstring);
|
|
||||||
reader.handle(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// templates don't work with enums? are you kidding me with this language?
|
// templates don't work with enums? are you kidding me with this language?
|
||||||
void read(PackSelectType& out, boost::json::object& jv, const char value_name[]) {
|
void read(PackSelectType& out, boost::json::object& jv, const char value_name[]) {
|
||||||
if (!jv.contains(value_name)) return;
|
if (!jv.contains(value_name)) return;
|
||||||
boost::json::string jstring = jv[value_name].as_string();
|
else {
|
||||||
const char* data = jstring.data();
|
wxStringInputStream stream = {_("")};
|
||||||
size_t size = jstring.size();
|
Reader reader(stream, nullptr, _(""));
|
||||||
String wxstring = String::FromUTF8(data, size);
|
reader.setValue(wxString(jv[value_name].as_string().c_str()));
|
||||||
if (wxstring.empty() && size > 0) {
|
reader.handle(out);
|
||||||
wxstring = String(data, wxConvWhateverWorks, size);
|
|
||||||
}
|
}
|
||||||
wxStringInputStream stream(wxstring);
|
|
||||||
Reader reader(stream, nullptr, _(""), false, true);
|
|
||||||
reader.setValue(wxstring);
|
|
||||||
reader.handle(out);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PackItemP json_to_mse_pack_item(boost::json::object& jv) {
|
PackItemP json_to_mse_pack_item(boost::json::object& jv) {
|
||||||
@@ -185,7 +163,7 @@ PackTypeP json_to_mse_pack_type(boost::json::object& jv) {
|
|||||||
read(pack_type->summary, jv, "summary");
|
read(pack_type->summary, jv, "summary");
|
||||||
read(pack_type->select, jv, "select");
|
read(pack_type->select, jv, "select");
|
||||||
if (jv.contains("items") && jv["items"].is_array()) {
|
if (jv.contains("items") && jv["items"].is_array()) {
|
||||||
boost::json::array pack_itemsv = jv["items"].get_array();
|
boost::json::array pack_itemsv = jv["items"].as_array();
|
||||||
for (size_t i = 0; i < pack_itemsv.size(); i++) {
|
for (size_t i = 0; i < pack_itemsv.size(); i++) {
|
||||||
boost::json::object pack_itemv = pack_itemsv[i].as_object();
|
boost::json::object pack_itemv = pack_itemsv[i].as_object();
|
||||||
pack_type->items.emplace_back(json_to_mse_pack_item(pack_itemv));
|
pack_type->items.emplace_back(json_to_mse_pack_item(pack_itemv));
|
||||||
@@ -206,43 +184,38 @@ KeywordP json_to_mse_keyword(boost::json::object& jv) {
|
|||||||
|
|
||||||
CardP json_to_mse_card(boost::json::object& jv, Set* set) {
|
CardP json_to_mse_card(boost::json::object& jv, Set* set) {
|
||||||
CardP card = make_intrusive<Card>(*set->game);
|
CardP card = make_intrusive<Card>(*set->game);
|
||||||
read(card->time_created, jv, "time_created");
|
read(card->time_created, jv, "time_created");
|
||||||
read(card->time_modified, jv, "time_modified");
|
read(card->time_modified, jv, "time_modified");
|
||||||
read(card->notes, jv, "notes");
|
read(card->notes, jv, "notes");
|
||||||
read(card->uid, jv, "uid");
|
read(card->uid, jv, "uid");
|
||||||
read(card->linked_card_1, jv, "linked_card_1");
|
read(card->linked_card_1, jv, "linked_card_1");
|
||||||
read(card->linked_card_2, jv, "linked_card_2");
|
read(card->linked_card_2, jv, "linked_card_2");
|
||||||
read(card->linked_card_3, jv, "linked_card_3");
|
read(card->linked_card_3, jv, "linked_card_3");
|
||||||
read(card->linked_card_4, jv, "linked_card_4");
|
read(card->linked_card_4, jv, "linked_card_4");
|
||||||
read(card->linked_relation_1, jv, "linked_relation_1");
|
read(card->linked_relation_1, jv, "linked_relation_1");
|
||||||
read(card->linked_relation_2, jv, "linked_relation_2");
|
read(card->linked_relation_2, jv, "linked_relation_2");
|
||||||
read(card->linked_relation_3, jv, "linked_relation_3");
|
read(card->linked_relation_3, jv, "linked_relation_3");
|
||||||
read(card->linked_relation_4, jv, "linked_relation_4");
|
read(card->linked_relation_4, jv, "linked_relation_4");
|
||||||
// card fields
|
// card fields
|
||||||
if (jv.contains("data") && jv["data"].is_object()) {
|
if (jv.contains("data") && jv["data"].is_object()) {
|
||||||
boost::json::object datav = jv["data"].get_object();
|
boost::json::object datav = jv["data"].as_object();
|
||||||
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
||||||
boost::json::string_view key_view = it->key();
|
String key_name = wxString(it->key_c_str());
|
||||||
String key_name = String::FromUTF8(key_view.data(), key_view.size());
|
|
||||||
Value* container = get_card_field_container(*set->game, card->data, key_name, false);
|
Value* container = get_card_field_container(*set->game, card->data, key_name, false);
|
||||||
ScriptValueP value = json_to_mse(it->value(), set);
|
ScriptValueP value = json_to_mse(it->value(), set);
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// stylesheet
|
// stylesheet
|
||||||
if (jv.contains("stylesheet")) {
|
if (jv.contains("stylesheet")) card->stylesheet = StyleSheet::byGameAndName(*set->game, wxString(jv["stylesheet"].as_string().c_str()));
|
||||||
boost::json::string stylesheet_name = jv["stylesheet"].as_string();
|
|
||||||
card->stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_name.data(), stylesheet_name.size()));
|
|
||||||
}
|
|
||||||
if (card->stylesheet) {
|
if (card->stylesheet) {
|
||||||
// styling fields
|
// styling fields
|
||||||
card->styling_data.init(card->stylesheet->styling_fields);
|
card->styling_data.init(card->stylesheet->styling_fields);
|
||||||
if (jv.contains("styling_data") && jv["styling_data"].is_object()) {
|
if (jv.contains("styling_data") && jv["styling_data"].is_object()) {
|
||||||
boost::json::object datav = jv["styling_data"].get_object();
|
boost::json::object datav = jv["styling_data"].as_object();
|
||||||
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
||||||
boost::json::string_view key_view = it->key();
|
String key_name = wxString(it->key_c_str());
|
||||||
String key_name = String::FromUTF8(key_view.data(), key_view.size());
|
Value* container = get_container(card->styling_data, wxString("styling"), key_name, false);
|
||||||
Value* container = get_container(card->styling_data, String("styling"), key_name, false);
|
|
||||||
ScriptValueP value = json_to_mse(it->value(), set);
|
ScriptValueP value = json_to_mse(it->value(), set);
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
card->has_styling = true;
|
card->has_styling = true;
|
||||||
@@ -250,18 +223,15 @@ CardP json_to_mse_card(boost::json::object& jv, Set* set) {
|
|||||||
}
|
}
|
||||||
// extra card fields
|
// extra card fields
|
||||||
if (jv.contains("extra_data") && jv["extra_data"].is_object()) {
|
if (jv.contains("extra_data") && jv["extra_data"].is_object()) {
|
||||||
boost::json::object datav = jv["extra_data"].get_object();
|
boost::json::object datav = jv["extra_data"].as_object();
|
||||||
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
||||||
boost::json::string_view stylesheet_view = it->key();
|
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, it->key_c_str());
|
||||||
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_view.data(), stylesheet_view.size()));
|
|
||||||
if (!stylesheet) continue;
|
if (!stylesheet) continue;
|
||||||
IndexMap<FieldP, ValueP>& stylesheet_data = card->extraDataFor(*stylesheet);
|
IndexMap<FieldP, ValueP>& stylesheet_data = card->extraDataFor(*stylesheet);
|
||||||
stylesheet_data.init(stylesheet->extra_card_fields);
|
|
||||||
boost::json::object stylesheet_datav = it->value().as_object();
|
boost::json::object stylesheet_datav = it->value().as_object();
|
||||||
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
|
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
|
||||||
boost::json::string_view key_view = stylesheet_it->key();
|
String key_name = wxString(stylesheet_it->key_c_str());
|
||||||
String key_name = String::FromUTF8(key_view.data(), key_view.size());
|
Value* container = get_container(stylesheet_data, wxString("extra card"), key_name, false);
|
||||||
Value* container = get_container(stylesheet_data, String("extra card"), key_name, false);
|
|
||||||
ScriptValueP value = json_to_mse(stylesheet_it->value(), set);
|
ScriptValueP value = json_to_mse(stylesheet_it->value(), set);
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
@@ -278,35 +248,30 @@ SetP json_to_mse_set(boost::json::object& jv) {
|
|||||||
if (!jv.contains("stylesheet")) {
|
if (!jv.contains("stylesheet")) {
|
||||||
throw ScriptError(_ERROR_("json set without stylesheet"));
|
throw ScriptError(_ERROR_("json set without stylesheet"));
|
||||||
}
|
}
|
||||||
boost::json::string game_name = jv["game"].as_string();
|
GameP game = Game::byName(wxString(jv["game"].as_string().c_str()));
|
||||||
GameP game = Game::byName(String::FromUTF8(game_name.data(), game_name.size()));
|
StyleSheetP stylesheet = StyleSheet::byGameAndName(*game, wxString(jv["stylesheet"].as_string().c_str()));
|
||||||
boost::json::string stylesheet_name = jv["stylesheet"].as_string();
|
|
||||||
StyleSheetP stylesheet = StyleSheet::byGameAndName(*game, String::FromUTF8(stylesheet_name.data(), stylesheet_name.size()));
|
|
||||||
SetP set = make_intrusive<Set>(stylesheet);
|
SetP set = make_intrusive<Set>(stylesheet);
|
||||||
// set fields
|
// set fields
|
||||||
if (jv.contains("set_info") && jv["set_info"].is_object()) {
|
if (jv.contains("set_info") && jv["set_info"].is_object()) {
|
||||||
boost::json::object datav = jv["set_info"].get_object();
|
boost::json::object datav = jv["set_info"].as_object();
|
||||||
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
||||||
boost::json::string_view key_view = it->key();
|
String key_name = wxString(it->key_c_str());
|
||||||
String key_name = String::FromUTF8(key_view.data(), key_view.size());
|
Value* container = get_container(set->data, wxString("set"), key_name, false);
|
||||||
Value* container = get_container(set->data, String("set"), key_name, false);
|
|
||||||
ScriptValueP value = json_to_mse(it->value(), set.get());
|
ScriptValueP value = json_to_mse(it->value(), set.get());
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// styling
|
// styling
|
||||||
if (jv.contains("styling") && jv["styling"].is_object()) {
|
if (jv.contains("styling") && jv["styling"].is_object()) {
|
||||||
boost::json::object datav = jv["styling"].get_object();
|
boost::json::object datav = jv["styling"].as_object();
|
||||||
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
for (auto it = datav.begin(); it != datav.end(); ++it) {
|
||||||
boost::json::string_view stylesheet_view = it->key();
|
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, it->key_c_str());
|
||||||
StyleSheetP stylesheet = StyleSheet::byGameAndName(*set->game, String::FromUTF8(stylesheet_view.data(), stylesheet_view.size()));
|
|
||||||
if (!stylesheet) continue;
|
if (!stylesheet) continue;
|
||||||
IndexMap<FieldP, ValueP>& stylesheet_data = set->stylingDataFor(*stylesheet);
|
IndexMap<FieldP, ValueP>& stylesheet_data = set->stylingDataFor(*stylesheet);
|
||||||
boost::json::object stylesheet_datav = it->value().as_object();
|
boost::json::object stylesheet_datav = it->value().as_object();
|
||||||
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
|
for (auto stylesheet_it = stylesheet_datav.begin(); stylesheet_it != stylesheet_datav.end(); ++stylesheet_it) {
|
||||||
boost::json::string_view key_view = stylesheet_it->key();
|
String key_name = wxString(stylesheet_it->key_c_str());
|
||||||
String key_name = String::FromUTF8(key_view.data(), key_view.size());
|
Value* container = get_container(stylesheet_data, wxString("styling"), key_name, false);
|
||||||
Value* container = get_container(stylesheet_data, String("styling"), key_name, false);
|
|
||||||
ScriptValueP value = json_to_mse(stylesheet_it->value(), set.get());
|
ScriptValueP value = json_to_mse(stylesheet_it->value(), set.get());
|
||||||
set_container(container, value, key_name);
|
set_container(container, value, key_name);
|
||||||
}
|
}
|
||||||
@@ -314,7 +279,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
|
|||||||
}
|
}
|
||||||
// cards
|
// cards
|
||||||
if (jv.contains("cards") && jv["cards"].is_array()) {
|
if (jv.contains("cards") && jv["cards"].is_array()) {
|
||||||
boost::json::array cardsv = jv["cards"].get_array();
|
boost::json::array cardsv = jv["cards"].as_array();
|
||||||
for (size_t i = 0; i < cardsv.size(); i++) {
|
for (size_t i = 0; i < cardsv.size(); i++) {
|
||||||
boost::json::object cardv = cardsv[i].as_object();
|
boost::json::object cardv = cardsv[i].as_object();
|
||||||
set->cards.emplace_back(json_to_mse_card(cardv, set.get()));
|
set->cards.emplace_back(json_to_mse_card(cardv, set.get()));
|
||||||
@@ -322,7 +287,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
|
|||||||
}
|
}
|
||||||
// keywords
|
// keywords
|
||||||
if (jv.contains("keywords") && jv["keywords"].is_array()) {
|
if (jv.contains("keywords") && jv["keywords"].is_array()) {
|
||||||
boost::json::array keywordsv = jv["keywords"].get_array();
|
boost::json::array keywordsv = jv["keywords"].as_array();
|
||||||
for (size_t i = 0; i < keywordsv.size(); i++) {
|
for (size_t i = 0; i < keywordsv.size(); i++) {
|
||||||
boost::json::object keywordv = keywordsv[i].as_object();
|
boost::json::object keywordv = keywordsv[i].as_object();
|
||||||
set->keywords.emplace_back(json_to_mse_keyword(keywordv));
|
set->keywords.emplace_back(json_to_mse_keyword(keywordv));
|
||||||
@@ -330,7 +295,7 @@ SetP json_to_mse_set(boost::json::object& jv) {
|
|||||||
}
|
}
|
||||||
// pack types
|
// pack types
|
||||||
if (jv.contains("pack_types") && jv["pack_types"].is_array()) {
|
if (jv.contains("pack_types") && jv["pack_types"].is_array()) {
|
||||||
boost::json::array pack_typesv = jv["pack_types"].get_array();
|
boost::json::array pack_typesv = jv["pack_types"].as_array();
|
||||||
for (size_t i = 0; i < pack_typesv.size(); i++) {
|
for (size_t i = 0; i < pack_typesv.size(); i++) {
|
||||||
boost::json::object pack_typev = pack_typesv[i].as_object();
|
boost::json::object pack_typev = pack_typesv[i].as_object();
|
||||||
set->pack_types.emplace_back(json_to_mse_pack_type(pack_typev));
|
set->pack_types.emplace_back(json_to_mse_pack_type(pack_typev));
|
||||||
@@ -353,13 +318,17 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set) {
|
|||||||
return to_script(integer);
|
return to_script(integer);
|
||||||
}
|
}
|
||||||
else if (jv.is_string()) {
|
else if (jv.is_string()) {
|
||||||
boost::json::string jstring = jv.get_string();
|
if (jv.as_string().empty()) return to_script(String());
|
||||||
if (jstring.empty()) return to_script(String());
|
std::string string = boost::json::value_to<std::string>(jv);
|
||||||
const char* data = jstring.data();
|
const char* cstring = string.c_str();
|
||||||
size_t size = jstring.size();
|
size_t nulpos = strlen(cstring);
|
||||||
String wxstring = String::FromUTF8(data, size);
|
// if the string contains nul bytes, we have to use the std::string constructor, even though we can't specify the encoding
|
||||||
|
if (nulpos < string.size()) return to_script(String(string));
|
||||||
|
// if the string doesn't contain nul bytes, we can use the constructor that allows to specify the encoding
|
||||||
|
String wxstring(cstring, wxConvUTF8);
|
||||||
if (!wxstring.empty()) return to_script(wxstring);
|
if (!wxstring.empty()) return to_script(wxstring);
|
||||||
return to_script(String(data, wxConvWhateverWorks, size));
|
// if all else fails, use "Whatever Works"
|
||||||
|
return to_script(String(cstring, wxConvWhateverWorks));
|
||||||
}
|
}
|
||||||
else if (jv.is_array()) {
|
else if (jv.is_array()) {
|
||||||
boost::json::array array = jv.get_array();
|
boost::json::array array = jv.get_array();
|
||||||
@@ -380,16 +349,18 @@ ScriptValueP json_to_mse(const boost::json::value& jv, Set* set) {
|
|||||||
if (mse_object_type == "keyword") return make_intrusive<ScriptObject<KeywordP>> (json_to_mse_keyword(object));
|
if (mse_object_type == "keyword") return make_intrusive<ScriptObject<KeywordP>> (json_to_mse_keyword(object));
|
||||||
if (mse_object_type == "pack_type") return make_intrusive<ScriptObject<PackTypeP>>(json_to_mse_pack_type(object));
|
if (mse_object_type == "pack_type") return make_intrusive<ScriptObject<PackTypeP>>(json_to_mse_pack_type(object));
|
||||||
if (mse_object_type == "pack_item") return make_intrusive<ScriptObject<PackItemP>>(json_to_mse_pack_item(object));
|
if (mse_object_type == "pack_item") return make_intrusive<ScriptObject<PackItemP>>(json_to_mse_pack_item(object));
|
||||||
queue_message(MESSAGE_ERROR, _ERROR_("json unknown type") + _("(") + String(mse_object_type.c_str()) + _(")"));
|
queue_message(MESSAGE_ERROR, _ERROR_("json unknown type") + _("(") + wxString(mse_object_type.c_str()) + _(")"));
|
||||||
return script_nil;
|
return script_nil;
|
||||||
}
|
}
|
||||||
ScriptCustomCollectionP result = make_intrusive<ScriptCustomCollection>();
|
ScriptCustomCollectionP result = make_intrusive<ScriptCustomCollection>();
|
||||||
for (auto it = object.begin(); it != object.end(); ++it) {
|
for (auto it = object.begin(); it != object.end(); ++it) {
|
||||||
boost::json::string_view jview = it->key();
|
boost::json::string_view jview = it->key();
|
||||||
String key_name = String::FromUTF8(jview.data(), jview.size());
|
std::string_view stdview = std::string_view(jview.data(), jview.size());
|
||||||
|
std::string stdstring = { stdview.begin(), stdview.end() };
|
||||||
|
String key(stdstring.c_str(), wxConvUTF8);
|
||||||
boost::json::value jvalue = it->value();
|
boost::json::value jvalue = it->value();
|
||||||
ScriptValueP value = json_to_mse(jvalue, set);
|
ScriptValueP value = json_to_mse(jvalue, set);
|
||||||
result->key_value[key_name] = value;
|
result->key_value[key] = value;
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -403,9 +374,8 @@ ScriptValueP json_to_mse(const String& string, Set* set) {
|
|||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
boost::json::parse_options options;
|
boost::json::parse_options options;
|
||||||
options.allow_invalid_utf8 = true;
|
options.allow_invalid_utf8 = true;
|
||||||
wxScopedCharBuffer buffer = string.ToUTF8();
|
boost::json::value jv = boost::json::parse(string.ToStdString(), ec, {}, options);
|
||||||
boost::json::value jv = boost::json::parse(boost::json::string_view(buffer.data(), buffer.length()), ec, {}, options);
|
//if(ec) queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
|
||||||
//if(ec && buffer.length() > 0) queue_message(MESSAGE_ERROR, _ERROR_("json cant parse") + _("\n\n") + ec.message());
|
|
||||||
if(ec) return script_nil;
|
if(ec) return script_nil;
|
||||||
return json_to_mse(jv, set);
|
return json_to_mse(jv, set);
|
||||||
}
|
}
|
||||||
@@ -542,92 +512,92 @@ boost::json::object mse_to_json(const StyleP& style) {
|
|||||||
|
|
||||||
boost::json::object stylev;
|
boost::json::object stylev;
|
||||||
stylev.emplace("mse_object_type", "style");
|
stylev.emplace("mse_object_type", "style");
|
||||||
stylev.emplace("z_index", String::Format(wxT("%i"), style->z_index));
|
stylev.emplace("z_index", wxString::Format(wxT("%i"), style->z_index));
|
||||||
stylev.emplace("tab_index", String::Format(wxT("%i"), style->tab_index));
|
stylev.emplace("tab_index", wxString::Format(wxT("%i"), style->tab_index));
|
||||||
stylev.emplace("left", String::Format(wxT("%.2f"), style->left()));
|
stylev.emplace("left", wxString::Format(wxT("%.2f"), style->left()));
|
||||||
stylev.emplace("top", String::Format(wxT("%.2f"), style->top()));
|
stylev.emplace("top", wxString::Format(wxT("%.2f"), style->top()));
|
||||||
stylev.emplace("right", String::Format(wxT("%.2f"), style->right()));
|
stylev.emplace("right", wxString::Format(wxT("%.2f"), style->right()));
|
||||||
stylev.emplace("bottom", String::Format(wxT("%.2f"), style->bottom()));
|
stylev.emplace("bottom", wxString::Format(wxT("%.2f"), style->bottom()));
|
||||||
stylev.emplace("width", String::Format(wxT("%.2f"), style->width()));
|
stylev.emplace("width", wxString::Format(wxT("%.2f"), style->width()));
|
||||||
stylev.emplace("height", String::Format(wxT("%.2f"), style->height()));
|
stylev.emplace("height", wxString::Format(wxT("%.2f"), style->height()));
|
||||||
stylev.emplace("angle", String::Format(wxT("%.2f"), style->angle()));
|
stylev.emplace("angle", wxString::Format(wxT("%.2f"), style->angle()));
|
||||||
stylev.emplace("visible", style->visible());
|
stylev.emplace("visible", style->visible());
|
||||||
stylev.emplace("mask", style->mask.toScriptString());
|
stylev.emplace("mask", style->mask.toScriptString());
|
||||||
|
|
||||||
if (TextStyle* s = dynamic_cast<TextStyle*>(style.get())) {
|
if (TextStyle* s = dynamic_cast<TextStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", "text");
|
stylev.emplace("field_type", "text");
|
||||||
|
|
||||||
boost::json::object fontv;
|
boost::json::object fontv;
|
||||||
fontv.emplace("name", s->font.name());
|
fontv.emplace("name", s->font.name());
|
||||||
fontv.emplace("italic_name", s->font.italic_name());
|
fontv.emplace("italic_name", s->font.italic_name());
|
||||||
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
|
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
|
||||||
fontv.emplace("weight", s->font.weight());
|
fontv.emplace("weight", s->font.weight());
|
||||||
fontv.emplace("style", s->font.style());
|
fontv.emplace("style", s->font.style());
|
||||||
fontv.emplace("underline", s->font.underline());
|
fontv.emplace("underline", s->font.underline());
|
||||||
fontv.emplace("strikethrough", s->font.strikethrough());
|
fontv.emplace("strikethrough", s->font.strikethrough());
|
||||||
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
|
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
|
||||||
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
|
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
|
||||||
fontv.emplace("color", format_color( s->font.color()));
|
fontv.emplace("color", format_color( s->font.color()));
|
||||||
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
||||||
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
||||||
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
||||||
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
|
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
|
||||||
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
||||||
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
|
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
|
||||||
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
|
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
|
||||||
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
||||||
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
|
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
|
||||||
stylev.emplace("font", fontv);
|
stylev.emplace("font", fontv);
|
||||||
|
|
||||||
boost::json::object symbolfontv;
|
boost::json::object symbolfontv;
|
||||||
symbolfontv.emplace("name", s->symbol_font.name());
|
symbolfontv.emplace("name", s->symbol_font.name());
|
||||||
symbolfontv.emplace("size", String::Format(wxT("%.2f"), s->symbol_font.size()));
|
symbolfontv.emplace("size", wxString::Format(wxT("%.2f"), s->symbol_font.size()));
|
||||||
symbolfontv.emplace("underline", s->symbol_font.underline());
|
symbolfontv.emplace("underline", s->symbol_font.underline());
|
||||||
symbolfontv.emplace("strikethrough", s->symbol_font.strikethrough());
|
symbolfontv.emplace("strikethrough", s->symbol_font.strikethrough());
|
||||||
symbolfontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->symbol_font.scale_down_to));
|
symbolfontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->symbol_font.scale_down_to));
|
||||||
symbolfontv.emplace("shadow_color", format_color( s->symbol_font.shadow_color()));
|
symbolfontv.emplace("shadow_color", format_color( s->symbol_font.shadow_color()));
|
||||||
symbolfontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_x()));
|
symbolfontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_x()));
|
||||||
symbolfontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_y()));
|
symbolfontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_displacement_y()));
|
||||||
symbolfontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->symbol_font.shadow_blur()));
|
symbolfontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->symbol_font.shadow_blur()));
|
||||||
symbolfontv.emplace("stroke_color", format_color( s->symbol_font.stroke_color()));
|
symbolfontv.emplace("stroke_color", format_color( s->symbol_font.stroke_color()));
|
||||||
symbolfontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->symbol_font.stroke_radius()));
|
symbolfontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->symbol_font.stroke_radius()));
|
||||||
symbolfontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->symbol_font.stroke_blur()));
|
symbolfontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->symbol_font.stroke_blur()));
|
||||||
stylev.emplace("symbol_font", symbolfontv);
|
stylev.emplace("symbol_font", symbolfontv);
|
||||||
|
|
||||||
stylev.emplace("always_symbol", s->always_symbol);
|
stylev.emplace("always_symbol", s->always_symbol);
|
||||||
stylev.emplace("allow_formating", s->allow_formating);
|
stylev.emplace("allow_formating", s->allow_formating);
|
||||||
stylev.emplace("alignment", alignment_to_string( s->alignment()));
|
stylev.emplace("alignment", alignment_to_string( s->alignment()));
|
||||||
stylev.emplace("direction", direction_to_string( s->direction));
|
stylev.emplace("direction", direction_to_string( s->direction));
|
||||||
stylev.emplace("padding_left", String::Format(wxT("%.2f"), s->padding_left()));
|
stylev.emplace("padding_left", wxString::Format(wxT("%.2f"), s->padding_left()));
|
||||||
stylev.emplace("padding_right", String::Format(wxT("%.2f"), s->padding_right()));
|
stylev.emplace("padding_right", wxString::Format(wxT("%.2f"), s->padding_right()));
|
||||||
stylev.emplace("padding_top", String::Format(wxT("%.2f"), s->padding_top()));
|
stylev.emplace("padding_top", wxString::Format(wxT("%.2f"), s->padding_top()));
|
||||||
stylev.emplace("padding_bottom", String::Format(wxT("%.2f"), s->padding_bottom()));
|
stylev.emplace("padding_bottom", wxString::Format(wxT("%.2f"), s->padding_bottom()));
|
||||||
stylev.emplace("padding_left_min", String::Format(wxT("%.2f"), s->padding_left_min()));
|
stylev.emplace("padding_left_min", wxString::Format(wxT("%.2f"), s->padding_left_min()));
|
||||||
stylev.emplace("padding_right_min", String::Format(wxT("%.2f"), s->padding_right_min()));
|
stylev.emplace("padding_right_min", wxString::Format(wxT("%.2f"), s->padding_right_min()));
|
||||||
stylev.emplace("padding_top_min", String::Format(wxT("%.2f"), s->padding_top_min()));
|
stylev.emplace("padding_top_min", wxString::Format(wxT("%.2f"), s->padding_top_min()));
|
||||||
stylev.emplace("padding_bottom_min", String::Format(wxT("%.2f"), s->padding_bottom_min()));
|
stylev.emplace("padding_bottom_min", wxString::Format(wxT("%.2f"), s->padding_bottom_min()));
|
||||||
stylev.emplace("line_height_soft", String::Format(wxT("%.2f"), s->line_height_soft()));
|
stylev.emplace("line_height_soft", wxString::Format(wxT("%.2f"), s->line_height_soft()));
|
||||||
stylev.emplace("line_height_hard", String::Format(wxT("%.2f"), s->line_height_hard()));
|
stylev.emplace("line_height_hard", wxString::Format(wxT("%.2f"), s->line_height_hard()));
|
||||||
stylev.emplace("line_height_line", String::Format(wxT("%.2f"), s->line_height_line()));
|
stylev.emplace("line_height_line", wxString::Format(wxT("%.2f"), s->line_height_line()));
|
||||||
stylev.emplace("line_height_soft_max", String::Format(wxT("%.2f"), s->line_height_soft_max()));
|
stylev.emplace("line_height_soft_max", wxString::Format(wxT("%.2f"), s->line_height_soft_max()));
|
||||||
stylev.emplace("line_height_hard_max", String::Format(wxT("%.2f"), s->line_height_hard_max()));
|
stylev.emplace("line_height_hard_max", wxString::Format(wxT("%.2f"), s->line_height_hard_max()));
|
||||||
stylev.emplace("line_height_line_max", String::Format(wxT("%.2f"), s->line_height_line_max()));
|
stylev.emplace("line_height_line_max", wxString::Format(wxT("%.2f"), s->line_height_line_max()));
|
||||||
stylev.emplace("paragraph_height", String::Format(wxT("%.2f"), s->paragraph_height()));
|
stylev.emplace("paragraph_height", wxString::Format(wxT("%.2f"), s->paragraph_height()));
|
||||||
|
|
||||||
boost::json::object layoutv;
|
boost::json::object layoutv;
|
||||||
layoutv.emplace("content_top", String::Format(wxT("%.2f"), s->layout->top));
|
layoutv.emplace("content_top", wxString::Format(wxT("%.2f"), s->layout->top));
|
||||||
layoutv.emplace("content_middle", String::Format(wxT("%.2f"), s->layout->middle()));
|
layoutv.emplace("content_middle", wxString::Format(wxT("%.2f"), s->layout->middle()));
|
||||||
layoutv.emplace("content_bottom", String::Format(wxT("%.2f"), s->layout->bottom()));
|
layoutv.emplace("content_bottom", wxString::Format(wxT("%.2f"), s->layout->bottom()));
|
||||||
layoutv.emplace("content_width", String::Format(wxT("%.2f"), s->layout->width));
|
layoutv.emplace("content_width", wxString::Format(wxT("%.2f"), s->layout->width));
|
||||||
layoutv.emplace("content_height", String::Format(wxT("%.2f"), s->layout->height));
|
layoutv.emplace("content_height", wxString::Format(wxT("%.2f"), s->layout->height));
|
||||||
layoutv.emplace("content_lines", String::Format(wxT("%i"), s->layout->lines.size()));
|
layoutv.emplace("content_lines", wxString::Format(wxT("%i"), s->layout->lines.size()));
|
||||||
layoutv.emplace("content_clauses", String::Format(wxT("%i"), s->layout->clauses.size()));
|
layoutv.emplace("content_clauses", wxString::Format(wxT("%i"), s->layout->clauses.size()));
|
||||||
layoutv.emplace("content_paragraphs", String::Format(wxT("%i"), s->layout->paragraphs.size()));
|
layoutv.emplace("content_paragraphs", wxString::Format(wxT("%i"), s->layout->paragraphs.size()));
|
||||||
layoutv.emplace("content_blocks", String::Format(wxT("%i"), s->layout->blocks.size()));
|
layoutv.emplace("content_blocks", wxString::Format(wxT("%i"), s->layout->blocks.size()));
|
||||||
boost::json::array separatorsv;
|
boost::json::array separatorsv;
|
||||||
int size = s->layout->separators.size();
|
int size = s->layout->separators.size();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
separatorsv.emplace_back(String::Format(wxT("%.2f"), s->layout->separators[i]));
|
separatorsv.emplace_back(wxString::Format(wxT("%.2f"), s->layout->separators[i]));
|
||||||
}
|
}
|
||||||
if (size > 0) layoutv.emplace("content_separators", separatorsv);
|
if (size > 0) layoutv.emplace("content_separators", separatorsv);
|
||||||
|
|
||||||
@@ -642,35 +612,35 @@ boost::json::object mse_to_json(const StyleP& style) {
|
|||||||
|
|
||||||
else if (MultipleChoiceStyle* s = dynamic_cast<MultipleChoiceStyle*>(style.get())) {
|
else if (MultipleChoiceStyle* s = dynamic_cast<MultipleChoiceStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", "multiple_choice");
|
stylev.emplace("field_type", "multiple_choice");
|
||||||
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
|
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
|
||||||
stylev.emplace("render_style", render_style_to_string( s->render_style));
|
stylev.emplace("render_style", render_style_to_string( s->render_style));
|
||||||
stylev.emplace("image", s->image.toScriptString());
|
stylev.emplace("image", s->image.toScriptString());
|
||||||
stylev.emplace("combine", combine_to_string( s->combine));
|
stylev.emplace("combine", combine_to_string( s->combine));
|
||||||
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
||||||
stylev.emplace("direction", direction_to_string( s->direction()));
|
stylev.emplace("direction", direction_to_string( s->direction()));
|
||||||
stylev.emplace("spacing", String::Format(wxT("%.2f"), s->spacing()));
|
stylev.emplace("spacing", wxString::Format(wxT("%.2f"), s->spacing()));
|
||||||
|
|
||||||
boost::json::object fontv;
|
boost::json::object fontv;
|
||||||
fontv.emplace("name", s->font.name());
|
fontv.emplace("name", s->font.name());
|
||||||
fontv.emplace("italic_name", s->font.italic_name());
|
fontv.emplace("italic_name", s->font.italic_name());
|
||||||
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
|
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
|
||||||
fontv.emplace("weight", s->font.weight());
|
fontv.emplace("weight", s->font.weight());
|
||||||
fontv.emplace("style", s->font.style());
|
fontv.emplace("style", s->font.style());
|
||||||
fontv.emplace("underline", s->font.underline());
|
fontv.emplace("underline", s->font.underline());
|
||||||
fontv.emplace("strikethrough", s->font.strikethrough());
|
fontv.emplace("strikethrough", s->font.strikethrough());
|
||||||
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
|
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
|
||||||
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
|
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
|
||||||
fontv.emplace("color", format_color( s->font.color()));
|
fontv.emplace("color", format_color( s->font.color()));
|
||||||
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
||||||
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
||||||
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
||||||
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
|
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
|
||||||
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
||||||
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
|
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
|
||||||
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
|
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
|
||||||
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
||||||
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
|
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
|
||||||
stylev.emplace("font", fontv);
|
stylev.emplace("font", fontv);
|
||||||
|
|
||||||
boost::json::object choiceimagesv;
|
boost::json::object choiceimagesv;
|
||||||
for (auto choice_image : s->choice_images) {
|
for (auto choice_image : s->choice_images) {
|
||||||
@@ -682,33 +652,33 @@ boost::json::object mse_to_json(const StyleP& style) {
|
|||||||
|
|
||||||
else if (ChoiceStyle* s = dynamic_cast<ChoiceStyle*>(style.get())) {
|
else if (ChoiceStyle* s = dynamic_cast<ChoiceStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", dynamic_cast<BooleanStyle*>(style.get()) ? "boolean" : "choice");
|
stylev.emplace("field_type", dynamic_cast<BooleanStyle*>(style.get()) ? "boolean" : "choice");
|
||||||
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
|
stylev.emplace("popup_style", popup_style_to_string( s->popup_style));
|
||||||
stylev.emplace("render_style", render_style_to_string( s->render_style));
|
stylev.emplace("render_style", render_style_to_string( s->render_style));
|
||||||
stylev.emplace("image", s->image.toScriptString());
|
stylev.emplace("image", s->image.toScriptString());
|
||||||
stylev.emplace("combine", combine_to_string( s->combine));
|
stylev.emplace("combine", combine_to_string( s->combine));
|
||||||
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
||||||
|
|
||||||
boost::json::object fontv;
|
boost::json::object fontv;
|
||||||
fontv.emplace("name", s->font.name());
|
fontv.emplace("name", s->font.name());
|
||||||
fontv.emplace("italic_name", s->font.italic_name());
|
fontv.emplace("italic_name", s->font.italic_name());
|
||||||
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
|
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
|
||||||
fontv.emplace("weight", s->font.weight());
|
fontv.emplace("weight", s->font.weight());
|
||||||
fontv.emplace("style", s->font.style());
|
fontv.emplace("style", s->font.style());
|
||||||
fontv.emplace("underline", s->font.underline());
|
fontv.emplace("underline", s->font.underline());
|
||||||
fontv.emplace("strikethrough", s->font.strikethrough());
|
fontv.emplace("strikethrough", s->font.strikethrough());
|
||||||
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
|
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
|
||||||
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
|
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
|
||||||
fontv.emplace("color", format_color( s->font.color()));
|
fontv.emplace("color", format_color( s->font.color()));
|
||||||
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
||||||
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
||||||
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
||||||
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
|
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
|
||||||
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
||||||
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
|
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
|
||||||
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
|
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
|
||||||
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
||||||
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
|
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
|
||||||
stylev.emplace("font", fontv);
|
stylev.emplace("font", fontv);
|
||||||
|
|
||||||
boost::json::object choiceimagesv;
|
boost::json::object choiceimagesv;
|
||||||
for (auto choice_image : s->choice_images) {
|
for (auto choice_image : s->choice_images) {
|
||||||
@@ -722,71 +692,71 @@ boost::json::object mse_to_json(const StyleP& style) {
|
|||||||
stylev.emplace("field_type", "package_choice");
|
stylev.emplace("field_type", "package_choice");
|
||||||
|
|
||||||
boost::json::object fontv;
|
boost::json::object fontv;
|
||||||
fontv.emplace("name", s->font.name());
|
fontv.emplace("name", s->font.name());
|
||||||
fontv.emplace("italic_name", s->font.italic_name());
|
fontv.emplace("italic_name", s->font.italic_name());
|
||||||
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
|
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
|
||||||
fontv.emplace("weight", s->font.weight());
|
fontv.emplace("weight", s->font.weight());
|
||||||
fontv.emplace("style", s->font.style());
|
fontv.emplace("style", s->font.style());
|
||||||
fontv.emplace("underline", s->font.underline());
|
fontv.emplace("underline", s->font.underline());
|
||||||
fontv.emplace("strikethrough", s->font.strikethrough());
|
fontv.emplace("strikethrough", s->font.strikethrough());
|
||||||
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
|
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
|
||||||
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
|
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
|
||||||
fontv.emplace("color", format_color( s->font.color()));
|
fontv.emplace("color", format_color( s->font.color()));
|
||||||
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
||||||
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
||||||
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
||||||
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
|
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
|
||||||
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
||||||
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
|
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
|
||||||
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
|
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
|
||||||
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
||||||
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
|
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
|
||||||
stylev.emplace("font", fontv);
|
stylev.emplace("font", fontv);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (ColorStyle* s = dynamic_cast<ColorStyle*>(style.get())) {
|
else if (ColorStyle* s = dynamic_cast<ColorStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", "color");
|
stylev.emplace("field_type", "color");
|
||||||
stylev.emplace("radius", String::Format(wxT("%.2f"), s->radius()));
|
stylev.emplace("radius", wxString::Format(wxT("%.2f"), s->radius()));
|
||||||
stylev.emplace("left_width", String::Format(wxT("%.2f"), s->left_width()));
|
stylev.emplace("left_width", wxString::Format(wxT("%.2f"), s->left_width()));
|
||||||
stylev.emplace("right_width", String::Format(wxT("%.2f"), s->right_width()));
|
stylev.emplace("right_width", wxString::Format(wxT("%.2f"), s->right_width()));
|
||||||
stylev.emplace("top_width", String::Format(wxT("%.2f"), s->top_width()));
|
stylev.emplace("top_width", wxString::Format(wxT("%.2f"), s->top_width()));
|
||||||
stylev.emplace("bottom_width", String::Format(wxT("%.2f"), s->bottom_width()));
|
stylev.emplace("bottom_width", wxString::Format(wxT("%.2f"), s->bottom_width()));
|
||||||
stylev.emplace("combine", combine_to_string( s->combine));
|
stylev.emplace("combine", combine_to_string( s->combine));
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (SymbolStyle* s = dynamic_cast<SymbolStyle*>(style.get())) {
|
else if (SymbolStyle* s = dynamic_cast<SymbolStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", "symbol");
|
stylev.emplace("field_type", "symbol");
|
||||||
stylev.emplace("min_aspect_ratio", String::Format(wxT("%.2f"), s->min_aspect_ratio));
|
stylev.emplace("min_aspect_ratio", wxString::Format(wxT("%.2f"), s->min_aspect_ratio));
|
||||||
stylev.emplace("max_aspect_ratio", String::Format(wxT("%.2f"), s->max_aspect_ratio));
|
stylev.emplace("max_aspect_ratio", wxString::Format(wxT("%.2f"), s->max_aspect_ratio));
|
||||||
boost::json::array variationsv;
|
boost::json::array variationsv;
|
||||||
int size = s->variations.size();
|
int size = s->variations.size();
|
||||||
for (int i = 0; i < size; i++) {
|
for (int i = 0; i < size; i++) {
|
||||||
boost::json::object variationv;
|
boost::json::object variationv;
|
||||||
variationv.emplace("name", s->variations[i]->name);
|
variationv.emplace("name", s->variations[i]->name);
|
||||||
variationv.emplace("border_radius", String::Format(wxT("%.2f"), s->variations[i]->border_radius));
|
variationv.emplace("border_radius", wxString::Format(wxT("%.2f"), s->variations[i]->border_radius));
|
||||||
SymbolFilterP filter = s->variations[i]->filter;
|
SymbolFilterP filter = s->variations[i]->filter;
|
||||||
if (SolidFillSymbolFilter* f = dynamic_cast<SolidFillSymbolFilter*>(filter.get())) {
|
if (SolidFillSymbolFilter* f = dynamic_cast<SolidFillSymbolFilter*>(filter.get())) {
|
||||||
variationv.emplace("fill_type", f->fillType());
|
variationv.emplace("fill_type", f->fillType());
|
||||||
variationv.emplace("fill_color", format_color( f->fill_color));
|
variationv.emplace("fill_color", format_color( f->fill_color));
|
||||||
variationv.emplace("border_color", format_color( f->border_color));
|
variationv.emplace("border_color", format_color( f->border_color));
|
||||||
}
|
}
|
||||||
else if (RadialGradientSymbolFilter* f = dynamic_cast<RadialGradientSymbolFilter*>(filter.get())) {
|
else if (RadialGradientSymbolFilter* f = dynamic_cast<RadialGradientSymbolFilter*>(filter.get())) {
|
||||||
variationv.emplace("fill_type", f->fillType());
|
variationv.emplace("fill_type", f->fillType());
|
||||||
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
|
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
|
||||||
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
|
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
|
||||||
variationv.emplace("border_color_1", format_color( f->border_color_1));
|
variationv.emplace("border_color_1", format_color( f->border_color_1));
|
||||||
variationv.emplace("border_color_2", format_color( f->border_color_2));
|
variationv.emplace("border_color_2", format_color( f->border_color_2));
|
||||||
}
|
}
|
||||||
else if (LinearGradientSymbolFilter* f = dynamic_cast<LinearGradientSymbolFilter*>(filter.get())) {
|
else if (LinearGradientSymbolFilter* f = dynamic_cast<LinearGradientSymbolFilter*>(filter.get())) {
|
||||||
variationv.emplace("fill_type", f->fillType());
|
variationv.emplace("fill_type", f->fillType());
|
||||||
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
|
variationv.emplace("fill_color_1", format_color( f->fill_color_1));
|
||||||
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
|
variationv.emplace("fill_color_2", format_color( f->fill_color_2));
|
||||||
variationv.emplace("border_color_1", format_color( f->border_color_1));
|
variationv.emplace("border_color_1", format_color( f->border_color_1));
|
||||||
variationv.emplace("border_color_2", format_color( f->border_color_2));
|
variationv.emplace("border_color_2", format_color( f->border_color_2));
|
||||||
variationv.emplace("center_x", String::Format(wxT("%.2f"), f->center_x));
|
variationv.emplace("center_x", wxString::Format(wxT("%.2f"), f->center_x));
|
||||||
variationv.emplace("center_y", String::Format(wxT("%.2f"), f->center_y));
|
variationv.emplace("center_y", wxString::Format(wxT("%.2f"), f->center_y));
|
||||||
variationv.emplace("end_x", String::Format(wxT("%.2f"), f->end_x));
|
variationv.emplace("end_x", wxString::Format(wxT("%.2f"), f->end_x));
|
||||||
variationv.emplace("end_y", String::Format(wxT("%.2f"), f->end_y));
|
variationv.emplace("end_y", wxString::Format(wxT("%.2f"), f->end_y));
|
||||||
}
|
}
|
||||||
variationsv.emplace_back(variationv);
|
variationsv.emplace_back(variationv);
|
||||||
}
|
}
|
||||||
@@ -795,34 +765,34 @@ boost::json::object mse_to_json(const StyleP& style) {
|
|||||||
|
|
||||||
else if (InfoStyle* s = dynamic_cast<InfoStyle*>(style.get())) {
|
else if (InfoStyle* s = dynamic_cast<InfoStyle*>(style.get())) {
|
||||||
stylev.emplace("field_type", "info");
|
stylev.emplace("field_type", "info");
|
||||||
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
stylev.emplace("alignment", alignment_to_string( s->alignment));
|
||||||
stylev.emplace("padding_left", String::Format(wxT("%.2f"), s->padding_left));
|
stylev.emplace("padding_left", wxString::Format(wxT("%.2f"), s->padding_left));
|
||||||
stylev.emplace("padding_right", String::Format(wxT("%.2f"), s->padding_right));
|
stylev.emplace("padding_right", wxString::Format(wxT("%.2f"), s->padding_right));
|
||||||
stylev.emplace("padding_top", String::Format(wxT("%.2f"), s->padding_top));
|
stylev.emplace("padding_top", wxString::Format(wxT("%.2f"), s->padding_top));
|
||||||
stylev.emplace("padding_bottom", String::Format(wxT("%.2f"), s->padding_bottom));
|
stylev.emplace("padding_bottom", wxString::Format(wxT("%.2f"), s->padding_bottom));
|
||||||
stylev.emplace("background_color", format_color( s->background_color));
|
stylev.emplace("background_color", format_color( s->background_color));
|
||||||
|
|
||||||
boost::json::object fontv;
|
boost::json::object fontv;
|
||||||
fontv.emplace("name", s->font.name());
|
fontv.emplace("name", s->font.name());
|
||||||
fontv.emplace("italic_name", s->font.italic_name());
|
fontv.emplace("italic_name", s->font.italic_name());
|
||||||
fontv.emplace("size", String::Format(wxT("%.2f"), s->font.size()));
|
fontv.emplace("size", wxString::Format(wxT("%.2f"), s->font.size()));
|
||||||
fontv.emplace("weight", s->font.weight());
|
fontv.emplace("weight", s->font.weight());
|
||||||
fontv.emplace("style", s->font.style());
|
fontv.emplace("style", s->font.style());
|
||||||
fontv.emplace("underline", s->font.underline());
|
fontv.emplace("underline", s->font.underline());
|
||||||
fontv.emplace("strikethrough", s->font.strikethrough());
|
fontv.emplace("strikethrough", s->font.strikethrough());
|
||||||
fontv.emplace("scale_down_to", String::Format(wxT("%.2f"), s->font.scale_down_to));
|
fontv.emplace("scale_down_to", wxString::Format(wxT("%.2f"), s->font.scale_down_to));
|
||||||
fontv.emplace("max_stretch", String::Format(wxT("%.2f"), s->font.max_stretch));
|
fontv.emplace("max_stretch", wxString::Format(wxT("%.2f"), s->font.max_stretch));
|
||||||
fontv.emplace("color", format_color( s->font.color()));
|
fontv.emplace("color", format_color( s->font.color()));
|
||||||
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
fontv.emplace("shadow_color", format_color( s->font.shadow_color()));
|
||||||
fontv.emplace("shadow_displacement_x", String::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
fontv.emplace("shadow_displacement_x", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_x()));
|
||||||
fontv.emplace("shadow_displacement_y", String::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
fontv.emplace("shadow_displacement_y", wxString::Format(wxT("%.2f"), s->font.shadow_displacement_y()));
|
||||||
fontv.emplace("shadow_blur", String::Format(wxT("%.2f"), s->font.shadow_blur()));
|
fontv.emplace("shadow_blur", wxString::Format(wxT("%.2f"), s->font.shadow_blur()));
|
||||||
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
fontv.emplace("stroke_color", format_color( s->font.stroke_color()));
|
||||||
fontv.emplace("stroke_radius", String::Format(wxT("%.2f"), s->font.stroke_radius()));
|
fontv.emplace("stroke_radius", wxString::Format(wxT("%.2f"), s->font.stroke_radius()));
|
||||||
fontv.emplace("stroke_blur", String::Format(wxT("%.2f"), s->font.stroke_blur()));
|
fontv.emplace("stroke_blur", wxString::Format(wxT("%.2f"), s->font.stroke_blur()));
|
||||||
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
fontv.emplace("separator_color", format_color( s->font.separator_color));
|
||||||
fontv.emplace("flags", String::Format(wxT("%i"), s->font.flags));
|
fontv.emplace("flags", wxString::Format(wxT("%i"), s->font.flags));
|
||||||
stylev.emplace("font", fontv);
|
stylev.emplace("font", fontv);
|
||||||
}
|
}
|
||||||
|
|
||||||
return stylev;
|
return stylev;
|
||||||
@@ -872,7 +842,7 @@ boost::json::object mse_to_json(const IndexMap<FieldP, ValueP>& map) {
|
|||||||
return indexmapv;
|
return indexmapv;
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set, bool suppress_warnings) {
|
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set) {
|
||||||
// special types
|
// special types
|
||||||
if (ScriptObject<PackItemP>* o = dynamic_cast<ScriptObject<PackItemP>*> (sv.get())) return mse_to_json( o->getValue());
|
if (ScriptObject<PackItemP>* o = dynamic_cast<ScriptObject<PackItemP>*> (sv.get())) return mse_to_json( o->getValue());
|
||||||
if (ScriptObject<PackTypeP>* o = dynamic_cast<ScriptObject<PackTypeP>*> (sv.get())) return mse_to_json( o->getValue());
|
if (ScriptObject<PackTypeP>* o = dynamic_cast<ScriptObject<PackTypeP>*> (sv.get())) return mse_to_json( o->getValue());
|
||||||
@@ -936,6 +906,6 @@ boost::json::value mse_to_json(const ScriptValueP& sv, Set* set, bool suppress_w
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!suppress_warnings) queue_message(MESSAGE_WARNING, _ERROR_1_("json unknown script type", sv->typeName()));
|
queue_message(MESSAGE_ERROR, _ERROR_1_("json unknown script type", sv->typeName()));
|
||||||
return boost::json::value(nullptr);
|
return boost::json::value(nullptr);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,4 +72,4 @@ boost::json::object mse_to_json(const Set* set);
|
|||||||
|
|
||||||
boost::json::object mse_to_json(const IndexMap<FieldP,ValueP>& map);
|
boost::json::object mse_to_json(const IndexMap<FieldP,ValueP>& map);
|
||||||
|
|
||||||
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set, bool suppress_warnings = false);
|
boost::json::value mse_to_json(const ScriptValueP& sv, Set* set);
|
||||||
|
|||||||
@@ -32,21 +32,6 @@ IndexMap<Key,Value>& DelayedIndexMaps<Key,Value>::get(const String& name, const
|
|||||||
return item->read_data;
|
return item->read_data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize this map with cloned values from another map
|
|
||||||
template <typename Key, typename Value>
|
|
||||||
void DelayedIndexMaps<Key,Value>::cloneFrom(const DelayedIndexMaps<Key,Value>& values) {
|
|
||||||
clear();
|
|
||||||
for (const auto& [name, src_ptr] : values.data) {
|
|
||||||
if (!src_ptr) continue;
|
|
||||||
auto dst_ptr = make_intrusive<DelayedIndexMapsData<Key,Value>>();
|
|
||||||
dst_ptr->unread_data = src_ptr->unread_data;
|
|
||||||
if (src_ptr->unread_data.empty()) {
|
|
||||||
dst_ptr->read_data.cloneFrom(src_ptr->read_data);
|
|
||||||
}
|
|
||||||
data[name] = dst_ptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Key, typename Value>
|
template <typename Key, typename Value>
|
||||||
void DelayedIndexMaps<Key,Value>::clear() {
|
void DelayedIndexMaps<Key,Value>::clear() {
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|||||||
@@ -60,8 +60,8 @@ public:
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/// Initialize this map with cloned values from another map
|
/// Initialize this map with cloned values from another list
|
||||||
void cloneFrom(const IndexMap<Key,Value>& values) {
|
void cloneFrom(const IndexMap<Key,Value>& values) {
|
||||||
if (this->size() == values.size()) return;
|
if (this->size() == values.size()) return;
|
||||||
this->reserve(values.size());
|
this->reserve(values.size());
|
||||||
for(size_t index = size() ; index < values.size() ; ++index) {
|
for(size_t index = size() ; index < values.size() ; ++index) {
|
||||||
@@ -147,8 +147,6 @@ class DelayedIndexMaps {
|
|||||||
public:
|
public:
|
||||||
/// Get the data for a specific name. Initialize the map with init_with (if it is not alread initialized)
|
/// Get the data for a specific name. Initialize the map with init_with (if it is not alread initialized)
|
||||||
IndexMap<Key,Value>& get(const String& name, const vector<Key>& init_with);
|
IndexMap<Key,Value>& get(const String& name, const vector<Key>& init_with);
|
||||||
/// Initialize this map with cloned values from another map
|
|
||||||
void cloneFrom(const DelayedIndexMaps<Key,Value>& values);
|
|
||||||
/// Clear the delayed index map
|
/// Clear the delayed index map
|
||||||
void clear();
|
void clear();
|
||||||
map<String, intrusive_ptr<DelayedIndexMapsData<Key,Value>>> data;
|
map<String, intrusive_ptr<DelayedIndexMapsData<Key,Value>>> data;
|
||||||
|
|||||||
@@ -684,9 +684,7 @@ void Packaged::validate(Version) {
|
|||||||
|
|
||||||
void Packaged::requireDependency(Packaged* package) {
|
void Packaged::requireDependency(Packaged* package) {
|
||||||
if (package == this) return; // dependency on self
|
if (package == this) return; // dependency on self
|
||||||
if (this->relativeFilename().find("mse-set") != String::npos) return; // skip checks on sets
|
|
||||||
String n = package->relativeFilename();
|
String n = package->relativeFilename();
|
||||||
if (n.find("mse-symbol-font") != String::npos) return; // skip checks for symbol-fonts
|
|
||||||
FOR_EACH(dep, dependencies) {
|
FOR_EACH(dep, dependencies) {
|
||||||
if (dep->package == n) {
|
if (dep->package == n) {
|
||||||
if (package->version < dep->version) {
|
if (package->version < dep->version) {
|
||||||
@@ -698,6 +696,8 @@ void Packaged::requireDependency(Packaged* package) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// skip dependency checks for symbol-fonts
|
||||||
|
if (package->relativeFilename().find("mse-symbol-font") != std::string::npos) return;
|
||||||
// dependency not found
|
// dependency not found
|
||||||
queue_message(MESSAGE_WARNING,_ERROR_4_("dependency not given", name(), package->relativeFilename(), package->relativeFilename(), package->version.toString()));
|
queue_message(MESSAGE_WARNING,_ERROR_4_("dependency not given", name(), package->relativeFilename(), package->relativeFilename(), package->version.toString()));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ using boost::tribool;
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Reader
|
// ----------------------------------------------------------------------------- : Reader
|
||||||
|
|
||||||
Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid, bool suppress_warnings)
|
Reader::Reader(wxInputStream& input, Packaged* package, const String& filename, bool ignore_invalid)
|
||||||
: indent(0), expected_indent(0), state(OUTSIDE)
|
: indent(0), expected_indent(0), state(OUTSIDE)
|
||||||
, ignore_invalid(ignore_invalid), suppress_warnings(suppress_warnings)
|
, ignore_invalid(ignore_invalid)
|
||||||
, filename(filename), package(package), line_number(0), previous_line_number(0)
|
, filename(filename), package(package), line_number(0), previous_line_number(0)
|
||||||
, input(input)
|
, input(input)
|
||||||
{
|
{
|
||||||
@@ -30,7 +30,7 @@ Reader::Reader(wxInputStream& input, Packaged* package, const String& filename,
|
|||||||
handleAppVersion();
|
handleAppVersion();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Reader::handleIgnore(Version end_version, const Char* a) {
|
void Reader::handleIgnore(int end_version, const Char* a) {
|
||||||
if (file_app_version < end_version) {
|
if (file_app_version < end_version) {
|
||||||
if (enterBlock(a)) exitBlock();
|
if (enterBlock(a)) exitBlock();
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ void Reader::warning(const String& msg, int line_number_delta, bool warn_on_prev
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Reader::showWarnings() {
|
void Reader::showWarnings() {
|
||||||
if (!suppress_warnings && !warnings.empty()) {
|
if (!warnings.empty()) {
|
||||||
queue_message(MESSAGE_WARNING, _("Warnings while reading file:\n") + filename + _("\n") + warnings);
|
queue_message(MESSAGE_WARNING, _("Warnings while reading file:\n") + filename + _("\n") + warnings);
|
||||||
warnings.clear();
|
warnings.clear();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ public:
|
|||||||
/** filename is used only for error messages
|
/** filename is used only for error messages
|
||||||
* package is used for looking up included files.
|
* package is used for looking up included files.
|
||||||
*/
|
*/
|
||||||
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = _(""), bool ignore_invalid = false, bool suppress_warnings = false);
|
Reader(wxInputStream& input, Packaged* package = nullptr, const String& filename = _(""), bool ignore_invalid = false);
|
||||||
|
|
||||||
~Reader() { showWarnings(); }
|
~Reader() { showWarnings(); }
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
/// Is the thing currently being read 'complex', i.e. does it have children
|
/// Is the thing currently being read 'complex', i.e. does it have children
|
||||||
inline bool isCompound() const { return indent != expected_indent - 1 || value.empty(); }
|
inline bool isCompound() const { return indent != expected_indent - 1 || value.empty(); }
|
||||||
/// Ignore old keys
|
/// Ignore old keys
|
||||||
void handleIgnore(Version, const Char*);
|
void handleIgnore(int, const Char*);
|
||||||
/// Get the version of the format we are reading
|
/// Get the version of the format we are reading
|
||||||
inline Version formatVersion() const { return file_app_version; }
|
inline Version formatVersion() const { return file_app_version; }
|
||||||
|
|
||||||
@@ -148,9 +148,7 @@ private:
|
|||||||
} state;
|
} state;
|
||||||
/// Should all invalid keys be ignored?
|
/// Should all invalid keys be ignored?
|
||||||
bool ignore_invalid;
|
bool ignore_invalid;
|
||||||
/// Should warnings be emitted?
|
|
||||||
bool suppress_warnings;
|
|
||||||
|
|
||||||
/// Filename for error messages
|
/// Filename for error messages
|
||||||
String filename;
|
String filename;
|
||||||
/// Package this file is from, if any
|
/// Package this file is from, if any
|
||||||
@@ -189,7 +187,7 @@ private:
|
|||||||
value = key == _("include_localized_file") ? addLocale(value) : key == _("include_dark_file") ? addDark(value) : value;
|
value = key == _("include_localized_file") ? addLocale(value) : key == _("include_dark_file") ? addDark(value) : value;
|
||||||
auto [stream, include_package] = openFileFromPackage(package, value);
|
auto [stream, include_package] = openFileFromPackage(package, value);
|
||||||
Reader sub_reader(*stream, include_package, value, ignore_invalid);
|
Reader sub_reader(*stream, include_package, value, ignore_invalid);
|
||||||
if (sub_reader.file_app_version.isZero()) {
|
if (sub_reader.file_app_version == 0) {
|
||||||
// in an included file, use the app version of the parent if there is none
|
// in an included file, use the app version of the parent if there is none
|
||||||
sub_reader.file_app_version = file_app_version;
|
sub_reader.file_app_version = file_app_version;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-29
@@ -9,8 +9,7 @@
|
|||||||
#include <util/prec.hpp>
|
#include <util/prec.hpp>
|
||||||
#include <util/rotation.hpp>
|
#include <util/rotation.hpp>
|
||||||
#include <gfx/gfx.hpp>
|
#include <gfx/gfx.hpp>
|
||||||
#include <data/font.hpp>
|
#include <data/font.hpp>
|
||||||
#include <wx/rawbmp.h>
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Rotation
|
// ----------------------------------------------------------------------------- : Rotation
|
||||||
|
|
||||||
@@ -277,33 +276,6 @@ void RotatedDC::DrawRoundedRectangle(const RealRect& r, double radius) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RotatedDC::DrawInvertRectangle(const RealRect& r) {
|
|
||||||
wxRect r_ext = trRectToBB(r);
|
|
||||||
|
|
||||||
wxBitmap bmp(r_ext.width, r_ext.height, 24);
|
|
||||||
wxMemoryDC memDC(bmp);
|
|
||||||
memDC.Blit(0, 0, r_ext.width, r_ext.height, &dc, r_ext.x, r_ext.y);
|
|
||||||
memDC.SelectObject(wxNullBitmap);
|
|
||||||
|
|
||||||
wxNativePixelData data(bmp);
|
|
||||||
if (!data) return; // Raw access not available on this platform/bitmap
|
|
||||||
wxNativePixelData::Iterator p(data);
|
|
||||||
for (int j = 0; j < r_ext.height; ++j) {
|
|
||||||
wxNativePixelData::Iterator rowStart = p;
|
|
||||||
for (int i = 0; i < r_ext.width; ++i) {
|
|
||||||
// Invert each channel
|
|
||||||
p.Red() = 255 - p.Red();
|
|
||||||
p.Green() = 255 - p.Green();
|
|
||||||
p.Blue() = 255 - p.Blue();
|
|
||||||
++p; // Move to next pixel in the row
|
|
||||||
}
|
|
||||||
p = rowStart;
|
|
||||||
p.OffsetY(data, 1); // Move to the next row
|
|
||||||
}
|
|
||||||
|
|
||||||
dc.DrawBitmap(bmp, RealPoint(r_ext.x, r_ext.y));
|
|
||||||
}
|
|
||||||
|
|
||||||
void RotatedDC::DrawCircle(const RealPoint& center, double radius) {
|
void RotatedDC::DrawCircle(const RealPoint& center, double radius) {
|
||||||
wxPoint p = tr(center);
|
wxPoint p = tr(center);
|
||||||
dc.DrawCircle(p.x + 1, p.y + 1, int(trS(radius)));
|
dc.DrawCircle(p.x + 1, p.y + 1, int(trS(radius)));
|
||||||
|
|||||||
@@ -173,7 +173,6 @@ public:
|
|||||||
void DrawLine (const RealPoint& p1, const RealPoint& p2);
|
void DrawLine (const RealPoint& p1, const RealPoint& p2);
|
||||||
void DrawRectangle(const RealRect& r);
|
void DrawRectangle(const RealRect& r);
|
||||||
void DrawRoundedRectangle(const RealRect& r, double radius);
|
void DrawRoundedRectangle(const RealRect& r, double radius);
|
||||||
void DrawInvertRectangle(const RealRect& r);
|
|
||||||
void DrawCircle(const RealPoint& center, double radius);
|
void DrawCircle(const RealPoint& center, double radius);
|
||||||
void DrawEllipse(const RealPoint& center, const RealSize& size);
|
void DrawEllipse(const RealPoint& center, const RealSize& size);
|
||||||
/// Draw an arc of an ellipse, angles are in radians
|
/// Draw an arc of an ellipse, angles are in radians
|
||||||
|
|||||||
+25
-27
@@ -13,32 +13,30 @@
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Version
|
// ----------------------------------------------------------------------------- : Version
|
||||||
|
|
||||||
UInt Version::toNumber() const { return major * 10000 + minor * 100 + revision; }
|
UInt Version::toNumber() const { return version; }
|
||||||
|
|
||||||
String Version::toString() const {
|
String Version::toString() const {
|
||||||
if (major >= 2000) {
|
if (version > 20000000) {
|
||||||
// the version is a date, use ISO notation
|
// major > 2000, the version is a date, use ISO notation
|
||||||
return String::Format(_("%04d-%02d-%02d"),
|
return String::Format(_("%04d-%02d-%02d"),
|
||||||
major,
|
(version / 10000) ,
|
||||||
minor,
|
(version / 100) % 100,
|
||||||
revision);
|
(version / 1) % 100);
|
||||||
} else {
|
} else {
|
||||||
return String::Format(_("%d.%d.%d"),
|
return String::Format(_("%d.%d.%d"),
|
||||||
major,
|
(version / 10000) ,
|
||||||
minor,
|
(version / 100) % 100,
|
||||||
revision);
|
(version / 1) % 100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Version Version::fromString(const String& version) {
|
Version Version::fromString(const String& version) {
|
||||||
if (version.empty()) return Version();
|
UInt major = 0, minor = 0, build = 0;
|
||||||
UInt major = 0, minor = 0, revision = 0;
|
if (wxSscanf(version, _("%u.%u.%u"), &major, &minor, &build)<=1) // a.b.c style
|
||||||
if (wxSscanf(version, _("%u.%u.%u"), &major, &minor, &revision)<=1) // a.b.c style
|
wxSscanf(version, _("%u-%u-%u"), &major, &minor, &build); // date style
|
||||||
wxSscanf(version, _("%u-%u-%u"), &major, &minor, &revision); // date style
|
return Version(major * 10000 + minor * 100 + build);
|
||||||
return Version(major, minor, revision);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Version::isZero() const { return revision == 0u && minor == 0u && major == 0u; }
|
|
||||||
|
|
||||||
template <> void Reader::handle(Version& v) {
|
template <> void Reader::handle(Version& v) {
|
||||||
v = Version::fromString(getValue());
|
v = Version::fromString(getValue());
|
||||||
@@ -53,7 +51,7 @@ template <> void GetDefaultMember::handle(const Version& v) {
|
|||||||
// ----------------------------------------------------------------------------- : Versions
|
// ----------------------------------------------------------------------------- : Versions
|
||||||
|
|
||||||
// NOTE: Don't use leading zeroes, they mean octal
|
// NOTE: Don't use leading zeroes, they mean octal
|
||||||
const Version app_version = Version(MSE_VERSION_MAJOR, MSE_VERSION_MINOR, MSE_VERSION_PATCH);
|
const Version app_version = 10000 * MSE_VERSION_MAJOR + 100 * MSE_VERSION_MINOR + MSE_VERSION_PATCH;
|
||||||
|
|
||||||
#if defined UNOFFICIAL_BUILD
|
#if defined UNOFFICIAL_BUILD
|
||||||
const Char* version_suffix = _(" (Unofficial)");
|
const Char* version_suffix = _(" (Unofficial)");
|
||||||
@@ -90,13 +88,13 @@ const Char* version_suffix = _(" (ascii build)");
|
|||||||
* 2.0.0 : bugfix release mostly, added error console
|
* 2.0.0 : bugfix release mostly, added error console
|
||||||
* 2.0.2 : store game and stylesheet version numbers
|
* 2.0.2 : store game and stylesheet version numbers
|
||||||
*/
|
*/
|
||||||
const Version file_version_locale = Version(2u, 0u, 2u);
|
const Version file_version_locale = 20002; // 2.0.2
|
||||||
const Version file_version_set = Version(2u, 0u, 2u);
|
const Version file_version_set = 20002; // 2.0.2
|
||||||
const Version file_version_game = Version(0u, 3u, 8u);
|
const Version file_version_game = 308; // 0.3.8
|
||||||
const Version file_version_stylesheet = Version(0u, 3u, 8u);
|
const Version file_version_stylesheet = 308; // 0.3.8
|
||||||
const Version file_version_symbol_font = Version(0u, 3u, 6u);
|
const Version file_version_symbol_font = 306; // 0.3.6
|
||||||
const Version file_version_export_template = Version(0u, 3u, 7u);
|
const Version file_version_export_template = 307; // 0.3.7
|
||||||
const Version file_version_installer = Version(0u, 3u, 7u);
|
const Version file_version_installer = 307; // 0.3.7
|
||||||
const Version file_version_symbol = Version(0u, 3u, 5u);
|
const Version file_version_symbol = 305; // 0.3.5
|
||||||
const Version file_version_clipboard = Version(2u, 6u, 0u);
|
const Version file_version_clipboard = 20002; // 2.0.2
|
||||||
const Version file_version_script = Version(0u, 3u, 7u);
|
const Version file_version_script = 307; // 0.3.7
|
||||||
|
|||||||
+13
-36
@@ -21,34 +21,16 @@
|
|||||||
/// A version number
|
/// A version number
|
||||||
struct Version {
|
struct Version {
|
||||||
public:
|
public:
|
||||||
Version() : major(0u), minor(0u), revision(0u) {}
|
Version() : version(0) {}
|
||||||
Version(UInt major, UInt minor, UInt revision) : major(major), minor(minor), revision(revision) {}
|
Version(UInt version) : version(version) {}
|
||||||
|
|
||||||
bool operator==(const Version& v) const {
|
inline bool operator == (Version v) const { return version == v.version; }
|
||||||
return std::tie(major, minor, revision)
|
inline bool operator != (Version v) const { return version != v.version; }
|
||||||
== std::tie(v.major, v.minor, v.revision);
|
inline bool operator < (Version v) const { return version < v.version; }
|
||||||
}
|
inline bool operator <= (Version v) const { return version <= v.version; }
|
||||||
bool operator!=(const Version& v) const {
|
inline bool operator > (Version v) const { return version > v.version; }
|
||||||
return std::tie(major, minor, revision)
|
inline bool operator >= (Version v) const { return version >= v.version; }
|
||||||
!= std::tie(v.major, v.minor, v.revision);
|
|
||||||
}
|
|
||||||
bool operator<(const Version& v) const {
|
|
||||||
return std::tie(major, minor, revision)
|
|
||||||
< std::tie(v.major, v.minor, v.revision);
|
|
||||||
}
|
|
||||||
bool operator>(const Version& v) const {
|
|
||||||
return std::tie(major, minor, revision)
|
|
||||||
> std::tie(v.major, v.minor, v.revision);
|
|
||||||
}
|
|
||||||
bool operator<=(const Version& v) const {
|
|
||||||
return std::tie(major, minor, revision)
|
|
||||||
<= std::tie(v.major, v.minor, v.revision);
|
|
||||||
}
|
|
||||||
bool operator>=(const Version& v) const {
|
|
||||||
return std::tie(major, minor, revision)
|
|
||||||
>= std::tie(v.major, v.minor, v.revision);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Convert a version number to a string
|
/// Convert a version number to a string
|
||||||
String toString() const;
|
String toString() const;
|
||||||
/// Get the version number as an integer number
|
/// Get the version number as an integer number
|
||||||
@@ -56,14 +38,9 @@ public:
|
|||||||
|
|
||||||
/// Convert a string to a version number
|
/// Convert a string to a version number
|
||||||
static Version fromString(const String& version);
|
static Version fromString(const String& version);
|
||||||
|
|
||||||
/// Did this version get properly initialized?
|
private:
|
||||||
bool isZero() const;
|
UInt version; ///< Version number encoded as aabbcc, where a=major, b=minor, c=revision
|
||||||
|
|
||||||
private:
|
|
||||||
UInt major = 0;
|
|
||||||
UInt minor = 0;
|
|
||||||
UInt revision = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------- : Versions
|
// ----------------------------------------------------------------------------- : Versions
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user