WoWInterface (
-   Lua/XML Help (
-   -   3d model viewer addon (

Yukka 02-27-20 07:17 AM

3d model viewer addon
EDIT: The addon is available here:

Hello everyone, I'm new and I need your help to make my first addon because I'm a noob :D

I would like to make an addon that shows the 3d model of the selected target (Players, NPCs, creatures, etc).

I need to make a button near the target portrait frame, it appears when I select a target and disapear when I unselect it. Then once I click the button there's the 3d model of the target that appears in the middle of the screen with no background and I can rotate it and make zooms with the mouse middle button. Then to close the view on the target 3d model I just need to press the portrait button again.

Would you please share with me some of your knowledge and feed me with basic code so I can realize this project. Thanks a lot.

Also, is this possible to do this with a macro?

Fizzlemizz 02-27-20 11:24 AM

It's a bit rough but something like: (you can paste the code into the website to create/download as an addon). The Show/Hide button is on the target frame (and assumes you are using the default UI).

Lua Code:
  1. local function SetFacing(self, deltaX)
  2.     self.deltaX = self.deltaX + (deltaX * 0.01)
  3.     self:SetFacing(self.deltaX)
  4. end
  5. local function SetPosition(self, x, y, z)
  6.     self.x = self.x + (x * 0.1)
  7.     self.y = self.y + (y * 0.01)
  8.     self.z = self.z + (z * 0.01)
  9.     self:SetPosition(self.x, self.y, self.z)
  10. end
  12. local f = CreateFrame("Button", nil, TargetFrame, "UIPanelButtonTemplate")
  13. f:SetSize(50, 20)
  14. f:SetPoint("BOTTOMLEFT", TargetFrameNameBackground, "TOPLEFT")
  15. f:SetText("Show")
  16. f:SetScript("OnClick", function(self, button)
  17.     local Shown = not self.Model:IsShown()
  18.     self.Model:SetShown(Shown)
  19.     self:SetText(Shown and "Hide" or "Show")
  20. end)
  22. f.Model = CreateFrame("PlayerModel", nil, UIParent)
  23. f.Model:Hide()
  24. f.Model:SetSize(200, 200)
  25. f.Model:SetPoint("CENTER", 200, 80)
  26. f.Model:EnableMouse(true)
  27. f.Model.deltaX = 0
  28. f.Model.x, f.Model.y, f.Model.z = 0, 0, 0
  29. f.Model:SetMovable(true)
  30. f.Model:SetResizable(true)
  31. f.Model:RegisterForDrag("LeftButton")
  32. f.Model.Texture = f.Model:CreateTexture()
  33. f.Model.Texture:Hide()
  34. f.Model.Texture:SetAllPoints()
  35. f.Model.Texture:SetTexture("Interface/BUTTONS/WHITE8X8")
  36. f.Model.Texture:SetVertexColor(0.2, 0.4, 0.7, 0.2)
  38. f.Model:SetScript("OnDragStart", function(self, ...)
  39.     if not self.UnLock then return end
  40.     if IsAltKeyDown() then
  41.         self:StartSizing("BOTTOMRIGHT")
  42.     else
  43.         self:StartMoving()
  44.     end
  45. end)
  46. f.Model:SetScript("OnDragStop", function(self)
  47.      self:StopMovingOrSizing()
  48.      self.ButtonDown = nil
  49. end)
  51. f.Model:SetScript("OnEvent", function(self, event, ...)
  52.     if event == "PLAYER_TARGET_CHANGED" then
  53.         self.Reset:GetScript("OnClick")(self.Reset)
  54.     else
  55.         self:SetUnit("target")
  56.     end
  57. end)
  58. f.Model:RegisterEvent("PLAYER_TARGET_CHANGED")
  59. f.Model:RegisterUnitEvent("UNIT_MODEL_CHANGED", target)
  60. f.Model:SetScript("OnMouseDown", function(self, button)
  61.     if self.UnLock then return end
  62.     self.ButtonDown = button
  63. end)
  64. f.Model:SetScript("OnMouseUp", function(self, button)
  65.     self.ButtonDown = nil
  66. end)
  67. f.Model:SetScript("OnMouseWheel", function(self, delta)
  68.     SetPosition(self, delta, 0, 0)
  70. end)
  71. f.Model:SetScript("OnUpdate", function(self, elapsed)
  72.     if self.ButtonDown then
  73.         if self.ButtonDown == "LeftButton" then
  74.             if self.UnLock then return end
  75.             local deltaX, deltaY = GetScaledCursorDelta()
  76.             SetFacing(self, deltaX)
  77.         elseif self.ButtonDown == "RightButton" then
  78.             local x, y, z = GetScaledCursorDelta()
  79.             SetPosition(self, 0, x, y)
  80.         end
  81.     end
  82. end)
  83. f.Model.Reset = CreateFrame("Button", nil, f.Model, "UIPanelButtonTemplate")
  84. f.Model.Reset:SetSize(60, 20)
  85. f.Model.Reset:SetPoint("BOTTOMLEFT", f.Model, "TOPLEFT")
  86. f.Model.Reset:SetText("Reset")
  87. f.Model.Reset:SetScript("OnClick", function(self)
  88.     local parent = self:GetParent()
  89.     parent.zoom  = 0
  90.     parent.deltaX = 0
  91.     parent.x, parent.y, parent.z = 0, 0, 0
  92.     SetFacing(parent, 0)
  93.     SetPosition(parent, 0, 0, 0)
  94.     parent:SetUnit("target")
  95. end)
  97. f.Model.Lock = CreateFrame("Button", nil, f.Model, "UIPanelButtonTemplate")
  98. f.Model.Lock:SetSize(60, 20)
  99. f.Model.Lock:SetPoint("BOTTOM", f.Model, "TOP")
  100. f.Model.Lock:SetText("Unlock")
  101. f.Model.Lock:SetScript("OnClick", function(self)
  102.     self:GetParent().UnLock = not self:GetParent().UnLock
  103.     self:SetText(self:GetParent().UnLock and "Lock" or "Unlock")
  104. end)
  106. f.Model.Close = CreateFrame("Button", nil, f.Model)
  107. f.Model.Close:SetSize(22, 22)
  108. f.Model.Close:SetPoint("BOTTOMRIGHT", f.Model, "TOPRIGHT")
  109. f.Model.Close:SetNormalTexture("Interface/Buttons/UI-Panel-MinimizeButton-Up")
  110. f.Model.Close:SetPushedTexture("Interface/Buttons/UI-Panel-MinimizeButton-Down")
  111. f.Model.Close:SetHighlightTexture("Interface/Buttons/UI-Panel-MinimizeButton-Highlight", "ADD")
  112. f.Model.Close:SetScript("OnClick", function(self)
  114.     f:GetScript("OnClick")(f) -- Call the target frame button's click handler
  115. end)
  117. f.Model.Background = CreateFrame("Button", nil, f.Model, "UIPanelButtonTemplate")
  118. f.Model.Background:SetSize(40, 20)
  119. f.Model.Background:SetPoint("RIGHT", f.Model.Close, "LEFT", -5, 0)
  120. f.Model.Background:SetText("Bg")
  121. f.Model.Background:SetScript("OnClick", function(self)
  122.     local parent = self:GetParent()
  123.     parent.Texture:SetShown(not parent.Texture:IsShown())
  124. end)
The zoom/facing numbers can be adjusted to suit your needs. Zooming/Rotating only work if the mouse starts on/over the 3D model (which is positioned to the right of center to try and avoid some overlaying of in-game character(s) (player etc.)).

Yukka 02-27-20 09:08 PM

Impressive, I'm amazed to see how short the code is. I tested it and it works amazing but I believe it would be even better if you learn me how to do this:

- Make the right clic can go trough the 3d model to be able to do actions like moving the camera while running and select other targets.
- Use the mouse middle click on the 3d model to move it where I want in the 3d view frame.

Then after that I think the addon will be finished :)

Fizzlemizz 02-28-20 12:54 PM

You can move the frame out of the way but arbitrarily clicking something behind it won't work.

If you replace SetPortraitZoom with SetPosition you can move/zoom the model inside the frame. You can select/view the methods available for the various UI widgets here.

Depending on what you are actually trying to achieve there probably needs to be far more work beyond this rough outline than I have time for.

Original post contains all the updated code.

Yukka 02-28-20 02:08 PM

Thank you. I just tried to add a button at the bottom left corner of the model frame to rezize as wish but it didn't worked... so I wrote few lines to add 2 buttons that change the size of the model frame and the model, the buttons showed but they did nothing. At least the positive thing for now is that I understand a bit when I read the code and learned how to modify few things in the script lol.

I fear to ask too much but I would like to add more options to this addon to make it even better if you accept:

- A button ("BG") that toggle between no background and a 50% transparency black background (Default is with the background).
- 2 buttons ("+" and "-") that resize the model frame (and the 3d model at the same time). Each click on + make it bigger and bigger, and - do the opposite.
- Once the model frame is locked, mouse middle click can be used to rotate the 3d model in all directions (not only left and right that mouse left click already does) to get views from above, bellow, ...

That's all but I guess that's a lot ^^

Fizzlemizz 02-28-20 03:07 PM

The first two are pretty simple, the last one not so much as it's beyond the scope of the PlayerModel widget and into things I've not played with yet.

Updated the code in the original post and added a "Bg" button and, when unlocked, the frame can be re-sized by holding down the alt-key and dragging the bottom right corner.

You can extract the code for the default UI and might get some useful information from their Wardrobe and Collections addons.

Yukka 02-28-20 03:50 PM

That's incredible! I can't thank you enough for this wonderful addon, it will help to have a closer look on the living beings of Azeroth :)

I came here asking for some basic code to start my addon then you litterally wrote everything, I don't mind that because you learned me new things. So it's yours, I just take that sweet code to play with it. But... I believe such a good addon must live longer and be shared with the rest of the community, can you please share it here and on Curseforge? I think you'll be the best person able to keep it up to date since you are an LUA professional.

Fizzlemizz 02-28-20 04:30 PM

Certainly no professional :).

If you install a debugger it should be reasonably straight forward to keep the code in order should anything break (I don't think there's anything earth shattering in what's there). Handy to have for any addon development.

work together.

Yukka 02-28-20 04:49 PM

Okay, I'll install those addons too.

Can I share it on Curseforge? I would like to credit you in the addon description if you accept.

Fizzlemizz 02-28-20 05:10 PM

You can do with it as you please, I have no need for credit. Just happy to help you get started.

All times are GMT -6. The time now is 03:28 AM.

vBulletin © 2021, Jelsoft Enterprises Ltd
© 2004 - 2020 MMOUI