Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing windows resolution scale messes up positioning? #341

Closed
ItsVoltz opened this issue Sep 20, 2021 · 32 comments
Closed

Changing windows resolution scale messes up positioning? #341

ItsVoltz opened this issue Sep 20, 2021 · 32 comments

Comments

@ItsVoltz
Copy link

With normal scaling
iuh4sVX

With 125% scaling:
E0ikIsC

However its the button positioning with the hardcoded buttonWidth for the two buttons together, is there a better way to dynamically align two buttons to center next to eachother?

			g.Custom(func() { // centered buttons
				width, _ := g.GetAvailableRegion()
				buttonWidth := float32(295)

				g.Row(
					g.Dummy(width/2-buttonWidth/2, 0),

					g.Button("Login").Size(136, 25).OnClick(cl.login),
					g.Button("Exit").Size(136, 25).OnClick(cl.exit),
				).Build()
			}),
@AllenDang
Copy link
Owner

@ItsVoltz Maybe giu.Align(...) is the thing you are looking for?

@ItsVoltz
Copy link
Author

ItsVoltz commented Sep 20, 2021

@ItsVoltz Maybe giu.Align(...) is the thing you are looking for?

I use align however is there a way to align two buttons in a row perfectly? when I try it just aligns the first one to the center then the second is off of the correctly centered button

Here is how it looks when I try to align it:
onM1u7B

Code:

			g.Align(g.AlignCenter).To(
				g.Row(
					g.Button("Login").Size(136, 25).OnClick(cl.login),
					g.Button("Exit").Size(136, 25).OnClick(cl.exit),
					),
				),

@AllenDang
Copy link
Owner

@gucio321 We may need to calcuate the row width here?

@AllenDang
Copy link
Owner

@ItsVoltz For now, you need to use giu.Dummy and calculate it's width based on the width of the two buttons.

@gucio321
Copy link
Collaborator

image

yep, @AllenDang It's a kind of bug in AlignmentSetter
I'll take a look

@ItsVoltz maybe try the following for now:

			g.Custom(func() { // centered buttons
				width, _ := g.GetAvailableRegion()
                                spacing := GetItemSpacing()
                                buttonW := (width - spacing)/2

				g.Row(
					g.Button("Login").Size(buttonW, 25).OnClick(cl.login),
					g.Button("Exit").Size(buttonW, 25).OnClick(cl.exit),
				).Build()
			}),

gucio321 added a commit to gucio321/giu that referenced this issue Sep 20, 2021
…Layout

added EXPERIMENTAL, public method GetWidgetWidth, which calculates a width of widget.

(related with AllenDang#341)
gucio321 added a commit to gucio321/giu that referenced this issue Sep 20, 2021
…Layout

added EXPERIMENTAL, public method GetWidgetWidth, which calculates a width of widget.

(related with AllenDang#341)
@ItsVoltz
Copy link
Author

image

yep, @AllenDang It's a kind of bug in AlignmentSetter
I'll take a look

@ItsVoltz maybe try the following for now:

			g.Custom(func() { // centered buttons
				width, _ := g.GetAvailableRegion()
                                spacing := GetItemSpacing()
                                buttonW := (width - spacing)/2

				g.Row(
					g.Button("Login").Size(buttonW, 25).OnClick(cl.login),
					g.Button("Exit").Size(buttonW, 25).OnClick(cl.exit),
				).Build()
			}),

See it works however not how I want as I don;t have the inputs span across the entire width:
image

@gucio321
Copy link
Collaborator

@ItsVoltz it should be fixed in #343 (align setter will work)

@ItsVoltz
Copy link
Author

ItsVoltz commented Sep 25, 2021

@ItsVoltz it should be fixed in #343 (align setter will work)

Does not work:

			g.Align(g.AlignCenter).To(
				g.Row(
					g.Button("Login").Size(136, 25).OnClick(cl.login),
					g.Button("Exit").Size(136, 25).OnClick(cl.exit)),
				),

@AllenDang
Copy link
Owner

@ItsVoltz The PR is just merged, can you make sure you are running the newest code from master branch?

@ItsVoltz
Copy link
Author

@ItsVoltz The PR is just merged, can you make sure you are running the newest code from master branch?

I am

@AllenDang
Copy link
Owner

@gucio321 Seems this issue still there.

@gucio321
Copy link
Collaborator

gucio321 commented Sep 25, 2021

@ItsVoltz could you try go get -u github.com/AllenDang/giu@36465fb9879a6ec167166bf35b66408b34150ed7? (sometimes go get -u repo@master doesn't use the latest commit)
I think that aligning a RowWidget should work:
image

@ItsVoltz
Copy link
Author

ItsVoltz commented Sep 25, 2021

@ItsVoltz could you try go get -u github.com/AllenDang/giu@36465fb9879a6ec167166bf35b66408b34150ed7? (sometimes go get -u repo@master doesn't use the latest commit)
I think that aligning a RowWidget should work:
image

That worked thank you!, all though I have come across a bug with clicks registering on these row aligned buttons, the first button works fine however clicks on the second one seem to work sometimes,

@ItsVoltz
Copy link
Author

ItsVoltz commented Sep 25, 2021

Also, another bug is if you are using align unless I actually use a g.Dummy(0, 0) in a row with the widget it doesn't correctly align it is off some pixels. EDIT: nvm it is still off some that was my solution before however it does not seem to work anymore

@gucio321
Copy link
Collaborator

gucio321 commented Sep 25, 2021

That worked thank you!, all though I have come across a bug with clicks registering on these row aligned buttons, the first button works fine however clicks on the second one seem to work sometimes,

that's very strange, but right, I can reproduce.
EDIT: seems like it happens only for buttons in row

@gucio321
Copy link
Collaborator

gucio321 commented Sep 25, 2021

@AllenDang I got an idea, but it it may be reallly experimanetal:
to measure widget size:

  • get MasterWindowSize
  • render widgets OUT OF WINDOW BOUNDS (to avoid user interaction with them)
  • measure widgets size

what do you think about it?
EDIT:
ok, it will not work, because of the fact, that I'm building widgets inside of WindowWidget's layout so the size of the window will be automatically changed?...
Does anyone has any idea how to render widgets and prevent user from interaction with them?
I see only this: ocornut/imgui#3714 (comment)

@gucio321
Copy link
Collaborator

hmm, in the other comment of discussion on upstream issue, I can see this:

  • using ImDrawListSplitter with two channels, select second channel, after drawing select to first channel but do not merge splitter back, also ImDrawList vertex pointer can be moved back to reuse vertices used by "invisible" widget.

I'll investigate if it can be used more evectively.

@gucio321
Copy link
Collaborator

@AllenDang seems like ImDrawListSplitter isn't implemented in imgui-go yet. could you take a look on it (as I'm not a C guy, I can't sadly do it myself)

@AllenDang
Copy link
Owner

@gucio321 Sure, let me do it.

@AllenDang
Copy link
Owner

AllenDang commented Sep 26, 2021

@gucio321 Frankly, I think we should hold Align until upstream finish measure widget before it is actually being built. Otherwise, a large refinement will occur in future, which leads to a waste of time for now. I've been experienced this on DPI awareness, at that moment I spent a lot of time to implement it and for now the code are totally useless.

And another thing I'm waiting for is docking.

@ItsVoltz
Copy link
Author

That worked thank you!, all though I have come across a bug with clicks registering on these row aligned buttons, the first button works fine however clicks on the second one seem to work sometimes,

that's very strange, but right, I can reproduce.
EDIT: seems like it happens only for buttons in row

Any idea on fix for the buttons in a row align

@gucio321
Copy link
Collaborator

Any idea on fix for the buttons in a row align

well, the problem is more complex, than I thought.
This isn't a bug only in case of buttons in row. It is present for all clickable widgets. The reason is, that Align builts one widget two times (invisible to measure width an visible - aligned). The real issue is, that the user is able to interact with this invisible button so it causes clicking issue described above.

So, @ItsVoltz ofc there is a solution (something like I described in #340 ) - manually align your buttons.
if you know them's width:

const button1W, button2W = 100, 80
// ...
giu.Custom(func() {
      availableW, _ := giu.GetAvailableRegion()
      spacingW, _ := giu.GetItemSpacing()
      giu.Dummy(availableW-(button1W+button2W+spacingW), 0).Build()
      giu.Row(
            giu.Button("my first button").Size(button1W, 20),
            giu.Button("my second button").Size(button2W, 20),
      ).Build()
}),

@gucio321
Copy link
Collaborator

@gucio321 Frankly, I think we should hold Align until upstream finish measure widget before it is actually being built. Otherwise, a large refinement will occur in future, which leads to a waste of time for now. I've been experienced this on DPI awareness, at that moment I spent a lot of time to implement it and for now the code are totally useless.

And another thing I'm waiting for is docking.

@AllenDang as far as I understand measure widget before it is actually being built will mean

We are currently missing - and we will eventually implement - a "null" layout mode which will allow submitting items for size measurement.

Originally posted in ocornut/imgui#3714 (comment)

so It will not be so large refinement for giu - just minor edit for GetWidgetWidth method (and removal of tone comments 😀).

The other thing is that imgui-go currently misses ImDrawListSplitter and giu alignment setter is probably unable to work with current implementation of widget measurement (rendering with 0 alpha).

@AllenDang
Copy link
Owner

@gucio321 Ok, I got cold these days, may need some time to implement ImDrawListSplitter... Sorry to the delay.

@gucio321
Copy link
Collaborator

well, I hope, that this code:

        {

            ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.

            ImDrawList* list =  ImGui::GetWindowDrawList();

            struct foo {
                    bool btn() { return ImGui::Button("btn",ImVec2{200,20}); };
            } btn;

            ImVec2 start = ImGui::GetCursorPos();
            ImVec2 size;

            list->ChannelsSplit(2);

            list->ChannelsSetCurrent(0);
            //ImGui::PushID("someotherid");


            if (btn.btn() ) {
                    std::cout << "btn 1 (invisible) pressed\n";
            };

            size = ImGui::GetItemRectSize();
            ImVec2 available = ImGui::GetContentRegionMax();
            start.x = (available.x-size.x)/2;


            //ImGui::PopID();

            ImGui::SetCursorPos(start);

            list->ChannelsSetCurrent(1);
            if (ImGui::BeginChild("measure") ){
            if (btn.btn()){
                    std::cout << "btn 1 pressed\n";
            };
            }
            ImGui::EndChild();
            list->ChannelsMerge();

            ImGui::End();
        }

despite it doesn't work like I expected, in connection with PushDisabled will finally work and we'll have these bugs fixed (clicking bug from here and double-pasting from #340 )

@gucio321
Copy link
Collaborator

gucio321 commented Sep 27, 2021

wow, @AllenDang it seems to work without list splitter for now:

        {

            ImGui::Begin("Hello, world!");                          // Create a window called "Hello, world!" and append into it.

            //ImDrawList* list =  ImGui::GetWindowDrawList();

            struct button {
                    bool Build() { return ImGui::Button("btn",ImVec2{200,20}); };
            } mybutton;

            ImVec2 start = ImGui::GetCursorPos();
            ImVec2 size;

            //list->ChannelsSplit(2);

            //list->ChannelsSetCurrent(0);

            if (mybutton.Build() ) {
                    std::cout << "btn 1 (invisible) pressed\n";
            };

            size = ImGui::GetItemRectSize();
            ImVec2 available = ImGui::GetContentRegionMax();
            start.x = (available.x-size.x)/2;

            ImGui::SetCursorPos(start);

            //list->ChannelsSetCurrent(1);
            if (ImGui::BeginChild("measure") ){
                if (mybutton.Build()){
                    std::cout << "btn 1 pressed\n";
                };
            }
            ImGui::EndChild();
            //list->ChannelsMerge();

            ImGui::End();
        }

I'll try to implement to go and tell you if it works.

IMO the problem is with the rendering order. if we put our centered button in a child, it works.
Is there any way to render invisible btn in background? I see GetForeground/BackgroundDrawList...

@AllenDang
Copy link
Owner

@gucio321 The best place to ask this question is raise an issue in imgui's issue list.

@AllenDang
Copy link
Owner

AllenDang commented Sep 27, 2021

@gucio321 After your implementation, it's not only Align but also a whole Flex-box like layout mechanism becomes possible. Keep going man! It's a huge step.

@gucio321
Copy link
Collaborator

I opened an issue in upstream: ocornut/imgui#4588
If there will not be any better idea, I'll try with ChildWidget, but I'll need to investigate some child's parameters, because in C imgui, child doesn't have any style/bg color and is exactly the same size as widget inside of it. In giu child doesn't look so...

@gucio321
Copy link
Collaborator

hmm, @AllenDang so it seems that there is no solution right now, So I'm going to try with ChildWidget until upstream issue gets fixed.
But I cannot figure out, why imgui-go's implementation of child doesn't work like this in DearImGui...
lets try this code:

// Here's some code anyone can copy and paste to reproduce your issue
        {
            ImGui::Begin("Hello, world!");

            struct foo {
                    bool btn() { return ImGui::Button("btn",ImVec2{200,20}); };
            } btn;

            ImVec2 start = ImGui::GetCursorPos();
            ImVec2 size;

            ImGui::PushID("someotherid");
            ImGui::PushStyleVar(ImGuiStyleVar_Alpha, 0);
            if (btn.btn() ) {
                    std::cout << "btn 1 (invisible) pressed\n";
            };
            ImGui::PopStyleVar();
            ImGui::PopID();

            size = ImGui::GetItemRectSize();
            ImVec2 available = ImGui::GetContentRegionMax();
            start.x = (available.x-size.x)/2;
            ImGui::SetCursorPos(start);

            if (ImGui::BeginChild("container")) {
                if (btn.btn()){
                    std::cout << "btn 1 pressed\n";
                }
            }
            ImGui::EndChild();

            ImGui::End();
        }

the child widget is here invisible at all
in giu, ChildWIdget has a gray background and is always visible
e.g.:

giu.Child().Layout(giu.Button("btn"))

wil be like:
image

do you have any idea? PushStyle?...

@AllenDang
Copy link
Owner

@gucio321 I just back to work, let me do some digging, will feedback to you soon.

@gucio321
Copy link
Collaborator

gucio321 commented May 9, 2023

The original problem is fixed. I'm going to close this, but @ItsVoltz don't hesitate to open a new issue if you still experience any problems!

@gucio321 gucio321 closed this as completed May 9, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants