-
Notifications
You must be signed in to change notification settings - Fork 246
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
Add AnchorPos struct and functions #252
Conversation
In this second commit, I added:
Following the code sample shared above, I updated padding to func drawRectangles(win *pixelgl.Window) {
imd := imdraw.New(nil)
for anchor, vect := range dotsPos {
rect := pixel.R(vect.X, vect.Y, vect.X + rectWidth, vect.Y + rectHeight)
rect.AnchorTo(anchor)
drawRect(imd, rect, colornames.Gray)
}
imd.Draw(win)
} Which gives: Note that labels are not correctly positioned since To be discussed: Maybe |
Concerning I'm not able to update the text position in any way: I tried to change its edit: hmm, just got it, I have to work with the transformation matrix when calling |
I finally fixed this by applying a matrix transformation instead of trying to move a text with a So in this third commit, I added:
Following the code defined in first comment, I removed the squares and blue dots, updated padding to func drawLabels(win *pixelgl.Window) {
basicAtlas := text.NewAtlas(basicfont.Face7x13, text.ASCII)
for anchor, vect := range dotsPos {
basicTxt := text.New(vect, basicAtlas)
basicTxt.Color = colornames.Gray
fmt.Fprintln(basicTxt, anchor.String())
basicTxt.Draw(win, pixel.IM.Aligned(basicTxt.Bounds(), anchor))
}
} which gives: |
Well, I drop the idea of adding a matrix transformation since it only applies a translation and Instead, I modified I also transformed The new func drawLabels(win *pixelgl.Window) {
const scale float64 = 2
basicAtlas := text.NewAtlas(basicfont.Face7x13, text.ASCII)
for anchor, vect := range dotsPos {
basicTxt := text.New(vect, basicAtlas)
basicTxt.Color = colornames.Gray
fmt.Fprintln(basicTxt, anchor.String())
alignment := basicTxt.Bounds().AnchorPos(anchor).Scaled(scale)
basicTxt.Draw(win, pixel.IM.Scaled(basicTxt.Orig, scale).Moved(alignment))
}
} |
Hey, this is aiming towards something very useful, anchoring is pretty hard right now. But, I’m skeptical about the necessity of the AnchorPos struct. What about adding a |
No tests? |
I think it's less intuitive. With Is there a specific reason to avoid the edit:
I prefer to get feedback before, many things may change my the meantime. ;) I will also update documentation as well when this PR will be in a stable state. |
My reason for avoiding But I see your point. Though I also think that a simple documentation comment can clear up a lot. However, if I were to go for a new, special type, I’d probably just go for: type Anchor Vec Which makes it clear that |
That makes sense. This last commit makes Anchor a type Vec instead of a struct. And here is the example code: func drawRectanglesAndDots(win *pixelgl.Window) {
imd := imdraw.New(nil)
for anchor, vect := range dotsPos {
rect := pixel.R(vect.X, vect.Y, vect.X + rectWidth, vect.Y + rectHeight).AlignedTo(anchor)
drawRect(imd, rect, colornames.Gray)
drawDot(imd, vect, colornames.Red)
}
imd.Draw(win)
}
func drawLabels(win *pixelgl.Window) {
const scale float64 = 2
basicAtlas := text.NewAtlas(basicfont.Face7x13, text.ASCII)
for anchor, vect := range dotsPos {
basicTxt := text.New(vect, basicAtlas)
basicTxt.Color = colornames.Blue
fmt.Fprintln(basicTxt, anchor.String())
offset := basicTxt.Bounds().AnchorPos(anchor).Scaled(scale)
basicTxt.Draw(win, pixel.IM.Scaled(basicTxt.Orig, scale).Moved(offset))
}
} I'm particularly happy with the elegance of |
Ok, I'm trying to do the same with I added the anchor property in anchor pixel.Anchor and created a new Text function that simply updates this property and returns the Text to allow chained expressions: func (txt *Text) AlignedTo(anchor pixel.Anchor) *Text {
txt.anchor = anchor
return txt
} Then in if matrix != txt.mat {
txt.mat = matrix
txt.dirty = true
} else {
offset := txt.Bounds().AnchorPos(txt.anchor)
txt.mat = txt.mat.Moved(offset)
} As you can see for now I only apply the transformation if no matrix is passed. So that works for this: basicTxt.AlignedTo(anchor).Draw(win, pixel.IM) But the basicTxt.AlignedTo(anchor).Draw(win, pixel.IM.Scaled(basicTxt.Orig, scale)) I'm lack of knowledge in affine transformations to update the matrix by moving it to offset defined above. Any help? |
Bingo! What I was looking for was the func drawLabels(win *pixelgl.Window) {
const scale float64 = 2
basicAtlas := text.NewAtlas(basicfont.Face7x13, text.ASCII)
for anchor, vect := range dotsPos {
basicTxt := text.New(vect, basicAtlas)
basicTxt.Color = colornames.Blue
fmt.Fprintln(basicTxt, anchor.String())
basicTxt.AlignedTo(anchor).Draw(win, pixel.IM.Scaled(basicTxt.Orig, scale))
}
} At this point I'm beginning to be satisfied of this PR, do you have other feedback to do? If not I can start to add unit tests and documentation. |
I just added 2 more commits: The first one fix the anchors positions, that was inverted. Indeed, if the red dot is the origin, by The second commit adds a new function:
Since I already use my Pixel fork for my personal project, I can say that it is useful in many cases. |
last commit: fix anchor position on some fonts (see #255) |
Any updates? Useful stuff in here, I would like to use it for a UI system Im currently building. |
@niklas-karlsson @roipoussiere Sorry for the long delay, been pretty busy at day job. I'll take a look at this one as well. |
This PR adds the concept of anchors to align elements.
It adds:
type Anchor
: a vector used to define anchors, such asCenter
,Top
,TopRight
, etc.;func (Anchor) String() string
: returns the string representation of an anchor.;func (*Rect) AnchorPos(anchor Anchor) Vec
: returns theabsoluteposition of the given anchor of the Rect.;edit:func (*Rect) AnchorTo(Anchor)
: updates the Rect position to align it on the given anchor.func (Rect) AlignedTo(Anchor) Rect
: returns the rect moved to be aligned on the given anchor.edit:func (Matrix) Aligned(Rect, anchorPos AnchorPos) Matrix
: moves everything to align the given rectangle on the given anchor position.func (*Text) AlignedTo(pixel.Anchor) *Text
: returns the text moved by the given anchor.func (Anchor) Opposite() Anchor
: returns the opposite position of the anchor (ie. Top -> Bottom; BottomLeft -> TopRight, etc.).Example code
edit: Update with last modifications.
Result
More to come
edit: done!
The modifications added in this first commit are required for other functions that I plan to add as well in this PR, namedAnchorTo
:-func (r *Rect) AnchorTo(anchor AnchorPos)
: updates the Rect position to align it on the given anchor.-func (r *Text) AnchorTo(anchor AnchorPos)
: updates the Text position to align it on the given anchor.- etc. At this point it's easy to add implementation for many other objects (Circle, Image, etc.)Example usage:Here,basicTxt
will be centered relative to thevect
position. WithAnchorPos.Left
, it will be centered verticaly but not horizontally, etc.This is helpful to position and align elements.I would like to get your feedback before to continue. ;)