[AvatarScaleMod] i forgotr

This commit is contained in:
NotAKidoS 2023-10-03 20:26:30 -05:00
parent 2861957e3d
commit 92bbd72338
16 changed files with 544 additions and 305 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,42 +1,47 @@
(function() {
/* -------------------------------
* CSS Embedding
* ------------------------------- */
{
function injectCSS() {
const embeddedCSS = `
.slider-container {
width: 80%;
padding-left: 2em;
position: relative;
}
.avatar-scale-slider-container {
// ass stands for Avatar Scale Slider
/* Container styles */
.ass-flex-container {
display: flex;
justify-content: space-between;
align-items: center;
}
/* ass Slider styles */
.ass-slider-container {
width: 100%;
height: 3em;
}
.ass-slider-base {
height: 3.25em;
position: relative;
background: #555;
border-radius: 1.5em;
cursor: pointer;
overflow: hidden;
}
.avatar-scale-track-inner {
.ass-slider-inner {
height: 100%;
background: #a9a9a9;
position: absolute;
top: 0;
left: 0;
}
.avatar-scale-snap-point {
.ass-snap-point {
height: 100%;
width: 2px;
background: white;
position: absolute;
top: 0;
}
.slider-display-value {
.ass-slider-value {
font-size: 2em;
position: relative;
left: 0.5em;
@ -44,16 +49,79 @@
white-space: nowrap;
}
.lock-icon {
/* Category (label) styles */
.ass-category-label {
font-size: 2.2em;
position: relative;
left: 0.5em;
color: #fff;
white-space: nowrap;
margin-right: 1em;
}
/* Circle Button styles */
.ass-circle-button {
height: 2em;
width: 2em;
border-radius: 50%;
background-color: #555;
border: none;
cursor: pointer;
color: #fff;
font-size: 1.75em;
display: flex;
align-items: center;
justify-content: center;
transition: background-color 0.3s;
}
.ass-circle-button:hover {
background-color: #777;
}
/* Custom Toggle styles */
.ass-custom-toggle {
width: 5em;
height: 2.5em;
background-color: #555;
border-radius: 1.25em;
position: absolute;
top: 50%;
right: 1em;
transform: translateY(-50%);
width: 1.5em;
height: 1.5em;
background: url('path_to_lock_icon.png') no-repeat center;
background-size: contain;
transform: translateY(-65%);
right: 0;
cursor: pointer;
transition: background-color 0.3s;
}
.ass-toggle-circle {
width: 2.5em;
height: 2.5em;
background-color: #a9a9a9;
border-radius: 50%;
position: absolute;
top: 0;
left: 0;
transition: left 0.3s;
}
.ass-custom-toggle.active .ass-toggle-circle {
left: 50%;
}
/* Label styles */
.ass-label {
font-size: 2em;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
position: relative;
z-index: 0;
}
.ass-toggle-setting {
position: relative;
height: 3.5em;
}
`;
const styleElement = document.createElement('style');
@ -63,113 +131,284 @@
}
/* -------------------------------
* Content Injection
* Main Content Element
* ------------------------------- */
{
const contentBlock = document.createElement('div');
contentBlock.innerHTML = `
<div class="settings-subcategory">
<div class="subcategory-name">Avatar Motion Tweaker</div>
<div class="subcategory-description"></div>
</div>
<div class="row-wrapper">
<div class="option-caption">Crouch limit: </div>
<div class="option-input">
<div id="CrouchLimit" class="inp_slider no-scroll" data-min="0" data-max="100" data-current="75"></div>
</div>
</div>
<div class="slider-container">
<div class="slider-display-value">
<span class="slider-value">0m</span>
</div>
<div class="avatar-scale-slider-container">
<div class="avatar-scale-track-inner"></div>
</div>
<div class="lock-icon"></div>
</div>
`;
const targetElement = document.getElementById('btkUI-AvatarScaleMod-MainPage');
if(targetElement) {
targetElement.appendChild(contentBlock);
} else {
console.warn('Target element "btkUI-AvatarScaleMod-MainPage" not found!');
class MainContent {
constructor(targetId) {
this.element = document.createElement('div');
this.element.id = "AvatarScaleModContainer";
const targetElement = document.getElementById(targetId);
if (targetElement) {
targetElement.appendChild(this.element);
} else {
console.warn(`Target element "${targetId}" not found!`);
}
}
}
/* -------------------------------
* Event Handlers & Utility Functions
* Generic Element Class
* ------------------------------- */
class Element {
constructor(tagName, parentElement) {
this.element = document.createElement(tagName);
parentElement.appendChild(this.element);
}
}
/* -------------------------------
* Container Object
* ------------------------------- */
{
const sliderContainer = document.querySelector('.avatar-scale-slider-container');
const trackInner = document.querySelector('.avatar-scale-track-inner');
const valueDisplay = document.querySelector('.slider-value');
class Container extends Element {
constructor(parentElement, {
width = '100%',
padding = '0em',
paddingTop = null,
paddingRight = null,
paddingBottom = null,
paddingLeft = null,
margin = '0em',
marginTop = null,
marginRight = null,
marginBottom = null,
marginLeft = null
} = {}) {
super('div', parentElement);
this.element.className = "ass-container";
this.element.style.width = width;
this.element.style.padding = padding;
this.element.style.margin = margin;
const SNAP_TOLERANCE = 0.02;
let snapPoints = [];
// padding values
if (paddingTop) this.element.style.paddingTop = paddingTop;
if (paddingRight) this.element.style.paddingRight = paddingRight;
if (paddingBottom) this.element.style.paddingBottom = paddingBottom;
if (paddingLeft) this.element.style.paddingLeft = paddingLeft;
let isDragging = false;
// margin values
if (marginTop) this.element.style.marginTop = marginTop;
if (marginRight) this.element.style.marginRight = marginRight;
if (marginBottom) this.element.style.marginBottom = marginBottom;
if (marginLeft) this.element.style.marginLeft = marginLeft;
sliderContainer.addEventListener('mousedown', (e) => {
isDragging = true;
updateTrackWidth(e.clientX);
});
this.flexContainer = new Element('div', this.element);
this.flexContainer.element.className = "ass-flex-container";
}
window.addEventListener('mousemove', (e) => {
if (!isDragging) return;
updateTrackWidth(e.clientX);
});
appendElementToFlex(element) {
this.flexContainer.element.appendChild(element);
}
window.addEventListener('mouseup', () => {
isDragging = false;
});
appendElement(element) {
this.element.appendChild(element);
}
}
function updateTrackWidth(clientX) {
const rect = sliderContainer.getBoundingClientRect();
/* -------------------------------
* Category (label) Class
* ------------------------------- */
class Category extends Element {
constructor(parentElement, text) {
super('span', parentElement);
this.element.className = "ass-category-label";
this.element.textContent = text;
}
}
// Get padding values from the slider container
const paddingLeft = parseFloat(getComputedStyle(sliderContainer).paddingLeft);
const paddingRight = parseFloat(getComputedStyle(sliderContainer).paddingRight);
/* -------------------------------
* Circle Button Class
* ------------------------------- */
class CircleButton extends Element {
constructor(parentElement, text) {
super('button', parentElement);
this.element.className = "ass-circle-button";
this.element.textContent = text;
}
}
// Calculate the effective width and position based on padding
/* -------------------------------
* Custom Toggle Class
* ------------------------------- */
class CustomToggle extends Element {
constructor(parentElement) {
super('div', parentElement);
this.element.className = "ass-custom-toggle";
this.toggleCircle = new Element('div', this.element);
this.toggleCircle.element.className = "ass-toggle-circle";
this.state = false;
this.element.addEventListener('click', () => {
this.toggle();
});
}
toggle() {
this.state = !this.state;
if (this.state) {
this.toggleCircle.element.style.left = '50%';
} else {
this.toggleCircle.element.style.left = '0';
}
}
}
/* -------------------------------
* Label Class
* ------------------------------- */
class Label extends Element {
constructor(parentElement, text) {
super('span', parentElement);
this.element.className = "ass-label";
this.element.textContent = text;
}
}
/* -------------------------------
* ToggleSetting Class
* ------------------------------- */
class ToggleSetting extends Element {
constructor(parentElement, labelText) {
super('div', parentElement);
this.element.className = "ass-toggle-setting";
const label = new Label(this.element, labelText);
this.toggle = new CustomToggle(this.element);
}
}
/* -------------------------------
* Slider Object
* ------------------------------- */
class Slider extends Element {
constructor(parentElement, min = 0.1, max = 5, initialValue = 1.8) {
super('div', parentElement);
this.element.className = "ass-slider-container";
this.min = min;
this.max = max;
// Value display
this.valueDisplay = new Element('span', this.element);
this.valueDisplay.element.className = "ass-slider-value";
// Slider content
this.sliderBase = new Element('div', this.element);
this.sliderBase.element.className = "ass-slider-base";
this.trackInner = new Element('div', this.sliderBase.element);
this.trackInner.element.className = "ass-slider-inner";
this.addEventListeners();
this.setInitialValue(initialValue);
}
setInitialValue(value) {
const percentage = (value - this.min) / (this.max - this.min);
this.trackInner.element.style.width = `${percentage * 100}%`;
this.valueDisplay.element.textContent = value.toFixed(2) + "m";
this.addSnapPoint(percentage);
}
addEventListeners() {
this.snapPoints = [];
let isDragging = false;
this.element.addEventListener('mousedown', (e) => {
isDragging = true;
this.updateTrackWidth(e.clientX);
});
window.addEventListener('mousemove', (e) => {
if (!isDragging) return;
this.updateTrackWidth(e.clientX);
});
window.addEventListener('mouseup', () => {
isDragging = false;
});
}
updateTrackWidth(clientX) {
const rect = this.element.getBoundingClientRect();
const paddingLeft = parseFloat(getComputedStyle(this.element).paddingLeft);
const paddingRight = parseFloat(getComputedStyle(this.element).paddingRight);
const effectiveWidth = rect.width - paddingLeft - paddingRight;
let x = clientX - rect.left - paddingLeft;
// Ensure the position is within the bounds of the effective width
x = Math.min(Math.max(0, x), effectiveWidth);
const percentage = x / effectiveWidth;
const closestSnap = snapPoints.reduce((closest, snap) => {
let percentage = x / effectiveWidth;
const closestSnap = this.snapPoints.reduce((closest, snap) => {
return Math.abs(closest - percentage) < Math.abs(snap - percentage) ? closest : snap;
}, 1);
const SNAP_TOLERANCE = 0.01;
if (Math.abs(closestSnap - percentage) <= SNAP_TOLERANCE) {
x = closestSnap * effectiveWidth;
percentage = closestSnap;
}
trackInner.style.width = `${x}px`;
valueDisplay.textContent = (x / effectiveWidth * 100).toFixed(2) + "m";
this.trackInner.element.style.width = `${x}px`;
const value = this.min + (this.max - this.min) * percentage;
this.valueDisplay.element.textContent = value.toFixed(2) + "m";
engine.call("asm-AvatarHeightUpdated", value);
}
function addSnapPoint(percentage) {
addSnapPoint(percentage) {
if (percentage < 0 || percentage > 1) return;
const snap = document.createElement('div');
snap.className = 'avatar-scale-snap-point';
snap.style.left = `${percentage * 100}%`;
sliderContainer.appendChild(snap);
snapPoints.push(percentage);
const snap = new Element('div', this.sliderBase.element);
snap.element.className = 'ass-snap-point';
snap.element.style.left = `${percentage * 100}%`;
this.snapPoints.push(percentage);
}
// To evenly space out snap points:
function addEvenSnapPoints(count) {
addEvenSnapPoints(count) {
for (let i = 1; i <= count; i++) {
addSnapPoint(i / (count + 1));
this.addSnapPoint(i / (count + 1));
}
}
// Example usage:
addEvenSnapPoints(5); // Adds 5 evenly spaced snap points
}
// Initialization
injectCSS();
const mainContent = new MainContent('btkUI-AvatarScaleMod-MainPage');
if (mainContent.element) {
const mainContainer = new Container(mainContent.element, {
width: '75%',
marginTop: '2em',
marginLeft: '2em',
marginBottom: '1em'
});
const slider = new Slider(mainContainer.flexContainer.element, 0.1, 3);
const buttonContainer = new Container(mainContainer.flexContainer.element, {
width: '20%',
marginTop: '2.5em',
marginLeft: '1em',
});
const circleButton1 = new CircleButton(buttonContainer.flexContainer.element, "+");
const circleButton2 = new CircleButton(buttonContainer.flexContainer.element, "-");
const settingsContainer = new Container(mainContent.element, {
width: '100%',
marginTop: '1em',
marginLeft: '1em',
});
const categoryLabel = new Category(settingsContainer.element, "Universal Scaling Settings:");
const settingsContainerInner = new Container(mainContent.element, {
width: '90%',
marginTop: '1em',
marginLeft: '3em',
});
const toggleSetting = new ToggleSetting(settingsContainerInner.element, "Universal Scaling (Mod Network)");
const toggleSetting2 = new ToggleSetting(settingsContainerInner.element, "Recognize Scale Gesture");
const toggleSetting3 = new ToggleSetting(settingsContainerInner.element, "Scale Components");
}
})();

View file

@ -1,13 +0,0 @@
.slider-container {
margin: 10px 0;
padding: 5px;
}
.slider-label {
display: block;
margin-bottom: 5px;
}
.test-slider {
width: 100%;
}