--[[******************************************************************** created: 2009/06/18 filename: Wrapper.lua author: Daniel Wellman purpose: Wraps around my Lua scripts to allow them to be used in WoW without any modification I mentioned the demo I was working on for a friend, and that could even be converted to run into WoW pretty easily He bet me that it couldn't run without a bunch of modifications, and here's the result! I should of bet money :( Note that console rendering is much different than what WoW wants, expect slowdowns! License: This software may be reproduced and distributed free of charge as as long as credit is given to the author. The author assumes no responsibility. The software is provided as is. *********************************************************************]] SLASH_CA1 = "/CA" --Last global to be loaded in my scripts local LAST_OBJECT_NAME = "SetSimulator" --The omnipresent grid variables local WIDTH, HEIGHT = 80, 25 --Insert the globals into the enviro local WrappedGlobalEnviroment = {WIDTH = WIDTH, HEIGHT = HEIGHT, WriteDebug = print, IS_WOW = true} local Frame = CreateFrame("Frame") do --Make sure to restore the old MT (if any) local oldMT = getmetatable(_G) --This grabs any new data that would be assigned to _G and instead puts it into our table --Since lua files are loaded in order from the TOC this allows us to avoid modifying the source of our CellularAutomata files --to convert them to a WoW addon setmetatable(_G, {__newindex = function(t, k, v) WrappedGlobalEnviroment[k] = v end, __index = function(t, k) return WrappedGlobalEnviroment[k] end,} ) Frame:RegisterEvent("ADDON_LOADED") Frame:SetScript("OnEvent", function(self, event, addon) if addon == "CellularAutomata" then self:UnregisterEvent("ADDON_LOADED") self:SetScript("OnEvent", nil) setmetatable(_G, oldMT) --Reset metatable, we're done end end) end local Call, CallMethod do local oldMT, oldGetCursorPosition local getmetatable, setmetatable = getmetatable, setmetatable local mt = {__index = function(t, k) return WrappedGlobalEnviroment[k] end,} --Allows us to return all arguments from the call while still restoring the MT local function RestoreAndReturnArgs(...) setmetatable(_G, oldMT) GetCursorPosition = oldGetCursorPosition return ... end local function SetupCall() oldGetCursorPosition = GetCursorPosition GetCursorPosition = WrappedGlobalEnviroment.GetCursorPosition oldMT = getmetatable(_G) setmetatable(_G, mt) end --Calls a function, allowing it to access our MT and then restores it function Call(funcName, ...) SetupCall() return RestoreAndReturnArgs(_G[funcName](...)) end function CallMethod(objectName, methodName, ...) SetupCall() return RestoreAndReturnArgs(_G[objectName][methodName](_G[objectName], ...)) end end do local Init local IsInited --Open the 'console' with /CA function SlashCmdList.CA(msg) Init() if Frame:IsVisible() then Frame:Hide() else Frame:Show() end end --Setup the console function Init() if IsInited then return end IsInited = true local SCALE = 10 Frame:Hide() Frame:SetFrameStrata("DIALOG") Frame:SetScript("OnMouseDown", Frame.StartMoving) Frame:SetScript("OnMouseUp", Frame.StopMovingOrSizing) Frame:SetBackdrop({bgFile = "Interface/Tooltips/UI-Tooltip-Background",}) Frame:SetPoint("CENTER", 0, 0) Frame:EnableMouse(true) Frame:SetMovable(true) Frame:EnableKeyboard(true) Frame:SetHeight((HEIGHT + 2) * SCALE) Frame:SetWidth((WIDTH + 2) * SCALE) local isEnterPressed, isEscapePressed = false, false Frame:SetScript("OnKeyDown", function(self, key) if key == "ENTER" then isEnterPressed = true elseif key == "ESCAPE" then isEscapePressed = true end end) Frame:SetScript("OnKeyUp", function(self, key) if key == "ENTER" then isEnterPressed = false elseif key == "ESCAPE" then isEscapePressed = false end end) local mouseX, mouseY = 1, 1 local isLeftMouseDown, isRightMouseDown = false, false local wasLeftMouseDown = false local wasEnterPressed, wasEscapePressed = false, false local TIME_STEP = .02 local timeAccumulator = 0 Frame:SetScript("OnUpdate", function(self, delta) timeAccumulator = timeAccumulator + delta if timeAccumulator >= TIME_STEP then if Call("Update", TIME_STEP) then --Exit self:Hide() --Reset escape pressed since the OnKeyUp event will never fire isEscapePressed = false else Call("Draw") end timeAccumulator = 0 end wasLeftMouseDown = isLeftMouseDown wasEnterPressed = isEnterPressed wasEscapePressed = isEscapePressed end) --Fake GetCursorPosition by getting the location of the mouse over a cell local function OnEnter(self) local cell = self.Cell mouseX = cell.X mouseY = cell.Y end local function OnMouseDown(self, button) if button == "LeftButton" then isLeftMouseDown = true elseif button == "RightButton" then isRightMouseDown = true end end local function OnMouseUp(self, button) if button == "LeftButton" then isLeftMouseDown = false elseif button == "RightButton" then isRightMouseDown = false end end local grid = {} for x=1, WIDTH do for y=1, HEIGHT do local cell = {X = x, Y = y} grid[x + y * WIDTH] = cell local frame = CreateFrame("Frame", nil, Frame) frame:EnableMouse(true) frame.Cell = cell frame:SetScript("OnEnter", OnEnter) frame:SetScript("OnMouseDown", OnMouseDown) frame:SetScript("OnMouseUp", OnMouseUp) frame:SetWidth(1 * SCALE) frame:SetHeight(1 * SCALE) frame:SetPoint("TOPLEFT", Frame, "TOPLEFT", cell.X * SCALE, -cell.Y * SCALE) do --Texture local texture = frame:CreateTexture(nil, "ARTWORK") texture:SetAllPoints(frame) cell.Texture = texture end do --Font local font = frame:CreateFontString(nil, "OVERLAY") font:SetPoint("CENTER", frame, 0, 0) font:SetFontObject(SystemFont_Med3) cell.Font = font end end end do local unpack = unpack function WrappedGlobalEnviroment.DrawSquare(x, y, char, foreColor, backColor) local cell = grid[x + y * WIDTH] cell.Texture:SetTexture(unpack(backColor)) cell.Font:SetText(char) cell.Font:SetTextColor(unpack(foreColor)) end end function WrappedGlobalEnviroment.Clear() for x=1, WIDTH do for y=1, HEIGHT do WrappedGlobalEnviroment.DrawSquare(x, y, ' ', WrappedGlobalEnviroment.Colors.Black, WrappedGlobalEnviroment.Colors.Black) end end end function WrappedGlobalEnviroment.IsLeftMousePressed() return isLeftMouseDown end function WrappedGlobalEnviroment.IsRightMousePressed() return isRightMouseDown end function WrappedGlobalEnviroment.IsLeftMouseClicked() return not isLeftMouseDown and wasLeftMouseDown end function WrappedGlobalEnviroment.IsEnterPressed() return not isEnterPressed and wasEnterPressed end function WrappedGlobalEnviroment.IsEscapePressed() return not isEscapePressed and wasEscapePressed end function WrappedGlobalEnviroment.GetCursorPosition() return mouseX, mouseY end end --Can't forget our limited console colors! local Colors = { Black = {0, 0, 0}, DarkBlue = {0, 0, .5}, DarkGreen = {0, .5, 0}, DarkTeal = {0, .5, .5}, DarkRed = {.5, 0, 0}, DarkPurple = {.5, 0, .5}, Gold = {.5, .5, 0}, Gray = {.5, .5, .5}, Silver = {.75, .75, .75}, Blue = {0, 0, 1}, Green = {0, 1, 0}, Teal = {0, 1, 1}, Red = {1, 0, 0}, Purple = {1, 0, 1}, Yellow = {1, 1, 0}, White = {1, 1, 1}, } WrappedGlobalEnviroment.Colors = Colors end