ModelHandle/source/website/sidebarsettingspanel.js
2022-01-10 18:10:51 +01:00

389 lines
13 KiB
JavaScript

import { Color, ColorToHexString } from '../engine/model/color.js';
import { AddDiv, AddDomElement, AddRangeSlider, AddToggle, ShowDomElement, GetDomElementOuterHeight, SetDomElementOuterHeight } from '../engine/viewer/domutils.js';
import { FeatureSet } from './featureset.js';
import { Settings, Theme } from './settings.js';
import { SidebarPanel } from './sidebarpanel.js';
export function AddColorPicker (parentDiv, defaultColor, predefinedColors, onChange)
{
let pickr = Pickr.create ({
el : parentDiv,
theme : 'monolith',
position : 'left-start',
swatches : predefinedColors,
comparison : false,
default : '#' + ColorToHexString (defaultColor),
components : {
preview : false,
opacity : false,
hue : true,
interaction: {
hex : false,
rgba : false,
hsla : false,
hsva : false,
cmyk : false,
input : true,
clear : false,
save : false
}
}
});
pickr.on ('change', (color, source, instance) => {
let rgbaColor = color.toRGBA ();
let ovColor = new Color (
parseInt (rgbaColor[0], 10),
parseInt (rgbaColor[1], 10),
parseInt (rgbaColor[2], 10)
);
onChange (ovColor);
});
return pickr;
}
export class SettingsColorSection
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.contentDiv = null;
this.pickr = null;
}
Init (title, description, color, predefinedColors, onChange)
{
this.contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
let titleDiv = AddDiv (this.contentDiv, 'ov_sidebar_subtitle');
let colorInput = AddDiv (titleDiv, 'ov_color_picker');
AddDiv (titleDiv, 'ov_sidebar_subtitle', title);
this.pickr = AddColorPicker (colorInput, color, predefinedColors, (color) => {
onChange (color);
});
AddDiv (this.contentDiv, 'ov_sidebar_settings_padded', description);
}
Show (show)
{
ShowDomElement (this.contentDiv, show);
}
Update (color)
{
if (this.pickr === null) {
return;
}
this.pickr.setColor ('#' + ColorToHexString (color));
}
Clear ()
{
if (this.pickr === null) {
return;
}
this.pickr.hide ();
}
}
export class SettingsGridDisplaySection
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.gridDisplayToggle = null;
}
Init (showGrid, onChange)
{
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
this.showGridToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
this.showGridToggle.OnChange (() => {
onChange (this.showGridToggle.GetStatus ());
});
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Show Grid');
this.showGridToggle.SetStatus (showGrid);
}
Update (showGrid)
{
if (this.showGridToggle === null) {
return;
}
this.showGridToggle.SetStatus (showGrid);
}
}
export class SettingsEdgeDisplaySection
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.edgeDisplayToggle = null;
this.pickr = null;
this.thresholdSlider = null;
this.thresholdSliderValue = null;
this.edgeSettingsDiv = null;
}
Init (showEdges, edgeColor, edgeThreshold, callbacks)
{
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
this.edgeDisplayToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Show Edges');
this.edgeSettingsDiv = AddDiv (contentDiv, 'ov_sidebar_settings_padded');
this.edgeDisplayToggle.OnChange (() => {
ShowDomElement (this.edgeSettingsDiv, this.edgeDisplayToggle.GetStatus ());
callbacks.onShowEdgesChange (this.edgeDisplayToggle.GetStatus () ? true : false);
});
let edgeColorRow = AddDiv (this.edgeSettingsDiv, 'ov_sidebar_settings_row');
let predefinedEdgeColors = ['#ffffff', '#e3e3e3', '#c9c9c9', '#898989', '#5f5f5f', '#494949', '#383838', '#0f0f0f'];
let colorInput = AddDiv (edgeColorRow, 'ov_color_picker');
this.pickr = AddColorPicker (colorInput, edgeColor, predefinedEdgeColors, (color) => {
callbacks.onEdgeColorChange (color);
});
AddDiv (edgeColorRow, null, 'Edge Color');
let thresholdRow = AddDiv (this.edgeSettingsDiv, 'ov_sidebar_settings_row large');
this.thresholdSlider = AddRangeSlider (thresholdRow, 0, 90);
this.thresholdSlider.setAttribute ('title', 'Edge Angle Threshold');
this.thresholdSliderValue = AddDomElement (thresholdRow, 'span', 'ov_slider_label');
this.thresholdSlider.addEventListener ('input', () => {
this.thresholdSliderValue.innerHTML = this.thresholdSlider.value;
});
this. thresholdSlider.addEventListener ('change', () => {
callbacks.onEdgeThresholdChange (this.thresholdSlider.value);
});
this.thresholdSlider.value = edgeThreshold;
this.thresholdSliderValue.innerHTML = edgeThreshold;
this.edgeDisplayToggle.SetStatus (showEdges);
this.ShowEdgeSettings (showEdges);
}
Update (showEdges, edgeColor, edgeThreshold)
{
if (this.edgeDisplayToggle === null) {
return;
}
this.edgeDisplayToggle.SetStatus (showEdges);
this.ShowEdgeSettings (showEdges);
this.pickr.setColor ('#' + ColorToHexString (edgeColor));
this.thresholdSlider.value = edgeThreshold;
this.thresholdSliderValue.innerHTML = edgeThreshold;
}
ShowEdgeSettings (show)
{
ShowDomElement (this.edgeSettingsDiv, show);
}
Clear ()
{
if (this.pickr === null) {
return;
}
this.pickr.hide ();
}
}
export class SettingsThemeSection
{
constructor (parentDiv)
{
this.parentDiv = parentDiv;
this.darkModeToggle = null;
}
Init (themeId, onChange)
{
let contentDiv = AddDiv (this.parentDiv, 'ov_sidebar_settings_content');
let titleDiv = AddDiv (contentDiv, 'ov_sidebar_subtitle');
this.darkModeToggle = AddToggle (titleDiv, 'ov_sidebar_subtitle_toggle');
this.darkModeToggle.OnChange (() => {
onChange (this.darkModeToggle.GetStatus () ? Theme.Dark : Theme.Light);
});
AddDiv (titleDiv, 'ov_sidebar_subtitle_text', 'Dark Mode');
let isDarkMode = (themeId === Theme.Dark);
this.darkModeToggle.SetStatus (isDarkMode);
}
Update (themeId)
{
if (this.darkModeToggle === null) {
return;
}
let isDarkMode = (themeId === Theme.Dark);
this.darkModeToggle.SetStatus (isDarkMode);
}
}
export class SidebarSettingsPanel extends SidebarPanel
{
constructor (parentDiv, settings)
{
super (parentDiv);
this.settings = settings;
this.sectionsDiv = AddDiv (this.contentDiv, 'ov_sidebar_settings_sections ov_thin_scrollbar');
this.backgroundColorSection = new SettingsColorSection (this.sectionsDiv);
this.defaultColorSection = new SettingsColorSection (this.sectionsDiv);
this.gridDisplaySection = null;
if (FeatureSet.ShowGrid) {
this.gridDisplaySection = new SettingsGridDisplaySection (this.sectionsDiv);
}
this.edgeDisplaySection = new SettingsEdgeDisplaySection (this.sectionsDiv);
this.themeSection = new SettingsThemeSection (this.sectionsDiv);
this.resetToDefaultsButton = AddDiv (this.contentDiv, 'ov_button ov_sidebar_button outline', 'Reset to Default');
this.resetToDefaultsButton.addEventListener ('click', () => {
this.ResetToDefaults ();
});
}
GetName ()
{
return 'Settings';
}
GetIcon ()
{
return 'settings';
}
Clear ()
{
this.backgroundColorSection.Clear ();
this.defaultColorSection.Clear ();
this.edgeDisplaySection.Clear ();
}
Init (callbacks)
{
super.Init (callbacks);
this.backgroundColorSection.Init (
'Background Color',
'Affects only the visualization.',
this.settings.backgroundColor,
['#ffffff', '#e3e3e3', '#c9c9c9', '#898989', '#5f5f5f', '#494949', '#383838', '#0f0f0f'],
(newColor) => {
this.SetBackgroundColor (newColor, false);
}
);
this.defaultColorSection.Init (
'Default Color',
'Appears when the model doesn\'t have materials.',
this.settings.defaultColor,
['#ffffff', '#e3e3e3', '#cc3333', '#fac832', '#4caf50', '#3393bd', '#9b27b0', '#fda4b8'],
(newColor) => {
this.SetDefaultColor (newColor, false);
}
);
if (this.gridDisplaySection !== null) {
this.gridDisplaySection.Init (this.settings.showGrid, (showGrid) => {
this.settings.showGrid = showGrid;
callbacks.onGridDisplayChange ();
});
}
this.edgeDisplaySection.Init (
this.settings.showEdges,
this.settings.edgeColor,
this.settings.edgeThreshold,
{
onShowEdgesChange : (showEdges) => {
this.settings.showEdges = showEdges;
callbacks.onEdgeDisplayChange ();
},
onEdgeColorChange : (edgeColor) => {
this.settings.edgeColor = edgeColor;
callbacks.onEdgeDisplayChange ();
},
onEdgeThresholdChange : (edgeThreshold) => {
this.settings.edgeThreshold = edgeThreshold;
callbacks.onEdgeDisplayChange ();
}
}
);
this.themeSection.Init (this.settings.themeId, (themeId) => {
this.settings.themeId = themeId;
if (themeId === Theme.Light) {
this.SetBackgroundColor (new Color (255, 255, 255), true);
this.SetDefaultColor (new Color (200, 200, 200), true);
} else if (themeId === Theme.Dark) {
this.SetBackgroundColor (new Color (42, 43, 46), true);
this.SetDefaultColor (new Color (200, 200, 200), true);
}
callbacks.onThemeChange ();
});
}
UpdateSettings (hasDefaultMaterial)
{
this.defaultColorSection.Show (hasDefaultMaterial);
this.Resize ();
}
SetBackgroundColor (color, setInput)
{
this.settings.backgroundColor = color;
if (setInput) {
this.backgroundColorSection.Update (color);
} else {
this.callbacks.onBackgroundColorChange ();
}
}
SetDefaultColor (color, setInput)
{
this.settings.defaultColor = color;
if (setInput) {
this.defaultColorSection.Update (color);
} else {
this.callbacks.onDefaultColorChange ();
}
}
ResetToDefaults ()
{
let defaultSettings = new Settings ();
this.settings.backgroundColor = defaultSettings.backgroundColor;
this.settings.defaultColor = defaultSettings.defaultColor;
this.settings.showGrid = defaultSettings.showGrid;
this.settings.showEdges = defaultSettings.showEdges;
this.settings.edgeColor = defaultSettings.edgeColor;
this.settings.edgeThreshold = defaultSettings.edgeThreshold;
this.settings.themeId = defaultSettings.themeId;
this.backgroundColorSection.Update (defaultSettings.backgroundColor);
this.defaultColorSection.Update (defaultSettings.defaultColor);
if (this.gridDisplaySection !== null) {
this.gridDisplaySection.Update (defaultSettings.showGrid);
}
this.edgeDisplaySection.Update (defaultSettings.showEdges, defaultSettings.edgeColor, defaultSettings.edgeThreshold);
this.themeSection.Update (defaultSettings.themeId);
if (this.gridDisplaySection !== null) {
this.callbacks.onGridDisplayChange ();
}
this.callbacks.onThemeChange ();
}
Resize ()
{
let titleHeight = GetDomElementOuterHeight (this.titleDiv);
let resetButtonHeight = GetDomElementOuterHeight (this.resetToDefaultsButton);
let height = this.parentDiv.offsetHeight;
SetDomElementOuterHeight (this.sectionsDiv, height - titleHeight - resetButtonHeight);
}
}