Last active
June 27, 2019 19:31
-
-
Save dhkatz/4d7b710b426d3235d4188fd991a11836 to your computer and use it in GitHub Desktop.
Garry's Mod Vue.js Example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div id="app"> | |
<Vitals ref="vitals" id="vitals"></Vitals> | |
</div> | |
</template> | |
<script> | |
import Vitals from './components/Vitals.vue'; | |
export default { | |
name: 'app', | |
components: { | |
Vitals | |
} | |
}; | |
</script> | |
<style lang="scss"> | |
@import url('https://fonts.googleapis.com/css?family=Roboto'); | |
body { | |
background-color: transparent; | |
background-size: cover; | |
color: black; | |
font-family: Roboto; | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Vue from 'vue'; | |
import App from './App.vue'; | |
import store from './store'; | |
Vue.config.productionTip = false; | |
new Vue({ | |
store, | |
render: h => h(App) | |
}).$mount('#app'); | |
window.State = store' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<template> | |
<div class="vitals"> | |
<div class="health"> | |
<i class="material-icons md-32">add_box</i> | |
<animated-number :value="health" :formatValue="toFixed" :duration="300"/> | |
</div> | |
<div class="armor" :class="{ none: armor <= 0}"> | |
<i class="material-icons md-32">security</i> | |
<animated-number :value="armor" :formatValue="toFixed" :duration="300"/> | |
</div> | |
<div class="test"> | |
<input v-model="test" placeholder="Edit Me" @click="callLua"> | |
</div> | |
</div> | |
</template> | |
<script> | |
import { mapState } from 'vuex'; | |
import AnimatedNumber from 'animated-number-vue'; | |
export default { | |
name: 'Vitals', | |
components: { | |
AnimatedNumber | |
}, | |
data: function() { | |
return { | |
test: '', | |
}; | |
}, | |
computed: mapState(['health', 'armor']), | |
methods: { | |
/** | |
* Convert a number to a string of fixed digits. | |
* @param {number} value | |
*/ | |
toFixed(value) { | |
return value.toFixed(0); | |
}, | |
callLua() { | |
console.log('Player clicked button'); | |
} | |
} | |
} | |
</script> | |
<style lang="scss" scoped> | |
@import url("https://fonts.googleapis.com/icon?family=Material+Icons"); | |
.material-icons.md-32 { | |
font-size: 32px; | |
} | |
.vitals { | |
position: absolute; | |
left: 16px; | |
bottom: 16px; | |
display: flex; | |
color: #40e038; | |
text-shadow: black 1px 1px 7px; | |
div { | |
line-height: 1; | |
font-size: 32px; | |
padding: 8px 16px; | |
display: flex; | |
&.none { | |
opacity: 0.2; | |
} | |
i { | |
padding-right: 10px; | |
} | |
} | |
} | |
</style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
vue = vue or { | |
Instances = {} | |
} | |
--- Register a new Vue.js HUD window. | |
-- @param name Name for the new instance | |
-- @param url The URL of the hosted page to load | |
-- @param options Extra options for configuring the instance | |
function vue:Instance(name, url, options) | |
options = options or {} | |
local INSTANCE = { | |
HTML = nil, | |
Initialized = false, | |
State = {}, | |
Callbacks = {} | |
} | |
function INSTANCE:RegisterState(data) | |
for key, callback in pairs(data) do | |
self.State[key] = nil | |
self.Callbacks[key] = callback | |
end | |
end | |
local html = vgui.Create("DHTML") | |
html:SetSize(ScrW(), ScrH()) | |
html:Dock(FILL) | |
html:OpenURL(url) | |
html:SetAllowLua(true) | |
html:SetKeyboardInputEnabled(true) | |
local PaintOld = html.Paint | |
function html:Paint(w, h) | |
if cvars.Number("cl_drawhud", 0) == 0 then | |
return true | |
end | |
PaintOld(self, w, h) | |
end | |
INSTANCE.HTML = html | |
if options.state then | |
INSTANCE:RegisterState(options.state) | |
end | |
INSTANCE.Initialized = true | |
table.insert(vue.Instances, INSTANCE) | |
return INSTANCE | |
end | |
--- Update Vue.js global state through Lua | |
function vue:Sync() | |
for _, instance in pairs(self.Instances) do | |
if not instance.Initialized then continue end | |
for key, callback in pairs(instance.Callbacks) do | |
instance.State[key] = callback() | |
end | |
for key, value in pairs(instance.State) do | |
instance.HTML:QueueJavascript("if (typeof State !== 'undefined') { " .. "State." .. key .. " = " .. value .. "; }") | |
end | |
end | |
end | |
hook.Add("Think", "vue.Think", function() | |
vue:Sync() | |
end) | |
local DISABLED = { ["CHudHealth"] = true, ["CHudBattery"] = true, ["CHudAmmo"] = true, ["CHudSecondaryAmmo"] = true } | |
hook.Add("HUDShouldDraw", "vue.HUDShouldDraw", function(name) | |
if DISABLED[name] then | |
return false | |
end | |
end) | |
hook.Add("Initialize", "vue.Initialize", function() | |
-- COMMENT OUT THIS SECTION IF YOU'RE USING DARKRP | |
local FKeyBinds = { | |
["gm_showhelp"] = "ShowHelp", | |
["gm_showteam"] = "ShowTeam", | |
["gm_showspare1"] = "ShowSpare1", | |
["gm_showspare2"] = "ShowSpare2" | |
} | |
local OldPlayerBindPress = GAMEMODE.PlayerBindPress | |
function GAMEMODE:PlayerBindPress(ply, bind, pressed) | |
OldPlayerBindPress(self, ply, bind, pressed) | |
local bnd = string.match(string.lower(bind), "gm_[a-z]+[12]?") | |
if bnd and FKeyBinds[bnd] then | |
hook.Call(FKeyBinds[bnd], GAMEMODE) | |
end | |
end | |
local GUIToggled = false | |
local mouseX, mouseY = ScrW() / 2, ScrH() / 2 | |
function GAMEMODE:ShowSpare1() | |
GUIToggled = not GUIToggled | |
if GUIToggled then | |
gui.SetMousePos(mouseX, mouseY) | |
else | |
mouseX, mouseY = gui.MousePos() | |
end | |
gui.EnableScreenClicker(GUIToggled) | |
end | |
-- END POTENTIAL COMMENTED OUT SECTION | |
vue:Instance("HUD", "http://localhost:8080/#/", { | |
state = { | |
health = function() | |
return LocalPlayer():Health() | |
end, | |
armor = function() | |
return LocalPlayer():Armor() | |
end | |
} | |
}) | |
end) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment