Skip to content

Instantly share code, notes, and snippets.

@dhkatz
Last active June 27, 2019 19:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dhkatz/4d7b710b426d3235d4188fd991a11836 to your computer and use it in GitHub Desktop.
Save dhkatz/4d7b710b426d3235d4188fd991a11836 to your computer and use it in GitHub Desktop.
Garry's Mod Vue.js Example
<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>
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'
<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>
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