New mod: Vive Extended Input

Unified UI elements script
This commit is contained in:
SDraw 2023-09-28 09:54:04 +03:00
parent 14e01e692e
commit 90de21cce8
No known key found for this signature in database
GPG key ID: BB95B4DAB2BB8BB5
26 changed files with 900 additions and 919 deletions

View file

@ -1,4 +1,4 @@
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.7", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonInfo(typeof(ml_pam.PickupArmMovement), "PickupArmMovement", "1.0.8", "SDraw", "https://github.com/SDraw/ml_mods_cvr")]
[assembly: MelonLoader.MelonGame(null, "ChilloutVR")]
[assembly: MelonLoader.MelonPriority(1)]
[assembly: MelonLoader.MelonPlatform(MelonLoader.MelonPlatformAttribute.CompatiblePlatforms.WINDOWS_X64)]

View file

@ -7,6 +7,6 @@ This mod adds arm tracking upon holding pickup in desktop mode.
* Put `ml_pam.dll` in `Mods` folder of game
# Usage
Available mod's settings in `Settings - Interactions`:
Available mod's settings in `Settings - Interactions - Pickup Arm Movement`:
* **Enable hand movement:** enables/disables arm tracking; default value - `true`.
* **Grab offset:** offset from pickup grab point; defalut value - `25`.

View file

@ -1,5 +1,4 @@
using ABI_RC.Core.InteractionSystem;
using cohtml;
using System;
using System.Collections.Generic;
@ -53,7 +52,8 @@ namespace ml_pam
};
ViewManager.Instance.gameMenuView.Listener.FinishLoad += (_) =>
{
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("menu.js"));
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("ui_elements.js"));
ViewManager.Instance.gameMenuView.View.ExecuteScript(Scripts.GetEmbeddedScript("ui_menu.js"));
foreach(var l_entry in ms_entries)
ViewManager.Instance.gameMenuView.View.TriggerEvent("updateModSettingPAM", l_entry.DisplayName, l_entry.GetValueAsString());
};

View file

@ -4,7 +4,7 @@
<TargetFramework>netstandard2.1</TargetFramework>
<Platforms>x64</Platforms>
<PackageId>PickupArmMovement</PackageId>
<Version>1.0.7</Version>
<Version>1.0.8</Version>
<Authors>SDraw</Authors>
<Company>None</Company>
<Product>PickupArmMovement</Product>
@ -17,11 +17,15 @@
<ItemGroup>
<None Remove="PickupArmMovement.json" />
<None Remove="resources\menu.js" />
<None Remove="resources\ui_menu.js" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="resources\menu.js" />
<EmbeddedResource Include="resources\ui_menu.js" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="..\js\ui_elements.js" Link="resources\ui_elements.js" />
</ItemGroup>
<ItemGroup>

View file

@ -1,209 +0,0 @@
// Add settings
var g_modSettingsPAM = [];
engine.on('updateModSettingPAM', function (_name, _value) {
for (var i = 0; i < g_modSettingsPAM.length; i++) {
if (g_modSettingsPAM[i].name == _name) {
g_modSettingsPAM[i].updateValue(_value);
break;
}
}
});
// Modified from original `inp` types, because I have no js knowledge to hook stuff
function inp_toggle_mod_pam(_obj, _callbackName) {
this.obj = _obj;
this.callbackName = _callbackName;
this.value = _obj.getAttribute('data-current');
this.name = _obj.id;
this.type = _obj.getAttribute('data-type');
var self = this;
this.mouseDown = function (_e) {
self.value = self.value == "True" ? "False" : "True";
self.updateState();
}
this.updateState = function () {
self.obj.classList.remove("checked");
if (self.value == "True") {
self.obj.classList.add("checked");
}
engine.call(self.callbackName, self.name, self.value);
}
_obj.addEventListener('mousedown', this.mouseDown);
this.getValue = function () {
return self.value;
}
this.updateValue = function (value) {
self.value = value;
self.obj.classList.remove("checked");
if (self.value == "True") {
self.obj.classList.add("checked");
}
}
this.updateValue(this.value);
return {
name: this.name,
value: this.getValue,
updateValue: this.updateValue
}
}
function inp_slider_mod_pam(_obj, _callbackName) {
this.obj = _obj;
this.callbackName = _callbackName;
this.minValue = parseFloat(_obj.getAttribute('data-min'));
this.maxValue = parseFloat(_obj.getAttribute('data-max'));
this.percent = 0;
this.value = parseFloat(_obj.getAttribute('data-current'));
this.dragActive = false;
this.name = _obj.id;
this.type = _obj.getAttribute('data-type');
this.stepSize = _obj.getAttribute('data-stepSize') || 0;
this.format = _obj.getAttribute('data-format') || '{value}';
var self = this;
if (this.stepSize != 0)
this.value = Math.round(this.value / this.stepSize) * this.stepSize;
else
this.value = Math.round(this.value);
this.valueLabelBackground = document.createElement('div');
this.valueLabelBackground.className = 'valueLabel background';
this.valueLabelBackground.innerHTML = this.format.replace('{value}', this.value);
this.obj.appendChild(this.valueLabelBackground);
this.valueBar = document.createElement('div');
this.valueBar.className = 'valueBar';
this.valueBar.setAttribute('style', 'width: ' + (((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;');
this.obj.appendChild(this.valueBar);
this.valueLabelForeground = document.createElement('div');
this.valueLabelForeground.className = 'valueLabel foreground';
this.valueLabelForeground.innerHTML = this.format.replace('{value}', this.value);
this.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / ((this.value - this.minValue) / (this.maxValue - this.minValue)) * 100) + '%;');
this.valueBar.appendChild(this.valueLabelForeground);
this.mouseDown = function (_e) {
self.dragActive = true;
self.mouseMove(_e, false);
}
this.mouseMove = function (_e, _write) {
if (self.dragActive) {
var rect = _obj.getBoundingClientRect();
var start = rect.left;
var end = rect.right;
self.percent = Math.min(Math.max((_e.clientX - start) / rect.width, 0), 1);
var value = self.percent;
value *= (self.maxValue - self.minValue);
value += self.minValue;
if (self.stepSize != 0) {
value = Math.round(value / self.stepSize);
self.value = value * self.stepSize;
self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue);
}
else
self.value = Math.round(value);
self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;');
self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;');
self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value);
engine.call(self.callbackName, self.name, "" + self.value);
self.displayImperial();
}
}
this.mouseUp = function (_e) {
self.mouseMove(_e, true);
self.dragActive = false;
}
_obj.addEventListener('mousedown', this.mouseDown);
document.addEventListener('mousemove', this.mouseMove);
document.addEventListener('mouseup', this.mouseUp);
this.getValue = function () {
return self.value;
}
this.updateValue = function (value) {
if (self.stepSize != 0)
self.value = Math.round(value * self.stepSize) / self.stepSize;
else
self.value = Math.round(value);
self.percent = (self.value - self.minValue) / (self.maxValue - self.minValue);
self.valueBar.setAttribute('style', 'width: ' + (self.percent * 100) + '%;');
self.valueLabelForeground.setAttribute('style', 'width: ' + (1.0 / self.percent * 100) + '%;');
self.valueLabelBackground.innerHTML = self.valueLabelForeground.innerHTML = self.format.replace('{value}', self.value);
self.displayImperial();
}
this.displayImperial = function () {
var displays = document.querySelectorAll('.imperialDisplay');
for (var i = 0; i < displays.length; i++) {
var binding = displays[i].getAttribute('data-binding');
if (binding == self.name) {
var realFeet = ((self.value * 0.393700) / 12);
var feet = Math.floor(realFeet);
var inches = Math.floor((realFeet - feet) * 12);
displays[i].innerHTML = feet + "&apos;" + inches + '&apos;&apos;';
}
}
}
return {
name: this.name,
value: this.getValue,
updateValue: this.updateValue
}
}
// Add own menu
{
let l_block = document.createElement('div');
l_block.innerHTML = `
<div class ="settings-subcategory">
<div class ="subcategory-name">Pickup Arm Mover</div>
<div class ="subcategory-description"></div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Enable hand movement: </div>
<div class ="option-input">
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
</div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Grab offset: </div>
<div class ="option-input">
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
</div>
</div>
`;
document.getElementById('settings-interaction').appendChild(l_block);
// Update toggles in new menu block
let l_toggles = l_block.querySelectorAll('.inp_toggle');
for (var i = 0; i < l_toggles.length; i++) {
g_modSettingsPAM[g_modSettingsPAM.length] = new inp_toggle_mod_pam(l_toggles[i], 'MelonMod_PAM_Call_InpToggle');
}
// Update sliders in new menu block
let l_sliders = l_block.querySelectorAll('.inp_slider');
for (var i = 0; i < l_sliders.length; i++) {
g_modSettingsPAM[g_modSettingsPAM.length] = new inp_slider_mod_pam(l_sliders[i], 'MelonMod_PAM_Call_InpSlider');
}
}

View file

@ -0,0 +1,49 @@
// Add settings
var g_modSettingsPAM = [];
engine.on('updateModSettingPAM', function (_name, _value) {
for (var i = 0; i < g_modSettingsPAM.length; i++) {
if (g_modSettingsPAM[i].name == _name) {
g_modSettingsPAM[i].updateValue(_value);
break;
}
}
});
// Add own menu
{
let l_block = document.createElement('div');
l_block.innerHTML = `
<div class ="settings-subcategory">
<div class ="subcategory-name">Pickup Arm Movement</div>
<div class ="subcategory-description"></div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Enable hand movement: </div>
<div class ="option-input">
<div id="Enabled" class ="inp_toggle no-scroll" data-current="true"></div>
</div>
</div>
<div class ="row-wrapper">
<div class ="option-caption">Grab offset: </div>
<div class ="option-input">
<div id="GrabOffset" class ="inp_slider no-scroll" data-min="0" data-max="100" data-current="25"></div>
</div>
</div>
`;
document.getElementById('settings-interaction').appendChild(l_block);
// Update toggles in new menu block
let l_toggles = l_block.querySelectorAll('.inp_toggle');
for (var i = 0; i < l_toggles.length; i++) {
g_modSettingsPAM[g_modSettingsPAM.length] = new inp_toggle_mod(l_toggles[i], 'MelonMod_PAM_Call_InpToggle');
}
// Update sliders in new menu block
let l_sliders = l_block.querySelectorAll('.inp_slider');
for (var i = 0; i < l_sliders.length; i++) {
g_modSettingsPAM[g_modSettingsPAM.length] = new inp_slider_mod(l_sliders[i], 'MelonMod_PAM_Call_InpSlider');
}
}