Quantcast

Split compilation into two phases: "quick" and "full".

Johnny C. Lam [10-18-12 - 01:05]
Split compilation into two phases: "quick" and "full".

The "quick" phase only compiles the parts of the script that may change as
a result of things that trigger recompilation.  This includes changing
SpellInfo(), AddCheckBox() and AddListItem().

The "full" phase compiles the entire script.  This has been modified to
also compile AddIcon() groups that may be disabled and storing their nodes
in Ovale.masterNodes.

At run-time, when a "quick" compile is requested, Ovale executes the quick
compile and then updates the status of each master node (corresponding to
an icon) as to whether the node is enabled or not.

OvaleFrame only shows icons for enabled master nodes.

git-svn-id: svn://svn.curseforge.net/wow/ovale/mainline/trunk@604 d5049fe3-3747-40f7-a4b5-f36d6801af5f
Filename
Ovale.lua
OvaleCompile.lua
OvaleData.lua
OvaleFrame.lua
diff --git a/Ovale.lua b/Ovale.lua
index 047fcd0..1b91834 100644
--- a/Ovale.lua
+++ b/Ovale.lua
@@ -34,6 +34,7 @@ Ovale.checkBoxes = {}
 Ovale.dropDowns = {}
 --master nodes of the current script (one node for each icon)
 Ovale.masterNodes = nil
+Ovale.masterNodesEnabled = {}
 --set it if there was a bug, traces will be enabled on next frame
 Ovale.bug = false
 Ovale.traced = false
@@ -49,6 +50,7 @@ Ovale.refreshNeeded = {}
 Ovale.compileOnItems = false
 Ovale.compileOnStances = false
 Ovale.combatStartTime = nil
+--needCompile is true, false, or "quick"
 Ovale.needCompile = false
 Ovale.listes = {}
 --</public-static-properties>
@@ -79,15 +81,21 @@ function Ovale:DebugListAura(target, filter)
 end

 function Ovale:CompileAll()
-	if OvaleOptions:GetProfile().code then
-		self.masterNodes = OvaleCompile:Compile(OvaleOptions:GetProfile().code)
+	local code = OvaleOptions:GetProfile().code
+	if code then
+		if self.needCompile == "quick" then
+			code = OvaleCompile:CompileDeclarations(code)
+			code = OvaleCompile:CompileInputs(code)
+		elseif self.needCompile then
+			self.masterNodes = OvaleCompile:Compile(code)
+		end
+		OvaleCompile:UpdateNodesEnabled(self.masterNodes, self.masterNodesEnabled)
 		self.refreshNeeded.player = true
-		self:UpdateFrame()
 		self.needCompile = false
+		self:UpdateFrame()
 	end
 end

-
 function Ovale:FirstInit()
 	self.firstInit = true

@@ -138,7 +146,7 @@ end

 function Ovale:UNIT_INVENTORY_CHANGED()
 	if self.compileOnItems then
-		self.needCompile = true
+		self.needCompile = self.needCompile or "quick"
 	else
 		self.refreshNeeded.player = true
 	end
@@ -146,7 +154,7 @@ end

 function Ovale:Ovale_UpdateShapeshiftForm()
 	if Ovale.compileOnStances then
-		Ovale.needCompile = true
+		Ovale.needCompile = self.needCompile or "quick"
 	else
 		Ovale.refreshNeeded.player = true
 	end
@@ -163,13 +171,13 @@ end
 --Called when a glyph has been added
 --The script needs to be compiled
 function Ovale:GLYPH_ADDED(event)
-	self.needCompile = true
+	self.needCompile = self.needCompile or "quick"
 end

 --Called when a glyph has been updated
 --The script needs to be compiled
 function Ovale:GLYPH_UPDATED(event)
-	self.needCompile = true
+	self.needCompile = self.needCompile or "quick"
 end

 function Ovale:CHAT_MSG_ADDON(event, prefix, msg, type, author)
