func (w *TextLine) preDraw(region Region) { if !w.initted { w.initted = true w.texture = gl.GenTexture() w.text = w.next_text w.figureDims() } if w.text != w.next_text { w.text = w.next_text w.figureDims() } gl.PushMatrix() gl.Color3d(0, 0, 0) gl.Begin(gl.QUADS) gl.Vertex2i(region.X, region.Y) gl.Vertex2i(region.X, region.Y+region.Dy) gl.Vertex2i(region.X+region.Dx, region.Y+region.Dy) gl.Vertex2i(region.X+region.Dx, region.Y) gl.End() gl.PushAttrib(gl.TEXTURE_BIT) gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.PushAttrib(gl.COLOR_BUFFER_BIT) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) }
func (w *ImageBox) Draw(region Region) { w.Render_region = region // We check texture == 0 and not active because active only indicates if we // have a texture that we need to free later. It's possible for us to have // a texture that someone else owns. if w.texture == 0 { return } gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.Enable(gl.BLEND) gl.Color4d(w.r, w.g, w.b, w.a) gl.Begin(gl.QUADS) gl.TexCoord2f(0, 0) gl.Vertex2i(region.X, region.Y) gl.TexCoord2f(0, -1) gl.Vertex2i(region.X, region.Y+region.Dy) gl.TexCoord2f(1, -1) gl.Vertex2i(region.X+region.Dx, region.Y+region.Dy) gl.TexCoord2f(1, 0) gl.Vertex2i(region.X+region.Dx, region.Y) gl.End() gl.Disable(gl.TEXTURE_2D) }
func (r Region) PushClipPlanes() { if len(clippers) == 0 { gl.Enable(gl.CLIP_PLANE0) gl.Enable(gl.CLIP_PLANE1) gl.Enable(gl.CLIP_PLANE2) gl.Enable(gl.CLIP_PLANE3) r.setClipPlanes() clippers = append(clippers, r) } else { cur := clippers[len(clippers)-1] clippers = append(clippers, r.Isect(cur)) clippers[len(clippers)-1].setClipPlanes() } }
func (m *Manager) LoadSprite(path string) (*Sprite, error) { // We can't run this during an init() function because it will get queued to // run before the opengl context is created, so we just check here and run // it if we haven't run it before. gen_tex_once.Do(func() { render.Queue(func() { gl.Enable(gl.TEXTURE_2D) error_texture = gl.GenTexture() error_texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) pink := []byte{255, 0, 255, 255} glu.Build2DMipmaps(gl.TEXTURE_2D, 4, 1, 1, gl.RGBA, pink) }) }) path = filepath.Clean(path) err := m.loadSharedSprite(path) if err != nil { return nil, err } var s Sprite m.mutex.Lock() s.shared = m.shared[path] m.mutex.Unlock() s.anim_node = s.shared.anim_start s.state_node = s.shared.state_start return &s, nil }
func RenderAdvanced(x, y, dx, dy, rot float64, flip bool) { if textureList != 0 { var run, op mathgl.Mat4 run.Identity() op.Translation(float32(x), float32(y), 0) run.Multiply(&op) op.Translation(float32(dx/2), float32(dy/2), 0) run.Multiply(&op) op.RotationZ(float32(rot)) run.Multiply(&op) if flip { op.Translation(float32(-dx/2), float32(-dy/2), 0) run.Multiply(&op) op.Scaling(float32(dx), float32(dy), 1) run.Multiply(&op) } else { op.Translation(float32(dx/2), float32(-dy/2), 0) run.Multiply(&op) op.Scaling(float32(-dx), float32(dy), 1) run.Multiply(&op) } gl.PushMatrix() gl.MultMatrixf(&run[0]) gl.Enable(gl.TEXTURE_2D) gl.CallList(textureList) gl.PopMatrix() } }
// Creates a LosTexture with the specified size, which must be a power of two. func MakeLosTexture() *LosTexture { var lt LosTexture lt.pix = make([]byte, LosTextureSizeSquared) lt.p2d = make([][]byte, LosTextureSize) lt.rec = make(chan gl.Texture, 1) for i := 0; i < LosTextureSize; i++ { lt.p2d[i] = lt.pix[i*LosTextureSize : (i+1)*LosTextureSize] } render.Queue(func() { gl.Enable(gl.TEXTURE_2D) tex := gl.GenTexture() tex.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) gl.TexImage2D(gl.TEXTURE_2D, 0, gl.ALPHA, len(lt.p2d), len(lt.p2d), 0, gl.ALPHA, gl.BYTE, lt.pix) lt.rec <- tex runtime.SetFinalizer(<, losTextureFinalize) }) return < }
func drawPrep() { gl.Disable(gl.DEPTH_TEST) gl.Disable(gl.TEXTURE_2D) gl.PolygonMode(gl.FRONT_AND_BACK, gl.FILL) gl.Enable(gl.BLEND) gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) gl.ClearStencil(0) gl.Clear(gl.STENCIL_BUFFER_BIT) }
// Updates OpenGl with any changes that have been made to the texture. // OpenGl calls in this method are run on the render thread func (lt *LosTexture) Remap() { if !lt.ready() { return } render.Queue(func() { gl.Enable(gl.TEXTURE_2D) lt.tex.Bind(gl.TEXTURE_2D) gl.TexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, len(lt.p2d), len(lt.p2d), gl.ALPHA, lt.pix) }) }
func makeErrorTexture() { gl.Enable(gl.TEXTURE_2D) error_texture = gl.GenTexture() error_texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) transparent := []byte{0, 0, 0, 0} glu.Build2DMipmaps(gl.TEXTURE_2D, 4, 1, 1, gl.RGBA, transparent) }
func (s *sheet) makeTexture(pixer <-chan []byte) { gl.Enable(gl.TEXTURE_2D) s.texture = gl.GenTexture() s.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) data := <-pixer glu.Build2DMipmaps(gl.TEXTURE_2D, 4, s.dx, s.dy, gl.RGBA, data) memory.FreeBlock(data) }
func Render(x, y, dx, dy float64) { var run, op mathgl.Mat4 run.Identity() op.Translation(float32(x), float32(y), 0) run.Multiply(&op) op.Scaling(float32(dx), float32(dy), 1) run.Multiply(&op) gl.PushMatrix() gl.Enable(gl.TEXTURE_2D) gl.MultMatrixf(&run[0]) gl.CallList(textureList) gl.PopMatrix() }
func (mdb *MediumDialogBox) Draw(region gui.Region) { mdb.region = region if mdb.done { return } gl.Enable(gl.TEXTURE_2D) gl.Color4ub(255, 255, 255, 255) mdb.layout.Background.Data().RenderNatural(region.X, region.Y) for _, button := range mdb.buttons { button.RenderAt(region.X, region.Y) } for i := range mdb.format.Sections { section := mdb.format.Sections[i] data := mdb.data.Pages[mdb.data.cur_page].Sections[i] p := section.Paragraph d := base.GetDictionary(p.Size) var just gui.Justification switch p.Halign { case "left": just = gui.Left case "right": just = gui.Right case "center": just = gui.Center default: base.Error().Printf("Unknown justification '%s'", p.Halign) p.Halign = "left" } var valign gui.Justification switch p.Valign { case "top": valign = gui.Top case "bottom": valign = gui.Bottom case "center": valign = gui.Center default: base.Error().Printf("Unknown justification '%s'", p.Valign) p.Valign = "top" } gl.Color4ub(255, 255, 255, 255) d.RenderParagraph(data.Text, float64(p.X+region.X), float64(p.Y+region.Y)-d.MaxHeight()/2, 0, float64(p.Dx), d.MaxHeight(), just, valign) gl.Color4ub(255, 255, 255, byte(data.shading*255)) tex := data.Image.Data() tex.RenderNatural(region.X+section.X-tex.Dx()/2, region.Y+section.Y-tex.Dy()/2) } }
func (w *ImageBox) SetImage(path string) { w.UnsetImage() data, err := os.Open(path) if err != nil { // TODO: Log error return } var img image.Image img, _, err = image.Decode(data) if err != nil { // TODO: Log error return } w.Request_dims.Dx = img.Bounds().Dx() w.Request_dims.Dy = img.Bounds().Dy() canvas := image.NewRGBA(image.Rect(0, 0, img.Bounds().Dx(), img.Bounds().Dy())) for y := 0; y < canvas.Bounds().Dy(); y++ { for x := 0; x < canvas.Bounds().Dx(); x++ { r, g, b, a := img.At(x, y).RGBA() base := 4*x + canvas.Stride*y canvas.Pix[base] = uint8(r) canvas.Pix[base+1] = uint8(g) canvas.Pix[base+2] = uint8(b) canvas.Pix[base+3] = uint8(a) } } w.texture = gl.GenTexture() gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) glu.Build2DMipmaps(gl.TEXTURE_2D, 4, img.Bounds().Dx(), img.Bounds().Dy(), gl.RGBA, canvas.Pix) w.active = true }
func (w *TextLine) figureDims() { // Always draw the text as white on a transparent background so that we can change // the color easily through opengl w.rdims.Dx, w.rdims.Dy = drawText(w.font, w.context, color.RGBA{255, 255, 255, 255}, image.NewRGBA(image.Rect(0, 0, 1, 1)), w.text) texture_dims := Dims{ Dx: int(nextPowerOf2(uint32(w.rdims.Dx))), Dy: int(nextPowerOf2(uint32(w.rdims.Dy))), } w.rgba = image.NewRGBA(image.Rect(0, 0, texture_dims.Dx, texture_dims.Dy)) drawText(w.font, w.context, color.RGBA{255, 255, 255, 255}, w.rgba, w.text) gl.Enable(gl.TEXTURE_2D) w.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) glu.Build2DMipmaps(gl.TEXTURE_2D, 4, w.rgba.Bounds().Dx(), w.rgba.Bounds().Dy(), gl.RGBA, w.rgba.Pix) gl.Disable(gl.TEXTURE_2D) }
func (w *VerticalTable) Draw(region Region) { gl.Enable(gl.BLEND) gl.Disable(gl.TEXTURE_2D) dx := region.Dx if dx > w.Request_dims.Dx && !w.Ex { dx = w.Request_dims.Dx } dy := region.Dy if dy > w.Request_dims.Dy && !w.Ex { dy = w.Request_dims.Dy } gl.Color4d( w.params.Background.R, w.params.Background.G, w.params.Background.B, w.params.Background.A) gl.Begin(gl.QUADS) gl.Vertex2i(region.X, region.Y+region.Dy-dy) gl.Vertex2i(region.X, region.Y+region.Dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy-dy) gl.End() gl.Color4d( w.params.Border.R, w.params.Border.G, w.params.Border.B, w.params.Border.A) gl.Begin(gl.LINES) gl.Vertex2i(region.X, region.Y+region.Dy-dy) gl.Vertex2i(region.X, region.Y+region.Dy) gl.Vertex2i(region.X, region.Y+region.Dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy-dy) gl.Vertex2i(region.X+dx, region.Y+region.Dy-dy) gl.Vertex2i(region.X, region.Y+region.Dy-dy) gl.End() fill_available := region.Dy - w.Request_dims.Dy if fill_available < 0 { fill_available = 0 } fill_request := 0 for _, child := range w.Children { if _, ey := child.Expandable(); ey { fill_request += child.Requested().Dy } } var child_region Region child_region.Y = region.Y + region.Dy for _, child := range w.Children { child_region.Dims = child.Requested() if _, ey := child.Expandable(); ey && fill_request > 0 { child_region.Dy += (child_region.Dy * fill_available) / fill_request } if region.Dy < w.Request_dims.Dy { child_region.Dims.Dy *= region.Dy child_region.Dims.Dy /= w.Request_dims.Dy } if child_region.Dx > region.Dx { child_region.Dx = region.Dx } if ex, _ := child.Expandable(); child_region.Dx < region.Dx && ex { child_region.Dx = region.Dx } child_region.X = region.X child_region.Y -= child_region.Dy child_region.Y -= w.params.Spacing child.Draw(child_region) } w.Render_region = region }
func drawFloor(room *Room, floor mathgl.Mat4, temp *WallTexture, cstack base.ColorStack, los_tex *LosTexture, los_alpha float64, floor_drawer []FloorDrawer) { gl.MatrixMode(gl.MODELVIEW) gl.PushMatrix() gl.LoadIdentity() gl.MultMatrixf(&floor[0]) defer gl.PopMatrix() gl.Enable(gl.STENCIL_TEST) defer gl.Disable(gl.STENCIL_TEST) gl.StencilFunc(gl.ALWAYS, 4, 4) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) gl.Disable(gl.TEXTURE_2D) gl.Begin(gl.QUADS) gl.Vertex2i(0, 0) gl.Vertex2i(0, room.Size.Dy) gl.Vertex2i(room.Size.Dx, room.Size.Dy) gl.Vertex2i(room.Size.Dx, 0) gl.End() gl.StencilFunc(gl.EQUAL, 4, 15) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) // Draw the floor gl.Enable(gl.TEXTURE_2D) cstack.ApplyWithAlpha(los_alpha) room.Floor.Data().Render(0, 0, float64(room.Size.Dx), float64(room.Size.Dy)) if los_tex != nil { los_tex.Bind() gl.BlendFunc(gl.SRC_ALPHA_SATURATE, gl.SRC_ALPHA) gl.Color4d(0, 0, 0, 1) gl.Begin(gl.QUADS) gl.TexCoord2i(0, 0) gl.Vertex2i(-room.X, -room.Y) gl.TexCoord2i(1, 0) gl.Vertex2i(-room.X, los_tex.Size()-room.Y) gl.TexCoord2i(1, 1) gl.Vertex2i(los_tex.Size()-room.X, los_tex.Size()-room.Y) gl.TexCoord2i(0, 1) gl.Vertex2i(los_tex.Size()-room.X, -room.Y) gl.End() gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) } cstack.ApplyWithAlpha(los_alpha) { g_texs = g_texs[0:0] if temp != nil { g_texs = append(g_texs, *temp) } for _, tex := range room.WallTextures { g_texs = append(g_texs, *tex) } for i, tex := range g_texs { if tex.X >= float32(room.Size.Dx) { tex.Rot -= 3.1415926535 / 2 } if temp != nil && i == 0 { cstack.Push(1, 0.7, 0.7, 0.7) } cstack.ApplyWithAlpha(los_alpha) tex.Render() if temp != nil && i == 0 { cstack.Pop() } } } gl.PushMatrix() gl.Translated(-float64(room.X), -float64(room.Y), 0) for _, fd := range floor_drawer { fd.RenderOnFloor() } gl.PopMatrix() // Re-enable textures because floor_drawer.RenderOnFloor() might have // disabled them gl.Enable(gl.TEXTURE_2D) gl.StencilFunc(gl.ALWAYS, 5, 5) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) gl.Disable(gl.TEXTURE_2D) gl.Color4d(0, 0, 0, 0) gl.Begin(gl.QUADS) gl.Vertex2i(0, 0) gl.Vertex2i(0, room.Size.Dy) gl.Vertex2i(room.Size.Dx, room.Size.Dy) gl.Vertex2i(room.Size.Dx, 0) gl.End() }
func losTextureFinalize(lt *LosTexture) { render.Queue(func() { gl.Enable(gl.TEXTURE_2D) lt.tex.Delete() }) }
func (rc *RosterChooser) Draw(r gui.Region) { rc.Render_region = r r.PushClipPlanes() defer r.PopClipPlanes() gl.Enable(gl.TEXTURE_2D) { // Up button x := r.X y := r.Y + r.Dy - rc.layout.Up.Data().Dy() rc.render.up.X = x rc.render.up.Y = y rc.render.up.Dx = rc.layout.Up.Data().Dx() rc.render.up.Dy = rc.layout.Up.Data().Dy() if rc.mouse.Inside(rc.render.up) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.8, 0.8, 0.8, 1) } rc.layout.Up.Data().RenderNatural(x, y) } { // Down button x := r.X y := r.Y + rc.layout.Down.Data().Dy() rc.render.down.X = x rc.render.down.Y = y rc.render.down.Dx = rc.layout.Down.Data().Dx() rc.render.down.Dy = rc.layout.Down.Data().Dy() if rc.mouse.Inside(rc.render.down) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.8, 0.8, 0.8, 1) } rc.layout.Down.Data().RenderNatural(x, y) } { // Options rc.render.all_options.X = r.X + rc.layout.Down.Data().Dx() rc.render.all_options.Y = r.Y + r.Dy - rc.layout.Num_options*rc.layout.Option.Dy rc.render.all_options.Dx = rc.layout.Option.Dx rc.render.all_options.Dy = rc.layout.Num_options * rc.layout.Option.Dy rc.render.all_options.PushClipPlanes() x := rc.render.all_options.X y := r.Y + r.Dy - rc.layout.Option.Dy + int(float64(rc.layout.Option.Dy)*rc.focus_pos) for i := range rc.options { rc.render.options[i] = gui.Region{ gui.Point{x, y}, gui.Dims{rc.layout.Option.Dx, rc.layout.Option.Dy}, } hovered := rc.mouse.Inside(rc.render.options[i]) selected := rc.selected[i] selectable := rc.selector(i, rc.selected, false) rc.options[i].Draw(hovered, selected, selectable, rc.render.options[i]) y -= rc.layout.Option.Dy } rc.render.all_options.PopClipPlanes() } { // Text d := base.GetDictionary(15) x := r.X y := float64(r.Y) + d.MaxHeight()/2 x1 := float64(x + r.Dx/3) x2 := float64(x + (2*r.Dx)/3) rc.render.done = gui.Region{ gui.Point{x, r.Y}, gui.Dims{r.Dx / 2, int(d.MaxHeight() * 2)}, } rc.render.undo = gui.Region{ gui.Point{x + r.Dx/2, r.Y}, gui.Dims{r.Dx / 2, int(d.MaxHeight() * 2)}, } if rc.mouse.Inside(rc.render.done) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.6, 0.6, 0.6, 1) } d.RenderString("Done", x1, y, 0, d.MaxHeight(), gui.Center) if rc.on_undo != nil { if rc.mouse.Inside(rc.render.undo) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.6, 0.6, 0.6, 1) } d.RenderString("Undo", x2, y, 0, d.MaxHeight(), gui.Center) } } }
func drawFurniture(roomx, roomy int, mat mathgl.Mat4, zoom float32, furniture []*Furniture, temp_furniture *Furniture, extras []Drawable, cstack base.ColorStack, los_tex *LosTexture, los_alpha float64) { gl.Enable(gl.TEXTURE_2D) gl.Color4d(1, 1, 1, los_alpha) gl.PushMatrix() gl.LoadIdentity() board_to_window := func(mx, my float32) (x, y float32) { v := mathgl.Vec4{X: mx, Y: my, W: 1} v.Transform(&mat) x, y = v.X, v.Y return } g_stuff = g_stuff[0:0] for i := range furniture { g_stuff = append(g_stuff, furniture[i]) } if temp_furniture != nil { g_stuff = append(g_stuff, temp_furniture) } for i := range extras { g_stuff = append(g_stuff, extras[i]) } g_stuff = OrderRectObjects(g_stuff) for i := len(g_stuff) - 1; i >= 0; i-- { f := g_stuff[i] var near_x, near_y, dx, dy float32 idx, idy := f.Dims() dx = float32(idx) dy = float32(idy) switch d := f.(type) { case *Furniture: ix, iy := d.Pos() near_x = float32(ix) near_y = float32(iy) case Drawable: fx, fy := d.FPos() near_x = float32(fx) near_y = float32(fy) } vis_tot := 1.0 if los_tex != nil { vis_tot = 0.0 // If we're looking at a piece of furniture that blocks Los then we // can't expect to have Los to all of it, so we will check the squares // around it. Full visibility will mean that half of the surrounding // cells are visible. blocks_los := false // Also need to check if it is an enemy unit if _, ok := f.(*Furniture); ok { blocks_los = true } if blocks_los { for x := near_x - 1; x < near_x+dx+1; x++ { vis_tot += float64(los_tex.Pix()[int(x)+roomx][int(near_y-1)+roomy]) vis_tot += float64(los_tex.Pix()[int(x)+roomx][int(near_y+dy+1)+roomy]) } for y := near_y; y < near_y+dy; y++ { vis_tot += float64(los_tex.Pix()[int(near_x-1)+roomx][int(y)+roomy]) vis_tot += float64(los_tex.Pix()[int(near_x+dx+1)+roomx][int(y)+roomy]) } vis_tot /= float64((dx*2 + dy*2 + 4) * 255 / 2) if vis_tot > 1 { vis_tot = 1 } } else { for x := near_x; x < near_x+dx; x++ { for y := near_y; y < near_y+dy; y++ { vis_tot += float64(los_tex.Pix()[int(x)+roomx][int(y)+roomy]) } } vis_tot /= float64(dx * dy * 255) } } leftx, _ := board_to_window(near_x, near_y+dy) rightx, _ := board_to_window(near_x+dx, near_y) _, boty := board_to_window(near_x, near_y) if f == temp_furniture { cstack.Push(1, 0, 0, 0.4) } else { bot := (LosMinVisibility / 255.0) vis := (vis_tot - bot) / (1 - bot) vis = vis * vis vis = vis*(1-bot) + bot vis = vis * vis cstack.Push(vis, vis, vis, 1) } cstack.ApplyWithAlpha(los_alpha) cstack.Pop() switch d := f.(type) { case *Furniture: d.Render(mathgl.Vec2{leftx, boty}, rightx-leftx) case Drawable: gl.Enable(gl.TEXTURE_2D) x := (leftx + rightx) / 2 d.Render(mathgl.Vec2{x, boty}, rightx-leftx) } } gl.PopMatrix() }
func handleLoadRequest(req loadRequest) { f, _ := os.Open(req.path) im, _, err := image.Decode(f) f.Close() if err != nil { return } gray := true dx := im.Bounds().Dx() dy := im.Bounds().Dy() for i := 0; i < dx; i++ { for j := 0; j < dy; j++ { r, g, b, _ := im.At(i, j).RGBA() if r != g || g != b { gray = false break } } if !gray { break } } var canvas draw.Image var pix []byte if gray { ga := NewGrayAlpha(im.Bounds()) pix = ga.Pix canvas = ga } else { pix = memory.GetBlock(4 * req.data.dx * req.data.dy) canvas = &image.RGBA{pix, 4 * req.data.dx, im.Bounds()} } draw.Draw(canvas, im.Bounds(), im, image.Point{}, draw.Src) load_mutex.Lock() load_count += len(pix) manual_unlock := false // This prevents us from trying to send too much to opengl in a single // frame. If we go over the threshold then we hold the lock until we're // done sending data to opengl, then other requests will be free to // queue up and they will run on the next frame. if load_count < load_threshold { load_mutex.Unlock() } else { manual_unlock = true } render.Queue(func() { { gl.Enable(gl.TEXTURE_2D) req.data.texture = gl.GenTexture() req.data.texture.Bind(gl.TEXTURE_2D) gl.TexEnvf(gl.TEXTURE_ENV, gl.TEXTURE_ENV_MODE, gl.MODULATE) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.REPEAT) gl.TexParameterf(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.REPEAT) } if gray { glu.Build2DMipmaps(gl.TEXTURE_2D, gl.LUMINANCE_ALPHA, req.data.dx, req.data.dy, gl.LUMINANCE_ALPHA, pix) } else { glu.Build2DMipmaps(gl.TEXTURE_2D, gl.RGBA, req.data.dx, req.data.dy, gl.RGBA, pix) } memory.FreeBlock(pix) if manual_unlock { load_count = 0 load_mutex.Unlock() } }) }
// room: the wall to draw // wall: the texture to render on the wall // temp: an additional texture to render along with the other detail textures // specified in room // left,right: the xy planes of the left and right walls func drawWall(room *Room, floor, left, right mathgl.Mat4, temp_tex *WallTexture, temp_door doorInfo, cstack base.ColorStack, los_tex *LosTexture, los_alpha float64) { gl.Enable(gl.STENCIL_TEST) defer gl.Disable(gl.STENCIL_TEST) gl.MatrixMode(gl.MODELVIEW) gl.PushMatrix() defer gl.PopMatrix() var dz int if room.Wall.Data().Dx() > 0 { dz = room.Wall.Data().Dy() * (room.Size.Dx + room.Size.Dy) / room.Wall.Data().Dx() } corner := float32(room.Size.Dx) / float32(room.Size.Dx+room.Size.Dy) gl.LoadIdentity() gl.MultMatrixf(&floor[0]) g_texs = g_texs[0:0] if temp_tex != nil { g_texs = append(g_texs, *temp_tex) } for _, tex := range room.WallTextures { g_texs = append(g_texs, *tex) } do_right_wall := func() { gl.Begin(gl.QUADS) gl.TexCoord2f(1, 0) gl.Vertex3i(room.Size.Dx, 0, 0) gl.TexCoord2f(1, -1) gl.Vertex3i(room.Size.Dx, 0, -dz) gl.TexCoord2f(corner, -1) gl.Vertex3i(room.Size.Dx, room.Size.Dy, -dz) gl.TexCoord2f(corner, 0) gl.Vertex3i(room.Size.Dx, room.Size.Dy, 0) gl.End() } g_doors = g_doors[0:0] for _, door := range room.Doors { g_doors = append(g_doors, door) } if temp_door.Door != nil { g_doors = append(g_doors, temp_door.Door) } alpha := 0.2 do_right_doors := func(opened bool) { for _, door := range g_doors { if door.Facing != FarRight { continue } if door.IsOpened() != opened { continue } door.TextureData().Bind() if door == temp_door.Door { if temp_door.Valid { cstack.Push(0, 0, 1, alpha) } else { cstack.Push(1, 0, 0, alpha) } } cstack.ApplyWithAlpha(alpha * los_alpha) gl.Begin(gl.QUADS) height := float64(door.Width*door.TextureData().Dy()) / float64(door.TextureData().Dx()) gl.TexCoord2f(1, 0) gl.Vertex3d(float64(room.Size.Dx), float64(door.Pos), 0) gl.TexCoord2f(1, -1) gl.Vertex3d(float64(room.Size.Dx), float64(door.Pos), -height) gl.TexCoord2f(0, -1) gl.Vertex3d(float64(room.Size.Dx), float64(door.Pos+door.Width), -height) gl.TexCoord2f(0, 0) gl.Vertex3d(float64(room.Size.Dx), float64(door.Pos+door.Width), 0) gl.End() if door == temp_door.Door { cstack.Pop() } } } // Right wall gl.StencilFunc(gl.NOTEQUAL, 8, 7) gl.StencilOp(gl.DECR_WRAP, gl.REPLACE, gl.REPLACE) gl.Color4d(0, 0, 0, 0) do_right_wall() gl.Enable(gl.TEXTURE_2D) cstack.ApplyWithAlpha(alpha * los_alpha) gl.StencilFunc(gl.EQUAL, 8, 15) gl.StencilOp(gl.KEEP, gl.ZERO, gl.ZERO) do_right_doors(true) cstack.ApplyWithAlpha(1.0 * los_alpha) gl.StencilFunc(gl.EQUAL, 15, 15) gl.StencilOp(gl.KEEP, gl.ZERO, gl.ZERO) do_right_doors(true) for _, alpha := range []float64{alpha, 1.0} { cstack.ApplyWithAlpha(alpha * los_alpha) if alpha == 1.0 { gl.StencilFunc(gl.EQUAL, 15, 15) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) } else { gl.StencilFunc(gl.EQUAL, 8, 15) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) } room.Wall.Data().Bind() do_right_wall() gl.PushMatrix() gl.LoadIdentity() gl.MultMatrixf(&right[0]) for i, tex := range g_texs { dx, dy := float32(room.Size.Dx), float32(room.Size.Dy) if tex.Y > dy { tex.X, tex.Y = dx+tex.Y-dy, dy+dx-tex.X } if tex.X > dx { tex.Rot -= 3.1415926535 / 2 } tex.X -= dx if temp_tex != nil && i == 0 { cstack.Push(1, 0.7, 0.7, 0.7) } cstack.ApplyWithAlpha(alpha * los_alpha) tex.Render() if temp_tex != nil && i == 0 { cstack.Pop() } } gl.PopMatrix() } cstack.ApplyWithAlpha(alpha * los_alpha) gl.StencilFunc(gl.EQUAL, 8, 15) do_right_doors(false) cstack.ApplyWithAlpha(1.0 * los_alpha) gl.StencilFunc(gl.EQUAL, 15, 15) do_right_doors(false) // Go back over the area we just drew on and replace it with all b0001 gl.StencilFunc(gl.ALWAYS, 1, 1) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) gl.Color4d(0, 0, 0, 0) do_right_wall() // Now that the entire wall has been draw we can cast shadows on it if we've // got a los texture if los_tex != nil { los_tex.Bind() gl.BlendFunc(gl.SRC_ALPHA_SATURATE, gl.SRC_ALPHA) gl.Color4d(0, 0, 0, 1) tx := (float64(room.X+room.Size.Dx) - 0.5) / float64(los_tex.Size()) ty := (float64(room.Y) + 0.5) / float64(los_tex.Size()) ty2 := (float64(room.Y+room.Size.Dy) - 0.5) / float64(los_tex.Size()) gl.Begin(gl.QUADS) gl.TexCoord2d(ty, tx) gl.Vertex3i(room.Size.Dx, 0, 0) gl.TexCoord2d(ty, tx) gl.Vertex3i(room.Size.Dx, 0, -dz) gl.TexCoord2d(ty2, tx) gl.Vertex3i(room.Size.Dx, room.Size.Dy, -dz) gl.TexCoord2d(ty2, tx) gl.Vertex3i(room.Size.Dx, room.Size.Dy, 0) gl.End() gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) } do_left_wall := func() { gl.Begin(gl.QUADS) gl.TexCoord2f(corner, 0) gl.Vertex3i(room.Size.Dx, room.Size.Dy, 0) gl.TexCoord2f(corner, -1) gl.Vertex3i(room.Size.Dx, room.Size.Dy, -dz) gl.TexCoord2f(0, -1) gl.Vertex3i(0, room.Size.Dy, -dz) gl.TexCoord2f(0, 0) gl.Vertex3i(0, room.Size.Dy, 0) gl.End() } do_left_doors := func(opened bool) { for _, door := range g_doors { if door.Facing != FarLeft { continue } if door.IsOpened() != opened { continue } door.TextureData().Bind() if door == temp_door.Door { if temp_door.Valid { cstack.Push(0, 0, 1, alpha) } else { cstack.Push(1, 0, 0, alpha) } } cstack.ApplyWithAlpha(alpha * los_alpha) gl.Begin(gl.QUADS) height := float64(door.Width*door.TextureData().Dy()) / float64(door.TextureData().Dx()) gl.TexCoord2f(0, 0) gl.Vertex3d(float64(door.Pos), float64(room.Size.Dy), 0) gl.TexCoord2f(0, -1) gl.Vertex3d(float64(door.Pos), float64(room.Size.Dy), -height) gl.TexCoord2f(1, -1) gl.Vertex3d(float64(door.Pos+door.Width), float64(room.Size.Dy), -height) gl.TexCoord2f(1, 0) gl.Vertex3d(float64(door.Pos+door.Width), float64(room.Size.Dy), 0) gl.End() if door == temp_door.Door { cstack.Pop() } } } gl.StencilFunc(gl.NOTEQUAL, 8, 7) gl.StencilOp(gl.DECR_WRAP, gl.REPLACE, gl.REPLACE) gl.Color4d(0, 0, 0, 0) do_left_wall() gl.Enable(gl.TEXTURE_2D) cstack.ApplyWithAlpha(alpha * los_alpha) gl.StencilFunc(gl.EQUAL, 8, 15) gl.StencilOp(gl.KEEP, gl.ZERO, gl.ZERO) do_left_doors(true) cstack.ApplyWithAlpha(1.0 * los_alpha) gl.StencilFunc(gl.EQUAL, 15, 15) gl.StencilOp(gl.KEEP, gl.ZERO, gl.ZERO) do_left_doors(true) for _, alpha := range []float64{alpha, 1.0} { if alpha == 1.0 { gl.StencilFunc(gl.EQUAL, 15, 15) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) } else { gl.StencilFunc(gl.EQUAL, 8, 15) gl.StencilOp(gl.KEEP, gl.KEEP, gl.KEEP) } room.Wall.Data().Bind() cstack.ApplyWithAlpha(alpha * los_alpha) do_left_wall() gl.PushMatrix() gl.LoadIdentity() gl.MultMatrixf(&left[0]) for i, tex := range g_texs { dx, dy := float32(room.Size.Dx), float32(room.Size.Dy) if tex.X > dx { tex.X, tex.Y = dx+dy-tex.Y, dy+tex.X-dx } tex.Y -= dy if temp_tex != nil && i == 0 { cstack.Push(1, 0.7, 0.7, 0.7) } cstack.ApplyWithAlpha(alpha * los_alpha) tex.Render() if temp_tex != nil && i == 0 { cstack.Pop() } } gl.PopMatrix() } cstack.ApplyWithAlpha(alpha * los_alpha) gl.StencilFunc(gl.EQUAL, 8, 15) do_left_doors(false) cstack.ApplyWithAlpha(1.0 * los_alpha) gl.StencilFunc(gl.EQUAL, 15, 15) do_left_doors(false) // Go back over the area we just drew on and replace it with all b0010 gl.StencilFunc(gl.ALWAYS, 2, 2) gl.StencilOp(gl.REPLACE, gl.REPLACE, gl.REPLACE) gl.Color4d(0, 0, 0, 0) do_left_wall() // Now that the entire wall has been draw we can cast shadows on it if we've // got a los texture if los_tex != nil { los_tex.Bind() gl.BlendFunc(gl.SRC_ALPHA_SATURATE, gl.SRC_ALPHA) gl.Color4d(0, 0, 0, 1) ty := (float64(room.Y+room.Size.Dy) - 0.5) / float64(los_tex.Size()) tx := (float64(room.X) + 0.5) / float64(los_tex.Size()) tx2 := (float64(room.X+room.Size.Dx) - 0.5) / float64(los_tex.Size()) gl.Begin(gl.QUADS) gl.TexCoord2d(ty, tx) gl.Vertex3i(0, room.Size.Dy, 0) gl.TexCoord2d(ty, tx) gl.Vertex3i(0, room.Size.Dy, -dz) gl.TexCoord2d(ty, tx2) gl.Vertex3i(room.Size.Dx, room.Size.Dy, -dz) gl.TexCoord2d(ty, tx2) gl.Vertex3i(room.Size.Dx, room.Size.Dy, 0) gl.End() gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA) } }
func (m *MainBar) Draw(region gui.Region) { m.region = region gl.Enable(gl.TEXTURE_2D) m.layout.Background.Data().Bind() gl.Color4d(1, 1, 1, 1) gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(region.X, region.Y) gl.TexCoord2d(0, -1) gl.Vertex2i(region.X, region.Y+region.Dy) gl.TexCoord2d(1, -1) gl.Vertex2i(region.X+region.Dx, region.Y+region.Dy) gl.TexCoord2d(1, 0) gl.Vertex2i(region.X+region.Dx, region.Y) gl.End() buttons := m.no_actions_buttons if m.ent != nil && len(m.ent.Actions) > m.layout.Actions.Count { buttons = m.all_buttons } for _, button := range buttons { button.RenderAt(region.X, region.Y) } ent := m.game.HoveredEnt() if ent == nil { ent = m.ent } if ent != nil && ent.Stats != nil { gl.Color4d(1, 1, 1, 1) ent.Still.Data().Bind() tdx := ent.Still.Data().Dx() tdy := ent.Still.Data().Dy() cx := region.X + m.layout.CenterStillFrame.X cy := region.Y + m.layout.CenterStillFrame.Y gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(cx-tdx/2, cy-tdy/2) gl.TexCoord2d(0, -1) gl.Vertex2i(cx-tdx/2, cy+tdy/2) gl.TexCoord2d(1, -1) gl.Vertex2i(cx+tdx/2, cy+tdy/2) gl.TexCoord2d(1, 0) gl.Vertex2i(cx+tdx/2, cy-tdy/2) gl.End() m.layout.Name.RenderString(ent.Name) m.layout.Ap.RenderString(fmt.Sprintf("Ap:%d", ent.Stats.ApCur())) m.layout.Hp.RenderString(fmt.Sprintf("Hp:%d", ent.Stats.HpCur())) m.layout.Corpus.RenderString(fmt.Sprintf("Corpus:%d", ent.Stats.Corpus())) m.layout.Ego.RenderString(fmt.Sprintf("Ego:%d", ent.Stats.Ego())) gl.Color4d(1, 1, 1, 1) m.layout.Divider.Data().Bind() tdx = m.layout.Divider.Data().Dx() tdy = m.layout.Divider.Data().Dy() cx = region.X + m.layout.Name.X cy = region.Y + m.layout.Name.Y - 5 gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex2i(cx-tdx/2, cy-tdy/2) gl.TexCoord2d(0, -1) gl.Vertex2i(cx-tdx/2, cy+(tdy+1)/2) gl.TexCoord2d(1, -1) gl.Vertex2i(cx+(tdx+1)/2, cy+(tdy+1)/2) gl.TexCoord2d(1, 0) gl.Vertex2i(cx+(tdx+1)/2, cy-tdy/2) gl.End() } if m.ent != nil && m.ent.Stats != nil { // Actions { spacing := m.layout.Actions.Icon_size * float64(m.layout.Actions.Count) spacing = m.layout.Actions.Width - spacing spacing /= float64(m.layout.Actions.Count - 1) m.state.Actions.space = spacing s := m.layout.Actions.Icon_size num_actions := len(m.ent.Actions) xpos := m.layout.Actions.X if num_actions > m.layout.Actions.Count { xpos -= m.state.Actions.scroll_pos * (s + spacing) } d := base.GetDictionary(10) var r gui.Region r.X = int(m.layout.Actions.X) r.Y = int(m.layout.Actions.Y - d.MaxHeight()) r.Dx = int(m.layout.Actions.Width) r.Dy = int(m.layout.Actions.Icon_size + d.MaxHeight()) r.PushClipPlanes() gl.Color4d(1, 1, 1, 1) for i, action := range m.ent.Actions { // Highlight the selected action if action == m.game.current_action { gl.Disable(gl.TEXTURE_2D) gl.Color4d(1, 0, 0, 1) gl.Begin(gl.QUADS) gl.Vertex3d(xpos-2, m.layout.Actions.Y-2, 0) gl.Vertex3d(xpos-2, m.layout.Actions.Y+s+2, 0) gl.Vertex3d(xpos+s+2, m.layout.Actions.Y+s+2, 0) gl.Vertex3d(xpos+s+2, m.layout.Actions.Y-2, 0) gl.End() } gl.Enable(gl.TEXTURE_2D) action.Icon().Data().Bind() if action.Preppable(m.ent, m.game) { gl.Color4d(1, 1, 1, 1) } else { gl.Color4d(0.5, 0.5, 0.5, 1) } gl.Begin(gl.QUADS) gl.TexCoord2d(0, 0) gl.Vertex3d(xpos, m.layout.Actions.Y, 0) gl.TexCoord2d(0, -1) gl.Vertex3d(xpos, m.layout.Actions.Y+s, 0) gl.TexCoord2d(1, -1) gl.Vertex3d(xpos+s, m.layout.Actions.Y+s, 0) gl.TexCoord2d(1, 0) gl.Vertex3d(xpos+s, m.layout.Actions.Y, 0) gl.End() gl.Disable(gl.TEXTURE_2D) ypos := m.layout.Actions.Y - d.MaxHeight() - 2 d.RenderString(fmt.Sprintf("%d", i+1), xpos+s/2, ypos, 0, d.MaxHeight(), gui.Center) xpos += spacing + m.layout.Actions.Icon_size } r.PopClipPlanes() // Now, if there is a selected action, position it between the arrows if m.state.Actions.selected != nil { // a := m.state.Actions.selected d := base.GetDictionary(15) x := m.layout.Actions.X + m.layout.Actions.Width/2 y := float64(m.layout.ActionLeft.Y) str := fmt.Sprintf("%s:%dAP", m.state.Actions.selected.String(), m.state.Actions.selected.AP()) gl.Color4d(1, 1, 1, 1) d.RenderString(str, x, y, 0, d.MaxHeight(), gui.Center) } } // Conditions { gl.Color4d(1, 1, 1, 1) c := m.layout.Conditions d := base.GetDictionary(int(c.Size)) ypos := c.Y + c.Height - d.MaxHeight() + m.state.Conditions.scroll_pos var r gui.Region r.X = int(c.X) r.Y = int(c.Y) r.Dx = int(c.Width) r.Dy = int(c.Height) r.PushClipPlanes() for _, s := range m.ent.Stats.ConditionNames() { d.RenderString(s, c.X+c.Width/2, ypos, 0, d.MaxHeight(), gui.Center) ypos -= float64(d.MaxHeight()) } r.PopClipPlanes() } // Gear if m.ent.ExplorerEnt != nil && m.ent.ExplorerEnt.Gear != nil { gear := m.ent.ExplorerEnt.Gear layout := m.layout.Gear icon := gear.Small_icon.Data() icon.RenderNatural(int(layout.X), int(layout.Y)) d := base.GetDictionary(10) d.RenderString("Gear", layout.X+float64(icon.Dx())/2, layout.Y-d.MaxHeight(), 0, d.MaxHeight(), gui.Center) } } // Mouseover text if m.state.MouseOver.active { var x int switch m.state.MouseOver.location { case mouseOverActions: x = int(m.layout.Actions.X + m.layout.Actions.Width/2) case mouseOverConditions: x = int(m.layout.Conditions.X + m.layout.Conditions.Width/2) case mouseOverGear: default: base.Warn().Printf("Got an unknown mouseover location: %d", m.state.MouseOver.location) m.state.MouseOver.active = false } y := m.layout.Background.Data().Dy() - 40 d := base.GetDictionary(15) d.RenderString(m.state.MouseOver.text, float64(x), float64(y), 0, d.MaxHeight(), gui.Center) } }