// interior layout is part of doubleLayout. // It creates a second form inside the middle section of the first form. func (fm *fmtag) interiorLayout(eng vu.Eng, s form.Section) *layout { lo := &layout{} w, h := s.Size() iw, ih := int(lin.Round(w, 0)), int(lin.Round(h, 0)) plan := []string{ "pqr", "pqr", "stu", } lo.form = form.New(plan, iw, ih, "gap 5 5") lo.visualize(eng) return lo }
// remCore removes the energy core from the minimap. func (mm *minimap) remCore(gamex, gamez float64) { scale := mm.scale gx, gz := lin.Round(gamex, 0)*scale, lin.Round(gamez, 0)*scale for index, core := range mm.cores { cx, _, cz := core.Location() cx, cz = lin.Round(cx, 0), lin.Round(cz, 0) if cx == gx && cz == gz { core.Dispose(vu.POV) mm.cores = append(mm.cores[:index], mm.cores[index+1:]...) return } } logf("hud.mapOverlay.remCore: failed to remove a core.") }
// Screen applies the camera transform on a 3D point in world space wx, wy, wz // and returns the 2D screen coordinate sx, sy. The window width and height // ww, wh are also needed. Essentially the reverse of the Ray method and // duplicates what is done in the rendering pipeline. func (c *camera) Screen(wx, wy, wz float64, ww, wh int) (sx, sy int) { vec := c.v0.SetS(wx, wy, wz, 1) vec.MultvM(vec, c.vm) // apply view matrix. vec.MultvM(vec, c.pm) // apply projection matrix. clipx := vec.X*0.5/vec.W + 0.5 // convert to range 0:1 clipy := vec.Y*0.5/vec.W + 0.5 // convert to range 0:1 clipz := vec.Z*0.5/vec.W + 0.5 // convert to range 0:1 if clipx < 0 || clipx > 1 || clipy < 0 || clipy > 1 || clipz < 0 || clipz > 1 { return -1, -1 // outside the screen area. } sx = int(lin.Round(clipx*float64(ww), 0)) sy = int(lin.Round(clipy*float64(wh), 0)) return sx, sy }
// resize informs the panel of the size change and updates the visual components // to match the new cell sizes. func (lo *layout) resize(ww, wh int) { lo.form.Resize(ww, wh) for cnt, sect := range lo.form.Sections() { x, y, w, h := sect.Bounds() lo.sects[cnt].SetScale(w, h, 0) lo.sects[cnt].SetLocation(x, y, 0) lo.labels[cnt].SetLocation(x, y, 0) } if lo.lo != nil { w, h := lo.form.Section("e").Size() iw, ih := int(lin.Round(w, 0)), int(lin.Round(h, 0)) offx, offy := lo.form.Section("e").Offset() lo.lo.resizeChild(offx, offy, iw, ih) } }
// Next implements Flow. Look up the direction for the given location // and return it as a unit vector. func (f *flow) Next(atx, aty float64) (dx, dy float64) { gridx, gridy := int(lin.Round(atx, 0)), int(lin.Round(aty, 0)) ir := 0.7071068 // inverse root of 2: 1/math.Sqrt(2) switch f.flowmap[gridx][gridy] { case north: return 0, 1 case ne: return ir, ir case east: return 1, 0 case se: return ir, -ir case south: return 0, -1 case sw: return -ir, -ir case west: return -1, 0 case nw: return -ir, ir } return 0, 0 }
func (s *section) Offset() (x, y float64) { return lin.Round(s.x-s.w*0.5, 0), lin.Round(s.y-s.h*0.5, 0) }
func (s *section) In(x, y int) bool { hw, hh := lin.Round(s.w*0.5, 0), lin.Round(s.h*0.5, 0) fx, fy := float64(x), float64(y) return fx >= s.x-hw && fx <= s.x+hw && fy >= s.y-hh && fy <= s.y+hh }