@@ -230,14 +238,14 @@ end
 local function OnCheckBoxValueChanged(widget)
 	OvaleOptions:GetProfile().check[widget.userdata.k] = widget:GetValue()
 	if Ovale.casesACocher[widget.userdata.k].compile then
-		Ovale.needCompile = true
+		Ovale.needCompile = Ovale.needCompile or "quick"
 	end
 end

 local function OnDropDownValueChanged(widget)
 	OvaleOptions:GetProfile().list[widget.userdata.k] = widget.value
 	if Ovale.listes[widget.userdata.k].compile then
-		Ovale.needCompile = true
+		Ovale.needCompile = Ovale.needCompile or "quick"
 	end
 end

diff --git a/OvaleCompile.lua b/OvaleCompile.lua
index 96048ce..5aaff7c 100644
--- a/OvaleCompile.lua
+++ b/OvaleCompile.lua
@@ -497,9 +497,6 @@ local function ParseAddIcon(params, text, secure)
 	masterNode = node[tonumber(masterNode)]
 	masterNode.params = ParseParameters(params)
 	masterNode.secure = secure
-	if not TestConditions(masterNode.params) then
-		return nil
-	end
 	return masterNode
 end

@@ -538,18 +535,7 @@ function OvaleCompile:CompileInputs(text)
 	return text
 end

-function OvaleCompile:Compile(text)
-	Ovale.compileOnItems = false
-	Ovale.compileOnStances = false
-	Ovale.bug = false
-	node = {}
-	defines = {}
-	unknownSpellNodes = {}
-
-	-- Suppression des commentaires
-	text = strgsub(text, "#.-\n","")
-	text = strgsub(text, "#.*$","")
-
+function OvaleCompile:CompileDeclarations(text)
 	-- Define(CONSTANTE valeur)
 	text = strgsub(text, "Define%s*%(%s*([%w_]+)%s+(%w+)%s*%)", ParseDefine)

@@ -573,14 +559,40 @@ function OvaleCompile:Compile(text)
 	text = strgsub(text, "SpellInfo%s*%((.-)%)", ParseSpellInfo)
 	text = strgsub(text, "ScoreSpells%s*%((.-)%)", ParseScoreSpells)
 	text = strgsub(text, "SpellList%s*%(%s*([%w_]+)%s*(.-)%)", ParseSpellList)
-
+
 	-- On vire les espaces en trop
 	text = strgsub(text, "\n", " ")
 	text = strgsub(text, "%s+", " ")

+	return text
+end
+
+function OvaleCompile:UpdateNodesEnabled(masterNodes, enabledTbl)
+	if masterNodes then
+		for k, node in pairs(masterNodes) do
+			enabledTbl[k] = TestConditions(node.params)
+		end
+	end
+end
+
+function OvaleCompile:Compile(text)
+	Ovale.compileOnItems = false
+	Ovale.compileOnStances = false
+	Ovale.bug = false
+	node = {}
+	defines = {}
+	unknownSpellNodes = {}
+
+	-- Suppression des commentaires
+	text = strgsub(text, "#.-\n","")
+	text = strgsub(text, "#.*$","")
+
+	-- Compile non-function and non-icon declarations.
+	text = self:CompileDeclarations(text)
+
 	-- On compile les AddCheckBox et AddListItem
 	text = self:CompileInputs(text)
-
+
 	for p,t in strgmatch(text, "AddFunction%s+(%w+)%s*(%b{})") do
 		local newNode = ParseCommands(t)
 		if newNode then
diff --git a/OvaleData.lua b/OvaleData.lua
index 8bb62a1..ba3d0a8 100644
--- a/OvaleData.lua
+++ b/OvaleData.lua
@@ -284,7 +284,7 @@ end
 --The user learnt a new spell
 function OvaleData:SPELLS_CHANGED()
 	self:FillSpellList()
-	Ovale.needCompile = true
+	Ovale.needCompile = Ovale.needCompile or "quick"
 end

 function OvaleData:GetRootSpellList()
@@ -393,7 +393,7 @@ function OvaleData:RemplirListeTalents()
 			self.pointsTalent[talentId] = 0
 		end
 		self.listeTalentsRemplie = true
-		Ovale.needCompile = true
+		Ovale.needCompile = Ovale.needCompile or "quick"
 		talentId = talentId + 1
 	end
 end
diff --git a/OvaleFrame.lua b/OvaleFrame.lua
index c79ec20..196e808 100644
--- a/OvaleFrame.lua
+++ b/OvaleFrame.lua
@@ -116,24 +116,26 @@ do

 	local function GetScore(self, spellId)
 		for k,action in pairs(self.actions) do
-			if action.spellId == spellId then
-				if not action.waitStart then
-					-- print("sort "..spellId.." parfait")
-					return 1
-				else
-					local lag = OvaleState.maintenant - action.waitStart
-					if lag>5 then
-					-- 	print("sort "..spellId.." ignoré (>5s)")
-						return nil
-					elseif lag>1.5 then
-					-- 	print("sort "..spellId.." trop lent !")
-						return 0
-					elseif lag>0 then
-					-- 	print("sort "..spellId.." un peu lent "..lag)
-						return 1-lag/1.5
-					else
-					-- 	print("sort "..spellId.." juste bon")
+			if Ovale.masterNodesEnabled[k] then
+				if action.spellId == spellId then
+					if not action.waitStart then
+						-- print("sort "..spellId.." parfait")
 						return 1
+					else
+						local lag = OvaleState.maintenant - action.waitStart
+						if lag>5 then
+						-- 	print("sort "..spellId.." ignoré (>5s)")
+							return nil
+						elseif lag>1.5 then
+						-- 	print("sort "..spellId.." trop lent !")
+							return 0
+						elseif lag>0 then
+						-- 	print("sort "..spellId.." un peu lent "..lag)
+							return 1-lag/1.5
+						else
+						-- 	print("sort "..spellId.." juste bon")
+							return 1
+						end
 					end
 				end
 			end
@@ -163,114 +165,116 @@ do

 		OvaleState:StartNewFrame()
 		for k,node in pairs(Ovale.masterNodes) do
-			local target = node.params.target or "target"
-			OvaleCondition.defaultTarget = target
-
-			if forceRefresh or Ovale.refreshNeeded[target] or Ovale.refreshNeeded["player"] or Ovale.refreshNeeded["pet"] then
-				if Ovale.trace then
-					Ovale:Print("****Master Node "..k)
-				end
-				OvaleBestAction:StartNewAction()
-				local start, ending, priorite, element = OvaleBestAction:Compute(node)
-				if start then
-					Ovale:Log("Compute start = "..start)
-				end
-				local action = self.actions[k]
-				local icons
-				if action.secure then
-					icons = action.secureIcons
-				else
-					icons = action.icons
-				end
-				if element and element.type == "value" then
-					local actionTexture
-					if node.params.texture then
-						actionTexture = GetSpellTexture(node.params.texture)
-					end
-					local value
-					if element.value and element.origin and element.rate then
-						value = element.value + (OvaleState.maintenant - element.origin) * element.rate
-					end
-					icons[1]:SetValue(value, actionTexture)
-					if #icons > 1 then
-						icons[2]:Update(element, nil)
-					end
-				else
-					local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-							actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget, noRed = OvaleBestAction:GetActionInfo(element)
-					if noRed then
-						start = actionCooldownStart + actionCooldownDuration
-						if start < OvaleState.currentTime then
-							start = OvaleState.currentTime
-						end
+			if Ovale.masterNodesEnabled[k] then
+				local target = node.params.target or "target"
+				OvaleCondition.defaultTarget = target
+
+				if forceRefresh or Ovale.refreshNeeded[target] or Ovale.refreshNeeded["player"] or Ovale.refreshNeeded["pet"] then
+					if Ovale.trace then
+						Ovale:Print("****Master Node "..k)
 					end
-
-					-- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide
-					if start and OvaleState.currentSpellId and OvaleState.attenteFinCast and spellId == OvaleState.currentSpellId and start<OvaleState.attenteFinCast then
-						start = OvaleState.attenteFinCast
+					OvaleBestAction:StartNewAction()
+					local start, ending, priorite, element = OvaleBestAction:Compute(node)
+					if start then
+						Ovale:Log("Compute start = "..start)
 					end
-
-					if (node.params.nocd and start~=nil and OvaleState.maintenant<start-node.params.nocd) then
-						icons[1]:Update(element, nil)
+					local action = self.actions[k]
+					local icons
+					if action.secure then
+						icons = action.secureIcons
 					else
-						icons[1]:Update(element, start, actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
-							actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget)
+						icons = action.icons
 					end
-
-					action.spellId = spellId
-
-					if start == OvaleState.maintenant and actionUsable then
-						if not action.waitStart then
-							action.waitStart = OvaleState.maintenant
+					if element and element.type == "value" then
+						local actionTexture
+						if node.params.texture then
+							actionTexture = GetSpellTexture(node.params.texture)
+						end
+						local value
+						if element.value and element.origin and element.rate then
+							value = element.value + (OvaleState.maintenant - element.origin) * element.rate
+						end
+						icons[1]:SetValue(value, actionTexture)
+						if #icons > 1 then
+							icons[2]:Update(element, nil)
 						end
 					else
-						action.waitStart = nil
-					end
-
-					if OvaleOptions:GetApparence().moving and icons[1].debutAction and icons[1].finAction then
-						local top=1-(OvaleState.maintenant - icons[1].debutAction)/(icons[1].finAction-icons[1].debutAction)
-						if top<0 then
-							top = 0
-						elseif top>1 then
-							top = 1
+						local actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
+								actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget, noRed = OvaleBestAction:GetActionInfo(element)
+						if noRed then
+							start = actionCooldownStart + actionCooldownDuration
+							if start < OvaleState.currentTime then
+								start = OvaleState.currentTime
+							end
 						end
-						icons[1]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + top*action.dx)/action.scale,(action.top - top*action.dy)/action.scale)
-						if icons[2] then
-							icons[2]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (top+1)*action.dx)/action.scale,(action.top - (top+1)*action.dy)/action.scale)
+
+						-- Dans le cas de canStopChannelling, on risque de demander d'interrompre le channelling courant, ce qui est stupide
+						if start and OvaleState.currentSpellId and OvaleState.attenteFinCast and spellId == OvaleState.currentSpellId and start<OvaleState.attenteFinCast then
+							start = OvaleState.attenteFinCast
 						end
-					end
-
-					if (node.params.size ~= "small" and not node.params.nocd and OvaleOptions:GetApparence().predictif) then
-						if start then
-							local castTime=0
-							if spellId then
-								local _, _, _, _, _, _, _castTime = GetSpellInfo(spellId)
-								if _castTime and _castTime>0 then
-									castTime = _castTime/1000
-								end
+
+						if (node.params.nocd and start~=nil and OvaleState.maintenant<start-node.params.nocd) then
+							icons[1]:Update(element, nil)
+						else
+							icons[1]:Update(element, start, actionTexture, actionInRange, actionCooldownStart, actionCooldownDuration,
+								actionUsable, actionShortcut, actionIsCurrent, actionEnable, spellId, actionTarget)
+						end
+
+						action.spellId = spellId
+
+						if start == OvaleState.maintenant and actionUsable then
+							if not action.waitStart then
+								action.waitStart = OvaleState.maintenant
 							end
-							local gcd = OvaleData:GetGCD(spellId)
-							local nextCast
-							if (castTime>gcd) then
-								nextCast = start + castTime
-							else
-								nextCast = start + gcd
-							end
-							if Ovale.trace then
-								Ovale:Print("****Second icon " .. start)
+						else
+							action.waitStart = nil
+						end
+
+						if OvaleOptions:GetApparence().moving and icons[1].debutAction and icons[1].finAction then
+							local top=1-(OvaleState.maintenant - icons[1].debutAction)/(icons[1].finAction-icons[1].debutAction)
+							if top<0 then
+								top = 0
+							elseif top>1 then
+								top = 1
 							end
-							local spellTarget
-							if element then
-								spellTarget = element.params.target
+							icons[1]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + top*action.dx)/action.scale,(action.top - top*action.dy)/action.scale)
+							if icons[2] then
+								icons[2]:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (top+1)*action.dx)/action.scale,(action.top - (top+1)*action.dy)/action.scale)
 							end
-							if spellTarget == "target" or not spellTarget then
-								spellTarget = target
+						end
+
+						if (node.params.size ~= "small" and not node.params.nocd and OvaleOptions:GetApparence().predictif) then
+							if start then
+								local castTime=0
+								if spellId then
+									local _, _, _, _, _, _, _castTime = GetSpellInfo(spellId)
+									if _castTime and _castTime>0 then
+										castTime = _castTime/1000
+									end
+								end
+								local gcd = OvaleData:GetGCD(spellId)
+								local nextCast
+								if (castTime>gcd) then
+									nextCast = start + castTime
+								else
+									nextCast = start + gcd
+								end
+								if Ovale.trace then
+									Ovale:Print("****Second icon " .. start)
+								end
+								local spellTarget
+								if element then
+									spellTarget = element.params.target
+								end
+								if spellTarget == "target" or not spellTarget then
+									spellTarget = target
+								end
+								OvaleState:AddSpellToStack(spellId, start, start + castTime, nextCast, false, UnitGUID(spellTarget))
+								start, ending, priorite, element = OvaleBestAction:Compute(node)
+								icons[2]:Update(element, start, OvaleBestAction:GetActionInfo(element))
+							else
+								icons[2]:Update(element, nil)
 							end
-							OvaleState:AddSpellToStack(spellId, start, start + castTime, nextCast, false, UnitGUID(spellTarget))
-							start, ending, priorite, element = OvaleBestAction:Compute(node)
-							icons[2]:Update(element, start, OvaleBestAction:GetActionInfo(element))
-						else
-							icons[2]:Update(element, nil)
 						end
 					end
 				end
@@ -319,87 +323,89 @@ do
 		local margin =  OvaleOptions:GetApparence().margin

 		for k,node in pairs(Ovale.masterNodes) do
-			if not self.actions[k] then
-				self.actions[k] = {icons={}, secureIcons={}}
-			end
-			local action = self.actions[k]
+			if Ovale.masterNodesEnabled[k] then
+				if not self.actions[k] then
+					self.actions[k] = {icons={}, secureIcons={}}
+				end
+				local action = self.actions[k]

-			local width, height, newScale
-			local nbIcons
-			if (node.params.size == "small") then
-				newScale = OvaleOptions:GetApparence().smallIconScale
-				width = newScale * 36 + margin
-				height = newScale * 36 + margin
-				nbIcons = 1
-			else
-				newScale = OvaleOptions:GetApparence().iconScale
-				width =newScale * 36 + margin
-				height = newScale * 36 + margin
-				if OvaleOptions:GetApparence().predictif and node.params.type ~= "value" then
-					nbIcons = 2
-				else
+				local width, height, newScale
+				local nbIcons
+				if (node.params.size == "small") then
+					newScale = OvaleOptions:GetApparence().smallIconScale
+					width = newScale * 36 + margin
+					height = newScale * 36 + margin
 					nbIcons = 1
+				else
+					newScale = OvaleOptions:GetApparence().iconScale
+					width =newScale * 36 + margin
+					height = newScale * 36 + margin
+					if OvaleOptions:GetApparence().predictif and node.params.type ~= "value" then
+						nbIcons = 2
+					else
+						nbIcons = 1
+					end
 				end
-			end
-			if (top + height > OvaleOptions:GetApparence().iconScale * 36 + margin) then
-				top = 0
-				left = maxWidth
-			end
-
-			action.scale = newScale
-			if (OvaleOptions:GetApparence().vertical) then
-				action.left = top
-				action.top = -left-BARRE-margin
-				action.dx = width
-				action.dy = 0
-			else
-				action.left = left
-				action.top = -top-BARRE-margin
-				action.dx = 0
-				action.dy = height
-			end
-			action.secure = node.secure
-
-			for l=1,nbIcons do
-				local icon
-				if not node.secure then
-					if not action.icons[l] then
-						action.icons[l] = CreateFrame("CheckButton", "Icon"..k.."n"..l,self.frame,"OvaleIconTemplate");
-					end
-					icon = action.icons[l]
+				if (top + height > OvaleOptions:GetApparence().iconScale * 36 + margin) then
+					top = 0
+					left = maxWidth
+				end
+
+				action.scale = newScale
+				if (OvaleOptions:GetApparence().vertical) then
+					action.left = top
+					action.top = -left-BARRE-margin
+					action.dx = width
+					action.dy = 0
 				else
-					if not action.secureIcons[l] then
-						action.secureIcons[l] = CreateFrame("CheckButton", "SecureIcon"..k.."n"..l,self.frame,"SecureOvaleIconTemplate");
-					end
-					icon = action.secureIcons[l]
+					action.left = left
+					action.top = -top-BARRE-margin
+					action.dx = 0
+					action.dy = height
 				end
-				local scale = action.scale
-				if l> 1 then
-					scale = scale  * OvaleOptions:GetApparence().secondIconScale
+				action.secure = node.secure
+
+				for l=1,nbIcons do
+					local icon
+					if not node.secure then
+						if not action.icons[l] then
+							action.icons[l] = CreateFrame("CheckButton", "Icon"..k.."n"..l,self.frame,"OvaleIconTemplate");
+						end
+						icon = action.icons[l]
+					else
+						if not action.secureIcons[l] then
+							action.secureIcons[l] = CreateFrame("CheckButton", "SecureIcon"..k.."n"..l,self.frame,"SecureOvaleIconTemplate");
+						end
+						icon = action.secureIcons[l]
+					end
+					local scale = action.scale
+					if l> 1 then
+						scale = scale  * OvaleOptions:GetApparence().secondIconScale
+					end
+					icon:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (l-1)*action.dx)/scale,(action.top - (l-1)*action.dy)/scale)
+					icon:SetScale(scale)
+					icon:SetFontScale(OvaleOptions:GetApparence().fontScale)
+					icon:SetParams(node.params)
+					icon:SetHelp(node.params.help)
+					icon:SetRangeIndicator(OvaleOptions:GetApparence().targetText)
+					icon:EnableMouse(not OvaleOptions:GetApparence().clickThru)
+					icon.cdShown = (l == 1)
+					if Masque then
+						self.skinGroup:AddButton(icon)
+					end
+					if l==1 then
+						icon:Show();
+					end
 				end
-				icon:SetPoint("TOPLEFT",self.frame,"TOPLEFT",(action.left + (l-1)*action.dx)/scale,(action.top - (l-1)*action.dy)/scale)
-				icon:SetScale(scale)
-				icon:SetFontScale(OvaleOptions:GetApparence().fontScale)
-				icon:SetParams(node.params)
-				icon:SetHelp(node.params.help)
-				icon:SetRangeIndicator(OvaleOptions:GetApparence().targetText)
-				icon:EnableMouse(not OvaleOptions:GetApparence().clickThru)
-				icon.cdShown = (l == 1)
-				if Masque then
-					self.skinGroup:AddButton(icon)
+
+				top = top + height
+				if (top> maxHeight) then
+					maxHeight = top
 				end
-				if l==1 then
-					icon:Show();
+				if (left + width > maxWidth) then
+					maxWidth = left + width
 				end
 			end
-
-			top = top + height
-			if (top> maxHeight) then
-				maxHeight = top
-			end
-			if (left + width > maxWidth) then
-				maxWidth = left + width
-			end
 		end

 		if (OvaleOptions:GetApparence().vertical) then