Thread Tools Display Modes
05-27-16, 03:32 PM   #81
sirann
A Flamescale Wyrmkin
Join Date: Mar 2007
Posts: 142
Originally Posted by semlar View Post
I agree with zork, it would make a lot more sense to generate your animation texture in the shape that you want than trying to fix it in-game.

It is possible to do what you want using rotations, but I don't think I can explain how to combine matrix transformations well enough to someone who doesn't already know something about matrices to make sense of it.

Essentially you would have to apply your translation, which is where you move the texture to a particular location (one of the 60 frames of your animation), then apply a rotation matrix centered around that point.

This page explains how to do the math involved (2 dimensional rotation), but really without some background on this subject already you're going to have a hard time applying it to what you're trying to do.

I would only do it this way if you really have to have your textures look like this and you can't generate them in the shape that you want.
When your addon requires knowledge of what I believe would be fourier transformations (right, rotating a square to make a circular pattern?) it can probably be done more efficiently :P
  Reply With Quote
05-27-16, 03:43 PM   #82
syncrow
A Flamescale Wyrmkin
 
syncrow's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 149
There is an issues with zork's method:
  • pre-shaping such textures works for fixed bar sizes.
  • Resizing the bar (different unit frame sizes with different healthbars....will crop the animation terribly
  • The animation will also be compressed during statusbar transition

I tested out something like this:



...to fix the problem with multiple sizes. Using that method, results in fixated widths in relation to its height to guarantee pixelperfekt 45° cropping. (failure)

Thx for that link btw, i will check that!
__________________

Last edited by syncrow : 05-27-16 at 03:46 PM.
  Reply With Quote
05-27-16, 10:17 PM   #83
lightspark
A Rage Talon Dragon Guard
 
lightspark's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2012
Posts: 341
Originally Posted by syncrow View Post
The animation will also be compressed during statusbar transition
You have to create an invisible statusbar, that'll be used to do the maths, and add a texture that'll be your fake statusbar, and then crop it via SetTexCoord, when you set invisible statusbar values.

Sry, wrong link there, just woke up T_T
__________________

Last edited by lightspark : 05-27-16 at 10:29 PM.
  Reply With Quote
05-28-16, 01:00 AM   #84
syncrow
A Flamescale Wyrmkin
 
syncrow's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2014
Posts: 149
Originally Posted by lightspark View Post
You have to create an invisible statusbar, that'll be used to do the maths, and add a texture that'll be your fake statusbar, and then crop it via SetTexCoord, when you set invisible statusbar values.
That doesn't fix the whole issue =/
__________________
  Reply With Quote
07-09-16, 08:29 AM   #85
Infus
A Deviate Faerie Dragon
Join Date: Jul 2016
Posts: 13
Originally Posted by semlar View Post
I wanted to post here because I came up with a technique based on the one outlined in this topic which can be applied to any source texture, rather than relying on semi-circles.
And somehow this broke in Legion. I'm not at the bottom of all the problems, but I have something that works on Legion.

Code:
-- Usage:
-- spinner = CreateSpinner(parent)
-- spinner:SetTexture('texturePath')
-- spinner:SetBlendMode('blendMode')
-- spinner:SetVertexColor(r, g, b)
-- spinner:SetClockwise(boolean) -- true to fill clockwise, false to fill counterclockwise
-- spinner:SetReverse(boolean) -- true to empty the bar instead of filling it
-- spinner:SetValue(percent) -- value between 0 and 1 to fill the bar to

-- Some math stuff
local cos, sin, pi2, halfpi = math.cos, math.sin, math.rad(360), math.rad(90)
local function Transform(tx, x, y, angle, aspect) -- Translates texture to x, y and rotates about its center
    local c, s = cos(angle), sin(angle)
    local y, oy = y / aspect, 0.5 / aspect
    local ULx, ULy = 0.5 + (x - 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x - 0.5) * s) * aspect
    local LLx, LLy = 0.5 + (x - 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x - 0.5) * s) * aspect
    local URx, URy = 0.5 + (x + 0.5) * c - (y - oy) * s, (oy + (y - oy) * c + (x + 0.5) * s) * aspect
    local LRx, LRy = 0.5 + (x + 0.5) * c - (y + oy) * s, (oy + (y + oy) * c + (x + 0.5) * s) * aspect
    tx:SetTexCoord(ULx, ULy, LLx, LLy, URx, URy, LRx, LRy)
end

-- Permanently pause our rotation animation after it starts playing
local function OnPlayUpdate(self)
    self:SetScript('OnUpdate', nil)
    self:Pause()
end

local function OnPlay(self)
    self:SetScript('OnUpdate', OnPlayUpdate)
end

local function SetValue(self, value)
    -- Correct invalid ranges, preferably just don't feed it invalid numbers
    if value > 1 then value = 1
    elseif value < 0 then value = 0 end

    -- Reverse our normal behavior
    if self._reverse then
        value = 1 - value
    end

    -- Determine which quadrant we're in
    local q, quadrant = self._clockwise and (1 - value) or value -- 4 - floor(value / 0.25)
    if q >= 0.75 then
        quadrant = 1
    elseif q >= 0.5 then
        quadrant = 2
    elseif q >= 0.25 then
        quadrant = 3
    else
        quadrant = 4
    end

    if self._quadrant ~= quadrant then
        self._quadrant = quadrant
        -- Show/hide necessary textures if we need to
        if self._clockwise then
            for i = 1, 4 do
                self._textures[i]:SetShown(i < quadrant)
            end
        else
            for i = 1, 4 do
                self._textures[i]:SetShown(i > quadrant)
            end
        end
        -- Move scrollframe/wedge to the proper quadrant
        self._scrollframe:Hide();
        self._scrollframe:SetAllPoints(self._textures[quadrant])
        self._scrollframe:Show();
    end

    -- Rotate the things
    local rads = value * pi2
    if not self._clockwise then rads = -rads + halfpi end
    Transform(self._wedge, -0.5, -0.5, rads, self._aspect)
    self._rotation:SetDuration(0.000001)
    self._rotation:SetEndDelay(2147483647)
    self._rotation:SetOrigin('BOTTOMRIGHT', 0, 0)
    self._rotation:SetRadians(-rads);
    self._group:Play();
end

local function SetClockwise(self, clockwise)
    self._clockwise = clockwise
end

local function SetReverse(self, reverse)
    self._reverse = reverse
end

local function OnSizeChanged(self, width, height)
    self._wedge:SetSize(width, height) -- it's important to keep this texture sized correctly
    self._aspect = width / height -- required to calculate the texture coordinates
end

-- Creates a function that calls a method on all textures at once
local function CreateTextureFunction(func, self, ...)
    return function(self, ...)
        for i = 1, 4 do
            local tx = self._textures[i]
            tx[func](tx, ...)
        end
        self._wedge[func](self._wedge, ...)
    end
end

-- Pass calls to these functions on our frame to its textures
local TextureFunctions = {
    SetTexture = CreateTextureFunction('SetTexture'),
    SetBlendMode = CreateTextureFunction('SetBlendMode'),
    SetVertexColor = CreateTextureFunction('SetVertexColor'),
}

local function CreateSpinner(parent)
    local spinner = CreateFrame('Frame', nil, parent)

    -- ScrollFrame clips the actively animating portion of the spinner
    local scrollframe = CreateFrame('ScrollFrame', nil, spinner)
    scrollframe:SetPoint('BOTTOMLEFT', spinner, 'CENTER')
    scrollframe:SetPoint('TOPRIGHT')
    spinner._scrollframe = scrollframe

    local scrollchild = CreateFrame('frame', nil, scrollframe)
    scrollframe:SetScrollChild(scrollchild)
    scrollchild:SetAllPoints(scrollframe)

    -- Wedge thing
    local wedge = scrollchild:CreateTexture()
    wedge:SetPoint('BOTTOMRIGHT', spinner, 'CENTER')
    spinner._wedge = wedge

    -- Top Right
    local trTexture = spinner:CreateTexture()
    trTexture:SetPoint('BOTTOMLEFT', spinner, 'CENTER')
    trTexture:SetPoint('TOPRIGHT')
    trTexture:SetTexCoord(0.5, 1, 0, 0.5)

    -- Bottom Right
    local brTexture = spinner:CreateTexture()
    brTexture:SetPoint('TOPLEFT', spinner, 'CENTER')
    brTexture:SetPoint('BOTTOMRIGHT')
    brTexture:SetTexCoord(0.5, 1, 0.5, 1)

    -- Bottom Left
    local blTexture = spinner:CreateTexture()
    blTexture:SetPoint('TOPRIGHT', spinner, 'CENTER')
    blTexture:SetPoint('BOTTOMLEFT')
    blTexture:SetTexCoord(0, 0.5, 0.5, 1)

    -- Top Left
    local tlTexture = spinner:CreateTexture()
    tlTexture:SetPoint('BOTTOMRIGHT', spinner, 'CENTER')
    tlTexture:SetPoint('TOPLEFT')
    tlTexture:SetTexCoord(0, 0.5, 0, 0.5)

    -- /4|1\ -- Clockwise texture arrangement
    -- \3|2/ --

    spinner._textures = {trTexture, brTexture, blTexture, tlTexture}
    spinner._quadrant = nil -- Current active quadrant
    spinner._clockwise = true -- fill clockwise
    spinner._reverse = false -- Treat the provided value as its inverse, eg. 75% will display as 25%
    spinner._aspect = 1 -- aspect ratio, width / height of spinner frame
    spinner:HookScript('OnSizeChanged', OnSizeChanged)

    for method, func in pairs(TextureFunctions) do
        spinner[method] = func
    end

    spinner.SetClockwise = SetClockwise
    spinner.SetReverse = SetReverse
    spinner.SetValue = SetValue

    local group = wedge:CreateAnimationGroup()
    group:SetScript('OnFinished', function() group:Play() end);
    local rotation = group:CreateAnimation('Rotation')
    spinner._rotation = rotation
    spinner._group = group;
    return spinner
end

----------
-- Demo
----------

local spinner1 = CreateSpinner(UIParent)
spinner1:SetPoint('BOTTOMRIGHT', UIParent, 'CENTER', -2, 2)
spinner1:SetSize(64, 64)
spinner1:SetTexture('interface/icons/inv_mushroom_11')

spinner1:SetClockwise(false)
spinner1:SetReverse(false)

local spinner2 = CreateSpinner(UIParent)
spinner2:SetPoint('BOTTOMLEFT', UIParent, 'CENTER', 2, 2)
spinner2:SetSize(64, 64)
spinner2:SetTexture('interface/icons/inv_mushroom_11')

spinner2:SetClockwise(true)
spinner2:SetReverse(false)

local spinner3 = CreateSpinner(UIParent)
spinner3:SetPoint('TOPRIGHT', UIParent, 'CENTER', -2, -2)
spinner3:SetSize(64, 64)
spinner3:SetTexture('interface/icons/inv_mushroom_11')

spinner3:SetClockwise(true)
spinner3:SetReverse(true)

local spinner4 = CreateSpinner(UIParent)
spinner4:SetPoint('TOPLEFT', UIParent, 'CENTER', 2, -2)
spinner4:SetSize(64, 64)
spinner4:SetTexture('interface/icons/inv_mushroom_11')

spinner4:SetClockwise(false)
spinner4:SetReverse(true)

local f = CreateFrame('frame')
local timespent = 0
f:SetScript('OnUpdate', function(self, elapsed)
    timespent = timespent + elapsed
    if timespent >= 3 then
        timespent = 0
    end

    local value = timespent / 3
    spinner1:SetValue(value)
    spinner2:SetValue(value)
    spinner3:SetValue(value)
    spinner4:SetValue(value)
end)
And the diff:
Code:
diff --git a/test4.lua b/test4.lua
index 5dbe0bc..8a0ccfe 100644
--- a/test4.lua
+++ b/test4.lua
@@ -64,14 +64,20 @@ local function SetValue(self, value)
             end
         end
         -- Move scrollframe/wedge to the proper quadrant
+        self._scrollframe:Hide();
         self._scrollframe:SetAllPoints(self._textures[quadrant])
+        self._scrollframe:Show();
     end

     -- Rotate the things
     local rads = value * pi2
     if not self._clockwise then rads = -rads + halfpi end
     Transform(self._wedge, -0.5, -0.5, rads, self._aspect)
-    self._rotation:SetRadians(-rads)
+    self._rotation:SetDuration(0.000001)
+    self._rotation:SetEndDelay(2147483647)
+    self._rotation:SetOrigin('BOTTOMRIGHT', 0, 0)
+    self._rotation:SetRadians(-rads);
+    self._group:Play();
 end

 local function SetClockwise(self, clockwise)
@@ -166,14 +172,10 @@ local function CreateSpinner(parent)
     spinner.SetValue = SetValue

     local group = wedge:CreateAnimationGroup()
+    group:SetScript('OnFinished', function() group:Play() end);
     local rotation = group:CreateAnimation('Rotation')
     spinner._rotation = rotation
-    rotation:SetDuration(0)
-    rotation:SetEndDelay(1)
-    rotation:SetOrigin('BOTTOMRIGHT', 0, 0)
-    group:SetScript('OnPlay', OnPlay)
-    group:Play()
-
+    spinner._group = group;
     return spinner
 end
  Reply With Quote
07-09-16, 09:57 AM   #86
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
SetRadians is broken in Legion. I've reported it but....
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
07-10-16, 08:51 AM   #87
Infus
A Deviate Faerie Dragon
Join Date: Jul 2016
Posts: 13
Originally Posted by Fizzlemizz View Post
SetRadians is broken in Legion. I've reported it but....
Not in my experience. The code I posted uses SetRadians and works.
  Reply With Quote
01-28-23, 04:39 PM   #88
EvilMaddness
An Aku'mai Servant
 
EvilMaddness's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2015
Posts: 33
The problem I'm ending up with

I'm using the two textures that you mentioned with one of the texture being transparent to make it seem like it's blending in with the other texture. The problem I'm facing with this is that I'm trying to have the first texrture start at 0.14 going clockwise while texture 2 ends at 0.14 going clockwise. But texture 2 will start at 12 0 clock giving it only a little time to fill up so before I even hit 100% it already filled up the texture.

I tried using different values ( percentages ) for power but no matter what I seem to change I end up getting the same result or make it worse. It's the texture I'm using because the way it lines up for it to work the way I want it would have to start and end at 0.14.

I tried even doing 50 / 50 on the textures with percentage and that didn't work either.
I'm not sure how to get around this one guys.
__________________
The Maddness Within lua
  Reply With Quote
01-28-23, 06:55 PM   #89
semlar
A Pyroguard Emberseer
 
semlar's Avatar
AddOn Author - Click to view addons
Join Date: Sep 2007
Posts: 1,060
Originally Posted by EvilMaddness View Post
I'm using the two textures that you mentioned with one of the texture being transparent to make it seem like it's blending in with the other texture. The problem I'm facing with this is that I'm trying to have the first texrture start at 0.14 going clockwise while texture 2 ends at 0.14 going clockwise. But texture 2 will start at 12 0 clock giving it only a little time to fill up so before I even hit 100% it already filled up the texture.

I tried using different values ( percentages ) for power but no matter what I seem to change I end up getting the same result or make it worse. It's the texture I'm using because the way it lines up for it to work the way I want it would have to start and end at 0.14.

I tried even doing 50 / 50 on the textures with percentage and that didn't work either.
I'm not sure how to get around this one guys.
You need 1 (one) texture file, and 4 in-game texture frames all set to that same image to create a spinner. The texture image file should be exactly what you want your texture to look like when it's 100% full; if you want a semi-circle, just leave part of it transparent.

This is the image that I used in one of my earlier posts to get this effect in-game:


