Advertisement
mece

StructurePicker

Jul 24th, 2022 (edited)
602
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 9.76 KB | None | 0 0
  1. -- 【 LICENCE 】
  2. --------------------------------------------------------------------------------
  3. -- The MIT License (MIT)
  4. --
  5. -- Copyright (c) mece from opencheattables.org
  6. --
  7. -- Permission is hereby granted, free of charge, to any person obtaining a
  8. -- copy of this software and associated documentation files (the "Software"),
  9. -- to deal in the Software without restriction, including without limitation
  10. -- the rights to use, copy, modify, merge, publish, distribute, sublicense,
  11. -- and/or sell copies of the Software, and to permit persons to whom the
  12. -- Software is furnished to do so, subject to the following conditions:
  13. --
  14. -- The above copyright notice and this permission notice shall be included in
  15. -- all copies or substantial portions of the Software.
  16. --
  17. -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  22. -- FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  23. -- DEALINGS IN THE SOFTWARE.
  24. --------------------------------------------------------------------------------
  25. -- 【 FILE INFO 】
  26. --  ㅤ❖ This is an extention for Cheat Engine 7.4 (https://cheatengine.org)
  27. --
  28. -- 【 FEATURES 】
  29. --  ㅤ❖ Adds 'Structure picker' menu item into the 'Structures' menu
  30. --  ㅤㅤ of 'Structure dissect' window (default shortcut Ctrl+D)
  31. --  ㅤ❖ New menu opens 'Structure picker' window with all global structures
  32. --  ㅤ❖ 'Structure picker' automatically selects the main structure of
  33. --  ㅤㅤ the 'Structure dissect' foreground window
  34. --  ㅤ❖ Selecting structure from the 'Structure picker' replaces the main
  35. --  ㅤㅤ structure of the 'Structure dissect' foreground window
  36. --  ㅤ❖ 'Structure picker' contains a text filter which helps to find
  37. --  ㅤㅤ a structure in a long list
  38. --  ㅤ❖ 'Up' and 'Down' arrow keys transfer focus from the filter to
  39. --  ㅤㅤ the list and used to navigate
  40. --  ㅤ❖ 'Ctrl+F' transfers focus from the list to the filter
  41.  
  42. -- 【 HOW TO INSTALL 】
  43. --  ㅤ❖ Place the .lua file in CE autorun folder. Could be:
  44. --  ㅤㅤ C:\Program Files\Cheat Engine 7.4\autorun
  45. --  ㅤ❖ Place the .frm file in CE autorun\forms folder. Could be:
  46. --  ㅤㅤ C:\Program Files\Cheat Engine 7.4\autorun\forms
  47. --
  48. -- 【 CHANGE LOG 】
  49. --  ㅤ⋯ 2022-06-09 ⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯⋯
  50. --  ㅤ❖ initial version
  51. --
  52. -- 【 CONTACT THE AUTHOR 】
  53. --  ㅤ❖ https://forum.cheatengine.org/profile.php?mode=viewprofile&u=388402
  54. --  ㅤ❖ https://opencheattables.org/memberlist.php?mode=viewprofile&u=239
  55. --
  56. --------------------------------------------------------------------------------
  57. local sp = {}
  58. --------------------------------------------------------------------------------
  59. local function isValidStructureFrm(frm)
  60.   return frm and (frm.ClassName=='TfrmStructures2')
  61. end
  62. --------------------------------------------------------------------------------
  63. local function updateGlobalStructureList()
  64.   local needUpdate = getStructureCount() ~= #sp.globalStructureList
  65.   if needUpdate then sp.globalStructureList = {} end
  66.   for i=0,getStructureCount()-1 do
  67.     local s = getStructure(i)
  68.     needUpdate = needUpdate or (sp.globalStructureList[i+1] ~= s) or (sp.globalStructureList[i+1].OldName ~= s.Name)
  69.     sp.globalStructureList[i+1] = s
  70.     sp.globalStructureList[i+1].OldName = s.Name
  71.   end
  72.   return needUpdate
  73. end
  74. --------------------------------------------------------------------------------
  75. local function lookupListBoxData(listBox, needle)
  76.   local index = -1
  77.   for i=0,listBox.Items.Count-1 do
  78.     if integerToUserData(listBox.Items.Data[i]) == needle then
  79.       index = i
  80.       break
  81.     end
  82.   end
  83.   return index
  84. end
  85. --------------------------------------------------------------------------------
  86. local function filtered(haystack)
  87.   local result = nil
  88.   local needle = sp.picker.CEEditFilter.Text
  89.   if needle and needle ~= '' then
  90.     result = not string.find(string.upper(haystack), string.upper(needle),1,true)
  91.   end
  92.   return result
  93. end
  94. --------------------------------------------------------------------------------
  95. local function changeSelection(listBox, newIndex)
  96.   listBox.clearSelection()
  97.   listBox.ItemIndex = newIndex
  98.   if newIndex >= 0 then
  99.     listBox.Selected[newIndex] = true
  100.   end
  101. end
  102. --------------------------------------------------------------------------------
  103. local function clearSelection(listBox)
  104.   listBox.clearSelection()
  105.   listBox.ItemIndex = -1
  106. end
  107. --------------------------------------------------------------------------------
  108. local function selectedData(listBox)
  109.   local data = nil
  110.   local idx = listBox.itemIndex
  111.   if idx >= 0 and listBox.Selected[idx] then
  112.     data = integerToUserData(listBox.Items.Data[idx])
  113.   end
  114.   return data
  115. end
  116. --------------------------------------------------------------------------------
  117. local function selectMainStructure(form)
  118.   local listBox = sp.picker.CEListBoxStructures
  119.   if form.MainStruct and listBox.Items.Count > 0 then
  120.     if form.MainStruct ~= selectedData(listBox) then
  121.       changeSelection(listBox, lookupListBoxData(listBox, form.MainStruct))
  122.     end
  123.   else
  124.     clearSelection(listBox)
  125.   end
  126. end
  127. --------------------------------------------------------------------------------
  128. local function updateCEListBoxStructures()
  129.   local items = sp.picker.CEListBoxStructures.Items
  130.   items.beginUpdate()
  131.   items.clear()
  132.   for i=0,getStructureCount()-1 do
  133.     local structure = getStructure(i)
  134.     if not filtered(structure.Name) then
  135.       items.add(structure.Name, userDataToInteger(structure))
  136.     end
  137.   end
  138.   items.endUpdate()
  139.   if isValidStructureFrm(sp.focused) then
  140.     selectMainStructure(sp.focused)
  141.   end
  142. end
  143. --------------------------------------------------------------------------------
  144. local function setMainStruct(form, struct)
  145.   form.MainStruct = nil
  146.   form.MainStruct = struct
  147.   form.structChange()
  148. end
  149. --------------------------------------------------------------------------------
  150. function CEFormStructurePicker_CEListBoxStructuresSelectionChange(listBox, user)
  151.   if user and listBox.Selected[listBox.ItemIndex] then
  152.     local selected = selectedData(listBox)
  153.     local form = sp.focused
  154.     if isValidStructureFrm(form) and form.MainStruct ~= selected then
  155.       setMainStruct(form, selected)
  156.     end
  157.   end
  158. end
  159. --------------------------------------------------------------------------------
  160. function CEFormStructurePicker_CETimerStructurePickerTimer(thisTimer)
  161.   if sp.picker.Visible then
  162.     if updateGlobalStructureList() then
  163.       updateCEListBoxStructures()
  164.     end
  165.     local form = sp.focused
  166.     if isValidStructureFrm(form) and form.oldMainStruct ~= form.MainStruct then
  167.       selectMainStructure(form)
  168.       form.oldMainStruct = form.MainStruct
  169.     end
  170.   end
  171. end
  172. --------------------------------------------------------------------------------
  173. function CEFormStructurePicker_CEEditFilterChange(editBox)
  174.   updateCEListBoxStructures()
  175.   if isValidStructureFrm(sp.focused) then
  176.     selectMainStructure(sp.focused)
  177.   end
  178. end
  179. --------------------------------------------------------------------------------
  180. function CEFormStructurePicker_CEEditFilterKeyDown(sender, key)
  181.   if key == VK_DOWN or key == VK_UP then
  182.     sp.picker.CEListBoxStructures.setFocus()
  183.     doKeyPress(key)
  184.   end
  185.   return key
  186. end
  187. --------------------------------------------------------------------------------
  188. function CEFormStructurePicker_CEListBoxStructuresKeyPress(sender, key)
  189.   -- https://www.windmill.co.uk/ascii-control-codes.html
  190.   if string.byte(key) == 6 then -- Ctrl+F
  191.     sp.picker.CEEditFilter.setFocus()
  192.     return nil
  193.   end
  194.   return key
  195. end
  196. --------------------------------------------------------------------------------
  197. local function file_exists(file_path)
  198.   local f = io.open(file_path, "r")
  199.   return f ~= nil and io.close(f)
  200. end
  201. --------------------------------------------------------------------------------
  202. if sp_structureFrmAddNotification then
  203.   unregisterFormAddNotification(sp_structureFrmAddNotification)
  204. end
  205. sp_structureFrmAddNotification = registerFormAddNotification(function(form)
  206.   if isValidStructureFrm(form) then
  207.     local callback = form.registerCreateCallback(function(form)
  208.       form.OnActivate = function(form)
  209.         sp.focused = form
  210.         if sp.picker.Visible then
  211.           if isValidStructureFrm(form) then
  212.             selectMainStructure(form)
  213.           end
  214.         end
  215.       end
  216.       form.unregisterCreateCallback(callback)
  217.       local ownermenu = form.Structures1
  218.       local mi = createMenuItem(ownermenu)
  219.       ownermenu.insert(2, mi)
  220.       mi.Caption = "Structure picker"
  221.       mi.ImageIndex = 15
  222.       mi.Shortcut = "Shift+D"
  223.       mi.OnClick = function()
  224.         updateCEListBoxStructures()
  225.         sp.picker.Left = form.Left + form.Width
  226.         sp.picker.Top = form.Top
  227.         sp.picker.show()
  228.       end
  229.     end)
  230.   end
  231. end)
  232. --------------------------------------------------------------------------------
  233. local pathsep = getOperatingSystem() and [[\]] or [[/]]
  234. local forms_path = getAutoRunPath()..'forms'..pathsep
  235. local file_path = forms_path .. 'StructurePicker.FRM'
  236. local CEFormWindowSwitcher = nil
  237. if file_exists(file_path) then
  238.   CEFormWindowSwitcher = createFormFromFile(file_path)
  239.   sp.picker = CEFormWindowSwitcher
  240.   sp.picker.CEEditFilter.Text = ''
  241.   sp.focused = nil
  242.   sp.globalStructureList = {}
  243. else
  244.   print(file_path .. " not found!")
  245. end
  246. --------------------------------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement