Commit 374fe636 authored by Gerschel's avatar Gerschel
Browse files

Squashed commit of the following:

commit b030b67ad005bfe29bcda692238a00042dcae816
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Wed Feb 8 16:38:56 2023 -0800

    styling adjustements

commit 80a2acb0230dd77489b0eb466f2efe827a053f6d
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Wed Feb 8 10:49:47 2023 -0800

    badge indicator toggles visibility by selection

commit 898922e025a6422ac947fb45c1fa4f1109882f0a
Merge: 745382a0 31bbfa72
Author: Gerschel <9631031+Gerschel@users.noreply.github.com>
Date:   Wed Feb 8 08:35:26 2023 -0800

    Merge pull request #1 from w-e-w/Rounding-Method

    Rounding Method

commit 31bbfa729a15ef35fa1f905345d3ba2b17b26ab9
Author: w-e-w <40751091+w-e-w@users.noreply.github.com>
Date:   Wed Feb 8 19:41:45 2023 +0900

    use switch

commit 85dbe511c33521d3ac62224bf0e0f3a48194ce63
Author: w-e-w <40751091+w-e-w@users.noreply.github.com>
Date:   Wed Feb 8 16:47:52 2023 +0900

    Rounding Method

commit 745382a0f4b8d16241545a3460d5206915959255
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 21:19:20 2023 -0800

    default set to round

commit 728579c618af30ec98a5af0991bd3f28bdaca399
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 21:17:03 2023 -0800

    cleaned some commented code out; added indicator

commit 5b288c24a1edd8a5c2f35214b9634316d05b8dae
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 18:19:00 2023 -0800

    needs cleaning; attempt at rounding

commit d9f18ae92b929576b0b8c5f1ef8b3b38e441e381
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 15:46:25 2023 -0800

    add rounding option in setting for aspect ratio

commit af22106802c9e42205649e4c71c23fcf5b8c62f6
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 13:18:45 2023 -0800

    added some ratios, sorted ratios by commonality

commit 11e2fba73cffe8cdbf4cd0860641b94428ca0e74
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Tue Feb 7 10:46:53 2023 -0800

    snaps to mulitples of 8 and along ratio

commit fa00387e07460b10ee82671a1bfa8687e00ee60b
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 14:54:59 2023 -0800

    updated slidercomponentcontroller

commit 8059bc111c3e2d1edb3314e05ab21b65120fa1dd
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 14:29:11 2023 -0800

    added step size adjustment on number field

commit 641157b9f27a874a24ee7b0a854a092e9eac3eec
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 14:12:03 2023 -0800

    added return step size to default when ratio is disabled

commit 5fb75ad28f2476f36100ec93922a8199adbd2a68
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 14:09:34 2023 -0800

    added step size adjustment

commit e33532883bc4709cd41c3775cbb646d1d5ab0584
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 11:56:15 2023 -0800

    adjusted dropdown size, padding, text-align

commit 81937329cee77f466c5a5b23c268d0c810128f84
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 11:39:57 2023 -0800

    added positioning and styling

commit 86eb4583782d92880a9a113a54ffbac9d92f3753
Author: Gerschel <Gerschel_Payne@hotmail.com>
Date:   Mon Feb 6 08:54:45 2023 -0800

    fix typo in defaults; added preventDefault in event
parent 5d483bf3
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -189,6 +189,8 @@ class SliderComponentController {
    }
    eventHandler() {
        this.element.dispatchEvent(new Event("input"));
        this.childNumField.dispatchEvent(new Event("input"));
        this.childRangeField.dispatchEvent(new Event("input"));
    }
    setVal(text) {
        this.updateVal(text);
+152 −12
Original line number Diff line number Diff line
class AspectRatioSliderController {
    constructor(widthSlider, heightSlider, ratioSource) {
    constructor(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod) {
        //References
        this.widthSlider = new SliderComponentController(widthSlider);
        this.heightSlider = new SliderComponentController(heightSlider);
        this.ratioSource = new DropdownComponentController(ratioSource);
        this.widthSlider.childRangeField.addEventListener("change", () => this.resize("width"));
        this.widthSlider.childNumField.addEventListener("change", () => this.resize("width"));
        this.heightSlider.childRangeField.addEventListener("change", () => this.resize("height"));
        this.heightSlider.childNumField.addEventListener("change", () => this.resize("height"));
        this.roundingSource = new CheckboxComponentController(roundingSource);
        this.roundingMethod = new RadioComponentController(roundingMethod);
        this.roundingIndicatorBadge = document.createElement("div");
        // Badge implementation
        this.roundingIndicatorBadge.innerText = "📐";
        this.roundingIndicatorBadge.classList.add("rounding-badge");
        this.ratioSource.element.appendChild(this.roundingIndicatorBadge);
        // Check initial value of ratioSource to set badge visbility
        let initialRatio = this.ratioSource.getVal();
        if (!initialRatio.includes(":")) {
            this.roundingIndicatorBadge.style.display = "none";
        }
        //Adjust badge icon if rounding is on
        if (this.roundingSource.getVal()) {
            this.roundingIndicatorBadge.classList.add("active");
            this.roundingIndicatorBadge.innerText = "⚠️";
        }
        //Make badge clickable to toggle setting
        this.roundingIndicatorBadge.addEventListener("click", () => {
            this.roundingSource.setVal(!this.roundingSource.getVal());
        });
        //Make rounding setting toggle badge text and style if setting changes
        this.roundingSource.child.addEventListener("change", () => {
            if (this.roundingSource.getVal()) {
                this.roundingIndicatorBadge.classList.add("active");
                this.roundingIndicatorBadge.innerText = "⚠️";
            }
            else {
                this.roundingIndicatorBadge.classList.remove("active");
                this.roundingIndicatorBadge.innerText = "📐";
            }
            this.adjustStepSize();
        });
        //Other event listeners
        this.widthSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); });
        this.widthSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("width"); });
        this.heightSlider.childRangeField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); });
        this.heightSlider.childNumField.addEventListener("change", (e) => { e.preventDefault(); this.resize("height"); });
        this.ratioSource.childSelector.addEventListener("change", (e) => {
            e.preventDefault();
            //Check and toggle display of badge conditionally on dropdown selection
            if (!this.ratioSource.getVal().includes(":")) {
                this.roundingIndicatorBadge.style.display = 'none';
            }
            else {
                this.roundingIndicatorBadge.style.display = 'block';
            }
            this.adjustStepSize();
        });
    }
    resize(dimension) {
        //For moving slider or number field
        let val = this.ratioSource.getVal();
        if (!val.includes(":")) {
            return;
@@ -16,26 +63,119 @@ class AspectRatioSliderController {
        let [width, height] = val.split(":").map(Number);
        let ratio = width / height;
        if (dimension == 'width') {
            this.heightSlider.setVal(Math.round(parseFloat(this.widthSlider.getVal()) / ratio).toString());
            let newHeight = parseInt(this.widthSlider.getVal()) / ratio;
            if (this.roundingSource.getVal()) {
                switch (this.roundingMethod.getVal()) {
                    case 'Round':
                        newHeight = Math.round(newHeight / 8) * 8;
                        break;
                    case 'Ceiling':
                        newHeight = Math.ceil(newHeight / 8) * 8;
                        break;
                    case 'Floor':
                        newHeight = Math.floor(newHeight / 8) * 8;
                        break;
                }
            }
            this.heightSlider.setVal(newHeight.toString());
        }
        else if (dimension == "height") {
            this.widthSlider.setVal(Math.round(parseFloat(this.heightSlider.getVal()) * ratio).toString());
            let newWidth = parseInt(this.heightSlider.getVal()) * ratio;
            if (this.roundingSource.getVal()) {
                switch (this.roundingMethod.getVal()) {
                    case 'Round':
                        newWidth = Math.round(newWidth / 8) * 8;
                        break;
                    case 'Ceiling':
                        newWidth = Math.ceil(newWidth / 8) * 8;
                        break;
                    case 'Floor':
                        newWidth = Math.floor(newWidth / 8) * 8;
                        break;
                }
            }
            this.widthSlider.setVal(newWidth.toString());
        }
    }
    adjustStepSize() {
        /* Sets scales/precision/rounding steps;*/
        let val = this.ratioSource.getVal();
        if (!val.includes(":")) {
            //If ratio unlocked
            this.widthSlider.childRangeField.step = "8";
            this.widthSlider.childRangeField.min = "64";
            this.widthSlider.childNumField.step = "8";
            this.widthSlider.childNumField.min = "64";
            this.heightSlider.childRangeField.step = "8";
            this.heightSlider.childRangeField.min = "64";
            this.heightSlider.childNumField.step = "8";
            this.heightSlider.childNumField.min = "64";
            return;
        }
        //Format string and calculate step sizes
        let [width, height] = val.split(":").map(Number);
        let decimalPlaces = (width.toString().split(".")[1] || []).length;
        //keep upto 6 decimal points of precision of ratio
        //euclidean gcd does not support floats, so we scale it up 
        decimalPlaces = decimalPlaces > 6 ? 6 : decimalPlaces;
        let gcd = this.gcd(width * 10 ** decimalPlaces, height * 10 ** decimalPlaces) / 10 ** decimalPlaces;
        let stepSize = 8 * height / gcd;
        let stepSizeOther = 8 * width / gcd;
        if (this.roundingSource.getVal()) {
            //If rounding is on set/keep default stepsizes
            this.widthSlider.childRangeField.step = "8";
            this.widthSlider.childRangeField.min = "64";
            this.widthSlider.childNumField.step = "8";
            this.widthSlider.childNumField.min = "64";
            this.heightSlider.childRangeField.step = "8";
            this.heightSlider.childRangeField.min = "64";
            this.heightSlider.childNumField.step = "8";
            this.heightSlider.childNumField.min = "64";
        }
        else {
            //if rounding is off, set step sizes so they enforce snapping
            //min is changed, because it offsets snap positions
            this.widthSlider.childRangeField.step = stepSizeOther.toString();
            this.widthSlider.childRangeField.min = stepSizeOther.toString();
            this.widthSlider.childNumField.step = stepSizeOther.toString();
            this.widthSlider.childNumField.min = stepSizeOther.toString();
            this.heightSlider.childRangeField.step = stepSize.toString();
            this.heightSlider.childRangeField.min = stepSize.toString();
            this.heightSlider.childNumField.step = stepSize.toString();
            this.heightSlider.childNumField.min = stepSize.toString();
        }
        let currentWidth = parseInt(this.widthSlider.getVal());
        //Rounding treated kinda like pythons divmod
        let stepsTaken = Math.round(currentWidth / stepSizeOther);
        //this snaps it to closest rule matches (rules being html step points, and ratio)
        let newWidth = stepsTaken * stepSizeOther;
        this.widthSlider.setVal(newWidth.toString());
        this.heightSlider.setVal(Math.round(newWidth / (width / height)).toString());
    }
    gcd(a, b) {
        //euclidean gcd
        if (b === 0) {
            return a;
        }
        return this.gcd(b, a % b);
    }
    static observeStartup(widthSliderId, heightSliderId, ratioSourceId) {
    static observeStartup(widthSliderId, heightSliderId, ratioSourceId, roundingSourceId, roundingMethodId) {
        let observer = new MutationObserver(() => {
            let widthSlider = document.querySelector("gradio-app").shadowRoot.getElementById(widthSliderId);
            let heightSlider = document.querySelector("gradio-app").shadowRoot.getElementById(heightSliderId);
            let ratioSource = document.querySelector("gradio-app").shadowRoot.getElementById(ratioSourceId);
            if (widthSlider && heightSlider && ratioSource) {
            let roundingSource = document.querySelector("gradio-app").shadowRoot.getElementById(roundingSourceId);
            let roundingMethod = document.querySelector("gradio-app").shadowRoot.getElementById(roundingMethodId);
            if (widthSlider && heightSlider && ratioSource && roundingSource && roundingMethod) {
                observer.disconnect();
                new AspectRatioSliderController(widthSlider, heightSlider, ratioSource);
                new AspectRatioSliderController(widthSlider, heightSlider, ratioSource, roundingSource, roundingMethod);
            }
        });
        observer.observe(gradioApp(), { childList: true, subtree: true });
    }
}
document.addEventListener("DOMContentLoaded", () => {
    AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio");
    AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio");
    //Register mutation observer for self start-up;
    AspectRatioSliderController.observeStartup("txt2img_width", "txt2img_height", "txt2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method");
    AspectRatioSliderController.observeStartup("img2img_width", "img2img_height", "img2img_ratio", "setting_aspect_ratios_rounding", "setting_aspect_ratios_rounding_method");
});
+12 −5
Original line number Diff line number Diff line
@@ -140,16 +140,21 @@ ui_reorder_categories = [
]

aspect_ratio_defaults = [
    "🔓"
    "🔓",
    "1:1",
    "1:2",
    "2:1",
    "2:3",
    "3:2",
    "4:3",
    "5:4",
    "9:16",
    "16:9",
    "9:16",
    "1.85:1",
    "2.35:1",
    "2.39:1",
    "2.40:1",
    "21:9",
    "1.375:1",
    "1.66:1",
    "1.75:1"
]

cmd_opts.disable_extension_access = (cmd_opts.share or cmd_opts.listen or cmd_opts.server_name) and not cmd_opts.enable_insecure_extension_access
@@ -469,6 +474,8 @@ options_templates.update(options_section(('ui', "User interface"), {
    "keyedit_precision_extra": OptionInfo(0.05, "Ctrl+up/down precision when editing <extra networks:0.9>", gr.Slider, {"minimum": 0.01, "maximum": 0.2, "step": 0.001}),
    "quicksettings": OptionInfo("sd_model_checkpoint", "Quicksettings list"),
    "ui_reorder": OptionInfo(", ".join(ui_reorder_categories), "txt2img/img2img UI item order"),
    "aspect_ratios_rounding": OptionInfo(True, "Round aspect ratios for more flexibility?", gr.Checkbox),
    "aspect_ratios_rounding_method": OptionInfo("Ceiling", "Aspect ratios rounding method", gr.Radio,{"choices": ["Round", "Ceiling", "Floor"]}),
    "aspect_ratios": OptionInfo(", ".join(aspect_ratio_defaults), "txt2img/img2img aspect ratios"),
    "ui_extra_networks_tab_reorder": OptionInfo("", "Extra networks tab order"),
    "localization": OptionInfo("None", "Localization (requires restart)", gr.Dropdown, lambda: {"choices": ["None"] + list(localization.localizations.keys())}, refresh=lambda: localization.list_localizations(cmd_opts.localizations_dir)),
+6 −4
Original line number Diff line number Diff line
@@ -483,8 +483,9 @@ def create_ui():
                                width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="txt2img_width")
                                height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="txt2img_height")

                            res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn")
                            with gr.Column(elem_id="txt2img_size_toolbox", scale=0):
                                aspect_ratio_dropdown = gr.Dropdown(value="🔓", choices=aspect_ratio_list(), interactive=True, type="value", elem_id="txt2img_ratio", show_label=False, label="Aspect Ratio")
                                res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="txt2img_res_switch_btn")
                            if opts.dimensions_and_batch_together:
                                with gr.Column(elem_id="txt2img_column_batch"):
                                    batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="txt2img_batch_count")
@@ -762,8 +763,9 @@ def create_ui():
                                width = gr.Slider(minimum=64, maximum=2048, step=8, label="Width", value=512, elem_id="img2img_width")
                                height = gr.Slider(minimum=64, maximum=2048, step=8, label="Height", value=512, elem_id="img2img_height")

                            res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
                            with gr.Column(elem_id="img2img_size_toolbox", scale=0):
                                aspect_ratio_dropdown = gr.Dropdown(value="🔓", choices=aspect_ratio_list(), interactive=True, type="value", elem_id="img2img_ratio", show_label=False, label="Aspect Ratio")
                                res_switch_btn = ToolButton(value=switch_values_symbol, elem_id="img2img_res_switch_btn")
                            if opts.dimensions_and_batch_together:
                                with gr.Column(elem_id="img2img_column_batch"):
                                    batch_count = gr.Slider(minimum=1, step=1, label='Batch count', value=1, elem_id="img2img_batch_count")
+46 −0
Original line number Diff line number Diff line
@@ -747,6 +747,52 @@ footer {
    margin-left: 0em;
}

#txt2img_size_toolbox, #img2img_size_toolbox{
    min-width: unset !important;
    gap: 0;
}

#txt2img_ratio, #img2img_ratio {
    padding: 0px;
    min-width: unset;
    max-width: fit-content;
}
#txt2img_ratio select, #img2img_ratio select{
   -o-appearance: none;
   -ms-appearance: none;
   -webkit-appearance: none;
   -moz-appearance: none;
   appearance: none;
   background-image: unset;
   padding-right: unset;
   min-width: 40px;
   max-width: 40px;
   min-height: 40px;
   max-height: 40px;
   line-height: 40px;
   padding: 0;
   text-align: center;
}
.rounding-badge {
  display: inline-block;
  border-radius: 0px;
  background-color: #ccc;
  cursor: pointer;
  position: absolute;
  top: -10px;
  right: -10px;
  width: 20px;
  height: 20px;
  padding: 1px;
  line-height: 16px;
  font-size: 14px;
}

.rounding-badge.active {
  background-color: #007bff;
  border-radius: 50%;
}

.inactive{
    opacity: 0.5;
}