If you post the code that you tried and the image texture that you used we can get a better idea of what the problem is and how to fix it.
  Reply With Quote
01-28-23, 07:15 PM   #90
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
This might have changed but I think EvilMaddness is wanting to have a full circle ring but have the start and finish point offset say -40 degrees (or whatever) from top.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
01-29-23, 01:44 AM   #91
EvilMaddness
An Aku'mai Servant
 
EvilMaddness's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2015
Posts: 33
Hey Fizz!

Yes I'm still working on it. Right now I tried changing the textures around in GIMP.
The first texture is the bottom half with a arc set starting at 0.14 going clockwise being even on the left side going into quadrant 3.

The second texture starts on the upper half continuing until it gets to 0.14 or just right before it.
Starting in quadrant 3 and ending at quadrant 1.

I figured this way I'm not fighting with the 12 o clock position like last time giving myself more room for the values to meet and fill more evenly.

Last time I had the upper texture only in quadrant4 giving it little time starting at 12 o clock then filling up clockwise to 0.14 so it was filling up the texture way to quick no matter what values I used.

Hopefully the new textures I'm using now will work but I haven't tried it out yet. I'm going to try setting the bottom half to 0.14 going up to 50% then have the other texture start at 50% going up to 100%. If it works I'll do the same for target, update the flash frame and others if in vehicle or other stuff in game to show or hide, then it should be good to go for a new add-on as a full functioning unit frame spinner for player and target for now. I didn't work on the focus frames yet or vehicle that will need to be next after the other spinners are finished.

Update: even with the new textures in place it still will show the texture in quadrant 1 before filling up before quadrant 3. This is why a start and end set angle is needed for this code but I don't have the experience for that advanced kinda coding.
Even if I do set the texture to be in quadrant 1 the vaule is too little for it to fill correctly with the other texture evenly has it's only filling from 12 o clock to 0.14
__________________
The Maddness Within lua

Last edited by EvilMaddness : 01-29-23 at 03:25 AM.
  Reply With Quote
01-29-23, 09:38 AM   #92
Fizzlemizz
I did that?
 
Fizzlemizz's Avatar
Premium Member
AddOn Author - Click to view addons
Join Date: Dec 2011
Posts: 1,857
Link a zip with the code and any custom image files you are using plus, maybe a couple of mock images of the look you are trying to achieve now.

If it's doable, maybe someone with the smarts can figure it out.
__________________
Fizzlemizz
Maintainer of Discord Unit Frames and Discord Art.
Author of FauxMazzle, FauxMazzleHUD and Move Pad Plus.
  Reply With Quote
02-13-23, 08:56 PM   #93
EvilMaddness
An Aku'mai Servant
 
EvilMaddness's Avatar
AddOn Author - Click to view addons
Join Date: Aug 2015
Posts: 33
Still trying

No progress yet on updating the code for a start and end angles to it. I think I've been going a good few months at it now.

I tried also using the four textures but it didn't work out for me that well. I guess it might be the angle I'm trying to get.
In Weakauras it starts at 42 and ends at 42 for my power texture which is really the only texture I'm trying to set the angle different on along with the power texture for target which I recall is a 46 to 46 angle.

I'm hoping that this code can be updated some day so we can finally just add in what angle we want for the texture to start and end at that will take in the value for the progress where ever the angle is at on the new spinner that is created.

And I understand. If weakauras already has the code to do that why not just use it?

I wanted to share my unit spinners for target and player as a stand alone add-on with the start and end angles already in place so no changes would be made.

Plus I don't think it's fare to have weakauras as an only option to have a start and end angle on the spinners. If I was to use the code I would have to add in some sort of licence to use it.

Anyways I hope someone like Zork, Semlar or Fizz might be able to make a new code for this to happen if they have any free time for this. I know it's not an easy task and would take a lot of time.
I mean I've been trying for a few months and still didn't come close yet.

But I havn't gave up on you guys. Sometimes you need good friends around to achieve this.
__________________
The Maddness Within lua
  Reply With Quote

WoWInterface » Developer Discussions » General Authoring Discussion » The ring theory part two

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off