diff --git a/.gitignore b/.gitignore index aa34b5aaf7..89d80f05cf 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,7 @@ luajit/ spec/test_results.log spec/test_generation.log src/luacov.stats.out +runtime/lua/debugger.lua # Release manifest-updated.xml @@ -37,3 +38,7 @@ src/Data/TimelessJewelData/*.bin # Simplegraphic Debugging runtime/imgui.ini runtime/SimpleGraphic/SimpleGraphic.log +runtime/SimpleGraphic/Screenshots + +.emmyrc.json +.luarc.json \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7710d13246..6492fb38e6 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,6 +136,8 @@ It is recommended to use it over the built-in Lua plugins. Please note that EmmyLua is not available for other editors based on Visual Studio Code, such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.org) but can be built from source if needed. +Another alternative on VSCode is to use [sumneko's Lua language server](https://marketplace.visualstudio.com/items?itemName=sumneko.lua) along with [actboy168's debugger](https://marketplace.visualstudio.com/items?itemName=actboy168.lua-debug). These can potentially offer more features than EmmyLua, such as conditional breakpoints. + ### Visual Studio Code 1. Create a new Debug Configuration of type EmmyLua New Debug @@ -168,11 +170,39 @@ such as [VSCodium](https://vscodium.com) or [Eclipse Theia](https://theia-ide.or 1. In VSCode click Start Debugging (the green icon) or press F5 1. The debugger should connect +You might also want to use actboy168 debugger. This is possible by using for example the following launch.json configuration: + +```json +{ + "version": "0.2.0", + "configurations": [ + { + "name": "🍄attach", + "type": "lua", + "request": "attach", + "stopOnEntry": false, + "address": "127.0.0.1:12306", + "luaVersion": "luajit", + }, + + ] +} +``` + +Then, similarly to the EmmyLua example: + +1. Find the sub-folder that looks like `actboy168.lua-debug-x.y.z-win32-x64` in `%USERPROFILE%/.vscode/extensions`. Navigate to it and find the `debugger.lua` script under the script folder. Copy this to `runtime/lua`. +2. Copy-paste the following code snippet into `launch:OnInit()`: + ```lua + local debugger = require("debugger"):start("127.0.0.1:12306") + -- debugger:event("wait") -- Uncomment this line if you want PoB to wait until the debugger is attached. + ``` + #### Excluding directories from EmmyLua Depending on the amount of system ram you have available and the amount that gets assigned to the jvm running the emmylua language server you might run into issues when trying to debug Path of building. -Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` file to the `.vscode` folder in the root of the Path of building folder with the following content: +Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua language server to use a significant amount of memory. Sometimes causing the language server to crash. To avoid this and speed up initialization consider adding an `.emmyrc.json` to the root of the Path of building folder with the following content: ```json { @@ -182,6 +212,9 @@ Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua }, "workspace": { "ignoreGlobs": [ + "**/*_spec.lua", + "spec/**/*.lua", + "runtime/lua/sha1/lua53_ops.lua", "**/src/Data/**/*.lua", "**/src/TreeData/**/*.lua", "**/src/Modules/ModParser.lua" @@ -190,6 +223,35 @@ Files in `/Data` `/Export` and `/TreeData` can be massive and cause the EmmyLua } ``` +This file can be customised according to what you want. It is a good idea to ignore test files as these tend to add things to the global namespace, which will look confusing, and they are designed to be run by Busted. `lua53_ops.lua` produces errors and doesn't actually get imported when using LuaJIT. It can be useful to keep the data and mod parser files, but generally this will increase the time the LSP takes to index the project on startup. + +### Excluding directories from Sumneko's language server + +If you prefer to not use EmmyLua, the following configuration works well for Sumneko's VS Code extension: + +```json +{ + "Lua.workspace.ignoreDir": [ + ".vscode", + // these files add things to global that aren't there in normal + // operation + "spec/*", + "src/Export/*", + "src/HeadlessWrapper.lua", + + // this has lua 5.3 code which produces errors, but doesn't actually run + "src/runtime/lua/sha1/*", + ], + "Lua.diagnostics.disable": ["inject-field"], + // disables diagnostics even when you open one of the above + "Lua.diagnostics.ignoredFiles": "Disable", + "Lua.runtime.version": "LuaJIT", + "Lua.workspace.preloadFileSize": 1000 +} +``` + +The extension will automatically skip large files from being preloaded (controlled by `Lua.workspace.preloadFileSize`), so they don't have to be excluded. The configuration file can be found by pressing Ctrl-Shift-P and selecting `Preferences: Open Workspace Settings (JSON)`. + ### PyCharm Community / IntelliJ Idea Community 1. Create a new "Debug Configuration" of type "Emmy Debugger(NEW)". diff --git a/spec/System/TestItemParse_spec.lua b/spec/System/TestItemParse_spec.lua index 4890207cea..88935c7d13 100644 --- a/spec/System/TestItemParse_spec.lua +++ b/spec/System/TestItemParse_spec.lua @@ -5,40 +5,40 @@ describe("TestItemParse", function() end it("Rarity", function() - local item = new("Item", "Rarity: Normal\nCoral Ring") + local item = new("Item"):Item("Rarity: Normal\nCoral Ring") assert.are.equals("NORMAL", item.rarity) - item = new("Item", "Rarity: Magic\nCoral Ring") + item = new("Item"):Item("Rarity: Magic\nCoral Ring") assert.are.equals("MAGIC", item.rarity) - item = new("Item", "Rarity: Rare\nName\nCoral Ring") + item = new("Item"):Item("Rarity: Rare\nName\nCoral Ring") assert.are.equals("RARE", item.rarity) - item = new("Item", "Rarity: Unique\nName\nCoral Ring") + item = new("Item"):Item("Rarity: Unique\nName\nCoral Ring") assert.are.equals("UNIQUE", item.rarity) - item = new("Item", "Rarity: Unique\nName\nCoral Ring\nFoil Unique (Verdant)") + item = new("Item"):Item("Rarity: Unique\nName\nCoral Ring\nFoil Unique (Verdant)") assert.are.equals("RELIC", item.rarity) end) it("Superior/Synthesised", function() - local item = new("Item", raw("", "Superior Plate Vest")) + local item = new("Item"):Item(raw("", "Superior Plate Vest")) assert.are.equals("Plate Vest", item.baseName) - item = new("Item", raw("", "Synthesised Plate Vest")) + item = new("Item"):Item(raw("", "Synthesised Plate Vest")) assert.are.equals("Plate Vest", item.baseName) - item = new("Item", raw("", "Superior Synthesised Plate Vest")) + item = new("Item"):Item(raw("", "Superior Synthesised Plate Vest")) assert.are.equals("Plate Vest", item.baseName) end) it("Two-Toned Boots", function() - local item = new("Item", raw("", "Two-Toned Boots")) + local item = new("Item"):Item(raw("", "Two-Toned Boots")) assert.are.equals("Two-Toned Boots (Armour/Energy Shield)", item.baseName) - item = new("Item", raw("Armour: 10\nEnergy Shield: 10", "Two-Toned Boots")) + item = new("Item"):Item(raw("Armour: 10\nEnergy Shield: 10", "Two-Toned Boots")) assert.are.equals("Two-Toned Boots (Armour/Energy Shield)", item.baseName) - item = new("Item", raw("Armour: 10\nEvasion Rating: 10", "Two-Toned Boots")) + item = new("Item"):Item(raw("Armour: 10\nEvasion Rating: 10", "Two-Toned Boots")) assert.are.equals("Two-Toned Boots (Armour/Evasion)", item.baseName) - item = new("Item", raw("Evasion Rating: 10\nEnergy Shield: 10", "Two-Toned Boots")) + item = new("Item"):Item(raw("Evasion Rating: 10\nEnergy Shield: 10", "Two-Toned Boots")) assert.are.equals("Two-Toned Boots (Evasion/Energy Shield)", item.baseName) end) it("Magic Two-Toned Boots", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Rarity: Magic Stalwart Two-Toned Boots of Plunder Armour: 100 @@ -47,7 +47,7 @@ describe("TestItemParse", function() assert.are.equal("Two-Toned Boots (Armour/Energy Shield)", item.baseName) assert.are.equal("Stalwart ", item.namePrefix) assert.are.equal(" of Plunder", item.nameSuffix) - item = new("Item", [[ + item = new("Item"):Item([[ Rarity: Magic Sanguine Two-Toned Boots of the Phoenix Armour: 100 @@ -56,7 +56,7 @@ describe("TestItemParse", function() assert.are.equal("Two-Toned Boots (Armour/Evasion)", item.baseName) assert.are.equal("Sanguine ", item.namePrefix) assert.are.equal(" of the Phoenix", item.nameSuffix) - item = new("Item", [[ + item = new("Item"):Item([[ Rarity: Magic Stout Two-Toned Boots of the Lightning Evasion Rating: 100 @@ -68,7 +68,7 @@ describe("TestItemParse", function() end) it("Title", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Rarity: Rare Phoenix Paw Iron Gauntlets @@ -79,24 +79,24 @@ describe("TestItemParse", function() end) it("Unique ID", function() - local item = new("Item", raw("Unique ID: 40f9711d5bd7ad2bcbddaf71c705607aef0eecd3dcadaafec6c0192f79b82863")) + local item = new("Item"):Item(raw("Unique ID: 40f9711d5bd7ad2bcbddaf71c705607aef0eecd3dcadaafec6c0192f79b82863")) assert.are.equals("40f9711d5bd7ad2bcbddaf71c705607aef0eecd3dcadaafec6c0192f79b82863", item.uniqueID) end) it("Item Level", function() - local item = new("Item", raw("Item Level: 10")) + local item = new("Item"):Item(raw("Item Level: 10")) assert.are.equals(10, item.itemLevel) end) it("Quality", function() - local item = new("Item", raw("Quality: 10")) + local item = new("Item"):Item(raw("Quality: 10")) assert.are.equals(10, item.quality) - item = new("Item", raw("Quality: +12% (augmented)")) + item = new("Item"):Item(raw("Quality: +12% (augmented)")) assert.are.equals(12, item.quality) end) it("Sockets", function() - local item = new("Item", raw("Sockets: R-G R-B-W A")) + local item = new("Item"):Item(raw("Sockets: R-G R-B-W A")) assert.are.same({ { color = "R", group = 0 }, { color = "G", group = 0 }, @@ -108,56 +108,56 @@ describe("TestItemParse", function() end) it("Jewel", function() - local item = new("Item", raw("Radius: Large\nLimited to: 2", "Cobalt Jewel")) + local item = new("Item"):Item(raw("Radius: Large\nLimited to: 2", "Cobalt Jewel")) assert.are.equals("Large", item.jewelRadiusLabel) assert.are.equals(2, item.limit) end) it("Variant name", function() - local item = new("Item", raw("Variant: Pre 3.19.0\nVariant: Current")) + local item = new("Item"):Item(raw("Variant: Pre 3.19.0\nVariant: Current")) assert.are.same({ "Pre 3.19.0", "Current" }, item.variantList) end) it("Talisman Tier", function() - local item = new("Item", raw("Talisman Tier: 3", "Rotfeather Talisman")) + local item = new("Item"):Item(raw("Talisman Tier: 3", "Rotfeather Talisman")) assert.are.equals(3, item.talismanTier) end) it("Defence", function() - local item = new("Item", raw("Armour: 25")) + local item = new("Item"):Item(raw("Armour: 25")) assert.are.equals(25, item.armourData.Armour) - item = new("Item", raw("Armour: 25 (augmented)")) + item = new("Item"):Item(raw("Armour: 25 (augmented)")) assert.are.equals(25, item.armourData.Armour) - item = new("Item", raw("Evasion Rating: 35", "Shabby Jerkin")) + item = new("Item"):Item(raw("Evasion Rating: 35", "Shabby Jerkin")) assert.are.equals(35, item.armourData.Evasion) - item = new("Item", raw("Energy Shield: 15", "Simple Robe")) + item = new("Item"):Item(raw("Energy Shield: 15", "Simple Robe")) assert.are.equals(15, item.armourData.EnergyShield) - item = new("Item", raw("Ward: 180", "Runic Crown")) + item = new("Item"):Item(raw("Ward: 180", "Runic Crown")) assert.are.equals(180, item.armourData.Ward) end) it("Defence BasePercentile", function() - local item = new("Item", raw("ArmourBasePercentile: 0.5")) + local item = new("Item"):Item(raw("ArmourBasePercentile: 0.5")) assert.are.equals(0.5, item.armourData.ArmourBasePercentile) - item = new("Item", raw("EvasionBasePercentile: 0.6", "Shabby Jerkin")) + item = new("Item"):Item(raw("EvasionBasePercentile: 0.6", "Shabby Jerkin")) assert.are.equals(0.6, item.armourData.EvasionBasePercentile) - item = new("Item", raw("EnergyShieldBasePercentile: 0.7", "Simple Robe")) + item = new("Item"):Item(raw("EnergyShieldBasePercentile: 0.7", "Simple Robe")) assert.are.equals(0.7, item.armourData.EnergyShieldBasePercentile) - item = new("Item", raw("WardBasePercentile: 0.8", "Runic Crown")) + item = new("Item"):Item(raw("WardBasePercentile: 0.8", "Runic Crown")) assert.are.equals(0.8, item.armourData.WardBasePercentile) end) it("Requires Level", function() - local item = new("Item", raw("Requires Level 10")) + local item = new("Item"):Item(raw("Requires Level 10")) assert.are.equals(10, item.requirements.level) - item = new("Item", raw("Level: 10")) + item = new("Item"):Item(raw("Level: 10")) assert.are.equals(10, item.requirements.level) - item = new("Item", raw("LevelReq: 10")) + item = new("Item"):Item(raw("LevelReq: 10")) assert.are.equals(10, item.requirements.level) end) it("Alt Variant", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Has Alt Variant: true Has Alt Variant Two: true Has Alt Variant Three: true @@ -184,7 +184,7 @@ describe("TestItemParse", function() end) it("Prefix/Suffix", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Prefix: {range:0.1}IncreasedLife1 Suffix: {range:0.2}ColdResist1 ]])) @@ -195,7 +195,7 @@ describe("TestItemParse", function() end) it("Implicits", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Implicits: 2 +8 to Strength +10 to Intelligence @@ -209,38 +209,38 @@ describe("TestItemParse", function() end) it("League", function() - local item = new("Item", raw("League: Heist")) + local item = new("Item"):Item(raw("League: Heist")) assert.are.equals("Heist", item.league) end) it("Source", function() - local item = new("Item", raw("Source: No longer obtainable")) + local item = new("Item"):Item(raw("Source: No longer obtainable")) assert.are.equals("No longer obtainable", item.source) end) it("Note", function() - local item = new("Item", raw("Note: ~price 1 chaos")) + local item = new("Item"):Item(raw("Note: ~price 1 chaos")) assert.are.equals("~price 1 chaos", item.note) end) it("Attribute Requirements", function() - local item = new("Item", raw("Dex: 100")) + local item = new("Item"):Item(raw("Dex: 100")) assert.are.equals(100, item.requirements.dex) - item = new("Item", raw("Int: 101")) + item = new("Item"):Item(raw("Int: 101")) assert.are.equals(101, item.requirements.int) - item = new("Item", raw("Str: 102")) + item = new("Item"):Item(raw("Str: 102")) assert.are.equals(102, item.requirements.str) end) it("Requires Class", function() - local item = new("Item", raw("Requires Class Witch")) + local item = new("Item"):Item(raw("Requires Class Witch")) assert.are.equals("Witch", item.classRestriction) - item = new("Item", raw("Class:: Witch")) + item = new("Item"):Item(raw("Class:: Witch")) assert.are.equals("Witch", item.classRestriction) end) it("Requires Class variant", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Selected Variant: 2 +8 to Strength {variant:1}Requires Class Witch @@ -251,70 +251,70 @@ describe("TestItemParse", function() end) it("Influence", function() - local item = new("Item", raw("Shaper Item")) + local item = new("Item"):Item(raw("Shaper Item")) assert.truthy(item.shaper) - item = new("Item", raw("Elder Item")) + item = new("Item"):Item(raw("Elder Item")) assert.truthy(item.elder) - item = new("Item", raw("Warlord Item")) + item = new("Item"):Item(raw("Warlord Item")) assert.truthy(item.adjudicator) - item = new("Item", raw("Hunter Item")) + item = new("Item"):Item(raw("Hunter Item")) assert.truthy(item.basilisk) - item = new("Item", raw("Crusader Item")) + item = new("Item"):Item(raw("Crusader Item")) assert.truthy(item.crusader) - item = new("Item", raw("Redeemer Item")) + item = new("Item"):Item(raw("Redeemer Item")) assert.truthy(item.eyrie) - item = new("Item", raw("Searing Exarch Item")) + item = new("Item"):Item(raw("Searing Exarch Item")) assert.truthy(item.cleansing) - item = new("Item", raw("Eater of Worlds Item")) + item = new("Item"):Item(raw("Eater of Worlds Item")) assert.truthy(item.tangle) end) it("short flags", function() - local item = new("Item", raw("Split")) + local item = new("Item"):Item(raw("Split")) assert.truthy(item.split) - item = new("Item", raw("Mirrored")) + item = new("Item"):Item(raw("Mirrored")) assert.truthy(item.mirrored) - item = new("Item", raw("Corrupted")) + item = new("Item"):Item(raw("Corrupted")) assert.truthy(item.corrupted) - item = new("Item", raw("Fractured Item")) + item = new("Item"):Item(raw("Fractured Item")) assert.truthy(item.fractured) - item = new("Item", raw("Synthesised Item")) + item = new("Item"):Item(raw("Synthesised Item")) assert.truthy(item.synthesised) - item = new("Item", raw("Crafted: true")) + item = new("Item"):Item(raw("Crafted: true")) assert.truthy(item.crafted) - item = new("Item", raw("Unreleased: true")) + item = new("Item"):Item(raw("Unreleased: true")) assert.truthy(item.unreleased) end) it("long flags", function() - local item = new("Item", raw("This item can be anointed by Cassia")) + local item = new("Item"):Item(raw("This item can be anointed by Cassia")) assert.truthy(item.canBeAnointed) - item = new("Item", raw("Can have a second Enchantment Modifier")) + item = new("Item"):Item(raw("Can have a second Enchantment Modifier")) assert.truthy(item.canHaveTwoEnchants) - item = new("Item", raw("Can have 1 additional Enchantment Modifiers")) + item = new("Item"):Item(raw("Can have 1 additional Enchantment Modifiers")) assert.truthy(item.canHaveTwoEnchants) - item = new("Item", raw("Can have 2 additional Enchantment Modifiers")) + item = new("Item"):Item(raw("Can have 2 additional Enchantment Modifiers")) assert.truthy(item.canHaveTwoEnchants) assert.truthy(item.canHaveThreeEnchants) - item = new("Item", raw("Can have 3 additional Enchantment Modifiers")) + item = new("Item"):Item(raw("Can have 3 additional Enchantment Modifiers")) assert.truthy(item.canHaveTwoEnchants) assert.truthy(item.canHaveThreeEnchants) assert.truthy(item.canHaveFourEnchants) - item = new("Item", raw("Has a Crucible Passive Skill Tree with only Support Passive Skills")) + item = new("Item"):Item(raw("Has a Crucible Passive Skill Tree with only Support Passive Skills")) assert.truthy(item.canHaveOnlySupportSkillsCrucibleTree) - item = new("Item", raw("Has a Crucible Passive Skill Tree")) + item = new("Item"):Item(raw("Has a Crucible Passive Skill Tree")) assert.truthy(item.canHaveShieldCrucibleTree) - item = new("Item", raw("Has a Two Handed Sword Crucible Passive Skill Tree")) + item = new("Item"):Item(raw("Has a Two Handed Sword Crucible Passive Skill Tree")) assert.truthy(item.canHaveTwoHandedSwordCrucibleTree) end) it("tags", function() - local item = new("Item", raw("{tags:life,physical_damage}+8 to Strength")) + local item = new("Item"):Item(raw("{tags:life,physical_damage}+8 to Strength")) assert.are.same({ "life", "physical_damage" }, item.explicitModLines[1].modTags) end) it("variant", function() - local item = new("Item", raw([[ + local item = new("Item"):Item(raw([[ Selected Variant: 2 {variant:1}+8 to Strength {variant:2,3}+10 to Strength @@ -326,37 +326,37 @@ describe("TestItemParse", function() end) it("range", function() - local item = new("Item", raw("{range:0.8}+(8-12) to Strength")) + local item = new("Item"):Item(raw("{range:0.8}+(8-12) to Strength")) assert.are.equals(0.8, item.explicitModLines[1].range) assert.are.equals(11, item.baseModList[1].value) -- range 0.8 of (8-12) = 11 end) it("crafted", function() - local item = new("Item", raw("{crafted}+8 to Strength")) + local item = new("Item"):Item(raw("{crafted}+8 to Strength")) assert.truthy(item.explicitModLines[1].crafted) - item = new("Item", raw("+8 to Strength (crafted)")) + item = new("Item"):Item(raw("+8 to Strength (crafted)")) assert.truthy(item.explicitModLines[1].crafted) end) it("crucible", function() - local item = new("Item", raw("{crucible}+8 to Strength")) + local item = new("Item"):Item(raw("{crucible}+8 to Strength")) assert.truthy(item.crucibleModLines[1].crucible) - item = new("Item", raw("+8 to Strength (crucible)")) + item = new("Item"):Item(raw("+8 to Strength (crucible)")) assert.truthy(item.crucibleModLines[1].crucible) end) it("custom", function() - local item = new("Item", raw("{custom}+8 to Strength")) + local item = new("Item"):Item(raw("{custom}+8 to Strength")) assert.truthy(item.explicitModLines[1].custom) end) it("eater", function() - local item = new("Item", raw("{eater}+8 to Strength")) + local item = new("Item"):Item(raw("{eater}+8 to Strength")) assert.truthy(item.explicitModLines[1].eater) end) it("enchant", function() - local item = new("Item", raw("+8 to Strength (enchant)")) + local item = new("Item"):Item(raw("+8 to Strength (enchant)")) assert.are.equals(1, #item.enchantModLines) -- enchant also sets crafted and implicit assert.truthy(item.enchantModLines[1].crafted) @@ -364,36 +364,36 @@ describe("TestItemParse", function() end) it("exarch", function() - local item = new("Item", raw("{exarch}+8 to Strength")) + local item = new("Item"):Item(raw("{exarch}+8 to Strength")) assert.truthy(item.explicitModLines[1].exarch) end) it("fractured", function() - local item = new("Item", raw("{fractured}+8 to Strength")) + local item = new("Item"):Item(raw("{fractured}+8 to Strength")) assert.truthy(item.explicitModLines[1].fractured) - item = new("Item", raw("+8 to Strength (fractured)")) + item = new("Item"):Item(raw("+8 to Strength (fractured)")) assert.truthy(item.explicitModLines[1].fractured) end) it("implicit", function() - local item = new("Item", raw("+8 to Strength (implicit)")) + local item = new("Item"):Item(raw("+8 to Strength (implicit)")) assert.truthy(item.implicitModLines[1].implicit) end) it("scourge", function() - local item = new("Item", raw("{scourge}+8 to Strength")) + local item = new("Item"):Item(raw("{scourge}+8 to Strength")) assert.truthy(item.scourgeModLines[1].scourge) - item = new("Item", raw("+8 to Strength (scourge)")) + item = new("Item"):Item(raw("+8 to Strength (scourge)")) assert.truthy(item.scourgeModLines[1].scourge) end) it("synthesis", function() - local item = new("Item", raw("{synthesis}+8 to Strength")) + local item = new("Item"):Item(raw("{synthesis}+8 to Strength")) assert.truthy(item.explicitModLines[1].synthesis) end) it("multiple bases", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Ashcaller Selected Variant: 3 {variant:1,2,3}Quartz Wand @@ -405,7 +405,7 @@ describe("TestItemParse", function() }, item.baseLines) assert.are.equals("Quartz Wand", item.baseName) - item = new("Item", [[ + item = new("Item"):Item([[ Ashcaller Selected Variant: 4 {variant:1,2,3}Quartz Wand @@ -415,7 +415,7 @@ describe("TestItemParse", function() end) it("parses text without armour value then changes quality and has correct final armour", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Armour Gloves Iron Gauntlets Quality: 0 @@ -428,7 +428,7 @@ describe("TestItemParse", function() end) it("magic item", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Rarity: MAGIC Name Prefix Iron Gauntlets -> +50 ignite chance +50% chance to Ignite @@ -442,13 +442,13 @@ describe("TestItemParse", function() end) it("Energy Blade", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Item Class: One Hand Swords Rarity: Magic Superior Energy Blade ]]) assert.are.equal("Energy Blade One Handed", item.baseName) - item = new("Item", [[ + item = new("Item"):Item([[ Item Class: Two Hand Swords Rarity: Magic Superior Energy Blade @@ -457,7 +457,7 @@ describe("TestItemParse", function() end) it("Flask buff", function() - local item = new("Item", [[ + local item = new("Item"):Item([[ Rarity: Magic Chemist's Granite Flask of the Opossum ]]) diff --git a/spec/System/TestItemTools_spec.lua b/spec/System/TestItemTools_spec.lua index 40224f2627..516202c914 100644 --- a/spec/System/TestItemTools_spec.lua +++ b/spec/System/TestItemTools_spec.lua @@ -50,7 +50,7 @@ describe("TestItemTools", function() if not common.classes.ItemsTab then LoadModule("Classes/ItemsTab") end - local item = new("Item", [[ + local item = new("Item"):Item([[ Rarity: Rare Dire Thread Cord Belt diff --git a/spec/System/TestRadiusJewelStatDiff_spec.lua b/spec/System/TestRadiusJewelStatDiff_spec.lua index 008fa01e54..3ba4d1eaa1 100644 --- a/spec/System/TestRadiusJewelStatDiff_spec.lua +++ b/spec/System/TestRadiusJewelStatDiff_spec.lua @@ -144,7 +144,7 @@ end -- parsing path: the mod sets jewelData.radiusIndex (an annular ring index, not -- the same as the full-circle index 3 that "Radius: Large" would produce). local function newThreadOfHope() - return new("Item", "Rarity: UNIQUE\n" .. + return new("Item"):Item("Rarity: UNIQUE\n" .. "Thread of Hope\n" .. "Crimson Jewel\n" .. "Variant: Large Ring\n" .. @@ -156,7 +156,7 @@ local function newThreadOfHope() end local function newCustomLeapJewel(name) - return new("Item", "Rarity: RARE\n" .. + return new("Item"):Item("Rarity: RARE\n" .. name .. "\n" .. "Crimson Jewel\n" .. "Radius: Variable\n" .. @@ -166,7 +166,7 @@ local function newCustomLeapJewel(name) end local function newPlainJewel() - return new("Item", "Rarity: RARE\n" .. + return new("Item"):Item("Rarity: RARE\n" .. "Plain Spark\n" .. "Crimson Jewel\n" .. "Implicits: 0\n") @@ -176,7 +176,7 @@ end -- a specific keystone. The parser populates both impossibleEscapeKeystone -- and impossibleEscapeKeystones from the "in Radius of X" mod. local function newImpossibleEscape(keystoneName) - return new("Item", "Rarity: UNIQUE\n" .. + return new("Item"):Item("Rarity: UNIQUE\n" .. "Impossible Escape\n" .. "Viridian Jewel\n" .. "Radius: Small\n" .. @@ -196,7 +196,7 @@ end -- text are intentionally omitted; the tests exercise behavior, not the parser -- against the full serialized form. local function newLethalPride() - return new("Item", "Rarity: UNIQUE\n" .. + return new("Item"):Item("Rarity: UNIQUE\n" .. "Lethal Pride\n" .. "Timeless Jewel\n" .. "Radius: Large\n" .. @@ -211,7 +211,7 @@ end -- will reset the modList back to the original tree node modList. local function simulateKaruiConquest(node) node.conqueredBy = { id = 10000, conqueror = { id = 1, type = "karui" } } - node.modList = new("ModList") + node.modList = new("ModList"):ModList() node.modList:NewMod("Life", "BASE", 100, "Timeless Jewel") end @@ -220,7 +220,7 @@ local function overrideNodeWithLife(spec, node, life) override.id = node.id override.dn = node.dn override.sd = { "+" .. life .. " to maximum Life" } - override.modList = new("ModList") + override.modList = new("ModList"):ModList() override.modList:NewMod("Life", "BASE", life, "Test") spec.hashOverrides[node.id] = override end @@ -456,7 +456,7 @@ describe("TestRadiusJewelStatDiff", function() local plainJewel = newPlainJewel() build.itemsTab:AddItem(plainJewel, true) - local tooltip = new("Tooltip") + local tooltip = new("Tooltip"):Tooltip() build.itemsTab:AddItemTooltip(tooltip, plainJewel, slot) assert.is_true(tooltipContains(tooltip, "Equipping this item in"), @@ -515,7 +515,7 @@ describe("TestRadiusJewelStatDiff", function() assert.are.equals(2, #targetNode.intuitiveLeapLikesAffecting, "Allocated overlap node should still be supported by both radius jewels") - local tooltip = new("Tooltip") + local tooltip = new("Tooltip"):Tooltip() build.itemsTab:AddItemTooltip(tooltip, itemA, slotA) assert.is_false(tooltipContainsNegativeStat(tooltip, "Total Life"), @@ -590,7 +590,7 @@ describe("TestRadiusJewelStatDiff", function() assert.is_true(#nodesInRadius > 0, "Should have allocated nodes in jewel radius") simulateKaruiConquest(nodesInRadius[1]) - local tooltip = new("Tooltip") + local tooltip = new("Tooltip"):Tooltip() build.itemsTab:AddItemTooltip(tooltip, item, slot) assert.is_true(tooltipContains(tooltip, "Removing this item"), diff --git a/spec/System/TestTradeQueryCurrency_spec.lua b/spec/System/TestTradeQueryCurrency_spec.lua index d412af2950..13fb6fb4ca 100644 --- a/spec/System/TestTradeQueryCurrency_spec.lua +++ b/spec/System/TestTradeQueryCurrency_spec.lua @@ -2,7 +2,7 @@ describe("TradeQuery Currency Conversion", function() local mock_tradeQuery before_each(function() - mock_tradeQuery = new("TradeQuery", { itemsTab = {} }) + mock_tradeQuery = new("TradeQuery"):TradeQuery({ itemsTab = {} }) end) -- test case for commit: "Skip callback on errors to prevent incomplete conversions" diff --git a/spec/System/TestTradeQueryGenerator_spec.lua b/spec/System/TestTradeQueryGenerator_spec.lua index befb96a657..b495860d63 100644 --- a/spec/System/TestTradeQueryGenerator_spec.lua +++ b/spec/System/TestTradeQueryGenerator_spec.lua @@ -1,5 +1,5 @@ describe("TradeQueryGenerator", function() - local mock_queryGen = new("TradeQueryGenerator", { itemsTab = {} }) + local mock_queryGen = new("TradeQueryGenerator"):TradeQueryGenerator({ itemsTab = {} }) describe("ProcessMod", function() -- Pass: Mod line maps correctly to trade stat entry without error diff --git a/spec/System/TestTradeQueryRateLimiter_spec.lua b/spec/System/TestTradeQueryRateLimiter_spec.lua index 4542385fdf..c1457f2be0 100644 --- a/spec/System/TestTradeQueryRateLimiter_spec.lua +++ b/spec/System/TestTradeQueryRateLimiter_spec.lua @@ -3,7 +3,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Extracts keys/values correctly -- Fail: Nil/malformed values, indicating regex failure, breaking policy updates from API it("parses basic headers", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local headers = limiter:ParseHeader("X-Rate-Limit-Policy: test\nRetry-After: 5\nContent-Type: json") assert.are.equal(headers["x-rate-limit-policy"], "test") assert.are.equal(headers["retry-after"], "5") @@ -15,7 +15,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Extracts rules/limits/states accurately -- Fail: Wrong buckets/windows, indicating parsing bug, enforcing incorrect rates it("parses full policy", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local header = "X-Rate-Limit-Policy: trade-search-request-limit\nX-Rate-Limit-Rules: Ip,Account\nX-Rate-Limit-Ip: 8:10:60,15:60:120\nX-Rate-Limit-Ip-State: 7:10:60,14:60:120\nX-Rate-Limit-Account: 2:5:60\nX-Rate-Limit-Account-State: 1:5:60\nRetry-After: 10" local policies = limiter:ParsePolicy(header) local policy = policies["trade-search-request-limit"] @@ -30,7 +30,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Reduces limits (e.g., 5 -> 4) -- Fail: Unchanged limits, indicating margin ignored, risking user over-requests it("applies margin to limits", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() limiter.limitMargin = 1 local header = "X-Rate-Limit-Policy: test\nX-Rate-Limit-Rules: Ip\nX-Rate-Limit-Ip: 5:10:60\nX-Rate-Limit-Ip-State: 4:10:60" limiter:UpdateFromHeader(header) @@ -42,7 +42,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Delays past timestamp -- Fail: Allows immediate request, indicating ignored cooldowns, causing 429 errors it("blocks on retry-after", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local now = os.time() limiter.policies["test"] = {} limiter.retryAfter["test"] = now + 10 @@ -53,7 +53,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Calculates delay from timestamps -- Fail: Allows request in limit, indicating state misread, over-throttling or bans it("blocks on window limit", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() local now = os.time() limiter.policies["test"] = { ["ip"] = { ["limits"] = { ["10"] = { ["request"] = 1, ["timeout"] = 60 } }, ["state"] = { ["10"] = { ["request"] = 1, ["timeout"] = 0 } } } } limiter.requestHistory["test"] = { timestamps = {now - 5} } @@ -67,7 +67,7 @@ describe("TradeQueryRateLimiter", function() -- Pass: Removes old stamps, decrements to 1 -- Fail: Stale data persists, indicating aging bug, perpetual blocking it("cleans up timestamps and decrements", function() - local limiter = new("TradeQueryRateLimiter") + local limiter = new("TradeQueryRateLimiter"):TradeQueryRateLimiter() limiter.policies["test"] = { ["ip"] = { ["state"] = { ["10"] = { ["request"] = 2, ["timeout"] = 0, ["decremented"] = nil } } } } limiter.requestHistory["test"] = { timestamps = {os.time() - 15, os.time() - 5}, maxWindow=10, lastCheck=os.time() - 10 } limiter:AgeOutRequests("test", os.time()) diff --git a/spec/System/TestTradeQueryRequests_spec.lua b/spec/System/TestTradeQueryRequests_spec.lua index 873b5102d5..7fc621fdb7 100644 --- a/spec/System/TestTradeQueryRequests_spec.lua +++ b/spec/System/TestTradeQueryRequests_spec.lua @@ -12,7 +12,7 @@ describe("TradeQueryRequests", function() return key end } - local requests = new("TradeQueryRequests", mock_limiter) + local requests = new("TradeQueryRequests"):TradeQueryRequests(mock_limiter) local function simulateRetry(requests, mock_limiter, policy, current_time) local now = current_time diff --git a/spec/System/TestTradeQuery_spec.lua b/spec/System/TestTradeQuery_spec.lua index 332374a839..222959e021 100644 --- a/spec/System/TestTradeQuery_spec.lua +++ b/spec/System/TestTradeQuery_spec.lua @@ -7,7 +7,7 @@ describe("TradeQuery", function() -- lives behind a callback we never trigger, or is already initialized -- by the TradeQuery constructor. local function newTradeQuery(state) - local tq = new("TradeQuery", { itemsTab = {} }) + local tq = new("TradeQuery"):TradeQuery({ itemsTab = {} }) tq.itemsTab.activeItemSet = {} tq.itemsTab.slots = {} tq.slotTables[1] = { slotName = "Ring 1" } @@ -27,7 +27,7 @@ describe("TradeQuery", function() -- No sorted results at all -> first guard must short-circuit. local tq = newTradeQuery({}) local dropdown = buildRow1Dropdown(tq) - local tooltip = new("Tooltip") + local tooltip = new("Tooltip"):Tooltip() assert.has_no.errors(function() dropdown.tooltipFunc(tooltip, "DROP", 1, nil) @@ -46,7 +46,7 @@ describe("TradeQuery", function() }) local dropdown = buildRow1Dropdown(tq) tq.resultTbl[1] = {} - local tooltip = new("Tooltip") + local tooltip = new("Tooltip"):Tooltip() assert.has_no.errors(function() dropdown.tooltipFunc(tooltip, "DROP", 1, nil) diff --git a/src/Classes/BuildListControl.lua b/src/Classes/BuildListControl.lua index 3f42430ce9..d4cbff5460 100644 --- a/src/Classes/BuildListControl.lua +++ b/src/Classes/BuildListControl.lua @@ -6,15 +6,18 @@ local ipairs = ipairs local s_format = string.format -local BuildListClass = newClass("BuildListControl", "ListControl", function(self, anchor, rect, listMode) - self.ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) +---@class BuildListControl: ListControl +local BuildListClass = newClass("BuildListControl", "ListControl") + +function BuildListClass:BuildListControl(anchor, rect, listMode) + self:ListControl(anchor, rect, 20, "VERTICAL", false, listMode.list) self.listMode = listMode - self.colList = { - { width = function() return self:GetProperty("width") - 172 end }, + self.colList = { + { width = function() return self:GetProperty("width") - 172 end }, { }, } self.showRowSeparators = true - self.controls.path = new("PathControl", {"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, listMode.subPath, function(subPath) + self.controls.path = new("PathControl"):PathControl({"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, listMode.subPath, function(subPath) listMode.subPath = subPath listMode:BuildList() self.selIndex = nil @@ -41,10 +44,11 @@ local BuildListClass = newClass("BuildListControl", "ListControl", function(self end end self.dragTargetList = { self.controls.path, self } - self.controls.path.width = function () + self.controls.path.width = function() return self.width() end -end) + return self +end function BuildListClass:SelByFileName(selFileName) for index, build in ipairs(self.list) do @@ -74,8 +78,8 @@ end function BuildListClass:RenameBuild(build, copyOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter the new name for this "..(build.folderName and "folder:" or "build:")) - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, build.folderName or build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter the new name for this "..(build.folderName and "folder:" or "build:")) + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, build.folderName or build.buildName, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.save.enabled = false if build.folderName then if buf:match("%S") then @@ -97,7 +101,7 @@ function BuildListClass:RenameBuild(build, copyOnName) end end end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() local newBuildName = controls.edit.buf if build.folderName then if copyOnName then @@ -132,7 +136,7 @@ function BuildListClass:RenameBuild(build, copyOnName) self.listMode:SelectControl(self) end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() self.listMode:SelectControl(self) end) diff --git a/src/Classes/ButtonControl.lua b/src/Classes/ButtonControl.lua index a37c6fc658..e231280f5e 100644 --- a/src/Classes/ButtonControl.lua +++ b/src/Classes/ButtonControl.lua @@ -3,14 +3,18 @@ -- Class: Button Control -- Basic button control. -- -local ButtonClass = newClass("ButtonControl", "Control", "TooltipHost", function(self, anchor, rect, label, onClick, onHover, forceTooltip) - self.Control(anchor, rect) - self.TooltipHost() +---@class ButtonControl: Control, TooltipHost +local ButtonClass = newClass("ButtonControl", "Control", "TooltipHost") + +function ButtonClass:ButtonControl(anchor, rect, label, onClick, onHover, forceTooltip) + self:Control(anchor, rect) + self:TooltipHost() self.label = label self.onClick = onClick self.onHover = onHover self.forceTooltip = forceTooltip -end) + return self +end function ButtonClass:Click() if self:IsShown() and self:IsEnabled() then diff --git a/src/Classes/CalcBreakdownControl.lua b/src/Classes/CalcBreakdownControl.lua index c93ff9f84c..47c7f48649 100644 --- a/src/Classes/CalcBreakdownControl.lua +++ b/src/Classes/CalcBreakdownControl.lua @@ -13,19 +13,24 @@ local m_cos = math.cos local m_pi = math.pi local band = bit.band -local CalcBreakdownClass = newClass("CalcBreakdownControl", "Control", "ControlHost", function(self, calcsTab) - self.Control() - self.ControlHost() +---@class CalcBreakdownControl: Control, ControlHost +local CalcBreakdownClass = newClass("CalcBreakdownControl", "Control", "ControlHost") + +function CalcBreakdownClass:CalcBreakdownControl(calcsTab) + self:Control() + self:ControlHost() self.calcsTab = calcsTab self.shown = false - self.tooltip = new("Tooltip") - self.nodeViewer = new("PassiveTreeView") + self.tooltip = new("Tooltip"):Tooltip() + self.nodeViewer = new("PassiveTreeView"):PassiveTreeView() self.rangeGuide = NewImageHandle() self.rangeGuide:Load("Assets/range_guide.png") self.uiOverlay = NewImageHandle() self.uiOverlay:Load("Assets/game_ui_small.png") - self.controls.scrollBar = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-2, 0, 18, 0}, 80, "VERTICAL", true) -end) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({ "RIGHT", self, "RIGHT" }, { -2, 0, 18, 0 }, 80, + "VERTICAL", true) + return self +end function CalcBreakdownClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/CalcSectionControl.lua b/src/Classes/CalcSectionControl.lua index 75be52c567..d5407bad43 100644 --- a/src/Classes/CalcSectionControl.lua +++ b/src/Classes/CalcSectionControl.lua @@ -5,9 +5,12 @@ -- local t_insert = table.insert -local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost", function(self, calcsTab, width, id, group, colour, subSection, updateFunc) - self.Control(calcsTab, {0, 0, width, 0}) - self.ControlHost() +---@class CalcSectionControl: Control, ControlHost +local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost") + +function CalcSectionClass:CalcSectionControl(calcsTab, width, id, group, colour, subSection, updateFunc) + self:Control(calcsTab, {0, 0, width, 0}) + self:ControlHost() self.calcsTab = calcsTab self.id = id self.group = group @@ -33,7 +36,7 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" end end subSec.collapsed = subSec.defaultCollapsed - self.controls["toggle"..i] = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-3, -13 + (16 * i), 16, 16}, function() + self.controls["toggle"..i] = new("ButtonControl"):ButtonControl({"TOPRIGHT",self,"TOPRIGHT"}, {-3, -13 + (16 * i), 16, 16}, function() return subSec.collapsed and "+" or "-" end, function() subSec.collapsed = not subSec.collapsed @@ -52,7 +55,8 @@ local CalcSectionClass = newClass("CalcSectionControl", "Control", "ControlHost" self.shown = function() return self.enabled end -end) + return self +end function CalcSectionClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/CalcsTab.lua b/src/Classes/CalcsTab.lua index 690103ba09..a9975f9191 100644 --- a/src/Classes/CalcsTab.lua +++ b/src/Classes/CalcsTab.lua @@ -16,10 +16,14 @@ local buffModeDropList = { { label = "Effective DPS", buffMode = "EFFECTIVE" } } -local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class CalcsTab: UndoHandler, ControlHost, Control +local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function CalcsTabClass:CalcsTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build @@ -32,13 +36,13 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.colWidth = 230 self.sectionList = { } - self.controls.search = new("EditControl", {"TOPLEFT",self,"TOPLEFT"}, {4, 5, 260, 20}, "", "Search", "%c", 100, nil, nil, nil, true) + self.controls.search = new("EditControl"):EditControl({"TOPLEFT",self,"TOPLEFT"}, {4, 5, 260, 20}, "", "Search", "%c", 100, nil, nil, nil, true) t_insert(self.controls, self.controls.search) -- Special section for skill/mode selection self:NewSection(3, "SkillSelect", 1, colorCodes.NORMAL, {{ defaultCollapsed = false, label = "View Skill Details", data = { { label = "Socket Group", { controlName = "mainSocketGroup", - control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 300, 16}, nil, function(index, value) self.input.skill_number = index self:AddUndoState() self.build.buildFlag = true @@ -52,14 +56,14 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro } }, }, { label = "Active Skill", { controlName = "mainSkill", - control = new("DropDownControl", nil, {0, 0, 300, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 300, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] mainSocketGroup.mainActiveSkillCalcs = index self.build.buildFlag = true end) }, }, { label = "Skill Part", playerFlag = "multiPart", { controlName = "mainSkillPart", - control = new("DropDownControl", nil, {0, 0, 250, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 250, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillPartCalcs = index @@ -67,7 +71,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro self.build.buildFlag = true end) }, },{ label = "Skill Stages", playerFlag = "multiStage", { controlName = "mainSkillStageCount", - control = new("EditControl", nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) + control = new("EditControl"):EditControl(nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillStageCountCalcs = tonumber(buf) @@ -76,7 +80,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro end) }, }, { label = "Active Mines", playerFlag = "mine", { controlName = "mainSkillMineCount", - control = new("EditControl", nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) + control = new("EditControl"):EditControl(nil, {0, 0, 52, 16}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillMineCountCalcs = tonumber(buf) @@ -85,13 +89,13 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro end) }, }, { label = "Show Minion Stats", flag = "haveMinion", { controlName = "showMinion", - control = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + control = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) self.input.showMinion = state self:AddUndoState() end, "Show stats for the minion instead of the player.") }, }, { label = "Minion", flag = "minion", { controlName = "mainSkillMinion", - control = new("DropDownControl", nil, {0, 0, 160, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 160, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance if value.itemSetId then @@ -104,12 +108,12 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro end) } }, { label = "Spectre Library", flag = "spectre", { controlName = "mainSkillMinionLibrary", - control = new("ButtonControl", nil, {0, 0, 100, 16}, "Manage Spectres...", function() + control = new("ButtonControl"):ButtonControl(nil, {0, 0, 100, 16}, "Manage Spectres...", function() self.build:OpenSpectreLibrary() end) } }, { label = "Minion Skill", flag = "haveMinion", { controlName = "mainSkillMinionSkill", - control = new("DropDownControl", nil, {0, 0, 200, 16}, nil, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 16}, nil, function(index, value) local mainSocketGroup = self.build.skillsTab.socketGroupList[self.input.skill_number] local srcInstance = mainSocketGroup.displaySkillListCalcs[mainSocketGroup.mainActiveSkillCalcs].activeEffect.srcInstance srcInstance.skillMinionSkillCalcs = index @@ -119,7 +123,7 @@ local CalcsTabClass = newClass("CalcsTab", "UndoHandler", "ControlHost", "Contro } }, { label = "Calculation Mode", { controlName = "mode", - control = new("DropDownControl", nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 100, 16}, buffModeDropList, function(index, value) self.input.misc_buffMode = value.buffMode self:AddUndoState() self.build.buildFlag = true @@ -147,11 +151,12 @@ Effective DPS: Curses and enemy properties (such as resistances and status condi self:NewSection(unpack(section)) end - self.controls.breakdown = new("CalcBreakdownControl", self) + self.controls.breakdown = new("CalcBreakdownControl"):CalcBreakdownControl(self) - self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) self.powerBuilderInitialized = nil -end) + return self +end function CalcsTabClass:Load(xml, dbFileName) for _, node in ipairs(xml) do @@ -351,7 +356,7 @@ function CalcsTabClass:Draw(viewPort, inputEvents) end function CalcsTabClass:NewSection(width, ...) - local section = new("CalcSectionControl", self, width * self.colWidth + 8 * (width - 1), ...) + local section = new("CalcSectionControl"):CalcSectionControl(self, width * self.colWidth + 8 * (width - 1), ...) section.widthCols = width t_insert(self.controls, section) t_insert(self.sectionList, section) diff --git a/src/Classes/CheckBoxControl.lua b/src/Classes/CheckBoxControl.lua index 16a83030f9..1c285db5fd 100644 --- a/src/Classes/CheckBoxControl.lua +++ b/src/Classes/CheckBoxControl.lua @@ -3,15 +3,19 @@ -- Class: Check Box Control -- Basic check box control. -- -local CheckBoxClass = newClass("CheckBoxControl", "Control", "TooltipHost", function(self, anchor, rect, label, changeFunc, tooltipText, initialState) +---@class CheckBoxControl: Control, TooltipHost +local CheckBoxClass = newClass("CheckBoxControl", "Control", "TooltipHost") + +function CheckBoxClass:CheckBoxControl(anchor, rect, label, changeFunc, tooltipText, initialState) rect[4] = rect[3] or 0 - self.Control(anchor, rect) - self.TooltipHost(tooltipText) + self:Control(anchor, rect) + self:TooltipHost(tooltipText) self.label = label self.labelWidth = DrawStringWidth(self.width - 4, "VAR", label or "") + 5 self.changeFunc = changeFunc self.state = initialState -end) + return self +end function CheckBoxClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/CompareBuySimilar.lua b/src/Classes/CompareBuySimilar.lua index 698d5be9b8..854b559966 100644 --- a/src/Classes/CompareBuySimilar.lua +++ b/src/Classes/CompareBuySimilar.lua @@ -31,7 +31,7 @@ end -- Helper: create a numeric EditControl without +/- spinner buttons local function newPlainNumericEdit(anchor, rect, init, prompt, limit) - local ctrl = new("EditControl", anchor, rect, init, prompt, "%D", limit) + local ctrl = new("EditControl"):EditControl(anchor, rect, init, prompt, "%D", limit) -- Remove the +/- spinner buttons that "%D" filter triggers ctrl.isNumeric = false if ctrl.controls then @@ -246,7 +246,7 @@ function M.openPopup(item, slotName, primaryBuild) local tradeQuery = primaryBuild.itemsTab and primaryBuild.itemsTab.tradeQuery local tradeQueryRequests = tradeQuery and tradeQuery.tradeQueryRequests if not tradeQueryRequests then - tradeQueryRequests = new("TradeQueryRequests") + tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() end -- Helper to fetch and populate leagues for a given realm API id @@ -277,24 +277,24 @@ function M.openPopup(item, slotName, primaryBuild) end -- Realm dropdown - controls.realmLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Realm:") - controls.realmDrop = new("DropDownControl", {"LEFT", controls.realmLabel, "RIGHT"}, {4, 0, 80, 20}, {"PC", "PS4", "Xbox"}, function(index, value) + controls.realmLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Realm:") + controls.realmDrop = new("DropDownControl"):DropDownControl({"LEFT", controls.realmLabel, "RIGHT"}, {4, 0, 80, 20}, {"PC", "PS4", "Xbox"}, function(index, value) local realmApiId = REALM_API_IDS[value] or "pc" fetchLeaguesForRealm(realmApiId) end) -- League dropdown - controls.leagueLabel = new("LabelControl", {"LEFT", controls.realmDrop, "RIGHT"}, {12, 0, 0, 16}, "^7League:") - controls.leagueDrop = new("DropDownControl", {"LEFT", controls.leagueLabel, "RIGHT"}, {4, 0, 160, 20}, {"Loading..."}, function(index, value) + controls.leagueLabel = new("LabelControl"):LabelControl({"LEFT", controls.realmDrop, "RIGHT"}, {12, 0, 0, 16}, "^7League:") + controls.leagueDrop = new("DropDownControl"):DropDownControl({"LEFT", controls.leagueLabel, "RIGHT"}, {4, 0, 160, 20}, {"Loading..."}, function(index, value) -- League selection stored in the dropdown itself end) controls.leagueDrop.enabled = function() return #controls.leagueDrop.list > 0 and controls.leagueDrop.list[1] ~= "Loading..." end -- Listed status dropdown - controls.listedDrop = new("DropDownControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-leftMargin, ctrlY, 242, 20}, LISTED_STATUS_LABELS, function(index, value) + controls.listedDrop = new("DropDownControl"):DropDownControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-leftMargin, ctrlY, 242, 20}, LISTED_STATUS_LABELS, function(index, value) -- Listed status selection stored in the dropdown itself end) - controls.listedLabel = new("LabelControl", {"RIGHT", controls.listedDrop, "LEFT"}, {-4, 0, 0, 16}, "^7Listed:") + controls.listedLabel = new("LabelControl"):LabelControl({"RIGHT", controls.listedDrop, "LEFT"}, {-4, 0, 0, 16}, "^7Listed:") -- Fetch initial leagues for default realm fetchLeaguesForRealm("pc") @@ -302,22 +302,22 @@ function M.openPopup(item, slotName, primaryBuild) if isUnique then -- Unique item name label - controls.nameLabel = new("LabelControl", nil, {0, ctrlY, 0, 16}, "^x" .. (colorCodes[item.rarity] or "FFFFFF"):gsub("%^x","") .. item.name) + controls.nameLabel = new("LabelControl"):LabelControl(nil, {0, ctrlY, 0, 16}, "^x" .. (colorCodes[item.rarity] or "FFFFFF"):gsub("%^x","") .. item.name) ctrlY = ctrlY + rowHeight else -- Category label local categoryLabel = tradeHelpers.getTradeCategoryLabel(slotName, item) - controls.categoryLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Category: " .. categoryLabel) + controls.categoryLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Category: " .. categoryLabel) ctrlY = ctrlY + rowHeight -- Base type checkbox - controls.baseTypeCheck = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) - controls.baseTypeLabel = new("LabelControl", {"LEFT", controls.baseTypeCheck, "RIGHT"}, {4, 0, 0, 16}, "^7Use specific base: " .. (item.baseName or "Unknown")) + controls.baseTypeCheck = new("CheckBoxControl"):CheckBoxControl(nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) + controls.baseTypeLabel = new("LabelControl"):LabelControl({"LEFT", controls.baseTypeCheck, "RIGHT"}, {4, 0, 0, 16}, "^7Use specific base: " .. (item.baseName or "Unknown")) ctrlY = ctrlY + rowHeight -- Item level ctrlY = ctrlY + 4 - controls.ilvlLabel = new("LabelControl", {"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Item Level:") + controls.ilvlLabel = new("LabelControl"):LabelControl({"TOPLEFT", nil, "TOPLEFT"}, {leftMargin, ctrlY, 0, 16}, "^7Item Level:") controls.ilvlMin = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Min", 4) controls.ilvlMax = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 4) ctrlY = ctrlY + rowHeight @@ -325,8 +325,8 @@ function M.openPopup(item, slotName, primaryBuild) -- Defence stat rows for i, def in ipairs(defenceEntries) do local prefix = "def" .. i - controls[prefix .. "Check"] = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) - controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, "^7" .. def.label) + controls[prefix .. "Check"] = new("CheckBoxControl"):CheckBoxControl(nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) + controls[prefix .. "Label"] = new("LabelControl"):LabelControl({"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, "^7" .. def.label) controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, tostring(m_floor(def.value)), "Min", 6) controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 6) ctrlY = ctrlY + rowHeight @@ -342,14 +342,14 @@ function M.openPopup(item, slotName, primaryBuild) for i, entry in ipairs(modEntries) do local prefix = "mod" .. i local canSearch = entry.tradeId ~= nil - controls[prefix .. "Check"] = new("CheckBoxControl", nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) + controls[prefix .. "Check"] = new("CheckBoxControl"):CheckBoxControl(nil, {-popupWidth/2 + leftMargin + checkboxSize/2, ctrlY, checkboxSize}, "", nil, nil) controls[prefix .. "Check"].enabled = function() return canSearch end -- Truncate long mod text to fit local displayText = entry.formatted if #displayText > 45 then displayText = displayText:sub(1, 42) .. "..." end - controls[prefix .. "Label"] = new("LabelControl", {"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, (canSearch and "^7" or "^8") .. displayText) + controls[prefix .. "Label"] = new("LabelControl"):LabelControl({"LEFT", controls[prefix .. "Check"], "RIGHT"}, {4, 0, 0, 16}, (canSearch and "^7" or "^8") .. displayText) controls[prefix .. "Min"] = newPlainNumericEdit(nil, {minFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, entry.value ~= 0 and tostring(m_floor(entry.value)) or "", "Min", 8) controls[prefix .. "Max"] = newPlainNumericEdit(nil, {maxFieldX - popupWidth/2, ctrlY, fieldW, fieldH}, "", "Max", 8) if not canSearch then @@ -361,7 +361,7 @@ function M.openPopup(item, slotName, primaryBuild) -- Search button ctrlY = ctrlY + 8 - controls.search = new("ButtonControl", nil, {0, ctrlY, 110, 20}, "Generate URL", function() + controls.search = new("ButtonControl"):ButtonControl(nil, {0, ctrlY, 110, 20}, "Generate URL", function() local success, result = pcall(function() return buildURL(item, slotName, controls, modEntries, defenceEntries, isUnique) end) @@ -376,7 +376,7 @@ function M.openPopup(item, slotName, primaryBuild) ctrlY = ctrlY + rowHeight + 4 -- URL field - controls.uri = new("EditControl", nil, {-30, ctrlY, popupWidth - 100, fieldH}, "", nil, "^%C\t\n") + controls.uri = new("EditControl"):EditControl(nil, {-30, ctrlY, popupWidth - 100, fieldH}, "", nil, "^%C\t\n") controls.uri:SetPlaceholder("Press 'Generate URL' then Ctrl+Click to open") controls.uri.tooltipFunc = function(tooltip) tooltip:Clear() @@ -384,7 +384,7 @@ function M.openPopup(item, slotName, primaryBuild) tooltip:AddLine(16, "^7Ctrl + Click to open in web browser") end end - controls.close = new("ButtonControl", nil, {popupWidth/2 - 50, ctrlY, 60, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {popupWidth/2 - 50, ctrlY, 60, 20}, "Close", function() main:ClosePopup() end) diff --git a/src/Classes/CompareEntry.lua b/src/Classes/CompareEntry.lua index f4e2ca5570..49ea44cddb 100644 --- a/src/Classes/CompareEntry.lua +++ b/src/Classes/CompareEntry.lua @@ -9,8 +9,11 @@ local s_format = string.format local m_min = math.min local m_max = math.max -local CompareEntryClass = newClass("CompareEntry", "ControlHost", function(self, xmlText, label) - self.ControlHost() +---@class CompareEntry: ControlHost +local CompareEntryClass = newClass("CompareEntry", "ControlHost") + +function CompareEntryClass:CompareEntry(xmlText, label) + self:ControlHost() self.label = label or "Comparison Build" self.buildName = label or "Comparison Build" @@ -51,7 +54,8 @@ local CompareEntryClass = newClass("CompareEntry", "ControlHost", function(self, if xmlText then self:LoadFromXML(xmlText) end -end) + return self +end function CompareEntryClass:LoadFromXML(xmlText) -- Parse the XML @@ -99,14 +103,14 @@ function CompareEntryClass:LoadFromXML(xmlText) -- Create tabs -- PartyTab is replaced with a stub providing an empty enemyModList and actor -- (CalcPerform.lua:1088 accesses build.partyTab.actor for party member buffs) - local partyActor = { Aura = {}, Curse = {}, Warcry = {}, Link = {}, modDB = new("ModDB"), output = {} } + local partyActor = { Aura = {}, Curse = {}, Warcry = {}, Link = {}, modDB = new("ModDB"):ModDB(), output = {} } partyActor.modDB.actor = partyActor - self.partyTab = { enemyModList = new("ModList"), actor = partyActor } - self.configTab = new("ConfigTab", self) - self.itemsTab = new("ItemsTab", self) - self.treeTab = new("TreeTab", self) - self.skillsTab = new("SkillsTab", self) - self.calcsTab = new("CalcsTab", self) + self.partyTab = { enemyModList = new("ModList"):ModList(), actor = partyActor } + self.configTab = new("ConfigTab"):ConfigTab(self) + self.itemsTab = new("ItemsTab"):ItemsTab(self) + self.treeTab = new("TreeTab"):TreeTab(self) + self.skillsTab = new("SkillsTab"):SkillsTab(self) + self.calcsTab = new("CalcsTab"):CalcsTab(self) -- Set up savers table self.savers = { diff --git a/src/Classes/ComparePowerReportListControl.lua b/src/Classes/ComparePowerReportListControl.lua index 00e21a2711..49cdb50799 100644 --- a/src/Classes/ComparePowerReportListControl.lua +++ b/src/Classes/ComparePowerReportListControl.lua @@ -7,8 +7,11 @@ local t_insert = table.insert local t_sort = table.sort -local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 18, "VERTICAL", false) +---@class ComparePowerReportListControl: ListControl +local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "ListControl") + +function ComparePowerReportListClass:ComparePowerReportListControl(anchor, rect) + self:ListControl(anchor, rect, 18, "VERTICAL", false) local width = rect[3] self.impactColumn = { width = width * 0.22, label = "", sortable = true } @@ -22,7 +25,8 @@ local ComparePowerReportListClass = newClass("ComparePowerReportListControl", "L self.colLabels = true self.showRowSeparators = true self.statusText = "Select a metric above to generate the power report." -end) + return self +end function ComparePowerReportListClass:SetReport(stat, report) self.impactColumn.label = stat and stat.label or "" diff --git a/src/Classes/CompareTab.lua b/src/Classes/CompareTab.lua index 24506313c6..dea270451e 100644 --- a/src/Classes/CompareTab.lua +++ b/src/Classes/CompareTab.lua @@ -122,9 +122,13 @@ local function matchFlags(reqFlags, notFlags, flags) return true end -local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", function(self, primaryBuild) - self.ControlHost() - self.Control() +---@class CompareTab: ControlHost, Control +local CompareTabClass = newClass("CompareTab", "ControlHost", "Control") + +---@param build Build +function CompareTabClass:CompareTab(primaryBuild) + self:ControlHost() + self:Control() self.primaryBuild = primaryBuild @@ -155,13 +159,13 @@ local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", functio self.treeOverlayMode = true -- Tooltip for item hover in Items view - self.itemTooltip = new("Tooltip") + self.itemTooltip = new("Tooltip"):Tooltip() -- Items expanded mode (false = compact names only, true = full item details inline) self.itemsExpandedMode = false -- Tooltip for calcs hover breakdown - self.calcsTooltip = new("Tooltip") + self.calcsTooltip = new("Tooltip"):Tooltip() self.calcsShowOnlyDifferences = true -- Interactive config controls state @@ -190,21 +194,22 @@ local CompareTabClass = newClass("CompareTab", "ControlHost", "Control", functio -- Controls for the comparison screen self:InitControls() -end) + return self +end function CompareTabClass:InitControls() -- Sub-tab buttons local subTabs = { "Summary", "Tree", "Skills", "Items", "Calcs", "Config" } local subTabModes = { "SUMMARY", "TREE", "SKILLS", "ITEMS", "CALCS", "CONFIG" } - self.controls.subTabAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.subTabAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) for i, tabName in ipairs(subTabs) do local mode = subTabModes[i] local prevName = i > 1 and ("subTab" .. subTabs[i-1]) or "subTabAnchor" local anchor = i == 1 and {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"} or {"LEFT", self.controls[prevName], "RIGHT"} - self.controls["subTab" .. tabName] = new("ButtonControl", anchor, {i == 1 and 0 or 4, 0, 72, 20}, tabName, function() + self.controls["subTab" .. tabName] = new("ButtonControl"):ButtonControl(anchor, {i == 1 and 0 or 4, 0, 72, 20}, tabName, function() -- Clear tree overlay compareSpec when leaving TREE mode if self.compareViewMode == "TREE" and self.treeOverlayMode and self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then @@ -225,8 +230,8 @@ function CompareTabClass:InitControls() end -- Build B selector dropdown - self.controls.compareBuildLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -88, 0, 16}, "^7Compare with:") - self.controls.compareBuildSelect = new("DropDownControl", {"LEFT", self.controls.compareBuildLabel, "RIGHT"}, {4, 0, 250, 20}, {}, function(index, value) + self.controls.compareBuildLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -88, 0, 16}, "^7Compare with:") + self.controls.compareBuildSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareBuildLabel, "RIGHT"}, {4, 0, 250, 20}, {}, function(index, value) if index and index > 0 and index <= #self.compareEntries then self.activeCompareIndex = index self.treeSearchNeedsSync = true @@ -237,12 +242,12 @@ function CompareTabClass:InitControls() end -- Import button (opens import popup) - self.controls.importBtn = new("ButtonControl", {"LEFT", self.controls.compareBuildSelect, "RIGHT"}, {8, 0, 100, 20}, "Import...", function() + self.controls.importBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.compareBuildSelect, "RIGHT"}, {8, 0, 100, 20}, "Import...", function() self:OpenImportPopup() end) -- Re-import current build button - self.controls.reimportBtn = new("ButtonControl", {"LEFT", self.controls.importBtn, "RIGHT"}, {4, 0, 140, 20}, "Re-import Current", function() + self.controls.reimportBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.importBtn, "RIGHT"}, {4, 0, 140, 20}, "Re-import Current", function() self:ReimportPrimary() end) self.controls.reimportBtn.tooltipFunc = function(tooltip) @@ -269,7 +274,7 @@ function CompareTabClass:InitControls() end -- Remove comparison build button - self.controls.removeBtn = new("ButtonControl", {"LEFT", self.controls.reimportBtn, "RIGHT"}, {4, 0, 70, 20}, "Remove", function() + self.controls.removeBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.reimportBtn, "RIGHT"}, {4, 0, 70, 20}, "Remove", function() if self.activeCompareIndex > 0 and self.activeCompareIndex <= #self.compareEntries then self:RemoveBuild(self.activeCompareIndex) end @@ -286,9 +291,9 @@ function CompareTabClass:InitControls() end -- Tree spec selector for comparison build - self.controls.compareSpecLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -54, 0, 16}, "^7Tree set:") + self.controls.compareSpecLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -54, 0, 16}, "^7Tree set:") self.controls.compareSpecLabel.shown = setsEnabled - self.controls.compareSpecSelect = new("DropDownControl", {"LEFT", self.controls.compareSpecLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareSpecSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareSpecLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -303,9 +308,9 @@ function CompareTabClass:InitControls() self.controls.compareSpecSelect.enableDroppedWidth = true -- Skill set selector for comparison build - self.controls.compareSkillSetLabel = new("LabelControl", {"LEFT", self.controls.compareSpecSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Skill set:") + self.controls.compareSkillSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareSpecSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Skill set:") self.controls.compareSkillSetLabel.shown = setsEnabled - self.controls.compareSkillSetSelect = new("DropDownControl", {"LEFT", self.controls.compareSkillSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareSkillSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareSkillSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.skillsTab and entry.skillsTab.skillSetOrderList[index] then entry:SetActiveSkillSet(entry.skillsTab.skillSetOrderList[index]) @@ -313,9 +318,9 @@ function CompareTabClass:InitControls() end) self.controls.compareSkillSetSelect.enabled = setsEnabled -- Item set selector for comparison build - self.controls.compareItemSetLabel = new("LabelControl", {"LEFT", self.controls.compareSkillSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Item set:") + self.controls.compareItemSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareSkillSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Item set:") self.controls.compareItemSetLabel.shown = setsEnabled - self.controls.compareItemSetSelect = new("DropDownControl", {"LEFT", self.controls.compareItemSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareItemSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareItemSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.itemsTab and entry.itemsTab.itemSetOrderList[index] then entry:SetActiveItemSet(entry.itemsTab.itemSetOrderList[index]) @@ -323,9 +328,9 @@ function CompareTabClass:InitControls() end) self.controls.compareItemSetSelect.enabled = setsEnabled -- Config set selector for comparison build - self.controls.compareConfigSetLabel = new("LabelControl", {"LEFT", self.controls.compareItemSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Config set:") + self.controls.compareConfigSetLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.compareItemSetSelect, "RIGHT"}, {8, 0, 0, 16}, "^7Config set:") self.controls.compareConfigSetLabel.shown = setsEnabled - self.controls.compareConfigSetSelect = new("DropDownControl", {"LEFT", self.controls.compareConfigSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) + self.controls.compareConfigSetSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.compareConfigSetLabel, "RIGHT"}, {2, 0, 150, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.configTab then local setId = entry.configTab.configSetOrderList[index] @@ -342,11 +347,11 @@ function CompareTabClass:InitControls() -- ============================================================ -- Comparison build main skill selector (row between sets and sub-tabs) -- ============================================================ - self.controls.cmpSkillLabel = new("LabelControl", {"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -32, 0, 16}, "^7Skill:") + self.controls.cmpSkillLabel = new("LabelControl"):LabelControl({"TOPLEFT", self.controls.subTabAnchor, "TOPLEFT"}, {0, -32, 0, 16}, "^7Skill:") self.controls.cmpSkillLabel.shown = setsEnabled -- Socket group dropdown - self.controls.cmpSocketGroup = new("DropDownControl", {"LEFT", self.controls.cmpSkillLabel, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) + self.controls.cmpSocketGroup = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpSkillLabel, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then entry:SetMainSocketGroup(index) @@ -357,7 +362,7 @@ function CompareTabClass:InitControls() self.controls.cmpSocketGroup.enableDroppedWidth = true -- Active skill within group - self.controls.cmpMainSkill = new("DropDownControl", {"LEFT", self.controls.cmpSocketGroup, "RIGHT"}, {4, 0, 225, 20}, {}, function(index, value) + self.controls.cmpMainSkill = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpSocketGroup, "RIGHT"}, {4, 0, 225, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -370,7 +375,7 @@ function CompareTabClass:InitControls() self.controls.cmpMainSkill.shown = false -- Skill part (multi-part skills) - self.controls.cmpSkillPart = new("DropDownControl", {"LEFT", self.controls.cmpMainSkill, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) + self.controls.cmpSkillPart = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMainSkill, "RIGHT"}, {4, 0, 200, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -387,9 +392,9 @@ function CompareTabClass:InitControls() self.controls.cmpSkillPart.shown = false -- Stage count - self.controls.cmpStageCountLabel = new("LabelControl", {"LEFT", self.controls.cmpSkillPart, "RIGHT"}, {6, 0, 0, 16}, "^7Stages:") + self.controls.cmpStageCountLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.cmpSkillPart, "RIGHT"}, {6, 0, 0, 16}, "^7Stages:") self.controls.cmpStageCountLabel.shown = function() return self.controls.cmpStageCount.shown end - self.controls.cmpStageCount = new("EditControl", {"LEFT", self.controls.cmpStageCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) + self.controls.cmpStageCount = new("EditControl"):EditControl({"LEFT", self.controls.cmpStageCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -406,9 +411,9 @@ function CompareTabClass:InitControls() self.controls.cmpStageCount.shown = false -- Mine count - self.controls.cmpMineCountLabel = new("LabelControl", {"LEFT", self.controls.cmpStageCount, "RIGHT"}, {6, 0, 0, 16}, "^7Mines:") + self.controls.cmpMineCountLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.cmpStageCount, "RIGHT"}, {6, 0, 0, 16}, "^7Mines:") self.controls.cmpMineCountLabel.shown = function() return self.controls.cmpMineCount.shown end - self.controls.cmpMineCount = new("EditControl", {"LEFT", self.controls.cmpMineCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) + self.controls.cmpMineCount = new("EditControl"):EditControl({"LEFT", self.controls.cmpMineCountLabel, "RIGHT"}, {4, 0, 52, 20}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -425,7 +430,7 @@ function CompareTabClass:InitControls() self.controls.cmpMineCount.shown = false -- Minion selector - self.controls.cmpMinion = new("DropDownControl", {"LEFT", self.controls.cmpMineCount, "RIGHT"}, {6, 0, 140, 20}, {}, function(index, value) + self.controls.cmpMinion = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMineCount, "RIGHT"}, {6, 0, 140, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -449,7 +454,7 @@ function CompareTabClass:InitControls() self.controls.cmpMinion.shown = false -- Minion skill selector - self.controls.cmpMinionSkill = new("DropDownControl", {"LEFT", self.controls.cmpMinion, "RIGHT"}, {4, 0, 140, 20}, {}, function(index, value) + self.controls.cmpMinionSkill = new("DropDownControl"):DropDownControl({"LEFT", self.controls.cmpMinion, "RIGHT"}, {4, 0, 140, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.mainSocketGroup] @@ -475,7 +480,7 @@ function CompareTabClass:InitControls() { label = "Effective DPS", buffMode = "EFFECTIVE" }, } -- Primary build calcs skill controls - self.controls.primCalcsSocketGroup = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.primCalcsSocketGroup = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) self.primaryBuild.calcsTab.input.skill_number = index self.primaryBuild.buildFlag = true end) @@ -483,7 +488,7 @@ function CompareTabClass:InitControls() self.controls.primCalcsSocketGroup.maxDroppedWidth = 400 self.controls.primCalcsSocketGroup.enableDroppedWidth = true - self.controls.primCalcsMainSkill = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.primCalcsMainSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then mainSocketGroup.mainActiveSkillCalcs = index @@ -492,7 +497,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMainSkill.shown = false - self.controls.primCalcsSkillPart = new("DropDownControl", nil, {0, 0, 150, 18}, {}, function(index, value) + self.controls.primCalcsSkillPart = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -505,7 +510,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsSkillPart.shown = false - self.controls.primCalcsStageCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.primCalcsStageCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -518,7 +523,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsStageCount.shown = false - self.controls.primCalcsMineCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.primCalcsMineCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -531,13 +536,13 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMineCount.shown = false - self.controls.primCalcsShowMinion = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + self.controls.primCalcsShowMinion = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) self.primaryBuild.calcsTab.input.showMinion = state self.primaryBuild.buildFlag = true end, "Show stats for the minion instead of the player.") self.controls.primCalcsShowMinion.shown = false - self.controls.primCalcsMinion = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.primCalcsMinion = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -557,7 +562,7 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMinion.shown = false - self.controls.primCalcsMinionSkill = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.primCalcsMinionSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local mainSocketGroup = self.primaryBuild.skillsTab.socketGroupList[self.primaryBuild.calcsTab.input.skill_number] if mainSocketGroup then local displaySkillList = mainSocketGroup.displaySkillListCalcs @@ -570,14 +575,14 @@ function CompareTabClass:InitControls() end) self.controls.primCalcsMinionSkill.shown = false - self.controls.primCalcsMode = new("DropDownControl", nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) + self.controls.primCalcsMode = new("DropDownControl"):DropDownControl(nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) self.primaryBuild.calcsTab.input.misc_buffMode = value.buffMode self.primaryBuild.buildFlag = true end) self.controls.primCalcsMode.shown = false -- Compare build calcs skill controls - self.controls.cmpCalcsSocketGroup = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.cmpCalcsSocketGroup = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then entry.calcsTab.input.skill_number = index @@ -588,7 +593,7 @@ function CompareTabClass:InitControls() self.controls.cmpCalcsSocketGroup.maxDroppedWidth = 400 self.controls.cmpCalcsSocketGroup.enableDroppedWidth = true - self.controls.cmpCalcsMainSkill = new("DropDownControl", nil, {0, 0, 200, 18}, {}, function(index, value) + self.controls.cmpCalcsMainSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -600,7 +605,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMainSkill.shown = false - self.controls.cmpCalcsSkillPart = new("DropDownControl", nil, {0, 0, 150, 18}, {}, function(index, value) + self.controls.cmpCalcsSkillPart = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -616,7 +621,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsSkillPart.shown = false - self.controls.cmpCalcsStageCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.cmpCalcsStageCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -632,7 +637,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsStageCount.shown = false - self.controls.cmpCalcsMineCount = new("EditControl", nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) + self.controls.cmpCalcsMineCount = new("EditControl"):EditControl(nil, {0, 0, 52, 18}, "", nil, "%D", 5, function(buf) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -648,7 +653,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMineCount.shown = false - self.controls.cmpCalcsShowMinion = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + self.controls.cmpCalcsShowMinion = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) local entry = self:GetActiveCompare() if entry then entry.calcsTab.input.showMinion = state @@ -657,7 +662,7 @@ function CompareTabClass:InitControls() end, "Show stats for the minion instead of the player.") self.controls.cmpCalcsShowMinion.shown = false - self.controls.cmpCalcsMinion = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.cmpCalcsMinion = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -680,7 +685,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMinion.shown = false - self.controls.cmpCalcsMinionSkill = new("DropDownControl", nil, {0, 0, 140, 18}, {}, function(index, value) + self.controls.cmpCalcsMinionSkill = new("DropDownControl"):DropDownControl(nil, {0, 0, 140, 18}, {}, function(index, value) local entry = self:GetActiveCompare() if entry then local mainSocketGroup = entry.skillsTab.socketGroupList[entry.calcsTab.input.skill_number] @@ -696,7 +701,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMinionSkill.shown = false - self.controls.cmpCalcsMode = new("DropDownControl", nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) + self.controls.cmpCalcsMode = new("DropDownControl"):DropDownControl(nil, {0, 0, 120, 18}, calcsBuffModeDropList, function(index, value) local entry = self:GetActiveCompare() if entry then entry.calcsTab.input.misc_buffMode = value.buffMode @@ -705,7 +710,7 @@ function CompareTabClass:InitControls() end) self.controls.cmpCalcsMode.shown = false - self.controls.calcsShowOnlyDifferencesCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Show only differences", function(state) + self.controls.calcsShowOnlyDifferencesCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Show only differences", function(state) self.calcsShowOnlyDifferences = state end, "Show only rows that differ between both builds. Disable to include unchanged rows.") self.controls.calcsShowOnlyDifferencesCheck.shown = function() @@ -732,7 +737,7 @@ function CompareTabClass:InitControls() end -- Overlay toggle checkbox - self.controls.treeOverlayCheck = new("CheckBoxControl", nil, {0, 0, 20}, "Overlay comparison", function(state) + self.controls.treeOverlayCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 20}, "Overlay comparison", function(state) self.treeOverlayMode = state self.treeSearchNeedsSync = true if not state and self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then @@ -742,7 +747,7 @@ function CompareTabClass:InitControls() self.controls.treeOverlayCheck.shown = treeFooterShown -- Overlay-mode search (single search for primary viewer) - self.controls.overlayTreeSearch = new("EditControl", nil, {0, 0, 300, 20}, "", "Search", "%c", 100, function(buf) + self.controls.overlayTreeSearch = new("EditControl"):EditControl(nil, {0, 0, 300, 20}, "", "Search", "%c", 100, function(buf) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then self.primaryBuild.treeTab.viewer.searchStr = buf end @@ -752,7 +757,7 @@ function CompareTabClass:InitControls() end -- Items expanded mode toggle - self.controls.itemsExpandedCheck = new("CheckBoxControl", nil, {0, 0, 20}, "Expanded mode", function(state) + self.controls.itemsExpandedCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 20}, "Expanded mode", function(state) self.itemsExpandedMode = state self.scrollY = 0 end) @@ -764,9 +769,9 @@ function CompareTabClass:InitControls() local itemsShown = function() return self.compareViewMode == "ITEMS" and self:GetActiveCompare() ~= nil end - self.controls.primaryItemSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Item set:") + self.controls.primaryItemSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Item set:") self.controls.primaryItemSetLabel.shown = itemsShown - self.controls.primaryItemSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.primaryItemSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) if self.primaryBuild.itemsTab and self.primaryBuild.itemsTab.itemSetOrderList[index] then self.primaryBuild.itemsTab:SetActiveItemSet(self.primaryBuild.itemsTab.itemSetOrderList[index]) self.primaryBuild.itemsTab:AddUndoState() @@ -776,9 +781,9 @@ function CompareTabClass:InitControls() self.controls.primaryItemSetSelect.shown = itemsShown -- Item set dropdown for compare build - self.controls.compareItemSetLabel2 = new("LabelControl", nil, {0, 0, 0, 16}, "^7Item set:") + self.controls.compareItemSetLabel2 = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Item set:") self.controls.compareItemSetLabel2.shown = itemsShown - self.controls.compareItemSetSelect2 = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.compareItemSetSelect2 = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.itemsTab and entry.itemsTab.itemSetOrderList[index] then entry:SetActiveItemSet(entry.itemsTab.itemSetOrderList[index]) @@ -788,9 +793,9 @@ function CompareTabClass:InitControls() self.controls.compareItemSetSelect2.shown = itemsShown -- Tree set dropdown for primary build - self.controls.primaryTreeSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Tree set:") + self.controls.primaryTreeSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Tree set:") self.controls.primaryTreeSetLabel.shown = itemsShown - self.controls.primaryTreeSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.primaryTreeSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.specList[index] then self.primaryBuild.modFlag = true self.primaryBuild.treeTab:SetActiveSpec(index) @@ -802,9 +807,9 @@ function CompareTabClass:InitControls() self.controls.primaryTreeSetSelect.enableDroppedWidth = true -- Tree set dropdown for compare build - self.controls.compareTreeSetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Tree set:") + self.controls.compareTreeSetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Tree set:") self.controls.compareTreeSetLabel.shown = itemsShown - self.controls.compareTreeSetSelect = new("DropDownControl", nil, {0, 0, 216, 20}, {}, function(index, value) + self.controls.compareTreeSetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 216, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -819,13 +824,13 @@ function CompareTabClass:InitControls() self.controls.compareTreeSetSelect.enableDroppedWidth = true -- Footer anchor controls (side-by-side only) - self.controls.leftFooterAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.leftFooterAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) self.controls.leftFooterAnchor.shown = treeSideBySideShown - self.controls.rightFooterAnchor = new("Control", nil, {0, 0, 0, 20}) + self.controls.rightFooterAnchor = new("Control"):Control(nil, {0, 0, 0, 20}) self.controls.rightFooterAnchor.shown = treeSideBySideShown -- Left side (primary build) spec/version controls (header, both modes) - self.controls.leftSpecSelect = new("DropDownControl", nil, {0, 0, 180, 20}, {}, function(index, value) + self.controls.leftSpecSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 180, 20}, {}, function(index, value) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.specList[index] then self.primaryBuild.modFlag = true self.primaryBuild.treeTab:SetActiveSpec(index) @@ -835,7 +840,7 @@ function CompareTabClass:InitControls() self.controls.leftSpecSelect.maxDroppedWidth = 500 self.controls.leftSpecSelect.enableDroppedWidth = true - self.controls.leftVersionSelect = new("DropDownControl", {"LEFT", self.controls.leftSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) + self.controls.leftVersionSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.leftSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) if selected and selected.value and self.primaryBuild.spec and selected.value ~= self.primaryBuild.spec.treeVersion then self.primaryBuild.treeTab:OpenVersionConvertPopup(selected.value, true) end @@ -843,7 +848,7 @@ function CompareTabClass:InitControls() self.controls.leftVersionSelect.shown = treeFooterShown -- Left search (footer, side-by-side only) - self.controls.leftTreeSearch = new("EditControl", {"TOPLEFT", self.controls.leftFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) + self.controls.leftTreeSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.leftFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) if self.primaryBuild.treeTab and self.primaryBuild.treeTab.viewer then self.primaryBuild.treeTab.viewer.searchStr = buf end @@ -851,7 +856,7 @@ function CompareTabClass:InitControls() self.controls.leftTreeSearch.shown = treeSideBySideShown -- Right side (compare build) spec/version controls (header, both modes) - self.controls.rightSpecSelect = new("DropDownControl", nil, {0, 0, 180, 20}, {}, function(index, value) + self.controls.rightSpecSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 180, 20}, {}, function(index, value) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.specList[index] then entry:SetActiveSpec(index) @@ -865,7 +870,7 @@ function CompareTabClass:InitControls() self.controls.rightSpecSelect.maxDroppedWidth = 500 self.controls.rightSpecSelect.enableDroppedWidth = true - self.controls.rightVersionSelect = new("DropDownControl", {"LEFT", self.controls.rightSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) + self.controls.rightVersionSelect = new("DropDownControl"):DropDownControl({"LEFT", self.controls.rightSpecSelect, "RIGHT"}, {4, 0, 100, 20}, self.treeVersionDropdownList, function(index, selected) local entry = self:GetActiveCompare() if entry and selected and selected.value and entry.spec then if selected.value ~= entry.spec.treeVersion then @@ -876,7 +881,7 @@ function CompareTabClass:InitControls() self.controls.rightVersionSelect.shown = treeFooterShown -- Copy compared tree to primary build - self.controls.copySpecBtn = new("ButtonControl", {"LEFT", self.controls.rightVersionSelect, "RIGHT"}, {4, 0, 76, 20}, "Copy tree", function() + self.controls.copySpecBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.rightVersionSelect, "RIGHT"}, {4, 0, 76, 20}, "Copy tree", function() self:CopyCompareSpecToPrimary(false) end) self.controls.copySpecBtn.shown = treeFooterShown @@ -885,14 +890,14 @@ function CompareTabClass:InitControls() return entry and entry.treeTab and entry.treeTab.specList[entry.treeTab.activeSpec] ~= nil end - self.controls.copySpecUseBtn = new("ButtonControl", {"LEFT", self.controls.copySpecBtn, "RIGHT"}, {2, 0, 100, 20}, "Copy and use", function() + self.controls.copySpecUseBtn = new("ButtonControl"):ButtonControl({"LEFT", self.controls.copySpecBtn, "RIGHT"}, {2, 0, 100, 20}, "Copy and use", function() self:CopyCompareSpecToPrimary(true) end) self.controls.copySpecUseBtn.shown = treeFooterShown self.controls.copySpecUseBtn.enabled = self.controls.copySpecBtn.enabled -- Right search (footer, side-by-side only) - self.controls.rightTreeSearch = new("EditControl", {"TOPLEFT", self.controls.rightFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) + self.controls.rightTreeSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.rightFooterAnchor, "TOPLEFT"}, {0, 0, 200, 20}, "", "Search", "%c", 100, function(buf) local entry = self:GetActiveCompare() if entry and entry.treeTab and entry.treeTab.viewer then entry.treeTab.viewer.searchStr = buf @@ -901,7 +906,7 @@ function CompareTabClass:InitControls() self.controls.rightTreeSearch.shown = treeSideBySideShown -- Config view: "Copy Config from Compare Build" button - self.controls.copyConfigBtn = new("ButtonControl", nil, {0, 0, 240, 20}, + self.controls.copyConfigBtn = new("ButtonControl"):ButtonControl(nil, {0, 0, 240, 20}, "Copy Config from Compare Build", function() self:CopyCompareConfig() end) self.controls.copyConfigBtn.shown = function() @@ -909,7 +914,7 @@ function CompareTabClass:InitControls() end -- Config view: "Show All / Hide Ineligible" toggle button - self.controls.configToggleBtn = new("ButtonControl", nil, {0, 0, 240, 20}, + self.controls.configToggleBtn = new("ButtonControl"):ButtonControl(nil, {0, 0, 240, 20}, function() return self.configToggle and "Hide Ineligible Configurations" or "Show All Configurations" end, @@ -921,7 +926,7 @@ function CompareTabClass:InitControls() end -- Config view: search bar - self.controls.configSearchEdit = new("EditControl", nil, {0, 0, 240, 20}, "", "Search", "%c", 100, nil, nil, nil, true) + self.controls.configSearchEdit = new("EditControl"):EditControl(nil, {0, 0, 240, 20}, "", "Search", "%c", 100, nil, nil, nil, true) self.controls.configSearchEdit.shown = function() return self.compareViewMode == "CONFIG" and self:GetActiveCompare() ~= nil end @@ -930,9 +935,9 @@ function CompareTabClass:InitControls() local configShown = function() return self.compareViewMode == "CONFIG" and self:GetActiveCompare() ~= nil end - self.controls.configPrimarySetLabel = new("LabelControl", nil, {0, 0, 0, 16}, "^7Config set:") + self.controls.configPrimarySetLabel = new("LabelControl"):LabelControl(nil, {0, 0, 0, 16}, "^7Config set:") self.controls.configPrimarySetLabel.shown = configShown - self.controls.configPrimarySetSelect = new("DropDownControl", nil, {0, 0, 150, 20}, nil, function(index, value) + self.controls.configPrimarySetSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 20}, nil, function(index, value) local configTab = self.primaryBuild.configTab local setId = configTab.configSetOrderList[index] if setId then @@ -960,7 +965,7 @@ function CompareTabClass:InitControls() t_insert(powerStatList, entry) end end - self.controls.comparePowerStatSelect = new("DropDownControl", nil, {0, 0, 200, 20}, powerStatList, function(index, value) + self.controls.comparePowerStatSelect = new("DropDownControl"):DropDownControl(nil, {0, 0, 200, 20}, powerStatList, function(index, value) if value and value.stat and value ~= self.comparePowerStat then self.comparePowerStat = value self.comparePowerDirty = true @@ -981,35 +986,35 @@ function CompareTabClass:InitControls() end -- Category checkboxes - self.controls.comparePowerTreeCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Tree:", function(state) + self.controls.comparePowerTreeCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Tree:", function(state) self.comparePowerCategories.treeNodes = state self.comparePowerDirty = true end, "Include passive tree nodes from compared build") self.controls.comparePowerTreeCheck.shown = powerReportShown self.controls.comparePowerTreeCheck.state = true - self.controls.comparePowerItemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Items:", function(state) + self.controls.comparePowerItemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Items:", function(state) self.comparePowerCategories.items = state self.comparePowerDirty = true end, "Include items from compared build") self.controls.comparePowerItemsCheck.shown = powerReportShown self.controls.comparePowerItemsCheck.state = true - self.controls.comparePowerGemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Skill gems:", function(state) + self.controls.comparePowerGemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Skill gems:", function(state) self.comparePowerCategories.skillGems = state self.comparePowerDirty = true end, "Include skill gem groups unique to compared build") self.controls.comparePowerGemsCheck.shown = powerReportShown self.controls.comparePowerGemsCheck.state = true - self.controls.comparePowerSupportGemsCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Support gems:", function(state) + self.controls.comparePowerSupportGemsCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Support gems:", function(state) self.comparePowerCategories.supportGems = state self.comparePowerDirty = true end, "Include support gems from compared build's active skill") self.controls.comparePowerSupportGemsCheck.shown = powerReportShown self.controls.comparePowerSupportGemsCheck.state = true - self.controls.comparePowerConfigCheck = new("CheckBoxControl", nil, {0, 0, 18}, "Config:", function(state) + self.controls.comparePowerConfigCheck = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, "Config:", function(state) self.comparePowerCategories.config = state self.comparePowerDirty = true end, "Include config option differences from compared build") @@ -1017,19 +1022,19 @@ function CompareTabClass:InitControls() self.controls.comparePowerConfigCheck.state = true -- Power report list control (static height, own scrollbar) - self.controls.comparePowerReportList = new("ComparePowerReportListControl", nil, {0, 0, 750, 250}) + self.controls.comparePowerReportList = new("ComparePowerReportListControl"):ComparePowerReportListControl(nil, {0, 0, 750, 250}) self.controls.comparePowerReportList.compareTab = self self.controls.comparePowerReportList.shown = powerReportShown -- Scrollbar for Calcs sub-tab - self.controls.calcsScrollBar = new("ScrollBarControl", nil, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.calcsScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 50, "VERTICAL", true) local calcsScrollBar = self.controls.calcsScrollBar self.controls.calcsScrollBar.shown = function() return self.compareViewMode == "CALCS" and self:GetActiveCompare() ~= nil and calcsScrollBar.enabled end -- Shared vertical scrollbar for Summary/Items/Skills/Config sub-tabs - self.controls.viewScrollBar = new("ScrollBarControl", nil, {0, 0, 18, 0}, 50, "VERTICAL", true) + self.controls.viewScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 50, "VERTICAL", true) local viewScrollBar = self.controls.viewScrollBar self.controls.viewScrollBar.shown = function() return self:GetActiveCompare() ~= nil @@ -1039,14 +1044,14 @@ function CompareTabClass:InitControls() end -- Horizontal scrollbar for Items sub-tab - self.controls.itemsHScrollBar = new("ScrollBarControl", nil, {0, 0, 0, LAYOUT.itemsHScrollBarHeight}, 60, "HORIZONTAL", true) + self.controls.itemsHScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, LAYOUT.itemsHScrollBarHeight}, 60, "HORIZONTAL", true) local itemsHScrollBar = self.controls.itemsHScrollBar self.controls.itemsHScrollBar.shown = function() return self.compareViewMode == "ITEMS" and self:GetActiveCompare() ~= nil and itemsHScrollBar.enabled end -- Horizontal scrollbar for Skills sub-tab - self.controls.skillsHScrollBar = new("ScrollBarControl", nil, {0, 0, 0, LAYOUT.skillsHScrollBarHeight}, 60, "HORIZONTAL", true) + self.controls.skillsHScrollBar = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, LAYOUT.skillsHScrollBarHeight}, 60, "HORIZONTAL", true) local skillsHScrollBar = self.controls.skillsHScrollBar self.controls.skillsHScrollBar.shown = function() return self.compareViewMode == "SKILLS" and self:GetActiveCompare() ~= nil and skillsHScrollBar.enabled @@ -1117,7 +1122,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc local control local pVal = inputTable[varData.var] if varData.type == "check" then - control = new("CheckBoxControl", nil, {0, 0, 18}, nil, function(state) + control = new("CheckBoxControl"):CheckBoxControl(nil, {0, 0, 18}, nil, function(state) inputTable[varData.var] = state configTab:UpdateControls() configTab:BuildModList() @@ -1128,7 +1133,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc or varData.type == "countAllowZero" or varData.type == "float" then local filter = (varData.type == "integer" and "^%-%d") or (varData.type == "float" and "^%d.") or "%D" - control = new("EditControl", nil, {0, 0, 90, 18}, + control = new("EditControl"):EditControl(nil, {0, 0, 90, 18}, tostring(pVal or ""), nil, filter, 7, function(buf) inputTable[varData.var] = tonumber(buf) @@ -1137,7 +1142,7 @@ local function makeConfigControl(varData, inputTable, configTab, buildObj, sourc buildObj.buildFlag = true end) elseif varData.type == "list" and varData.list then - control = new("DropDownControl", nil, {0, 0, 150, 18}, + control = new("DropDownControl"):DropDownControl(nil, {0, 0, 150, 18}, varData.list, function(index, value) inputTable[varData.var] = value.val configTab:UpdateControls() @@ -1226,7 +1231,7 @@ end -- Import a comparison build from XML text function CompareTabClass:ImportBuild(xmlText, label) - local entry = new("CompareEntry", xmlText, label) + local entry = new("CompareEntry"):CompareEntry(xmlText, label) if entry and entry.calcsTab and entry.calcsTab.mainOutput then t_insert(self.compareEntries, entry) self.activeCompareIndex = #self.compareEntries @@ -1306,7 +1311,7 @@ function CompareTabClass:CopyCompareSpecToPrimary(andUse) -- Create new spec from source (same pattern as PassiveSpecListControl Copy) -- Note: we don't copy jewels because they reference item IDs in the compared -- build's itemsTab which don't exist in the primary build - local newSpec = new("PassiveSpec", self.primaryBuild, sourceSpec.treeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self.primaryBuild, sourceSpec.treeVersion) newSpec.title = (sourceSpec.title or "Default") .. " (Compared)" newSpec:RestoreUndoState(sourceSpec:CreateUndoState()) newSpec:BuildClusterJewelGraphs() @@ -1408,7 +1413,7 @@ function CompareTabClass:CopyCompareItemToPrimary(slotName, compareEntry, andUse local cItem = cSlot and compareEntry.itemsTab.items and compareEntry.itemsTab.items[cSlot.selItemId] if not cItem or not cItem.raw then return end - local newItem = new("Item", cItem.raw) + local newItem = new("Item"):Item(cItem.raw) newItem:NormaliseQuality() local pItemsTab = self.primaryBuild.itemsTab pItemsTab:AddItem(newItem, true) -- true = noAutoEquip @@ -1431,20 +1436,20 @@ function CompareTabClass:OpenImportPopup() -- Use a local variable for state text so it doesn't go into the controls table -- (PopupDialog iterates all controls table entries and expects them to be control objects) local stateText = "" - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Paste a build code or URL to import as comparison:") - controls.input = new("EditControl", nil, {0, 50, 450, 20}, "", nil, nil, nil, nil, nil, nil, true) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Paste a build code or URL to import as comparison:") + controls.input = new("EditControl"):EditControl(nil, {0, 50, 450, 20}, "", nil, nil, nil, nil, nil, nil, true) controls.input.enterFunc = function() if controls.input.buf and controls.input.buf ~= "" then controls.go.onClick() end end - controls.name = new("EditControl", nil, {0, 80, 450, 20}, "", "Name (optional)", nil, 100, nil) - controls.state = new("LabelControl", {"TOPLEFT", controls.name, "BOTTOMLEFT"}, {0, 4, 0, 16}) + controls.name = new("EditControl"):EditControl(nil, {0, 80, 450, 20}, "", "Name (optional)", nil, 100, nil) + controls.state = new("LabelControl"):LabelControl({"TOPLEFT", controls.name, "BOTTOMLEFT"}, {0, 4, 0, 16}) controls.state.label = function() return stateText or "" end - controls.go = new("ButtonControl", nil, {-118, 130, 80, 20}, "Import", function() + controls.go = new("ButtonControl"):ButtonControl(nil, {-118, 130, 80, 20}, "Import", function() local buf = controls.input.buf if not buf or buf == "" then return @@ -1481,11 +1486,11 @@ function CompareTabClass:OpenImportPopup() stateText = colorCodes.NEGATIVE .. "Invalid build code" end end) - controls.importFolder = new("ButtonControl", nil, {0, 130, 140, 20}, "Import from Folder", function() + controls.importFolder = new("ButtonControl"):ButtonControl(nil, {0, 130, 140, 20}, "Import from Folder", function() main:ClosePopup() self:OpenImportFolderPopup() end) - controls.cancel = new("ButtonControl", nil, {118, 130, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {118, 130, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(500, 160, "Import Comparison Build", controls, "go", "input", "cancel") @@ -1537,11 +1542,11 @@ function CompareTabClass:OpenImportFolderPopup() end -- Search box and sort dropdown sit above the build list. - controls.searchText = new("EditControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 450, 20}, "", "Search", "%c%(%)", 100, function(buf) + controls.searchText = new("EditControl"):EditControl({"TOPLEFT", nil, "TOPLEFT"}, {15, 25, 450, 20}, "", "Search", "%c%(%)", 100, function(buf) searchText = buf listHost:BuildList() end, nil, nil, true) - controls.sort = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value) + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {475, 25, 210, 20}, buildListHelpers.buildSortDropList, function(index, value) sortMode = value.sortMode main.buildSortMode = value.sortMode buildListHelpers.SortList(listHost.list, sortMode) @@ -1549,7 +1554,7 @@ function CompareTabClass:OpenImportFolderPopup() controls.sort:SelByValue(sortMode, "sortMode") -- Build list itself. Reuses BuildListControl (which provides the PathControl breadcrumbs) - controls.buildList = new("BuildListControl", {"TOPLEFT", nil, "TOPLEFT"}, {15, 75, 0, 0}, listHost) + controls.buildList = new("BuildListControl"):BuildListControl({"TOPLEFT", nil, "TOPLEFT"}, {15, 75, 0, 0}, listHost) controls.buildList.width = function() return 670 end controls.buildList.height = function() return 355 end @@ -1581,14 +1586,14 @@ function CompareTabClass:OpenImportFolderPopup() -- Populate the initial list now that the control (and its path control) exist. listHost:BuildList() - controls.open = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {255, 465, 80, 20}, "Open", function() + controls.open = new("ButtonControl"):ButtonControl({"TOPLEFT", nil, "TOPLEFT"}, {255, 465, 80, 20}, "Open", function() local sel = controls.buildList.selValue if sel then controls.buildList:LoadBuild(sel) end end) controls.open.enabled = function() return controls.buildList.selValue ~= nil end - controls.close = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {365, 465, 80, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl({"TOPLEFT", nil, "TOPLEFT"}, {365, 465, 80, 20}, "Close", function() main:ClosePopup() end) @@ -2655,7 +2660,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories local pSlot = self.primaryBuild.itemsTab and self.primaryBuild.itemsTab.slots[slotName] local pItem = pSlot and self.primaryBuild.itemsTab.items[pSlot.selItemId] if cItem and cItem.raw and not (pItem and pItem.name == cItem.name) then - local newItem = new("Item", cItem.raw) + local newItem = new("Item"):Item(cItem.raw) newItem:NormaliseQuality() -- if our comparison has abyssal jewels, but the primary build @@ -2678,7 +2683,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories -- might not exist if cmpJewel then -- copy item - local itemCopy = new("Item", cmpJewel:BuildRaw()) + local itemCopy = new("Item"):Item(cmpJewel:BuildRaw()) table.insert(cmpJewels, itemCopy) self.primaryBuild.itemsTab:AddItem(itemCopy, false) @@ -2763,7 +2768,7 @@ function CompareTabClass:ComparePowerBuilder(compareEntry, powerStat, categories local jewelSlots = self:GetJewelComparisonSlots(compareEntry) for _, jEntry in ipairs(jewelSlots) do if jEntry.cItem and jEntry.cItem.raw and not (jEntry.pItem and jEntry.pItem.name == jEntry.cItem.name) then - local newItem = new("Item", jEntry.cItem.raw) + local newItem = new("Item"):Item(jEntry.cItem.raw) newItem:NormaliseQuality() local bestImpactVal = nil @@ -3904,7 +3909,7 @@ function CompareTabClass:DrawItems(vp, compareEntry, inputEvents) local calcFunc, calcBase = self.calcs.getMiscCalculator(self.primaryBuild) if calcFunc then -- Create a fresh item to evaluate - local newItem = new("Item", hoverEquipItem.raw) + local newItem = new("Item"):Item(hoverEquipItem.raw) newItem:NormaliseQuality() -- Determine what's currently in the target slot diff --git a/src/Classes/ConfigSetListControl.lua b/src/Classes/ConfigSetListControl.lua index c38e809d76..f944097082 100644 --- a/src/Classes/ConfigSetListControl.lua +++ b/src/Classes/ConfigSetListControl.lua @@ -7,10 +7,13 @@ local t_insert = table.insert local t_remove = table.remove local m_max = math.max -local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl", function(self, anchor, rect, configTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, configTab.configSetOrderList) +---@class ConfigSetListControl: ListControl +local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl") + +function ConfigSetListClass:ConfigSetListControl(anchor, rect, configTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, configTab.configSetOrderList) self.configTab = configTab - self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() local configSet = configTab.configSets[self.selValue] local newConfigSet = copyTable(configSet) newConfigSet.id = 1 @@ -23,30 +26,31 @@ local ConfigSetListClass = newClass("ConfigSetListControl", "ListControl", funct self.controls.copy.enabled = function() return self.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSet(configTab.configSets[self.selValue]) end) self.controls.rename.enabled = function() return self.selValue ~= nil end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() self:RenameSet(configTab:NewConfigSet(), true) end) -end) + return self +end function ConfigSetListClass:RenameSet(configSet, addOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this config set:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, configSet.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this config set:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, configSet.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() configSet.title = controls.edit.buf self.configTab.modFlag = true if addOnName then @@ -59,7 +63,7 @@ function ConfigSetListClass:RenameSet(configSet, addOnName) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if addOnName then self.configTab.configSets[configSet.id] = nil end diff --git a/src/Classes/ConfigTab.lua b/src/Classes/ConfigTab.lua index 22222887c8..9a29f59697 100644 --- a/src/Classes/ConfigTab.lua +++ b/src/Classes/ConfigTab.lua @@ -12,10 +12,14 @@ local s_upper = string.upper local varList = LoadModule("Modules/ConfigOptions") local configVisibility = LoadModule("Modules/ConfigVisibility") -local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class ConfigTab: UndoHandler, ControlHost, Control +local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function ConfigTabClass:ConfigTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build @@ -36,10 +40,10 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.toggleConfigs = false - self.controls.sectionAnchor = new("LabelControl", { "TOPLEFT", self, "TOPLEFT" }, { 0, 20, 0, 0 }, "") + self.controls.sectionAnchor = new("LabelControl"):LabelControl({ "TOPLEFT", self, "TOPLEFT" }, { 0, 20, 0, 0 }, "") -- Set selector - self.controls.setSelect = new("DropDownControl", { "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 76, -12, 210, 20 }, nil, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 76, -12, 210, 20 }, nil, function(index, value) self:SetActiveConfigSet(self.configSetOrderList[index]) self:AddUndoState() end) @@ -47,15 +51,15 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.controls.setSelect.enabled = function() return #self.configSetOrderList > 1 end - self.controls.setLabel = new("LabelControl", { "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Config set:") - self.controls.setManage = new("ButtonControl", { "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() + self.controls.setLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Config set:") + self.controls.setManage = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() self:OpenConfigSetManagePopup() end) - self.controls.search = new("EditControl", { "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 8, 15, 360, 20 }, "", "Search", "%c", 100, function() + self.controls.search = new("EditControl"):EditControl({ "TOPLEFT", self.controls.sectionAnchor, "TOPLEFT" }, { 8, 15, 360, 20 }, "", "Search", "%c", 100, function() self:UpdateControls() end, nil, nil, true) - self.controls.toggleConfigs = new("ButtonControl", { "LEFT", self.controls.search, "RIGHT" }, { 10, 0, 200, 20 }, function() + self.controls.toggleConfigs = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.search, "RIGHT" }, { 10, 0, 200, 20 }, function() -- dynamic text return self.toggleConfigs and "Hide Ineligible Configurations" or "Show All Configurations" end, function() @@ -131,7 +135,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont local lastSection for _, varData in ipairs(varList) do if varData.section then - lastSection = new("SectionControl", {"TOPLEFT",self.controls.search,"BOTTOMLEFT"}, {0, 0, 360, 0}, varData.section) + lastSection = new("SectionControl"):SectionControl({"TOPLEFT",self.controls.search,"BOTTOMLEFT"}, {0, 0, 360, 0}, varData.section) lastSection.varControlList = { } lastSection.col = varData.col lastSection.height = function(self) @@ -148,14 +152,14 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont else local control if varData.type == "check" then - control = new("CheckBoxControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 18}, varData.label, function(state) + control = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 18}, varData.label, function(state) self.configSets[self.activeConfigSetId].input[varData.var] = state self:AddUndoState() self:BuildModList() self.build.buildFlag = true end) elseif varData.type == "count" or varData.type == "integer" or varData.type == "countAllowZero" or varData.type == "float" then - control = new("EditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 90, 18}, "", nil, (varData.type == "integer" and "^%-%d") or (varData.type == "float" and "^%d.") or "%D", 10, function(buf, placeholder) + control = new("EditControl"):EditControl({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 90, 18}, "", nil, (varData.type == "integer" and "^%-%d") or (varData.type == "float" and "^%d.") or "%D", 10, function(buf, placeholder) if placeholder then self.configSets[self.activeConfigSetId].placeholder[varData.var] = tonumber(buf) else @@ -166,14 +170,14 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end) elseif varData.type == "list" then - control = new("DropDownControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 118, 16}, varData.list, function(index, value) + control = new("DropDownControl"):DropDownControl({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 118, 16}, varData.list, function(index, value) self.configSets[self.activeConfigSetId].input[varData.var] = value.val self:AddUndoState() self:BuildModList() self.build.buildFlag = true end) elseif varData.type == "text" and not varData.resizable then - control = new("EditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118}, "", nil, "^%C\t\n", nil, function(buf, placeholder) + control = new("EditControl"):EditControl({"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118}, "", nil, "^%C\t\n", nil, function(buf, placeholder) if placeholder then self.configSets[self.activeConfigSetId].placeholder[varData.var] = tostring(buf) else @@ -184,7 +188,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end, 16) elseif varData.type == "text" and varData.resizable then - control = new("ResizableEditControl", {"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118, nil, nil, nil, 118 + 16 * 40}, "", nil, "^%C\t\n", nil, function(buf, placeholder) + control = new("ResizableEditControl"):ResizableEditControl({"TOPLEFT",lastSection,"TOPLEFT"}, {8, 0, 344, 118, nil, nil, nil, 118 + 16 * 40}, "", nil, "^%C\t\n", nil, function(buf, placeholder) if placeholder then self.configSets[self.activeConfigSetId].placeholder[varData.var] = tostring(buf) else @@ -195,7 +199,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont self.build.buildFlag = true end, 16) else - control = new("Control", {"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 16, 16}) + control = new("Control"):Control({"TOPLEFT",lastSection,"TOPLEFT"}, {234, 0, 16, 16}) end if varData.inactiveText then @@ -519,7 +523,7 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont end local labelControl = control if varData.label and varData.type ~= "check" then - labelControl = new("LabelControl", {"RIGHT",control,"LEFT"}, {-4, 0, 0, DrawStringWidth(14, "VAR", varData.label) > 228 and 12 or 14}, "^7"..varData.label) + labelControl = new("LabelControl"):LabelControl({"RIGHT",control,"LEFT"}, {-4, 0, 0, DrawStringWidth(14, "VAR", varData.label) > 228 and 12 or 14}, "^7"..varData.label) t_insert(self.controls, labelControl) end if varData.var then @@ -607,8 +611,9 @@ local ConfigTabClass = newClass("ConfigTab", "UndoHandler", "ControlHost", "Cont t_insert(lastSection.varControlList, control) end end - self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) -end) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {0, 0, 18, 0}, 50, "VERTICAL", true) + return self +end function ConfigTabClass:Load(xml, fileName) self.activeConfigSetId = 1 @@ -850,9 +855,9 @@ function ConfigTabClass:UpdateLevel() end function ConfigTabClass:BuildModList() - local modList = new("ModList") + local modList = new("ModList"):ModList() self.modList = modList - local enemyModList = new("ModList") + local enemyModList = new("ModList"):ModList() self.enemyModList = enemyModList local input = self.configSets[self.activeConfigSetId].input local placeholder = self.configSets[self.activeConfigSetId].placeholder @@ -934,8 +939,8 @@ end function ConfigTabClass:OpenConfigSetManagePopup() main:OpenPopup(370, 290, "Manage Config Sets", { - new("ConfigSetListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("ConfigSetListControl"):ConfigSetListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) diff --git a/src/Classes/Control.lua b/src/Classes/Control.lua index 110eb6884e..1b96288642 100644 --- a/src/Classes/Control.lua +++ b/src/Classes/Control.lua @@ -6,6 +6,8 @@ local t_insert = table.insert local m_floor = math.floor + +---@enum (key) AnchorPoint local anchorPos = { ["TOPLEFT"] = { 0 , 0 }, ["TOP"] = { 0.5, 0 }, @@ -32,7 +34,18 @@ local rect = { for containers --]] -local ControlClass = newClass("Control", function(self, anchor, rect) +---@class Control +---@field enabled boolean | fun(...: any): boolean +---@field onFocusGained? fun() +---@field onFocusLost? fun() +local ControlClass = newClass("Control") + +---@alias ControlAnchor [AnchorPoint, Control|ControlHost, AnchorPoint, boolean|nil] +---@alias ControlRect [number|nil, number|nil, number|nil, number] + +---@param anchor? ControlAnchor +---@param rect? ControlRect +function ControlClass:Control(anchor, rect) self.rectStart = rect or {0, 0, 0, 0} self.x, self.y, self.width, self.height = unpack(self.rectStart) self.shown = true @@ -41,7 +54,8 @@ local ControlClass = newClass("Control", function(self, anchor, rect) if anchor then self:SetAnchor(anchor[1], anchor[2], anchor[3], nil, nil, anchor[4]) end -end) + return self +end function ControlClass:GetProperty(name) if type(self[name]) == "function" then diff --git a/src/Classes/ControlHost.lua b/src/Classes/ControlHost.lua index 13aec58ef9..4f795135b8 100644 --- a/src/Classes/ControlHost.lua +++ b/src/Classes/ControlHost.lua @@ -4,9 +4,13 @@ -- Host for UI controls -- -local ControlHostClass = newClass("ControlHost", function(self) - self.controls = { } -end) +---@class ControlHost +local ControlHostClass = newClass("ControlHost") + +function ControlHostClass:ControlHost() + self.controls = {} + return self +end function ControlHostClass:SelectControl(newSelControl) if self.selControl == newSelControl then diff --git a/src/Classes/DraggerControl.lua b/src/Classes/DraggerControl.lua index de331cbb04..6619b5314c 100644 --- a/src/Classes/DraggerControl.lua +++ b/src/Classes/DraggerControl.lua @@ -3,9 +3,12 @@ -- Class: Dragger Button Control -- Dragger button control. -- -local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost", function(self, anchor, rect, label, onKeyDown, onKeyUp, onRightClick, onHover, forceTooltip) - self.Control(anchor, rect) - self.TooltipHost() +---@type DraggerControl: Control, TooltipHost +local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost") + +function DraggerClass:DraggerControl(anchor, rect, label, onKeyDown, onKeyUp, onRightClick, onHover, forceTooltip) + self:Control(anchor, rect) + self:TooltipHost() self.label = label self.onKeyDown = onKeyDown self.onKeyUp = onKeyUp @@ -14,7 +17,8 @@ local DraggerClass = newClass("DraggerControl", "Control", "TooltipHost", functi self.forceTooltip = forceTooltip self.cursorX = 0 self.cursorY = 0 -end) + return self +end function DraggerClass:SetImage(path) if path then diff --git a/src/Classes/DropDownControl.lua b/src/Classes/DropDownControl.lua index bd75e93f1d..379a6d0bf8 100644 --- a/src/Classes/DropDownControl.lua +++ b/src/Classes/DropDownControl.lua @@ -8,11 +8,14 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor -local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "TooltipHost", "SearchHost", function(self, anchor, rect, list, selFunc, tooltipText) - self.Control(anchor, rect) - self.ControlHost() - self.TooltipHost(tooltipText) - self.SearchHost( +---@class DropDownControl: Control, ControlHost, TooltipHost, SearchHost +local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "TooltipHost", "SearchHost") + +function DropDownClass:DropDownControl(anchor, rect, list, selFunc, tooltipText) + self:Control(anchor, rect) + self:ControlHost() + self:TooltipHost(tooltipText) + self:SearchHost( -- list to filter function() return self.list @@ -30,7 +33,7 @@ local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "Too return StripEscapes(listVal) end ) - self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-1, 0, 18, 0}, (self.height - 4) * 4) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {-1, 0, 18, 0}, (self.height - 4) * 4) self.controls.scrollBar.height = function() return self.dropHeight + 2 end @@ -49,8 +52,9 @@ local DropDownClass = newClass("DropDownControl", "Control", "ControlHost", "Too self.enableDroppedWidth = false -- Set by the parent control. Activates the auto width of the box component. self.enableChangeBoxWidth = false - -- self.tag = "-" -end) + -- self.tag = "-" + return self +end -- maps the actual dropdown row index (after eventual filtering) to the original (unfiltered) list index function DropDownClass:DropIndexToListIndex(dropIndex) diff --git a/src/Classes/EditControl.lua b/src/Classes/EditControl.lua index 2964057adf..353297fe1d 100644 --- a/src/Classes/EditControl.lua +++ b/src/Classes/EditControl.lua @@ -36,11 +36,14 @@ local function newlineCount(str) end end -local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler", "TooltipHost", function(self, anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) - self.ControlHost() - self.Control(anchor, rect) - self.UndoHandler() - self.TooltipHost() +---@class EditControl: ControlHost, Control, UndoHandler, TooltipHost +local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler", "TooltipHost") + +function EditClass:EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) + self:ControlHost() + self:Control(anchor, rect) + self:UndoHandler() + self:TooltipHost() self:SetText(init or "") self.prompt = prompt self.filter = filter or (main.unicode and "%c" or "^%w%p ") @@ -64,24 +67,24 @@ local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler if self.filter == "%D" or self.filter == "^%-%d" then -- Add +/- buttons for integer number edits self.isNumeric = true - self.controls.buttonDown = new("ButtonControl", {"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "-", function() + self.controls.buttonDown = new("ButtonControl"):ButtonControl({"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "-", function() self:OnKeyUp("DOWN") end) - self.controls.buttonUp = new("ButtonControl", {"RIGHT",self.controls.buttonDown,"LEFT"}, {-1, 0, buttonSize, buttonSize}, "+", function() + self.controls.buttonUp = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.buttonDown,"LEFT"}, {-1, 0, buttonSize, buttonSize}, "+", function() self:OnKeyUp("UP") end) elseif clearable then - self.controls.buttonClear = new("ButtonControl", {"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "x", function() + self.controls.buttonClear = new("ButtonControl"):ButtonControl({"RIGHT",self,"RIGHT"}, {-2, 0, buttonSize, buttonSize}, "x", function() self:SetText("", true) end) self.controls.buttonClear.shown = function() return #self.buf > 0 and self:IsMouseInBounds() end end - self.controls.scrollBarH = new("ScrollBarControl", {"BOTTOMLEFT",self,"BOTTOMLEFT"}, {1, -1, 0, 14}, 60, "HORIZONTAL", true) + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl({"BOTTOMLEFT",self,"BOTTOMLEFT"}, {1, -1, 0, 14}, 60, "HORIZONTAL", true) self.controls.scrollBarH.width = function() local width, height = self:GetSize() return width - (self.controls.scrollBarV.enabled and 16 or 2) end - self.controls.scrollBarV = new("ScrollBarControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-1, 1, 14, 0}, (lineHeight or 0) * 3, "VERTICAL", true) + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT",self,"TOPRIGHT"}, {-1, 1, 14, 0}, (lineHeight or 0) * 3, "VERTICAL", true) self.controls.scrollBarV.height = function() local width, height = self:GetSize() return height - (self.controls.scrollBarH.enabled and 16 or 2) @@ -91,7 +94,8 @@ local EditClass = newClass("EditControl", "ControlHost", "Control", "UndoHandler self.controls.scrollBarV.shown = false end self.protected = false -end) + return self +end function EditClass:SetText(text, notify) self.buf = tostring(text) diff --git a/src/Classes/ExtBuildListControl.lua b/src/Classes/ExtBuildListControl.lua index fb6070ba69..c00323a3a2 100644 --- a/src/Classes/ExtBuildListControl.lua +++ b/src/Classes/ExtBuildListControl.lua @@ -10,36 +10,39 @@ local m_max = math.max local m_min = math.min local dkjson = require "dkjson" -local ExtBuildListControlClass = newClass("ExtBuildListControl", "ControlHost", "Control", - function(self, anchor, rect, providers) - self.Control(anchor, rect) - self.ControlHost() - self:SelectControl() - - self.rowHeight = 200 - self.scroll = "VERTICAL" - self.forceTooltip = false - self.font = "VAR" - self.importButtons = {} - self.previewButtons = {} - self.inTransition = false - self.contentHeight = 0 - self.tabs = {} - self.activeListProvider = nil - self.buildProviders = providers - self.buildProvidersList = {} - self.providerMaxLength = 150 - for _, provider in ipairs(self.buildProviders) do - self.providerMaxLength = m_max(self.providerMaxLength, DrawStringWidth(16, self.font, provider.name) + 30) - t_insert(self.buildProvidersList, provider.name) - end - end) +---@class ExtBuildListControl: ControlHost, Control +local ExtBuildListControlClass = newClass("ExtBuildListControl", "ControlHost", "Control") + +function ExtBuildListControlClass:ExtBuildListControl(anchor, rect, providers) + self:Control(anchor, rect) + self:ControlHost() + self:SelectControl() + + self.rowHeight = 200 + self.scroll = "VERTICAL" + self.forceTooltip = false + self.font = "VAR" + self.importButtons = {} + self.previewButtons = {} + self.inTransition = false + self.contentHeight = 0 + self.tabs = {} + self.activeListProvider = nil + self.buildProviders = providers + self.buildProvidersList = {} + self.providerMaxLength = 150 + for _, provider in ipairs(self.buildProviders) do + self.providerMaxLength = m_max(self.providerMaxLength, DrawStringWidth(16, self.font, provider.name) + 30) + t_insert(self.buildProvidersList, provider.name) + end + return self +end function ExtBuildListControlClass:Init(providerName) wipeTable(self.controls) wipeTable(self.tabs) - self.controls.sort = new("DropDownControl", { "TOP", self, "TOP" }, { 0, -20, self.providerMaxLength, 20 }, + self.controls.sort = new("DropDownControl"):DropDownControl({ "TOP", self, "TOP" }, { 0, -20, self.providerMaxLength, 20 }, self.buildProvidersList, function(index, value) self:Init(value) end) @@ -72,7 +75,7 @@ function ExtBuildListControlClass:Init(providerName) if lastControl then anchor = { "LEFT", lastControl, "RIGHT" } end - local button = new("ButtonControl", anchor, { 0, lastControl and 0 or -20, stringWidth + 10, 20 }, title, function() + local button = new("ButtonControl"):ButtonControl(anchor, { 0, lastControl and 0 or -20, stringWidth + 10, 20 }, title, function() if self.activeListProvider:GetActiveList() == title then return end @@ -105,7 +108,7 @@ function ExtBuildListControlClass:Init(providerName) return (self.width() - self.controls.sort.width()) / 2 end - self.controls.scrollBarV = new("ScrollBarControl", { "RIGHT", self, "RIGHT" }, { -1, 0, self.scroll and 16 or 0, 0 }, + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({ "RIGHT", self, "RIGHT" }, { -1, 0, self.scroll and 16 or 0, 0 }, 80, "VERTICAL") { -- y = function() -- return (self.scrollH and -8 or 0) @@ -120,7 +123,7 @@ function ExtBuildListControlClass:Init(providerName) end if self.activeListProvider:GetPageUrl() then - self.controls.all = new("ButtonControl", { "BOTTOM", self, "BOTTOM" }, { 0, 1, self.width, 20 }, "See All", + self.controls.all = new("ButtonControl"):ButtonControl({ "BOTTOM", self, "BOTTOM" }, { 0, 1, self.width, 20 }, "See All", function() local url = self.activeListProvider:GetPageUrl() if url then @@ -407,14 +410,14 @@ function ExtBuildListControlClass:Draw(viewPort, noTooltip) local relativeHeight = currentHeight + 10 - self.controls.scrollBarV.offset if relativeHeight > y and relativeHeight < self.height() + y - 10 then if build.buildLink then - local importButton = new("ButtonControl", nil, { x, currentHeight - self.controls.scrollBarV.offset, 45, 20 }, "Import", function() + local importButton = new("ButtonControl"):ButtonControl(nil, { x, currentHeight - self.controls.scrollBarV.offset, 45, 20 }, "Import", function() self:importBuild(build) end) t_insert(self.controls, importButton) end if build.previewLink then - local previewButton = new("ButtonControl", nil, { x + 50, currentHeight - self.controls.scrollBarV.offset, 60, 20 }, "Preview", function() + local previewButton = new("ButtonControl"):ButtonControl(nil, { x + 50, currentHeight - self.controls.scrollBarV.offset, 60, 20 }, "Preview", function() OpenURL(build.previewLink) end) t_insert(self.controls, previewButton) diff --git a/src/Classes/ExtBuildListProvider.lua b/src/Classes/ExtBuildListProvider.lua index 2b0904ce86..546dc8b32c 100644 --- a/src/Classes/ExtBuildListProvider.lua +++ b/src/Classes/ExtBuildListProvider.lua @@ -10,14 +10,16 @@ -- .buildList [Needs to be filled in :GetBuilds with current list. buildName and buildLink fields are required.] -- .statusMsg [This can be used to print status message on the screen. Builds will not be listed if it has a value other than nil.] -local ExtBuildListProviderClass = newClass("ExtBuildListProvider", - function(self, listTitles) - self.listTitles = listTitles - self.buildList = {} - self.activeList = nil - self.statusMsg = nil - end -) +---@class ExtBuildListProvider +local ExtBuildListProviderClass = newClass("ExtBuildListProvider") + +function ExtBuildListProviderClass:ExtBuildListProvider(listTitles) + self.listTitles = listTitles + self.buildList = {} + self.activeList = nil + self.statusMsg = nil + return self +end function ExtBuildListProviderClass:GetPageUrl() return nil diff --git a/src/Classes/FolderListControl.lua b/src/Classes/FolderListControl.lua index 8cc7c11ba2..8e0abcd406 100644 --- a/src/Classes/FolderListControl.lua +++ b/src/Classes/FolderListControl.lua @@ -6,13 +6,16 @@ local ipairs = ipairs local t_insert = table.insert -local FolderListClass = newClass("FolderListControl", "ListControl", function(self, anchor, rect, subPath, onChange) - self.ListControl(anchor, rect, 16, "VERTICAL", false, { }) +---@class FolderListControl: ListControl +local FolderListClass = newClass("FolderListControl", "ListControl") + +function FolderListClass:FolderListControl(anchor, rect, subPath, onChange) + self:ListControl(anchor, rect, 16, "VERTICAL", false, { }) self.subPath = subPath or "" self.sortMode = "NAME" self.onChangeCallback = onChange - self.controls.path = new("PathControl", {"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, self.subPath, function(newSubPath) + self.controls.path = new("PathControl"):PathControl({"BOTTOM",self,"TOP"}, {0, -2, self.width, 24}, main.buildPath, self.subPath, function(newSubPath) self.subPath = newSubPath self:BuildList() self.selIndex = nil @@ -22,7 +25,8 @@ local FolderListClass = newClass("FolderListControl", "ListControl", function(se end end) self:BuildList() -end) + return self +end function FolderListClass:SortList() if not self.list then return end diff --git a/src/Classes/GemSelectControl.lua b/src/Classes/GemSelectControl.lua index f8ef76d229..ba7f0d50e5 100644 --- a/src/Classes/GemSelectControl.lua +++ b/src/Classes/GemSelectControl.lua @@ -14,9 +14,19 @@ local m_floor = math.floor local toolTipText = "Prefix tag searches with a colon and exclude tags with a dash. e.g. :fire:lightning:-cold:area" local imbuedTooltipText = "\"Socketed in\" item must be set in order to add an imbued support.\nOnly one imbued support is allowed per item." -local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self, anchor, rect, skillsTab, index, changeFunc, forceTooltip, imbued) - self.EditControl(anchor, rect, nil, nil, "^ %a':-") - self.controls.scrollBar = new("ScrollBarControl", { "TOPRIGHT", self, "TOPRIGHT" }, {-1, 0, 18, 0}, (self.height - 4) * 4) +---@class GemSelectControl: EditControl +local GemSelectClass = newClass("GemSelectControl", "EditControl") + +---@param anchor ControlAnchor +---@param rect ControlRect +---@param skillsTab SkillsTab +---@param index integer +---@param changeFunc fun(...) +---@param forceTooltip boolean +---@param imbued boolean +function GemSelectClass:GemSelectControl(anchor, rect, skillsTab, index, changeFunc, forceTooltip, imbued) + self:EditControl(anchor, rect, nil, nil, "^ %a':-") + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({ "TOPRIGHT", self, "TOPRIGHT" }, {-1, 0, 18, 0}, (self.height - 4) * 4) self.controls.scrollBar.y = function() local width, height = self:GetSize() return height + 1 @@ -52,7 +62,8 @@ local GemSelectClass = newClass("GemSelectControl", "EditControl", function(self lifeReservationPercent = "LifePercent", } self.imbuedSelect = imbued -end) + return self +end function GemSelectClass:CalcOutputWithThisGem(calcFunc, gemData, useFullDPS) local gemList = self.skillsTab.displayGroup.gemList @@ -486,7 +497,7 @@ function GemSelectClass:Draw(viewPort, noTooltip) SetViewport() self:DrawControls(viewPort, (noTooltip and not self.forceTooltip) and self) if self.hoverSel then - local calcFunc, calcBase = self.skillsTab.build.calcsTab:GetMiscCalculator(self.build) + local calcFunc, calcBase = self.skillsTab.build.calcsTab:GetMiscCalculator() if calcFunc then self.tooltip:Clear() local gemData = self.gems[self.list[self.hoverSel]] diff --git a/src/Classes/ImportTab.lua b/src/Classes/ImportTab.lua index 7f4e631ff9..384fac07c3 100644 --- a/src/Classes/ImportTab.lua +++ b/src/Classes/ImportTab.lua @@ -19,27 +19,31 @@ local realmList = { local influenceInfo = itemLib.influenceInfo.all -local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function(self, build) - self.ControlHost() - self.Control() +---@class ImportTab: ControlHost, Control +local ImportTabClass = newClass("ImportTab", "ControlHost", "Control") + +---@param build Build +function ImportTabClass:ImportTab(build) + self:ControlHost() + self:Control() self.build = build self.charImportMode = "GETACCOUNTNAME" self.charImportStatus = "Idle" - self.controls.sectionCharImport = new("SectionControl", {"TOPLEFT",self,"TOPLEFT"}, {10, 18, 650, 250}, "Character Import") - self.controls.charImportStatusLabel = new("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 14, 200, 16}, function() + self.controls.sectionCharImport = new("SectionControl"):SectionControl({"TOPLEFT",self,"TOPLEFT"}, {10, 18, 650, 250}, "Character Import") + self.controls.charImportStatusLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 14, 200, 16}, function() return "^7Character import status: "..self.charImportStatus end) -- Stage: input account name - self.controls.accountNameHeader = new("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 16}, "^7To start importing a character, enter the character's account name:") + self.controls.accountNameHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 16}, "^7To start importing a character, enter the character's account name:") self.controls.accountNameHeader.shown = function() return self.charImportMode == "GETACCOUNTNAME" end - self.controls.accountRealm = new("DropDownControl", {"TOPLEFT",self.controls.accountNameHeader,"BOTTOMLEFT"}, {0, 4, 60, 20}, realmList) + self.controls.accountRealm = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.accountNameHeader,"BOTTOMLEFT"}, {0, 4, 60, 20}, realmList) self.controls.accountRealm:SelByValue(main.lastRealm or "PC", "id") - self.controls.accountName = new("EditControl", {"LEFT",self.controls.accountRealm,"RIGHT"}, {8, 0, 200, 20}, main.lastAccountName or "", nil, "%c", nil, nil, nil, nil, true) + self.controls.accountName = new("EditControl"):EditControl({"LEFT",self.controls.accountRealm,"RIGHT"}, {8, 0, 200, 20}, main.lastAccountName or "", nil, "%c", nil, nil, nil, nil, true) self.controls.accountName.pasteFilter = function(text) return text:gsub(".", function(c) local byte = c:byte() @@ -61,7 +65,7 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( return a:lower() < b:lower() end) end -- don't load the list many times - self.controls.accountNameGo = new("ButtonControl", {"LEFT",self.controls.accountName,"RIGHT"}, {8, 0, 60, 20}, "Start", function() + self.controls.accountNameGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.accountName,"RIGHT"}, {8, 0, 60, 20}, "Start", function() self.controls.sessionInput.buf = "" self:DownloadCharacterList() end) @@ -75,13 +79,13 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( end end - self.controls.accountHistory = new("DropDownControl", {"LEFT",self.controls.accountNameGo,"RIGHT"}, {8, 0, 200, 20}, historyList, function() + self.controls.accountHistory = new("DropDownControl"):DropDownControl({"LEFT",self.controls.accountNameGo,"RIGHT"}, {8, 0, 200, 20}, historyList, function() self.controls.accountName.buf = self.controls.accountHistory.list[self.controls.accountHistory.selIndex] end) self.controls.accountHistory:SelByValue(main.lastAccountName) self.controls.accountHistory:CheckDroppedWidth(true) - self.controls.removeAccount = new("ButtonControl", {"LEFT",self.controls.accountHistory,"RIGHT"}, {8, 0, 20, 20}, "X", function() + self.controls.removeAccount = new("ButtonControl"):ButtonControl({"LEFT",self.controls.accountHistory,"RIGHT"}, {8, 0, 20, 20}, "X", function() local accountName = self.controls.accountHistory.list[self.controls.accountHistory.selIndex] if (accountName ~= nil) then t_remove(self.controls.accountHistory.list, self.controls.accountHistory.selIndex) @@ -95,15 +99,15 @@ local ImportTabClass = newClass("ImportTab", "ControlHost", "Control", function( tooltip:AddLine(16, "^7Removes account from the dropdown list") end - self.controls.accountNameMissingDiscriminator = new("LabelControl", {"TOPLEFT",self.controls.accountName,"BOTTOMLEFT"}, {0, 8, 0, 16}, "^1Missing discriminator e.g. #1234") + self.controls.accountNameMissingDiscriminator = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.accountName,"BOTTOMLEFT"}, {0, 8, 0, 16}, "^1Missing discriminator e.g. #1234") self.controls.accountNameMissingDiscriminator.shown = function() return not self.controls.accountName.buf:match("[#%-]%d%d%d%d$") and self.controls.accountName.buf ~= "" end - self.controls.accountNameUnicode = new("LabelControl", {"TOPLEFT",self.controls.accountRealm,"BOTTOMLEFT"}, {0, 34, 0, 14}, "^7Note: if the account name contains non-ASCII characters it must be pasted into the textbox,\nnot typed manually.") + self.controls.accountNameUnicode = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.accountRealm,"BOTTOMLEFT"}, {0, 34, 0, 14}, "^7Note: if the account name contains non-ASCII characters it must be pasted into the textbox,\nnot typed manually.") -- Stage: input POESESSID - self.controls.sessionHeader = new("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 14}) + self.controls.sessionHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 14}) self.controls.sessionHeader.label = function() return [[ ^7The list of characters on ']]..self.controls.accountName.buf..[[' couldn't be retrieved. This may be because: @@ -119,19 +123,19 @@ You can get this from your web browser's cookies while logged into the Path of E self.controls.sessionHeader.shown = function() return self.charImportMode == "GETSESSIONID" end - self.controls.sessionRetry = new("ButtonControl", {"TOPLEFT",self.controls.sessionHeader,"TOPLEFT"}, {0, 122, 60, 20}, "Retry", function() + self.controls.sessionRetry = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.sessionHeader,"TOPLEFT"}, {0, 122, 60, 20}, "Retry", function() self:DownloadCharacterList() end) - self.controls.sessionCancel = new("ButtonControl", {"LEFT",self.controls.sessionRetry,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() + self.controls.sessionCancel = new("ButtonControl"):ButtonControl({"LEFT",self.controls.sessionRetry,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() self.charImportMode = "GETACCOUNTNAME" self.charImportStatus = "Idle" end) - self.controls.sessionPrivacySettings = new("ButtonControl", {"LEFT",self.controls.sessionCancel,"RIGHT"}, {8, 0, 120, 20}, "Privacy Settings", function() + self.controls.sessionPrivacySettings = new("ButtonControl"):ButtonControl({"LEFT",self.controls.sessionCancel,"RIGHT"}, {8, 0, 120, 20}, "Privacy Settings", function() OpenURL('https://www.pathofexile.com/my-account/privacy') end) - self.controls.sessionInput = new("EditControl", {"TOPLEFT",self.controls.sessionRetry,"BOTTOMLEFT"}, {0, 8, 350, 20}, "", "POESESSID", "%X", 32) + self.controls.sessionInput = new("EditControl"):EditControl({"TOPLEFT",self.controls.sessionRetry,"BOTTOMLEFT"}, {0, 8, 350, 20}, "", "POESESSID", "%X", 32) self.controls.sessionInput:SetProtected(true) - self.controls.sessionGo = new("ButtonControl", {"LEFT",self.controls.sessionInput,"RIGHT"}, {8, 0, 60, 20}, "Go", function() + self.controls.sessionGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.sessionInput,"RIGHT"}, {8, 0, 60, 20}, "Go", function() self:DownloadCharacterList() end) self.controls.sessionGo.enabled = function() @@ -139,20 +143,20 @@ You can get this from your web browser's cookies while logged into the Path of E end -- Stage: select character and import data - self.controls.charSelectHeader = new("LabelControl", {"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 16}, "^7Choose character to import data from:") + self.controls.charSelectHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.sectionCharImport,"TOPLEFT"}, {6, 40, 200, 16}, "^7Choose character to import data from:") self.controls.charSelectHeader.shown = function() return self.charImportMode == "SELECTCHAR" or self.charImportMode == "IMPORTING" end - self.controls.charSelectLeagueLabel = new("LabelControl", {"TOPLEFT",self.controls.charSelectHeader,"BOTTOMLEFT"}, {0, 6, 0, 14}, "^7League:") - self.controls.charSelectLeague = new("DropDownControl", {"LEFT",self.controls.charSelectLeagueLabel,"RIGHT"}, {4, 0, 150, 18}, nil, function(index, value) + self.controls.charSelectLeagueLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.charSelectHeader,"BOTTOMLEFT"}, {0, 6, 0, 14}, "^7League:") + self.controls.charSelectLeague = new("DropDownControl"):DropDownControl({"LEFT",self.controls.charSelectLeagueLabel,"RIGHT"}, {4, 0, 150, 18}, nil, function(index, value) self:BuildCharacterList(value.league) end) - self.controls.charSelect = new("DropDownControl", {"TOPLEFT",self.controls.charSelectHeader,"BOTTOMLEFT"}, {0, 24, 400, 18}) + self.controls.charSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.charSelectHeader,"BOTTOMLEFT"}, {0, 24, 400, 18}) self.controls.charSelect.enabled = function() return self.charImportMode == "SELECTCHAR" end - self.controls.charImportHeader = new("LabelControl", {"TOPLEFT",self.controls.charSelect,"BOTTOMLEFT"}, {0, 16, 200, 16}, "^7Import:") - self.controls.charImportTree = new("ButtonControl", {"LEFT",self.controls.charImportHeader, "RIGHT"}, {8, 0, 170, 20}, "Passive Tree and Jewels", function() + self.controls.charImportHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.charSelect,"BOTTOMLEFT"}, {0, 16, 200, 16}, "^7Import:") + self.controls.charImportTree = new("ButtonControl"):ButtonControl({"LEFT",self.controls.charImportHeader, "RIGHT"}, {8, 0, 170, 20}, "Passive Tree and Jewels", function() if self.build.spec:CountAllocNodes() > 0 then main:OpenConfirmPopup("Character Import", "Importing the passive tree will overwrite your current tree.", "Import", function() self:DownloadPassiveTree() @@ -165,39 +169,39 @@ You can get this from your web browser's cookies while logged into the Path of E self.controls.charImportTree.enabled = function() return self.charImportMode == "SELECTCHAR" end - self.controls.charImportTreeClearJewels = new("CheckBoxControl", {"LEFT",self.controls.charImportTree,"RIGHT"}, {90, 0, 18}, "Delete jewels:", nil, "Delete all existing jewels when importing.", true) - self.controls.charImportItems = new("ButtonControl", {"LEFT",self.controls.charImportTree, "LEFT"}, {0, 36, 110, 20}, "Items and Skills", function() + self.controls.charImportTreeClearJewels = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.charImportTree,"RIGHT"}, {90, 0, 18}, "Delete jewels:", nil, "Delete all existing jewels when importing.", true) + self.controls.charImportItems = new("ButtonControl"):ButtonControl({"LEFT",self.controls.charImportTree, "LEFT"}, {0, 36, 110, 20}, "Items and Skills", function() self:DownloadItems() self:SetPredefinedBuildName() end) self.controls.charImportItems.enabled = function() return self.charImportMode == "SELECTCHAR" end - self.controls.charImportItemsClearSkills = new("CheckBoxControl", {"LEFT",self.controls.charImportItems,"RIGHT"}, {85, 0, 18}, "Delete skills:", nil, "Delete all existing skills when importing.", true) - self.controls.charImportItemsClearItems = new("CheckBoxControl", {"LEFT",self.controls.charImportItems,"RIGHT"}, {220, 0, 18}, "Delete equipment:", nil, "Delete all equipped items when importing.", true) - self.controls.charImportItemsIgnoreWeaponSwap = new("CheckBoxControl", {"LEFT",self.controls.charImportItems,"RIGHT"}, {380, 0, 18}, "Ignore weapon swap:", nil, "Ignore items and skills in weapon swap.", false) - self.controls.charBanditNote = new("LabelControl", {"TOPLEFT",self.controls.charImportHeader,"BOTTOMLEFT"}, {0, 50, 200, 14}, "^7Tip: After you finish importing a character, make sure you update the bandit choice,\nas it cannot be imported.") + self.controls.charImportItemsClearSkills = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.charImportItems,"RIGHT"}, {85, 0, 18}, "Delete skills:", nil, "Delete all existing skills when importing.", true) + self.controls.charImportItemsClearItems = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.charImportItems,"RIGHT"}, {220, 0, 18}, "Delete equipment:", nil, "Delete all equipped items when importing.", true) + self.controls.charImportItemsIgnoreWeaponSwap = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.charImportItems,"RIGHT"}, {380, 0, 18}, "Ignore weapon swap:", nil, "Ignore items and skills in weapon swap.", false) + self.controls.charBanditNote = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.charImportHeader,"BOTTOMLEFT"}, {0, 50, 200, 14}, "^7Tip: After you finish importing a character, make sure you update the bandit choice,\nas it cannot be imported.") - self.controls.charClose = new("ButtonControl", {"TOPLEFT",self.controls.charImportHeader,"BOTTOMLEFT"}, {0, 90, 60, 20}, "Close", function() + self.controls.charClose = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.charImportHeader,"BOTTOMLEFT"}, {0, 90, 60, 20}, "Close", function() self.charImportMode = "GETACCOUNTNAME" self.charImportStatus = "Idle" end) -- Build import/export - self.controls.sectionBuild = new("SectionControl", {"TOPLEFT",self.controls.sectionCharImport,"BOTTOMLEFT"}, {0, 18, 650, 182}, "Build Sharing") - self.controls.generateCodeLabel = new("LabelControl", {"TOPLEFT",self.controls.sectionBuild,"TOPLEFT"}, {6, 14, 0, 16}, "^7Generate a code to share this build with other Path of Building users:") - self.controls.generateCode = new("ButtonControl", {"LEFT",self.controls.generateCodeLabel,"RIGHT"}, {4, 0, 80, 20}, "Generate", function() + self.controls.sectionBuild = new("SectionControl"):SectionControl({"TOPLEFT",self.controls.sectionCharImport,"BOTTOMLEFT"}, {0, 18, 650, 182}, "Build Sharing") + self.controls.generateCodeLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.sectionBuild,"TOPLEFT"}, {6, 14, 0, 16}, "^7Generate a code to share this build with other Path of Building users:") + self.controls.generateCode = new("ButtonControl"):ButtonControl({"LEFT",self.controls.generateCodeLabel,"RIGHT"}, {4, 0, 80, 20}, "Generate", function() self.controls.generateCodeOut:SetText(common.base64.encode(Deflate(self.build:SaveDB("code"))):gsub("+","-"):gsub("/","_")) end) - self.controls.enablePartyExportBuffs = new("CheckBoxControl", {"LEFT",self.controls.generateCode,"RIGHT"}, {100, 0, 18}, "Export Support", function(state) + self.controls.enablePartyExportBuffs = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.generateCode,"RIGHT"}, {100, 0, 18}, "Export Support", function(state) self.build.partyTab.enableExportBuffs = state self.build.buildFlag = true end, "This is for party play, to export support character, it enables the exporting of auras, curses and modifiers to the enemy", false) - self.controls.generateCodeOut = new("EditControl", {"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, {0, 8, 250, 20}, "", "Code", "%Z") + self.controls.generateCodeOut = new("EditControl"):EditControl({"TOPLEFT",self.controls.generateCodeLabel,"BOTTOMLEFT"}, {0, 8, 250, 20}, "", "Code", "%Z") self.controls.generateCodeOut.enabled = function() return #self.controls.generateCodeOut.buf > 0 end - self.controls.generateCodeCopy = new("ButtonControl", {"LEFT",self.controls.generateCodeOut,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() + self.controls.generateCodeCopy = new("ButtonControl"):ButtonControl({"LEFT",self.controls.generateCodeOut,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() Copy(self.controls.generateCodeOut.buf) self.controls.generateCodeOut:SetText("") end) @@ -217,12 +221,12 @@ You can get this from your web browser's cookies while logged into the Path of E end local exportWebsitesList = getExportSitesFromImportList() - self.controls.exportFrom = new("DropDownControl", { "LEFT", self.controls.generateCodeCopy,"RIGHT"}, {8, 0, 120, 20}, exportWebsitesList, function(_, selectedWebsite) + self.controls.exportFrom = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.generateCodeCopy,"RIGHT"}, {8, 0, 120, 20}, exportWebsitesList, function(_, selectedWebsite) main.lastExportedWebsite = selectedWebsite.id self.exportWebsiteSelected = selectedWebsite.id end) self.controls.exportFrom:SelByValue(self.exportWebsiteSelected or main.lastExportedWebsite or "Maxroll", "id") - self.controls.generateCodeByLink = new("ButtonControl", { "LEFT", self.controls.exportFrom, "RIGHT"}, {8, 0, 100, 20}, "Share", function() + self.controls.generateCodeByLink = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.exportFrom, "RIGHT"}, {8, 0, 100, 20}, "Share", function() local exportWebsite = exportWebsitesList[self.controls.exportFrom.selIndex] local subScriptId = buildSites.UploadBuild(self.controls.generateCodeOut.buf, exportWebsite) if subScriptId then @@ -254,8 +258,8 @@ You can get this from your web browser's cookies while logged into the Path of E end return #self.controls.generateCodeOut.buf > 0 end - self.controls.generateCodeNote = new("LabelControl", {"TOPLEFT",self.controls.generateCodeOut,"BOTTOMLEFT"}, {0, 4, 0, 14}, "^7Note: this code can be very long; you can use 'Share' to shrink it.") - self.controls.importCodeHeader = new("LabelControl", {"TOPLEFT",self.controls.generateCodeNote,"BOTTOMLEFT"}, {0, 26, 0, 16}, "^7To import a build, enter URL or code here:") + self.controls.generateCodeNote = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.generateCodeOut,"BOTTOMLEFT"}, {0, 4, 0, 14}, "^7Note: this code can be very long; you can use 'Share' to shrink it.") + self.controls.importCodeHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.generateCodeNote,"BOTTOMLEFT"}, {0, 26, 0, 16}, "^7To import a build, enter URL or code here:") local importCodeHandle = function (buf) self.importCodeSite = nil @@ -330,21 +334,21 @@ You can get this from your web browser's cookies while logged into the Path of E end end - self.controls.importCodeIn = new("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, 20}, "", nil, nil, nil, importCodeHandle, nil, nil, true) + self.controls.importCodeIn = new("EditControl"):EditControl({"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, 20}, "", nil, nil, nil, importCodeHandle, nil, nil, true) self.controls.importCodeIn.enterFunc = function() if self.importCodeValid then self.controls.importCodeGo.onClick() end end - self.controls.importCodeState = new("LabelControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, 16}) + self.controls.importCodeState = new("LabelControl"):LabelControl({"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, 16}) self.controls.importCodeState.label = function() return self.importCodeDetail or "" end - self.controls.importCodeMode = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 200, 20}, { "Import to this build", "Import to a new build", "Import as comparison" }) + self.controls.importCodeMode = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 200, 20}, { "Import to this build", "Import to a new build", "Import as comparison" }) self.controls.importCodeMode.enabled = function() return (self.build.dbFileName or self.controls.importCodeMode.selIndex == 3) and self.importCodeValid end - self.controls.importCodeGo = new("ButtonControl", {"LEFT",self.controls.importCodeMode,"RIGHT"}, {8, 0, 160, 20}, "Import", function() + self.controls.importCodeGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.importCodeMode,"RIGHT"}, {8, 0, 160, 20}, "Import", function() if self.importCodeSite and not self.importCodeXML then self.importCodeFetching = true local selectedWebsite = buildSites.websiteList[self.importCodeSite] @@ -374,7 +378,8 @@ You can get this from your web browser's cookies while logged into the Path of E self.controls.importCodeGo.onClick() end end -end) + return self +end function ImportTabClass:Load(xml, fileName) self.lastRealm = xml.attrib.lastRealm @@ -1000,7 +1005,7 @@ function ImportTabClass:ImportItem(itemData, slotName) return end - local item = new("Item") + local item = new("Item"):Item() -- Determine rarity, display name and base type of the item item.rarity = rarityMap[itemData.frameType] diff --git a/src/Classes/Item.lua b/src/Classes/Item.lua index d63d7374f9..3dee2afbeb 100644 --- a/src/Classes/Item.lua +++ b/src/Classes/Item.lua @@ -57,11 +57,15 @@ end local influenceInfo = itemLib.influenceInfo.all -local ItemClass = newClass("Item", function(self, raw, rarity, highQuality) +---@class Item +local ItemClass = newClass("Item") + +function ItemClass:Item(raw, rarity, highQuality) if raw then self:ParseRaw(sanitiseText(raw), rarity, highQuality) - end -end) + end + return self +end -- Reset all influence keys to false function ItemClass:ResetInfluence() @@ -1384,7 +1388,7 @@ function ItemClass:BuildModListForSlotNum(baseList, slotNum) if slotNum ~= 1 then slotName = slotName:gsub("1", tostring(slotNum)) end - local modList = new("ModList") + local modList = new("ModList"):ModList() for _, baseMod in ipairs(baseList) do local mod = copyTable(baseMod) local add = true @@ -1673,7 +1677,7 @@ function ItemClass:BuildModList() if not self.base then return end - local baseList = new("ModList") + local baseList = new("ModList"):ModList() if self.base.weapon then self.weaponData = { } elseif self.base.armour then diff --git a/src/Classes/ItemDBControl.lua b/src/Classes/ItemDBControl.lua index 3136d1a847..0e6a5aa5af 100644 --- a/src/Classes/ItemDBControl.lua +++ b/src/Classes/ItemDBControl.lua @@ -10,8 +10,11 @@ local m_max = math.max local m_floor = math.floor -local ItemDBClass = newClass("ItemDBControl", "ListControl", function(self, anchor, rect, itemsTab, db, dbType) - self.ListControl(anchor, rect, 16, "VERTICAL", false) +---@class ItemDBControl: ListControl +local ItemDBClass = newClass("ItemDBControl", "ListControl") + +function ItemDBClass:ItemDBControl(anchor, rect, itemsTab, db, dbType) + self:ListControl(anchor, rect, 16, "VERTICAL", false) self.itemsTab = itemsTab self.db = db self.dbType = dbType @@ -28,35 +31,36 @@ local ItemDBClass = newClass("ItemDBControl", "ListControl", function(self, anch self.typeList = { "Any type", "Armour", "Jewellery", "One Handed Melee", "Two Handed Melee" } self.slotList = { "Any slot", "Weapon 1", "Weapon 2", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring", "Belt", "Jewel", "Flask", "Graft 1", "Graft 2" } local baseY = dbType == "RARE" and -22 or -62 - self.controls.slot = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY, 179, 18}, self.slotList, function(index, value) + self.controls.slot = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY, 179, 18}, self.slotList, function(index, value) self.listBuildFlag = true end) - self.controls.type = new("DropDownControl", {"LEFT",self.controls.slot,"RIGHT"}, {2, 0, 179, 18}, self.typeList, function(index, value) + self.controls.type = new("DropDownControl"):DropDownControl({"LEFT",self.controls.slot,"RIGHT"}, {2, 0, 179, 18}, self.typeList, function(index, value) self.listBuildFlag = true end) if dbType == "UNIQUE" then - self.controls.sort = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY + 20, 179, 18}, self.sortDropList, function(index, value) + self.controls.sort = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, baseY + 20, 179, 18}, self.sortDropList, function(index, value) self:SetSortMode(value.sortMode) end) - self.controls.league = new("DropDownControl", {"LEFT",self.controls.sort,"RIGHT"}, {2, 0, 179, 18}, self.leagueList, function(index, value) + self.controls.league = new("DropDownControl"):DropDownControl({"LEFT",self.controls.sort,"RIGHT"}, {2, 0, 179, 18}, self.leagueList, function(index, value) self.listBuildFlag = true end) - self.controls.requirement = new("DropDownControl", {"LEFT",self.controls.sort,"BOTTOMLEFT"}, {0, 11, 179, 18}, { "Any requirements", "Current level", "Current attributes", "Current useable" }, function(index, value) + self.controls.requirement = new("DropDownControl"):DropDownControl({"LEFT",self.controls.sort,"BOTTOMLEFT"}, {0, 11, 179, 18}, { "Any requirements", "Current level", "Current attributes", "Current useable" }, function(index, value) self.listBuildFlag = true end) - self.controls.obtainable = new("DropDownControl", {"LEFT",self.controls.requirement,"RIGHT"}, {2, 0, 179, 18}, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption"}, function(index, value) + self.controls.obtainable = new("DropDownControl"):DropDownControl({"LEFT",self.controls.requirement,"RIGHT"}, {2, 0, 179, 18}, { "Obtainable", "Any source", "Unobtainable", "Vendor Recipe", "Upgraded", "Boss Item", "Corruption"}, function(index, value) self.listBuildFlag = true end) end - self.controls.search = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() + self.controls.search = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() self.listBuildFlag = true end, nil, nil, true) - self.controls.searchMode = new("DropDownControl", {"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) + self.controls.searchMode = new("DropDownControl"):DropDownControl({"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) self.listBuildFlag = true end) self:BuildSortOrder() self.listBuildFlag = true -end) + return self +end function ItemDBClass:LoadLeaguesAndTypes() local leagueFlag = { } @@ -323,7 +327,7 @@ end function ItemDBClass:OnSelClick(index, item, doubleClick) if IsKeyDown("CTRL") then -- Add item - local newItem = new("Item", item.raw) + local newItem = new("Item"):Item(item.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true) diff --git a/src/Classes/ItemListControl.lua b/src/Classes/ItemListControl.lua index 53f9fde103..b184b12042 100644 --- a/src/Classes/ItemListControl.lua +++ b/src/Classes/ItemListControl.lua @@ -6,19 +6,22 @@ local pairs = pairs local t_insert = table.insert -local ItemListClass = newClass("ItemListControl", "ListControl", function(self, anchor, rect, itemsTab, forceTooltip) - self.ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemOrderList, forceTooltip) +---@class ItemListControl: ListControl +local ItemListClass = newClass("ItemListControl", "ListControl") + +function ItemListClass:ItemListControl(anchor, rect, itemsTab, forceTooltip) + self:ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemOrderList, forceTooltip) self.itemsTab = itemsTab self.label = "^7All items:" self.defaultText = "^x7F7F7FThis is the list of items that have been added to this build.\nYou can add items to this list by dragging them from\none of the other lists, or by clicking 'Add to build' when\nviewing an item." self.dragTargetList = { } - self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end - self.controls.deleteAll = new("ButtonControl", {"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() + self.controls.deleteAll = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() main:OpenConfirmPopup("Delete All", "Are you sure you want to delete all items in this build?", "Delete", function() for _, slot in pairs(itemsTab.slots) do slot:SetSelItemId(0) @@ -40,7 +43,7 @@ local ItemListClass = newClass("ItemListControl", "ListControl", function(self, self.controls.deleteAll.enabled = function() return #self.list > 0 end - self.controls.deleteUnused = new("ButtonControl", {"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 100, 18}, "Delete Unused", function() + self.controls.deleteUnused = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 100, 18}, "Delete Unused", function() local delList = {} for _, itemId in pairs(self.list) do if not itemsTab:GetEquippedSlotForItem(itemsTab.items[itemId]) and not self:FindEquippedAbyssJewel(itemId, false) and not self:FindSocketedJewel(itemId, false) then @@ -62,10 +65,11 @@ local ItemListClass = newClass("ItemListControl", "ListControl", function(self, self.controls.deleteUnused.enabled = function() return #self.list > 0 end - self.controls.sort = new("ButtonControl", {"RIGHT",self.controls.deleteUnused,"LEFT"}, {-4, 0, 60, 18}, "Sort", function() + self.controls.sort = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.deleteUnused,"LEFT"}, {-4, 0, 60, 18}, "Sort", function() itemsTab:SortItemList() end) -end) + return self +end function ItemListClass:FindSocketedJewel(jewelId, excludeActiveSpec) if not self.itemsTab.items[jewelId] or self.itemsTab.items[jewelId].type ~= "Jewel" then @@ -146,7 +150,7 @@ end function ItemListClass:ReceiveDrag(type, value, source) if type == "Item" then - local newItem = new("Item", value.raw) + local newItem = new("Item"):Item(value.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true, self.selDragIndex) self.itemsTab:PopulateSlots() @@ -184,7 +188,7 @@ function ItemListClass:OnSelClick(index, itemId, doubleClick) self.itemsTab.build.buildFlag = true end elseif doubleClick then - local newItem = new("Item", item:BuildRaw()) + local newItem = new("Item"):Item(item:BuildRaw()) newItem.id = item.id self.itemsTab:SetDisplayItem(newItem) end diff --git a/src/Classes/ItemSetListControl.lua b/src/Classes/ItemSetListControl.lua index 04d87e8537..4448d74ae2 100644 --- a/src/Classes/ItemSetListControl.lua +++ b/src/Classes/ItemSetListControl.lua @@ -8,10 +8,13 @@ local t_remove = table.remove local m_max = math.max local s_format = string.format -local ItemSetListClass = newClass("ItemSetListControl", "ListControl", function(self, anchor, rect, itemsTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemSetOrderList) +---@class ItemSetListControl: ListControl +local ItemSetListClass = newClass("ItemSetListControl", "ListControl") + +function ItemSetListClass:ItemSetListControl(anchor, rect, itemsTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, itemsTab.itemSetOrderList) self.itemsTab = itemsTab - self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() local newSet = copyTable(itemsTab.itemSets[self.selValue]) newSet.id = 1 while itemsTab.itemSets[newSet.id] do @@ -23,31 +26,32 @@ local ItemSetListClass = newClass("ItemSetListControl", "ListControl", function( self.controls.copy.enabled = function() return self.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSet(itemsTab.itemSets[self.selValue]) end) self.controls.rename.enabled = function() return self.selValue ~= nil end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() local newSet = itemsTab:NewItemSet() self:RenameSet(newSet, true) end) -end) + return self +end function ItemSetListClass:RenameSet(itemSet, addOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this item set:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, itemSet.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this item set:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, itemSet.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() itemSet.title = controls.edit.buf self.itemsTab.modFlag = true if addOnName then @@ -60,7 +64,7 @@ function ItemSetListClass:RenameSet(itemSet, addOnName) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if addOnName then self.itemsTab.itemSets[itemSet.id] = nil end @@ -95,7 +99,7 @@ function ItemSetListClass:ReceiveDrag(type, value, source) local itemSet = self.itemsTab:NewItemSet() itemSet.title = value.title for slotName, item in pairs(value.slots) do - local newItem = new("Item", item.raw) + local newItem = new("Item"):Item(item.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true) itemSet[slotName].selItemId = newItem.id diff --git a/src/Classes/ItemSlotControl.lua b/src/Classes/ItemSlotControl.lua index d7b549f3a2..9eafb7cc00 100644 --- a/src/Classes/ItemSlotControl.lua +++ b/src/Classes/ItemSlotControl.lua @@ -7,8 +7,11 @@ local pairs = pairs local t_insert = table.insert local m_min = math.min -local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(self, anchor, x, y, itemsTab, slotName, slotLabel, nodeId) - self.DropDownControl(anchor, {x, y, 310, 20}, { }, function(index, value) +---@class ItemSlotControl: DropDownControl +local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl") + +function ItemSlotClass:ItemSlotControl(anchor, x, y, itemsTab, slotName, slotLabel, nodeId) + self:DropDownControl(anchor, {x, y, 310, 20}, { }, function(index, value) if self.items[index] ~= self.selItemId then self:SetSelItemId(self.items[index]) itemsTab:PopulateSlots() @@ -29,7 +32,7 @@ local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(se self.slotName = slotName self.slotNum = tonumber(slotName:match("%d+$") or slotName:match("%d+")) if slotName:match("Flask") then - self.controls.activate = new("CheckBoxControl", {"RIGHT",self,"LEFT"}, {-2, 0, 20}, nil, function(state) + self.controls.activate = new("CheckBoxControl"):CheckBoxControl({"RIGHT",self,"LEFT"}, {-2, 0, 20}, nil, function(state) self.active = state itemsTab.activeItemSet[self.slotName].active = state itemsTab:AddUndoState() @@ -55,7 +58,8 @@ local ItemSlotClass = newClass("ItemSlotControl", "DropDownControl", function(se end self.label = slotLabel or slotName self.nodeId = nodeId -end) + return self +end function ItemSlotClass:SetSelItemId(selItemId) if self.nodeId then @@ -118,7 +122,7 @@ function ItemSlotClass:ReceiveDrag(type, value, source) if value.id and self.itemsTab.items[value.id] then self:SetSelItemId(value.id) else - local newItem = new("Item", value.raw) + local newItem = new("Item"):Item(value.raw) newItem:NormaliseQuality() self.itemsTab:AddItem(newItem, true) self:SetSelItemId(newItem.id) diff --git a/src/Classes/ItemsTab.lua b/src/Classes/ItemsTab.lua index 10b3140f61..1fe551bb15 100644 --- a/src/Classes/ItemsTab.lua +++ b/src/Classes/ItemsTab.lua @@ -92,14 +92,18 @@ local function getOutputStatValue(output, stat) return 0 end -local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class ItemsTab: UndoHandler, ControlHost, Control +local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function ItemsTabClass:ItemsTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build - self.socketViewer = new("PassiveTreeView") + self.socketViewer = new("PassiveTreeView"):PassiveTreeView() self.items = { } self.itemOrderList = { } @@ -107,10 +111,10 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.showStatDifferences = true -- PoB Trader class initialization - self.tradeQuery = new("TradeQuery", self) + self.tradeQuery = new("TradeQuery"):TradeQuery(self) -- Set selector - self.controls.setSelect = new("DropDownControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 8, 216, 20}, nil, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",self,"TOPLEFT"}, {96, 8, 216, 20}, nil, function(index, value) self:SetActiveItemSet(self.itemSetOrderList[index]) self:AddUndoState() end) @@ -124,13 +128,13 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self:AddItemSetTooltip(tooltip, self.itemSets[self.itemSetOrderList[index]]) end end - self.controls.setLabel = new("LabelControl", {"RIGHT",self.controls.setSelect,"LEFT"}, {-2, 0, 0, 16}, "^7Item set:") - self.controls.setManage = new("ButtonControl", {"LEFT",self.controls.setSelect,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() + self.controls.setLabel = new("LabelControl"):LabelControl({"RIGHT",self.controls.setSelect,"LEFT"}, {-2, 0, 0, 16}, "^7Item set:") + self.controls.setManage = new("ButtonControl"):ButtonControl({"LEFT",self.controls.setSelect,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() self:OpenItemSetManagePopup() end) -- Price Items - self.controls.priceDisplayItem = new("ButtonControl", {"TOPLEFT",self,"TOPLEFT"}, {96, 32, 310, 20}, "Trade for these items", function() + self.controls.priceDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self,"TOPLEFT"}, {96, 32, 310, 20}, "Trade for these items", function() self.tradeQuery:PriceItem() end) self.controls.priceDisplayItem.tooltipFunc = function(tooltip) @@ -143,7 +147,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.slots = { } self.orderedSlots = { } self.slotOrder = { } - self.slotAnchor = new("Control", {"TOPLEFT",self,"TOPLEFT"}, {96, 76, 310, 0}) + self.slotAnchor = new("Control"):Control({"TOPLEFT",self,"TOPLEFT"}, {96, 76, 310, 0}) local prevSlot = self.slotAnchor local function addSlot(slot) prevSlot = slot @@ -153,7 +157,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro t_insert(self.controls, slot) end for index, slotName in ipairs(baseSlots) do - local slot = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName) + local slot = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName) addSlot(slot) if slotName:match("Weapon") then -- Add alternate weapon slot @@ -161,14 +165,14 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro slot.shown = function() return not self.activeItemSet.useSecondWeaponSet end - local swapSlot = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap", slotName) + local swapSlot = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap", slotName) addSlot(swapSlot) swapSlot.weaponSet = 2 swapSlot.shown = function() return self.activeItemSet.useSecondWeaponSet end for i = 1, 6 do - local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) + local abyssal = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Swap Abyssal Socket "..i, "Abyssal #"..i) addSlot(abyssal) abyssal.parentSlot = swapSlot abyssal.weaponSet = 2 @@ -189,7 +193,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro if slotName == "Weapon 1" or slotName == "Weapon 2" or slotName == "Helmet" or slotName == "Gloves" or slotName == "Body Armour" or slotName == "Boots" or slotName == "Belt" then -- Add Abyssal Socket slots for i = 1, 6 do - local abyssal = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) + local abyssal = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, slotName.." Abyssal Socket "..i, "Abyssal #"..i) addSlot(abyssal) abyssal.parentSlot = slot if slotName:match("Weapon") then @@ -204,7 +208,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro end -- Passive tree dropdown controls - self.controls.specSelect = new("DropDownControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, {0, 8, 216, 20}, nil, function(index, value) + self.controls.specSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, {0, 8, 216, 20}, nil, function(index, value) if self.build.treeTab.specList[index] then self.build.modFlag = true self.build.treeTab:SetActiveSpec(index) @@ -214,10 +218,10 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return #self.controls.specSelect.list > 1 end prevSlot = self.controls.specSelect - self.controls.specButton = new("ButtonControl", {"LEFT",prevSlot,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() + self.controls.specButton = new("ButtonControl"):ButtonControl({"LEFT",prevSlot,"RIGHT"}, {4, 0, 90, 20}, "Manage...", function() self.build.treeTab:OpenSpecManagePopup() end) - self.controls.specLabel = new("LabelControl", {"RIGHT",prevSlot,"LEFT"}, {-2, 0, 0, 16}, "^7Passive tree:") + self.controls.specLabel = new("LabelControl"):LabelControl({"RIGHT",prevSlot,"LEFT"}, {-2, 0, 0, 16}, "^7Passive tree:") self.sockets = { } local socketOrder = { } @@ -230,12 +234,12 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return a.id < b.id end) for _, node in ipairs(socketOrder) do - local socketControl = new("ItemSlotControl", {"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, "Jewel "..node.id, "Socket", node.id) + local socketControl = new("ItemSlotControl"):ItemSlotControl({"TOPLEFT",prevSlot,"BOTTOMLEFT"}, 0, 2, self, "Jewel "..node.id, "Socket", node.id) self.sockets[node.id] = socketControl addSlot(socketControl) end - self.controls.slotHeader = new("LabelControl", {"BOTTOMLEFT",self.slotAnchor,"TOPLEFT"}, {0, -4, 0, 16}, "^7Equipped items:") - self.controls.weaponSwap1 = new("ButtonControl", {"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {-20, -2, 18, 18}, "I", function() + self.controls.slotHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT",self.slotAnchor,"TOPLEFT"}, {0, -4, 0, 16}, "^7Equipped items:") + self.controls.weaponSwap1 = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {-20, -2, 18, 18}, "I", function() if self.activeItemSet.useSecondWeaponSet then self.activeItemSet.useSecondWeaponSet = false self:AddUndoState() @@ -255,7 +259,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.controls.weaponSwap1.locked = function() return not self.activeItemSet.useSecondWeaponSet end - self.controls.weaponSwap2 = new("ButtonControl", {"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {0, -2, 18, 18}, "II", function() + self.controls.weaponSwap2 = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.slotAnchor,"TOPRIGHT"}, {0, -2, 18, 18}, "II", function() if not self.activeItemSet.useSecondWeaponSet then self.activeItemSet.useSecondWeaponSet = true self:AddUndoState() @@ -275,24 +279,24 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro self.controls.weaponSwap2.locked = function() return self.activeItemSet.useSecondWeaponSet end - self.controls.weaponSwapLabel = new("LabelControl", {"RIGHT",self.controls.weaponSwap1,"LEFT"}, {-4, 0, 0, 14}, "^7Weapon Set:") + self.controls.weaponSwapLabel = new("LabelControl"):LabelControl({"RIGHT",self.controls.weaponSwap1,"LEFT"}, {-4, 0, 0, 14}, "^7Weapon Set:") -- All items list if main.portraitMode then - self.controls.itemList = new("ItemListControl", {"TOPRIGHT",self.lastSlot,"BOTTOMRIGHT"}, {0, 0, 360, 308}, self, true) + self.controls.itemList = new("ItemListControl"):ItemListControl({"TOPRIGHT",self.lastSlot,"BOTTOMRIGHT"}, {0, 0, 360, 308}, self, true) else - self.controls.itemList = new("ItemListControl", {"TOPLEFT",self.controls.setManage,"TOPRIGHT"}, {20, 20, 360, 308}, self, true) + self.controls.itemList = new("ItemListControl"):ItemListControl({"TOPLEFT",self.controls.setManage,"TOPRIGHT"}, {20, 20, 360, 308}, self, true) end -- Database selector - self.controls.selectDBLabel = new("LabelControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 14, 0, 16}, "^7Import from:") + self.controls.selectDBLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 14, 0, 16}, "^7Import from:") self.controls.selectDBLabel.shown = function() return self.height < 980 end - self.controls.selectDB = new("DropDownControl", {"LEFT",self.controls.selectDBLabel,"RIGHT"}, {4, 0, 150, 18}, { "Uniques", "Rare Templates" }) + self.controls.selectDB = new("DropDownControl"):DropDownControl({"LEFT",self.controls.selectDBLabel,"RIGHT"}, {4, 0, 150, 18}, { "Uniques", "Rare Templates" }) -- Unique database - self.controls.uniqueDB = new("ItemDBControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(244, self.maxY - select(2, c:GetPos())) end}, self, main.uniqueDB, "UNIQUE") + self.controls.uniqueDB = new("ItemDBControl"):ItemDBControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(244, self.maxY - select(2, c:GetPos())) end}, self, main.uniqueDB, "UNIQUE") self.controls.uniqueDB.y = function() return self.controls.selectDBLabel:IsShown() and 118 or 96 end @@ -301,7 +305,7 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro end -- Rare template database - self.controls.rareDB = new("ItemDBControl", {"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(260, self.maxY - select(2, c:GetPos())) end}, self, main.rareDB, "RARE") + self.controls.rareDB = new("ItemDBControl"):ItemDBControl({"TOPLEFT",self.controls.itemList,"BOTTOMLEFT"}, {0, 76, 360, function(c) return m_min(260, self.maxY - select(2, c:GetPos())) end}, self, main.rareDB, "RARE") self.controls.rareDB.y = function() return self.controls.selectDBLabel:IsShown() and 78 or 396 end @@ -309,16 +313,16 @@ local ItemsTabClass = newClass("ItemsTab", "UndoHandler", "ControlHost", "Contro return not self.controls.selectDBLabel:IsShown() or self.controls.selectDB.selIndex == 2 end -- Create/import item - self.controls.craftDisplayItem = new("ButtonControl", {"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 120, 20}, "Craft item...", function() + self.controls.craftDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 120, 20}, "Craft item...", function() self:CraftItem() end) self.controls.craftDisplayItem.shown = function() return self.displayItem == nil end - self.controls.newDisplayItem = new("ButtonControl", {"TOPLEFT",self.controls.craftDisplayItem,"TOPRIGHT"}, {8, 0, 120, 20}, "Create custom...", function() + self.controls.newDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.craftDisplayItem,"TOPRIGHT"}, {8, 0, 120, 20}, "Create custom...", function() self:EditDisplayItemText() end) - self.controls.displayItemTip = new("LabelControl", {"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, + self.controls.displayItemTip = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.craftDisplayItem,"BOTTOMLEFT"}, {0, 8, 100, 16}, [[^7Double-click an item from one of the lists, or copy and paste an item from in game (hover over the item and Ctrl+C) to view or edit @@ -331,31 +335,31 @@ drag it onto the slot. This will also add it to your build if it's from the unique/template list. If there's 2 slots an item can go in, holding Shift will put it in the second.]]) - self.controls.sharedItemList = new("SharedItemListControl", {"TOPLEFT",self.controls.craftDisplayItem, "BOTTOMLEFT"}, {0, 232, 340, 308}, self, true) + self.controls.sharedItemList = new("SharedItemListControl"):SharedItemListControl({"TOPLEFT",self.controls.craftDisplayItem, "BOTTOMLEFT"}, {0, 232, 340, 308}, self, true) -- Display item - self.displayItemTooltip = new("Tooltip") + self.displayItemTooltip = new("Tooltip"):Tooltip() self.displayItemTooltip.maxWidth = 458 - self.anchorDisplayItem = new("Control", {"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 0, 0}) + self.anchorDisplayItem = new("Control"):Control({"TOPLEFT",main.portraitMode and self.controls.setManage or self.controls.itemList,"TOPRIGHT"}, {20, main.portraitMode and 0 or -20, 0, 0}) self.anchorDisplayItem.shown = function() return self.displayItem ~= nil end - self.controls.addDisplayItem = new("ButtonControl", {"TOPLEFT",self.anchorDisplayItem,"TOPLEFT"}, {0, 0, 100, 20}, "", function() + self.controls.addDisplayItem = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorDisplayItem,"TOPLEFT"}, {0, 0, 100, 20}, "", function() self:AddDisplayItem() end) self.controls.addDisplayItem.label = function() return self.items[self.displayItem.id] and "Save" or "Add to build" end - self.controls.editDisplayItem = new("ButtonControl", {"LEFT",self.controls.addDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Edit...", function() + self.controls.editDisplayItem = new("ButtonControl"):ButtonControl({"LEFT",self.controls.addDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Edit...", function() self:EditDisplayItemText() end) - self.controls.removeDisplayItem = new("ButtonControl", {"LEFT",self.controls.editDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() + self.controls.removeDisplayItem = new("ButtonControl"):ButtonControl({"LEFT",self.controls.editDisplayItem,"RIGHT"}, {8, 0, 60, 20}, "Cancel", function() self:SetDisplayItem() end) -- Section: Variant(s) - self.controls.displayItemSectionVariant = new("Control", {"TOPLEFT",self.controls.addDisplayItem,"BOTTOMLEFT"}, {0, 8, 0, function() + self.controls.displayItemSectionVariant = new("Control"):Control({"TOPLEFT",self.controls.addDisplayItem,"BOTTOMLEFT"}, {0, 8, 0, function() if not self.controls.displayItemVariant:IsShown() then return 0 end @@ -366,7 +370,7 @@ holding Shift will put it in the second.]]) (self.displayItem.hasAltVariant4 and 24 or 0) + (self.displayItem.hasAltVariant5 and 24 or 0)) end}) - self.controls.displayItemVariant = new("DropDownControl", {"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) + self.controls.displayItemVariant = new("DropDownControl"):DropDownControl({"TOPLEFT", self.controls.displayItemSectionVariant,"TOPLEFT"}, {0, 0, 300, 20}, nil, function(index, value) self.displayItem.variant = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -376,7 +380,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemVariant.shown = function() return self.displayItem.variantList and #self.displayItem.variantList > 1 end - self.controls.displayItemAltVariant = new("DropDownControl", {"TOPLEFT",self.controls.displayItemVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self.controls.displayItemAltVariant = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) self.displayItem.variantAlt = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -386,7 +390,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAltVariant.shown = function() return self.displayItem.hasAltVariant end - self.controls.displayItemAltVariant2 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self.controls.displayItemAltVariant2 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) self.displayItem.variantAlt2 = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -396,7 +400,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAltVariant2.shown = function() return self.displayItem.hasAltVariant2 end - self.controls.displayItemAltVariant3 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant2,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self.controls.displayItemAltVariant3 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant2,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) self.displayItem.variantAlt3 = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -406,7 +410,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAltVariant3.shown = function() return self.displayItem.hasAltVariant3 end - self.controls.displayItemAltVariant4 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant3,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self.controls.displayItemAltVariant4 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant3,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) self.displayItem.variantAlt4 = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -416,7 +420,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemAltVariant4.shown = function() return self.displayItem.hasAltVariant4 end - self.controls.displayItemAltVariant5 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemAltVariant4,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) + self.controls.displayItemAltVariant5 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemAltVariant4,"BOTTOMLEFT"}, {0, 4, 300, 20}, nil, function(index, value) self.displayItem.variantAlt5 = index self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -428,11 +432,11 @@ holding Shift will put it in the second.]]) end -- Section: Sockets and Links - self.controls.displayItemSectionSockets = new("Control", {"TOPLEFT",self.controls.displayItemSectionVariant,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionSockets = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionVariant,"BOTTOMLEFT"}, {0, 0, 0, function() return self.displayItem and self.displayItem.selectableSocketCount > 0 and 28 or 0 end}) for i = 1, 6 do - local drop = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {(i-1) * 64, 0, 36, 20}, socketDropList, function(index, value) + local drop = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {(i-1) * 64, 0, 36, 20}, socketDropList, function(index, value) self.displayItem.sockets[i].color = value.color self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -442,7 +446,7 @@ holding Shift will put it in the second.]]) end self.controls["displayItemSocket"..i] = drop if i < 6 then - local link = new("CheckBoxControl", {"LEFT",drop,"RIGHT"}, {4, 0, 20}, nil, function(state) + local link = new("CheckBoxControl"):CheckBoxControl({"LEFT",drop,"RIGHT"}, {4, 0, 20}, nil, function(state) if state and self.displayItem.sockets[i].group ~= self.displayItem.sockets[i+1].group then for s = i + 1, #self.displayItem.sockets do self.displayItem.sockets[s].group = self.displayItem.sockets[s].group - 1 @@ -461,7 +465,7 @@ holding Shift will put it in the second.]]) self.controls["displayItemLink"..i] = link end end - self.controls.displayItemAddSocket = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {function() return (#self.displayItem.sockets - self.displayItem.abyssalSocketCount) * 64 - 12 end, 0, 20, 20}, "+", function() + self.controls.displayItemAddSocket = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionSockets,"TOPLEFT"}, {function() return (#self.displayItem.sockets - self.displayItem.abyssalSocketCount) * 64 - 12 end, 0, 20, 20}, "+", function() local insertIndex = #self.displayItem.sockets - self.displayItem.abyssalSocketCount + 1 t_insert(self.displayItem.sockets, insertIndex, { color = self.displayItem.defaultSocketColor, @@ -479,28 +483,28 @@ holding Shift will put it in the second.]]) end -- Section: Enchant / Anoint / Corrupt - self.controls.displayItemSectionEnchant = new("Control", {"TOPLEFT",self.controls.displayItemSectionSockets,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionEnchant = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionSockets,"BOTTOMLEFT"}, {0, 0, 0, function() return (self.controls.displayItemEnchant:IsShown() or self.controls.displayItemEnchant2:IsShown() or self.controls.displayItemAnoint:IsShown() or self.controls.displayItemAnoint2:IsShown() or self.controls.displayItemCorrupt:IsShown() ) and 28 or 0 end}) - self.controls.displayItemEnchant = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionEnchant,"TOPLEFT"}, {0, 0, 160, 20}, "Apply Enchantment...", function() + self.controls.displayItemEnchant = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionEnchant,"TOPLEFT"}, {0, 0, 160, 20}, "Apply Enchantment...", function() self:EnchantDisplayItem(1) end) self.controls.displayItemEnchant.shown = function() return self.displayItem and self.displayItem.enchantments end - self.controls.displayItemEnchant2 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemEnchant,"TOPRIGHT",true}, {8, 0, 160, 20}, "Apply Enchantment 2...", function() + self.controls.displayItemEnchant2 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemEnchant,"TOPRIGHT",true}, {8, 0, 160, 20}, "Apply Enchantment 2...", function() self:EnchantDisplayItem(2) end) self.controls.displayItemEnchant2.shown = function() return self.displayItem and self.displayItem.enchantments and self.displayItem.canHaveTwoEnchants and #self.displayItem.enchantModLines > 0 end - self.controls.displayItemAnoint = new("ButtonControl", {"TOPLEFT",self.controls.displayItemEnchant2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint...", function() + self.controls.displayItemAnoint = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemEnchant2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint...", function() self:AnointDisplayItem(1) end) self.controls.displayItemAnoint.shown = function() return self.displayItem and isAnointable(self.displayItem) end - self.controls.displayItemAnoint2 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 2...", function() + self.controls.displayItemAnoint2 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 2...", function() self:AnointDisplayItem(2) end) self.controls.displayItemAnoint2.shown = function() @@ -509,7 +513,7 @@ holding Shift will put it in the second.]]) self.displayItem.canHaveTwoEnchants and #self.displayItem.enchantModLines > 0 end - self.controls.displayItemAnoint3 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 3...", function() + self.controls.displayItemAnoint3 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint2,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 3...", function() self:AnointDisplayItem(3) end) self.controls.displayItemAnoint3.shown = function() @@ -518,7 +522,7 @@ holding Shift will put it in the second.]]) self.displayItem.canHaveThreeEnchants and #self.displayItem.enchantModLines > 1 end - self.controls.displayItemAnoint4 = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint3,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 4...", function() + self.controls.displayItemAnoint4 = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint3,"TOPRIGHT",true}, {8, 0, 100, 20}, "Anoint 4...", function() self:AnointDisplayItem(4) end) self.controls.displayItemAnoint4.shown = function() @@ -527,21 +531,21 @@ holding Shift will put it in the second.]]) self.displayItem.canHaveFourEnchants and #self.displayItem.enchantModLines > 2 end - self.controls.displayItemCorrupt = new("ButtonControl", {"TOPLEFT",self.controls.displayItemAnoint4,"TOPRIGHT",true}, {8, 10, 100, 20}, "Corrupt...", function() + self.controls.displayItemCorrupt = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemAnoint4,"TOPRIGHT",true}, {8, 10, 100, 20}, "Corrupt...", function() self:CorruptDisplayItem("Corrupted") end) self.controls.displayItemCorrupt.shown = function() return self.displayItem and self.displayItem.corruptible end --[[ - self.controls.displayItemScourge = new("ButtonControl", {"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 100, 20}, "Scourge...", function() + self.controls.displayItemScourge = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 100, 20}, "Scourge...", function() self:CorruptDisplayItem("Scourge") end) self.controls.displayItemScourge.shown = function() return self.displayItem and self.displayItem.corruptible end --]] - self.controls.displayItemAddImplicit = new("ButtonControl", {"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 120, 20}, "Add Implicit...", function() + self.controls.displayItemAddImplicit = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemCorrupt,"TOPRIGHT",true}, {8, 0, 120, 20}, "Add Implicit...", function() self:AddImplicitToDisplayItem() end) self.controls.displayItemAddImplicit.shown = function() @@ -580,17 +584,17 @@ holding Shift will put it in the second.]]) self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() end - self.controls.displayItemSectionInfluence = new("Control", {"TOPLEFT",self.controls.displayItemSectionEnchant,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionInfluence = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionEnchant,"BOTTOMLEFT"}, {0, 0, 0, function() return self.displayItem and self.displayItem.canBeInfluenced and 28 or 0 end}) - self.controls.displayItemInfluence = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionInfluence,"TOPRIGHT"}, {0, 0, 100, 20}, influenceDisplayList, function(index, value) + self.controls.displayItemInfluence = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionInfluence,"TOPRIGHT"}, {0, 0, 100, 20}, influenceDisplayList, function(index, value) local otherIndex = self.controls.displayItemInfluence2.selIndex setDisplayItemInfluence({ index - 1, otherIndex - 1 }) end) self.controls.displayItemInfluence.shown = function() return self.displayItem and self.displayItem.canBeInfluenced end - self.controls.displayItemInfluence2 = new("DropDownControl", {"TOPLEFT",self.controls.displayItemInfluence,"TOPRIGHT",true}, {8, 0, 100, 20}, influenceDisplayList, function(index, value) + self.controls.displayItemInfluence2 = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemInfluence,"TOPRIGHT",true}, {8, 0, 100, 20}, influenceDisplayList, function(index, value) local otherIndex = self.controls.displayItemInfluence.selIndex setDisplayItemInfluence({ index - 1, otherIndex - 1 }) end) @@ -599,15 +603,15 @@ holding Shift will put it in the second.]]) end -- Section: Item Quality - self.controls.displayItemSectionQuality = new("Control", {"TOPLEFT",self.controls.displayItemSectionInfluence,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionQuality = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionInfluence,"BOTTOMLEFT"}, {0, 0, 0, function() return (self.controls.displayItemQuality:IsShown() and self.controls.displayItemQualityEdit:IsShown()) and 28 or 0 end}) - self.controls.displayItemQuality = new("LabelControl", {"TOPLEFT",self.controls.displayItemSectionQuality,"TOPRIGHT"}, {-4, 0, 0, 16}, "^7Quality:") + self.controls.displayItemQuality = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.displayItemSectionQuality,"TOPRIGHT"}, {-4, 0, 0, 16}, "^7Quality:") self.controls.displayItemQuality.shown = function() return self.displayItem and self.displayItem.quality and (self.displayItem.base.type ~= "Amulet" or self.displayItem.base.type ~= "Belt" or self.displayItem.base.type ~= "Jewel" or self.displayItem.base.type ~= "Quiver" or self.displayItem.base.type ~= "Ring" or self.displayItem.type ~= "Graft") end - self.controls.displayItemQualityEdit = new("EditControl", {"LEFT",self.controls.displayItemQuality,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + self.controls.displayItemQualityEdit = new("EditControl"):EditControl({"LEFT",self.controls.displayItemQuality,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) self.displayItem.quality = tonumber(buf) self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -617,10 +621,10 @@ holding Shift will put it in the second.]]) end -- Section: Catalysts - self.controls.displayItemSectionCatalyst = new("Control", {"TOPLEFT",self.controls.displayItemSectionQuality,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionCatalyst = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionQuality,"BOTTOMLEFT"}, {0, 0, 0, function() return (self.controls.displayItemCatalyst:IsShown() or self.controls.displayItemCatalystQualityEdit:IsShown()) and 28 or 0 end}) - self.controls.displayItemCatalyst = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionCatalyst,"TOPRIGHT"}, {0, 0, 250, 20}, + self.controls.displayItemCatalyst = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionCatalyst,"TOPRIGHT"}, {0, 0, 250, 20}, {"Catalyst","Abrasive (Attack)","Accelerating (Speed)","Dextral (Suffix)","Fertile (Life & Mana)","Imbued (Caster)","Intrinsic (Attribute)","Noxious (Physical & Chaos Damage)", "Prismatic (Resistance)","Sinistral (Prefix)","Tempering (Defense)","Turbulent (Elemental)","Unstable (Critical)"}, function(index, value) @@ -642,7 +646,7 @@ holding Shift will put it in the second.]]) self.controls.displayItemCatalyst.shown = function() return self.displayItem and (self.displayItem.crafted or self.displayItem.hasModTags) and (self.displayItem.base.type == "Amulet" or self.displayItem.base.type == "Ring" or self.displayItem.base.type == "Belt") end - self.controls.displayItemCatalystQualityEdit = new("EditControl", {"LEFT",self.controls.displayItemCatalyst,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + self.controls.displayItemCatalystQualityEdit = new("EditControl"):EditControl({"LEFT",self.controls.displayItemCatalyst,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) self.displayItem.catalystQuality = tonumber(buf) if self.displayItem.crafted then for i = 1, self.displayItem.affixLimit do @@ -659,10 +663,10 @@ holding Shift will put it in the second.]]) end -- Section: Cluster Jewel - self.controls.displayItemSectionClusterJewel = new("Control", {"TOPLEFT",self.controls.displayItemSectionCatalyst,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionClusterJewel = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionCatalyst,"BOTTOMLEFT"}, {0, 0, 0, function() return self.controls.displayItemClusterJewelSkill:IsShown() and 52 or 0 end}) - self.controls.displayItemClusterJewelSkill = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionClusterJewel,"TOPLEFT"}, {0, 0, 300, 20}, { }, function(index, value) + self.controls.displayItemClusterJewelSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionClusterJewel,"TOPLEFT"}, {0, 0, 300, 20}, { }, function(index, value) self.displayItem.clusterJewelSkill = value.skillId self:CraftClusterJewel() end) { @@ -671,8 +675,8 @@ holding Shift will put it in the second.]]) end } - self.controls.displayItemClusterJewelNodeCountLabel = new("LabelControl", {"TOPLEFT",self.controls.displayItemClusterJewelSkill,"BOTTOMLEFT"}, {0, 7, 0, 14}, "^7Added Passives:") - self.controls.displayItemClusterJewelNodeCount = new("SliderControl", {"LEFT",self.controls.displayItemClusterJewelNodeCountLabel,"RIGHT"}, {2, 0, 150, 20}, function(val) + self.controls.displayItemClusterJewelNodeCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.displayItemClusterJewelSkill,"BOTTOMLEFT"}, {0, 7, 0, 14}, "^7Added Passives:") + self.controls.displayItemClusterJewelNodeCount = new("SliderControl"):SliderControl({"LEFT",self.controls.displayItemClusterJewelNodeCountLabel,"RIGHT"}, {2, 0, 150, 20}, function(val) local divVal = self.controls.displayItemClusterJewelNodeCount:GetDivVal() local clusterJewel = self.displayItem.clusterJewel self.displayItem.clusterJewelNodeCount = round(val * (clusterJewel.maxNodes - clusterJewel.minNodes) + clusterJewel.minNodes) @@ -680,7 +684,7 @@ holding Shift will put it in the second.]]) end) -- Section: Affix Selection - self.controls.displayItemSectionAffix = new("Control", {"TOPLEFT",self.controls.displayItemSectionClusterJewel,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionAffix = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionClusterJewel,"BOTTOMLEFT"}, {0, 0, 0, function() if not self.displayItem or not self.displayItem.crafted then return 0 end @@ -738,7 +742,7 @@ holding Shift will put it in the second.]]) end return range end - drop = new("DropDownControl", {"TOPLEFT",prev,"TOPLEFT"}, {i==1 and 40 or 0, 0, 418, 20}, nil, function(index, value) + drop = new("DropDownControl"):DropDownControl({"TOPLEFT",prev,"TOPLEFT"}, {i==1 and 40 or 0, 0, 418, 20}, nil, function(index, value) local affix = { modId = "None" } if value.modId then affix.modId = value.modId @@ -873,7 +877,7 @@ holding Shift will put it in the second.]]) drop.shown = function() return self.displayItem and self.displayItem.crafted and i <= self.displayItem.affixLimit end - slider = new("SliderControl", {"TOPLEFT",drop,"BOTTOMLEFT"}, {0, 2, 300, 16}, function(val) + slider = new("SliderControl"):SliderControl({"TOPLEFT",drop,"BOTTOMLEFT"}, {0, 2, 300, 16}, function(val) local affix = self.displayItem[drop.outputTable][drop.outputIndex] local index, range = slider:GetDivVal() affix.modId = drop.list[drop.selIndex].modList[index] @@ -913,21 +917,21 @@ holding Shift will put it in the second.]]) end drop.slider = slider self.controls["displayItemAffix"..i] = drop - self.controls["displayItemAffixLabel"..i] = new("LabelControl", {"RIGHT",drop,"LEFT"}, {-4, 0, 0, 14}, function() + self.controls["displayItemAffixLabel"..i] = new("LabelControl"):LabelControl({"RIGHT",drop,"LEFT"}, {-4, 0, 0, 14}, function() return drop.outputTable == "prefixes" and "^7Prefix:" or "^7Suffix:" end) self.controls["displayItemAffixRange"..i] = slider - self.controls["displayItemAffixRangeLabel"..i] = new("LabelControl", {"RIGHT",slider,"LEFT"}, {-4, 0, 0, 14}, function() + self.controls["displayItemAffixRangeLabel"..i] = new("LabelControl"):LabelControl({"RIGHT",slider,"LEFT"}, {-4, 0, 0, 14}, function() return drop.selIndex > 1 and "^7Roll:" or "^x7F7F7FRoll:" end) end -- Section: Custom modifiers -- if either Custom or Crucible mod buttons are shown, create the control for the list of mods - self.controls.displayItemSectionCustom = new("Control", {"TOPLEFT",self.controls.displayItemSectionAffix,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionCustom = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionAffix,"BOTTOMLEFT"}, {0, 0, 0, function() return (self.controls.displayItemAddCustom:IsShown() or self.controls.displayItemAddCrucible:IsShown()) and 28 + self.displayItem.customCount * 22 or 0 end}) - self.controls.displayItemAddCustom = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, 0, 120, 20}, "Add modifier...", function() + self.controls.displayItemAddCustom = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, 0, 120, 20}, "Add modifier...", function() self:AddCustomModifierToDisplayItem() end) self.controls.displayItemAddCustom.shown = function() @@ -936,7 +940,7 @@ holding Shift will put it in the second.]]) -- Section: Crucible modifiers -- if the Add modifier button is not shown, take its place, otherwise move it to the right of it - self.controls.displayItemAddCrucible = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {function() + self.controls.displayItemAddCrucible = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {function() return (self.controls.displayItemAddCustom:IsShown() and 128) or 0 end, 0, 150, 20}, "Add Crucible mod...", function() self:AddCrucibleModifierToDisplayItem() @@ -946,7 +950,7 @@ holding Shift will put it in the second.]]) end -- Section: Modifier Range - self.controls.displayItemSectionRange = new("Control", {"TOPLEFT",self.controls.displayItemSectionCustom,"BOTTOMLEFT"}, {0, 0, 0, function() + self.controls.displayItemSectionRange = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionCustom,"BOTTOMLEFT"}, {0, 0, 0, function() if not self.displayItem or not self.displayItem.rangeLineList[1] then return 0 end @@ -957,13 +961,13 @@ holding Shift will put it in the second.]]) return 28 end end}) - self.controls.displayItemRangeLine = new("DropDownControl", {"TOPLEFT",self.controls.displayItemSectionRange,"TOPLEFT"}, {0, 0, 350, 18}, nil, function(index, value) + self.controls.displayItemRangeLine = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.displayItemSectionRange,"TOPLEFT"}, {0, 0, 350, 18}, nil, function(index, value) self.controls.displayItemRangeSlider.val = self.displayItem.rangeLineList[index].range end) self.controls.displayItemRangeLine.shown = function() return self.displayItem and self.displayItem.rangeLineList[1] ~= nil and not (main.showAllItemAffixes and self.displayItem.rarity == "UNIQUE") end - self.controls.displayItemRangeSlider = new("SliderControl", {"LEFT",self.controls.displayItemRangeLine,"RIGHT"}, {8, 0, 100, 18}, function(val) + self.controls.displayItemRangeSlider = new("SliderControl"):SliderControl({"LEFT",self.controls.displayItemRangeLine,"RIGHT"}, {8, 0, 100, 18}, function(val) self.displayItem.rangeLineList[self.controls.displayItemRangeLine.selIndex].range = val self.displayItem:BuildAndParseRaw() self:UpdateDisplayItemTooltip() @@ -973,7 +977,7 @@ holding Shift will put it in the second.]]) for i = 1, 20 do local baseControl = i == 1 and self.controls.displayItemSectionRange or self.controls["displayItemStackedRangeSlider"..(i-1)] - self.controls["displayItemStackedRangeSlider"..i] = new("SliderControl", {"TOPLEFT",baseControl,"TOPLEFT"}, {0, function() + self.controls["displayItemStackedRangeSlider"..i] = new("SliderControl"):SliderControl({"TOPLEFT",baseControl,"TOPLEFT"}, {0, function() return i == 1 and 2 or 22 end, 100, 18}, function(val) if self.displayItem and self.displayItem.rangeLineList[i] then @@ -983,7 +987,7 @@ holding Shift will put it in the second.]]) self:UpdateCustomControls() end end) - self.controls["displayItemStackedRangeLine"..i] = new("LabelControl", {"LEFT",self.controls["displayItemStackedRangeSlider"..i],"RIGHT"}, {8, -2, 350, 14}, function() + self.controls["displayItemStackedRangeLine"..i] = new("LabelControl"):LabelControl({"LEFT",self.controls["displayItemStackedRangeSlider"..i],"RIGHT"}, {8, -2, 350, 14}, function() if self.displayItem and self.displayItem.rangeLineList[i] then return "^7" .. self.displayItem.rangeLineList[i].line end @@ -999,11 +1003,11 @@ holding Shift will put it in the second.]]) end -- Tooltip anchor - self.controls.displayItemTooltipAnchor = new("Control", {"TOPLEFT",self.controls.displayItemSectionRange,"BOTTOMLEFT"}) + self.controls.displayItemTooltipAnchor = new("Control"):Control({"TOPLEFT",self.controls.displayItemSectionRange,"BOTTOMLEFT"}) -- Scroll bars - self.controls.scrollBarH = new("ScrollBarControl", nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) - self.controls.scrollBarV = new("ScrollBarControl", nil, {0, 0, 18, 0}, 100, "VERTICAL", true) + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 18, 0}, 100, "VERTICAL", true) -- Initialise drag target lists t_insert(self.controls.itemList.dragTargetList, self.controls.sharedItemList) @@ -1031,7 +1035,8 @@ holding Shift will put it in the second.]]) self:PopulateSlots() self.lastSlot = self.slots[baseSlots[#baseSlots]] -end) + return self +end function ItemsTabClass:Load(xml, dbFileName) self.activeItemSetId = 0 @@ -1040,7 +1045,7 @@ function ItemsTabClass:Load(xml, dbFileName) self.tradeQuery.statSortSelectionList = { } for _, node in ipairs(xml) do if node.elem == "Item" then - local item = new("Item", "") + local item = new("Item"):Item("") item.id = tonumber(node.attrib.id) item.variant = tonumber(node.attrib.variant) if node.attrib.variantAlt then @@ -1421,7 +1426,7 @@ function ItemsTabClass:EquipItemInSet(item, itemSetId) slotName = slotName .. " Swap" end if not item.id or not self.items[item.id] then - item = new("Item", item.raw) + item = new("Item"):Item(item.raw) self:AddItem(item, true) end local altSlot = slotName:gsub("1","2") @@ -1660,7 +1665,7 @@ end -- Attempt to create a new item from the given item raw text and sets it as the new display item function ItemsTabClass:CreateDisplayItemFromRaw(itemRaw, normalise) - local newItem = new("Item", itemRaw) + local newItem = new("Item"):Item(itemRaw) if newItem.base then self:CopyAnointsAndEldritchImplicits(newItem, main.migrateEldritchImplicits, false) if normalise then @@ -1963,9 +1968,9 @@ function ItemsTabClass:UpdateCustomControls() local line = itemLib.formatModLine(modLine) if line then if not self.controls["displayItemCustomModifierRemove"..i] then - self.controls["displayItemCustomModifierRemove"..i] = new("ButtonControl", {"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, i * 22 + 4, 70, 20}, "^7Remove") - self.controls["displayItemCustomModifier"..i] = new("LabelControl", {"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {65, 0, 0, 16}) - self.controls["displayItemCustomModifierLabel"..i] = new("LabelControl", {"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {5, 0, 0, 16}) + self.controls["displayItemCustomModifierRemove"..i] = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.displayItemSectionCustom,"TOPLEFT"}, {0, i * 22 + 4, 70, 20}, "^7Remove") + self.controls["displayItemCustomModifier"..i] = new("LabelControl"):LabelControl({"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {65, 0, 0, 16}) + self.controls["displayItemCustomModifierLabel"..i] = new("LabelControl"):LabelControl({"LEFT",self.controls["displayItemCustomModifierRemove"..i],"RIGHT"}, {5, 0, 0, 16}) end self.controls["displayItemCustomModifierRemove"..i].shown = true local label = itemLib.formatModLine(modLine) @@ -2024,7 +2029,7 @@ end function ItemsTabClass:AddModComparisonTooltip(tooltip, mod) local slotName = self.displayItem:GetPrimarySlot() - local newItem = new("Item", self.displayItem:BuildRaw()) + local newItem = new("Item"):Item(self.displayItem:BuildRaw()) for _, subMod in ipairs(mod) do t_insert(newItem.explicitModLines, { line = checkLineForAllocates(subMod, self.build.spec.nodes), modTags = mod.modTags, [mod.type] = true }) @@ -2108,11 +2113,11 @@ end -- Opens the item set manager function ItemsTabClass:OpenItemSetManagePopup() local controls = { } - controls.setList = new("ItemSetListControl", nil, {-155, 50, 300, 200}, self) - controls.sharedList = new("SharedItemSetListControl", nil, {155, 50, 300, 200}, self) + controls.setList = new("ItemSetListControl"):ItemSetListControl(nil, {-155, 50, 300, 200}, self) + controls.sharedList = new("SharedItemSetListControl"):SharedItemSetListControl(nil, {155, 50, 300, 200}, self) controls.setList.dragTargetList = { controls.sharedList } controls.sharedList.dragTargetList = { controls.setList } - controls.close = new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end) main:OpenPopup(630, 290, "Manage Item Sets", controls) @@ -2122,7 +2127,7 @@ end function ItemsTabClass:CraftItem() local controls = { } local function makeItem(base) - local item = new("Item") + local item = new("Item"):Item() item.name = base.name item.base = base.base item.baseName = base.name @@ -2166,21 +2171,21 @@ function ItemsTabClass:CraftItem() item:BuildAndParseRaw() return item end - controls.rarityLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 20, 0, 16}, "Rarity:") - controls.rarity = new("DropDownControl", nil, {-80, 20, 100, 18}, rarityDropList) + controls.rarityLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 20, 0, 16}, "Rarity:") + controls.rarity = new("DropDownControl"):DropDownControl(nil, {-80, 20, 100, 18}, rarityDropList) controls.rarity.selIndex = self.lastCraftRaritySel or 3 - controls.title = new("EditControl", nil, {70, 20, 190, 18}, "", "Name") + controls.title = new("EditControl"):EditControl(nil, {70, 20, 190, 18}, "", "Name") controls.title.shown = function() return controls.rarity.selIndex >= 3 end - controls.typeLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 45, 0, 16}, "Type:") - controls.type = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {55, 45, 295, 18}, self.build.data.itemBaseTypeList, function(index, value) + controls.typeLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 45, 0, 16}, "Type:") + controls.type = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {55, 45, 295, 18}, self.build.data.itemBaseTypeList, function(index, value) controls.base.list = self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[index]] controls.base.selIndex = 1 end) controls.type.selIndex = self.lastCraftTypeSel or 1 - controls.baseLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {50, 70, 0, 16}, "Base:") - controls.base = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {55, 70, 200, 18}, self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[controls.type.selIndex]]) + controls.baseLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {50, 70, 0, 16}, "Base:") + controls.base = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {55, 70, 200, 18}, self.build.data.itemBaseLists[self.build.data.itemBaseTypeList[controls.type.selIndex]]) controls.base.selIndex = self.lastCraftBaseSel or 1 controls.base.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() @@ -2188,7 +2193,7 @@ function ItemsTabClass:CraftItem() self:AddItemTooltip(tooltip, makeItem(value), nil, true) end end - controls.save = new("ButtonControl", nil, {-45, 100, 80, 20}, "Create", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 100, 80, 20}, "Create", function() main:ClosePopup() local item = makeItem(controls.base.list[controls.base.selIndex]) self:SetDisplayItem(item) @@ -2199,7 +2204,7 @@ function ItemsTabClass:CraftItem() self.lastCraftTypeSel = controls.type.selIndex self.lastCraftBaseSel = controls.base.selIndex end) - controls.cancel = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 100, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 130, "Craft Item", controls) @@ -2216,8 +2221,8 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) return "Rarity: "..controls.rarity.list[controls.rarity.selIndex].rarity.."\n"..controls.edit.buf end end - controls.rarity = new("DropDownControl", nil, {-190, 10, 100, 18}, rarityDropList) - controls.edit = new("EditControl", nil, {0, 40, 480, 420}, "", nil, "^%C\t\n", nil, nil, 14) + controls.rarity = new("DropDownControl"):DropDownControl(nil, {-190, 10, 100, 18}, rarityDropList) + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 480, 420}, "", nil, "^%C\t\n", nil, nil, 14) if self.displayItem then controls.edit:SetText(self.displayItem:BuildRaw():gsub("Rarity: %w+\n","")) controls.rarity:SelByValue(self.displayItem.rarity, "rarity") @@ -2226,7 +2231,7 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) end controls.edit.font = "FIXED" controls.edit.pasteFilter = sanitiseText - controls.save = new("ButtonControl", nil, {-45, 470, 80, 20}, self.displayItem and "Save" or "Create", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 470, 80, 20}, self.displayItem and "Save" or "Create", function() local id = self.displayItem and self.displayItem.id self:CreateDisplayItemFromRaw(buildRaw(), not self.displayItem) self.displayItem.id = id @@ -2236,12 +2241,12 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) main:ClosePopup() end, nil, true) controls.save.enabled = function() - local item = new("Item", buildRaw()) + local item = new("Item"):Item(buildRaw()) return item.base ~= nil end controls.save.tooltipFunc = function(tooltip) tooltip:Clear() - local item = new("Item", buildRaw()) + local item = new("Item"):Item(buildRaw()) if item.base then self:AddItemTooltip(tooltip, item, nil, true) else @@ -2254,7 +2259,7 @@ function ItemsTabClass:EditDisplayItemText(alsoAddItem) tooltip:AddLine(14, "Scholar's Platinum Kris of Joy") end end - controls.cancel = new("ButtonControl", nil, {45, 470, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 470, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(500, 500, self.displayItem and "Edit Item Text" or "Create Custom Item from Text", controls, nil, "edit") @@ -2330,7 +2335,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) buildEnchantmentSourceList() buildEnchantmentList() local function enchantItem(idx, remove) - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) local index = idx or controls.enchantment.selIndex item.id = self.displayItem.id local entry = enchantmentList[index] @@ -2359,7 +2364,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) if entry.sortValues[stat] ~= nil then return entry.sortValues[stat] end - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id local line = entry.line local first, second = line:match("([^/]+)/([^/]+)") @@ -2419,8 +2424,8 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) end end if haveSkills then - controls.skillLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Skill:") - controls.skill = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 180, 18}, skillList, function(index, value) + controls.skillLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Skill:") + controls.skill = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 180, 18}, skillList, function(index, value) buildEnchantmentSourceList() buildEnchantmentList() controls.enchantment:SetSel(1) @@ -2428,7 +2433,7 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) applySort(controls.sort.list[controls.sort.selIndex].stat, true) end end) - controls.allSkills = new("CheckBoxControl", {"TOPLEFT",nil,"TOPLEFT"}, {350, 20, 18}, "All skills:", function(state) + controls.allSkills = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",nil,"TOPLEFT"}, {350, 20, 18}, "All skills:", function(state) buildSkillList(not state) controls.skill:SetSel(1) buildEnchantmentList() @@ -2443,33 +2448,33 @@ function ItemsTabClass:EnchantDisplayItem(enchantSlot) controls.allSkills.enabled = false end end - controls.enchantmentSourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Source:") - controls.enchantmentSource = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 180, 18}, enchantmentSourceList, function(index, value) + controls.enchantmentSourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Source:") + controls.enchantmentSource = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 180, 18}, enchantmentSourceList, function(index, value) buildEnchantmentList() controls.enchantment:SetSel(m_min(controls.enchantment.selIndex, #enchantmentList)) if controls.sort then applySort(controls.sort.list[controls.sort.selIndex].stat, true) end end) - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 45, 0, 16}, "^7Sort by:") - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 45, 240, 18}, sortList, function(index, value) + controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 45, 0, 16}, "^7Sort by:") + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 45, 240, 18}, sortList, function(index, value) applySort(value.stat, true) end) - controls.enchantmentLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Enchantment:") - controls.enchantment = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 495, 18}, enchantmentList) + controls.enchantmentLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Enchantment:") + controls.enchantment = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 495, 18}, enchantmentList) controls.enchantment.tooltipFunc = function(tooltip, mode, index) tooltip:Clear() self:AddItemTooltip(tooltip, enchantItem(index), nil, true) end - controls.save = new("ButtonControl", nil, {-88, 100, 80, 20}, "Enchant", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-88, 100, 80, 20}, "Enchant", function() self:SetDisplayItem(enchantItem()) main:ClosePopup() end) - controls.remove = new("ButtonControl", nil, {0, 100, 80, 20}, "Remove", function() + controls.remove = new("ButtonControl"):ButtonControl(nil, {0, 100, 80, 20}, "Remove", function() self:SetDisplayItem(enchantItem(nil, true)) main:ClosePopup() end) - controls.close = new("ButtonControl", nil, {88, 100, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {88, 100, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(605, 130, "Enchant Item", controls) @@ -2513,7 +2518,7 @@ end ---@return table @The new item function ItemsTabClass:anointItem(node) self.anointEnchantSlot = self.anointEnchantSlot or 1 - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id if #item.enchantModLines >= self.anointEnchantSlot then t_remove(item.enchantModLines, self.anointEnchantSlot) @@ -2585,7 +2590,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) self.anointEnchantSlot = enchantSlot or 1 local controls = { } - controls.notableDB = new("NotableDBControl", {"TOPLEFT",nil,"TOPLEFT"}, {10, 60, 360, 360}, self, self.build.spec.tree.nodes, "ANOINT") + controls.notableDB = new("NotableDBControl"):NotableDBControl({"TOPLEFT",nil,"TOPLEFT"}, {10, 60, 360, 360}, self, self.build.spec.tree.nodes, "ANOINT") local function saveLabel() local node = controls.notableDB.selValue @@ -2606,7 +2611,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) local width = saveLabelWidth() return -(width + 90) / 2 end - controls.save = new("ButtonControl", {"BOTTOMLEFT", nil, "BOTTOM" }, {saveLabelX, -4, saveLabelWidth, 20}, saveLabel, function() + controls.save = new("ButtonControl"):ButtonControl({"BOTTOMLEFT", nil, "BOTTOM" }, {saveLabelX, -4, saveLabelWidth, 20}, saveLabel, function() self:SetDisplayItem(self:anointItem(controls.notableDB.selValue)) main:ClosePopup() end) @@ -2614,7 +2619,7 @@ function ItemsTabClass:AnointDisplayItem(enchantSlot) tooltip:Clear() self:AppendAnointTooltip(tooltip, controls.notableDB.selValue) end - controls.close = new("ButtonControl", {"TOPLEFT", controls.save, "TOPRIGHT" }, {10, 0, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl({"TOPLEFT", controls.save, "TOPRIGHT" }, {10, 0, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(380, 448, "Anoint Item", controls) @@ -2669,7 +2674,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) if entry.sortValues[stat] ~= nil then return entry.sortValues[stat] end - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id item.corrupted = true local mod = entry.mod @@ -2740,7 +2745,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) if controls.implicit4 then controls.implicit4:UpdateSearch() end end local function corruptItem() - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id item.corrupted = true local newImplicit = { } @@ -2766,8 +2771,8 @@ function ItemsTabClass:CorruptDisplayItem(modType) item:BuildAndParseRaw() return item end - controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") - controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) + controls.sourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") + controls.source = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) if value == "Scourge" then currentModType = "ScourgeUpside" buildImplicitList("ScourgeUpside") @@ -2820,12 +2825,12 @@ function ItemsTabClass:CorruptDisplayItem(modType) controls.implicit4:SetSel(1) end) controls.source.enabled = #sourceList > 1 - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) applySort(value.stat) end) - controls.implicitLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {75, 45, 0, 16}, "^7Implicit #1:") - controls.implicit = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {80, 45, 440, 18}, nil, function() + controls.implicitLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {75, 45, 0, 16}, "^7Implicit #1:") + controls.implicit = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {80, 45, 440, 18}, nil, function() buildList(controls.implicit2, controls.implicit, currentModType) end) controls.implicit.tooltipFunc = function(tooltip, mode, index, value) @@ -2839,8 +2844,8 @@ function ItemsTabClass:CorruptDisplayItem(modType) end controls.implicit.shown = not self.displayItem.implicitsCannotBeChanged controls.implicitLabel.shown = not self.displayItem.implicitsCannotBeChanged - controls.implicit2Label = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {75, 65, 0, 16}, "^7Implicit #2:") - controls.implicit2 = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {80, 65, 440, 18}, nil, function() + controls.implicit2Label = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {75, 65, 0, 16}, "^7Implicit #2:") + controls.implicit2 = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {80, 65, 440, 18}, nil, function() buildList(controls.implicit, controls.implicit2, currentModType) end) controls.implicit2.tooltipFunc = function(tooltip, mode, index, value) @@ -2854,8 +2859,8 @@ function ItemsTabClass:CorruptDisplayItem(modType) end controls.implicit2.shown = not self.displayItem.implicitsCannotBeChanged controls.implicit2Label.shown = not self.displayItem.implicitsCannotBeChanged - controls.implicit3Label = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {75, 85, 0, 16}, "^7Implicit #3:") - controls.implicit3 = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {80, 65, 440, 18}, nil, function() + controls.implicit3Label = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {75, 85, 0, 16}, "^7Implicit #3:") + controls.implicit3 = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {80, 65, 440, 18}, nil, function() buildList(controls.implicit4, controls.implicit3, "ScourgeDownside") end) controls.implicit3.tooltipFunc = function(tooltip, mode, index, value) @@ -2869,8 +2874,8 @@ function ItemsTabClass:CorruptDisplayItem(modType) end controls.implicit3Label.shown = false controls.implicit3.shown = false - controls.implicit4Label = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {75, 105, 0, 16}, "^7Implicit #4:") - controls.implicit4 = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {80, 105, 440, 18}, nil, function() + controls.implicit4Label = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {75, 105, 0, 16}, "^7Implicit #4:") + controls.implicit4 = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {80, 105, 440, 18}, nil, function() buildList(controls.implicit3, controls.implicit4, "ScourgeDownside") end) controls.implicit4.tooltipFunc = function(tooltip, mode, index, value) @@ -2884,11 +2889,11 @@ function ItemsTabClass:CorruptDisplayItem(modType) end controls.implicit4Label.shown = false controls.implicit4.shown = false - controls.implicitCannotBeChangedLabel = new("LabelControl", {"TOPLEFT",nil,"TOPLEFT"}, {20, 45, 0, 20}, "^7This Items Implicits Cannot Be Changed") + controls.implicitCannotBeChangedLabel = new("LabelControl"):LabelControl({"TOPLEFT",nil,"TOPLEFT"}, {20, 45, 0, 20}, "^7This Items Implicits Cannot Be Changed") controls.implicitCannotBeChangedLabel.shown = self.displayItem.implicitsCannotBeChanged buildList(controls.implicit, controls.implicit2, currentModType) buildList(controls.implicit2, controls.implicit, currentModType) - controls.save = new("ButtonControl", nil, {-45, 99, 80, 20}, modType, function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 99, 80, 20}, modType, function() self:SetDisplayItem(corruptItem()) main:ClosePopup() end) @@ -2896,7 +2901,7 @@ function ItemsTabClass:CorruptDisplayItem(modType) tooltip:Clear() self:AddItemTooltip(tooltip, corruptItem(), nil, true) end - controls.close = new("ButtonControl", nil, {45, 99, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 99, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(605, 129, modType .. " Item", controls) @@ -2920,7 +2925,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() if listMod.sortValues[stat] ~= nil then return listMod.sortValues[stat] end - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id for _, line in ipairs(listMod.mod) do t_insert(item.explicitModLines, { line = checkLineForAllocates(line, self.build.spec.nodes), modTags = listMod.mod.modTags, [listMod.type] = true }) @@ -3142,7 +3147,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() t_insert(sourceList, { label = "Custom", sourceId = "CUSTOM" }) buildMods(sourceList[1].sourceId) local function addModifier() - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id local sourceId = sourceList[controls.source.selIndex].sourceId if sourceId == "CUSTOM" then @@ -3158,8 +3163,8 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() item:BuildAndParseRaw() return item end - controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") - controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) + controls.sourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") + controls.source = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) buildMods(value.sourceId) controls.modSelect:SetSel(1) if controls.sort then @@ -3167,18 +3172,18 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() end end) controls.source.enabled = #sourceList > 1 - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") + controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") controls.sortLabel.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) applySort(value.stat, true) end) controls.sort.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Modifier:") - controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modList) + controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Modifier:") + controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modList) controls.modSelect.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end @@ -3191,11 +3196,11 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() self:AddModComparisonTooltip(tooltip, value.mod) end end - controls.custom = new("EditControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) + controls.custom = new("EditControl"):EditControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) controls.custom.shown = function() return sourceList[controls.source.selIndex].sourceId == "CUSTOM" end - controls.save = new("ButtonControl", nil, {-45, 75, 80, 20}, "Add", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 75, 80, 20}, "Add", function() self:SetDisplayItem(addModifier()) main:ClosePopup() end) @@ -3203,7 +3208,7 @@ function ItemsTabClass:AddCustomModifierToDisplayItem() tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) end - controls.close = new("ButtonControl", nil, {45, 75, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 75, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(710, 105, "Add Modifier to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") @@ -3280,7 +3285,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() end end local function addModifier() - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id item.crucibleModLines = { } local listMod = { @@ -3307,8 +3312,8 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() buildCrucibleMods() local y = 45 for i = 1,5 do - controls["modSelectNode"..i.."Label"] = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, y, 0, 16}, "^7Node "..i..":") - controls["modSelectNode"..i] = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, y, 555, 18}, modList[i]) + controls["modSelectNode"..i.."Label"] = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, y, 0, 16}, "^7Node "..i..":") + controls["modSelectNode"..i] = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, y, 555, 18}, modList[i]) controls["modSelectNode"..i].tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() if mode ~= "OUT" and value and value ~= "None" then @@ -3328,7 +3333,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() end end end - controls.save = new("ButtonControl", nil, {-45, 157, 80, 20}, "Add", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 157, 80, 20}, "Add", function() self:SetDisplayItem(addModifier()) main:ClosePopup() end) @@ -3336,7 +3341,7 @@ function ItemsTabClass:AddCrucibleModifierToDisplayItem() tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) end - controls.close = new("ButtonControl", nil, {45, 157, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 157, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(710, 185, "Add Crucible Modifier to Item", controls, "save") @@ -3531,7 +3536,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() if listMod.sortValues[stat] ~= nil then return listMod.sortValues[stat] end - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id applyCandidateMod(item, listMod) item:BuildAndParseRaw() @@ -3614,7 +3619,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() end end local function addModifier() - local item = new("Item", self.displayItem:BuildRaw()) + local item = new("Item"):Item(self.displayItem:BuildRaw()) item.id = self.displayItem.id local sourceId = sourceList[controls.source.selIndex].sourceId if sourceId == "CUSTOM" then @@ -3629,8 +3634,8 @@ function ItemsTabClass:AddImplicitToDisplayItem() item:BuildAndParseRaw() return item end - controls.sourceLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") - controls.source = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) + controls.sourceLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 20, 0, 16}, "^7Source:") + controls.source = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 20, 150, 18}, sourceList, function(index, value) if value.sourceId ~= "CUSTOM" then controls.modSelectLabel.y = 70 buildMods(value.sourceId) @@ -3645,18 +3650,18 @@ function ItemsTabClass:AddImplicitToDisplayItem() end end) controls.source.enabled = #sourceList > 1 - controls.sortLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") + controls.sortLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {350, 20, 0, 16}, "^7Sort by:") controls.sortLabel.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.sort = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) + controls.sort = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {355, 20, 240, 18}, sortList, function(index, value) applySort(value.stat, true) end) controls.sort.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end - controls.modGroupSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Type:") - controls.modGroupSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modGroups, function(index, value) + controls.modGroupSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 45, 0, 16}, "^7Type:") + controls.modGroupSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 600, 18}, modGroups, function(index, value) controls.modSelect.list = modList[value.modListIndex] controls.modSelect:SetSel(1) end) @@ -3678,8 +3683,8 @@ function ItemsTabClass:AddImplicitToDisplayItem() self:AddModComparisonTooltip(tooltip, value.mod) end end - controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Modifier:") - controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 600, 18}, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or { }) + controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {95, 70, 0, 16}, "^7Modifier:") + controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 70, 600, 18}, sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" and modList[modGroups[1].modListIndex] or { }) controls.modSelect.shown = function() return sourceList[controls.source.selIndex].sourceId ~= "CUSTOM" end @@ -3692,11 +3697,11 @@ function ItemsTabClass:AddImplicitToDisplayItem() self:AddModComparisonTooltip(tooltip, value.mod) end end - controls.custom = new("EditControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) + controls.custom = new("EditControl"):EditControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 45, 440, 18}) controls.custom.shown = function() return sourceList[controls.source.selIndex].sourceId == "CUSTOM" end - controls.save = new("ButtonControl", nil, {-45, 100, 80, 20}, "Add", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 100, 80, 20}, "Add", function() self:SetDisplayItem(addModifier()) main:ClosePopup() end) @@ -3704,7 +3709,7 @@ function ItemsTabClass:AddImplicitToDisplayItem() tooltip:Clear() self:AddItemTooltip(tooltip, addModifier()) end - controls.close = new("ButtonControl", nil, {45, 100, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 100, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(710, 130, "Add Implicit to Item", controls, "save", sourceList[controls.source.selIndex].sourceId == "CUSTOM" and "custom") diff --git a/src/Classes/LabelControl.lua b/src/Classes/LabelControl.lua index 2f799ece2d..afedc6fdf3 100644 --- a/src/Classes/LabelControl.lua +++ b/src/Classes/LabelControl.lua @@ -3,13 +3,20 @@ -- Class: Label Control -- Simple text label. -- -local LabelClass = newClass("LabelControl", "Control", function(self, anchor, rect, label) - self.Control(anchor, rect) +---@class LabelControl: Control +local LabelClass = newClass("LabelControl", "Control") + +---@param anchor? ControlAnchor +---@param rect? ControlRect +---@param label string +function LabelClass:LabelControl(anchor, rect, label) + self:Control(anchor, rect) self.label = label self.width = function() return DrawStringWidth(self:GetProperty("height"), "VAR", self:GetProperty("label")) end -end) + return self +end function LabelClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/ListControl.lua b/src/Classes/ListControl.lua index 34dd0e7f41..7527b4cd96 100644 --- a/src/Classes/ListControl.lua +++ b/src/Classes/ListControl.lua @@ -30,16 +30,19 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor -local ListClass = newClass("ListControl", "Control", "ControlHost", function(self, anchor, rect, rowHeight, scroll, isMutable, list, forceTooltip) - self.Control(anchor, rect) - self.ControlHost() +---@class ListControl: Control, ControlHost +local ListClass = newClass("ListControl", "Control", "ControlHost") + +function ListClass:ListControl(anchor, rect, rowHeight, scroll, isMutable, list, forceTooltip) + self:Control(anchor, rect) + self:ControlHost() self.rowHeight = rowHeight self.scroll = scroll self.isMutable = isMutable self.list = list or { } self.forceTooltip = forceTooltip self.colList = { { } } - self.tooltip = new("Tooltip") + self.tooltip = new("Tooltip"):Tooltip() self.font = "VAR" if self.scroll then if self.scroll == "HORIZONTAL" then @@ -48,7 +51,7 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel self.scrollH = false end end - self.controls.scrollBarH = new("ScrollBarControl", {"BOTTOM",self,"BOTTOM"}, {-8, -1, 0, self.scroll and 16 or 0}, rowHeight * 2, "HORIZONTAL") { + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl({"BOTTOM",self,"BOTTOM"}, {-8, -1, 0, self.scroll and 16 or 0}, rowHeight * 2, "HORIZONTAL") { shown = function() return self.scrollH end, @@ -57,7 +60,7 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel return width - 18 end } - self.controls.scrollBarV = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-1, 0, self.scroll and 16 or 0, 0}, rowHeight * 2, "VERTICAL") { + self.controls.scrollBarV = new("ScrollBarControl"):ScrollBarControl({"RIGHT",self,"RIGHT"}, {-1, 0, self.scroll and 16 or 0, 0}, rowHeight * 2, "VERTICAL") { y = function() return (self.scrollH and -8 or 0) end, @@ -71,7 +74,9 @@ local ListClass = newClass("ListControl", "Control", "ControlHost", function(sel self.controls.scrollBarV.shown = false end self.labelPositionOffset = {0, 0} -end) + return self +end + function ListClass:SelectIndex(index) self.selValue = self.list[index] diff --git a/src/Classes/MinionListControl.lua b/src/Classes/MinionListControl.lua index 1bd119853c..2c153fdbaa 100644 --- a/src/Classes/MinionListControl.lua +++ b/src/Classes/MinionListControl.lua @@ -8,14 +8,17 @@ local t_insert = table.insert local t_remove = table.remove local s_format = string.format -local MinionListClass = newClass("MinionListControl", "ListControl", function(self, anchor, rect, data, list, dest) - self.ListControl(anchor, rect, 16, "VERTICAL", not dest, list) +---@class MinionListControl: ListControl +local MinionListClass = newClass("MinionListControl", "ListControl") + +function MinionListClass:MinionListControl(anchor, rect, data, list, dest) + self:ListControl(anchor, rect, 16, "VERTICAL", not dest, list) self.data = data self.dest = dest if dest then self.dragTargetList = { dest } self.label = "^7Available Spectres:" - self.controls.add = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Add", function() + self.controls.add = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Add", function() self:AddSel() end) self.controls.add.enabled = function() @@ -23,14 +26,15 @@ local MinionListClass = newClass("MinionListControl", "ListControl", function(se end else self.label = "^7Spectres in Build:" - self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Remove", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Remove", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end end -end) + return self +end function MinionListClass:AddSel() if self.dest and not isValueInArray(self.dest.list, self.selValue) then diff --git a/src/Classes/MinionSearchListControl.lua b/src/Classes/MinionSearchListControl.lua index 699e739681..43773259d9 100644 --- a/src/Classes/MinionSearchListControl.lua +++ b/src/Classes/MinionSearchListControl.lua @@ -8,16 +8,19 @@ local t_insert = table.insert local t_remove = table.remove local s_format = string.format -local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListControl", function(self, anchor, rect, data, list, dest) - self.MinionListControl(anchor, rect, data, list, dest) +---@class MinionSearchListControl: MinionListControl +local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListControl") + +function MinionSearchListClass:MinionSearchListControl(anchor, rect, data, list, dest) + self:MinionListControl(anchor, rect, data, list, dest) self.unfilteredList = copyTable(list) self.isMutable = false - self.controls.searchText = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 203, 18}, "", "Search", "%c", 100, function(buf) + self.controls.searchText = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 203, 18}, "", "Search", "%c", 100, function(buf) self:ListFilterChanged(buf, self.controls.searchModeDropDown.selIndex) end, nil, nil, true) - self.controls.searchModeDropDown = new("DropDownControl", {"LEFT",self.controls.searchText,"RIGHT"}, {2, 0, 60, 18}, { "Names", "Skills", "Both"}, function(index, value) + self.controls.searchModeDropDown = new("DropDownControl"):DropDownControl({"LEFT",self.controls.searchText,"RIGHT"}, {2, 0, 60, 18}, { "Names", "Skills", "Both"}, function(index, value) self:ListFilterChanged(self.controls.searchText.buf, index) end) @@ -28,7 +31,8 @@ local MinionSearchListClass = newClass("MinionSearchListControl", "MinionListCon self.controls.delete.y = self.controls.add.y - 20 end -end) + return self +end function MinionSearchListClass:DoesEntryMatchFilters(searchStr, minionId, filterMode) if filterMode == 1 or filterMode == 3 then diff --git a/src/Classes/ModDB.lua b/src/Classes/ModDB.lua index 3b7ae60922..c71599b5a0 100644 --- a/src/Classes/ModDB.lua +++ b/src/Classes/ModDB.lua @@ -17,10 +17,14 @@ local bor = bit.bor local mod_createMod = modLib.createMod -local ModDBClass = newClass("ModDB", "ModStore", function(self, parent) - self.ModStore(parent) +---@class ModDB: ModStore +local ModDBClass = newClass("ModDB", "ModStore") + +function ModDBClass:ModDB(parent) + self:ModStore(parent) self.mods = { } -end) + return self +end function ModDBClass:AddMod(mod) local name = mod.name diff --git a/src/Classes/ModList.lua b/src/Classes/ModList.lua index 7bb6e2aba8..ec686674d7 100644 --- a/src/Classes/ModList.lua +++ b/src/Classes/ModList.lua @@ -16,9 +16,13 @@ local bor = bit.bor local mod_createMod = modLib.createMod -local ModListClass = newClass("ModList", "ModStore", function(self, parent) - self.ModStore(parent) -end) +---@class ModList: ModStore +local ModListClass = newClass("ModList", "ModStore") + +function ModListClass:ModList(parent) + self:ModStore(parent) + return self +end function ModListClass:AddMod(mod) t_insert(self, mod) diff --git a/src/Classes/ModStore.lua b/src/Classes/ModStore.lua index 92603eb323..cc5cc83251 100644 --- a/src/Classes/ModStore.lua +++ b/src/Classes/ModStore.lua @@ -27,12 +27,16 @@ local conditionName = setmetatable({ }, { __index = function(t, var) return t[var] end }) -local ModStoreClass = newClass("ModStore", function(self, parent) +---@class ModStore +local ModStoreClass = newClass("ModStore") + +function ModStoreClass:ModStore(parent) self.parent = parent or false self.actor = parent and parent.actor or { } self.multipliers = { } self.conditions = { } -end) + return self +end function ModStoreClass:ScaleAddMod(mod, scale, replace) local unscalable = false diff --git a/src/Classes/NotableDBControl.lua b/src/Classes/NotableDBControl.lua index d08ec4080c..4255e933f5 100644 --- a/src/Classes/NotableDBControl.lua +++ b/src/Classes/NotableDBControl.lua @@ -19,8 +19,10 @@ local function IsAnointableNode(node) end ---@class NotableDBControl : ListControl -local NotableDBClass = newClass("NotableDBControl", "ListControl", function(self, anchor, rect, itemsTab, db, dbType) - self.ListControl(anchor, rect, 16, "VERTICAL", false) +local NotableDBClass = newClass("NotableDBControl", "ListControl") + +function NotableDBClass:NotableDBControl(anchor, rect, itemsTab, db, dbType) + self:ListControl(anchor, rect, 16, "VERTICAL", false) self.itemsTab = itemsTab self.db = db self.dbType = dbType @@ -32,18 +34,19 @@ local NotableDBClass = newClass("NotableDBControl", "ListControl", function(self self.sortDropList = { } self.sortOrder = { } self.sortMode = "NAME" - self.controls.sort = new("DropDownControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -22, 360, 18}, self.sortDropList, function(index, value) + self.controls.sort = new("DropDownControl"):DropDownControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -22, 360, 18}, self.sortDropList, function(index, value) self:SetSortMode(value.sortMode) end) - self.controls.search = new("EditControl", {"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() + self.controls.search = new("EditControl"):EditControl({"BOTTOMLEFT",self,"TOPLEFT"}, {0, -2, 258, 18}, "", "Search", "%c", 100, function() self.listBuildFlag = true end, nil, nil, true) - self.controls.searchMode = new("DropDownControl", {"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) + self.controls.searchMode = new("DropDownControl"):DropDownControl({"LEFT",self.controls.search,"RIGHT"}, {2, 0, 100, 18}, { "Anywhere", "Names", "Modifiers" }, function(index, value) self.listBuildFlag = true end) self:BuildSortOrder() self.listBuildFlag = true -end) + return self +end ---@param node table @The notable node to check ---@return boolean @Whether the notable matches the type and search filters. diff --git a/src/Classes/NotesTab.lua b/src/Classes/NotesTab.lua index f78ea2eb41..8bfc7c7772 100644 --- a/src/Classes/NotesTab.lua +++ b/src/Classes/NotesTab.lua @@ -5,9 +5,13 @@ -- local t_insert = table.insert -local NotesTabClass = newClass("NotesTab", "ControlHost", "Control", function(self, build) - self.ControlHost() - self.Control() +---@class NotesTab: ControlHost, Control +local NotesTabClass = newClass("NotesTab", "ControlHost", "Control") + +---@param build Build +function NotesTabClass:NotesTab(build) + self:ControlHost() + self:Control() self.build = build @@ -17,33 +21,34 @@ local NotesTabClass = newClass("NotesTab", "ControlHost", "Control", function(se local notesDesc = [[^7You can use Ctrl +/- (or Ctrl+Scroll) to zoom in and out and Ctrl+0 to reset. This field also supports different colors. Using the caret symbol (^) followed by a Hex code or a number (0-9) will set the color. Below are some common color codes PoB uses: ]] - self.controls.notesDesc = new("LabelControl", {"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, 16}, notesDesc) - self.controls.normal = new("ButtonControl", {"TOPLEFT",self.controls.notesDesc,"TOPLEFT"}, {0, 48, 100, 18}, colorCodes.NORMAL.."NORMAL", function() self:SetColor(colorCodes.NORMAL) end) - self.controls.magic = new("ButtonControl", {"TOPLEFT",self.controls.normal,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.MAGIC.."MAGIC", function() self:SetColor(colorCodes.MAGIC) end) - self.controls.rare = new("ButtonControl", {"TOPLEFT",self.controls.magic,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.RARE.."RARE", function() self:SetColor(colorCodes.RARE) end) - self.controls.unique = new("ButtonControl", {"TOPLEFT",self.controls.rare,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.UNIQUE.."UNIQUE", function() self:SetColor(colorCodes.UNIQUE) end) - self.controls.fire = new("ButtonControl", {"TOPLEFT",self.controls.normal,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.FIRE.."FIRE", function() self:SetColor(colorCodes.FIRE) end) - self.controls.cold = new("ButtonControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.COLD.."COLD", function() self:SetColor(colorCodes.COLD) end) - self.controls.lightning = new("ButtonControl", {"TOPLEFT",self.controls.cold,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.LIGHTNING.."LIGHTNING", function() self:SetColor(colorCodes.LIGHTNING) end) - self.controls.chaos = new("ButtonControl", {"TOPLEFT",self.controls.lightning,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.CHAOS.."CHAOS", function() self:SetColor(colorCodes.CHAOS) end) - self.controls.strength = new("ButtonControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.STRENGTH.."STRENGTH", function() self:SetColor(colorCodes.STRENGTH) end) - self.controls.dexterity = new("ButtonControl", {"TOPLEFT",self.controls.strength,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.DEXTERITY.."DEXTERITY", function() self:SetColor(colorCodes.DEXTERITY) end) - self.controls.intelligence = new("ButtonControl", {"TOPLEFT",self.controls.dexterity,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.INTELLIGENCE.."INTELLIGENCE", function() self:SetColor(colorCodes.INTELLIGENCE) end) - self.controls.default = new("ButtonControl", {"TOPLEFT",self.controls.intelligence,"TOPLEFT"}, {120, 0, 100, 18}, "^7DEFAULT", function() self:SetColor("^7") end) + self.controls.notesDesc = new("LabelControl"):LabelControl({"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, 16}, notesDesc) + self.controls.normal = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.notesDesc,"TOPLEFT"}, {0, 48, 100, 18}, colorCodes.NORMAL.."NORMAL", function() self:SetColor(colorCodes.NORMAL) end) + self.controls.magic = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.normal,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.MAGIC.."MAGIC", function() self:SetColor(colorCodes.MAGIC) end) + self.controls.rare = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.magic,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.RARE.."RARE", function() self:SetColor(colorCodes.RARE) end) + self.controls.unique = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.rare,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.UNIQUE.."UNIQUE", function() self:SetColor(colorCodes.UNIQUE) end) + self.controls.fire = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.normal,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.FIRE.."FIRE", function() self:SetColor(colorCodes.FIRE) end) + self.controls.cold = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.COLD.."COLD", function() self:SetColor(colorCodes.COLD) end) + self.controls.lightning = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.cold,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.LIGHTNING.."LIGHTNING", function() self:SetColor(colorCodes.LIGHTNING) end) + self.controls.chaos = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.lightning,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.CHAOS.."CHAOS", function() self:SetColor(colorCodes.CHAOS) end) + self.controls.strength = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 18, 100, 18}, colorCodes.STRENGTH.."STRENGTH", function() self:SetColor(colorCodes.STRENGTH) end) + self.controls.dexterity = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.strength,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.DEXTERITY.."DEXTERITY", function() self:SetColor(colorCodes.DEXTERITY) end) + self.controls.intelligence = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.dexterity,"TOPLEFT"}, {120, 0, 100, 18}, colorCodes.INTELLIGENCE.."INTELLIGENCE", function() self:SetColor(colorCodes.INTELLIGENCE) end) + self.controls.default = new("ButtonControl"):ButtonControl({"TOPLEFT",self.controls.intelligence,"TOPLEFT"}, {120, 0, 100, 18}, "^7DEFAULT", function() self:SetColor("^7") end) - self.controls.edit = new("EditControl", {"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 48, 0, 0}, "", nil, "^%C\t\n", nil, nil, 16, true) + self.controls.edit = new("EditControl"):EditControl({"TOPLEFT",self.controls.fire,"TOPLEFT"}, {0, 48, 0, 0}, "", nil, "^%C\t\n", nil, nil, 16, true) self.controls.edit.width = function() return self.width - 16 end self.controls.edit.height = function() return self.height - 128 end - self.controls.toggleColorCodes = new("ButtonControl", {"TOPRIGHT",self,"TOPRIGHT"}, {-10, 70, 160, 20}, "Show Color Codes", function() + self.controls.toggleColorCodes = new("ButtonControl"):ButtonControl({"TOPRIGHT",self,"TOPRIGHT"}, {-10, 70, 160, 20}, "Show Color Codes", function() self.showColorCodes = not self.showColorCodes self:SetShowColorCodes(self.showColorCodes) end) self:SelectControl(self.controls.edit) -end) + return self +end function NotesTabClass:SetShowColorCodes(setting) self.showColorCodes = setting diff --git a/src/Classes/PartyTab.lua b/src/Classes/PartyTab.lua index 61b0140368..ee9b119d55 100644 --- a/src/Classes/PartyTab.lua +++ b/src/Classes/PartyTab.lua @@ -9,15 +9,19 @@ local s_format = string.format local t_insert = table.insert local m_max = math.max -local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(self, build) - self.ControlHost() - self.Control() +---@class PartyTab: ControlHost, Control +local PartyTabClass = newClass("PartyTab", "ControlHost", "Control") + +---@param build Build +function PartyTabClass:PartyTab(build) + self:ControlHost() + self:Control() self.build = build - self.actor = { Aura = { }, Curse = { }, Warcry = { }, Link = { }, modDB = new("ModDB"), output = { } } + self.actor = { Aura = { }, Curse = { }, Warcry = { }, Link = { }, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.buffExports = { } self.enableExportBuffs = false @@ -61,7 +65,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se All of these effects can be found in the Calcs tab]] - self.controls.notesDesc = new("LabelControl", {"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, theme.stringHeight}, notesDesc) + self.controls.notesDesc = new("LabelControl"):LabelControl({"TOPLEFT",self,"TOPLEFT"}, {8, 8, 150, theme.stringHeight}, notesDesc) self.controls.notesDesc.width = function() local width = self.width / 2 - 16 if width ~= self.controls.notesDesc.lastWidth then @@ -70,7 +74,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end return width end - self.controls.importCodeHeader = new("LabelControl", {"TOPLEFT",self.controls.notesDesc,"BOTTOMLEFT"}, {0, 32, 0, theme.stringHeight}, "^7Enter a build code/URL below:") + self.controls.importCodeHeader = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.notesDesc,"BOTTOMLEFT"}, {0, 32, 0, theme.stringHeight}, "^7Enter a build code/URL below:") self.controls.importCodeHeader.y = function() return theme.lineCounter(self.controls.notesDesc.label) + 4 end @@ -270,7 +274,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end if partyDestinations[self.controls.importCodeDestination.selIndex] == "All" or partyDestinations[self.controls.importCodeDestination.selIndex] == "EnemyConditions" or partyDestinations[self.controls.importCodeDestination.selIndex] == "EnemyMods" then wipeTable(self.enemyModList) - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self:ParseBuffs(self.enemyModList, self.controls.enemyCond.buf, "EnemyConditions") self:ParseBuffs(self.enemyModList, self.controls.enemyMods.buf, "EnemyMods", self.controls.simpleEnemyMods) end @@ -280,7 +284,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se end end - self.controls.importCodeIn = new("EditControl", {"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, theme.buttonHeight}, "", nil, nil, nil, importCodeHandle) + self.controls.importCodeIn = new("EditControl"):EditControl({"TOPLEFT",self.controls.importCodeHeader,"BOTTOMLEFT"}, {0, 4, 328, theme.buttonHeight}, "", nil, nil, nil, importCodeHandle) self.controls.importCodeIn.width = function() return (self.width > 880) and 328 or (self.width / 2 - 100) end @@ -289,13 +293,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.importCodeGo.onClick() end end - self.controls.importCodeState = new("LabelControl", {"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, theme.stringHeight}) + self.controls.importCodeState = new("LabelControl"):LabelControl({"LEFT",self.controls.importCodeIn,"RIGHT"}, {8, 0, 0, theme.stringHeight}) self.controls.importCodeState.label = function() return self.importCodeDetail or "" end - self.controls.importCodeDestination = new("DropDownControl", {"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, theme.buttonHeight}, partyDestinations) + self.controls.importCodeDestination = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.importCodeIn,"BOTTOMLEFT"}, {0, 4, 160, theme.buttonHeight}, partyDestinations) self.controls.importCodeDestination.tooltipText = "Destination for Import/clear\nCurrently Links Skills do not export" - self.controls.importCodeGo = new("ButtonControl", {"LEFT",self.controls.importCodeDestination,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Import", function() + self.controls.importCodeGo = new("ButtonControl"):ButtonControl({"LEFT",self.controls.importCodeDestination,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Import", function() local importCodeFetching = false if self.importCodeSite and not self.importCodeXML then self.importCodeFetching = true @@ -323,7 +327,7 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.importCodeGo.onClick() end end - self.controls.appendNotReplace = new("CheckBoxControl", {"LEFT",self.controls.importCodeGo,"RIGHT"}, {60, 0, theme.buttonHeight}, "Append", function(state) + self.controls.appendNotReplace = new("CheckBoxControl"):CheckBoxControl({"LEFT",self.controls.importCodeGo,"RIGHT"}, {60, 0, theme.buttonHeight}, "Append", function(state) end, "This sets the import button to append to the current party lists instead of replacing them (curses will still replace)", false) self.controls.appendNotReplace.x = function() return (self.width > theme.widthThreshold1) and 60 or (-276) @@ -332,36 +336,36 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return (self.width > theme.widthThreshold1) and 0 or 24 end - self.controls.clear = new("ButtonControl", {"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() + self.controls.clear = new("ButtonControl"):ButtonControl({"LEFT",self.controls.appendNotReplace,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Clear", function() clearInputText() wipeTable(self.enemyModList) - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.build.buildFlag = true end) self.controls.clear.tooltipText = "^7Clears all the party tab imported data" - self.controls.ShowAdvanceTools = new("CheckBoxControl", {"TOPLEFT",self.controls.importCodeDestination,"BOTTOMLEFT"}, {140, 4, theme.buttonHeight}, "^7Show Advanced Info", function(state) + self.controls.ShowAdvanceTools = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",self.controls.importCodeDestination,"BOTTOMLEFT"}, {140, 4, theme.buttonHeight}, "^7Show Advanced Info", function(state) end, "This shows the advanced info like what stats each aura/curse etc are adding, as well as enables the ability to edit them without a re-export\nDo not edit any boxes unless you know what you are doing, use copy/paste or import instead", false) self.controls.ShowAdvanceTools.y = function() return (self.width > theme.widthThreshold1) and 4 or 28 end - self.controls.removeEffects = new("ButtonControl", {"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() + self.controls.removeEffects = new("ButtonControl"):ButtonControl({"LEFT",self.controls.ShowAdvanceTools,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "Disable Party Effects", function() wipeTable(self.actor) wipeTable(self.enemyModList) - self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } + self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self.build.buildFlag = true end) self.controls.removeEffects.tooltipText = "^7Removes the effects of the supports, without removing the data\nUse \"rebuild all\" to apply the effects again" - self.controls.rebuild = new("ButtonControl", {"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() + self.controls.rebuild = new("ButtonControl"):ButtonControl({"LEFT",self.controls.removeEffects,"RIGHT"}, {8, 0, 160, theme.buttonHeight}, "^7Rebuild All", function() wipeTable(self.actor) wipeTable(self.enemyModList) - self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"), output = { } } + self.actor = { Aura = {}, Curse = {}, Warcry = { }, Link = {}, modDB = new("ModDB"):ModDB(), output = { } } self.actor.modDB.actor = self.actor - self.enemyModList = new("ModList") + self.enemyModList = new("ModList"):ModList() self:ParseBuffs(self.actor["modDB"], self.controls.editPartyMemberStats.buf, "PartyMemberStats", self.actor["output"]) self:ParseBuffs(self.actor["Aura"], self.controls.editAuras.buf, "Aura", self.controls.simpleAuras) self:ParseBuffs(self.actor["Curse"], self.controls.editCurses.buf, "Curse", self.controls.simpleCurses) @@ -379,11 +383,11 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return (self.width > theme.widthThreshold1) and 0 or 24 end - self.controls.editAurasLabel = new("LabelControl", {"TOPLEFT",self.controls.ShowAdvanceTools,"TOPLEFT"}, {-140, 40, 0, theme.stringHeight}, "^7Auras") + self.controls.editAurasLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.ShowAdvanceTools,"TOPLEFT"}, {-140, 40, 0, theme.stringHeight}, "^7Auras") self.controls.editAurasLabel.y = function() return 36 + ((self.width <= theme.widthThreshold1) and 24 or 0) end - self.controls.editAuras = new("EditControl", {"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editAuras = new("EditControl"):EditControl({"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editAuras.width = function() return self.width / 2 - 16 end @@ -394,16 +398,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editAuras.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleAuras = new("LabelControl", {"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleAuras = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editAurasLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleAuras.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editWarcriesLabel = new("LabelControl", {"TOPLEFT",self.controls.editAurasLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Warcry Skills") + self.controls.editWarcriesLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editAurasLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Warcry Skills") self.controls.editWarcriesLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editAuras.height() + 8) or (theme.lineCounter(self.controls.simpleAuras.label) + 4) end - self.controls.editWarcries = new("EditControl", {"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editWarcries = new("EditControl"):EditControl({"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editWarcries.width = function() return self.width / 2 - 16 end @@ -413,16 +417,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editWarcries.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleWarcries = new("LabelControl", {"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleWarcries = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editWarcriesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleWarcries.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editLinksLabel = new("LabelControl", {"TOPLEFT",self.controls.editWarcriesLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Link Skills") + self.controls.editLinksLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editWarcriesLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Link Skills") self.controls.editLinksLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editWarcries.height() + 8) or (theme.lineCounter(self.controls.simpleWarcries.label) + 4) end - self.controls.editLinks = new("EditControl", {"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editLinks = new("EditControl"):EditControl({"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editLinks.width = function() return self.width / 2 - 16 end @@ -432,13 +436,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editLinks.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleLinks = new("LabelControl", {"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleLinks = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editLinksLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleLinks.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editPartyMemberStatsLabel = new("LabelControl", {"TOPLEFT",self.controls.notesDesc,"TOPRIGHT"}, {8, 0, 0, theme.stringHeight}, "^7Party Member Stats") - self.controls.editPartyMemberStats = new("EditControl", {"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editPartyMemberStatsLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.notesDesc,"TOPRIGHT"}, {8, 0, 0, theme.stringHeight}, "^7Party Member Stats") + self.controls.editPartyMemberStats = new("EditControl"):EditControl({"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editPartyMemberStats.width = function() return self.width / 2 - 16 end @@ -449,11 +453,11 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se return self.controls.ShowAdvanceTools.state end - self.controls.enemyCondLabel = new("LabelControl", {"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Conditions") + self.controls.enemyCondLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editPartyMemberStatsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Conditions") self.controls.enemyCondLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.editPartyMemberStats.height() + 8) or 4 end - self.controls.enemyCond = new("EditControl", {"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.enemyCond = new("EditControl"):EditControl({"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.enemyCond.width = function() return self.width / 2 - 16 end @@ -463,16 +467,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.enemyCond.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleEnemyCond = new("LabelControl", {"TOPLEFT",self.controls.enemyCondLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "^7---------------------------\n") + self.controls.simpleEnemyCond = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyCondLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "^7---------------------------\n") self.controls.simpleEnemyCond.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.enemyModsLabel = new("LabelControl", {"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Modifiers") + self.controls.enemyModsLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyCondLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Enemy Modifiers") self.controls.enemyModsLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.enemyCond.height() + 8) or (theme.lineCounter(self.controls.simpleEnemyCond.label) + 4) end - self.controls.enemyMods = new("EditControl", {"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.enemyMods = new("EditControl"):EditControl({"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.enemyMods.width = function() return self.width / 2 - 16 end @@ -482,16 +486,16 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.enemyMods.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleEnemyMods = new("LabelControl", {"TOPLEFT",self.controls.enemyModsLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "\n") + self.controls.simpleEnemyMods = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyModsLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "\n") self.controls.simpleEnemyMods.shown = function() return not self.controls.ShowAdvanceTools.state end - self.controls.editCursesLabel = new("LabelControl", {"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Curses") + self.controls.editCursesLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.enemyModsLabel,"BOTTOMLEFT"}, {0, 8, 0, theme.stringHeight}, "^7Curses") self.controls.editCursesLabel.y = function() return self.controls.ShowAdvanceTools.state and (self.controls.enemyMods.height() + 8) or (theme.lineCounter(self.controls.simpleEnemyMods.label) + 4) end - self.controls.editCurses = new("EditControl", {"TOPLEFT",self.controls.editCursesLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) + self.controls.editCurses = new("EditControl"):EditControl({"TOPLEFT",self.controls.editCursesLabel,"BOTTOMLEFT"}, {0, 2, 0, 0}, "", nil, "^%C\t\n", nil, nil, 14, true) self.controls.editCurses.width = function() return self.width / 2 - 16 end @@ -501,12 +505,13 @@ local PartyTabClass = newClass("PartyTab", "ControlHost", "Control", function(se self.controls.editCurses.shown = function() return self.controls.ShowAdvanceTools.state end - self.controls.simpleCurses = new("LabelControl", {"TOPLEFT",self.controls.editCursesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") + self.controls.simpleCurses = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.editCursesLabel,"TOPLEFT"}, {0, 18, 0, theme.stringHeight}, "") self.controls.simpleCurses.shown = function() return not self.controls.ShowAdvanceTools.state end self:SelectControl(self.controls.editAuras) -end) + return self +end function PartyTabClass:Load(xml, fileName) for _, node in ipairs(xml) do @@ -839,7 +844,7 @@ function PartyTabClass:ParseBuffs(list, buf, buffType, label) end if not listElement[currentName] then listElement[currentName] = { - modList = new("ModList"), + modList = new("ModList"):ModList(), effectMult = currentEffect } if isMark then @@ -848,7 +853,7 @@ function PartyTabClass:ParseBuffs(list, buf, buffType, label) elseif listElement[currentName].effectMult ~= currentEffect then if listElement[currentName].effectMult < currentEffect then listElement[currentName] = { - modList = new("ModList"), + modList = new("ModList"):ModList(), effectMult = currentEffect } else diff --git a/src/Classes/PassiveMasteryControl.lua b/src/Classes/PassiveMasteryControl.lua index 6cf35b182c..87242b0cb5 100644 --- a/src/Classes/PassiveMasteryControl.lua +++ b/src/Classes/PassiveMasteryControl.lua @@ -9,20 +9,23 @@ local m_min = math.min local m_max = math.max local m_floor = math.floor ---constructor -local PassiveMasteryControlClass = newClass("PassiveMasteryControl", "ListControl", function(self, anchor, rect, list, treeTab, node, saveButton) +---@class PassiveMasteryControl: ListControl +local PassiveMasteryControlClass = newClass("PassiveMasteryControl", "ListControl") + +function PassiveMasteryControlClass:PassiveMasteryControl(anchor, rect, list, treeTab, node, saveButton) self.list = list or { } -- automagical width for j=1,#list do rect[3] = m_max(rect[3], DrawStringWidth(16, "VAR", list[j].label) + 5) end - self.ListControl(anchor, rect, 16, false, false, self.list) + self:ListControl(anchor, rect, 16, false, false, self.list) self.treeTab = treeTab self.treeView = treeTab.viewer self.node = node self.selIndex = nil self.saveButton = saveButton -end) + return self +end function PassiveMasteryControlClass:Draw(viewPort) self.ListControl.Draw(self, viewPort) diff --git a/src/Classes/PassiveSpec.lua b/src/Classes/PassiveSpec.lua index e28e74a86b..c869014dce 100644 --- a/src/Classes/PassiveSpec.lua +++ b/src/Classes/PassiveSpec.lua @@ -16,8 +16,11 @@ local b_rshift = bit.rshift local band = bit.band local bor = bit.bor -local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler", function(self, build, treeVersion, convert) - self.UndoHandler() +---@class PassiveSpec: UndoHandler +local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler") + +function PassiveSpecClass:PassiveSpec(build, treeVersion, convert) + self:UndoHandler() self.build = build @@ -25,7 +28,8 @@ local PassiveSpecClass = newClass("PassiveSpec", "UndoHandler", function(self, b self:Init(treeVersion, convert) self:SelectClass(0) -end) + return self +end function PassiveSpecClass:Init(treeVersion, convert) self.treeVersion = treeVersion @@ -1574,7 +1578,7 @@ function PassiveSpecClass:ReplaceNode(old, newNode) old.name = newNode.name old.mods = newNode.mods old.modKey = newNode.modKey - old.modList = new("ModList") + old.modList = new("ModList"):ModList() old.modList:AddList(newNode.modList) old.sprites = newNode.sprites old.effectSprites = newNode.effectSprites @@ -2263,12 +2267,12 @@ end --- Adds a line to or replaces a node given a line to add/replace with --- @param node table The node to replace/add to --- @param sd string The line being parsed and added ---- @param replacement boolean true to replace the node with the new mod, false to simply add it +--- @param replacement? boolean true to replace the node with the new mod, false to simply add it function PassiveSpecClass:NodeAdditionOrReplacementFromString(node,sd,replacement) local addition = {} addition.sd = {sd} addition.mods = { } - addition.modList = new("ModList") + addition.modList = new("ModList"):ModList() addition.modKey = "" local i = 1 while addition.sd[i] do @@ -2339,7 +2343,7 @@ function PassiveSpecClass:NodeAdditionOrReplacementFromString(node,sd,replacemen node.mods = tableConcat(node.mods, addition.mods) node.modKey = node.modKey .. addition.modKey end - local modList = new("ModList") + local modList = new("ModList"):ModList() modList:AddList(addition.modList) if not replacement then modList:AddList(node.modList) diff --git a/src/Classes/PassiveSpecListControl.lua b/src/Classes/PassiveSpecListControl.lua index f227764d8f..7f760ed3f0 100644 --- a/src/Classes/PassiveSpecListControl.lua +++ b/src/Classes/PassiveSpecListControl.lua @@ -7,11 +7,14 @@ local t_insert = table.insert local t_remove = table.remove local m_max = math.max -local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl", function(self, anchor, rect, treeTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, treeTab.specList) +---@class PassiveSpecListControl: ListControl +local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl") + +function PassiveSpecListClass:PassiveSpecListControl(anchor, rect, treeTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, treeTab.specList) self.treeTab = treeTab - self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() - local newSpec = new("PassiveSpec", treeTab.build, self.selValue.treeVersion) + self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + local newSpec = new("PassiveSpec"):PassiveSpec(treeTab.build, self.selValue.treeVersion) newSpec.title = self.selValue.title newSpec.jewels = copyTable(self.selValue.jewels) newSpec:RestoreUndoState(self.selValue:CreateUndoState()) @@ -21,35 +24,36 @@ local PassiveSpecListClass = newClass("PassiveSpecListControl", "ListControl", f self.controls.copy.enabled = function() return self.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSpec(self.selValue, "Rename Tree") end) self.controls.rename.enabled = function() return self.selValue ~= nil end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() - local newSpec = new("PassiveSpec", treeTab.build, latestTreeVersion) + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + local newSpec = new("PassiveSpec"):PassiveSpec(treeTab.build, latestTreeVersion) newSpec:SelectClass(treeTab.build.spec.curClassId) newSpec:SelectAscendClass(treeTab.build.spec.curAscendClassId) newSpec:SelectSecondaryAscendClass(treeTab.build.spec.curSecondaryAscendClassId) self:RenameSpec(newSpec, "New Tree", true) end) self:UpdateItemsTabPassiveTreeDropdown() -end) + return self +end function PassiveSpecListClass:RenameSpec(spec, title, addOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this passive tree:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, spec.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this passive tree:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, spec.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() spec.title = controls.edit.buf self.treeTab.modFlag = true if addOnName then @@ -62,7 +66,7 @@ function PassiveSpecListClass:RenameSpec(spec, title, addOnName) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) -- main:OpenPopup(370, 100, spec.title and "Rename" or "Set Name", controls, "save", "edit") diff --git a/src/Classes/PassiveTree.lua b/src/Classes/PassiveTree.lua index 6ea7da09a0..8a09a96814 100644 --- a/src/Classes/PassiveTree.lua +++ b/src/Classes/PassiveTree.lua @@ -49,7 +49,10 @@ local function getFile(URL) return #page > 0 and page end -local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) +---@class PassiveTree +local PassiveTreeClass = newClass("PassiveTree") + +function PassiveTreeClass:PassiveTree(treeVersion) self.treeVersion = treeVersion local versionNum = treeVersions[treeVersion].num @@ -720,14 +723,15 @@ local PassiveTreeClass = newClass("PassiveTree", function(self, treeVersion) if treeVersion == latestTreeVersion then buildTreeDependentUniques(self) end -end) + return self +end function PassiveTreeClass:ProcessStats(node, startIndex) startIndex = startIndex or 1 if startIndex == 1 then node.modKey = "" node.mods = { } - node.modList = new("ModList") + node.modList = new("ModList"):ModList() end if not node.sd then diff --git a/src/Classes/PassiveTreeView.lua b/src/Classes/PassiveTreeView.lua index f774737424..e0965d346a 100644 --- a/src/Classes/PassiveTreeView.lua +++ b/src/Classes/PassiveTreeView.lua @@ -14,7 +14,10 @@ local m_floor = math.floor local band = bit.band local b_rshift = bit.rshift -local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) +---@class PassiveTreeView +local PassiveTreeViewClass = newClass("PassiveTreeView") + +function PassiveTreeViewClass:PassiveTreeView() self.ring = NewImageHandle() self.ring:Load("Assets/ring.png", "CLAMP") self.highlightRing = NewImageHandle() @@ -53,7 +56,7 @@ local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) self.kalguur2 = NewImageHandle() self.kalguur2:Load("TreeData/PassiveSkillScreenKalguuranJewelCircle2.png", "CLAMP") - self.tooltip = new("Tooltip") + self.tooltip = new("Tooltip"):Tooltip() self.zoomLevel = 3 self.zoom = 1.2 ^ self.zoomLevel @@ -66,7 +69,8 @@ local PassiveTreeViewClass = newClass("PassiveTreeView", function(self) self.searchStrResults = {} self.showStatDifferences = true self.hoverNode = nil -end) + return self +end function PassiveTreeViewClass:Load(xml, fileName) if xml.attrib.zoomLevel then diff --git a/src/Classes/PathControl.lua b/src/Classes/PathControl.lua index 4d62bef272..af32ccbbb5 100644 --- a/src/Classes/PathControl.lua +++ b/src/Classes/PathControl.lua @@ -6,16 +6,20 @@ local ipairs = ipairs local t_insert = table.insert -local PathClass = newClass("PathControl", "Control", "ControlHost", "UndoHandler", function(self, anchor, rect, basePath, subPath, onChange) - self.Control(anchor, rect) - self.ControlHost() - self.UndoHandler() +---@class PathControl +local PathClass = newClass("PathControl", "Control", "ControlHost", "UndoHandler") + +function PathClass:PathControl(anchor, rect, basePath, subPath, onChange) + self:Control(anchor, rect) + self:ControlHost() + self:UndoHandler() self.basePath = basePath self.baseName = basePath:match("([^/]+)/$") or "Base" self:SetSubPath(subPath or "") self:ResetUndo() self.onChange = onChange -end) + return self +end function PathClass:SetSubPath(subPath, noUndo) if subPath == self.subPath then @@ -33,7 +37,7 @@ function PathClass:SetSubPath(subPath, noUndo) for index, folder in ipairs(self.folderList) do local button = self.controls["folder"..i] if not button then - button = new("ButtonControl", {"LEFT",self,"LEFT"}, {0, 0, 0, self.height - 4}) + button = new("ButtonControl"):ButtonControl({"LEFT",self,"LEFT"}, {0, 0, 0, self.height - 4}) self.controls["folder"..i] = button end button.shown = true diff --git a/src/Classes/PoBArchivesProvider.lua b/src/Classes/PoBArchivesProvider.lua index c2b6ab2a52..d2d694b774 100644 --- a/src/Classes/PoBArchivesProvider.lua +++ b/src/Classes/PoBArchivesProvider.lua @@ -9,17 +9,19 @@ local dkjson = require "dkjson" local archivesUrl = 'https://pobarchives.com' -local PoBArchivesProviderClass = newClass("PoBArchivesProvider", "ExtBuildListProvider", - function(self, mode) - if mode == "builds" then - self.ExtBuildListProvider({"Trending", "Latest"}) - else - self.ExtBuildListProvider({"Similar Builds"}) - end - self.buildList = {} - self.mode = mode +---@class PoBArchivesProvider: ExtBuildListProvider +local PoBArchivesProviderClass = newClass("PoBArchivesProvider", "ExtBuildListProvider") + +function PoBArchivesProviderClass:PoBArchivesProvider(mode) + if mode == "builds" then + self:ExtBuildListProvider({"Trending", "Latest"}) + else + self:ExtBuildListProvider({"Similar Builds"}) end -) + self.buildList = {} + self.mode = mode + return self +end function PoBArchivesProviderClass:GetApiUrl() if self.importCode then diff --git a/src/Classes/PopupDialog.lua b/src/Classes/PopupDialog.lua index 223059def9..1e54e8c695 100644 --- a/src/Classes/PopupDialog.lua +++ b/src/Classes/PopupDialog.lua @@ -5,10 +5,13 @@ -- local m_floor = math.floor -local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control", function(self, width, height, title, controls, enterControl, defaultControl, +---@class PopupDialog: ControlHost, Control +local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control") + +function PopupDialogClass:PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - self.ControlHost() - self.Control(nil, {0, 0, width, height}) + self:ControlHost() + self:Control(nil, {0, 0, width, height}) self.x = function() return m_floor((main.screenW - width) / 2) end @@ -35,7 +38,8 @@ local PopupDialogClass = newClass("PopupDialog", "ControlHost", "Control", funct self.scrollBarFunc = scrollBarFunc -- allow resizing of popup self.resizeFunc = resizeFunc -end) + return self +end function PopupDialogClass:Draw(viewPort) local x, y = self:GetPos() diff --git a/src/Classes/PowerReportListControl.lua b/src/Classes/PowerReportListControl.lua index bd2c1d2cd3..69738aac11 100644 --- a/src/Classes/PowerReportListControl.lua +++ b/src/Classes/PowerReportListControl.lua @@ -8,8 +8,11 @@ local t_insert = table.insert local t_remove = table.remove local t_sort = table.sort -local PowerReportListClass = newClass("PowerReportListControl", "ListControl", function(self, anchor, rect, nodeSelectCallback) - self.ListControl(anchor, rect, 16, "VERTICAL", false) +---@class PowerReportListControl: ListControl +local PowerReportListClass = newClass("PowerReportListControl", "ListControl") + +function PowerReportListClass:PowerReportListControl(anchor, rect, nodeSelectCallback) + self:ListControl(anchor, rect, 16, "VERTICAL", false) local width = rect[3] self.powerColumn = { width = width * 0.16, label = "", sortable = true } @@ -27,7 +30,7 @@ local PowerReportListClass = newClass("PowerReportListControl", "ListControl", f self.allocated = false self.label = "Building Tree..." - self.controls.filterSelect = new("DropDownControl", {"BOTTOMRIGHT", self, "TOPRIGHT"}, {0, -2, 200, 20}, + self.controls.filterSelect = new("DropDownControl"):DropDownControl({"BOTTOMRIGHT", self, "TOPRIGHT"}, {0, -2, 200, 20}, { "Show Unallocated", "Show Unallocated & Clusters", "Show Allocated" }, function(index, value) self.showClusters = index == 2 @@ -35,12 +38,13 @@ local PowerReportListClass = newClass("PowerReportListControl", "ListControl", f self:ReList() self:ReSort(3) -- Sort by power end) - self.controls.masteryCheck = new("CheckBoxControl", {"RIGHT", self.controls.filterSelect, "LEFT"}, {-120, 0, 18}, "Show Masteries:", function(state) + self.controls.masteryCheck = new("CheckBoxControl"):CheckBoxControl({"RIGHT", self.controls.filterSelect, "LEFT"}, {-120, 0, 18}, "Show Masteries:", function(state) self.showMasteries = state self:ReList() self:ReSort(3) -- Sort by power end, nil, true) -end) + return self +end function PowerReportListClass:SetReport(stat, report) self.powerColumn.label = stat and stat.label or "" diff --git a/src/Classes/RectangleOutlineControl.lua b/src/Classes/RectangleOutlineControl.lua index 8b8b0b9d47..d01a58d814 100644 --- a/src/Classes/RectangleOutlineControl.lua +++ b/src/Classes/RectangleOutlineControl.lua @@ -3,11 +3,15 @@ -- Class: RectangleOutline Control -- Simple Outline Only Rectangle control -- -local RectangleOutlineClass = newClass("RectangleOutlineControl", "Control", function(self, anchor, rect, colors, stroke) - self.Control(anchor, rect) +---@class RectangleOutlineControl: Control +local RectangleOutlineClass = newClass("RectangleOutlineControl", "Control") + +function RectangleOutlineClass:RectangleOutlineControl(anchor, rect, colors, stroke) + self:Control(anchor, rect) self.stroke = stroke or 1 self.colors = colors or { 1, 1, 1 } -end) + return self +end function RectangleOutlineClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/ResizableEditControl.lua b/src/Classes/ResizableEditControl.lua index 66a0402e3f..4f5145fc3b 100644 --- a/src/Classes/ResizableEditControl.lua +++ b/src/Classes/ResizableEditControl.lua @@ -6,14 +6,17 @@ local m_max = math.max local m_min = math.min -local ResizableEditClass = newClass("ResizableEditControl", "EditControl", function(self, anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) - self.EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) +---@class ResizableEditControl: EditControl +local ResizableEditClass = newClass("ResizableEditControl", "EditControl") + +function ResizableEditClass:ResizableEditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) + self:EditControl(anchor, rect, init, prompt, filter, limit, changeFunc, lineHeight, allowZoom, clearable) local x, y, width, height, minWidth, minHeight, maxWidth, maxHeight = unpack(rect) self.minHeight = minHeight or height self.maxHeight = maxHeight or height self.minWidth = minWidth or width self.maxWidth = maxWidth or width - self.controls.draggerHeight = new("DraggerControl", {"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) + self.controls.draggerHeight = new("DraggerControl"):DraggerControl({"BOTTOMRIGHT", self, "BOTTOMRIGHT"}, {7, 7, 14, 14}, "//", nil, nil, function (position) -- onRightClick if (self.height ~= self.minHeight) or (self.width ~= self.minWidth) then self:SetWidth(self.minWidth) @@ -24,7 +27,9 @@ local ResizableEditClass = newClass("ResizableEditControl", "EditControl", funct end end) self.protected = false -end) + return self +end + function ResizableEditClass:Draw(viewPort, noTooltip) self:SetBoundedDrag(self) self.EditControl:Draw(viewPort, noTooltip) diff --git a/src/Classes/ScrollBarControl.lua b/src/Classes/ScrollBarControl.lua index 7dfc416e9e..145fb94bfd 100644 --- a/src/Classes/ScrollBarControl.lua +++ b/src/Classes/ScrollBarControl.lua @@ -8,8 +8,11 @@ local m_max = math.max local m_ceil = math.ceil local m_floor = math.floor -local ScrollBarClass = newClass("ScrollBarControl", "Control", function(self, anchor, rect, step, dir, autoHide) - self.Control(anchor, rect) +---@class ScrollBarControl: Control +local ScrollBarClass = newClass("ScrollBarControl", "Control") + +function ScrollBarClass:ScrollBarControl(anchor, rect, step, dir, autoHide) + self:Control(anchor, rect) self.step = step or self.width * 2 self.dir = dir or "VERTICAL" self.offset = 0 @@ -19,7 +22,8 @@ local ScrollBarClass = newClass("ScrollBarControl", "Control", function(self, an return self.enabled end end -end) + return self +end function ScrollBarClass:SetContentDimension(conDim, viewDim) self.conDim = conDim diff --git a/src/Classes/SearchHost.lua b/src/Classes/SearchHost.lua index 60a65e6408..ceac2b6fe4 100644 --- a/src/Classes/SearchHost.lua +++ b/src/Classes/SearchHost.lua @@ -4,12 +4,16 @@ -- Search host -- -local SearchHostClass = newClass("SearchHost", function(self, listAccessor, valueAccessor) +---@class SearchHost +local SearchHostClass = newClass("SearchHost") + +function SearchHostClass:SearchHost(listAccessor, valueAccessor) self.searchListAccessor = listAccessor self.valueAccessor = valueAccessor self.searchTerm = "" self.searchInfos = {} -end) + return self +end local function splitWords(s) local words = {} diff --git a/src/Classes/SectionControl.lua b/src/Classes/SectionControl.lua index 45e1498d2e..e0acb6fd21 100644 --- a/src/Classes/SectionControl.lua +++ b/src/Classes/SectionControl.lua @@ -4,10 +4,14 @@ -- Section box with label -- -local SectionClass = newClass("SectionControl", "Control", function(self, anchor, rect, label) - self.Control(anchor, rect) +---@class SectionControl: Control +local SectionClass = newClass("SectionControl", "Control") + +function SectionClass:SectionControl(anchor, rect, label) + self:Control(anchor, rect) self.label = label -end) + return self +end function SectionClass:Draw() local x, y = self:GetPos() diff --git a/src/Classes/SharedItemListControl.lua b/src/Classes/SharedItemListControl.lua index b7605b61dc..a4891b368f 100644 --- a/src/Classes/SharedItemListControl.lua +++ b/src/Classes/SharedItemListControl.lua @@ -7,19 +7,23 @@ local pairs = pairs local t_insert = table.insert local t_remove = table.remove -local SharedItemListClass = newClass("SharedItemListControl", "ListControl", function(self, anchor, rect, itemsTab, forceTooltip) - self.ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemList, forceTooltip) +---@class SharedItemListControl: ListControl +local SharedItemListClass = newClass("SharedItemListControl", "ListControl") + +function SharedItemListClass:SharedItemListControl(anchor, rect, itemsTab, forceTooltip) + self:ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemList, forceTooltip) self.itemsTab = itemsTab self.label = "^7Shared items:" self.defaultText = "^x7F7F7FThis is a list of items that will be shared between all of\nyour builds.\nYou can add items to this list by dragging them from\none of the other lists." self.dragTargetList = { } - self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end -end) + return self +end function SharedItemListClass:GetRowValue(column, index, item) if column == 1 then @@ -44,7 +48,7 @@ end function SharedItemListClass:ReceiveDrag(type, value, source) if type == "Item" then local rawItem = { raw = value:BuildRaw() } - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) if not value.id then newItem:NormaliseQuality() end diff --git a/src/Classes/SharedItemSetListControl.lua b/src/Classes/SharedItemSetListControl.lua index c24932a705..ba604874c7 100644 --- a/src/Classes/SharedItemSetListControl.lua +++ b/src/Classes/SharedItemSetListControl.lua @@ -8,37 +8,41 @@ local t_remove = table.remove local m_max = math.max local s_format = string.format -local SharedItemSetListClass = newClass("SharedItemSetListControl", "ListControl", function(self, anchor, rect, itemsTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemSetList) +---@class SharedItemSetListControl: ListControl +local SharedItemSetListClass = newClass("SharedItemSetListControl", "ListControl") + +function SharedItemSetListClass:SharedItemSetListControl(anchor, rect, itemsTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, main.sharedItemSetList) self.itemsTab = itemsTab self.defaultText = "^x7F7F7FThis is a list of item sets that will be shared\nbetween all of your builds.\nYou can add sets to this list by dragging them\nfrom the build's set list." - self.controls.delete = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSet(self.selValue) end) self.controls.rename.enabled = function() return self.selValue ~= nil end -end) + return self +end function SharedItemSetListClass:RenameSet(sharedItemSet) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this item set:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, sharedItemSet.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this item set:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, sharedItemSet.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() sharedItemSet.title = controls.edit.buf self.itemsTab.modFlag = true main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 100, sharedItemSet.title and "Rename" or "Set Name", controls, "save", "edit") @@ -82,7 +86,7 @@ function SharedItemSetListClass:ReceiveDrag(type, value, source) if slot.selItemId ~= 0 then local item = self.itemsTab.items[slot.selItemId] local rawItem = { raw = item:BuildRaw() } - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) if not value.id then newItem:NormaliseQuality() end diff --git a/src/Classes/SkillListControl.lua b/src/Classes/SkillListControl.lua index c820ce6cd6..13237af9bd 100644 --- a/src/Classes/SkillListControl.lua +++ b/src/Classes/SkillListControl.lua @@ -26,17 +26,20 @@ local slot_map = { ["Belt"] = { icon = NewImageHandle(), path = "Assets/icon_belt.png" }, } -local SkillListClass = newClass("SkillListControl", "ListControl", function(self, anchor, rect, skillsTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.socketGroupList) +---@class SkillListControl: ListControl +local SkillListClass = newClass("SkillListControl", "ListControl") + +function SkillListClass:SkillListControl(anchor, rect, skillsTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.socketGroupList) self.skillsTab = skillsTab self.label = "^7Socket Groups:" - self.controls.delete = new("ButtonControl", {"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOPRIGHT"}, {0, -2, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil and self.selValue.source == nil end - self.controls.deleteAll = new("ButtonControl", {"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() + self.controls.deleteAll = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.delete,"LEFT"}, {-4, 0, 70, 18}, "Delete All", function() main:OpenConfirmPopup("Delete All", "Are you sure you want to delete all socket groups in this build?", "Delete", function() wipeTable(self.list) skillsTab:RebuildImbuedSupportBySlot() @@ -50,11 +53,11 @@ local SkillListClass = newClass("SkillListControl", "ListControl", function(self self.controls.deleteAll.enabled = function() return #self.list > 0 end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 60, 18}, "New", function() - local newGroup = { - label = "", - enabled = true, - gemList = { } + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.deleteAll,"LEFT"}, {-4, 0, 60, 18}, "New", function() + local newGroup = { + label = "", + enabled = true, + gemList = { } } t_insert(self.list, newGroup) self.selIndex = #self.list @@ -67,7 +70,8 @@ local SkillListClass = newClass("SkillListControl", "ListControl", function(self for k, x in pairs(slot_map) do x.icon:Load(x.path) end -end) + return self +end function SkillListClass:GetRowValue(column, index, socketGroup) if column == 1 then diff --git a/src/Classes/SkillSetListControl.lua b/src/Classes/SkillSetListControl.lua index c8208c476d..a9d181aa60 100644 --- a/src/Classes/SkillSetListControl.lua +++ b/src/Classes/SkillSetListControl.lua @@ -8,10 +8,13 @@ local t_remove = table.remove local m_max = math.max local s_format = string.format -local SkillSetListClass = newClass("SkillSetListControl", "ListControl", function(self, anchor, rect, skillsTab) - self.ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList) +---@class SkillSetListControl: ListControl +local SkillSetListClass = newClass("SkillSetListControl", "ListControl") + +function SkillSetListClass:SkillSetListControl(anchor, rect, skillsTab) + self:ListControl(anchor, rect, 16, "VERTICAL", true, skillsTab.skillSetOrderList) self.skillsTab = skillsTab - self.controls.copy = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() + self.controls.copy = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {2, -4, 60, 18}, "Copy", function() local skillSet = skillsTab.skillSets[self.selValue] local newSkillSet = copyTable(skillSet, true) newSkillSet.socketGroupList = { } @@ -33,30 +36,31 @@ local SkillSetListClass = newClass("SkillSetListControl", "ListControl", functio self.controls.copy.enabled = function() return self.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex, self.selValue) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end - self.controls.rename = new("ButtonControl", {"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self,"TOP"}, {-2, -4, 60, 18}, "Rename", function() self:RenameSet(skillsTab.skillSets[self.selValue]) end) self.controls.rename.enabled = function() return self.selValue ~= nil end - self.controls.new = new("ButtonControl", {"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"RIGHT",self.controls.rename,"LEFT"}, {-4, 0, 60, 18}, "New", function() self:RenameSet(skillsTab:NewSkillSet(), true) end) -end) + return self +end function SkillSetListClass:RenameSet(skillSet, addOnName) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this skill set:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, skillSet.title, nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this skill set:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, skillSet.title, nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() skillSet.title = controls.edit.buf self.skillsTab.modFlag = true if addOnName then @@ -69,7 +73,7 @@ function SkillSetListClass:RenameSet(skillSet, addOnName) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if addOnName then self.skillsTab.skillSets[skillSet.id] = nil end diff --git a/src/Classes/SkillsTab.lua b/src/Classes/SkillsTab.lua index 8c4644c701..51f33f86c0 100644 --- a/src/Classes/SkillsTab.lua +++ b/src/Classes/SkillsTab.lua @@ -75,10 +75,14 @@ local sortGemTypeList = { { label = "Effective Hit Pool", type = "TotalEHP" }, } -local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Control", function(self, build) - self.UndoHandler() - self.ControlHost() - self.Control() +---@class SkillsTab: UndoHandler, ControlHost, Control +local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Control") + +---@param build Build +function SkillsTabClass:SkillsTab(build) + self:UndoHandler() + self:ControlHost() + self:Control() self.build = build @@ -92,7 +96,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.defaultGemQuality = main.defaultGemQuality -- Set selector - self.controls.setSelect = new("DropDownControl", { "TOPLEFT", self, "TOPLEFT" }, { 76, 8, 210, 20 }, nil, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", self, "TOPLEFT" }, { 76, 8, 210, 20 }, nil, function(index, value) self:SetActiveSkillSet(self.skillSetOrderList[index]) self:AddUndoState() end) @@ -100,14 +104,14 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.setSelect.enabled = function() return #self.skillSetOrderList > 1 end - self.controls.setLabel = new("LabelControl", { "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Skill set:") - self.controls.setManage = new("ButtonControl", { "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() + self.controls.setLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.setSelect, "LEFT" }, { -2, 0, 0, 16 }, "^7Skill set:") + self.controls.setManage = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.setSelect, "RIGHT" }, { 4, 0, 90, 20 }, "Manage...", function() self:OpenSkillSetManagePopup() end) -- Socket group list - self.controls.groupList = new("SkillListControl", { "TOPLEFT", self, "TOPLEFT" }, { 20, 54, 360, 300 }, self) - self.controls.groupTip = new("LabelControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, + self.controls.groupList = new("SkillListControl"):SkillListControl({ "TOPLEFT", self, "TOPLEFT" }, { 20, 54, 360, 300 }, self) + self.controls.groupTip = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, 8, 0, 14 }, [[ ^7Usage Tips: - You can copy/paste socket groups using Ctrl+C and Ctrl+V. @@ -120,14 +124,14 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont -- Gem options local optionInputsX = 170 local optionInputsY = 45 - self.controls.optionSection = new("SectionControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 156 }, "Gem Options") - self.controls.sortGemsByDPS = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 70, 20 }, "Sort gems by DPS:", function(state) + self.controls.optionSection = new("SectionControl"):SectionControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { 0, optionInputsY + 50, 360, 156 }, "Gem Options") + self.controls.sortGemsByDPS = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 70, 20 }, "Sort gems by DPS:", function(state) self.sortGemsByDPS = state end, nil, true) - self.controls.sortGemsByDPSFieldControl = new("DropDownControl", { "LEFT", self.controls.sortGemsByDPS, "RIGHT" }, { 10, 0, 140, 20 }, sortGemTypeList, function(index, value) + self.controls.sortGemsByDPSFieldControl = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.sortGemsByDPS, "RIGHT" }, { 10, 0, 140, 20 }, sortGemTypeList, function(index, value) self.sortGemsByDPSField = value.type end) - self.controls.defaultLevel = new("DropDownControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 94, 170, 20 }, defaultGemLevelList, function(index, value) + self.controls.defaultLevel = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 94, 170, 20 }, defaultGemLevelList, function(index, value) self.defaultGemLevel = value.gemLevel end) self.controls.defaultLevel.tooltipFunc = function(tooltip, mode, index, value) @@ -136,36 +140,36 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont tooltip:AddLine(16, "^7" .. value.description) end end - self.controls.defaultLevelLabel = new("LabelControl", { "RIGHT", self.controls.defaultLevel, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem level:") - self.controls.defaultQuality = new("EditControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 118, 60, 20 }, nil, nil, "%D", 2, function(buf) + self.controls.defaultLevelLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.defaultLevel, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem level:") + self.controls.defaultQuality = new("EditControl"):EditControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 118, 60, 20 }, nil, nil, "%D", 2, function(buf) self.defaultGemQuality = m_min(tonumber(buf) or 0, 23) end) - self.controls.defaultQualityLabel = new("LabelControl", { "RIGHT", self.controls.defaultQuality, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem quality:") - self.controls.showSupportGemTypes = new("DropDownControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 142, 170, 20 }, showSupportGemTypeList, function(index, value) + self.controls.defaultQualityLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.defaultQuality, "LEFT" }, { -4, 0, 0, 16 }, "^7Default gem quality:") + self.controls.showSupportGemTypes = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 142, 170, 20 }, showSupportGemTypeList, function(index, value) self.showSupportGemTypes = value.show end) - self.controls.showSupportGemTypesLabel = new("LabelControl", { "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") - self.controls.showLegacyGems = new("CheckBoxControl", { "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) + self.controls.showSupportGemTypesLabel = new("LabelControl"):LabelControl({ "RIGHT", self.controls.showSupportGemTypes, "LEFT" }, { -4, 0, 0, 16 }, "^7Show support gems:") + self.controls.showLegacyGems = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.groupList, "BOTTOMLEFT" }, { optionInputsX, optionInputsY + 166, 20 }, "^7Show legacy gems:", function(state) self.showLegacyGems = state end) -- Socket group details if main.portraitMode then - self.anchorGroupDetail = new("Control", { "TOPLEFT", self.controls.optionSection, "BOTTOMLEFT" }, { 0, 20, 0, 0 }) + self.anchorGroupDetail = new("Control"):Control({ "TOPLEFT", self.controls.optionSection, "BOTTOMLEFT" }, { 0, 20, 0, 0 }) else - self.anchorGroupDetail = new("Control", { "TOPLEFT", self.controls.groupList, "TOPRIGHT" }, { 20, 0, 0, 0 }) + self.anchorGroupDetail = new("Control"):Control({ "TOPLEFT", self.controls.groupList, "TOPRIGHT" }, { 20, 0, 0, 0 }) end self.anchorGroupDetail.shown = function() return self.displayGroup ~= nil end - self.controls.groupLabel = new("EditControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 0, 380, 20 }, nil, "Label", "%c", 50, function(buf) + self.controls.groupLabel = new("EditControl"):EditControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 0, 380, 20 }, nil, "Label", "%c", 50, function(buf) self.displayGroup.label = buf self:ProcessSocketGroup(self.displayGroup) self:AddUndoState() self.build.buildFlag = true end) - self.controls.groupSlotLabel = new("LabelControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") - self.controls.groupSlot = new("DropDownControl", { "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) + self.controls.groupSlotLabel = new("LabelControl"):LabelControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 0, 30, 0, 16 }, "^7Socketed in:") + self.controls.groupSlot = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.anchorGroupDetail, "TOPLEFT" }, { 85, 28, 130, 20 }, groupSlotDropList, function(index, value) -- maintain imbued support to new slot if self.imbuedSupportBySlot[self.displayGroup.slot] and self.displayGroup.imbuedSupport then if value.slotName and not self.imbuedSupportBySlot[value.slotName] then @@ -200,12 +204,12 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.groupSlot.enabled = function() return self.displayGroup.source == nil end - self.controls.groupEnabled = new("CheckBoxControl", { "LEFT", self.controls.groupSlot, "RIGHT" }, { 70, 0, 20 }, "Enabled:", function(state) + self.controls.groupEnabled = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.groupSlot, "RIGHT" }, { 70, 0, 20 }, "Enabled:", function(state) self.displayGroup.enabled = state self:AddUndoState() self.build.buildFlag = true end) - self.controls.includeInFullDPS = new("CheckBoxControl", { "LEFT", self.controls.groupEnabled, "RIGHT" }, { 145, 0, 20 }, "Include in Full DPS:", function(state) + self.controls.includeInFullDPS = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.groupEnabled, "RIGHT" }, { 145, 0, 20 }, "Include in Full DPS:", function(state) self.displayGroup.includeInFullDPS = state self:AddUndoState() self.build.buildFlag = true @@ -217,8 +221,8 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont -- buildFlag to true triggers the reload/run the CalcSetup to add on the support -- the last var in the GemSelectControl init, the true, sets imbuedSelect to true which sets the level to 1 and support filtering self.imbuedSupportBySlot = { } - self.controls.imbuedSupportLabel = new("LabelControl", { "LEFT", self.controls.groupSlotLabel, "LEFT" }, { 86, 28, 0, 16 }, colorCodes.CRAFTED.."Imbued Support:") - self.controls.imbuedSupport = new("GemSelectControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, gemMatch, slotName) + self.controls.imbuedSupportLabel = new("LabelControl"):LabelControl({ "LEFT", self.controls.groupSlotLabel, "LEFT" }, { 86, 28, 0, 16 }, colorCodes.CRAFTED.."Imbued Support:") + self.controls.imbuedSupport = new("GemSelectControl"):GemSelectControl({ "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 8, 0, 250, 20 }, self, 1, function(gemData, _, _, gemMatch, slotName) local targetSlot = slotName or (self.displayGroup and self.displayGroup.slot) if not targetSlot then return @@ -256,7 +260,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.imbuedSupportLabel.shown = function() -- don't show imbued for skills from items return not self.displayGroup.source end - self.controls.imbuedSupportClear = new("ButtonControl", { "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 260, 0, 20, 20}, "x", function() + self.controls.imbuedSupportClear = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.imbuedSupportLabel, "RIGHT" }, { 260, 0, 20, 20}, "x", function() self.controls.imbuedSupport.gemId = nil self.controls.imbuedSupport:SetText("") self.controls.imbuedSupport:gemChangeFunc(nil) @@ -266,11 +270,11 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont end self.controls.imbuedSupportClear.tooltipText = "Remove this imbued support." - self.controls.groupCountLabel = new("LabelControl", { "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") + self.controls.groupCountLabel = new("LabelControl"):LabelControl({ "LEFT", self.controls.includeInFullDPS, "RIGHT" }, { 16, 0, 0, 16 }, "Count:") self.controls.groupCountLabel.shown = function() return self.displayGroup.source ~= nil end - self.controls.groupCount = new("EditControl", { "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) + self.controls.groupCount = new("EditControl"):EditControl({ "LEFT", self.controls.groupCountLabel, "RIGHT" }, { 4, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) self.displayGroup.groupCount = tonumber(buf) or 1 self:AddUndoState() self.build.buildFlag = true @@ -278,7 +282,7 @@ local SkillsTabClass = newClass("SkillsTab", "UndoHandler", "ControlHost", "Cont self.controls.groupCount.shown = function() return self.displayGroup.source ~= nil end - self.controls.sourceNote = new("LabelControl", { "TOPLEFT", self.controls.groupSlotLabel, "TOPLEFT" }, { 0, 30, 0, 16 }) + self.controls.sourceNote = new("LabelControl"):LabelControl({ "TOPLEFT", self.controls.groupSlotLabel, "TOPLEFT" }, { 0, 30, 0, 16 }) self.controls.sourceNote.shown = function() return self.displayGroup.source ~= nil end @@ -315,7 +319,7 @@ will automatically apply to the skill.]] end -- Scroll bar - self.controls.scrollBarH = new("ScrollBarControl", nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) + self.controls.scrollBarH = new("ScrollBarControl"):ScrollBarControl(nil, {0, 0, 0, 18}, 100, "HORIZONTAL", true) -- Initialise skill sets self.skillSets = { } @@ -324,15 +328,16 @@ will automatically apply to the skill.]] self:SetActiveSkillSet(1) -- Skill gem slots - self.anchorGemSlots = new("Control", {"TOPLEFT",self.anchorGroupDetail,"TOPLEFT"}, {0, 28 + 28 + 16 + 28, 0, 0}) + self.anchorGemSlots = new("Control"):Control({"TOPLEFT",self.anchorGroupDetail,"TOPLEFT"}, {0, 28 + 28 + 16 + 28, 0, 0}) self.gemSlots = { } self:CreateGemSlot(1) - self.controls.gemNameHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].nameSpec, "TOPLEFT"}, {0, -2, 0, 16}, "^7Gem name:") - self.controls.gemLevelHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") - self.controls.gemQualityHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") - self.controls.gemEnableHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") - self.controls.gemCountHeader = new("LabelControl", {"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") -end) + self.controls.gemNameHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].nameSpec, "TOPLEFT"}, {0, -2, 0, 16}, "^7Gem name:") + self.controls.gemLevelHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].level, "TOPLEFT"}, {0, -2, 0, 16}, "^7Level:") + self.controls.gemQualityHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].quality, "TOPLEFT"}, {0, -2, 0, 16}, "^7Quality:") + self.controls.gemEnableHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].enabled, "TOPLEFT"}, {-16, -2, 0, 16}, "^7Enabled:") + self.controls.gemCountHeader = new("LabelControl"):LabelControl({"BOTTOMLEFT", self.gemSlots[1].count, "TOPLEFT"}, {8, -2, 0, 16}, "^7Count:") + return self +end function SkillsTabClass:LoadSkill(node, skillSetId) @@ -658,7 +663,7 @@ function SkillsTabClass:CreateGemSlot(index) self.build.buildFlag = true end -- Delete gem - slot.delete = new("ButtonControl", nil, {0, 0, 20, 20}, "x", function() + slot.delete = new("ButtonControl"):ButtonControl(nil, {0, 0, 20, 20}, "x", function() return deleteGem() end) if index == 1 then @@ -679,7 +684,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Delete"] = slot.delete -- Gem name specification - slot.nameSpec = new("GemSelectControl", { "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo, focusLost, bufMatchesGem) + slot.nameSpec = new("GemSelectControl"):GemSelectControl({ "LEFT", slot.delete, "RIGHT" }, { 2, 0, 300, 20 }, self, index, function(gemId, addUndo, focusLost, bufMatchesGem) if not self.displayGroup then return end @@ -735,7 +740,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Name"] = slot.nameSpec -- Gem level - slot.level = new("EditControl", { "LEFT", slot.nameSpec, "RIGHT" }, { 2, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) + slot.level = new("EditControl"):EditControl({ "LEFT", slot.nameSpec, "RIGHT" }, { 2, 0, 60, 20 }, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } @@ -757,7 +762,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Level"] = slot.level -- Gem quality - slot.quality = new("EditControl", {"LEFT",slot.level,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + slot.quality = new("EditControl"):EditControl({"LEFT",slot.level,"RIGHT"}, {2, 0, 60, 20}, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } @@ -839,7 +844,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Quality"] = slot.quality -- Enable gem - slot.enabled = new("CheckBoxControl", {"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) + slot.enabled = new("CheckBoxControl"):CheckBoxControl({"LEFT",slot.quality,"RIGHT"}, {18, 0, 20}, nil, function(state) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, enableGlobal2 = true, count = 1, new = true } @@ -878,7 +883,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Enable"] = slot.enabled -- Count gem - slot.count = new("EditControl", {"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) + slot.count = new("EditControl"):EditControl({"LEFT",slot.enabled,"RIGHT"}, {18, 0, 60, 20}, nil, nil, "%D", 2, function(buf) local gemInstance = self.displayGroup.gemList[index] if not gemInstance then gemInstance = { nameSpec = "", level = self.defaultGemLevel or 20, quality = self.defaultGemQuality or 0, enabled = true, enableGlobal1 = true, count = 1, new = true } @@ -919,14 +924,14 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."Count"] = slot.count -- Parser/calculator error message - slot.errMsg = new("LabelControl", {"LEFT",slot.count,"RIGHT"}, {2, 2, 0, 16}, function() + slot.errMsg = new("LabelControl"):LabelControl({"LEFT",slot.count,"RIGHT"}, {2, 2, 0, 16}, function() local gemInstance = self.displayGroup and self.displayGroup.gemList[index] return "^1"..(gemInstance and gemInstance.errMsg or "") end) self.controls["gemSlot"..index.."ErrMsg"] = slot.errMsg -- Enable global-effect skill 1 - slot.enableGlobal1 = new("CheckBoxControl", {"TOPLEFT",slot.delete,"BOTTOMLEFT"}, {0, 2, 20}, "", function(state) + slot.enableGlobal1 = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",slot.delete,"BOTTOMLEFT"}, {0, 2, 20}, "", function(state) local gemInstance = self.displayGroup.gemList[index] gemInstance.enableGlobal1 = state self:AddUndoState() @@ -945,7 +950,7 @@ function SkillsTabClass:CreateGemSlot(index) self.controls["gemSlot"..index.."EnableGlobal1"] = slot.enableGlobal1 -- Enable global-effect skill 2 - slot.enableGlobal2 = new("CheckBoxControl", {"LEFT",slot.enableGlobal1,"RIGHT",true}, {0, 0, 20}, "", function(state) + slot.enableGlobal2 = new("CheckBoxControl"):CheckBoxControl({"LEFT",slot.enableGlobal1,"RIGHT",true}, {0, 0, 20}, "", function(state) local gemInstance = self.displayGroup.gemList[index] gemInstance.enableGlobal2 = state self:AddUndoState() @@ -1289,8 +1294,8 @@ end -- Opens the skill set manager function SkillsTabClass:OpenSkillSetManagePopup() main:OpenPopup(370, 290, "Manage Skill Sets", { - new("SkillSetListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("SkillSetListControl"):SkillSetListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) diff --git a/src/Classes/SliderControl.lua b/src/Classes/SliderControl.lua index 2c3048de48..89dba3e1fc 100644 --- a/src/Classes/SliderControl.lua +++ b/src/Classes/SliderControl.lua @@ -7,14 +7,18 @@ local m_min = math.min local m_max = math.max local m_ceil = math.ceil -local SliderClass = newClass("SliderControl", "Control", "TooltipHost", function(self, anchor, rect, changeFunc, scrollWheelSpeedTbl) - self.Control(anchor, rect) - self.TooltipHost() +---@class SliderControl: Control, TooltipHost +local SliderClass = newClass("SliderControl", "Control", "TooltipHost") + +function SliderClass:SliderControl(anchor, rect, changeFunc, scrollWheelSpeedTbl) + self:Control(anchor, rect) + self:TooltipHost() self.knobSize = self.height - 2 self.val = 0 self.changeFunc = changeFunc self.scrollWheelSpeedTbl = scrollWheelSpeedTbl or { ["SHIFT"] = 0.25, ["CTRL"] = 0.01, ["DEFAULT"] = 0.05 } -end) + return self +end function SliderClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/TextListControl.lua b/src/Classes/TextListControl.lua index 7302a153b9..b9c7f726d5 100644 --- a/src/Classes/TextListControl.lua +++ b/src/Classes/TextListControl.lua @@ -3,10 +3,13 @@ -- Class: Text List -- Simple list control for displaying a block of text -- -local TextListClass = newClass("TextListControl", "Control", "ControlHost", function(self, anchor, rect, columns, list, sectionHeights) - self.Control(anchor, rect) - self.ControlHost() - self.controls.scrollBar = new("ScrollBarControl", {"RIGHT",self,"RIGHT"}, {-1, 0, 18, 0}, 40) +---@class TextListControl: Control, ControlHost +local TextListClass = newClass("TextListControl", "Control", "ControlHost") + +function TextListClass:TextListControl(anchor, rect, columns, list, sectionHeights) + self:Control(anchor, rect) + self:ControlHost() + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"RIGHT",self,"RIGHT"}, {-1, 0, 18, 0}, 40) self.controls.scrollBar.height = function() local width, height = self:GetSize() return height - 2 @@ -14,7 +17,8 @@ local TextListClass = newClass("TextListControl", "Control", "ControlHost", func self.columns = columns or { { x = 0, align = "LEFT" } } self.list = list or { } self.sectionHeights = sectionHeights -end) + return self +end function TextListClass:IsMouseOver() if not self:IsShown() then diff --git a/src/Classes/TimelessJewelListControl.lua b/src/Classes/TimelessJewelListControl.lua index c1a25a720f..8378525b98 100644 --- a/src/Classes/TimelessJewelListControl.lua +++ b/src/Classes/TimelessJewelListControl.lua @@ -9,13 +9,17 @@ local m_min = math.min local m_max = math.max local t_concat = table.concat -local TimelessJewelListControlClass = newClass("TimelessJewelListControl", "ListControl", function(self, anchor, rect, build) +---@class TimelessJewelListControl: ListControl +local TimelessJewelListControlClass = newClass("TimelessJewelListControl", "ListControl") + +function TimelessJewelListControlClass:TimelessJewelListControl(anchor, rect, build) self.build = build self.sharedList = self.build.timelessData.sharedResults or { } self.list = self.build.timelessData.searchResults or { } - self.ListControl(anchor, rect, 16, true, false, self.list) + self:ListControl(anchor, rect, 16, true, false, self.list) self.selIndex = nil -end) + return self +end function TimelessJewelListControlClass:Draw(viewPort, noTooltip) self.noTooltip = noTooltip @@ -247,7 +251,7 @@ Passives in radius are Conquered by the Eternal Empire Historic ]] end - local item = new("Item", itemData) + local item = new("Item"):Item(itemData) self.build.itemsTab:AddItem(item, true) self.build.itemsTab:PopulateSlots() self.list[index].label = "^xB2B2B2" .. self.list[index].label diff --git a/src/Classes/TimelessJewelSocketControl.lua b/src/Classes/TimelessJewelSocketControl.lua index b6e8527be1..28494df3c2 100644 --- a/src/Classes/TimelessJewelSocketControl.lua +++ b/src/Classes/TimelessJewelSocketControl.lua @@ -6,11 +6,15 @@ local m_min = math.min -local TimelessJewelSocketClass = newClass("TimelessJewelSocketControl", "DropDownControl", function(self, anchor, rect, list, selFunc, build, socketViewer) - self.DropDownControl(anchor, rect, list, selFunc) +---@class TimelessJewelSocketControl: DropDownControl +local TimelessJewelSocketClass = newClass("TimelessJewelSocketControl", "DropDownControl") + +function TimelessJewelSocketClass:TimelessJewelSocketControl(anchor, rect, list, selFunc, build, socketViewer) + self:DropDownControl(anchor, rect, list, selFunc) self.build = build self.socketViewer = socketViewer -end) + return self +end function TimelessJewelSocketClass:Draw(viewPort, noTooltip) local x, y = self:GetPos() diff --git a/src/Classes/Tooltip.lua b/src/Classes/Tooltip.lua index 26f47c87e4..65f0f0d038 100644 --- a/src/Classes/Tooltip.lua +++ b/src/Classes/Tooltip.lua @@ -40,11 +40,15 @@ for _, recipeName in pairs(recipeNames) do recipeImages[recipeName]:Load("TreeData/" .. recipeName .. ".png", "CLAMP") end -local TooltipClass = newClass("Tooltip", function(self) +---@class Tooltip +local TooltipClass = newClass("Tooltip") + +function TooltipClass:Tooltip() self.lines = { } self.blocks = { } self:Clear() -end) + return self +end function TooltipClass:Clear(clearUpdateParams) wipeTable(self.lines) diff --git a/src/Classes/TooltipHost.lua b/src/Classes/TooltipHost.lua index bd8db5231d..42a9c3e0e9 100644 --- a/src/Classes/TooltipHost.lua +++ b/src/Classes/TooltipHost.lua @@ -3,10 +3,14 @@ -- Class: Tooltip Host -- Tooltip host -- -local TooltipHostClass = newClass("TooltipHost", function(self, tooltipText) - self.tooltip = new("Tooltip") +---@class TooltipHost +local TooltipHostClass = newClass("TooltipHost") + +function TooltipHostClass:TooltipHost(tooltipText) + self.tooltip = new("Tooltip"):Tooltip() self.tooltipText = tooltipText -end) + return self +end function TooltipHostClass:DrawTooltip(x, y, width, height, viewPort, ...) if self.tooltipFunc then diff --git a/src/Classes/TradeQuery.lua b/src/Classes/TradeQuery.lua index 9e1308bfb9..3d9a71fcc6 100644 --- a/src/Classes/TradeQuery.lua +++ b/src/Classes/TradeQuery.lua @@ -18,7 +18,10 @@ local s_format = string.format local baseSlots = { "Weapon 1", "Weapon 2", "Weapon 1 Swap", "Weapon 2 Swap", "Helmet", "Body Armour", "Gloves", "Boots", "Amulet", "Ring 1", "Ring 2", "Ring 3", "Belt", "Flask 1", "Flask 2", "Flask 3", "Flask 4", "Flask 5" } -local TradeQueryClass = newClass("TradeQuery", function(self, itemsTab) +---@class TradeQuery +local TradeQueryClass = newClass("TradeQuery") + +function TradeQueryClass:TradeQuery(itemsTab) self.itemsTab = itemsTab self.itemsTab.leagueDropList = { } self.totalPrice = { } @@ -49,14 +52,15 @@ local TradeQueryClass = newClass("TradeQuery", function(self, itemsTab) -- last query for each row self.lastQueries = {} - self.tradeQueryRequests = new("TradeQueryRequests") + self.tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() main.onFrameFuncs["TradeQueryRequests"] = function() self.tradeQueryRequests:ProcessQueue() end -- set self.hostName = "https://www.pathofexile.com/" -end) + return self +end ---Fetch currency short-names from Poe API (used for PoeNinja price pairing) ---@param callback fun() @@ -224,7 +228,7 @@ end -- Opens the item pricing popup function TradeQueryClass:PriceItem() - self.tradeQueryGenerator = new("TradeQueryGenerator", self) + self.tradeQueryGenerator = new("TradeQueryGenerator"):TradeQueryGenerator(self) main.onFrameFuncs["TradeQueryGenerator"] = function() self.tradeQueryGenerator:OnFrame() end @@ -241,7 +245,7 @@ function TradeQueryClass:PriceItem() local itemSet = self.itemsTab.itemSets[itemSetId] t_insert(newItemList, itemSet.title or "Default") end - self.controls.setSelect = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {pane_margins_horizontal, pane_margins_vertical, 188, row_height}, newItemList, function(index, value) + self.controls.setSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {pane_margins_horizontal, pane_margins_vertical, 188, row_height}, newItemList, function(index, value) self.itemsTab:SetActiveItemSet(self.itemsTab.itemSetOrderList[index]) self.itemsTab:AddUndoState() end) @@ -250,20 +254,20 @@ function TradeQueryClass:PriceItem() return #self.itemsTab.itemSetOrderList > 1 end - self.controls.poesessidButton = new("ButtonControl", {"TOPLEFT", self.controls.setSelect, "TOPLEFT"}, {0, row_height + row_vertical_padding, 188, row_height}, function() return main.POESESSID ~= "" and "^2Session Mode" or colorCodes.WARNING.."No Session Mode" end, function() + self.controls.poesessidButton = new("ButtonControl"):ButtonControl({"TOPLEFT", self.controls.setSelect, "TOPLEFT"}, {0, row_height + row_vertical_padding, 188, row_height}, function() return main.POESESSID ~= "" and "^2Session Mode" or colorCodes.WARNING.."No Session Mode" end, function() local poesessid_controls = {} - poesessid_controls.sessionInput = new("EditControl", nil, {0, 18, 350, 18}, main.POESESSID, nil, "%X", 32) + poesessid_controls.sessionInput = new("EditControl"):EditControl(nil, {0, 18, 350, 18}, main.POESESSID, nil, "%X", 32) poesessid_controls.sessionInput:SetProtected(true) poesessid_controls.sessionInput.placeholder = "Enter your session ID here" poesessid_controls.sessionInput.tooltipText = "You can get this from your web browser's cookies while logged into the Path of Exile website." - poesessid_controls.save = new("ButtonControl", {"TOPRIGHT", poesessid_controls.sessionInput, "TOP"}, {-8, 24, 90, row_height}, "Save", function() + poesessid_controls.save = new("ButtonControl"):ButtonControl({"TOPRIGHT", poesessid_controls.sessionInput, "TOP"}, {-8, 24, 90, row_height}, "Save", function() main.POESESSID = poesessid_controls.sessionInput.buf main:ClosePopup() main:SaveSettings() self:UpdateRealms() end) poesessid_controls.save.enabled = function() return #poesessid_controls.sessionInput.buf == 32 or poesessid_controls.sessionInput.buf == "" end - poesessid_controls.cancel = new("ButtonControl", {"TOPLEFT", poesessid_controls.sessionInput, "TOP"}, {8, 24, 90, row_height}, "Cancel", function() + poesessid_controls.cancel = new("ButtonControl"):ButtonControl({"TOPLEFT", poesessid_controls.sessionInput, "TOP"}, {8, 24, 90, row_height}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(364, 72, "Change session ID", poesessid_controls) @@ -293,7 +297,7 @@ on trade site to work on other leagues and realms)]] "Any (includes offline)" } - self.controls.tradeTypeSelection = new("DropDownControl", { "TOPLEFT", self.controls.poesessidButton, "BOTTOMLEFT" }, + self.controls.tradeTypeSelection = new("DropDownControl"):DropDownControl({ "TOPLEFT", self.controls.poesessidButton, "BOTTOMLEFT" }, { 0, row_vertical_padding, 188, row_height }, self.tradeTypes, function(index, value) self.tradeTypeIndex = index end) @@ -302,7 +306,7 @@ on trade site to work on other leagues and realms)]] -- Fetches Box self.maxFetchPerSearchDefault = 2 - self.controls.fetchCountEdit = new("EditControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-12, 19, 154, row_height}, "", "Fetch Pages", "%D", 3, function(buf) + self.controls.fetchCountEdit = new("EditControl"):EditControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-12, 19, 154, row_height}, "", "Fetch Pages", "%D", 3, function(buf) self.maxFetchPages = m_min(m_max(tonumber(buf) or self.maxFetchPerSearchDefault, 1), 10) self.tradeQueryRequests.maxFetchPerSearch = 10 * self.maxFetchPages self.controls.fetchCountEdit.focusValue = self.maxFetchPages @@ -326,7 +330,7 @@ on trade site to work on other leagues and realms)]] self.statSortSelectionList = { } initStatSortSelectionList(self.statSortSelectionList) end - self.controls.StatWeightMultipliersButton = new("ButtonControl", {"TOPRIGHT", self.controls.fetchCountEdit, "BOTTOMRIGHT"}, {0, row_vertical_padding, 150, row_height}, "^7Adjust search weights", function() + self.controls.StatWeightMultipliersButton = new("ButtonControl"):ButtonControl({"TOPRIGHT", self.controls.fetchCountEdit, "BOTTOMRIGHT"}, {0, row_vertical_padding, 150, row_height}, "^7Adjust search weights", function() self.itemsTab.modFlag = true self:SetStatWeights() end) @@ -351,7 +355,7 @@ on trade site to work on other leagues and realms)]] self.sortModes.Price, self.sortModes.Weight, } - self.controls.itemSortSelection = new("DropDownControl", {"TOPRIGHT", self.controls.StatWeightMultipliersButton, "TOPLEFT"}, {-8, 0, 170, row_height}, self.itemSortSelectionList, function(index, value) + self.controls.itemSortSelection = new("DropDownControl"):DropDownControl({"TOPRIGHT", self.controls.StatWeightMultipliersButton, "TOPLEFT"}, {-8, 0, 170, row_height}, self.itemSortSelectionList, function(index, value) self.pbItemSortSelectionIndex = index for row_idx, _ in pairs(self.resultTbl) do self:UpdateControlsWithItems(row_idx) @@ -366,11 +370,11 @@ Lowest Price - Sorts from lowest to highest price of retrieved items Highest Weight - Displays the order retrieved from trade]] -- avoid calling selFunc to avoid updating controls before they are initialised self.controls.itemSortSelection:SetSel(self.pbItemSortSelectionIndex, true) - self.controls.itemSortSelectionLabel = new("LabelControl", {"TOPRIGHT", self.controls.itemSortSelection, "TOPLEFT"}, {-4, 0, 56, 16}, "^7Sort By:") + self.controls.itemSortSelectionLabel = new("LabelControl"):LabelControl({"TOPRIGHT", self.controls.itemSortSelection, "TOPLEFT"}, {-4, 0, 56, 16}, "^7Sort By:") -- Realm selection - self.controls.realmLabel = new("LabelControl", {"LEFT", self.controls.setSelect, "RIGHT"}, {18, 0, 20, row_height - 4}, "^7Realm:") - self.controls.realm = new("DropDownControl", {"LEFT", self.controls.realmLabel, "RIGHT"}, {6, 0, 150, row_height}, self.realmDropList, function(index, value) + self.controls.realmLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.setSelect, "RIGHT"}, {18, 0, 20, row_height - 4}, "^7Realm:") + self.controls.realm = new("DropDownControl"):DropDownControl({"LEFT", self.controls.realmLabel, "RIGHT"}, {6, 0, 150, row_height}, self.realmDropList, function(index, value) self.pbRealmIndex = index self.pbRealm = self.realmIds[value] local function setLeagueDropList() @@ -410,8 +414,8 @@ Highest Weight - Displays the order retrieved from trade]] end -- League selection - self.controls.leagueLabel = new("LabelControl", {"TOPRIGHT", self.controls.realmLabel, "TOPRIGHT"}, {0, row_height + row_vertical_padding, 20, row_height - 4}, "^7League:") - self.controls.league = new("DropDownControl", {"LEFT", self.controls.leagueLabel, "RIGHT"}, {6, 0, 150, row_height}, self.itemsTab.leagueDropList, function(index, value) + self.controls.leagueLabel = new("LabelControl"):LabelControl({"TOPRIGHT", self.controls.realmLabel, "TOPRIGHT"}, {0, row_height + row_vertical_padding, 20, row_height - 4}, "^7League:") + self.controls.league = new("DropDownControl"):DropDownControl({"LEFT", self.controls.leagueLabel, "RIGHT"}, {6, 0, 150, row_height}, self.itemsTab.leagueDropList, function(index, value) self.pbLeagueIndex = index self.pbLeague = value self:SetCurrencyConversionButton() @@ -464,7 +468,7 @@ Highest Weight - Displays the order retrieved from trade]] t_insert(slotTables, { slotName = self.itemsTab.sockets[nodeId].label, nodeId = nodeId }) end - self.controls.sectionAnchor = new("LabelControl", {"LEFT", self.controls.tradeTypeSelection, "LEFT"}, {0, row_vertical_padding + row_height, 0, 0}, "") + self.controls.sectionAnchor = new("LabelControl"):LabelControl({"LEFT", self.controls.tradeTypeSelection, "LEFT"}, {0, row_vertical_padding + row_height, 0, 0}, "") top_pane_alignment_ref = {"TOPLEFT", self.controls.sectionAnchor, "TOPLEFT"} local scrollBarShown = #slotTables > 21 -- clipping starts beyond this -- dynamically hide rows that are above or below the scrollBar @@ -489,7 +493,7 @@ Highest Weight - Displays the order retrieved from trade]] end end - self.controls.otherTradesLabel = new("LabelControl", top_pane_alignment_ref, {0, (#slotTables+1)*(row_height + row_vertical_padding), 100, 16}, "^8Other trades:") + self.controls.otherTradesLabel = new("LabelControl"):LabelControl(top_pane_alignment_ref, {0, (#slotTables+1)*(row_height + row_vertical_padding), 100, 16}, "^8Other trades:") self.controls.otherTradesLabel.shown = function() return hideRowFunc(self, #slotTables+1) end @@ -515,7 +519,7 @@ Highest Weight - Displays the order retrieved from trade]] self.pane_height = (row_height + row_vertical_padding) * effective_row_count + 3 * pane_margins_vertical + row_height / 2 local pane_width = 850 + (scrollBarShown and 25 or 0) - self.controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT", self.controls["StatWeightMultipliersButton"],"TOPRIGHT"}, {0, 25, 18, 0}, 50, "VERTICAL", false) + self.controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT", self.controls["StatWeightMultipliersButton"],"TOPRIGHT"}, {0, 25, 18, 0}, 50, "VERTICAL", false) self.controls.scrollBar.shown = function() return scrollBarShown end local function wipeItemControls() @@ -525,18 +529,18 @@ Highest Weight - Displays the order retrieved from trade]] end end end - self.controls.fullPrice = new("LabelControl", {"BOTTOM", nil, "BOTTOM"}, {0, -row_height - pane_margins_vertical - row_vertical_padding, pane_width - 2 * pane_margins_horizontal, row_height}, "") - self.controls.close = new("ButtonControl", {"BOTTOM", nil, "BOTTOM"}, {0, -pane_margins_vertical, 90, row_height}, "Done", function() + self.controls.fullPrice = new("LabelControl"):LabelControl({"BOTTOM", nil, "BOTTOM"}, {0, -row_height - pane_margins_vertical - row_vertical_padding, pane_width - 2 * pane_margins_horizontal, row_height}, "") + self.controls.close = new("ButtonControl"):ButtonControl({"BOTTOM", nil, "BOTTOM"}, {0, -pane_margins_vertical, 90, row_height}, "Done", function() main:ClosePopup() -- there's a case where if you have a socket(s) allocated, open TradeQuery, close it, dealloc, then open TradeQuery again -- the deallocated socket controls were still showing, so this will remove all dynamically created controls from items wipeItemControls() end) - self.controls.updateCurrencyConversion = new("ButtonControl", {"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {pane_margins_horizontal, -pane_margins_vertical, 240, row_height}, "Get Currency Conversion Rates", function() + self.controls.updateCurrencyConversion = new("ButtonControl"):ButtonControl({"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {pane_margins_horizontal, -pane_margins_vertical, 240, row_height}, "Get Currency Conversion Rates", function() self:PullPoENinjaCurrencyConversion(self.pbLeague) end) - self.controls.pbNotice = new("LabelControl", {"BOTTOMRIGHT", nil, "BOTTOMRIGHT"}, {-row_height - pane_margins_vertical - row_vertical_padding, -pane_margins_vertical, 300, row_height}, "") + self.controls.pbNotice = new("LabelControl"):LabelControl( {"BOTTOMRIGHT", nil, "BOTTOMRIGHT"}, {-row_height - pane_margins_vertical - row_vertical_padding, -pane_margins_vertical, 300, row_height}, "") -- used in PopupDialog:Draw() local function scrollBarFunc() @@ -555,7 +559,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) local sliderController = { index = 1 } local popupHeight = 285 - controls.ListControl = new("TradeStatWeightMultiplierListControl", {"TOPLEFT", nil, "TOPRIGHT"}, {-410, 45, 400, 200}, statList, sliderController) + controls.ListControl = new("TradeStatWeightMultiplierListControl"):TradeStatWeightMultiplierListControl({"TOPLEFT", nil, "TOPRIGHT"}, {-410, 45, 400, 200}, statList, sliderController) for id, stat in pairs(data.powerStatList) do if not stat.ignoreForItems and stat.label ~= "Name" then @@ -571,8 +575,8 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) end end - controls.SliderLabel = new("LabelControl", { "TOPLEFT", nil, "TOPRIGHT" }, {-410, 20, 0, 16}, "^7"..statList[1].stat.label..":") - controls.Slider = new("SliderControl", { "TOPLEFT", controls.SliderLabel, "TOPRIGHT" }, {20, 0, 150, 16}, function(value) + controls.SliderLabel = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPRIGHT" }, {-410, 20, 0, 16}, "^7"..statList[1].stat.label..":") + controls.Slider = new("SliderControl"):SliderControl({ "TOPLEFT", controls.SliderLabel, "TOPRIGHT" }, {20, 0, 150, 16}, function(value) if value == 0 then controls.SliderValue.label = "^7Disabled" statList[sliderController.index].stat.weightMult = 0 @@ -583,7 +587,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) statList[sliderController.index].label = s_format("%.2f : ", 0.01 + value * 0.99)..statList[sliderController.index].stat.label end end) - controls.SliderValue = new("LabelControl", { "TOPLEFT", controls.Slider, "TOPRIGHT" }, {20, 0, 0, 16}, "^7Disabled") + controls.SliderValue = new("LabelControl"):LabelControl({ "TOPLEFT", controls.Slider, "TOPRIGHT" }, {20, 0, 0, 16}, "^7Disabled") controls.Slider.tooltip.realDraw = controls.Slider.tooltip.Draw controls.Slider.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.Slider.val)) @@ -609,7 +613,7 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) end end - controls.finalise = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-90, -10, 80, 20}, "Save", function() + controls.finalise = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {-90, -10, 80, 20}, "Save", function() main:ClosePopup() -- used in ItemsTab to save to xml under TradeSearchWeights node @@ -627,13 +631,13 @@ function TradeQueryClass:SetStatWeights(previousSelectionList) self:UpdateControlsWithItems(row_idx) end end) - controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 0, -10, 80, 20 }, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { 0, -10, 80, 20 }, "Cancel", function() if previousSelectionList and #previousSelectionList > 0 then self.statSortSelectionList = copyTable(previousSelectionList, true) end main:ClosePopup() end) - controls.reset = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, { 90, -10, 80, 20 }, "Reset", function() + controls.reset = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, { 90, -10, 80, 20 }, "Reset", function() local previousSelection = { } if isSameAsDefaultList(self.statSortSelectionList) then previousSelection = copyTable(previousSelectionList, true) @@ -761,7 +765,7 @@ function TradeQueryClass:GetResultEvaluation(row_idx, result_index, calcFunc, ba } table.sort(result.evaluation, function(a, b) return a.weight > b.weight end) else - local item = new("Item", result.item_string) + local item = new("Item"):Item(result.item_string) local output = self:ReduceOutput(calcFunc({ repSlotName = slotName, repItem = item })) local weight = self.tradeQueryGenerator.WeightedRatioOutputs(baseOutput, output, self.statSortSelectionList) @@ -781,7 +785,7 @@ function TradeQueryClass:UpdateDropdownList(row_idx) local pb_index = self.sortedResultTbl[row_idx][result_index].index local result = self.resultTbl[row_idx][pb_index] local price = string.format(" %s(%d %s)", colorCodes["CURRENCY"], result.amount, result.currency) - local item = new("Item", result.item_string) + local item = new("Item"):Item(result.item_string) table.insert(dropdownLabels, colorCodes[item.rarity] .. item.name .. price) end self.controls["resultDropdown".. row_idx].selIndex = 1 @@ -925,7 +929,7 @@ function TradeQueryClass:findValidSlotForWatchersEye() local tmpWE=nil for _,v in ipairs(data.uniques.generated) do if v:find("Watcher's Eye") then - tmpWE= new("Item",v) + tmpWE= new("Item"):Item(v) break end end @@ -946,8 +950,8 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro slotTbl.slotName == "Watcher's Eye" and self:findValidSlotForWatchersEye() or slotTbl.fullName and self.itemsTab.slots[slotTbl.fullName]) -- fullName for Abyssal Sockets local nameColor = slotTbl.unique and colorCodes.UNIQUE or "^7" - controls["name"..row_idx] = new("LabelControl", top_pane_alignment_ref, {0, row_idx*(row_height + row_vertical_padding), 100, row_height - 4}, nameColor..slotTbl.slotName) - controls["bestButton"..row_idx] = new("ButtonControl", { "LEFT", controls["name"..row_idx], "LEFT"}, {100 + 8, 0, 80, row_height}, "Find best", function() + controls["name"..row_idx] = new("LabelControl"):LabelControl(top_pane_alignment_ref, {0, row_idx*(row_height + row_vertical_padding), 100, row_height - 4}, nameColor..slotTbl.slotName) + controls["bestButton"..row_idx] = new("ButtonControl"):ButtonControl({ "LEFT", controls["name"..row_idx], "LEFT"}, {100 + 8, 0, 80, row_height}, "Find best", function() self.tradeQueryGenerator:RequestQuery(activeSlot, { slotTbl = slotTbl, controls = controls, row_idx = row_idx }, self.statSortSelectionList, function(context, query, errMsg) if errMsg then self:SetNotice(context.controls.pbNotice, colorCodes.NEGATIVE .. errMsg) @@ -978,13 +982,13 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro if self.tradeQueryGenerator.lastCopyEldritch or self.tradeQueryGenerator.lastCopyEnchantMode == "Copy Current" then for i, _ in ipairs(items) do - local item = new("Item", items[i].item_string) + local item = new("Item"):Item(items[i].item_string) self.itemsTab:CopyAnointsAndEldritchImplicits(item, true, true, context.slotTbl.slotName) items[i].item_string = item:BuildRaw() end elseif self.tradeQueryGenerator.lastCopyEnchantMode == "Remove" then for i, _ in ipairs(items) do - local item = new("Item", items[i].item_string) + local item = new("Item"):Item(items[i].item_string) item.enchantModLines = {} items[i].item_string = item:BuildRaw() end @@ -1008,7 +1012,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro controls["bestButton"..row_idx].enabled = function() return self.pbLeague end controls["bestButton"..row_idx].tooltipText = "Creates a weighted search to find the highest Stat Value items for this slot." local pbURL - controls["uri"..row_idx] = new("EditControl", { "TOPLEFT", controls["bestButton"..row_idx], "TOPRIGHT"}, {8, 0, 514, row_height}, nil, nil, "^%C\t\n", nil, function(buf) + controls["uri"..row_idx] = new("EditControl"):EditControl({ "TOPLEFT", controls["bestButton"..row_idx], "TOPRIGHT"}, {8, 0, 514, row_height}, nil, nil, "^%C\t\n", nil, function(buf) local subpath = buf:match(self.hostName .. "trade/search/(.+)$") or "" local paths = {} for path in subpath:gmatch("[^/]+") do @@ -1035,7 +1039,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro tooltip:AddLine(16, "Control + click to open in web-browser") end end - controls["priceButton"..row_idx] = new("ButtonControl", { "TOPLEFT", controls["uri"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Price Item", + controls["priceButton"..row_idx] = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls["uri"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Price Item", function() controls["priceButton"..row_idx].label = "Searching..." self.tradeQueryRequests:SearchWithURL(controls["uri"..row_idx].buf, function(items, errMsg, query) @@ -1067,7 +1071,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro local clampItemIndex = function(index) return m_min(m_max(index or 1, 1), self.sortedResultTbl[row_idx] and #self.sortedResultTbl[row_idx] or 1) end - controls["changeButton"..row_idx] = new("ButtonControl", { "LEFT", controls["name"..row_idx], "LEFT"}, {100 + 8, 0, 80, row_height}, "<< Search", function() + controls["changeButton"..row_idx] = new("ButtonControl"):ButtonControl({ "LEFT", controls["name"..row_idx], "LEFT"}, {100 + 8, 0, 80, row_height}, "<< Search", function() self.itemIndexTbl[row_idx] = nil self.sortedResultTbl[row_idx] = nil self.resultTbl[row_idx] = nil @@ -1075,7 +1079,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro self.controls.fullPrice.label = "Total Price: " .. self:GetTotalPriceString() end) controls["changeButton"..row_idx].shown = function() return self.resultTbl[row_idx] end - controls["resultDropdown"..row_idx] = new("DropDownControl", { "TOPLEFT", controls["changeButton"..row_idx], "TOPRIGHT"}, {8, 0, 325, row_height}, {}, function(index) + controls["resultDropdown"..row_idx] = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls["changeButton"..row_idx], "TOPRIGHT"}, {8, 0, 325, row_height}, {}, function(index) self.itemIndexTbl[row_idx] = self.sortedResultTbl[row_idx][index].index self:SetFetchResultReturn(row_idx, self.itemIndexTbl[row_idx]) end) @@ -1104,7 +1108,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro if not result then return end - local item = new("Item", result.item_string) + local item = new("Item"):Item(result.item_string) tooltip:Clear() if slotTbl.slotName == "Watcher's Eye" then -- for watcher's eye we don't have a target slot. this will also @@ -1117,7 +1121,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro tooltip:AddSeparator(10) tooltip:AddLine(16, string.format("^7Price: %s %s", result.amount, result.currency)) end - controls["importButton"..row_idx] = new("ButtonControl", { "TOPLEFT", controls["resultDropdown"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Import Item", function() + controls["importButton"..row_idx] = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls["resultDropdown"..row_idx], "TOPRIGHT"}, {8, 0, 100, row_height}, "Import Item", function() self.itemsTab:CreateDisplayItemFromRaw(self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string) local item = self.itemsTab.displayItem -- pass "true" to not auto equip it as we will have our own logic @@ -1139,7 +1143,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro -- TODO: item parsing bug caught here. -- item.baseName is nil and throws error in the following AddItemTooltip func -- if the item is unidentified - local item = new("Item", item_string) + local item = new("Item"):Item(item_string) if slotTbl.slotName == "Watcher's Eye" then -- we have no comparison slot for the watcher's eye self.itemsTab:AddItemTooltip(tooltip, item, nil, true) @@ -1153,7 +1157,7 @@ function TradeQueryClass:PriceItemRowDisplay(row_idx, top_pane_alignment_ref, ro return self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]].item_string ~= nil end -- Whisper so we can copy to clipboard - controls["whisperButton" .. row_idx] = new("ButtonControl", + controls["whisperButton" .. row_idx] = new("ButtonControl"):ButtonControl( { "TOPLEFT", controls["importButton" .. row_idx], "TOPRIGHT" }, { 8, 0, 170, row_height }, function() local itemResult = self.itemIndexTbl[row_idx] and self.resultTbl[row_idx][self.itemIndexTbl[row_idx]] diff --git a/src/Classes/TradeQueryGenerator.lua b/src/Classes/TradeQueryGenerator.lua index eeb2fdeaab..9bf031b569 100644 --- a/src/Classes/TradeQueryGenerator.lua +++ b/src/Classes/TradeQueryGenerator.lua @@ -106,7 +106,10 @@ local function logToFile(...) ConPrintf(...) end -local TradeQueryGeneratorClass = newClass("TradeQueryGenerator", function(self, queryTab) +---@class TradeQueryGenerator +local TradeQueryGeneratorClass = newClass("TradeQueryGenerator") + +function TradeQueryGeneratorClass:TradeQueryGenerator(queryTab) self:InitMods() self.queryTab = queryTab self.itemsTab = queryTab.itemsTab @@ -114,7 +117,8 @@ local TradeQueryGeneratorClass = newClass("TradeQueryGenerator", function(self, self.lastMaxPrice = nil self.lastMaxPriceTypeIndex = nil self.lastMaxLevel = nil -end) + return self +end local function fetchStats() local tradeStats = "" @@ -786,7 +790,7 @@ function TradeQueryGeneratorClass:StartQuery(slot, options) -- Create a temp item for the slot with no mods local itemRawStr = "Rarity: RARE\nStat Tester\n" .. testItemType - local testItem = new("Item", itemRawStr) + local testItem = new("Item"):Item(itemRawStr) -- Apply any requests influences if options.influence1 > 1 then @@ -823,7 +827,7 @@ function TradeQueryGeneratorClass:StartQuery(slot, options) -- Open progress tracking blocker popup local controls = { } - controls.progressText = new("LabelControl", {"TOP",nil,"TOP"}, {0, 30, 0, 16}, string.format("Calculating Mod Weights...")) + controls.progressText = new("LabelControl"):LabelControl({"TOP",nil,"TOP"}, {0, 30, 0, 16}, string.format("Calculating Mod Weights...")) self.calcContext.popup = main:OpenPopup(280, 65, "Please Wait", controls) end @@ -1133,12 +1137,12 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb local isWeaponSlot = slot and (slot.slotName == "Weapon 1" or slot.slotName == "Weapon 2") local isEldritchModSlot = slot and eldritchModSlots[slot.slotName] == true - controls.includeCorrupted = new("CheckBoxControl", {"TOP",nil,"TOP"}, {-40, 30, 18}, "Corrupted Mods:", function(state) end, "Includes corruption implicit modifiers in the weighted sum.\nNote that there is a maximum search filter count which means this might cause other weights to not be included.") + controls.includeCorrupted = new("CheckBoxControl"):CheckBoxControl({"TOP",nil,"TOP"}, {-40, 30, 18}, "Corrupted Mods:", function(state) end, "Includes corruption implicit modifiers in the weighted sum.\nNote that there is a maximum search filter count which means this might cause other weights to not be included.") controls.includeCorrupted.state = not context.slotTbl.alreadyCorrupted and (self.lastIncludeCorrupted == nil or self.lastIncludeCorrupted == true) controls.includeCorrupted.enabled = not context.slotTbl.alreadyCorrupted -- removing checkbox until synthesis mods are supported - --controls.includeSynthesis = new("CheckBoxControl", {"TOPRIGHT",controls.includeEldritch,"BOTTOMRIGHT"}, {0, 5, 18}, "Synthesis Mods:", function(state) end) + --controls.includeSynthesis = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT",controls.includeEldritch,"BOTTOMRIGHT"}, {0, 5, 18}, "Synthesis Mods:", function(state) end) --controls.includeSynthesis.state = (self.lastIncludeSynthesis == nil or self.lastIncludeSynthesis == true) local lastItemAnchor = controls.includeCorrupted @@ -1155,19 +1159,19 @@ function TradeQueryGeneratorClass:RequestQuery(slot, context, statWeights, callb -- these unique items cannot be mirrored if not context.slotTbl.unique then - controls.includeMirrored = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Mirrored Items:", function(state) end) + controls.includeMirrored = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Mirrored Items:", function(state) end) controls.includeMirrored.state = (self.lastIncludeMirrored == nil or self.lastIncludeMirrored == true) updateLastAnchor(controls.includeMirrored) end if not isJewelSlot and not isAbyssalJewelSlot and includeScourge then - controls.includeScourge = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Scourge Mods:", function(state) end) + controls.includeScourge = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Scourge Mods:", function(state) end) controls.includeScourge.state = (self.lastIncludeScourge == nil or self.lastIncludeScourge == true) updateLastAnchor(controls.includeScourge) end if isAmuletSlot then - controls.includeTalisman = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Talisman Mods:", function(state) end) + controls.includeTalisman = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Talisman Mods:", function(state) end) controls.includeTalisman.state = (self.lastIncludeTalisman == nil or self.lastIncludeTalisman == true) updateLastAnchor(controls.includeTalisman) end @@ -1180,16 +1184,16 @@ All: weights are generated for all eldritch implicit modifiers. Omit while: weights are generated, but conditional "While unique/atlas boss" modifiers are skipped. It is often not recommended to use "All" as this includes a lot of high power modifiers, which will cause other useful modifiers to be left out in the weighted sum.]] - controls.includeEldritch = new("DropDownControl", { "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 92, 18 }, + controls.includeEldritch = new("DropDownControl"):DropDownControl({ "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 92, 18 }, { "None", "All", "Omit While" }, function(_state) end, eldritchTooltip) - controls.includeEldritchLabel = new("LabelControl", { "RIGHT", controls.includeEldritch, "LEFT" }, + controls.includeEldritchLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.includeEldritch, "LEFT" }, { -4, 0, 80, 16 }, "Eldritch Mods:") controls.includeEldritch:SetSel(self.lastIncludeEldritch or 1) updateLastAnchor(controls.includeEldritch) local eldritchTooltip = "Replaces the eldritch modifiers on search results with the eldritch modifiers from your currently equipped item." local labelText = "Copy Current Implicits:" - controls.copyEldritch = new("CheckBoxControl", + controls.copyEldritch = new("CheckBoxControl"):CheckBoxControl( { "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 18, 18 }, labelText, function(state) end, eldritchTooltip, false) @@ -1202,20 +1206,20 @@ which will cause other useful modifiers to be left out in the weighted sum.]] Copy Current: current %s will be applied to the search result items. Remove: %s will be removed from the search results.]], term, term, term) local copyEnchantList = { "Keep", "Copy Current", "Remove" } - controls.copyEnchantMode = new("DropDownControl", + controls.copyEnchantMode = new("DropDownControl"):DropDownControl( { "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 120, 18 }, copyEnchantList, function(state) end, enchantTooltip) controls.copyEnchantMode.state = self.lastCopyEnchantMode or false local labelText = isWeaponSlot and "^7Enchant Behaviour:" or "^7Anoint Behaviour:" - controls.copyEnchantModeLabel = new("LabelControl", { "RIGHT", controls.copyEnchantMode, "LEFT" }, + controls.copyEnchantModeLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.copyEnchantMode, "LEFT" }, { -4, 0, 80, 16 }, labelText) updateLastAnchor(controls.copyEnchantMode) end if isJewelSlot and context.slotTbl.slotName ~= "Watcher's Eye" then - controls.jewelType = new("DropDownControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, { "Any", "Base", "Abyss" }, function(index, value) end) + controls.jewelType = new("DropDownControl"):DropDownControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, { "Any", "Base", "Abyss" }, function(index, value) end) controls.jewelType.selIndex = self.lastJewelType or 1 - controls.jewelTypeLabel = new("LabelControl", {"RIGHT",controls.jewelType,"LEFT"}, {-5, 0, 0, 16}, "Jewel Type:") + controls.jewelTypeLabel = new("LabelControl"):LabelControl({"RIGHT",controls.jewelType,"LEFT"}, {-5, 0, 0, 16}, "Jewel Type:") updateLastAnchor(controls.jewelType) elseif slot and not isAbyssalJewelSlot and context.slotTbl.slotName ~= "Watcher's Eye" then local selFunc = function() @@ -1226,22 +1230,22 @@ Remove: %s will be removed from the search results.]], term, term, term) controls.copyEldritch.enabled = not hasInfluence1 and not hasInfluence2 end end - controls.influence1 = new("DropDownControl", { "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 100, 18 }, + controls.influence1 = new("DropDownControl"):DropDownControl({ "TOPLEFT", lastItemAnchor, "BOTTOMLEFT" }, { 0, 5, 100, 18 }, influenceDropdownNames, selFunc) controls.influence1:SetSel(self.lastInfluence1 or 1) - controls.influence1Label = new("LabelControl", {"RIGHT",controls.influence1,"LEFT"}, {-5, 0, 0, 16}, "^7Influence 1:") + controls.influence1Label = new("LabelControl"):LabelControl({"RIGHT",controls.influence1,"LEFT"}, {-5, 0, 0, 16}, "^7Influence 1:") - controls.influence2 = new("DropDownControl", { "TOPLEFT", controls.influence1, "BOTTOMLEFT" }, { 0, 5, 100, 18 }, + controls.influence2 = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.influence1, "BOTTOMLEFT" }, { 0, 5, 100, 18 }, influenceDropdownNames, selFunc) controls.influence2:SetSel(self.lastInfluence2 or 1) selFunc() - controls.influence2Label = new("LabelControl", { "RIGHT", controls.influence2, "LEFT" }, { -5, 0, 0, 16 }, + controls.influence2Label = new("LabelControl"):LabelControl({ "RIGHT", controls.influence2, "LEFT" }, { -5, 0, 0, 16 }, "^7Influence 2:") updateLastAnchor(controls.influence2, 46) elseif isAbyssalJewelSlot then - controls.jewelType = new("DropDownControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, { "Abyss" }, nil) + controls.jewelType = new("DropDownControl"):DropDownControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, { "Abyss" }, nil) controls.jewelType.selIndex = 1 - controls.jewelTypeLabel = new("LabelControl", {"RIGHT",controls.jewelType,"LEFT"}, {-5, 0, 0, 16}, "Jewel Type:") + controls.jewelTypeLabel = new("LabelControl"):LabelControl({"RIGHT",controls.jewelType,"LEFT"}, {-5, 0, 0, 16}, "Jewel Type:") updateLastAnchor(controls.jewelType) end -- Add max price limit selection dropbox @@ -1249,38 +1253,38 @@ Remove: %s will be removed from the search results.]], term, term, term) for _, currency in ipairs(currencyTable) do t_insert(currencyDropdownNames, currency.name) end - controls.maxPrice = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") + controls.maxPrice = new("EditControl"):EditControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") controls.maxPrice.buf = self.lastMaxPrice and tostring(self.lastMaxPrice) or "" - controls.maxPriceType = new("DropDownControl", {"LEFT",controls.maxPrice,"RIGHT"}, {5, 0, 150, 18}, currencyDropdownNames, nil) + controls.maxPriceType = new("DropDownControl"):DropDownControl({"LEFT",controls.maxPrice,"RIGHT"}, {5, 0, 150, 18}, currencyDropdownNames, nil) controls.maxPriceType.selIndex = self.lastMaxPriceTypeIndex or 1 - controls.maxPriceLabel = new("LabelControl", {"RIGHT",controls.maxPrice,"LEFT"}, {-5, 0, 0, 16}, "^7Max Price:") + controls.maxPriceLabel = new("LabelControl"):LabelControl({"RIGHT",controls.maxPrice,"LEFT"}, {-5, 0, 0, 16}, "^7Max Price:") updateLastAnchor(controls.maxPrice) - controls.maxLevel = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, nil, nil, "%D") + controls.maxLevel = new("EditControl"):EditControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 100, 18}, nil, nil, "%D") controls.maxLevel.buf = self.lastMaxLevel and tostring(self.lastMaxLevel) or "" - controls.maxLevelLabel = new("LabelControl", {"RIGHT",controls.maxLevel,"LEFT"}, {-5, 0, 0, 16}, "Max Level:") + controls.maxLevelLabel = new("LabelControl"):LabelControl({"RIGHT",controls.maxLevel,"LEFT"}, {-5, 0, 0, 16}, "Max Level:") updateLastAnchor(controls.maxLevel) -- basic filtering by slot for sockets and links, Megalomaniac does not have slot and Sockets use "Jewel nodeId" if slot and not isJewelSlot and not isAbyssalJewelSlot and not slot.slotName:find("Flask") then - controls.sockets = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") + controls.sockets = new("EditControl"):EditControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") controls.sockets.buf = self.lastSockets and tostring(self.lastSockets) or "" - controls.socketsLabel = new("LabelControl", {"RIGHT",controls.sockets,"LEFT"}, {-5, 0, 0, 16}, "^7# of Empty Sockets:") + controls.socketsLabel = new("LabelControl"):LabelControl({"RIGHT",controls.sockets,"LEFT"}, {-5, 0, 0, 16}, "^7# of Empty Sockets:") updateLastAnchor(controls.sockets) if not slot.slotName:find("Belt") and not slot.slotName:find("Ring") and not slot.slotName:find("Amulet") then - controls.links = new("EditControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") - controls.linksLabel = new("LabelControl", {"RIGHT",controls.links,"LEFT"}, {-5, 0, 0, 16}, "^7# of Links:") + controls.links = new("EditControl"):EditControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, 5, 70, 18}, nil, nil, "%D") + controls.linksLabel = new("LabelControl"):LabelControl({"RIGHT",controls.links,"LEFT"}, {-5, 0, 0, 16}, "^7# of Links:") updateLastAnchor(controls.links) end end for i, stat in ipairs(statWeights) do - controls["sortStatType"..tostring(i)] = new("LabelControl", {"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, i == 1 and 5 or 3, 70, 16}, i < (#statWeights < 6 and 10 or 5) and s_format("^7%.2f: %s", stat.weightMult, stat.label) or ("+ "..tostring(#statWeights - 4).." Additional Stats")) + controls["sortStatType"..tostring(i)] = new("LabelControl"):LabelControl({"TOPLEFT",lastItemAnchor,"BOTTOMLEFT"}, {0, i == 1 and 5 or 3, 70, 16}, i < (#statWeights < 6 and 10 or 5) and s_format("^7%.2f: %s", stat.weightMult, stat.label) or ("+ "..tostring(#statWeights - 4).." Additional Stats")) lastItemAnchor = controls["sortStatType"..tostring(i)] popupHeight = popupHeight + 19 if i == 1 then - controls.sortStatLabel = new("LabelControl", {"RIGHT",lastItemAnchor,"LEFT"}, {-5, 0, 0, 16}, "^7Stat to Sort By:") + controls.sortStatLabel = new("LabelControl"):LabelControl({"RIGHT",lastItemAnchor,"LEFT"}, {-5, 0, 0, 16}, "^7Stat to Sort By:") elseif i == 5 then -- tooltips do not actually work for labels lastItemAnchor.tooltipFunc = function(tooltip) @@ -1299,13 +1303,13 @@ Remove: %s will be removed from the search results.]], term, term, term) popupHeight = popupHeight + 4 if context.slotTbl.slotName == "Watcher's Eye" then - controls.includeAllWEMods = new("CheckBoxControl", {"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Include all Watcher's Eye mods:", function(state) end) + controls.includeAllWEMods = new("CheckBoxControl"):CheckBoxControl({"TOPRIGHT",lastItemAnchor,"BOTTOMRIGHT"}, {0, 5, 18}, "Include all Watcher's Eye mods:", function(state) end) controls.includeAllWEMods.tooltipText = "Include mods that could not have a weight calculated for them at weight 0." lastItemAnchor = controls.includeAllWEMods popupHeight = popupHeight + 23 end - controls.generateQuery = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Execute", function() + controls.generateQuery = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Execute", function() main:ClosePopup() self.tradeTypeIndex = context.controls.tradeTypeSelection.selIndex @@ -1370,7 +1374,7 @@ Remove: %s will be removed from the search results.]], term, term, term) self:StartQuery(slot, options) end) - controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(400, popupHeight, "Query Options", controls) diff --git a/src/Classes/TradeQueryRateLimiter.lua b/src/Classes/TradeQueryRateLimiter.lua index 42573d0f3b..4507d554c6 100644 --- a/src/Classes/TradeQueryRateLimiter.lua +++ b/src/Classes/TradeQueryRateLimiter.lua @@ -6,7 +6,9 @@ -- ---@class TradeQueryRateLimiter -local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter", function(self) +local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter") + +function TradeQueryRateLimiterClass:TradeQueryRateLimiter() -- policies_sample = { -- -- label: policy -- ["trade-search-request-limit"] = { @@ -54,7 +56,8 @@ local TradeQueryRateLimiterClass = newClass("TradeQueryRateLimiter", function(se ["trade-search-request-limit"] = {}, ["trade-fetch-request-limit"] = {} } -end) + return self +end function TradeQueryRateLimiterClass:GetPolicyName(key) return self.policyNames[key] diff --git a/src/Classes/TradeQueryRequests.lua b/src/Classes/TradeQueryRequests.lua index 95f8b6a5ad..3ad9f60730 100644 --- a/src/Classes/TradeQueryRequests.lua +++ b/src/Classes/TradeQueryRequests.lua @@ -7,16 +7,18 @@ local dkjson = require "dkjson" ---@class TradeQueryRequests -local TradeQueryRequestsClass = newClass("TradeQueryRequests", function(self, rateLimiter) +local TradeQueryRequestsClass = newClass("TradeQueryRequests") + +function TradeQueryRequestsClass:TradeQueryRequests(rateLimiter) self.maxFetchPerSearch = 10 - self.tradeQuery = tradeQuery - self.rateLimiter = rateLimiter or new("TradeQueryRateLimiter") + self.rateLimiter = rateLimiter or new("TradeQueryRateLimiter"):TradeQueryRateLimiter() self.requestQueue = { ["search"] = {}, ["fetch"] = {}, } self.hostName = "https://www.pathofexile.com/" -end) + return self +end ---Main routine for processing request queue function TradeQueryRequestsClass:ProcessQueue() diff --git a/src/Classes/TradeStatWeightMultiplierListControl.lua b/src/Classes/TradeStatWeightMultiplierListControl.lua index 0d528470f5..bde6c6a2bf 100644 --- a/src/Classes/TradeStatWeightMultiplierListControl.lua +++ b/src/Classes/TradeStatWeightMultiplierListControl.lua @@ -4,12 +4,16 @@ -- Specialized UI element for listing and modifying Trade Stat Weight Multipliers. -- -local TradeStatWeightMultiplierListControlClass = newClass("TradeStatWeightMultiplierListControl", "ListControl", function(self, anchor, rect, list, indexController) +---@class TradeStatWeightMultiplierListControl: ListControl +local TradeStatWeightMultiplierListControlClass = newClass("TradeStatWeightMultiplierListControl", "ListControl") + +function TradeStatWeightMultiplierListControlClass:TradeStatWeightMultiplierListControl(anchor, rect, list, indexController) self.list = list self.indexController = indexController - self.ListControl(anchor, rect, 16, true, false, self.list) + self:ListControl(anchor, rect, 16, true, false, self.list) self.selIndex = nil -end) + return self +end function TradeStatWeightMultiplierListControlClass:Draw(viewPort, noTooltip) self.noTooltip = noTooltip diff --git a/src/Classes/TreeTab.lua b/src/Classes/TreeTab.lua index 77bfe3ffdb..d6bdc04cff 100644 --- a/src/Classes/TreeTab.lua +++ b/src/Classes/TreeTab.lua @@ -19,24 +19,28 @@ local s_gsub = string.gsub local s_byte = string.byte local dkjson = require "dkjson" -local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) - self.ControlHost() +---@class TreeTab: ControlHost +local TreeTabClass = newClass("TreeTab", "ControlHost") + +---@param build Build +function TreeTabClass:TreeTab(build) + self:ControlHost() self.build = build self.isComparing = false; self.isCustomMaxDepth = false; - self.viewer = new("PassiveTreeView") + self.viewer = new("PassiveTreeView"):PassiveTreeView() self.specList = { } - self.specList[1] = new("PassiveSpec", build, latestTreeVersion) + self.specList[1] = new("PassiveSpec"):PassiveSpec(build, latestTreeVersion) self:SetActiveSpec(1) self:SetCompareSpec(1) - self.anchorControls = new("Control", nil, {0, 0, 0, 20}) + self.anchorControls = new("Control"):Control(nil, {0, 0, 0, 20}) -- Tree list dropdown - self.controls.specSelect = new("DropDownControl", { "LEFT",self.anchorControls,"RIGHT" }, { 0, 0, 190, 20 }, nil, function(index, value) + self.controls.specSelect = new("DropDownControl"):DropDownControl({ "LEFT",self.anchorControls,"RIGHT" }, { 0, 0, 190, 20 }, nil, function(index, value) if self.specList[index] then self.build.modFlag = true self:SetActiveSpec(index) @@ -103,7 +107,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end -- Compare checkbox - self.controls.compareCheck = new("CheckBoxControl", { "LEFT", self.controls.specSelect, "RIGHT" }, { 74, 0, 20 }, "Compare:", function(state) + self.controls.compareCheck = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.specSelect, "RIGHT" }, { 74, 0, 20 }, "Compare:", function(state) self.isComparing = state self:SetCompareSpec(self.activeCompareSpec) self.controls.compareSelect.shown = state @@ -115,7 +119,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end) -- Compare tree dropdown - self.controls.compareSelect = new("DropDownControl", { "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 190, 20 }, nil, function(index, value) + self.controls.compareSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 190, 20 }, nil, function(index, value) if self.specList[index] then self:SetCompareSpec(index) else @@ -126,18 +130,18 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.compareSelect.maxDroppedWidth = 1000 self.controls.compareSelect.enableDroppedWidth = true self.controls.compareSelect.enableChangeBoxWidth = true - self.controls.reset = new("ButtonControl", { "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 145, 20 }, "Reset Tree/Tattoos", function() + self.controls.reset = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.compareCheck, "RIGHT" }, { 8, 0, 145, 20 }, "Reset Tree/Tattoos", function() local controls = { } local buttonY = 65 - controls.warningLabel = new("LabelControl", nil, { 0, 30, 0, 16 }, "^7Warning: resetting your passive tree or removing all tattoos cannot be undone.\n") - controls.reset = new("ButtonControl", nil, { -130, buttonY, 100, 20 }, "Reset Tree", function() + controls.warningLabel = new("LabelControl"):LabelControl(nil, { 0, 30, 0, 16 }, "^7Warning: resetting your passive tree or removing all tattoos cannot be undone.\n") + controls.reset = new("ButtonControl"):ButtonControl(nil, { -130, buttonY, 100, 20 }, "Reset Tree", function() self.build.spec:ResetNodes() self.build.spec:BuildAllDependsAndPaths() self.build.spec:AddUndoState() self.build.buildFlag = true main:ClosePopup() end) - controls.removeTattoo = new("ButtonControl", nil, { 0, buttonY, 144, 20 }, "Remove All Tattoos", function() + controls.removeTattoo = new("ButtonControl"):ButtonControl(nil, { 0, buttonY, 144, 20 }, "Remove All Tattoos", function() for id, node in pairs(self.build.spec.hashOverrides) do --hashOverrides will contain only the nodes that have been tattoo-ed if node.isTattoo then self:RemoveTattooFromNode(self.build.spec.nodes[id]) @@ -147,7 +151,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.build.buildFlag = true main:ClosePopup() end) - controls.cancel = new("ButtonControl", nil, { 130, buttonY, 100, 20 }, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, { 130, buttonY, 100, 20 }, "Cancel", function() main:ClosePopup() end) main:OpenPopup(570, 100, "Reset Tree/Tattoos", controls, nil, "edit", "cancel") @@ -162,8 +166,8 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) } t_insert(self.treeVersions, value) end - self.controls.versionText = new("LabelControl", { "LEFT", self.controls.reset, "RIGHT" }, { 8, 0, 0, 16 }, "^7Version:") - self.controls.versionSelect = new("DropDownControl", { "LEFT", self.controls.versionText, "RIGHT" }, { 8, 0, 100, 20 }, self.treeVersions, function(index, selected) + self.controls.versionText = new("LabelControl"):LabelControl({ "LEFT", self.controls.reset, "RIGHT" }, { 8, 0, 0, 16 }, "^7Version:") + self.controls.versionSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.versionText, "RIGHT" }, { 8, 0, 100, 20 }, self.treeVersions, function(index, selected) if selected.value ~= self.build.spec.treeVersion then self:OpenVersionConvertPopup(selected.value, true) end @@ -175,7 +179,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.versionSelect.selIndex = #self.treeVersions -- Tree Search Textbox - self.controls.treeSearch = new("EditControl", { "LEFT", self.controls.versionSelect, "RIGHT" }, { 8, 0, main.portraitMode and 200 or 300, 20 }, "", "Search", "%c", 100, function(buf) + self.controls.treeSearch = new("EditControl"):EditControl({ "LEFT", self.controls.versionSelect, "RIGHT" }, { 8, 0, main.portraitMode and 200 or 300, 20 }, "", "Search", "%c", 100, function(buf) self.viewer.searchStr = buf self.searchFlag = buf ~= self.viewer.searchStrSaved end, nil, nil, true) @@ -184,7 +188,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) -- table holding all realm/league pairs. (allLeagues[realm] = [league.id,...]) self.tradeLeaguesList = {} -- Find Timeless Jewel Button - self.controls.findTimelessJewel = new("ButtonControl", { "LEFT", self.controls.treeSearch, "RIGHT" }, { 8, 0, 150, 20 }, "Find Timeless Jewel", function() + self.controls.findTimelessJewel = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.treeSearch, "RIGHT" }, { 8, 0, 150, 20 }, "Find Timeless Jewel", function() self:FindTimelessJewel() end) @@ -192,7 +196,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.defaultTattoo = { } -- Show Node Power Checkbox - self.controls.treeHeatMap = new("CheckBoxControl", { "LEFT", self.controls.findTimelessJewel, "RIGHT" }, { 130, 0, 20 }, "Show Node Power:", function(state) + self.controls.treeHeatMap = new("CheckBoxControl"):CheckBoxControl({ "LEFT", self.controls.findTimelessJewel, "RIGHT" }, { 130, 0, 20 }, "Show Node Power:", function(state) self.viewer.showHeatMap = state self.controls.treeHeatMapStatSelect.shown = state @@ -205,7 +209,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end) -- Control for setting max node depth to limit calculation time of the heat map - self.controls.nodePowerMaxDepthSelect = new("DropDownControl", { "LEFT", self.controls.treeHeatMap, "RIGHT" }, { 8, 0, 55, 20 }, { "All", 5, 10, 15, "Custom" }, function(index, value) + self.controls.nodePowerMaxDepthSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.treeHeatMap, "RIGHT" }, { 8, 0, 55, 20 }, { "All", 5, 10, 15, "Custom" }, function(index, value) -- Show custom value control and resize/move elements self.isCustomMaxDepth = value == "Custom" if self.isCustomMaxDepth then @@ -238,7 +242,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.nodePowerMaxDepthSelect.tooltipText = "Limit of Node distance to search (lower = faster)" -- Control for setting max node depth by custom value - self.controls.nodePowerMaxDepthCustom = new("EditControl", { "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 70, 20 }, "0", nil, "%D", nil, function(value) + self.controls.nodePowerMaxDepthCustom = new("EditControl"):EditControl({ "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 70, 20 }, "0", nil, "%D", nil, function(value) self.build.calcsTab.nodePowerMaxDepth = tonumber(value) -- If the heat map is shown, recalculate it with new value @@ -249,7 +253,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) self.controls.nodePowerMaxDepthCustom.shown = false -- Control for selecting the power stat to sort by (Defense, DPS, etc) - self.controls.treeHeatMapStatSelect = new("DropDownControl", { "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 150, 20 }, nil, function(index, value) + self.controls.treeHeatMapStatSelect = new("DropDownControl"):DropDownControl({ "LEFT", self.controls.nodePowerMaxDepthSelect, "RIGHT" }, { 8, 0, 150, 20 }, nil, function(index, value) self:SetPowerCalc(value) end) self.controls.treeHeatMap.tooltipText = function() @@ -265,14 +269,14 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end -- Show/Hide Power Report Button - self.controls.powerReport = new("ButtonControl", { "LEFT", self.controls.treeHeatMapStatSelect, "RIGHT" }, { 8, 0, 150, 20 }, + self.controls.powerReport = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.treeHeatMapStatSelect, "RIGHT" }, { 8, 0, 150, 20 }, function() return self.controls.powerReportList.shown and "Hide Power Report" or "Show Power Report" end, function() self.controls.powerReportList.shown = not self.controls.powerReportList.shown end) -- Power Report List local yPos = self.controls.treeHeatMap.y == 0 and self.controls.specSelect.height + 4 or self.controls.specSelect.height * 2 + 8 - self.controls.powerReportList = new("PowerReportListControl", { "TOPLEFT", self.controls.specSelect, "BOTTOMLEFT" }, { 0, yPos, 700, 170 }, function(selectedNode) + self.controls.powerReportList = new("PowerReportListControl"):PowerReportListControl({ "TOPLEFT", self.controls.specSelect, "BOTTOMLEFT" }, { 0, yPos, 700, 170 }, function(selectedNode) -- this code is called by the list control when the user "selects" one of the passives in the list. -- we use this to set a flag which causes the next Draw() to recenter the passive tree on the desired node. if selectedNode.x then @@ -319,7 +323,7 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) end end - self.controls.specConvertText = new("LabelControl", { "BOTTOMLEFT", self.controls.specSelect, "TOPLEFT" }, { 0, -14, 0, 16 }, "^7This is an older tree version, which may not be fully compatible with the current game version.") + self.controls.specConvertText = new("LabelControl"):LabelControl({ "BOTTOMLEFT", self.controls.specSelect, "TOPLEFT" }, { 0, -14, 0, 16 }, "^7This is an older tree version, which may not be fully compatible with the current game version.") self.controls.specConvertText.shown = function() return self.showConvert end @@ -332,16 +336,17 @@ local TreeTabClass = newClass("TreeTab", "ControlHost", function(self, build) local function buildConvertAllButtonLabel() return colorCodes.POSITIVE.."Convert all trees to "..treeVersions[getLatestTreeVersion()].display end - self.controls.specConvert = new("ButtonControl", { "LEFT", self.controls.specConvertText, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertButtonLabel()) + 20 end, 20 }, buildConvertButtonLabel, function() + self.controls.specConvert = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.specConvertText, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertButtonLabel()) + 20 end, 20 }, buildConvertButtonLabel, function() self:ConvertToVersion(getLatestTreeVersion(), false, true) end) - self.controls.specConvertAll = new("ButtonControl", { "LEFT", self.controls.specConvert, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertAllButtonLabel()) + 20 end, 20 }, buildConvertAllButtonLabel, function() + self.controls.specConvertAll = new("ButtonControl"):ButtonControl({ "LEFT", self.controls.specConvert, "RIGHT" }, { 8, 0, function() return DrawStringWidth(16, "VAR", buildConvertAllButtonLabel()) + 20 end, 20 }, buildConvertAllButtonLabel, function() self:OpenVersionConvertAllPopup(getLatestTreeVersion()) end) self.jumpToNode = false self.jumpToX = 0 self.jumpToY = 0 -end) + return self +end function TreeTabClass:RemoveTattooFromNode(node) self.build.spec.tree.nodes[node.id].isTattoo = false @@ -495,7 +500,7 @@ function TreeTabClass:Load(xml, dbFileName) self.specList = { } if xml.elem == "Spec" then -- Import single spec from old build - self.specList[1] = new("PassiveSpec", self.build, defaultTreeVersion) + self.specList[1] = new("PassiveSpec"):PassiveSpec(self.build, defaultTreeVersion) self.specList[1]:Load(xml, dbFileName) self.activeSpec = 1 self.build.spec = self.specList[1] @@ -508,14 +513,14 @@ function TreeTabClass:Load(xml, dbFileName) main:OpenMessagePopup("Unknown Passive Tree Version", "The build you are trying to load uses an unrecognised version of the passive skill tree.\nYou may need to update the program before loading this build.") return true end - local newSpec = new("PassiveSpec", self.build, node.attrib.treeVersion or defaultTreeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, node.attrib.treeVersion or defaultTreeVersion) newSpec:Load(node, dbFileName) t_insert(self.specList, newSpec) end end end if not self.specList[1] then - self.specList[1] = new("PassiveSpec", self.build, latestTreeVersion) + self.specList[1] = new("PassiveSpec"):PassiveSpec(self.build, latestTreeVersion) end self:SetActiveSpec(tonumber(xml.attrib.activeSpec) or 1) end @@ -592,7 +597,7 @@ function TreeTabClass:ConvertToVersion(version, remove, success, ignoreTreeSubTy version = version..treeSubTypeCapture end end - local newSpec = new("PassiveSpec", self.build, version) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, version) newSpec.title = self.build.spec.title newSpec.jewels = copyTable(self.build.spec.jewels) newSpec:RestoreUndoState(self.build.spec:CreateUndoState(), version) @@ -628,19 +633,19 @@ end function TreeTabClass:OpenSpecManagePopup() local importTree = - new("ButtonControl", nil, {-99, 259, 90, 20}, "Import Tree", function() + new("ButtonControl"):ButtonControl(nil, {-99, 259, 90, 20}, "Import Tree", function() self:OpenImportPopup() end) local exportTree = - new("ButtonControl", {"LEFT", importTree, "RIGHT"}, {8, 0, 90, 20}, "Export Tree", function() + new("ButtonControl"):ButtonControl({"LEFT", importTree, "RIGHT"}, {8, 0, 90, 20}, "Export Tree", function() self:OpenExportPopup() end) main:OpenPopup(370, 290, "Manage Passive Trees", { - new("PassiveSpecListControl", nil, {0, 50, 350, 200}, self), + new("PassiveSpecListControl"):PassiveSpecListControl(nil, {0, 50, 350, 200}, self), importTree, exportTree, - new("ButtonControl", {"LEFT", exportTree, "RIGHT"}, {8, 0, 90, 20}, "Done", function() + new("ButtonControl"):ButtonControl({"LEFT", exportTree, "RIGHT"}, {8, 0, 90, 20}, "Done", function() main:ClosePopup() end), }) @@ -648,17 +653,17 @@ end function TreeTabClass:OpenVersionConvertPopup(version, ignoreTreeSubType) local controls = { } - controls.warningLabel = new("LabelControl", nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. + controls.warningLabel = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. "Convert will replace your current tree.\nCopy + Convert will backup your current tree.\n") - controls.convert = new("ButtonControl", nil, {-125, 105, 100, 20}, "Convert", function() + controls.convert = new("ButtonControl"):ButtonControl(nil, {-125, 105, 100, 20}, "Convert", function() self:ConvertToVersion(version, true, false, ignoreTreeSubType) main:ClosePopup() end) - controls.convertCopy = new("ButtonControl", nil, {0, 105, 125, 20}, "Copy + Convert", function() + controls.convertCopy = new("ButtonControl"):ButtonControl(nil, {0, 105, 125, 20}, "Copy + Convert", function() self:ConvertToVersion(version, false, false, ignoreTreeSubType) main:ClosePopup() end) - controls.cancel = new("ButtonControl", nil, {125, 105, 100, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {125, 105, 100, 20}, "Cancel", function() self.controls.versionSelect:SelByValue(self.build.spec.treeVersion, 'value') main:ClosePopup() end) @@ -667,13 +672,13 @@ end function TreeTabClass:OpenVersionConvertAllPopup(version) local controls = { } - controls.warningLabel = new("LabelControl", nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. + controls.warningLabel = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Warning: some or all of the passives may be de-allocated due to changes in the tree.\n\n" .. "Convert will replace all trees that are not Version "..treeVersions[version].display..".\nThis action cannot be undone.\n") - controls.convert = new("ButtonControl", nil, {-58, 105, 100, 20}, "Convert", function() + controls.convert = new("ButtonControl"):ButtonControl(nil, {-58, 105, 100, 20}, "Convert", function() self:ConvertAllToVersion(version) main:ClosePopup() end) - controls.cancel = new("ButtonControl", nil, {58, 105, 100, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {58, 105, 100, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(570, 140, "Convert all to Version "..treeVersions[version].display, controls, "convert", "edit") @@ -684,7 +689,7 @@ function TreeTabClass:OpenImportPopup() local controls = { } local function decodePoePlannerTreeLink(treeLink) -- treeVersion is not known at this point. We need to decode the URL to get it. - local tmpSpec = new("PassiveSpec", self.build, latestTreeVersion) + local tmpSpec = new("PassiveSpec"):PassiveSpec(self.build, latestTreeVersion) local newTreeVersion_or_errMsg = tmpSpec:DecodePoePlannerURL(treeLink, true) -- Check for an error message if string.find(newTreeVersion_or_errMsg, "Invalid") then @@ -693,7 +698,7 @@ function TreeTabClass:OpenImportPopup() end -- 20230908. We always create a new Spec() - local newSpec = new("PassiveSpec", self.build, newTreeVersion_or_errMsg) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, newTreeVersion_or_errMsg) newSpec.title = controls.name.buf newSpec:DecodePoePlannerURL(treeLink, false) --DecodePoePlannerURL was used above and URL proven correct. t_insert(self.specList, newSpec) @@ -709,7 +714,7 @@ function TreeTabClass:OpenImportPopup() -- newTreeVersion is passed in as an output of validateTreeVersion(). It will always be a valid tree version text string -- 20230908. We always create a new Spec() ConPrintf("Tree version: " .. newTreeVersion) - local newSpec = new("PassiveSpec", self.build, newTreeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self.build, newTreeVersion) newSpec.title = controls.name.buf local errMsg = newSpec:DecodeURL(treeLink) if errMsg then @@ -740,18 +745,18 @@ function TreeTabClass:OpenImportPopup() return latestTreeVersion .. (alternateType and ("_" .. alternateType:gsub("-", "_")) or "") end - controls.nameLabel = new("LabelControl", nil, {-180, 20, 0, 16}, "Enter name for this passive tree:") - controls.name = new("EditControl", nil, {100, 20, 350, 18}, "", nil, nil, nil, function(buf) + controls.nameLabel = new("LabelControl"):LabelControl(nil, {-180, 20, 0, 16}, "Enter name for this passive tree:") + controls.name = new("EditControl"):EditControl(nil, {100, 20, 350, 18}, "", nil, nil, nil, function(buf) controls.msg.label = "" controls.import.enabled = buf:match("%S") and controls.edit.buf:match("%S") end) - controls.editLabel = new("LabelControl", nil, {-150, 45, 0, 16}, "Enter passive tree link:") - controls.edit = new("EditControl", nil, {100, 45, 350, 18}, "", nil, nil, nil, function(buf) + controls.editLabel = new("LabelControl"):LabelControl(nil, {-150, 45, 0, 16}, "Enter passive tree link:") + controls.edit = new("EditControl"):EditControl(nil, {100, 45, 350, 18}, "", nil, nil, nil, function(buf) controls.msg.label = "" controls.import.enabled = buf:match("%S") and controls.name.buf:match("%S") end) - controls.msg = new("LabelControl", nil, {0, 65, 0, 16}, "") - controls.import = new("ButtonControl", nil, {-45, 85, 80, 20}, "Import", function() + controls.msg = new("LabelControl"):LabelControl(nil, {0, 65, 0, 16}, "") + controls.import = new("ButtonControl"):ButtonControl(nil, {-45, 85, 80, 20}, "Import", function() local treeLink = controls.edit.buf if #treeLink == 0 then return @@ -803,7 +808,7 @@ function TreeTabClass:OpenImportPopup() end end) controls.import.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 85, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 85, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(580, 115, "Import Tree", controls, "import", "name") @@ -813,9 +818,9 @@ function TreeTabClass:OpenExportPopup() local treeLink = self.build.spec:EncodeURL(treeVersions[self.build.spec.treeVersion].url) local popup local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "Passive tree link:") - controls.edit = new("EditControl", nil, {0, 40, 350, 18}, treeLink, nil, "%Z") - controls.shrink = new("ButtonControl", nil, {-90, 70, 140, 20}, "Shrink with PoEURL", function() + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "Passive tree link:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 18}, treeLink, nil, "%Z") + controls.shrink = new("ButtonControl"):ButtonControl(nil, {-90, 70, 140, 20}, "Shrink with PoEURL", function() controls.shrink.enabled = false controls.shrink.label = "Shrinking..." launch:DownloadPage("http://poeurl.com/shrink.php?url="..treeLink, function(response, errMsg) @@ -829,10 +834,10 @@ function TreeTabClass:OpenExportPopup() end end) end) - controls.copy = new("ButtonControl", nil, {30, 70, 80, 20}, "Copy", function() + controls.copy = new("ButtonControl"):ButtonControl(nil, {30, 70, 80, 20}, "Copy", function() Copy(treeLink) end) - controls.done = new("ButtonControl", nil, {120, 70, 80, 20}, "Done", function() + controls.done = new("ButtonControl"):ButtonControl(nil, {120, 70, 80, 20}, "Done", function() main:ClosePopup() end) popup = main:OpenPopup(380, 100, "Export Tree", controls, "done", "edit") @@ -900,7 +905,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) end end for idx, desc in ipairs(wrapTable) do - controls[idx] = new("LabelControl", {"TOPLEFT", controls[idx-1] or controls.modSelect,"TOPLEFT"}, {0, 20, 600, 16}, "^7"..desc) + controls[idx] = new("LabelControl"):LabelControl({"TOPLEFT", controls[idx-1] or controls.modSelect,"TOPLEFT"}, {0, 20, 600, 16}, "^7"..desc) totalHeight = totalHeight + 20 end main.popups[1].height = totalHeight + 75 @@ -912,8 +917,8 @@ function TreeTabClass:ModifyNodePopup(selectedNode) end buildMods(selectedNode) - controls.modSelectLabel = new("LabelControl", {"TOPRIGHT",nil,"TOPLEFT"}, {170, 25, 0, 16}, "^7Modifier:") - controls.modSelect = new("DropDownControl", {"TOPLEFT",nil,"TOPLEFT"}, {175, 25, 250, 18}, modGroups, function(idx) constructUI(modGroups[idx]) end) + controls.modSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT",nil,"TOPLEFT"}, {170, 25, 0, 16}, "^7Modifier:") + controls.modSelect = new("DropDownControl"):DropDownControl({"TOPLEFT",nil,"TOPLEFT"}, {175, 25, 250, 18}, modGroups, function(idx) constructUI(modGroups[idx]) end) controls.modSelect.selIndex = self.defaultTattoo[nodeName] or 1 controls.modSelect.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() @@ -923,7 +928,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) end end end - controls.save = new("ButtonControl", nil, {-90, 75, 80, 20}, "Add", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-90, 75, 80, 20}, "Add", function() addModifier(selectedNode) self.build.spec:AddUndoState() self.modFlag = true @@ -931,7 +936,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) self.defaultTattoo[nodeName] = controls.modSelect.selIndex main:ClosePopup() end) - controls.reset = new("ButtonControl", nil, {0, 75, 80, 20}, "Reset Node", function() + controls.reset = new("ButtonControl"):ButtonControl(nil, {0, 75, 80, 20}, "Reset Node", function() self:RemoveTattooFromNode(selectedNode) self.build.spec:AddUndoState() self.modFlag = true @@ -939,7 +944,7 @@ function TreeTabClass:ModifyNodePopup(selectedNode) self.defaultTattoo[nodeName] = nil main:ClosePopup() end) - controls.close = new("ButtonControl", nil, {90, 75, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {90, 75, 80, 20}, "Cancel", function() main:ClosePopup() end) @@ -976,13 +981,13 @@ function TreeTabClass:ModifyNodePopup(selectedNode) end return count end - controls.totalTattoos = new("ButtonControl", nil, { 0, 95, 145, 20 }, "^7Tattoo Count: ".. getTattooCount() .."/50", function() return end) + controls.totalTattoos = new("ButtonControl"):ButtonControl(nil, { 0, 95, 145, 20 }, "^7Tattoo Count: ".. getTattooCount() .."/50", function() return end) controls.totalTattoos.tooltipFunc = function(tooltip, mode, index, value) getTattooCount(tooltip) end main:OpenPopup(600, 105, "Replace Modifier of Node", controls, "save") constructUI(modGroups[self.defaultTattoo[nodeName] or 1]) -- Show Legacy Tattoos - controls.showLegacyTattoo = new("CheckBoxControl", { "LEFT", controls.totalTattoos, "RIGHT" }, { 195, 0, 20 }, "Show Legacy Tattoos:", function(state) + controls.showLegacyTattoo = new("CheckBoxControl"):CheckBoxControl({ "LEFT", controls.totalTattoos, "RIGHT" }, { 195, 0, 20 }, "Show Legacy Tattoos:", function(state) self.showLegacyTattoo = state buildMods(selectedNode) end) @@ -1024,13 +1029,13 @@ function TreeTabClass:OpenMasteryPopup(node, viewPort) --Check to make sure that the effects list has a potential mod to apply to a mastery if not (next(effects) == nil) then local passiveMasteryControlHeight = (#effects + 1) * 14 + 2 - controls.close = new("ButtonControl", nil, {0, 30 + passiveMasteryControlHeight, 90, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 30 + passiveMasteryControlHeight, 90, 20}, "Cancel", function() node.sd = cachedSd node.allMasteryOptions = cachedAllMasteryOption self.build.spec.tree:ProcessStats(node) main:ClosePopup() end) - controls.effect = new("PassiveMasteryControl", {"TOPLEFT",nil,"TOPLEFT"}, {6, 25, 0, passiveMasteryControlHeight}, effects, self, node, controls.save) + controls.effect = new("PassiveMasteryControl"):PassiveMasteryControl({"TOPLEFT",nil,"TOPLEFT"}, {6, 25, 0, passiveMasteryControlHeight}, effects, self, node, controls.save) main:OpenPopup(controls.effect.width + 12, controls.effect.height + 60, node.name, controls, nil, nil, "close") end end @@ -1159,7 +1164,7 @@ function TreeTabClass:BuildPowerReportList(currentStat) end function TreeTabClass:FindTimelessJewel() - local socketViewer = new("PassiveTreeView") + local socketViewer = new("PassiveTreeView"):PassiveTreeView() local treeData = self.build.spec.tree local legionNodes = treeData.legion.nodes local legionAdditions = treeData.legion.additions @@ -1480,13 +1485,13 @@ function TreeTabClass:FindTimelessJewel() self.build.modFlag = true end - controls.devotionSelectLabel = new("LabelControl", {"TOPRIGHT", nil, "TOPLEFT"}, {820, 25, 0, 16}, "^7Devotion modifiers:") + controls.devotionSelectLabel = new("LabelControl"):LabelControl({"TOPRIGHT", nil, "TOPLEFT"}, {820, 25, 0, 16}, "^7Devotion modifiers:") controls.devotionSelectLabel.shown = timelessData.jewelType.id == 4 - controls.devotionSelect1 = new("DropDownControl", {"TOP", controls.devotionSelectLabel, "BOTTOM"}, {0, 8, 200, 18}, devotionVariants, function(index, value) + controls.devotionSelect1 = new("DropDownControl"):DropDownControl({"TOP", controls.devotionSelectLabel, "BOTTOM"}, {0, 8, 200, 18}, devotionVariants, function(index, value) timelessData.devotionVariant1 = index end) controls.devotionSelect1.selIndex = timelessData.devotionVariant1 - controls.devotionSelect2 = new("DropDownControl", {"TOP", controls.devotionSelect1, "BOTTOM"}, {0, 7, 200, 18}, devotionVariants, function(index, value) + controls.devotionSelect2 = new("DropDownControl"):DropDownControl({"TOP", controls.devotionSelect1, "BOTTOM"}, {0, 7, 200, 18}, devotionVariants, function(index, value) timelessData.devotionVariant2 = index end) controls.devotionSelect2.selIndex = timelessData.devotionVariant2 @@ -1496,7 +1501,7 @@ function TreeTabClass:FindTimelessJewel() local labelHeight = 16 local labelSpacing = 4 - controls.jewelSelect = new("DropDownControl", {"TOPLEFT", nil, "TOPLEFT"}, {380, 25, 200, rowHeight}, jewelTypes, function(index, value) + controls.jewelSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", nil, "TOPLEFT"}, {380, 25, 200, rowHeight}, jewelTypes, function(index, value) timelessData.jewelType = value controls.devotionSelectLabel.shown = value.id == 4 -- Militant Faith controls.protectAllocatedLabel.shown = (value.id == 4 and controls.socketFilter.state) @@ -1509,15 +1514,15 @@ function TreeTabClass:FindTimelessJewel() updateSearchList("", true) end) controls.jewelSelect.selIndex = timelessData.jewelType.id - controls.jewelSelectLabel = new("LabelControl", {"RIGHT", controls.jewelSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Type:") + controls.jewelSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.jewelSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Type:") - controls.conquerorSelect = new("DropDownControl", {"TOPLEFT", controls.jewelSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, conquerorTypes[timelessData.jewelType.id], function(index, value) + controls.conquerorSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.jewelSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, conquerorTypes[timelessData.jewelType.id], function(index, value) timelessData.conquerorType = value self.build.modFlag = true end) controls.conquerorSelect.selIndex = timelessData.conquerorType.id - controls.conquerorSelectLabel = new("LabelControl", {"RIGHT", controls.conquerorSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Conqueror:") + controls.conquerorSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.conquerorSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Conqueror:") local allocatedNodes = { } local protectedNodes = { } @@ -1542,7 +1547,7 @@ function TreeTabClass:FindTimelessJewel() end - controls.socketSelect = new("TimelessJewelSocketControl", {"TOPLEFT", controls.conquerorSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, jewelSockets, function(index, value) + controls.socketSelect = new("TimelessJewelSocketControl"):TimelessJewelSocketControl({"TOPLEFT", controls.conquerorSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, jewelSockets, function(index, value) timelessData.jewelSocket = value setAllocatedNodes() -- reset list when changing sockets self.build.modFlag = true @@ -1554,7 +1559,7 @@ function TreeTabClass:FindTimelessJewel() break end end - controls.socketSelectLabel = new("LabelControl", {"RIGHT", controls.socketSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Socket:") + controls.socketSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.socketSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Jewel Socket:") local function clearProtected() -- clear all controls, nodes related to Militant Faith filtering protectedNodesCount = 0 @@ -1566,7 +1571,7 @@ function TreeTabClass:FindTimelessJewel() end end - controls.socketFilter = new("CheckBoxControl", {"TOPLEFT", controls.socketSelect, "BOTTOMLEFT"}, {0, rowSpacing, rowHeight}, nil, function(value) + controls.socketFilter = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT", controls.socketSelect, "BOTTOMLEFT"}, {0, rowSpacing, rowHeight}, nil, function(value) timelessData.socketFilter = value self.build.modFlag = true controls.socketFilterAdditionalDistanceLabel.shown = value @@ -1580,7 +1585,7 @@ function TreeTabClass:FindTimelessJewel() clearProtected() end end) - controls.socketFilterLabel = new("LabelControl", {"RIGHT", controls.socketFilter, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Filter Nodes:") + controls.socketFilterLabel = new("LabelControl"):LabelControl({"RIGHT", controls.socketFilter, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Filter Nodes:") controls.socketFilter.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() tooltip:AddLine(16, "^7Enable this option to exclude nodes that you do not have allocated on your active passive skill tree.") @@ -1589,17 +1594,17 @@ function TreeTabClass:FindTimelessJewel() controls.socketFilter.state = timelessData.socketFilter -- Militant Faith protect notables controls - controls.protectAllocatedLabel = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, { 15, 25, 0, 16 }, "^7Protect allocated nodes from changing:") - controls.protectAllocatedSelect = new("DropDownControl", { "TOPLEFT", controls.protectAllocatedLabel, "BOTTOMLEFT" }, { 0, 8, 200, 18 }, nil, nil) - controls.protectAllocatedButtonAdd = new("ButtonControl", { "LEFT", controls.protectAllocatedSelect, "RIGHT" }, { 5, 0, 44, 18 }, "Add", function() + controls.protectAllocatedLabel = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, { 15, 25, 0, 16 }, "^7Protect allocated nodes from changing:") + controls.protectAllocatedSelect = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.protectAllocatedLabel, "BOTTOMLEFT" }, { 0, 8, 200, 18 }, nil, nil) + controls.protectAllocatedButtonAdd = new("ButtonControl"):ButtonControl({ "LEFT", controls.protectAllocatedSelect, "RIGHT" }, { 5, 0, 44, 18 }, "Add", function() local selValue = controls.protectAllocatedSelect:GetSelValue() if selValue and not controls["protected:"..selValue] then protectedNodesCount = protectedNodesCount + 1 t_insert(protectedNodes, selValue) - controls["protected:"..selValue] = new("LabelControl", { "TOPLEFT", controls.protectAllocatedSelect, "BOTTOMLEFT" }, { 0, 16 * protectedNodesCount - 10, 0, 16 }, "^7"..selValue) + controls["protected:"..selValue] = new("LabelControl"):LabelControl({ "TOPLEFT", controls.protectAllocatedSelect, "BOTTOMLEFT" }, { 0, 16 * protectedNodesCount - 10, 0, 16 }, "^7"..selValue) end end) - controls.protectAllocatedButtonClear = new("ButtonControl", { "LEFT", controls.protectAllocatedButtonAdd, "RIGHT" }, { 5, 0, 44, 18 }, "Clear", function() + controls.protectAllocatedButtonClear = new("ButtonControl"):ButtonControl({ "LEFT", controls.protectAllocatedButtonAdd, "RIGHT" }, { 5, 0, 44, 18 }, "Clear", function() clearProtected() end) -- set shown and list on load @@ -1615,8 +1620,8 @@ function TreeTabClass:FindTimelessJewel() end local socketFilterAdditionalDistanceMAX = 10 - controls.socketFilterAdditionalDistanceLabel = new("LabelControl", {"LEFT", controls.socketFilter, "RIGHT"}, {10, 0, 0, 16}, "^7Node Distance:") - controls.socketFilterAdditionalDistance = new("SliderControl", {"LEFT", controls.socketFilterAdditionalDistanceLabel, "RIGHT"}, {10, 0, 66, 18}, function(value) + controls.socketFilterAdditionalDistanceLabel = new("LabelControl"):LabelControl({"LEFT", controls.socketFilter, "RIGHT"}, {10, 0, 0, 16}, "^7Node Distance:") + controls.socketFilterAdditionalDistance = new("SliderControl"):SliderControl({"LEFT", controls.socketFilterAdditionalDistanceLabel, "RIGHT"}, {10, 0, 66, 18}, function(value) timelessData.socketFilterDistance = m_floor(value * socketFilterAdditionalDistanceMAX + 0.01) controls.socketFilterAdditionalDistanceValue.label = s_format("^7%d", timelessData.socketFilterDistance) end, { ["SHIFT"] = 1, ["CTRL"] = 1 / (socketFilterAdditionalDistanceMAX * 2), ["DEFAULT"] = 1 / socketFilterAdditionalDistanceMAX }) @@ -1635,7 +1640,7 @@ function TreeTabClass:FindTimelessJewel() end return controls.socketFilterAdditionalDistance.tooltip.realDraw(self, x, y, width, height, viewPort) end - controls.socketFilterAdditionalDistanceValue = new("LabelControl", {"LEFT", controls.socketFilterAdditionalDistance, "RIGHT"}, {5, 0, 0, 16}, "^70") + controls.socketFilterAdditionalDistanceValue = new("LabelControl"):LabelControl({"LEFT", controls.socketFilterAdditionalDistance, "RIGHT"}, {5, 0, 0, 16}, "^70") controls.socketFilterAdditionalDistance:SetVal((timelessData.socketFilterDistance or 0) / socketFilterAdditionalDistanceMAX) controls.socketFilterAdditionalDistanceLabel.shown = timelessData.socketFilter controls.socketFilterAdditionalDistance.shown = timelessData.socketFilter @@ -1645,11 +1650,11 @@ function TreeTabClass:FindTimelessJewel() local scrollWheelSpeedTbl2 = { ["SHIFT"] = 0.2, ["CTRL"] = 0.002, ["DEFAULT"] = 0.02 } local nodeSliderStatLabel = "None" - controls.nodeSlider = new("SliderControl", {"TOPLEFT", controls.socketFilter, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + controls.nodeSlider = new("SliderControl"):SliderControl({"TOPLEFT", controls.socketFilter, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) controls.nodeSliderValue.label = s_format("^7%.3f", value * 10) parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) end, scrollWheelSpeedTbl) - controls.nodeSliderLabel = new("LabelControl", {"RIGHT", controls.nodeSlider, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Primary Node Weight:") + controls.nodeSliderLabel = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Primary Node Weight:") controls.nodeSlider.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() if not controls.nodeSlider.dragging then @@ -1661,7 +1666,7 @@ function TreeTabClass:FindTimelessJewel() end end end - controls.nodeSliderValue = new("LabelControl", {"LEFT", controls.nodeSlider, "RIGHT"}, {5, 0, 0, 16}, "^71.000") + controls.nodeSliderValue = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider, "RIGHT"}, {5, 0, 0, 16}, "^71.000") controls.nodeSlider.tooltip.realDraw = controls.nodeSlider.tooltip.Draw controls.nodeSlider.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.nodeSlider.val)) @@ -1674,11 +1679,11 @@ function TreeTabClass:FindTimelessJewel() controls.nodeSlider:SetVal(0.1) local nodeSlider2StatLabel = "None" - controls.nodeSlider2 = new("SliderControl", {"TOPLEFT", controls.nodeSlider, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + controls.nodeSlider2 = new("SliderControl"):SliderControl({"TOPLEFT", controls.nodeSlider, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) controls.nodeSlider2Value.label = s_format("^7%.3f", value * 10) parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) end, scrollWheelSpeedTbl) - controls.nodeSlider2Label = new("LabelControl", {"RIGHT", controls.nodeSlider2, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Secondary Node Weight:") + controls.nodeSlider2Label = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider2, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Secondary Node Weight:") controls.nodeSlider2.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() if not controls.nodeSlider2.dragging then @@ -1690,7 +1695,7 @@ function TreeTabClass:FindTimelessJewel() end end end - controls.nodeSlider2Value = new("LabelControl", {"LEFT", controls.nodeSlider2, "RIGHT"}, {5, 0, 0, 16}, "^71.000") + controls.nodeSlider2Value = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider2, "RIGHT"}, {5, 0, 0, 16}, "^71.000") controls.nodeSlider2.tooltip.realDraw = controls.nodeSlider2.tooltip.Draw controls.nodeSlider2.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.nodeSlider2.val)) @@ -1702,7 +1707,7 @@ function TreeTabClass:FindTimelessJewel() end controls.nodeSlider2:SetVal(0.1) - controls.nodeSlider3 = new("SliderControl", {"TOPLEFT", controls.nodeSlider2, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) + controls.nodeSlider3 = new("SliderControl"):SliderControl({"TOPLEFT", controls.nodeSlider2, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, function(value) if value == 1 then controls.nodeSlider3Value.label = "^7Required" else @@ -1710,14 +1715,14 @@ function TreeTabClass:FindTimelessJewel() end parseSearchList(1, controls.searchListFallback and controls.searchListFallback.shown or false) end, scrollWheelSpeedTbl2) - controls.nodeSlider3Label = new("LabelControl", {"RIGHT", controls.nodeSlider3, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Minimum Node Weight:") + controls.nodeSlider3Label = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSlider3, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Minimum Node Weight:") controls.nodeSlider3.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() if not controls.nodeSlider3.dragging then tooltip:AddLine(16, "^7Seeds that do not meet the minimum weight threshold for a desired node are excluded from the search results.") end end - controls.nodeSlider3Value = new("LabelControl", {"LEFT", controls.nodeSlider3, "RIGHT"}, {5, 0, 0, 16}, "^70") + controls.nodeSlider3Value = new("LabelControl"):LabelControl({"LEFT", controls.nodeSlider3, "RIGHT"}, {5, 0, 0, 16}, "^70") controls.nodeSlider3.tooltip.realDraw = controls.nodeSlider3.tooltip.Draw controls.nodeSlider3.tooltip.Draw = function(self, x, y, width, height, viewPort) local sliderOffsetX = round(184 * (1 - controls.nodeSlider3.val)) @@ -1756,7 +1761,7 @@ function TreeTabClass:FindTimelessJewel() end buildMods() - controls.nodeSelect = new("DropDownControl", {"TOPLEFT", controls.nodeSlider3, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, modData, function(index, value) + controls.nodeSelect = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.nodeSlider3, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, modData, function(index, value) nodeSliderStatLabel = "None" nodeSlider2StatLabel = "None" if value.id then @@ -1815,7 +1820,7 @@ function TreeTabClass:FindTimelessJewel() self.build.modFlag = true end end) - controls.nodeSelectLabel = new("LabelControl", {"RIGHT", controls.nodeSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Search for Node:") + controls.nodeSelectLabel = new("LabelControl"):LabelControl({"RIGHT", controls.nodeSelect, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Search for Node:") controls.nodeSelect.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() if mode ~= "OUT" and value.descriptions then @@ -2000,12 +2005,12 @@ function TreeTabClass:FindTimelessJewel() }) end end - controls.fallbackWeightsList = new("DropDownControl", {"TOPLEFT", controls.nodeSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, fallbackWeightsList, function(index) + controls.fallbackWeightsList = new("DropDownControl"):DropDownControl({"TOPLEFT", controls.nodeSelect, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, fallbackWeightsList, function(index) timelessData.fallbackWeightMode.idx = index end) - controls.fallbackWeightsLabel = new("LabelControl", {"RIGHT", controls.fallbackWeightsList, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Fallback Weight Mode:") + controls.fallbackWeightsLabel = new("LabelControl"):LabelControl({"RIGHT", controls.fallbackWeightsList, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Fallback Weight Mode:") controls.fallbackWeightsList.selIndex = timelessData.fallbackWeightMode.idx or 1 - controls.fallbackWeightsButton = new("ButtonControl", {"LEFT", controls.fallbackWeightsList, "RIGHT"}, {5, 0, 66, 18}, "Generate", function() + controls.fallbackWeightsButton = new("ButtonControl"):ButtonControl({"LEFT", controls.fallbackWeightsList, "RIGHT"}, {5, 0, 66, 18}, "Generate", function() setupFallbackWeights() controls.searchListFallbackButton.label = "^4Fallback Nodes" end) @@ -2013,12 +2018,12 @@ function TreeTabClass:FindTimelessJewel() tooltip:Clear() tooltip:AddLine(16, "^7Click this button to generate new fallback node weights, replacing your old ones.") end - controls.totalMinimumWeight = new("EditControl", {"TOPLEFT", controls.fallbackWeightsList, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, "", nil, "%D", nil, function(val) + controls.totalMinimumWeight = new("EditControl"):EditControl({"TOPLEFT", controls.fallbackWeightsList, "BOTTOMLEFT"}, {0, rowSpacing, 200, rowHeight}, "", nil, "%D", nil, function(val) local num = tonumber(val) timelessData.totalMinimumWeight = num or nil self.build.modFlag = true end) - controls.totalMinimumWeightLabel = new("LabelControl", {"RIGHT", controls.totalMinimumWeight, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Total Minimum Weight:") + controls.totalMinimumWeightLabel = new("LabelControl"):LabelControl({"RIGHT", controls.totalMinimumWeight, "LEFT"}, {-labelSpacing, 0, 0, labelHeight}, "^7Total Minimum Weight:") controls.totalMinimumWeight.tooltipFunc = function(tooltip, mode, index, value) tooltip:Clear() tooltip:AddLine(16, "^7Optional: Only show results where total weight meets or exceeds this value.") @@ -2029,7 +2034,7 @@ function TreeTabClass:FindTimelessJewel() local buttonHeight = 20 local edgePadding = 12 local listYOffset = -(buttonHeight + edgePadding * 2) - controls.searchList = new("EditControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + controls.searchList = new("EditControl"):EditControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, { edgePadding, listYOffset, listWidth, listHeight }, timelessData.searchList, nil, "^%C\t\n", nil, function(value) timelessData.searchList = value @@ -2040,7 +2045,7 @@ function TreeTabClass:FindTimelessJewel() controls.searchList.enabled = true controls.searchList:SetText(timelessData.searchList and timelessData.searchList or "") - controls.searchListFallback = new("EditControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + controls.searchListFallback = new("EditControl"):EditControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, { edgePadding, listYOffset, listWidth, listHeight }, timelessData.searchListFallback, nil, "^%C\t\n", nil, function(value) timelessData.searchListFallback = value @@ -2051,7 +2056,7 @@ function TreeTabClass:FindTimelessJewel() controls.searchListFallback.enabled = false controls.searchListFallback:SetText(timelessData.searchListFallback and timelessData.searchListFallback or "") - controls.searchListButton = new("ButtonControl", + controls.searchListButton = new("ButtonControl"):ButtonControl( { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, { edgePadding, listYOffset - listHeight - rowSpacing, 106, buttonHeight }, "^7Desired Nodes", function() if controls.searchListFallback.shown then @@ -2070,7 +2075,7 @@ function TreeTabClass:FindTimelessJewel() end controls.searchListButton.locked = function() return controls.searchList.shown end - controls.searchListFallbackButton = new("ButtonControl", {"LEFT", controls.searchListButton, "RIGHT"}, {5, 0, 110, buttonHeight}, "^7Fallback Nodes", function() + controls.searchListFallbackButton = new("ButtonControl"):ButtonControl({"LEFT", controls.searchListButton, "RIGHT"}, {5, 0, 110, buttonHeight}, "^7Fallback Nodes", function() controls.searchList.shown = false controls.searchList.enabled = false controls.searchListFallback.shown = true @@ -2087,11 +2092,11 @@ function TreeTabClass:FindTimelessJewel() end controls.searchListFallbackButton.locked = function() return controls.searchListFallback.shown end - controls.searchResults = new("TimelessJewelListControl", { "BOTTOMLEFT", nil, "BOTTOMLEFT" }, + controls.searchResults = new("TimelessJewelListControl"):TimelessJewelListControl({ "BOTTOMLEFT", nil, "BOTTOMLEFT" }, { edgePadding*2 + listWidth, -(buttonHeight + edgePadding * 2), listWidth, listHeight }, self.build) - self.tradeQueryRequests = new("TradeQueryRequests") - controls.msg = new("LabelControl", nil, { -280, 5, 0, 20 }, "") - controls.searchTradeButton = new("ButtonControl", { "BOTTOMRIGHT", controls.searchResults, "TOPRIGHT" }, { 0, -rowSpacing, 170, buttonHeight }, "Open Trade URL", function() + self.tradeQueryRequests = new("TradeQueryRequests"):TradeQueryRequests() + controls.msg = new("LabelControl"):LabelControl(nil, { -280, 5, 0, 20 }, "") + controls.searchTradeButton = new("ButtonControl"):ButtonControl({ "BOTTOMRIGHT", controls.searchResults, "TOPRIGHT" }, { 0, -rowSpacing, 170, buttonHeight }, "Open Trade URL", function() local seedTrades = {} local startRow, endRow if controls.searchResults.highlightIndex and not controls.searchMore.state then @@ -2210,17 +2215,17 @@ function TreeTabClass:FindTimelessJewel() tooltip:AddLine(16, "^7After selecting a row You can also shift+click on another row to select a range of rows to search.") end - controls.searchTradeLeagueSelect = new("DropDownControl", { "RIGHT", controls.searchTradeButton, "LEFT" }, + controls.searchTradeLeagueSelect = new("DropDownControl"):DropDownControl({ "RIGHT", controls.searchTradeButton, "LEFT" }, { -labelSpacing, 0, 140, buttonHeight }, nil, function(idx, val) self.timelessJewelLeagueSelect = val end) - controls.searchTradeLeagueLabel = new("LabelControl", { "TOPRIGHT", controls.searchTradeLeagueSelect, "TOPLEFT" }, + controls.searchTradeLeagueLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", controls.searchTradeLeagueSelect, "TOPLEFT" }, { -labelSpacing, 0, 0, labelHeight }, "^7League:") -- Realm selection self.realmList = { "PC", "Sony", "Xbox" } - controls.realmSelection = new("DropDownControl", { "BOTTOMLEFT", controls.searchTradeLeagueSelect, "TOPLEFT" }, + controls.realmSelection = new("DropDownControl"):DropDownControl({ "BOTTOMLEFT", controls.searchTradeLeagueSelect, "TOPLEFT" }, { 0, -rowSpacing, 50, buttonHeight }, self.realmList, nil) local function updateLeagues() local currentRealmId = controls.realmSelection:GetSelValue():lower() @@ -2274,7 +2279,7 @@ function TreeTabClass:FindTimelessJewel() -- manually call the function because when initialising, because the -- function does not get called when the selection index stays the same controls.realmSelection.selFunc(controls.realmSelection.selIndex) - controls.realmLabel = new("LabelControl", { "TOPRIGHT", controls.realmSelection, "TOPLEFT" }, + controls.realmLabel = new("LabelControl"):LabelControl({ "TOPRIGHT", controls.realmSelection, "TOPLEFT" }, { -labelSpacing, 0, 0, labelHeight }, "^7Realm:") -- Buyout selection @@ -2285,7 +2290,7 @@ function TreeTabClass:FindTimelessJewel() "In person (online)", "Any (includes offline)" } - controls.tradeTypeSelection = new("DropDownControl", { "BOTTOMRIGHT", controls.searchTradeButton, "TOPRIGHT" }, + controls.tradeTypeSelection = new("DropDownControl"):DropDownControl({ "BOTTOMRIGHT", controls.searchTradeButton, "TOPRIGHT" }, { 0, -rowSpacing, 205, buttonHeight }, tradeTypes, function(index, value) self.tradeTypeIndex = index end) @@ -2294,7 +2299,7 @@ function TreeTabClass:FindTimelessJewel() controls.tradeTypeSelection:SetSel(self.tradeTypeIndex) -- Checkbox to search a lot at once, or just a few - controls.searchMore = new("CheckBoxControl", { "BOTTOMRIGHT", controls.tradeTypeSelection, "TOPRIGHT" }, + controls.searchMore = new("CheckBoxControl"):CheckBoxControl({ "BOTTOMRIGHT", controls.tradeTypeSelection, "TOPRIGHT" }, { 0, -rowSpacing, 19 }, nil, function(state) self.lastSearchMore = state end, @@ -2304,7 +2309,7 @@ function TreeTabClass:FindTimelessJewel() if self.lastSearchMore then controls.searchMore.state = self.lastSearchMore end - controls.searchMoreLabel = new("LabelControl", { "RIGHT", controls.searchMore, "LEFT" }, + controls.searchMoreLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.searchMore, "LEFT" }, { -labelSpacing, 0, 0, labelHeight }, "^7Search Maximum Amount:") -- Helper function to search a single socket @@ -2626,17 +2631,17 @@ function TreeTabClass:FindTimelessJewel() local buttonDivider = 10 local buttonWidth = 80 -- reset button anchored to middle of panel and other buttons anchored to it - controls.resetButton = new("ButtonControl", {"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {panelWidth / 2 - buttonWidth/2, -edgePadding, buttonWidth, buttonHeight}, "Reset", function() + controls.resetButton = new("ButtonControl"):ButtonControl({"BOTTOMLEFT", nil, "BOTTOMLEFT"}, {panelWidth / 2 - buttonWidth/2, -edgePadding, buttonWidth, buttonHeight}, "Reset", function() updateSearchList("", true) updateSearchList("", false) wipeTable(timelessData.searchResults) controls.searchTradeButton.enabled = false clearProtected() end) - controls.closeButton = new("ButtonControl", {"LEFT", controls.resetButton, "RIGHT"}, {buttonDivider, 0, buttonWidth, buttonHeight}, "Cancel", function() + controls.closeButton = new("ButtonControl"):ButtonControl({"LEFT", controls.resetButton, "RIGHT"}, {buttonDivider, 0, buttonWidth, buttonHeight}, "Cancel", function() main:ClosePopup() end) - controls.searchButton = new("ButtonControl", {"RIGHT", controls.resetButton, "LEFT"}, {-buttonDivider, 0, buttonWidth, buttonHeight}, "Search", function() + controls.searchButton = new("ButtonControl"):ButtonControl({"RIGHT", controls.resetButton, "LEFT"}, {-buttonDivider, 0, buttonWidth, buttonHeight}, "Search", function() if timelessData.jewelSocket.id == -1 then wipeTable(timelessData.searchResults) wipeTable(timelessData.sharedResults) diff --git a/src/Classes/UndoHandler.lua b/src/Classes/UndoHandler.lua index 6759de6cf0..3103b2faa2 100644 --- a/src/Classes/UndoHandler.lua +++ b/src/Classes/UndoHandler.lua @@ -9,10 +9,14 @@ local t_insert = table.insert local t_remove = table.remove -local UndoHandlerClass = newClass("UndoHandler", function(self) +---@class UndoHandler +local UndoHandlerClass = newClass("UndoHandler") + +function UndoHandlerClass:UndoHandler() self.undo = { } self.redo = { } -end) + return self +end -- Initialises the undo/redo buffers -- Should be called after the current state is first loaded/initialised diff --git a/src/Export/Classes/Dat64File.lua b/src/Export/Classes/Dat64File.lua index 9ebb0b6e22..4d052f3423 100644 --- a/src/Export/Classes/Dat64File.lua +++ b/src/Export/Classes/Dat64File.lua @@ -84,7 +84,10 @@ local dataTypes = { }, } -local Dat64FileClass = newClass("Dat64File", function(self, name, raw) +---@class Dat64File +local Dat64FileClass = newClass("Dat64File") + +function Dat64FileClass:Dat64File(name, raw) self.name = name:lower() self.raw = raw @@ -124,7 +127,8 @@ local Dat64FileClass = newClass("Dat64File", function(self, name, raw) --ConPrintf("Loaded '%s': %d Rows at %d Bytes", self.name, self.rowCount, self.rowSize) self:OnSpecChanged() -end) + return self +end function Dat64FileClass:OnSpecChanged() wipeTable(self.cols) diff --git a/src/Export/Classes/DatFile.lua b/src/Export/Classes/DatFile.lua index f63f80a92e..6bc843fe95 100644 --- a/src/Export/Classes/DatFile.lua +++ b/src/Export/Classes/DatFile.lua @@ -76,7 +76,10 @@ local dataTypes = { }, } -local DatFileClass = newClass("DatFile", function(self, name, raw) +---@class DatFile +local DatFileClass = newClass("DatFile") + +function DatFileClass:DatFile(name, raw) self.name = name self.raw = raw @@ -116,7 +119,8 @@ local DatFileClass = newClass("DatFile", function(self, name, raw) --ConPrintf("Loaded '%s': %d Rows at %d Bytes", self.name, self.rowCount, self.rowSize) self:OnSpecChanged() -end) + return self +end function DatFileClass:OnSpecChanged() wipeTable(self.cols) diff --git a/src/Export/Classes/DatListControl.lua b/src/Export/Classes/DatListControl.lua index e1153982d9..a47aac70d7 100644 --- a/src/Export/Classes/DatListControl.lua +++ b/src/Export/Classes/DatListControl.lua @@ -3,12 +3,16 @@ -- Class: Dat List -- Dat list control. -- -local DatListClass = newClass("DatListControl", "ListControl", function(self, anchor, rect) +---@class DatListControl: ListControl +local DatListClass = newClass("DatListControl", "ListControl") + +function DatListClass:DatListControl(anchor, rect) self.originalList = main.datFileList self.searchBuf = "" self.filteredList = self.originalList - self.ListControl(anchor, rect, 14, "VERTICAL", false, self.filteredList) -end) + self:ListControl(anchor, rect, 14, "VERTICAL", false, self.filteredList) + return self +end function DatListClass:BuildFilteredList() local search = self.searchBuf:lower() diff --git a/src/Export/Classes/GGPKData.lua b/src/Export/Classes/GGPKData.lua index 4092782c0e..b2eafd79f9 100644 --- a/src/Export/Classes/GGPKData.lua +++ b/src/Export/Classes/GGPKData.lua @@ -31,7 +31,10 @@ end -- Path can be in any format recognized by the extractor at oozPath, ie, -- a .ggpk file or a Steam Path of Exile directory -local GGPKClass = newClass("GGPKData", function(self, path, datPath, reExport) +---@class GGPKData +local GGPKClass = newClass("GGPKData") + +function GGPKClass:GGPKData(path, datPath, reExport) if datPath then self.oozPath = datPath:match("\\$") and datPath or (datPath .. "\\") else @@ -46,7 +49,8 @@ local GGPKClass = newClass("GGPKData", function(self, path, datPath, reExport) self.ot = { } self:AddDat64Files() -end) + return self +end function GGPKClass:CleanDir(reExport) if reExport then diff --git a/src/Export/Classes/GGPKSourceListControl.lua b/src/Export/Classes/GGPKSourceListControl.lua index 90f01fd3ca..ab478c1f8e 100644 --- a/src/Export/Classes/GGPKSourceListControl.lua +++ b/src/Export/Classes/GGPKSourceListControl.lua @@ -3,46 +3,50 @@ -- Class: GGPK Source List -- GGPK source list control. -- -local GGPKSourceListClass = newClass("GGPKSourceListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 16, false, false, main.datSources) +---@class GGPKSourceListControl: ListControl +local GGPKSourceListClass = newClass("GGPKSourceListControl", "ListControl") + +function GGPKSourceListClass:GGPKSourceListControl(anchor, rect) + self:ListControl(anchor, rect, 16, false, false, main.datSources) self.colList = { { width = self.width * 0.25, label = "Name", sortable = true }, { width = self.width * 0.75, label = "Spec File Path" }, } self.colLabels = true - self.controls.new = new("ButtonControl", {"BOTTOMLEFT",self,"TOP"}, {-62, -4, 60, 18}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self,"TOP"}, {-62, -4, 60, 18}, "New", function() local datSource = {} self:EditDATSource(datSource, true) end) - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.new,"RIGHT"}, {4, 0, 60, 18}, "Delete", function() self:OnSelDelete(self.selIndex) end) self.controls.delete.enabled = function() return self.selValue ~= nil and #self.list > 1 end -end) + return self +end function GGPKSourceListClass:EditDATSource(datSource, newSource) local controls = { } - controls.labelLabel = new("LabelControl", nil, {-30, 20, 0, 16}, "^7Name:") - controls.label = new("EditControl", nil, {85, 20, 180, 20}, datSource.label, nil, nil, nil, function(buf) + controls.labelLabel = new("LabelControl"):LabelControl(nil, {-30, 20, 0, 16}, "^7Name:") + controls.label = new("EditControl"):EditControl(nil, {85, 20, 180, 20}, datSource.label, nil, nil, nil, function(buf) controls.save.enabled = (controls.dat.buf:match("%S") or controls.ggpk.buf:match("%S")) and buf:match("%S") end) - controls.ggpkLabel = new("LabelControl", nil, {0, 40, 0, 16}, "^7Source from GGPK/Steam PoE path:") - controls.ggpk = new("EditControl", {"TOP",controls.ggpkLabel,"TOP"}, {0, 20, 350, 20}, datSource.ggpkPath, nil, nil, nil, function(buf) + controls.ggpkLabel = new("LabelControl"):LabelControl(nil, {0, 40, 0, 16}, "^7Source from GGPK/Steam PoE path:") + controls.ggpk = new("EditControl"):EditControl({"TOP",controls.ggpkLabel,"TOP"}, {0, 20, 350, 20}, datSource.ggpkPath, nil, nil, nil, function(buf) controls.save.enabled = (buf:match("%S") or controls.dat.buf:match("%S")) and controls.label.buf:match("%S") and controls.spec.buf:match("%S") end) controls.ggpk.enabled = function() return not controls.dat.buf:match("%S") end - controls.datLabel = new("LabelControl", {"TOP",controls.ggpk,"TOP"}, {0, 22, 0, 16}, "^7Source from DAT files:") - controls.dat = new("EditControl", {"TOP",controls.datLabel,"TOP"}, {0, 20, 350, 20}, datSource.datFilePath, nil, nil, nil, function(buf) + controls.datLabel = new("LabelControl"):LabelControl({"TOP",controls.ggpk,"TOP"}, {0, 22, 0, 16}, "^7Source from DAT files:") + controls.dat = new("EditControl"):EditControl({"TOP",controls.datLabel,"TOP"}, {0, 20, 350, 20}, datSource.datFilePath, nil, nil, nil, function(buf) controls.save.enabled = (buf:match("%S") or controls.ggpk.buf:match("%S")) and controls.label.buf:match("%S") and controls.spec.buf:match("%S") end) controls.dat.enabled = function() return not controls.ggpk.buf:match("%S") end - controls.specLabel = new("LabelControl", {"TOP",controls.dat,"TOP"}, {0, 22, 0, 16}, "^7Spec File location:") - controls.spec = new("EditControl", {"TOP",controls.specLabel,"TOP"}, {0, 20, 350, 20}, datSource.spec or "spec.lua", nil, nil, nil, function(buf) + controls.specLabel = new("LabelControl"):LabelControl({"TOP",controls.dat,"TOP"}, {0, 22, 0, 16}, "^7Spec File location:") + controls.spec = new("EditControl"):EditControl({"TOP",controls.specLabel,"TOP"}, {0, 20, 350, 20}, datSource.spec or "spec.lua", nil, nil, nil, function(buf) controls.save.enabled = (controls.dat.buf:match("%S") or controls.ggpk.buf:match("%S")) and controls.label.buf:match("%S") and buf:match("%S") end) - controls.save = new("ButtonControl", {"TOP",controls.spec,"TOP"}, {-45, 22, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({"TOP",controls.spec,"TOP"}, {-45, 22, 80, 20}, "Save", function() local reload = datSource.label == (main.datSource and main.datSource.label) datSource.label = controls.label.buf datSource.ggpkPath = controls.ggpk.buf or "" @@ -59,7 +63,7 @@ function GGPKSourceListClass:EditDATSource(datSource, newSource) main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", {"TOP",controls.spec,"TOP"}, {45, 22, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({"TOP",controls.spec,"TOP"}, {45, 22, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 200, datSource[1] and "Edit DAT Source" or "New DAT Source", controls, "save", "edit") diff --git a/src/Export/Classes/RowListControl.lua b/src/Export/Classes/RowListControl.lua index 08d1e344dc..ace29a0534 100644 --- a/src/Export/Classes/RowListControl.lua +++ b/src/Export/Classes/RowListControl.lua @@ -6,11 +6,15 @@ local ipairs = ipairs local t_insert = table.insert -local RowListClass = newClass("RowListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 14, "HORIZONTAL", false, { }) +---@class RowListControl: ListControl +local RowListClass = newClass("RowListControl", "ListControl") + +function RowListClass:RowListControl(anchor, rect) + self:ListControl(anchor, rect, 14, "HORIZONTAL", false, { }) self.colLabels = true self._autoSizeToggleState = {} -- internal toggle memory, not saved to spec -end) + return self +end function RowListClass:BuildRows(filter) wipeTable(self.list) diff --git a/src/Export/Classes/ScriptListControl.lua b/src/Export/Classes/ScriptListControl.lua index 048f02544c..c4bc132769 100644 --- a/src/Export/Classes/ScriptListControl.lua +++ b/src/Export/Classes/ScriptListControl.lua @@ -3,9 +3,13 @@ -- Class: Script List -- Script list control. -- -local ScriptListClass = newClass("ScriptListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 16, "VERTICAL", false, main.scriptList) -end) +---@class ScriptListControl: ListControl +local ScriptListClass = newClass("ScriptListControl", "ListControl") + +function ScriptListClass:ScriptListControl(anchor, rect) + self:ListControl(anchor, rect, 16, "VERTICAL", false, main.scriptList) + return self +end function ScriptListClass:GetRowValue(column, index, script) if column == 1 then diff --git a/src/Export/Classes/SpecColListControl.lua b/src/Export/Classes/SpecColListControl.lua index 9371234e68..ca491dcf11 100644 --- a/src/Export/Classes/SpecColListControl.lua +++ b/src/Export/Classes/SpecColListControl.lua @@ -5,9 +5,13 @@ -- local t_remove = table.remove -local SpecColListClass = newClass("SpecColListControl", "ListControl", function(self, anchor, rect) - self.ListControl(anchor, rect, 14, "VERTICAL", true) -end) +---@class SpecColListControl: ListControl +local SpecColListClass = newClass("SpecColListControl", "ListControl") + +function SpecColListClass:SpecColListControl(anchor, rect) + self:ListControl(anchor, rect, 14, "VERTICAL", true) + return self +end function SpecColListClass:GetRowValue(column, index, specCol) if column == 1 then diff --git a/src/Export/Main.lua b/src/Export/Main.lua index b840261a33..de597f711b 100644 --- a/src/Export/Main.lua +++ b/src/Export/Main.lua @@ -20,7 +20,7 @@ LoadModule("../Modules/Common.lua") LoadModule("../Classes/ControlHost.lua") -main = new("ControlHost") +main = new("ControlHost"):ControlHost() local classList = { "UndoHandler", @@ -158,14 +158,14 @@ function main:Init() self.colList = { } - self.controls.shownLeagueLabel = new("LabelControl", nil, {10, 10, 100, 16}, "^7Data from:") - self.controls.leagueLabel = new("LabelControl", {"LEFT", self.controls.shownLeagueLabel, "RIGHT"}, {10, 0, 100, 16}, function() return "^7" .. (self.leagueLabel or "Unknown") end) - self.controls.addSource = new("ButtonControl", nil, {10, 30, 100, 18}, "Edit Sources...", function() - self.OpenPathPopup() + self.controls.shownLeagueLabel = new("LabelControl"):LabelControl(nil, {10, 10, 100, 16}, "^7Data from:") + self.controls.leagueLabel = new("LabelControl"):LabelControl({"LEFT", self.controls.shownLeagueLabel, "RIGHT"}, {10, 0, 100, 16}, function() return "^7" .. (self.leagueLabel or "Unknown") end) + self.controls.addSource = new("ButtonControl"):ButtonControl(nil, {10, 30, 100, 18}, "Edit Sources...", function() + self:OpenPathPopup() end) self.datSources = self.datSources or { } - self.controls.datSource = new("DropDownControl", nil, {10, 50, 250, 18}, self.datSources, function(_, value) + self.controls.datSource = new("DropDownControl"):DropDownControl(nil, {10, 50, 250, 18}, self.datSources, function(_, value) self:LoadDatSource(value) end, nil) @@ -173,11 +173,11 @@ function main:Init() self.controls.datSource:SelByValue(self.datSource.label, "label") end - self.controls.scripts = new("ButtonControl", nil, {160, 30, 100, 18}, "Scripts >>", function() + self.controls.scripts = new("ButtonControl"):ButtonControl(nil, {160, 30, 100, 18}, "Scripts >>", function() self:SetCurrentDat() end) - self.controls.scriptAll = new("ButtonControl", nil, {270, 10, 140, 18}, "Run All", function() + self.controls.scriptAll = new("ButtonControl"):ButtonControl(nil, {270, 10, 140, 18}, "Run All", function() do -- run stat desc first local errMsg = PLoadModule("Scripts/".."statdesc"..".lua") if errMsg then @@ -195,7 +195,7 @@ function main:Init() end } - self.controls.clearOutput = new("ButtonControl", nil, {1230, 10, 100, 18}, "Clear", function() + self.controls.clearOutput = new("ButtonControl"):ButtonControl(nil, {1230, 10, 100, 18}, "Clear", function() wipeTable(self.scriptOutput) end) { shown = function() @@ -205,23 +205,23 @@ function main:Init() return #self.scriptOutput > 0 end } - self.controls.clearAutoClearOutput = new("CheckBoxControl", { "TOPLEFT", self.controls.clearOutput, "BOTTOMLEFT" }, { 120, 10, 20, 20 }, "Auto Clear Output:", function(state) + self.controls.clearAutoClearOutput = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", self.controls.clearOutput, "BOTTOMLEFT" }, { 120, 10, 20, 20 }, "Auto Clear Output:", function(state) self.clearAutoClearOutput = state end, nil, false) - self.controls.helpText = new("LabelControl", {"TOPLEFT",self.controls.clearOutput,"BOTTOMLEFT"}, {0, 42, 100, 16}, "Press Ctrl+F5 to re-export\ndata from the game") + self.controls.helpText = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.clearOutput,"BOTTOMLEFT"}, {0, 42, 100, 16}, "Press Ctrl+F5 to re-export\ndata from the game") - self.controls.scriptList = new("ScriptListControl", nil, {270, 35, 140, 400}) { + self.controls.scriptList = new("ScriptListControl"):ScriptListControl(nil, {270, 35, 140, 400}) { shown = function() return not self.curDatFile end } - self.controls.scriptOutput = new("TextListControl", nil, {420, 10, 800, 600}, nil, self.scriptOutput) { + self.controls.scriptOutput = new("TextListControl"):TextListControl(nil, {420, 10, 800, 600}, nil, self.scriptOutput) { shown = function() return not self.curDatFile end } - self.controls.copyScriptOutput = new("ButtonControl",{"TOPRIGHT", self.controls.scriptOutput, "BOTTOMRIGHT"},{0, 4, 80, 20},"Copy",function() + self.controls.copyScriptOutput = new("ButtonControl"):ButtonControl({"TOPRIGHT", self.controls.scriptOutput, "BOTTOMRIGHT"},{0, 4, 80, 20},"Copy",function() local lines = {} local textList = self.controls.scriptOutput.list or {} -- grab the actual list for _, entry in ipairs(textList) do @@ -235,14 +235,14 @@ function main:Init() end ) - self.controls.datSearch = new("EditControl", {"TOPLEFT", self.controls.datSource, "BOTTOMLEFT"}, {0, 2, 250, 18}, nil, "^7Search", nil, nil, function(buf) + self.controls.datSearch = new("EditControl"):EditControl({"TOPLEFT", self.controls.datSource, "BOTTOMLEFT"}, {0, 2, 250, 18}, nil, "^7Search", nil, nil, function(buf) self.controls.datList.searchBuf = buf self.controls.datList:BuildFilteredList() end, nil, nil, true) - self.controls.datList = new("DatListControl", {"TOPLEFT",self.controls.datSearch,"BOTTOMLEFT"}, {0, 2, 250, function() return self.screenH - 100 end}) + self.controls.datList = new("DatListControl"):DatListControl({"TOPLEFT",self.controls.datSearch,"BOTTOMLEFT"}, {0, 2, 250, function() return self.screenH - 100 end}) - self.controls.specEditToggle = new("ButtonControl", nil, {270, 10, 100, 18}, function() return self.editSpec and "Done <<" or "Edit >>" end, function() + self.controls.specEditToggle = new("ButtonControl"):ButtonControl(nil, {270, 10, 100, 18}, function() return self.editSpec and "Done <<" or "Edit >>" end, function() self.editSpec = not self.editSpec if self.editSpec then self:SetCurrentCol(1) @@ -252,13 +252,13 @@ function main:Init() return self.curDatFile end } - self.controls.specColList = new("SpecColListControl", {"TOPLEFT",self.controls.specEditToggle,"BOTTOMLEFT"}, {0, 2, 200, 200}) { + self.controls.specColList = new("SpecColListControl"):SpecColListControl({"TOPLEFT",self.controls.specEditToggle,"BOTTOMLEFT"}, {0, 2, 200, 200}) { shown = function() return self.editSpec end } - self.controls.colName = new("EditControl", {"TOPLEFT",self.controls.specColList,"TOPRIGHT"}, {10, 0, 150, 18}, nil, nil, nil, nil, function(buf) + self.controls.colName = new("EditControl"):EditControl({"TOPLEFT",self.controls.specColList,"TOPRIGHT"}, {10, 0, 150, 18}, nil, nil, nil, nil, function(buf) self.curSpecCol.name = buf self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() @@ -272,19 +272,19 @@ function main:Init() end } - self.controls.colType = new("DropDownControl", {"TOPLEFT",self.controls.colName,"BOTTOMLEFT"}, {0, 4, 90, 18}, self.typeDrop, function(_, value) + self.controls.colType = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.colName,"BOTTOMLEFT"}, {0, 4, 90, 18}, self.typeDrop, function(_, value) self.curSpecCol.type = value self.curDatFile:OnSpecChanged() self:UpdateCol() end, "^7Field type in the dat file") - self.controls.colIsList = new("CheckBoxControl", {"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {30, 4, 18}, "List:", function(state) + self.controls.colIsList = new("CheckBoxControl"):CheckBoxControl({"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {30, 4, 18}, "List:", function(state) self.curSpecCol.list = state self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() end) - self.controls.colRefTo = new("EditControl", {"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {0, 26, 150, 18}, nil, nil, nil, nil, function(buf) + self.controls.colRefTo = new("EditControl"):EditControl({"TOPLEFT",self.controls.colType,"BOTTOMLEFT"}, {0, 26, 150, 18}, nil, nil, nil, nil, function(buf) self.curSpecCol.refTo = buf self.curDatFile:OnSpecChanged() end) { @@ -294,7 +294,7 @@ function main:Init() end } - self.controls.colWidth = new("EditControl", {"TOPLEFT",self.controls.colRefTo,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) + self.controls.colWidth = new("EditControl"):EditControl({"TOPLEFT",self.controls.colRefTo,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.width = m_max(tonumber(buf) or 150, 20) self.controls.rowList:BuildColumns() end) { @@ -305,7 +305,7 @@ function main:Init() end } - self.controls.enumBase = new("EditControl", {"TOPLEFT",self.controls.colWidth,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) + self.controls.enumBase = new("EditControl"):EditControl({"TOPLEFT",self.controls.colWidth,"BOTTOMLEFT"}, {0, 4, 100, 18}, nil, nil, "%D", nil, function(buf) self.curSpecCol.enumBase = tonumber(buf) or 0 self.curDatFile:OnSpecChanged() end) { @@ -316,14 +316,14 @@ function main:Init() end } - self.controls.colDelete = new("ButtonControl", {"BOTTOMRIGHT",self.controls.colName,"TOPRIGHT"}, {0, -4, 18, 18}, "x", function() + self.controls.colDelete = new("ButtonControl"):ButtonControl({"BOTTOMRIGHT",self.controls.colName,"TOPRIGHT"}, {0, -4, 18, 18}, "x", function() t_remove(self.curDatFile.spec, self.curSpecColIndex) self.curDatFile:OnSpecChanged() self.controls.rowList:BuildColumns() self:SetCurrentCol() end) - self.controls.filter = new("EditControl", nil, {270, 0, 800, 18}, nil, "^8Filter") { + self.controls.filter = new("EditControl"):EditControl(nil, {270, 0, 800, 18}, nil, "^8Filter") { y = function() return self.editSpec and 240 or 30 end, @@ -336,10 +336,10 @@ function main:Init() end, } self.controls.filter.tooltipText = "Takes a Lua expression that returns true or false for a row.\nE.g. `Id:match(\"test\")` or for a key column, `Col and Col.Id:match(\"test\")`" - self.controls.filterError = new("LabelControl", {"LEFT",self.controls.filter,"RIGHT"}, {4, 2, 0, 14}, "") - self.controls.showRaw = new("LabelControl", {"LEFT",self.controls.filter,"RIGHT"}, {600, 2, 0, 14}, "^7Hold ALT to show raw data.") + self.controls.filterError = new("LabelControl"):LabelControl({"LEFT",self.controls.filter,"RIGHT"}, {4, 2, 0, 14}, "") + self.controls.showRaw = new("LabelControl"):LabelControl({"LEFT",self.controls.filter,"RIGHT"}, {600, 2, 0, 14}, "^7Hold ALT to show raw data.") - self.controls.rowList = new("RowListControl", nil, {270, 0, 0, 0}) { + self.controls.rowList = new("RowListControl"):RowListControl(nil, {270, 0, 0, 0}) { y = function() return self.editSpec and 260 or 50 end, @@ -354,7 +354,7 @@ function main:Init() end } - self.controls.addCol = new("ButtonControl", {"LEFT",self.controls.specEditToggle,"RIGHT"}, {10, 0, 80, 18}, "Add", function() + self.controls.addCol = new("ButtonControl"):ButtonControl({"LEFT",self.controls.specEditToggle,"RIGHT"}, {10, 0, 80, 18}, "Add", function() self:AddSpecCol() end) { shown = function() @@ -396,8 +396,8 @@ end function main:OpenPathPopup() main:OpenPopup(370, 290, "Manage GGPK versions", { - new("GGPKSourceListControl", nil, {0, 50, 350, 200}, self), - new("ButtonControl", nil, {0, 260, 90, 20}, "Done", function() + new("GGPKSourceListControl"):GGPKSourceListControl(nil, {0, 50, 350, 200}, self), + new("ButtonControl"):ButtonControl(nil, {0, 260, 90, 20}, "Done", function() main:ClosePopup() end), }) @@ -486,10 +486,10 @@ function main:InitGGPK() local now = GetTime() local ggpkPath = self.datSource.ggpkPath if ggpkPath and ggpkPath ~= "" then - self.ggpk = new("GGPKData", ggpkPath, nil, self.reExportGGPKData) + self.ggpk = new("GGPKData"):GGPKData(ggpkPath, nil, self.reExportGGPKData) ConPrintf("GGPK: %d ms", GetTime() - now) elseif self.datSource.datFilePath then - self.ggpk = new("GGPKData", nil, self.datSource.datFilePath, self.reExportGGPKData) + self.ggpk = new("GGPKData"):GGPKData(nil, self.datSource.datFilePath, self.reExportGGPKData) ConPrintf("GGPK: %d ms", GetTime() - now) end end @@ -502,7 +502,7 @@ function main:LoadDatFiles() ConPrintf("DAT find: %d ms", GetTime() - now) now = GetTime() end - local datFile = new("DatFile", record.name:gsub("%.dat$",""), record.data) + local datFile = new("DatFile"):DatFile(record.name:gsub("%.dat$",""), record.data) t_insert(self.datFileList, datFile) self.datFileByName[datFile.name] = datFile end @@ -516,7 +516,7 @@ function main:LoadDat64Files() ConPrintf("DAT64 find: %d ms", GetTime() - now) now = GetTime() end - local datFile = new("Dat64File", record.name:gsub("%.datc64$",""), record.data) + local datFile = new("Dat64File"):Dat64File(record.name:gsub("%.datc64$",""), record.data) t_insert(self.datFileList, datFile) self.datFileByName[datFile.name] = datFile end @@ -774,7 +774,7 @@ function main:CopyFolder(srcName, dstName) end function main:OpenPopup(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - local popup = new("PopupDialog", width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) + local popup = new("PopupDialog"):PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) t_insert(self.popups, 1, popup) return popup end @@ -787,10 +787,10 @@ function main:OpenMessagePopup(title, msg) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.close = new("ButtonControl", nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") @@ -800,15 +800,15 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end local confirmWidth = m_max(80, DrawStringWidth(16, "VAR", confirmLabel) + 10) - controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() + controls.confirm = new("ButtonControl"):ButtonControl(nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() main:ClosePopup() onConfirm() end) - t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() + t_insert(controls, new("ButtonControl"):ButtonControl(nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() main:ClosePopup() end)) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") @@ -816,11 +816,11 @@ end function main:OpenNewFolderPopup(path, onClose) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter folder name:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter folder name:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.create.enabled = buf:match("%S") end) - controls.create = new("ButtonControl", nil, {-45, 70, 80, 20}, "Create", function() + controls.create = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Create", function() local newFolderName = controls.edit.buf local res, msg = MakeDir(path..newFolderName) if not res then @@ -833,7 +833,7 @@ function main:OpenNewFolderPopup(path, onClose) main:ClosePopup() end) controls.create.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if onClose then onClose() end diff --git a/src/GameVersions.lua b/src/GameVersions.lua index a161531d86..3f7ee8680c 100644 --- a/src/GameVersions.lua +++ b/src/GameVersions.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: lowercase-global -- Game versions ---Default target version for unknown builds and builds created before 3.0.0. legacyTargetVersion = "2_6" diff --git a/src/HeadlessWrapper.lua b/src/HeadlessWrapper.lua index 4305a0850d..75fdef64ae 100644 --- a/src/HeadlessWrapper.lua +++ b/src/HeadlessWrapper.lua @@ -1,177 +1,23 @@ #@ +---@diagnostic disable: lowercase-global -- This wrapper allows the program to run headless on any OS (in theory) -- It can be run using a standard lua interpreter, although LuaJIT is preferable +-- define global SimpleGraphic API functions. some of these have dummy function +-- bodies intended for headless use. +dofile("_SimpleGraphic.def.lua") --- Callbacks -local callbackTable = { } -local mainObject -function runCallback(name, ...) - if callbackTable[name] then - return callbackTable[name](...) - elseif mainObject and mainObject[name] then - return mainObject[name](mainObject, ...) - end -end -function SetCallback(name, func) - callbackTable[name] = func -end -function GetCallback(name) - return callbackTable[name] -end -function SetMainObject(obj) - mainObject = obj -end - --- Image Handles -local imageHandleClass = { } -imageHandleClass.__index = imageHandleClass -function NewImageHandle() - return setmetatable({ }, imageHandleClass) -end -function imageHandleClass:Load(fileName, ...) - self.valid = true -end -function imageHandleClass:Unload() - self.valid = false -end -function imageHandleClass:IsValid() - return self.valid -end -function imageHandleClass:SetLoadingPriority(pri) end -function imageHandleClass:ImageSize() - return 1, 1 -end - --- Rendering -function RenderInit(flag, ...) end -function GetScreenSize() - return 1920, 1080 -end -function GetScreenScale() - return 1 -end -function GetVirtualScreenSize() - return GetScreenSize() -end -function GetDPIScaleOverridePercent() - return 1 -end -function SetDPIScaleOverridePercent(scale) end -function SetClearColor(r, g, b, a) end -function SetDrawLayer(layer, subLayer) end -function SetViewport(x, y, width, height) end -function SetDrawColor(r, g, b, a) end -function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom) end -function DrawImageQuad(imageHandle, x1, y1, x2, y2, x3, y3, x4, y4, s1, t1, s2, t2, s3, t3, s4, t4) end -function DrawString(left, top, align, height, font, text) end -function DrawStringWidth(height, font, text) - return 1 -end -function DrawStringCursorIndex(height, font, text, cursorX, cursorY) - return 0 -end -function StripEscapes(text) - return text:gsub("%^%d",""):gsub("%^x%x%x%x%x%x%x","") -end -function GetAsyncCount() - return 0 -end --- Search Handles -function NewFileSearch() end +-- Callbacks +__callbackTable__ = { } --- General Functions -function SetWindowTitle(title) end -function GetCursorPos() - return 0, 0 -end -function SetCursorPos(x, y) end -function ShowCursor(doShow) end -function IsKeyDown(keyName) end -function Copy(text) end -function Paste() end -function Deflate(data) - -- TODO: Might need this - return "" -end -function Inflate(data) - -- TODO: And this - return "" -end -function GetTime() - return 0 -end -function GetScriptPath() - return "" -end -function GetRuntimePath() - return "" -end -function GetUserPath() - return "" -end -function MakeDir(path) end -function RemoveDir(path) end -function SetWorkDir(path) end -function GetWorkDir() - return "" -end -function LaunchSubScript(scriptText, funcList, subList, ...) end -function AbortSubScript(ssID) end -function IsSubScriptRunning(ssID) end -function LoadModule(fileName, ...) - if not fileName:match("%.lua") then - fileName = fileName .. ".lua" - end - local func, err = loadfile(fileName) - if func then - return func(...) - else - error("LoadModule() error loading '"..fileName.."': "..err) - end -end -function PLoadModule(fileName, ...) - if not fileName:match("%.lua") then - fileName = fileName .. ".lua" - end - local func, err = loadfile(fileName) - if func then - return PCall(func, ...) - else - error("PLoadModule() error loading '"..fileName.."': "..err) - end -end -function PCall(func, ...) - local ret = { pcall(func, ...) } - if ret[1] then - table.remove(ret, 1) - return nil, unpack(ret) - else - return ret[2] +function runCallback(name, ...) + if __callbackTable__[name] then + return __callbackTable__[name](...) + elseif __mainObject__ and __mainObject__[name] then + return __mainObject__[name](__mainObject__, ...) end end -function ConPrintf(fmt, ...) - -- Optional - print(string.format(fmt, ...)) -end -function ConPrintTable(tbl, noRecurse) end -function ConExecute(cmd) end -function ConClear() end -function SpawnProcess(cmdName, args) end -function OpenURL(url) end -function SetProfiling(isEnabled) end -function Restart() end -function Exit() end -function TakeScreenshot() end - ----@return string? provider ----@return string? version ----@return number? status -function GetCloudProvider(fullPath) - return nil, nil, nil -end - local l_require = require function require(name) @@ -188,32 +34,32 @@ dofile("Launch.lua") -- Prevents loading of ModCache -- Allows running mod parsing related tests without pushing ModCache -- The CI env var will be true when run from github workflows but should be false for other tools using the headless wrapper -mainObject.continuousIntegrationMode = os.getenv("CI") +__mainObject__.continuousIntegrationMode = os.getenv("CI") runCallback("OnInit") runCallback("OnFrame") -- Need at least one frame for everything to initialise -if mainObject.promptMsg then +if __mainObject__.promptMsg then -- Something went wrong during startup - print(mainObject.promptMsg) + print(__mainObject__.promptMsg) io.read("*l") return end -- The build module; once a build is loaded, you can find all the good stuff in here -build = mainObject.main.modes["BUILD"] +build = __mainObject__.main.modes["BUILD"] -- Here's some helpful helper functions to help you get started function newBuild() - mainObject.main:SetMode("BUILD", false, "Help, I'm stuck in Path of Building!") + __mainObject__.main:SetMode("BUILD", false, "Help, I'm stuck in Path of Building!") runCallback("OnFrame") end function loadBuildFromXML(xmlText, name) - mainObject.main:SetMode("BUILD", false, name or "", xmlText) + __mainObject__.main:SetMode("BUILD", false, name or "", xmlText) runCallback("OnFrame") end function loadBuildFromJSON(getItemsJSON, getPassiveSkillsJSON) - mainObject.main:SetMode("BUILD", false, "") + __mainObject__.main:SetMode("BUILD", false, "") runCallback("OnFrame") local charData = build.importTab:ImportItemsAndSkills(getItemsJSON) build.importTab:ImportPassiveTreeAndJewels(getPassiveSkillsJSON, charData) diff --git a/src/Launch.lua b/src/Launch.lua index e018879cad..e0dbffd6e8 100644 --- a/src/Launch.lua +++ b/src/Launch.lua @@ -12,6 +12,7 @@ SetWindowTitle(APP_NAME) ConExecute("set vid_mode 8") ConExecute("set vid_resizable 3") +---@diagnostic disable-next-line: lowercase-global launch = { } SetMainObject(launch) jit.opt.start('maxtrace=4000','maxmcode=8192') @@ -321,7 +322,6 @@ function launch:DownloadPage(url, callback, params) } end end - function launch:ApplyUpdate(mode) if mode == "basic" then -- Need to revert to the basic environment to fully apply the update diff --git a/src/Modules/Build.lua b/src/Modules/Build.lua index b7376f5d6b..41b4417a74 100644 --- a/src/Modules/Build.lua +++ b/src/Modules/Build.lua @@ -14,7 +14,9 @@ local m_floor = math.floor local m_abs = math.abs local s_format = string.format -local buildMode = new("ControlHost") +---@class Build: ControlHost +---@field spec PassiveSpec added by TreeTab +local buildMode = new("ControlHost"):ControlHost() local function InsertIfNew(t, val) if (not t) then return end @@ -111,24 +113,24 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.secondaryAscendDropLegacySelection = nil self.secondaryAscendDropEntryCount = nil - local miscTooltip = new("Tooltip") + local miscTooltip = new("Tooltip"):Tooltip() -- Controls: top bar, left side - self.anchorTopBarLeft = new("Control", nil, {4, 4, 0, 20}) - self.controls.back = new("ButtonControl", {"LEFT",self.anchorTopBarLeft,"RIGHT"}, {0, 0, 60, 20}, "<< Back", function() + self.anchorTopBarLeft = new("Control"):Control(nil, {4, 4, 0, 20}) + self.controls.back = new("ButtonControl"):ButtonControl({"LEFT",self.anchorTopBarLeft,"RIGHT"}, {0, 0, 60, 20}, "<< Back", function() if self.unsaved then self:OpenSavePopup("LIST") else self:CloseBuild() end end) - self.controls.save = new("ButtonControl", {"LEFT",self.controls.back,"RIGHT"}, {8, 0, 50, 20}, "Save", function() + self.controls.save = new("ButtonControl"):ButtonControl({"LEFT",self.controls.back,"RIGHT"}, {8, 0, 50, 20}, "Save", function() self:SaveDBFile() end) self.controls.save.enabled = function() return not self.dbFileName or self.unsaved end - self.controls.saveAs = new("ButtonControl", {"LEFT",self.controls.save,"RIGHT"}, {8, 0, 70, 20}, "Save As", function() + self.controls.saveAs = new("ButtonControl"):ButtonControl({"LEFT",self.controls.save,"RIGHT"}, {8, 0, 70, 20}, "Save As", function() self:OpenSaveAsPopup() end) self.controls.saveAs.enabled = function() @@ -139,7 +141,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin local function buildNameConditional() return self.anchorTopBarRight:GetPos() < 800 end - self.controls.buildName = new("Control", {"LEFT",self.controls.saveAs,"RIGHT"}, {4, 36, 0, 20}) + self.controls.buildName = new("Control"):Control({"LEFT",self.controls.saveAs,"RIGHT"}, {4, 36, 0, 20}) self.controls.buildName.width = function(control) local limit = buildNameConditional() and 203 or (self.anchorTopBarRight:GetPos() - 98 - 62 @@ -181,12 +183,12 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin end -- Controls: top bar, right side - self.anchorTopBarRight = new("Control", nil, {function() return main.screenW / 2 + 6 end, 4, 0, 20}) + self.anchorTopBarRight = new("Control"):Control(nil, {function() return main.screenW / 2 + 6 end, 4, 0, 20}) local function getPointDisplayX() -- I had it hardcoded to -323 before switching to the control sizing return - (23 + self.controls.pointDisplay:GetSize() + self.controls.levelScalingButton:GetSize() + self.controls.characterLevel:GetSize()) end - self.controls.pointDisplay = new("Control", {"LEFT",self.anchorTopBarRight,"RIGHT"}, {function() return getPointDisplayX() end, 0, 0, 20}) + self.controls.pointDisplay = new("Control"):Control({"LEFT",self.anchorTopBarRight,"RIGHT"}, {function() return getPointDisplayX() end, 0, 0, 20}) self.controls.pointDisplay.width = function(control) control.str, control.req = self:EstimatePlayerProgress() return DrawStringWidth(16, "FIXED", control.str) + 8 @@ -208,14 +210,14 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin SetDrawLayer(nil, 0) end end - self.controls.levelScalingButton = new("ButtonControl", {"LEFT",self.controls.pointDisplay,"RIGHT"}, {7, 0, 50, 20}, self.characterLevelAutoMode and "Auto" or "Manual", function() + self.controls.levelScalingButton = new("ButtonControl"):ButtonControl({"LEFT",self.controls.pointDisplay,"RIGHT"}, {7, 0, 50, 20}, self.characterLevelAutoMode and "Auto" or "Manual", function() self.characterLevelAutoMode = not self.characterLevelAutoMode self.controls.levelScalingButton.label = self.characterLevelAutoMode and "Auto" or "Manual" self.configTab:BuildModList() self.modFlag = true self.buildFlag = true end) - self.controls.characterLevel = new("EditControl", {"LEFT",self.controls.levelScalingButton,"RIGHT"}, {5, 0, 106, 20}, "", "Level", "%D", 3, function(buf) + self.controls.characterLevel = new("EditControl"):EditControl({"LEFT",self.controls.levelScalingButton,"RIGHT"}, {5, 0, 106, 20}, "", "Level", "%D", 3, function(buf) self.characterLevel = m_min(m_max(tonumber(buf) or 1, 1), 100) self.configTab:BuildModList() self.modFlag = true @@ -252,7 +254,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin end end end - self.controls.classDrop = new("DropDownControl", {"LEFT",self.controls.characterLevel,"RIGHT"}, {10, 0, 85, 20}, nil, function(index, value) + self.controls.classDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.characterLevel,"RIGHT"}, {10, 0, 85, 20}, nil, function(index, value) if value.classId ~= self.spec.curClassId then if self.spec:CountAllocNodes() == 0 or self.spec:IsClassConnected(value.classId) then self.spec:SelectClass(value.classId) @@ -276,13 +278,13 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin end end end) - self.controls.ascendDrop = new("DropDownControl", {"LEFT",self.controls.classDrop,"RIGHT"}, {4, 0, 120, 20}, nil, function(index, value) + self.controls.ascendDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.classDrop,"RIGHT"}, {4, 0, 120, 20}, nil, function(index, value) self.spec:SelectAscendClass(value.ascendClassId) self.spec:AddUndoState() self.spec:SetWindowTitleWithBuildClass() self.buildFlag = true end) - self.controls.secondaryAscendDrop = new("DropDownControl", {"LEFT",self.controls.ascendDrop,"RIGHT"}, {4, 0, 160, 20}, { + self.controls.secondaryAscendDrop = new("DropDownControl"):DropDownControl({"LEFT",self.controls.ascendDrop,"RIGHT"}, {4, 0, 160, 20}, { { label = "None", ascendClassId = 0 }, }, function(index, value) if not value or not self.spec then @@ -298,7 +300,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin local initialSecondarySelection = (self.spec and self.spec.curSecondaryAscendClassId) or 0 self.controls.secondaryAscendDrop:SelByValue(initialSecondarySelection, "ascendClassId") - self.controls.buildLoadouts = new("DropDownControl", {"LEFT",self.controls.secondaryAscendDrop,"RIGHT"}, {4, 0, 190, 20}, {}, function(index, value) + self.controls.buildLoadouts = new("DropDownControl"):DropDownControl({"LEFT",self.controls.secondaryAscendDrop,"RIGHT"}, {4, 0, 190, 20}, {}, function(index, value) if value == "^7^7Loadouts:" or value == "^7^7-----" then self.controls.buildLoadouts:SetSel(1) return @@ -315,14 +317,14 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin end if value == "^7^7New Loadout" then local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter name for this loadout:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, "New Loadout", nil, nil, 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter name for this loadout:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, "New Loadout", nil, nil, 100, function(buf) controls.save.enabled = buf:match("%S") end) - controls.save = new("ButtonControl", nil, {-45, 70, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Save", function() local loadout = controls.edit.buf - local newSpec = new("PassiveSpec", self, latestTreeVersion) + local newSpec = new("PassiveSpec"):PassiveSpec(self, latestTreeVersion) newSpec.title = loadout t_insert(self.treeTab.specList, newSpec) @@ -343,7 +345,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin main:ClosePopup() end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(370, 100, "Set Name", controls, "save", "edit", "cancel") @@ -427,50 +429,50 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.displayStats, self.minionDisplayStats, self.extraSaveStats = LoadModule("Modules/BuildDisplayStats") -- Controls: Side bar - self.anchorSideBar = new("Control", nil, {4, 60, 0, 0}) + self.anchorSideBar = new("Control"):Control(nil, {4, 60, 0, 0}) self.anchorSideBar.y = function() return buildNameConditional() and 60 or 36 end - self.controls.modeImport = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 0, 134, 20}, "Import/Export Build", function() + self.controls.modeImport = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 0, 134, 20}, "Import/Export Build", function() self.viewMode = "IMPORT" end) self.controls.modeImport.locked = function() return self.viewMode == "IMPORT" end - self.controls.modeNotes = new("ButtonControl", {"LEFT",self.controls.modeImport,"RIGHT"}, {4, 0, 58, 20}, "Notes", function() + self.controls.modeNotes = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeImport,"RIGHT"}, {4, 0, 58, 20}, "Notes", function() self.viewMode = "NOTES" end) self.controls.modeNotes.locked = function() return self.viewMode == "NOTES" end - self.controls.modeConfig = new("ButtonControl", {"TOPRIGHT",self.anchorSideBar,"TOPLEFT"}, {300, 0, 100, 20}, "Configuration", function() + self.controls.modeConfig = new("ButtonControl"):ButtonControl({"TOPRIGHT",self.anchorSideBar,"TOPLEFT"}, {300, 0, 100, 20}, "Configuration", function() self.viewMode = "CONFIG" end) self.controls.modeConfig.locked = function() return self.viewMode == "CONFIG" end - self.controls.modeTree = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 26, 72, 20}, "Tree", function() + self.controls.modeTree = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 26, 72, 20}, "Tree", function() self.viewMode = "TREE" end) self.controls.modeTree.locked = function() return self.viewMode == "TREE" end - self.controls.modeSkills = new("ButtonControl", {"LEFT",self.controls.modeTree,"RIGHT"}, {4, 0, 72, 20}, "Skills", function() + self.controls.modeSkills = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeTree,"RIGHT"}, {4, 0, 72, 20}, "Skills", function() self.viewMode = "SKILLS" end) self.controls.modeSkills.locked = function() return self.viewMode == "SKILLS" end - self.controls.modeItems = new("ButtonControl", {"LEFT",self.controls.modeSkills,"RIGHT"}, {4, 0, 72, 20}, "Items", function() + self.controls.modeItems = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeSkills,"RIGHT"}, {4, 0, 72, 20}, "Items", function() self.viewMode = "ITEMS" end) self.controls.modeItems.locked = function() return self.viewMode == "ITEMS" end - self.controls.modeCalcs = new("ButtonControl", {"LEFT",self.controls.modeItems,"RIGHT"}, {4, 0, 72, 20}, "Calcs", function() + self.controls.modeCalcs = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeItems,"RIGHT"}, {4, 0, 72, 20}, "Calcs", function() self.viewMode = "CALCS" end) self.controls.modeCalcs.locked = function() return self.viewMode == "CALCS" end - self.controls.modeParty = new("ButtonControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 52, 72, 20}, "Party", function() + self.controls.modeParty = new("ButtonControl"):ButtonControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 52, 72, 20}, "Party", function() self.viewMode = "PARTY" end) self.controls.modeParty.locked = function() return self.viewMode == "PARTY" end - self.controls.modeCompare = new("ButtonControl", {"LEFT",self.controls.modeParty,"RIGHT"}, {4, 0, 72, 20}, "Compare", function() + self.controls.modeCompare = new("ButtonControl"):ButtonControl({"LEFT",self.controls.modeParty,"RIGHT"}, {4, 0, 72, 20}, "Compare", function() self.viewMode = "COMPARE" end) self.controls.modeCompare.locked = function() return self.viewMode == "COMPARE" end -- Skills - self.controls.mainSkillLabel = new("LabelControl", {"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 80, 300, 16}, "^7Main Skill:") - self.controls.mainSocketGroup = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillLabel,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) + self.controls.mainSkillLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.anchorSideBar,"TOPLEFT"}, {0, 80, 300, 16}, "^7Main Skill:") + self.controls.mainSocketGroup = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillLabel,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) self.mainSocketGroup = index self.modFlag = true self.buildFlag = true @@ -482,44 +484,44 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.skillsTab:AddSocketGroupTooltip(tooltip, socketGroup) end end - self.controls.mainSkill = new("DropDownControl", {"TOPLEFT",self.controls.mainSocketGroup,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) + self.controls.mainSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSocketGroup,"BOTTOMLEFT"}, {0, 2, 300, 18}, nil, function(index, value) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] mainSocketGroup.mainActiveSkill = index self.modFlag = true self.buildFlag = true end) - self.controls.mainSkillPart = new("DropDownControl", {"TOPLEFT",self.controls.mainSkill,"BOTTOMLEFT",true}, {0, 2, 300, 18}, nil, function(index, value) + self.controls.mainSkillPart = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkill,"BOTTOMLEFT",true}, {0, 2, 300, 18}, nil, function(index, value) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillPart = index self.modFlag = true self.buildFlag = true end) - self.controls.mainSkillStageCountLabel = new("LabelControl", {"TOPLEFT",self.controls.mainSkillPart,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Stages:") { + self.controls.mainSkillStageCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.mainSkillPart,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Stages:") { shown = function() return self.controls.mainSkillStageCount:IsShown() end, } - self.controls.mainSkillStageCount = new("EditControl", {"LEFT",self.controls.mainSkillStageCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) + self.controls.mainSkillStageCount = new("EditControl"):EditControl({"LEFT",self.controls.mainSkillStageCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillStageCount = tonumber(buf) self.modFlag = true self.buildFlag = true end) - self.controls.mainSkillMineCountLabel = new("LabelControl", {"TOPLEFT",self.controls.mainSkillStageCountLabel,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Active Mines:") { + self.controls.mainSkillMineCountLabel = new("LabelControl"):LabelControl({"TOPLEFT",self.controls.mainSkillStageCountLabel,"BOTTOMLEFT",true}, {0, 3, 0, 16}, "^7Active Mines:") { shown = function() return self.controls.mainSkillMineCount:IsShown() end, } - self.controls.mainSkillMineCount = new("EditControl", {"LEFT",self.controls.mainSkillMineCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) + self.controls.mainSkillMineCount = new("EditControl"):EditControl({"LEFT",self.controls.mainSkillMineCountLabel,"RIGHT",true}, {2, 0, 60, 18}, nil, nil, "%D", nil, function(buf) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillMineCount = tonumber(buf) self.modFlag = true self.buildFlag = true end) - self.controls.mainSkillMinion = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillMineCountLabel,"BOTTOMLEFT",true}, {0, 3, 178, 18}, nil, function(index, value) + self.controls.mainSkillMinion = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillMineCountLabel,"BOTTOMLEFT",true}, {0, 3, 178, 18}, nil, function(index, value) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance if value.itemSetId then @@ -548,24 +550,24 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin tooltip:AddLine(14, colorCodes.TIP.."Tip: You can drag items from the Items tab onto this dropdown to equip them onto the minion.") end end - self.controls.mainSkillMinionLibrary = new("ButtonControl", {"LEFT",self.controls.mainSkillMinion,"RIGHT"}, {2, 0, 120, 18}, "Manage Spectres...", function() + self.controls.mainSkillMinionLibrary = new("ButtonControl"):ButtonControl({"LEFT",self.controls.mainSkillMinion,"RIGHT"}, {2, 0, 120, 18}, "Manage Spectres...", function() self:OpenSpectreLibrary() end) - self.controls.mainSkillMinionSkill = new("DropDownControl", {"TOPLEFT",self.controls.mainSkillMinion,"BOTTOMLEFT",true}, {0, 2, 200, 16}, nil, function(index, value) + self.controls.mainSkillMinionSkill = new("DropDownControl"):DropDownControl({"TOPLEFT",self.controls.mainSkillMinion,"BOTTOMLEFT",true}, {0, 2, 200, 16}, nil, function(index, value) local mainSocketGroup = self.skillsTab.socketGroupList[self.mainSocketGroup] local srcInstance = mainSocketGroup.displaySkillList[mainSocketGroup.mainActiveSkill].activeEffect.srcInstance srcInstance.skillMinionSkill = index self.modFlag = true self.buildFlag = true end) - self.controls.statBoxAnchor = new("Control", {"TOPLEFT",self.controls.mainSkillMinionSkill,"BOTTOMLEFT",true}, {0, 2, 0, 0}) - self.controls.statBox = new("TextListControl", {"TOPLEFT",self.controls.statBoxAnchor,"BOTTOMLEFT"}, {0, 2, 300, 0}, {{x=170,align="RIGHT_X"},{x=174,align="LEFT"}}) + self.controls.statBoxAnchor = new("Control"):Control({"TOPLEFT",self.controls.mainSkillMinionSkill,"BOTTOMLEFT",true}, {0, 2, 0, 0}) + self.controls.statBox = new("TextListControl"):TextListControl({"TOPLEFT",self.controls.statBoxAnchor,"BOTTOMLEFT"}, {0, 2, 300, 0}, {{x=170,align="RIGHT_X"},{x=174,align="LEFT"}}) self.controls.statBox.height = function(control) local x, y = control:GetPos() local warnHeight = main.showWarnings and #self.controls.warnings.lines > 0 and 18 or 0 return main.screenH - main.mainBarHeight - 4 - y - warnHeight end - self.controls.warnings = new("Control",{"TOPLEFT",self.controls.statBox,"BOTTOMLEFT",true}, {0, 0, 0, 18}) + self.controls.warnings = new("Control"):Control({"TOPLEFT",self.controls.statBox,"BOTTOMLEFT",true}, {0, 0, 0, 18}) self.controls.warnings.lines = {} self.controls.warnings.width = function(control) return control.str and DrawStringWidth(16, "FIXED", control.str) + 8 or 0 @@ -594,15 +596,15 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.latestTree = main.tree[latestTreeVersion] data.setJewelRadiiGlobally(latestTreeVersion) self.data = data - self.importTab = new("ImportTab", self) - self.notesTab = new("NotesTab", self) - self.partyTab = new("PartyTab", self) - self.configTab = new("ConfigTab", self) - self.itemsTab = new("ItemsTab", self) - self.treeTab = new("TreeTab", self) - self.skillsTab = new("SkillsTab", self) - self.calcsTab = new("CalcsTab", self) - self.compareTab = new("CompareTab", self) + self.importTab = new("ImportTab"):ImportTab(self) + self.notesTab = new("NotesTab"):NotesTab(self) + self.partyTab = new("PartyTab"):PartyTab(self) + self.configTab = new("ConfigTab"):ConfigTab(self) + self.itemsTab = new("ItemsTab"):ItemsTab(self) + self.treeTab = new("TreeTab"):TreeTab(self) + self.skillsTab = new("SkillsTab"):SkillsTab(self) + self.calcsTab = new("CalcsTab"):CalcsTab(self) + self.compareTab = new("CompareTab"):CompareTab(self) -- Load sections from the build file self.savers = { @@ -675,7 +677,7 @@ function buildMode:Init(dbFileName, buildName, buildXML, convertBuild, importLin self.spec:SetWindowTitleWithBuildClass() --[[ - local testTooltip = new("Tooltip") + local testTooltip = new("Tooltip"):Tooltip() for _, item in pairs(main.uniqueDB.list) do ConPrintf("%s", item.name) self.itemsTab:AddItemTooltip(testTooltip, item) @@ -1258,24 +1260,24 @@ end function buildMode:OpenConversionPopup() local controls = { } local currentVersion = treeVersions[latestTreeVersion].display - controls.note = new("LabelControl", nil, {0, 20, 0, 16}, colorCodes.TIP..[[ + controls.note = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, colorCodes.TIP..[[ Info:^7 You are trying to load a build created for a version of Path of Exile that is not supported by us. You will have to convert it to the current game version to load it. To use a build newer than the current supported game version, you may have to update. To use a build older than the current supported game version, we recommend loading it in an older version of Path of Building Community instead. ]]) - controls.label = new("LabelControl", nil, {0, 110, 0, 16}, colorCodes.WARNING..[[ + controls.label = new("LabelControl"):LabelControl(nil, {0, 110, 0, 16}, colorCodes.WARNING..[[ Warning:^7 Converting a build to a different game version may have side effects. For example, if the passive tree has changed, then some passives may be deallocated. You should create a backup copy of the build before proceeding. ]]) - controls.convert = new("ButtonControl", nil, {-40, 170, 120, 20}, "Convert to ".. currentVersion, function() + controls.convert = new("ButtonControl"):ButtonControl(nil, {-40, 170, 120, 20}, "Convert to ".. currentVersion, function() main:ClosePopup() self:Shutdown() self:Init(self.dbFileName, self.buildName, nil, true) end) - controls.cancel = new("ButtonControl", nil, {60, 170, 70, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {60, 170, 70, 20}, "Cancel", function() main:ClosePopup() self:CloseBuild() end) @@ -1289,13 +1291,13 @@ function buildMode:OpenSavePopup(mode) ["UPDATE"] = "before updating?", } local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]) - controls.save = new("ButtonControl", nil, {-90, 70, 80, 20}, "Save", function() + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7This build has unsaved changes.\nDo you want to save them "..modeDesc[mode]) + controls.save = new("ButtonControl"):ButtonControl(nil, {-90, 70, 80, 20}, "Save", function() main:ClosePopup() self.actionOnSave = mode self:SaveDBFile() end) - controls.noSave = new("ButtonControl", nil, {0, 70, 80, 20}, "Don't Save", function() + controls.noSave = new("ButtonControl"):ButtonControl(nil, {0, 70, 80, 20}, "Don't Save", function() main:ClosePopup() if mode == "LIST" then self:CloseBuild() @@ -1305,7 +1307,7 @@ function buildMode:OpenSavePopup(mode) launch:ApplyUpdate(launch.updateAvailable) end end) - controls.close = new("ButtonControl", nil, {90, 70, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {90, 70, 80, 20}, "Cancel", function() main:ClosePopup() end) main:OpenPopup(300, 100, "Save Changes", controls) @@ -1328,13 +1330,13 @@ function buildMode:OpenSaveAsPopup() end end end - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter new build name:") - controls.edit = new("EditControl", nil, {0, 40, 450, 20}, + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter new build name:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 450, 20}, not self.dbFileName and main.predefinedBuildName or (self.buildName or self.dbFileName):gsub("[\\/:%*%?\"<>|%c]", "-"), nil, "\\/:%*%?\"<>|%c", 100, function(buf) updateBuildName() end) - controls.folderLabel = new("LabelControl", {"TOPLEFT",nil,"TOPLEFT"}, {10, 70, 0, 16}, "^7Folder:") - controls.newFolder = new("ButtonControl", {"TOPLEFT",nil,"TOPLEFT"}, {100, 67, 94, 20}, "New Folder...", function() + controls.folderLabel = new("LabelControl"):LabelControl({"TOPLEFT",nil,"TOPLEFT"}, {10, 70, 0, 16}, "^7Folder:") + controls.newFolder = new("ButtonControl"):ButtonControl({"TOPLEFT",nil,"TOPLEFT"}, {100, 67, 94, 20}, "New Folder...", function() main:OpenNewFolderPopup(main.buildPath..controls.folder.subPath, function(newFolderName) if newFolderName then controls.folder:OpenFolder(newFolderName) @@ -1342,13 +1344,13 @@ function buildMode:OpenSaveAsPopup() end) end) - controls.folder = new("FolderListControl", nil, {0, 115, 450, 400}, self.dbFileSubPath, function(subPath) + controls.folder = new("FolderListControl"):FolderListControl(nil, {0, 115, 450, 400}, self.dbFileSubPath, function(subPath) updateBuildName() end) controls.folder.sortMode = self.saveAsSortMode controls.folder:SortList() - controls.save = new("ButtonControl", nil, {-45, 525, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 525, 80, 20}, "Save", function() main:ClosePopup() self.dbFileName = newFileName self.buildName = newBuildName @@ -1356,7 +1358,7 @@ function buildMode:OpenSaveAsPopup() self:SaveDBFile() self.spec:SetWindowTitleWithBuildClass() end) - controls.close = new("ButtonControl", nil, {45, 525, 80, 20}, "Cancel", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {45, 525, 80, 20}, "Cancel", function() main:ClosePopup() self.actionOnSave = nil end) @@ -1368,7 +1370,7 @@ function buildMode:OpenSaveAsPopup() controls.save.enabled = false end - controls.buildSortMode = new("DropDownControl", { "TOPRIGHT", nil, "TOPRIGHT" }, { -10, 70, 120, 18 }, { + controls.buildSortMode = new("DropDownControl"):DropDownControl({ "TOPRIGHT", nil, "TOPRIGHT" }, { -10, 70, 120, 18 }, { { label = "Sort By Name", mode = "NAME" }, { label = "Sort By Last Edited", mode = "EDITED" }, }, function(index, value) @@ -1397,19 +1399,19 @@ function buildMode:OpenSpectreLibrary() end end) local controls = { } - controls.list = new("MinionListControl", nil, {-139, 40, 265, 250}, self.data, destList) - controls.source = new("MinionSearchListControl", nil, {139, 60, 265, 230}, self.data, sourceList, controls.list) - controls.save = new("ButtonControl", nil, {-45, 330, 80, 20}, "Save", function() + controls.list = new("MinionListControl"):MinionListControl(nil, {-139, 40, 265, 250}, self.data, destList) + controls.source = new("MinionSearchListControl"):MinionSearchListControl(nil, {139, 60, 265, 230}, self.data, sourceList, controls.list) + controls.save = new("ButtonControl"):ButtonControl(nil, {-45, 330, 80, 20}, "Save", function() self.spectreList = destList self.modFlag = true self.buildFlag = true main:ClosePopup() end) - controls.cancel = new("ButtonControl", nil, {45, 330, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 330, 80, 20}, "Cancel", function() main:ClosePopup() end) - controls.noteLine1 = new("LabelControl", {"TOPLEFT",controls.list,"BOTTOMLEFT"}, {99, 2, 0, 16}, "^7Spectres in your Library must be assigned to an active") - controls.noteLine2 = new("LabelControl", {"TOPLEFT",controls.list,"BOTTOMLEFT"}, {95, 18, 0, 16}, "^7Raise Spectre gem for their buffs and curses to activate") + controls.noteLine1 = new("LabelControl"):LabelControl({"TOPLEFT",controls.list,"BOTTOMLEFT"}, {99, 2, 0, 16}, "^7Spectres in your Library must be assigned to an active") + controls.noteLine2 = new("LabelControl"):LabelControl({"TOPLEFT",controls.list,"BOTTOMLEFT"}, {95, 18, 0, 16}, "^7Raise Spectre gem for their buffs and curses to activate") local spectrePopup = main:OpenPopup(575, 360, "Spectre Library", controls) spectrePopup:SelectControl(spectrePopup.controls.source.controls.searchText) end @@ -1443,7 +1445,7 @@ function buildMode:OpenSimilarPopup() local buildProviders = { { name = "PoB Archives", - impl = new("PoBArchivesProvider", "similar") + impl = new("PoBArchivesProvider"):PoBArchivesProvider("similar") } } local width = 600 @@ -1451,7 +1453,7 @@ function buildMode:OpenSimilarPopup() return main.screenH * 0.8 end local padding = 50 - controls.similarBuildList = new("ExtBuildListControl", nil, {0, padding, width, height() - 2 * padding}, buildProviders) + controls.similarBuildList = new("ExtBuildListControl"):ExtBuildListControl(nil, {0, padding, width, height() - 2 * padding}, buildProviders) controls.similarBuildList.shown = true controls.similarBuildList.height = function() return height() - 2 * padding @@ -1464,7 +1466,7 @@ function buildMode:OpenSimilarPopup() -- controls.similarBuildList.shown = not controls.similarBuildList:IsShown() - controls.close = new("ButtonControl", nil, {0, height() - (padding + 20) / 2, 80, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, height() - (padding + 20) / 2, 80, 20}, "Close", function() main:ClosePopup() end) -- used in PopupDialog to dynamically size the popup diff --git a/src/Modules/BuildList.lua b/src/Modules/BuildList.lua index c9b67025cd..354f59112b 100644 --- a/src/Modules/BuildList.lua +++ b/src/Modules/BuildList.lua @@ -10,7 +10,7 @@ local t_insert = table.insert local buildListHelpers = LoadModule("Modules/BuildListHelpers") local buildSortDropList = buildListHelpers.buildSortDropList -local listMode = new("ControlHost") +local listMode = new("ControlHost"):ControlHost() function listMode:Init(selBuildName, subPath) if self.initialised then @@ -28,7 +28,7 @@ function listMode:Init(selBuildName, subPath) return end - self.anchor = new("Control", nil, {0, 4, 0, 0}) + self.anchor = new("Control"):Control(nil, {0, 4, 0, 0}) self.anchor.x = function() return main.screenW / 2 end @@ -36,34 +36,34 @@ function listMode:Init(selBuildName, subPath) self.subPath = subPath or "" self.list = { } - self.controls.new = new("ButtonControl", {"TOP",self.anchor,"TOP"}, {-259, 0, 60, 20}, "New", function() + self.controls.new = new("ButtonControl"):ButtonControl({"TOP",self.anchor,"TOP"}, {-259, 0, 60, 20}, "New", function() main:SetMode("BUILD", false, "Unnamed build") end) - self.controls.newFolder = new("ButtonControl", {"LEFT",self.controls.new,"RIGHT"}, {8, 0, 90, 20}, "New Folder", function() + self.controls.newFolder = new("ButtonControl"):ButtonControl({"LEFT",self.controls.new,"RIGHT"}, {8, 0, 90, 20}, "New Folder", function() self.controls.buildList:NewFolder() end) - self.controls.open = new("ButtonControl", {"LEFT",self.controls.newFolder,"RIGHT"}, {8, 0, 60, 20}, "Open", function() + self.controls.open = new("ButtonControl"):ButtonControl({"LEFT",self.controls.newFolder,"RIGHT"}, {8, 0, 60, 20}, "Open", function() self.controls.buildList:LoadBuild(self.controls.buildList.selValue) end) self.controls.open.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.copy = new("ButtonControl", {"LEFT",self.controls.open,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() + self.controls.copy = new("ButtonControl"):ButtonControl({"LEFT",self.controls.open,"RIGHT"}, {8, 0, 60, 20}, "Copy", function() self.controls.buildList:RenameBuild(self.controls.buildList.selValue, true) end) self.controls.copy.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.rename = new("ButtonControl", {"LEFT",self.controls.copy,"RIGHT"}, {8, 0, 60, 20}, "Rename", function() + self.controls.rename = new("ButtonControl"):ButtonControl({"LEFT",self.controls.copy,"RIGHT"}, {8, 0, 60, 20}, "Rename", function() self.controls.buildList:RenameBuild(self.controls.buildList.selValue) end) self.controls.rename.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.delete = new("ButtonControl", {"LEFT",self.controls.rename,"RIGHT"}, {8, 0, 60, 20}, "Delete", function() + self.controls.delete = new("ButtonControl"):ButtonControl({"LEFT",self.controls.rename,"RIGHT"}, {8, 0, 60, 20}, "Delete", function() self.controls.buildList:DeleteBuild(self.controls.buildList.selValue) end) self.controls.delete.enabled = function() return self.controls.buildList.selValue ~= nil end - self.controls.sort = new("DropDownControl", {"LEFT",self.controls.delete,"RIGHT"}, {8, 0, 140, 20}, buildSortDropList, function(index, value) + self.controls.sort = new("DropDownControl"):DropDownControl({"LEFT",self.controls.delete,"RIGHT"}, {8, 0, 140, 20}, buildSortDropList, function(index, value) main.buildSortMode = value.sortMode self:SortList() end) self.controls.sort:SelByValue(main.buildSortMode, "sortMode") - self.controls.buildList = new("BuildListControl", {"TOP",self.anchor,"TOP"}, {0, 75, 900, 0}, self) + self.controls.buildList = new("BuildListControl"):BuildListControl({"TOP",self.anchor,"TOP"}, {0, 75, 900, 0}, self) self.controls.buildList.height = function() return main.screenH - 80 end @@ -93,7 +93,7 @@ function listMode:Init(selBuildName, subPath) self.controls.ExtBuildList = self:getPublicBuilds() end - self.controls.searchText = new("EditControl", {"TOP",self.anchor,"TOP"}, {0, 25, 640, 20}, self.filterBuildList, "Search", "%c%(%)", 100, function(buf) + self.controls.searchText = new("EditControl"):EditControl({"TOP",self.anchor,"TOP"}, {0, 25, 640, 20}, self.filterBuildList, "Search", "%c%(%)", 100, function(buf) main.filterBuildList = buf self:BuildList() end, nil, nil, true) @@ -111,10 +111,10 @@ function listMode:getPublicBuilds() local buildProviders = { { name = "PoB Archives", - impl = new("PoBArchivesProvider", "builds") + impl = new("PoBArchivesProvider"):PoBArchivesProvider("builds") } } - local extBuildList = new("ExtBuildListControl", {"LEFT",self.controls.buildList,"RIGHT"}, {25, 0, main.screenW * 1 / 4 - 50, 0}, buildProviders) + local extBuildList = new("ExtBuildListControl"):ExtBuildListControl({"LEFT",self.controls.buildList,"RIGHT"}, {25, 0, main.screenW * 1 / 4 - 50, 0}, buildProviders) extBuildList:Init("PoB Archives") extBuildList.height = function() return main.screenH - 80 diff --git a/src/Modules/CalcActiveSkill.lua b/src/Modules/CalcActiveSkill.lua index de735dc5a3..d964730fec 100644 --- a/src/Modules/CalcActiveSkill.lua +++ b/src/Modules/CalcActiveSkill.lua @@ -178,9 +178,9 @@ function calcs.copyActiveSkill(env, mode, skill) local newSkill = calcs.createActiveSkill(activeEffect, skill.supportList, skill.actor, skill.socketGroup, skill.summonSkill) local newEnv, _, _, _ = calcs.initEnv(env.build, mode, env.override) calcs.buildActiveSkillModList(newEnv, newSkill) - newSkill.skillModList = new("ModList", newSkill.baseSkillModList) + newSkill.skillModList = new("ModList"):ModList(newSkill.baseSkillModList) if newSkill.minion then - newSkill.minion.modDB = new("ModDB") + newSkill.minion.modDB = new("ModDB"):ModDB() newSkill.minion.modDB.actor = newSkill.minion calcs.createMinionSkills(env, newSkill) newSkill.skillPartName = newSkill.minion.mainSkill.activeEffect.grantedEffect.name @@ -470,7 +470,7 @@ function calcs.buildActiveSkillModList(env, activeSkill) end -- Initialise skill modifier list - local skillModList = new("ModList", activeSkill.actor.modDB) + local skillModList = new("ModList"):ModList(activeSkill.actor.modDB) activeSkill.skillModList = skillModList activeSkill.baseSkillModList = skillModList diff --git a/src/Modules/CalcDefence.lua b/src/Modules/CalcDefence.lua index 6f73ef814b..cb64744a50 100644 --- a/src/Modules/CalcDefence.lua +++ b/src/Modules/CalcDefence.lua @@ -51,7 +51,7 @@ function calcs.armourReduction(armour, raw) end -- Based on code from FR and BS found in act_*.txt ----@param activeSkill/output/breakdown references table passed in from calc offence +---@param activeSkill any /output/breakdown references table passed in from calc offence ---@param sourceType string type of incoming damage - it will be converted (taken as) from this type if applicable ---@param baseDmg for which to calculate the damage ---@return table of taken damage parts, and number, sum of damages diff --git a/src/Modules/CalcPerform.lua b/src/Modules/CalcPerform.lua index 03ab616ab8..2c232da9db 100644 --- a/src/Modules/CalcPerform.lua +++ b/src/Modules/CalcPerform.lua @@ -43,7 +43,7 @@ end -- Merge an instance of a buff, taking the highest value of each modifier local function mergeBuff(src, destTable, destKey) if not destTable[destKey] then - destTable[destKey] = new("ModList") + destTable[destKey] = new("ModList"):ModList() end local dest = destTable[destKey] for _, mod in ipairs(src) do @@ -1105,9 +1105,9 @@ function calcs.perform(env, skipEHP) -- Build minion skills for _, activeSkill in ipairs(env.player.activeSkillList) do - activeSkill.skillModList = new("ModList", activeSkill.baseSkillModList) + activeSkill.skillModList = new("ModList"):ModList(activeSkill.baseSkillModList) if activeSkill.minion then - activeSkill.minion.modDB = new("ModDB") + activeSkill.minion.modDB = new("ModDB"):ModDB() activeSkill.minion.modDB.actor = activeSkill.minion calcs.createMinionSkills(env, activeSkill) activeSkill.skillPartName = activeSkill.minion.mainSkill.activeEffect.grantedEffect.name @@ -1593,13 +1593,13 @@ function calcs.perform(env, skipEHP) -- so utility flasks are grouped by base, unique flasks are grouped by name, and magic flasks by their modifiers if buffModList[1] then if not onlyMinion then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buffModList, effectMod) mergeBuff(srcList, flaskBuffs, baseName) mergeBuff(srcList, flaskBuffsPerBase[item.baseName], baseName) end if (not onlyRecovery or checkNonRecoveryFlasksForMinions) and (flasksApplyToMinion or quickSilverAppliesToAllies or (nonUniqueFlasksApplyToMinion and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC")) then - srcList = new("ModList") + srcList = new("ModList"):ModList() srcList:ScaleAddList(buffModList, effectModNonPlayer) mergeBuff(srcList, flaskBuffsNonPlayer, baseName) mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], baseName) @@ -1607,7 +1607,7 @@ function calcs.perform(env, skipEHP) end if modList[1] then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(modList, effectMod) local key if item.rarity == "UNIQUE" or item.rarity == "RELIC" then @@ -1624,7 +1624,7 @@ function calcs.perform(env, skipEHP) mergeBuff(srcList, flaskBuffsNonUtility, key) end if (not onlyRecovery or checkNonRecoveryFlasksForMinions) and (flasksApplyToMinion or quickSilverAppliesToAllies or (nonUniqueFlasksApplyToMinion and item.rarity ~= "UNIQUE" and item.rarity ~= "RELIC")) then - srcList = new("ModList") + srcList = new("ModList"):ModList() srcList:ScaleAddList(modList, effectModNonPlayer) mergeBuff(srcList, flaskBuffsNonPlayer, key) mergeBuff(srcList, flaskBuffsPerBaseNonPlayer[item.baseName], key) @@ -1746,14 +1746,14 @@ function calcs.perform(env, skipEHP) -- same deal as flasks, go look at the comment there if buffModList[1] then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buffModList, effectMod) mergeBuff(srcList, tinctureBuffs, baseName) mergeBuff(srcList, tinctureBuffsPerBase[item.baseName], baseName) end if modList[1] then - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(modList, effectMod) local key if item.rarity == "UNIQUE" or item.rarity == "RELIC" then @@ -2101,8 +2101,8 @@ function calcs.perform(env, skipEHP) minionCurses.limit = modData.value + 1 break elseif modData.name == "AllyModifier" and modData.type == "LIST" then - buffs["Spectre"] = buffs["Spectre"] or new("ModList") - minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList") + buffs["Spectre"] = buffs["Spectre"] or new("ModList"):ModList() + minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name @@ -2110,14 +2110,14 @@ function calcs.perform(env, skipEHP) t_insert(buffs["Spectre"], copyModValue) end elseif modData.name == "MinionModifier" and modData.type == "LIST" then - minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList") + minionBuffs["Spectre"] = minionBuffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name t_insert(minionBuffs["Spectre"], copyModValue) end elseif modData.name == "PlayerModifier" and modData.type == "LIST" then - buffs["Spectre"] = buffs["Spectre"] or new("ModList") + buffs["Spectre"] = buffs["Spectre"] or new("ModList"):ModList() for _, modValue in pairs(modData.value) do local copyModValue = copyTable(modValue) copyModValue.source = "Spectre:"..spectreData.name @@ -2179,7 +2179,7 @@ function calcs.perform(env, skipEHP) if not buff.applyNotPlayer then activeSkill.buffSkill = true modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") + skillModList:Sum("INC", skillCfg, buff.name:gsub(" ", "").."Effect") local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) @@ -2191,7 +2191,7 @@ function calcs.perform(env, skipEHP) if env.minion and not env.minion.hostile and (buff.applyMinions or buff.applyAllies or skillModList:Flag(nil, "BuffAppliesToAllies")) then activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect") + env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf") local more = modStore:More(skillCfg, "BuffEffect") * env.minion.modDB:More(nil, "BuffEffectOnSelf") srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) @@ -2210,7 +2210,7 @@ function calcs.perform(env, skipEHP) local modStore = buff.activeSkillBuff and skillModList or modDB if not buff.applyNotPlayer then activeSkill.buffSkill = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) @@ -2243,12 +2243,12 @@ function calcs.perform(env, skipEHP) local cooldownOverride = modStore:Override(skillCfg, "CooldownRecovery") local actual_cooldown = cooldownOverride or (activeSkill.skillData.cooldown + modStore:Sum("BASE", skillCfg, "CooldownRecovery")) / calcLib.mod(modStore, skillCfg, "CooldownRecovery") local uptime = modDB:Flag(nil, "Condition:WarcryMaxHit") and 1 or m_min(full_duration / actual_cooldown, 1) - local extraWarcryModList = activeSkill.activeEffect.grantedEffect.name == "Rallying Cry" and new("ModList") or {} + local extraWarcryModList = activeSkill.activeEffect.grantedEffect.name == "Rallying Cry" and new("ModList"):ModList() or {} if not modDB:Flag(nil, "CannotGainWarcryBuffs") then if not buff.applyNotPlayer then activeSkill.buffSkill = true modDB.conditions["AffectedBy"..warcryName] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnSelf", "BuffEffectOnPlayer") local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnSelf") for _, warcryBuff in ipairs(buff.modList) do @@ -2261,7 +2261,7 @@ function calcs.perform(env, skipEHP) if env.minion then activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..warcryName] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = skillModList:Sum("INC", skillCfg, "BuffEffect") + env.minion.modDB:Sum("INC", skillCfg, "BuffEffectOnSelf") local more = skillModList:More(skillCfg, "BuffEffect") * env.minion.modDB:More(skillCfg, "BuffEffectOnSelf") for _, warcryBuff in ipairs(buff.modList) do @@ -2289,7 +2289,7 @@ function calcs.perform(env, skipEHP) mergeBuff(srcList, minionBuffs, buff.name) end if partyTabEnableExportBuffs then - local newModList = new("ModList") + local newModList = new("ModList"):ModList() local inc = skillModList:Sum("INC", skillCfg, "BuffEffect") local more = skillModList:More(skillCfg, "BuffEffect") newModList:AddList(buff.modList) @@ -2326,7 +2326,7 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedBy"..buff.name:sub(6):gsub(" ","")] = true end modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) mergeBuff(srcList, buffs, buff.name) @@ -2341,7 +2341,7 @@ function calcs.perform(env, skipEHP) activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) mergeBuff(srcList, minionBuffs, buff.name) @@ -2350,7 +2350,7 @@ function calcs.perform(env, skipEHP) local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect") local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect") local mult = (1 + inc / 100) * more - local newModList = new("ModList") + local newModList = new("ModList"):ModList() newModList:AddList(buff.modList) newModList:AddList(extraAuraModList) if buffExports["Aura"][buff.name] then @@ -2359,7 +2359,7 @@ function calcs.perform(env, skipEHP) buffExports["Aura"][buff.name] = { effectMult = mult, modList = newModList } if modDB:Flag(nil, "AurasAffectEnemies") and not activeSkill.skillModList:Flag(skillCfg, "SelfAurasAffectYouAndLinkedTarget") then local newModList = {} - local srcList = new("ModList") + local srcList = new("ModList"):ModList() for _, mod in ipairs(buff.modList) do t_insert(newModList, mod) end @@ -2377,7 +2377,7 @@ function calcs.perform(env, skipEHP) env.player.mainSkill.skillModList.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.player.mainSkill.skillModList.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") local lists = {extraAuraModList, buff.modList} @@ -2430,7 +2430,7 @@ function calcs.perform(env, skipEHP) local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "DebuffEffect") local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "DebuffEffect") mult = (1 + inc / 100) * more - local newModList = new("ModList") + local newModList = new("ModList"):ModList() newModList:AddList(extraAuraModList) buffExports["Aura"][buff.name..(buffExports["Aura"][buff.name] and "_Debuff" or "")] = { effectMult = mult, modList = newModList } if allyBuffs["AuraDebuff"] and allyBuffs["AuraDebuff"][buff.name] and allyBuffs["AuraDebuff"][buff.name].effectMult / 100 > mult then @@ -2456,7 +2456,7 @@ function calcs.perform(env, skipEHP) activeSkill.debuffSkill = true enemyDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local mult = 1 local extraAuraModList = { } if buff.type == "AuraDebuff" then @@ -2486,7 +2486,7 @@ function calcs.perform(env, skipEHP) t_insert(newModList, mod) end -- A full modlist causes issues with copy table for mine auras - --local newModList = new("ModList") + --local newModList = new("ModList"):ModList() --newModList:AddList(buff.modList) --newModList:AddList(extraAuraModList) buffExports["Aura"][buff.name..(buffExports["Aura"][buff.name] and "_Debuff" or "")] = { effectMult = mult, modList = newModList } @@ -2540,21 +2540,21 @@ function calcs.perform(env, skipEHP) mult = (1 + inc / 100) * more end if buff.type == "Curse" then - curse.modList = new("ModList") + curse.modList = new("ModList"):ModList() curse.modList:ScaleAddList(buff.modList, mult) if partyTabEnableExportBuffs then buffExports["Curse"][buff.name] = { isMark = curse.isMark, effectMult = curse.isMark and mult or (1 + inc / 100) * moreMark, modList = buff.modList } end else -- Curse applies a buff; scale by curse effect, then buff effect - local temp = new("ModList") + local temp = new("ModList"):ModList() temp:ScaleAddList(buff.modList, mult) - curse.buffModList = new("ModList") + curse.buffModList = new("ModList"):ModList() local buffInc = modDB:Sum("INC", skillCfg, "BuffEffectOnSelf") local buffMore = modDB:More(skillCfg, "BuffEffectOnSelf") curse.buffModList:ScaleAddList(temp, (1 + buffInc / 100) * buffMore) if env.minion then - curse.minionBuffModList = new("ModList") + curse.minionBuffModList = new("ModList"):ModList() local buffInc = env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf") local buffMore = env.minion.modDB:More(nil, "BuffEffectOnSelf") curse.minionBuffModList:ScaleAddList(temp, (1 + buffInc / 100) * buffMore) @@ -2589,7 +2589,7 @@ function calcs.perform(env, skipEHP) local more = skillModList:More(skillCfg, "LinkEffect", "BuffEffect") local mult = (1 + inc / 100) * more if partyTabEnableExportBuffs then - local newModList = new("ModList") + local newModList = new("ModList"):ModList() newModList:AddList(buff.modList) newModList:AddList(extraLinkModList) buffExports["Link"][buff.name] = { effectMult = mult, modList = newModList } @@ -2598,7 +2598,7 @@ function calcs.perform(env, skipEHP) activeSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByLink"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() inc = inc + env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf", "LinkEffectOnSelf") more = more * env.minion.modDB:More(nil, "BuffEffectOnSelf", "LinkEffectOnSelf") mult = (1 + inc / 100) * more @@ -2653,7 +2653,7 @@ function calcs.perform(env, skipEHP) if buff.applyAllies then activeMinionSkill.buffSkill = true modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect", "BuffEffectOnPlayer") + modDB:Sum("INC", nil, "BuffEffectOnSelf") local more = modStore:More(skillCfg, "BuffEffect", "BuffEffectOnPlayer") * modDB:More(nil, "BuffEffectOnSelf") srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) @@ -2677,7 +2677,7 @@ function calcs.perform(env, skipEHP) else activeSkill.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true end - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = modStore:Sum("INC", skillCfg, "BuffEffect", (env.minion == castingMinion) and "BuffEffectOnSelf" or nil) local more = modStore:More(skillCfg, "BuffEffect", (env.minion == castingMinion) and "BuffEffectOnSelf" or nil) srcList:ScaleAddList(buff.modList, (1 + inc / 100) * more) @@ -2717,7 +2717,7 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedBy"..buff.name:sub(6):gsub(" ","")] = true end modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) setSpectreSource(srcList, buff.name) @@ -2732,7 +2732,7 @@ function calcs.perform(env, skipEHP) activeMinionSkill.minionBuffSkill = true env.minion.modDB.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.minion.modDB.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, mult) srcList:ScaleAddList(extraAuraModList, mult) setSpectreSource(srcList, buff.name) @@ -2742,7 +2742,7 @@ function calcs.perform(env, skipEHP) local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect") local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect") local mult = (1 + inc / 100) * more - local newModList = new("ModList") + local newModList = new("ModList"):ModList() newModList:AddList(buff.modList) newModList:AddList(extraAuraModList) setSpectreSource(newModList, buff.name) @@ -2755,7 +2755,7 @@ function calcs.perform(env, skipEHP) env.player.mainSkill.skillModList.conditions["AffectedBy"..buff.name:gsub(" ","")] = true env.player.mainSkill.skillModList.conditions["AffectedByAura"] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local inc = skillModList:Sum("INC", skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") local more = skillModList:More(skillCfg, "AuraEffect", "BuffEffect", "AuraBuffEffect") local lists = {extraAuraModList, buff.modList} @@ -2791,7 +2791,7 @@ function calcs.perform(env, skipEHP) } local inc = skillModList:Sum("INC", skillCfg, "CurseEffect") + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") local more = skillModList:More(skillCfg, "CurseEffect") * enemyDB:More(nil, "CurseEffectOnSelf") - curse.modList = new("ModList") + curse.modList = new("ModList"):ModList() curse.modList:ScaleAddList(buff.modList, (1 + inc / 100) * more) t_insert(minionCurses, curse) end @@ -2809,7 +2809,7 @@ function calcs.perform(env, skipEHP) end if env.mode_effective and stackCount > 0 then activeMinionSkill.debuffSkill = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() local mult = 1 if buff.type == "AuraDebuff" then mult = 0 @@ -2852,14 +2852,14 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedBy"..buffName:gsub(" ","")] = true local inc = modDB:Sum("INC", nil, "BuffEffectOnSelf", "AuraEffectOnSelf") local more = modDB:More(nil, "BuffEffectOnSelf", "AuraEffectOnSelf") - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, (buff.effectMult + inc) / 100 * more) mergeBuff(srcList, buffs, buffName) if env.minion then env.minion.modDB.conditions["AffectedBy"..buffName:gsub(" ","")] = true local inc = env.minion.modDB:Sum("INC", nil, "BuffEffectOnSelf", "AuraEffectOnSelf") local more = env.minion.modDB:More(nil, "BuffEffectOnSelf", "AuraEffectOnSelf") - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(buff.modList, (buff.effectMult + inc) / 100 * more) mergeBuff(srcList, minionBuffs, buffName) end @@ -2872,14 +2872,14 @@ function calcs.perform(env, skipEHP) if not modDB:Flag(nil, "AlliesAurasCannotAffectSelf") and not modDB.conditions["AffectedBy"..auraNameCompressed] then modDB.conditions["AffectedByAura"] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, buffs, auraName) end if env.minion and not env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] then env.minion.modDB.conditions["AffectedByAura"] = true env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, minionBuffs, auraName) end @@ -2892,14 +2892,14 @@ function calcs.perform(env, skipEHP) modDB.conditions["AffectedByAura"] = true modDB.conditions["AffectedBy"..auraName:sub(6):gsub(" ","")] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, buffs, auraName) end if env.minion and not env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] then env.minion.modDB.conditions["AffectedByAura"] = true env.minion.modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, minionBuffs, auraName) end @@ -2913,7 +2913,7 @@ function calcs.perform(env, skipEHP) if not enemyDB.conditions["AffectedBy"..auraNameCompressed] then enemyDB.conditions["AffectedBy"..auraNameCompressed] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, debuffs, auraName) end @@ -2925,7 +2925,7 @@ function calcs.perform(env, skipEHP) if not enemyDB.conditions["AffectedBy"..auraNameCompressed] then enemyDB.conditions["AffectedBy"..auraNameCompressed] = true modDB.conditions["AffectedBy"..auraNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(aura.modList, aura.effectMult / 100) mergeBuff(srcList, debuffs, auraName) end @@ -2938,7 +2938,7 @@ function calcs.perform(env, skipEHP) if not modDB.conditions["AffectedBy"..warcryNameCompressed] then modDB.conditions["AffectedByWarcry"] = true modDB.conditions["AffectedBy"..warcryNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() for _, warcryBuff in ipairs(warcry.modList) do srcList:ScaleAddList({warcryBuff}, (warcry.effectMult or 100) / 100 * (warcryBuff[1].warcryPowerBonus or 1)) end @@ -2947,7 +2947,7 @@ function calcs.perform(env, skipEHP) if env.minion and not env.minion.modDB.conditions["AffectedBy"..warcryNameCompressed] then env.minion.modDB.conditions["AffectedByWarcry"] = true env.minion.modDB.conditions["AffectedBy"..warcryNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() for _, warcryBuff in ipairs(warcry.modList) do srcList:ScaleAddList({warcryBuff}, (warcry.effectMult or 100) / 100 * (warcryBuff[1].warcryPowerBonus or 1)) end @@ -2961,7 +2961,7 @@ function calcs.perform(env, skipEHP) if not modDB.conditions["AffectedBy"..linkNameCompressed] then modDB.conditions["AffectedByLink"] = true modDB.conditions["AffectedBy"..linkNameCompressed] = true - local srcList = new("ModList") + local srcList = new("ModList"):ModList() srcList:ScaleAddList(link.modList, (link.effectMult or 100) / 100) mergeBuff(srcList, buffs, linkName) end @@ -2996,7 +2996,7 @@ function calcs.perform(env, skipEHP) -- Check for extra curses for dest, modDB in pairs({[curses] = modDB, [minionCurses] = env.minion and env.minion.modDB}) do for _, value in ipairs(modDB:List(nil, "ExtraCurse")) do - local gemModList = new("ModList") + local gemModList = new("ModList"):ModList() local grantedEffect = env.data.skills[value.skillId] if grantedEffect then calcs.mergeSkillInstanceMods(env, gemModList, { @@ -3030,7 +3030,7 @@ function calcs.perform(env, skipEHP) fromPlayer = (dest == curses), priority = determineCursePriority(grantedEffect.name), } - curse.modList = new("ModList") + curse.modList = new("ModList"):ModList() curse.modList:ScaleAddList(curseModList, (1 + enemyDB:Sum("INC", nil, "CurseEffectOnSelf") / 100) * enemyDB:More(nil, "CurseEffectOnSelf")) t_insert(dest, curse) end @@ -3048,7 +3048,7 @@ function calcs.perform(env, skipEHP) local newCurse = { name = curseName, priority = 0, - modList = new("ModList") + modList = new("ModList"):ModList() } local mult = curse.effectMult / 100 if curse.isMark then @@ -3241,7 +3241,7 @@ function calcs.perform(env, skipEHP) if modDB:Flag(nil, "ManaIncreasedByOvercappedLightningRes") then -- Calculate resistances for ManaIncreasedByOvercappedLightningRes without mutating conversion mods on the player ModDB. local tempResistActor = { - modDB = new("ModDB", modDB), + modDB = new("ModDB"):ModDB(modDB), output = output, activeSkillList = env.player.activeSkillList, enemy = env.player.enemy, @@ -3261,7 +3261,7 @@ function calcs.perform(env, skipEHP) end -- Check for extra auras - buffExports["Aura"]["extraAura"] = { effectMult = 1, modList = new("ModList") } + buffExports["Aura"]["extraAura"] = { effectMult = 1, modList = new("ModList"):ModList() } for _, value in ipairs(modDB:List(nil, "ExtraAura")) do local modList = { value.mod } if not value.onlyAllies and not (value.fromAllies and modDB:Flag(nil, "AlliesAurasCannotAffectSelf")) then diff --git a/src/Modules/CalcSetup.lua b/src/Modules/CalcSetup.lua index cd68f9074b..eda7f9fc16 100644 --- a/src/Modules/CalcSetup.lua +++ b/src/Modules/CalcSetup.lua @@ -111,7 +111,7 @@ function calcs.initModDB(env, modDB) end function calcs.buildModListForNode(env, node) - local modList = new("ModList") + local modList = new("ModList"):ModList() if node.type == "Keystone" then modList:AddMod(node.keystoneMod) else @@ -132,7 +132,7 @@ function calcs.buildModListForNode(env, node) -- Apply effect scaling local scale = calcLib.mod(modList, nil, "PassiveSkillEffect") if scale ~= 1 then - local scaledList = new("ModList") + local scaledList = new("ModList"):ModList() scaledList:ScaleAddList(modList, scale) modList = scaledList end @@ -175,7 +175,7 @@ function calcs.buildModListForNodeList(env, nodeList, finishJewels) end -- Add node modifiers - local modList = new("ModList") + local modList = new("ModList"):ModList() local explodeSources = {} for _, node in pairs(nodeList) do local nodeModList, explode = calcs.buildModListForNode(env, node) @@ -382,11 +382,11 @@ function calcs.initEnv(build, mode, override, specEnv) env.override = override env.classId = env.spec.curClassId - modDB = new("ModDB") + modDB = new("ModDB"):ModDB() env.modDB = modDB - enemyDB = new("ModDB") + enemyDB = new("ModDB"):ModDB() env.enemyDB = enemyDB - env.itemModDB = new("ModDB") + env.itemModDB = new("ModDB"):ModDB() env.enemyLevel = build.configTab.enemyLevel or m_min(data.misc.MaxEnemyLevel, build.characterLevel) @@ -977,7 +977,7 @@ function calcs.initEnv(build, mode, override, specEnv) end if item.type == "Shield" and env.allocNodes[45175] and env.allocNodes[45175].dn == "Necromantic Aegis" then -- Special handling for Necromantic Aegis - env.aegisModList = new("ModList") + env.aegisModList = new("ModList"):ModList() for _, mod in ipairs(srcList) do -- Filter out mods that apply to socketed gems, or which add supports local add = true @@ -999,7 +999,7 @@ function calcs.initEnv(build, mode, override, specEnv) local info = env.data.weaponTypeInfo[type] if info and type ~= "Bow" then local name = info.oneHand and "Energy Blade One Handed" or "Energy Blade Two Handed" - local item = new("Item") + local item = new("Item"):Item() item.name = name item.base = data.itemBases[name] item.baseName = name @@ -1030,7 +1030,7 @@ function calcs.initEnv(build, mode, override, specEnv) end elseif slotName == "Weapon 1" and item.name == "The Iron Mass, Gladius" then -- Special handling for The Iron Mass - env.theIronMass = new("ModList") + env.theIronMass = new("ModList"):ModList() for _, mod in ipairs(srcList) do -- Filter out mods that apply to socketed gems, or which add supports local add = true @@ -1048,7 +1048,7 @@ function calcs.initEnv(build, mode, override, specEnv) end elseif slotName == "Weapon 1" and item.grantedSkills[1] and item.grantedSkills[1].skillId == "UniqueAnimateWeapon" then -- Special handling for The Dancing Dervish - env.weaponModList1 = new("ModList") + env.weaponModList1 = new("ModList"):ModList() for _, mod in ipairs(srcList) do -- Filter out mods that apply to socketed gems, or which add supports local add = true @@ -1107,25 +1107,25 @@ function calcs.initEnv(build, mode, override, specEnv) local widowHailMod= (1 + (items["Weapon 1"] and items["Weapon 1"].baseModList:Sum("INC", nil, "EffectOfBonusesFromQuiver") + env.initialNodeModDB:Sum("INC", nil, "EffectOfBonusesFromQuiver") or 100) / 100) scale = scale * widowHailMod env.modDB:NewMod("WidowHailMultiplier", "BASE", widowHailMod, "Widowhail") - local combinedList = new("ModList") + local combinedList = new("ModList"):ModList() for _, mod in ipairs(srcList) do combinedList:MergeMod(mod) end env.itemModDB:ScaleAddList(combinedList, scale) elseif env.modDB.multipliers["Corrupted" .. item.rarity:gsub("(%a)(%u*)", function(a, b) return a..string.lower(b) end) .. "JewelEffect"] and item.type == "Jewel" and item.corrupted and slot.nodeId and item.base.subType ~= "Charm" and not env.spec.nodes[slot.nodeId].containJewelSocket then scale = scale + env.modDB.multipliers["Corrupted" .. item.rarity:gsub("(%a)(%u*)", function(a, b) return a..string.lower(b) end) .. "JewelEffect"] - local combinedList = new("ModList") + local combinedList = new("ModList"):ModList() for _, mod in ipairs(srcList) do combinedList:MergeMod(mod) end env.itemModDB:ScaleAddList(combinedList, scale) elseif item.type == "Gloves" and calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") ~=1 then scale = calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromGloves") - 1 - local combinedList = new("ModList") + local combinedList = new("ModList"):ModList() for _, mod in ipairs(srcList) do combinedList:MergeMod(mod) end - local scaledList = new("ModList") + local scaledList = new("ModList"):ModList() scaledList:ScaleAddList(combinedList, scale) for _, mod in ipairs(scaledList) do combinedList:MergeMod(mod, true) @@ -1133,11 +1133,11 @@ function calcs.initEnv(build, mode, override, specEnv) env.itemModDB:AddList(combinedList) elseif item.type == "Boots" and calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromBoots") ~= 1 then scale = calcLib.mod(env.initialNodeModDB, nil, "EffectOfBonusesFromBoots") - 1 - local combinedList = new("ModList") + local combinedList = new("ModList"):ModList() for _, mod in ipairs(srcList) do combinedList:MergeMod(mod) end - local scaledList = new("ModList") + local scaledList = new("ModList"):ModList() scaledList:ScaleAddList(combinedList, scale) for _, mod in ipairs(scaledList) do combinedList:MergeMod(mod, true) @@ -1282,7 +1282,7 @@ function calcs.initEnv(build, mode, override, specEnv) end if not override or (override and not override.extraJewelFuncs) then override = override or {} - override.extraJewelFuncs = new("ModList") + override.extraJewelFuncs = new("ModList"):ModList() override.extraJewelFuncs.actor = env.player for _, mod in ipairs(env.modDB:Tabulate("LIST", nil, "ExtraJewelFunc")) do override.extraJewelFuncs:AddMod(mod.mod) diff --git a/src/Modules/Common.lua b/src/Modules/Common.lua index ae49f47782..84c1d6ca6d 100644 --- a/src/Modules/Common.lua +++ b/src/Modules/Common.lua @@ -1,3 +1,4 @@ +---@diagnostic disable: lowercase-global -- Path of Building -- -- Module: Common @@ -68,13 +69,17 @@ end local function getClass(className) local class = common.classes[className] if not class then - LoadModule("Classes/"..className) + LoadModule("Classes/" .. className) class = common.classes[className] - assert(class, "Class '"..className.."' not defined in class file") + assert(class, "Class '" .. className .. "' not defined in class file") end return class end --- newClass(""[, ""[, "" ...]], constructorFunc) + +---@generic T +---@param className `T` +---@param ... string parent class names +---@return T function newClass(className, ...) local class = { } common.classes[className] = class @@ -87,11 +92,10 @@ function newClass(className, ...) end class._className = className local numVarArg = select("#", ...) - class._constructor = select(numVarArg, ...) - if numVarArg > 1 then + if numVarArg > 0 then -- Build list of parent classes class._parents = { } - for i = 1, numVarArg - 1 do + for i = 1, numVarArg do class._parents[i] = getClass(select(i, ...)) end -- Build list of all classes directly or indirectly inherited by this class @@ -112,6 +116,10 @@ function newClass(className, ...) end return class end + +---@generic T +---@param className `T` +---@return T function new(className, ...) local class = getClass(className) local object = setmetatable({ }, class) @@ -131,29 +139,36 @@ function new(className, ...) end, __newindex = object, __call = function(...) - if not parent._constructor then + if not parent[parent._className] then error("Parent class '"..parent._className.."' of class '"..class._className.."' has no constructor") end if object._parentInit[parent] then error("Parent class '"..parent._className.."' of class '"..class._className.."' has already been initialised") end - parent._constructor(...) + parent[parent._className](select(2, ...)) object._parentInit[parent] = true end, } object[parent._className] = setmetatable(proxyMeta, proxyMeta) end end - if class._constructor then - class._constructor(object, ...) - end - if class._parents then - -- Check that the constructors for all parent and superparent classes have been called - for parent in pairs(class._superParents) do - if parent._constructor and not object._parentInit[parent] then - error("Parent class '"..parent._className.."' of class '"..className.."' must be initialised") + + if class[className] and not rawget(class, "_constructorInitialised") then + local originalFunc = class[className] + class[className] = function(self, ...) + local ret = originalFunc(self, ...) + if class._parents then + -- Check that the constructors for all parent and superparent classes have been called + for parent in pairs(class._superParents) do + if parent[parent._className] and not self._parentInit[parent] then + error("Parent class '" .. + parent._className .. "' of class '" .. className .. "' must be initialised") + end + end end + return ret end + class._constructorInitialised = true end return object end @@ -463,11 +478,11 @@ function mergeDB(srcDB, modDB) end function specCopy(env) - local modDB = new("ModDB") + local modDB = new("ModDB"):ModDB() modDB:AddDB(env.modDB) modDB.conditions = copyTable(env.modDB.conditions) modDB.multipliers = copyTable(env.modDB.multipliers) - local enemyDB = new("ModDB") + local enemyDB = new("ModDB"):ModDB() if env.enemyDB then enemyDB:AddDB(env.enemyDB) enemyDB.conditions = copyTable(env.enemyDB.conditions) @@ -475,7 +490,7 @@ function specCopy(env) end local minionDB = nil if env.minion then - minionDB = new("ModDB") + minionDB = new("ModDB"):ModDB() minionDB:AddDB(env.minion.modDB) minionDB.conditions = copyTable(env.minion.modDB.conditions) minionDB.multipliers = copyTable(env.minion.modDB.multipliers) diff --git a/src/Modules/Data.lua b/src/Modules/Data.lua index a880019c7f..ca3edb1fd9 100644 --- a/src/Modules/Data.lua +++ b/src/Modules/Data.lua @@ -103,6 +103,7 @@ end -- Remaining Item Data and uniques ---------------------------------------- +---@diagnostic disable-next-line: lowercase-global data = { } -- Misc data tables diff --git a/src/Modules/Main.lua b/src/Modules/Main.lua index beae31b7be..106983fc1c 100644 --- a/src/Modules/Main.lua +++ b/src/Modules/Main.lua @@ -51,7 +51,8 @@ end local tempTable1 = { } local tempTable2 = { } -main = new("ControlHost") +---@diagnostic disable-next-line: lowercase-global +main = new("ControlHost"):ControlHost() function main:Init() self:DetectUnicodeSupport() @@ -154,7 +155,7 @@ function main:Init() local function loadItemDBs() for type, typeList in pairsYield(data.uniques) do for _, raw in pairs(typeList) do - newItem = new("Item", raw, "UNIQUE", true) + newItem = new("Item"):Item(raw, "UNIQUE", true) if newItem.base then self.uniqueDB.list[newItem.name] = newItem elseif launch.devMode then @@ -167,7 +168,7 @@ function main:Init() ConPrintf("Uniques loaded") for _, raw in pairsYield(data.rares) do - newItem = new("Item", raw, "RARE", true) + newItem = new("Item"):Item(raw, "RARE", true) if newItem.base then if newItem.crafted then if newItem.base.implicit and #newItem.implicitModLines == 0 then @@ -198,23 +199,23 @@ function main:Init() self.defaultItemAffixQuality = saved end - self.anchorMain = new("Control", nil, {4, 0, 0, 0}) + self.anchorMain = new("Control"):Control(nil, {4, 0, 0, 0}) self.anchorMain.y = function() return self.screenH - 4 end - self.controls.options = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, 0, 68, 20}, "Options", function() + self.controls.options = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, 0, 68, 20}, "Options", function() self:OpenOptionsPopup() end) - self.controls.about = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {72, 0, 68, 20}, "About", function() + self.controls.about = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {72, 0, 68, 20}, "About", function() self:OpenAboutPopup() end) - self.controls.applyUpdate = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "^x50E050Update Ready", function() + self.controls.applyUpdate = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "^x50E050Update Ready", function() self:OpenUpdatePopup() end) self.controls.applyUpdate.shown = function() return launch.updateAvailable and launch.updateAvailable ~= "none" end - self.controls.checkUpdate = new("ButtonControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "", function() + self.controls.checkUpdate = new("ButtonControl"):ButtonControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -24, 140, 20}, "", function() launch:CheckForUpdate() end) self.controls.checkUpdate.shown = function() @@ -226,15 +227,15 @@ function main:Init() self.controls.checkUpdate.enabled = function() return not launch.updateCheckRunning end - self.controls.forkLabel = new("LabelControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {148, -26, 0, 16}, "") + self.controls.forkLabel = new("LabelControl"):LabelControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {148, -26, 0, 16}, "") self.controls.forkLabel.label = function() return "^8PoB Community Fork" end - self.controls.versionLabel = new("LabelControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {148, -2, 0, 16}, "") + self.controls.versionLabel = new("LabelControl"):LabelControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {148, -2, 0, 16}, "") self.controls.versionLabel.label = function() return "^8" .. (launch.versionBranch == "beta" and "Beta: " or "Version: ") .. launch.versionNumber .. (launch.versionBranch == "dev" and " (Dev)" or "") end - self.controls.devMode = new("LabelControl", {"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -26, 0, 20}, colorCodes.NEGATIVE.."Dev Mode") + self.controls.devMode = new("LabelControl"):LabelControl({"BOTTOMLEFT",self.anchorMain,"BOTTOMLEFT"}, {0, -26, 0, 20}, colorCodes.NEGATIVE.."Dev Mode") self.controls.devMode.shown = function() return launch.devMode end @@ -318,7 +319,7 @@ function main:LoadTree(treeVersion) elseif isValueInTable(treeVersionList, treeVersion) then data.setJewelRadiiGlobally(treeVersion) --ConPrintf("[main:LoadTree] - Lazy Loading Tree " .. treeVersion) - self.tree[treeVersion] = new("PassiveTree", treeVersion) + self.tree[treeVersion] = new("PassiveTree"):PassiveTree(treeVersion) return self.tree[treeVersion] end return nil @@ -666,7 +667,7 @@ function main:LoadSharedItems() rawItem.raw = subChild end end - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) t_insert(self.sharedItemList, newItem) elseif child.elem == "ItemSet" then local sharedItemSet = { title = child.attrib.title, slots = { } } @@ -678,7 +679,7 @@ function main:LoadSharedItems() rawItem.raw = subChild end end - local newItem = new("Item", rawItem.raw) + local newItem = new("Item"):Item(rawItem.raw) sharedItemSet.slots[grandChild.attrib.slotName] = newItem end end @@ -774,14 +775,14 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) local controls = { } local defaultLabelPlacementX = 8 - controls.label = new("LabelControl", { "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, 20, 206, 16 }, function() + controls.label = new("LabelControl"):LabelControl({ "TOPLEFT", nil, "TOPLEFT" }, { defaultLabelPlacementX, 20, 206, 16 }, function() return "^7User settings path cannot be loaded: ".. errMsg .. "\nCurrent Path: "..invalidPath:gsub("?", "^1?^7").."/Path of Building/".. "\nIf this location is managed by OneDrive, navigate to that folder and manually try" .. "\nto open Settings.xml in a text editor before re-opening Path of Building" .. "\nOtherwise, specify a new location for your Settings.xml:" end) - controls.userPath = new("EditControl", { "TOPLEFT", controls.label, "TOPLEFT" }, { 0, 60, 206, 20 }, invalidPath, nil, nil, nil, function(buf) + controls.userPath = new("EditControl"):EditControl({ "TOPLEFT", controls.label, "TOPLEFT" }, { 0, 60, 206, 20 }, invalidPath, nil, nil, nil, function(buf) invalidPath = sanitiseText(buf) if not invalidPath:match("?") then controls.save.enabled = true @@ -789,7 +790,7 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) controls.save.enabled = false end end) - controls.save = new("ButtonControl", { "TOPLEFT", controls.userPath, "TOPLEFT" }, { 0, 26, 206, 20 }, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({ "TOPLEFT", controls.userPath, "TOPLEFT" }, { 0, 26, 206, 20 }, "Save", function() local res, msg = MakeDir(controls.userPath.buf) if not res and msg ~= "No error" then self:OpenMessagePopup("Error", "Couldn't create '"..controls.userPath.buf.."' : "..msg) @@ -799,7 +800,7 @@ function main:OpenPathPopup(invalidPath, errMsg, ignoreBuild) end end) controls.save.enabled = false - controls.cancel = new("ButtonControl", nil, { 0, 0, 0, 0 }, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, { 0, 0, 0, 0 }, "Cancel", function() -- Do nothing, require user to enter a location end) self:OpenPopup(600, 150, "Change Settings Path", controls, "save", nil, "cancel") @@ -864,7 +865,7 @@ function main:OpenOptionsPopup(savedState) local popupWidth = useTwoColumns and columnWidth * 2 or columnWidth -- Scrollbar anchor - controls.sectionAnchor = new("Control", { "TOPLEFT", nil, "TOPLEFT" }, { 0, 0, popupWidth, 0 }) + controls.sectionAnchor = new("Control"):Control({ "TOPLEFT", nil, "TOPLEFT" }, { 0, 0, popupWidth, 0 }) -- local func to make a new line with a heightModifier local function nextRow(heightModifier) @@ -876,9 +877,9 @@ function main:OpenOptionsPopup(savedState) -- local func to make a new section header local function drawSectionHeader(id, title, omitHorizontalLine) local headerBGColor ={ .6, .6, .6} - controls["section-"..id .. "-bg"] = new("RectangleOutlineControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + scrollBarWidth + 8, currentY, columnWidth - (scrollBarWidth * 2) - 17, 26 }, headerBGColor, 1) + controls["section-"..id .. "-bg"] = new("RectangleOutlineControl"):RectangleOutlineControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + scrollBarWidth + 8, currentY, columnWidth - (scrollBarWidth * 2) - 17, 26 }, headerBGColor, 1) nextRow(.2) - controls["section-"..id .. "-label"] = new("LabelControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + columnWidth / 2 - 60, currentY, 0, 16 }, "^7" .. title) + controls["section-"..id .. "-label"] = new("LabelControl"):LabelControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + columnWidth / 2 - 60, currentY, 0, 16 }, "^7" .. title) nextRow(1.5) end @@ -887,25 +888,25 @@ function main:OpenOptionsPopup(savedState) drawSectionHeader("app", "Application options") - controls.connectionProtocol = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { + controls.connectionProtocol = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { { label = "Auto", protocol = 0 }, { label = "IPv4", protocol = 1 }, { label = "IPv6", protocol = 2 }, }, function(index, value) self.connectionProtocol = value.protocol end) - controls.connectionProtocolLabel = new("LabelControl", { "RIGHT", controls.connectionProtocol, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Connection Protocol:") + controls.connectionProtocolLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.connectionProtocol, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Connection Protocol:") controls.connectionProtocol.tooltipText = "Changes which protocol is used when downloading updates and importing builds." controls.connectionProtocol:SelByValue(launch.connectionProtocol, "protocol") nextRow() - controls.proxyType = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 18 }, { + controls.proxyType = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 18 }, { { label = "HTTP", scheme = "http" }, { label = "SOCKS", scheme = "socks5" }, { label = "SOCKS5H", scheme = "socks5h" }, }) - controls.proxyLabel = new("LabelControl", { "RIGHT", controls.proxyType, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Proxy server:") - controls.proxyURL = new("EditControl", { "LEFT", controls.proxyType, "RIGHT" }, { 4, 0, 206, 18 }) + controls.proxyLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.proxyType, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Proxy server:") + controls.proxyURL = new("EditControl"):EditControl({ "LEFT", controls.proxyType, "RIGHT" }, { 4, 0, 206, 18 }) if launch.proxyURL then local scheme, url = launch.proxyURL:match("(%w+)://(.+)") @@ -914,7 +915,7 @@ function main:OpenOptionsPopup(savedState) end nextRow() - controls.dpiScaleOverride = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 150, 18 }, { + controls.dpiScaleOverride = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 150, 18 }, { { label = "Use system default", percent = 0 }, { label = "100%", percent = 100 }, { label = "125%", percent = 125 }, @@ -930,95 +931,95 @@ function main:OpenOptionsPopup(savedState) self:ClosePopup() self:OpenOptionsPopup(savedState) end) - controls.dpiScaleOverrideLabel = new("LabelControl", { "RIGHT", controls.dpiScaleOverride, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7UI scaling override:") + controls.dpiScaleOverrideLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.dpiScaleOverride, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7UI scaling override:") controls.dpiScaleOverride.tooltipText = "Overrides Windows DPI scaling inside Path of Building.\nChoose a percentage between 100% and 250% or revert to the system default." controls.dpiScaleOverride:SelByValue(self.dpiScaleOverridePercent, "percent") nextRow() - controls.buildPath = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 290, 18 }) - controls.buildPathLabel = new("LabelControl", { "RIGHT", controls.buildPath, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Build save path:") + controls.buildPath = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 290, 18 }) + controls.buildPathLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.buildPath, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Build save path:") if self.buildPath ~= self.defaultBuildPath then controls.buildPath:SetText(self.buildPath) end controls.buildPath.tooltipText = "Overrides the default save location for builds.\nThe default location is: '"..self.defaultBuildPath.."'" nextRow() - controls.nodePowerTheme = new("DropDownControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { + controls.nodePowerTheme = new("DropDownControl"):DropDownControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, { { label = "Red & Blue", theme = "RED/BLUE" }, { label = "Red & Green", theme = "RED/GREEN" }, { label = "Green & Blue", theme = "GREEN/BLUE" }, }, function(index, value) self.nodePowerTheme = value.theme end) - controls.nodePowerThemeLabel = new("LabelControl", { "RIGHT", controls.nodePowerTheme, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Node Power colours:") + controls.nodePowerThemeLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.nodePowerTheme, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Node Power colours:") controls.nodePowerTheme.tooltipText = "Changes the colour scheme used for the node power display on the passive tree." controls.nodePowerTheme:SelByValue(self.nodePowerTheme, "theme") nextRow() - controls.colorPositive = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorPositive:gsub('^(^)', '0')), nil, nil, 8, function(buf) + controls.colorPositive = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorPositive:gsub('^(^)', '0')), nil, nil, 8, function(buf) local match = string.match(buf, "0x%x+") if match and #match == 8 then updateColorCode("POSITIVE", buf) self.colorPositive = buf end end) - controls.colorPositiveLabel = new("LabelControl", { "RIGHT", controls.colorPositive, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for positive values:") + controls.colorPositiveLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.colorPositive, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for positive values:") controls.colorPositive.tooltipText = "Overrides the default hex colour for positive values in breakdowns. \nExpected format is 0x000000. " .. "The default value is " .. tostring(defaultColorCodes.POSITIVE:gsub('^(^)', '0')) .. ".\nIf updating while inside a build, please re-load the build after saving." nextRow() - controls.colorNegative = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorNegative:gsub('^(^)', '0')), nil, nil, 8, function(buf) + controls.colorNegative = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorNegative:gsub('^(^)', '0')), nil, nil, 8, function(buf) local match = string.match(buf, "0x%x+") if match and #match == 8 then updateColorCode("NEGATIVE", buf) self.colorNegative = buf end end) - controls.colorNegativeLabel = new("LabelControl", { "RIGHT", controls.colorNegative, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for negative values:") + controls.colorNegativeLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.colorNegative, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for negative values:") controls.colorNegative.tooltipText = "Overrides the default hex colour for negative values in breakdowns. \nExpected format is 0x000000. " .. "The default value is " .. tostring(defaultColorCodes.NEGATIVE:gsub('^(^)', '0')) .. ".\nIf updating while inside a build, please re-load the build after saving." nextRow() - controls.colorHighlight = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorHighlight:gsub('^(^)', '0')), nil, nil, 8, function(buf) + controls.colorHighlight = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 100, 18 }, tostring(self.colorHighlight:gsub('^(^)', '0')), nil, nil, 8, function(buf) local match = string.match(buf, "0x%x+") if match and #match == 8 then updateColorCode("HIGHLIGHT", buf) self.colorHighlight = buf end end) - controls.colorHighlightLabel = new("LabelControl", { "RIGHT", controls.colorHighlight, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for highlight nodes:") + controls.colorHighlightLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.colorHighlight, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Hex colour for highlight nodes:") controls.colorHighlight.tooltipText = "Overrides the default hex colour for highlighting nodes in passive tree search. \nExpected format is 0x000000. " .. "The default value is " .. tostring(defaultColorCodes.HIGHLIGHT:gsub('^(^)', '0')) .."\nIf updating while inside a build, please re-load the build after saving." nextRow() - controls.betaTest = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Opt-in to weekly beta test builds:", function(state) + controls.betaTest = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Opt-in to weekly beta test builds:", function(state) self.betaTest = state end) nextRow() - controls.edgeSearchHighlight = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20}, "^7Show search circles at viewport edge", function(state) + controls.edgeSearchHighlight = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20}, "^7Show search circles at viewport edge", function(state) self.edgeSearchHighlight = state end) nextRow() - controls.showPublicBuilds = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show Latest/Trending builds:", function(state) + controls.showPublicBuilds = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show Latest/Trending builds:", function(state) self.showPublicBuilds = state end) nextRow() - controls.showFlavourText = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Styled Tooltips with Flavour Text:", function(state) + controls.showFlavourText = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Styled Tooltips with Flavour Text:", function(state) self.showFlavourText = state end) controls.showFlavourText.tooltipText = "If updating while inside a build, please re-load the build after saving." nextRow() - controls.showAnimations = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show Animations:", function(state) + controls.showAnimations = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show Animations:", function(state) self.showAnimations = state end) nextRow() - controls.showAllItemAffixes = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show all item affixes sliders:", function(state) + controls.showAllItemAffixes = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show all item affixes sliders:", function(state) self.showAllItemAffixes = state end) controls.showAllItemAffixes.tooltipText = "Display all item affix slots as a stacked list instead of hiding them in dropdowns" @@ -1036,80 +1037,80 @@ function main:OpenOptionsPopup(savedState) -- Build-related Option Section starts drawSectionHeader("build", "Build-related options") - controls.showThousandsSeparators = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show thousands separators:", function(state) + controls.showThousandsSeparators = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show thousands separators:", function(state) self.showThousandsSeparators = state end) controls.showThousandsSeparators.state = self.showThousandsSeparators nextRow() - controls.thousandsSeparator = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 30, 20 }, self.thousandsSeparator, nil, "%w", 1, function(buf) + controls.thousandsSeparator = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 30, 20 }, self.thousandsSeparator, nil, "%w", 1, function(buf) self.thousandsSeparator = buf end) - controls.thousandsSeparatorLabel = new("LabelControl", { "RIGHT", controls.thousandsSeparator, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Thousands separator:") + controls.thousandsSeparatorLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.thousandsSeparator, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Thousands separator:") nextRow() - controls.decimalSeparator = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 30, 20 }, self.decimalSeparator, nil, "%w", 1, function(buf) + controls.decimalSeparator = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 30, 20 }, self.decimalSeparator, nil, "%w", 1, function(buf) self.decimalSeparator = buf end) - controls.decimalSeparatorLabel = new("LabelControl", { "RIGHT", controls.decimalSeparator, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Decimal separator:") + controls.decimalSeparatorLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.decimalSeparator, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Decimal separator:") nextRow() - controls.titlebarName = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show build name in window title:", function(state) + controls.titlebarName = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show build name in window title:", function(state) self.showTitlebarName = state end) nextRow() - controls.defaultGemQuality = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 20 }, self.defaultGemQuality, nil, "%D", 2, function(gemQuality) + controls.defaultGemQuality = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 20 }, self.defaultGemQuality, nil, "%D", 2, function(gemQuality) self.defaultGemQuality = m_min(tonumber(gemQuality) or 0, 23) end) controls.defaultGemQuality.tooltipText = "Set the default quality that can be overwritten by build-related quality settings in the skill panel." - controls.defaultGemQualityLabel = new("LabelControl", { "RIGHT", controls.defaultGemQuality, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Default gem quality:") + controls.defaultGemQualityLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.defaultGemQuality, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Default gem quality:") nextRow() - controls.defaultCharLevel = new("EditControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 20 }, self.defaultCharLevel, nil, "%D", 3, function(charLevel) + controls.defaultCharLevel = new("EditControl"):EditControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 80, 20 }, self.defaultCharLevel, nil, "%D", 3, function(charLevel) self.defaultCharLevel = m_min(m_max(tonumber(charLevel) or 1, 1), 100) end) controls.defaultCharLevel.tooltipText = "Set the default level of your builds. If this is higher than 1, manual level mode will be enabled by default in new builds." - controls.defaultCharLevelLabel = new("LabelControl", { "RIGHT", controls.defaultCharLevel, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Default character level:") + controls.defaultCharLevelLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.defaultCharLevel, "LEFT" }, { defaultLabelSpacingPx, 0, 0, 16 }, "^7Default character level:") nextRow() - controls.defaultItemAffixQualitySlider = new("SliderControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 200, 20 }, function(value) + controls.defaultItemAffixQualitySlider = new("SliderControl"):SliderControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 200, 20 }, function(value) self.defaultItemAffixQuality = round(value, 2) controls.defaultItemAffixQualityValue.label = (self.defaultItemAffixQuality * 100) .. "%" end) - controls.defaultItemAffixQualityLabel = new("LabelControl", { "RIGHT", controls.defaultItemAffixQualitySlider, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Default item affix quality:") - controls.defaultItemAffixQualityValue = new("LabelControl", { "LEFT", controls.defaultItemAffixQualitySlider, "RIGHT" }, { -defaultLabelSpacingPx, 0, 92, 16 }, "50%") + controls.defaultItemAffixQualityLabel = new("LabelControl"):LabelControl({ "RIGHT", controls.defaultItemAffixQualitySlider, "LEFT" }, { defaultLabelSpacingPx, 0, 92, 16 }, "^7Default item affix quality:") + controls.defaultItemAffixQualityValue = new("LabelControl"):LabelControl({ "LEFT", controls.defaultItemAffixQualitySlider, "RIGHT" }, { -defaultLabelSpacingPx, 0, 92, 16 }, "50%") controls.defaultItemAffixQualitySlider.val = self.defaultItemAffixQuality controls.defaultItemAffixQualityValue.label = (self.defaultItemAffixQuality * 100) .. "%" nextRow() - controls.showWarnings = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show build warnings:", function(state) + controls.showWarnings = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show build warnings:", function(state) self.showWarnings = state end) controls.showWarnings.state = self.showWarnings nextRow() - controls.slotOnlyTooltips = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show tooltips only for affected slots:", function(state) + controls.slotOnlyTooltips = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show tooltips only for affected slots:", function(state) self.slotOnlyTooltips = state end, "Shows comparisons in tooltips only for the slot you are currently placing the item in, instead of all slots.") controls.slotOnlyTooltips.state = self.slotOnlyTooltips nextRow() - controls.migrateEldritchImplicits = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Copy Eldritch Implicits onto Display Item:", function(state) + controls.migrateEldritchImplicits = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Copy Eldritch Implicits onto Display Item:", function(state) self.migrateEldritchImplicits = state end) controls.migrateEldritchImplicits.tooltipText = "Apply Eldritch Implicits from current gear when comparing new gear, given the new item doesn't have any influence" controls.migrateEldritchImplicits.state = self.migrateEldritchImplicits nextRow() - controls.notSupportedModTooltips = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show tooltip for unsupported mods :", function(state) + controls.notSupportedModTooltips = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Show tooltip for unsupported mods :", function(state) self.notSupportedModTooltips = state end) controls.notSupportedModTooltips.tooltipText = "Show ^8(Not supported in PoB yet) ^7next to unsupported mods" controls.notSupportedModTooltips.state = self.notSupportedModTooltips nextRow() - controls.invertSliderScrollDirection = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Invert slider scroll direction:", function(state) + controls.invertSliderScrollDirection = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Invert slider scroll direction:", function(state) self.invertSliderScrollDirection = state end) controls.invertSliderScrollDirection.tooltipText = "Default scroll direction is:\nScroll Up = Move right\nScroll Down = Move left" @@ -1117,7 +1118,7 @@ function main:OpenOptionsPopup(savedState) if launch.devMode then nextRow() - controls.disableDevAutoSave = new("CheckBoxControl", { "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Disable Dev AutoSave:", function(state) + controls.disableDevAutoSave = new("CheckBoxControl"):CheckBoxControl({ "TOPLEFT", controls.sectionAnchor, "TOPLEFT" }, { currentX + defaultLabelPlacementX, currentY, 20 }, "^7Disable Dev AutoSave:", function(state) self.disableDevAutoSave = state end) controls.disableDevAutoSave.tooltipText = "Do not Autosave builds while on Dev branch" @@ -1139,7 +1140,7 @@ function main:OpenOptionsPopup(savedState) nextRow(1.5) -- lock the Save/Cancel buttons to the bottom so they don't scroll away - controls.save = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Save", function() + controls.save = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {-45, -10, 80, 20}, "Save", function() launch.connectionProtocol = tonumber(self.connectionProtocol) if controls.proxyURL.buf:match("%w") then launch.proxyURL = controls.proxyType.list[controls.proxyType.selIndex].scheme .. "://" .. controls.proxyURL.buf @@ -1164,7 +1165,7 @@ function main:OpenOptionsPopup(savedState) main:ClosePopup() main:SaveSettings() end) - controls.cancel = new("ButtonControl", { "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl({ "BOTTOM", nil, "BOTTOM" }, {45, -10, 80, 20}, "Cancel", function() self.nodePowerTheme = savedState.nodePowerTheme self.colorPositive = savedState.colorPositive updateColorCode("POSITIVE", self.colorPositive) @@ -1199,7 +1200,7 @@ function main:OpenOptionsPopup(savedState) local popupHeight = useScrollBar and (self.screenH - 20) or currentY + 30 if useScrollBar then - controls.scrollBar = new("ScrollBarControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-2, 25, scrollBarWidth, popupHeight - 65}, 50, "VERTICAL", true) + controls.scrollBar = new("ScrollBarControl"):ScrollBarControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-2, 25, scrollBarWidth, popupHeight - 65}, 50, "VERTICAL", true) controls.scrollBar:SetContentDimension(currentY, popupHeight - 65) end @@ -1293,15 +1294,15 @@ function main:OpenUpdatePopup() end end local controls = { } - controls.changeLog = new("TextListControl", nil, {0, 20, 780, 542}, nil, changeList) - controls.update = new("ButtonControl", nil, {-45, 570, 80, 20}, "Update", function() + controls.changeLog = new("TextListControl"):TextListControl(nil, {0, 20, 780, 542}, nil, changeList) + controls.update = new("ButtonControl"):ButtonControl(nil, {-45, 570, 80, 20}, "Update", function() self:ClosePopup() local ret = self:CallMode("CanExit", "UPDATE") if ret == nil or ret == true then launch:ApplyUpdate(launch.updateAvailable) end end) - controls.cancel = new("ButtonControl", nil, {45, 570, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 570, 80, 20}, "Cancel", function() self:ClosePopup() end) self:OpenPopup(800, 600, "Update Available", controls) @@ -1397,23 +1398,23 @@ function main:OpenAboutPopup(helpSectionIndex) helpSectionIndex = newIndex end local controls = { } - controls.close = new("ButtonControl", {"TOPRIGHT",nil,"TOPRIGHT"}, {-10, 10, 50, 20}, "Close", function() + controls.close = new("ButtonControl"):ButtonControl({"TOPRIGHT",nil,"TOPRIGHT"}, {-10, 10, 50, 20}, "Close", function() self:ClosePopup() end) - controls.version = new("LabelControl", nil, {0, 18, 0, 18}, "^7Path of Building Community Fork v"..launch.versionNumber) - controls.forum = new("LabelControl", nil, {0, 36, 0, 18}, "^7Based on Openarl's Path of Building") - controls.github = new("ButtonControl", nil, {0, 62, 438, 18}, "^7GitHub page: ^x4040FFhttps://github.com/PathOfBuildingCommunity/PathOfBuilding", function(control) + controls.version = new("LabelControl"):LabelControl(nil, {0, 18, 0, 18}, "^7Path of Building Community Fork v"..launch.versionNumber) + controls.forum = new("LabelControl"):LabelControl(nil, {0, 36, 0, 18}, "^7Based on Openarl's Path of Building") + controls.github = new("ButtonControl"):ButtonControl(nil, {0, 62, 438, 18}, "^7GitHub page: ^x4040FFhttps://github.com/PathOfBuildingCommunity/PathOfBuilding", function(control) OpenURL("https://github.com/PathOfBuildingCommunity/PathOfBuilding") end) - controls.verLabel = new("ButtonControl", {"TOPLEFT", nil, "TOPLEFT"}, {10, 85, 100, 18}, "^7Version history:", function() + controls.verLabel = new("ButtonControl"):ButtonControl({"TOPLEFT", nil, "TOPLEFT"}, {10, 85, 100, 18}, "^7Version history:", function() controls.changelog.list = changeList controls.changelog.sectionHeights = changeVersionHeights end) - controls.helpLabel = new("ButtonControl", {"TOPRIGHT", nil, "TOPRIGHT"}, {-10, 85, 40, 18}, "^7Help:", function() + controls.helpLabel = new("ButtonControl"):ButtonControl({"TOPRIGHT", nil, "TOPRIGHT"}, {-10, 85, 40, 18}, "^7Help:", function() controls.changelog.list = helpList controls.changelog.sectionHeights = helpSectionHeights end) - controls.changelog = new("TextListControl", nil, {0, 103, popupWidth - 20, 515}, {{ x = 1, align = "LEFT" }, { x = 135, align = "LEFT" }}, helpSectionIndex and helpList or changeList, helpSectionIndex and helpSectionHeights or changeVersionHeights) + controls.changelog = new("TextListControl"):TextListControl(nil, {0, 103, popupWidth - 20, 515}, {{ x = 1, align = "LEFT" }, { x = 135, align = "LEFT" }}, helpSectionIndex and helpList or changeList, helpSectionIndex and helpSectionHeights or changeVersionHeights) if helpSectionIndex then controls.changelog.controls.scrollBar.offset = helpSections[helpSectionIndex].height * textSize end @@ -1595,7 +1596,7 @@ function main:CopyFolder(srcName, dstName) end function main:OpenPopup(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) - local popup = new("PopupDialog", width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) + local popup = new("PopupDialog"):PopupDialog(width, height, title, controls, enterControl, defaultControl, escapeControl, scrollBarFunc, resizeFunc) t_insert(self.popups, 1, popup) return popup end @@ -1608,10 +1609,10 @@ function main:OpenMessagePopup(title, msg) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.close = new("ButtonControl", nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {0, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") @@ -1621,7 +1622,7 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end local confirmWidth = m_max(80, DrawStringWidth(16, "VAR", confirmLabel) + 10) @@ -1636,7 +1637,7 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, local buttonY = 40 + numMsgLines * 16 local function placeButton(width, label, onClick, isConfirm) local centerX = leftEdge + width / 2 - local ctrl = new("ButtonControl", nil, {centerX, buttonY, width, 20}, label, function() + local ctrl = new("ButtonControl"):ButtonControl(nil, {centerX, buttonY, width, 20}, label, function() main:ClosePopup() onClick() end) @@ -1653,11 +1654,11 @@ function main:OpenConfirmPopup(title, msg, confirmLabel, onConfirm, extraLabel, return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, totalWidth + 40), 70 + numMsgLines * 16, title, controls, "confirm") else -- Two button layout (original) - controls.confirm = new("ButtonControl", nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() + controls.confirm = new("ButtonControl"):ButtonControl(nil, {-5 - m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, confirmLabel, function() main:ClosePopup() onConfirm() end) - t_insert(controls, new("ButtonControl", nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() + t_insert(controls, new("ButtonControl"):ButtonControl(nil, {5 + m_ceil(confirmWidth/2), 40 + numMsgLines * 16, confirmWidth, 20}, "Cancel", function() main:ClosePopup() end)) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "confirm") @@ -1666,11 +1667,11 @@ end function main:OpenNewFolderPopup(path, onClose) local controls = { } - controls.label = new("LabelControl", nil, {0, 20, 0, 16}, "^7Enter folder name:") - controls.edit = new("EditControl", nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) + controls.label = new("LabelControl"):LabelControl(nil, {0, 20, 0, 16}, "^7Enter folder name:") + controls.edit = new("EditControl"):EditControl(nil, {0, 40, 350, 20}, nil, nil, "\\/:%*%?\"<>|%c", 100, function(buf) controls.create.enabled = buf:match("%S") end) - controls.create = new("ButtonControl", nil, {-45, 70, 80, 20}, "Create", function() + controls.create = new("ButtonControl"):ButtonControl(nil, {-45, 70, 80, 20}, "Create", function() local newFolderName = controls.edit.buf local res, msg = MakeDir(path..newFolderName) if not res then @@ -1683,7 +1684,7 @@ function main:OpenNewFolderPopup(path, onClose) main:ClosePopup() end) controls.create.enabled = false - controls.cancel = new("ButtonControl", nil, {45, 70, 80, 20}, "Cancel", function() + controls.cancel = new("ButtonControl"):ButtonControl(nil, {45, 70, 80, 20}, "Cancel", function() if onClose then onClose() end @@ -1708,14 +1709,14 @@ function main:OpenCloudErrorPopup(fileName) local controls = { } local numMsgLines = 0 for line in string.gmatch(msg .. "\n", "([^\n]*)\n") do - t_insert(controls, new("LabelControl", nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) + t_insert(controls, new("LabelControl"):LabelControl(nil, {0, 20 + numMsgLines * 16, 0, 16}, line)) numMsgLines = numMsgLines + 1 end - controls.help = new("ButtonControl", nil, {-55, 40 + numMsgLines * 16, 80, 20}, "Help (web)", function() + controls.help = new("ButtonControl"):ButtonControl(nil, {-55, 40 + numMsgLines * 16, 80, 20}, "Help (web)", function() OpenURL(url) end) controls.help.tooltipText = url - controls.close = new("ButtonControl", nil, {55, 40 + numMsgLines * 16, 80, 20}, "Ok", function() + controls.close = new("ButtonControl"):ButtonControl(nil, {55, 40 + numMsgLines * 16, 80, 20}, "Ok", function() main:ClosePopup() end) return self:OpenPopup(m_max(DrawStringWidth(16, "VAR", msg) + 30, 190), 70 + numMsgLines * 16, title, controls, "close") diff --git a/src/Modules/ModParser.lua b/src/Modules/ModParser.lua index 2438ab4ec8..b94e65cac1 100644 --- a/src/Modules/ModParser.lua +++ b/src/Modules/ModParser.lua @@ -6214,7 +6214,7 @@ local jewelSelfUnallocFuncs = { ["Grants all bonuses of Unallocated Small Passive Skills in Radius"] = function(node, out, data) if node then if node.type == "Normal" then - data.modList = data.modList or new("ModList") + data.modList = data.modList or new("ModList"):ModList() -- Filter out "Condition:ConnectedTo" mods as these nodes are not technically allocated by this jewel func for _, mod in ipairs(out) do @@ -6230,7 +6230,7 @@ local jewelSelfUnallocFuncs = { ["Grants all bonuses of Unallocated Notable Passive Skills in Radius"] = function(node, out, data) if node then if node.type == "Notable" then - data.modList = data.modList or new("ModList") + data.modList = data.modList or new("ModList"):ModList() -- Filter out "Condition:ConnectedTo" mods as these nodes are not technically allocated by this jewel func for _, mod in ipairs(out) do diff --git a/src/Modules/ToastNotification.lua b/src/Modules/ToastNotification.lua index e934dfcca4..2c95af2cda 100644 --- a/src/Modules/ToastNotification.lua +++ b/src/Modules/ToastNotification.lua @@ -171,17 +171,14 @@ function ToastNotification:Render() if not toast.mode then toast.mode = "SHOWING" toast.start = GetTime() - toast.dismissButton = new( - "ButtonControl", - { "BOTTOMLEFT", anchorMain, "BOTTOMLEFT" }, + toast.dismissButton = new("ButtonControl"):ButtonControl({ "BOTTOMLEFT", anchorMain, "BOTTOMLEFT" }, { 4, 0, 80, 20 }, "Dismiss", function() dismissedIds[toast.id] = true toast.mode = "HIDING" toast.start = GetTime() - end - ) + end) end local now = GetTime() diff --git a/src/_SimpleGraphic.def.lua b/src/_SimpleGraphic.def.lua new file mode 100644 index 0000000000..aad9578544 --- /dev/null +++ b/src/_SimpleGraphic.def.lua @@ -0,0 +1,467 @@ +--- this file defines function signatures for the runtime API, and is not meant +-- to be used directly. the function bodies here ARE NOT correct for regular +-- PoB use. they are implemented by SimpleGraphic, and are only correct for +-- headless mode, in which case this file IS executed. +--- @meta + +---@alias Font "FIXED"|"VAR"|"VAR BOLD"|"FONTIN SC"|"FONTIN SC ITALIC"|"FONTIN"|"FONTIN ITALIC" + +---@param name string +---@param func? fun() +function SetCallback(name, func) + ---@diagnostic disable-next-line: undefined-global headless wrapper + __callbackTable__[name] = func +end + +---@param name string +---@return table +function GetCallback(name) + ---@diagnostic disable-next-line: undefined-global headless wrapper + return __callbackTable__[name] +end + +---@param object? table +function SetMainObject(object) + __mainObject__ = object +end + +---@class ImageHandle +local imageHandleClass = {} +imageHandleClass.__index = imageHandleClass + +---@return ImageHandle +function NewImageHandle() + return setmetatable({}, imageHandleClass) +end + +---@param fileName string +---@param ... "ASYNC"|"CLAMP"|"MIPMAP" +function imageHandleClass:Load(fileName, ...) + self.valid = true +end + +---@class ArtHandle +local artHandleClass = {} + +---@return integer width +---@return integer height +function artHandleClass:Size() end + +---@alias ArtFlag "CLAMP"|"MIPMAP"|"NEAREST" + +---@param art userdata ArtHandle +---@param x1 integer +---@param y1 integer +---@param x2 integer +---@param y2 integer +---@param ... ArtFlag +function imageHandleClass:LoadArtRectangle(art, x1, y1, x2, y2, ...) end + +---@param art userdata ArtHandle +---@param xC integer +---@param yC integer +---@param rMin integer +---@param rMax integer +---@param ... ArtFlag +function imageHandleClass:LoadArtArcBand(art, xC, yC, rMin, rMax, ...) end + +function imageHandleClass:Unload() + self.valid = false +end + +---@return boolean +function imageHandleClass:IsValid() + return self.valid +end + +---@param priority number +function imageHandleClass:SetLoadingPriority(priority) end + +---@return integer width +---@return integer height +function imageHandleClass:ImageSize() + return 1, 1 +end + +---@param fileName string +---@return userdata +function NewArtHandle(fileName) end + +---@return integer width +---@return integer height +function GetScreenSize() + return 1920, 1080 +end + +---@return number +function GetScreenScale() + return 1 +end + +---@param red number +---@param green number +---@param blue number +---@param alpha? number +function SetClearColor(red, green, blue, alpha) end + +---@param layer? number +---@param subLayer? number +function SetDrawLayer(layer, subLayer) end + +---@return integer +function GetDrawLayer() end + +---@param x number +---@param y number +---@param width number +---@param height number +---@overload fun() +function SetViewport(x, y, width, height) end + +---@param mode ("ALPHA"|"PREALPHA"|"ADDITIVE") +function SetBlendMode(mode) end + +---@param r number +---@param g number +---@param b number +---@param a number? +function SetDrawColor(r, g, b, a) end + +---@param escapeStr string +function SetDrawColor(escapeStr) end + +---@return number r +---@return number g +---@return number b +---@return number a +function GetDrawColor() end + +---@param percent integer +function SetDPIScaleOverridePercent(percent) end + +---@return integer +function GetDPIScaleOverridePercent() + return 1 +end + +---@param imgHandle? userdata +---@param left number +---@param top number +---@param width number +---@param height number +function DrawImage(imgHandle, left, top, width, height) end + +---@param imgHandle? userdata +---@param left number +---@param top number +---@param width number +---@param height number +---@param tcLeft number +---@param tcTop number +---@param tcRight number +---@param tcBottom number +function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom) end + +---@param imgHandle? userdata +---@param left number +---@param top number +---@param width number +---@param height number +---@param stackIdx integer must be positive +---@param mask? integer must be positive +function DrawImage(imgHandle, left, top, width, height, tcLeft, tcTop, tcRight, tcBottom, stackIdx, mask) end + +---@param imgHandle? userdata +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param y4 number +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4) end + +---@param imgHandle? userdata +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param s1 number +---@param t1 number +---@param s2 number +---@param t2 number +---@param s3 number +---@param t3 number +---@param s4 number +---@param t4 number +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4, s1, t1, s2, t2, s3, t3, s4, t4) end + +---@param imgHandle? userdata +---@param x1 number +---@param y1 number +---@param x2 number +---@param y2 number +---@param x3 number +---@param y3 number +---@param x4 number +---@param y4 number +---@param stackIdx integer? must be positive +---@param mask integer? must be positive +function DrawImageQuad(imgHandle, x1, y1, x2, y2, x3, y3, x4, y4, stackIdx, mask) end + +---@param left number +---@param top number +---@param align? ("LEFT"|"CENTER"|"RIGHT"|"CENTER_X"|"RIGHT_X") +---@param height number +---@param font Font +---@param text string +function DrawString(left, top, align, height, font, text) end + +---@param height number +---@param font Font +---@param text string +---@return integer physicalWidth +function DrawStringWidth(height, font, text) + return 1 +end + +---@param height number +---@param font Font +---@param text string +---@param cursorX number +---@param cursorY number +---@return integer +function DrawStringCursorIndex(height, font, text, cursorX, cursorY) + return 0 +end + +---@param text string +---@return string +function StripEscapes(text) + local s, _ = text:gsub("%^%d", ""):gsub("%^x%x%x%x%x%x%x", "") + return s +end + +---@return integer asyncCount +function GetAsyncCount() + return 0 +end + +---@param flag1 string +---@param ... string +function RenderInit(flag1, ...) end + +---@class FileSearchHandle +local fileSearchHandleClass = {} + +---@return boolean +function fileSearchHandleClass:NextFile() end + +---@return string +function fileSearchHandleClass:GetFileName() end + +---@return integer +function fileSearchHandleClass:GetFileSize() end + +---@return number +function fileSearchHandleClass:GetFileModifiedTime() end + +---@param spec string +---@param findDirectories? boolean +---@return FileSearchHandle +function NewFileSearch(spec, findDirectories) end + +---@param path string +---@return string? name +---@return string? version +---@return integer? status +function GetCloudProvider(path) + return nil, nil, nil +end + +---@param title string +function SetWindowTitle(title) end + +---@return number x +---@return number y +function GetCursorPos() + return 0, 0 +end + +---@param x number +---@param y number +function SetCursorPos(x, y) end + +---@param doShow boolean +function ShowCursor(doShow) end + +---@param keyName string cannot be empty or an unrecognised key name +function IsKeyDown(keyName) end + +---@param text string +function Copy(text) end + +---@return string? data +function Paste() end + +---@param data string +---@return string? compressedData +---@return string? errMsg +function Deflate(data) + return "" +end + +---@param data string +---@return string? data +---@return string? errMsg +function Inflate(data) + return "" +end + +---@return integer timeMillis +function GetTime() + return 0 +end + +---@return string scriptPath +---@return string? scriptFallback +---@return string? errMsg +function GetScriptPath() + return "" +end + +---@return string runtimePath +---@return string? fallbackPath +---@return string? errMsg +function GetRuntimePath() + return "" +end + +---@return string? userPath +---@return string? invalidPath +---@return string? errMsg +function GetUserPath() + return "" +end + +---@param path string +---@return true|([nil, string]) true on success, or nil and error message +function MakeDir(path) end + +---@param path string +---@param recurse? boolean +function RemoveDir(path, recurse) end + +---@param path string +function SetWorkDir(path) end + +---@return string +function GetWorkDir() + return "" +end + +---@alias SubScriptID userdata + +---@param scriptText string +---@param funcList string +---@param subList string +---@param ... nil|boolean|number|string +---@return SubScriptID +function LaunchSubScript(scriptText, funcList, subList, ...) end + +---@param ssID SubScriptID +function AbortSubScript(ssID) end + +---@param ssID SubScriptID +---@return boolean isRunning +function IsSubScriptRunning(ssID) end + +---@param name string +---@param ... any +---@return unknown retVal use ---@module "name" instead +function LoadModule(name, ...) + if not name:match("%.lua") then + name = name .. ".lua" + end + local func, err = loadfile(name) + if func then + return func(...) + else + error("LoadModule() error loading '" .. name .. "': " .. err) + end +end + +---@param modName string +---@param ... any +---@return unknown retVal use ---@module "name" instead +function PLoadModule(modName, ...) + if not modName:match("%.lua") then + modName = modName .. ".lua" + end + local func, err = loadfile(modName) + if func then + return PCall(func, ...) + else + error("PLoadModule() error loading '" .. modName .. "': " .. err) + end +end + +---@generic T +---@generic R +---@param func fun(...: T): R +---@param ... any +---@return any? err +---@return R? retVal +function PCall(func, ...) + local ret = { pcall(func, ...) } + if ret[1] then + table.remove(ret, 1) + ---@diagnostic disable-next-line: redundant-return-value headless wrapper + return nil, unpack(ret) + else + return ret[2] + end +end + +---@param fmt string +---@param ... any +function ConPrintf(fmt, ...) + -- Optional + print(string.format(fmt, ...)) +end + +---@param tbl table +---@param noRecurse any converted to boolean +function ConPrintTable(tbl, noRecurse) end + +---@param cmd string +function ConExecute(cmd) end + +function ConClear() end + +---@param ... (string|boolean|number|integer) +function print(...) end + +---@param cmdName string +---@param args string? +function SpawnProcess(cmdName, args) end + +---@param url string +---@return string? error +function OpenURL(url) end + +---@param isEnabled boolean +function SetProfiling(isEnabled) end + +function TakeScreenshot() end + +function Restart() end + +---@param msg string? +function Exit(msg) end + +function SetForeground() end