示例#1
0
func (s *Screen) drawWidgets() {
	if !s.visible {
		return
	}
	s.window.MakeContextCurrent()
	s.fbW, s.fbH = s.window.GetFramebufferSize()
	s.w, s.h = s.window.GetSize()
	gl.Viewport(0, 0, s.fbW, s.fbH)

	s.pixelRatio = float32(s.fbW) / float32(s.w)
	s.context.BeginFrame(s.w, s.h, s.pixelRatio)
	s.Draw(s, s.context)
	elapsed := GetTime() - s.lastInteraction

	if elapsed > 0.5 {
		// Draw tooltips
		widget := s.FindWidget(s, s.mousePosX, s.mousePosY)
		if widget != nil && widget.Tooltip() != "" {
			var tooltipWidth float32 = 150
			ctx := s.context
			ctx.SetFontFace(s.theme.FontNormal)
			ctx.SetFontSize(15.0)
			ctx.SetTextAlign(nanovgo.AlignCenter | nanovgo.AlignTop)
			ctx.SetTextLineHeight(1.1)
			posX, posY := widget.AbsolutePosition()
			posX += widget.Width() / 2
			posY += widget.Height() + 10
			bounds := ctx.TextBoxBounds(float32(posX), float32(posY), tooltipWidth, widget.Tooltip())
			ctx.SetGlobalAlpha(minF(1.0, 2*(elapsed-0.5)) * 0.8)
			ctx.BeginPath()
			ctx.SetFillColor(nanovgo.MONO(0, 255))
			h := (bounds[2] - bounds[0]) / 2
			ctx.RoundedRect(bounds[0]-4-h, bounds[1]-4, bounds[2]-bounds[0]+8, bounds[3]-bounds[1]+8, 3)
			px := (bounds[2]+bounds[0])/2 - h
			ctx.MoveTo(px, bounds[1]-10)
			ctx.LineTo(px+7, bounds[1]+1)
			ctx.LineTo(px-7, bounds[1]+1)
			ctx.Fill()

			ctx.SetFillColor(nanovgo.MONO(255, 255))
			ctx.SetFontBlur(0.0)
			ctx.TextBox(float32(posX)-h, float32(posY), tooltipWidth, widget.Tooltip())

		}
	}

	s.context.EndFrame()
}
示例#2
0
文件: viewport.go 项目: CodyGuo/gxui
func newViewport(driver *driver, width, height int, title string, fullscreen bool) *viewport {
	v := &viewport{
		fullscreen: fullscreen,
		scaling:    1,
		title:      title,
	}

	glfw.DefaultWindowHints()
	glfw.WindowHint(glfw.Samples, 4)
	var monitor *glfw.Monitor
	if fullscreen {
		monitor = glfw.GetPrimaryMonitor()
		if width == 0 || height == 0 {
			vm := monitor.GetVideoMode()
			width, height = vm.Width, vm.Height
		}
	}
	wnd, err := glfw.CreateWindow(width, height, v.title, monitor, nil)
	if err != nil {
		panic(err)
	}
	width, height = wnd.GetSize() // At this time, width and height serve as a "hint" for glfw.CreateWindow, so get actual values from window.

	wnd.MakeContextCurrent()

	v.context = newContext()

	cursorPoint := func(x, y float64) math.Point {
		// HACK: xpos is off by 1 and ypos is off by 3 on OSX.
		// Compensate until real fix is found.
		x -= 1.0
		y -= 3.0
		return math.Point{X: int(x), Y: int(y)}.ScaleS(1 / v.scaling)
	}
	wnd.SetCloseCallback(func(*glfw.Window) {
		v.Close()
	})
	wnd.SetPosCallback(func(w *glfw.Window, x, y int) {
		v.Lock()
		v.position = math.NewPoint(x, y)
		v.Unlock()
	})
	wnd.SetSizeCallback(func(_ *glfw.Window, w, h int) {
		v.Lock()
		v.sizeDipsUnscaled = math.Size{W: w, H: h}
		v.sizeDips = v.sizeDipsUnscaled.ScaleS(1 / v.scaling)
		v.Unlock()
		v.onResize.Fire()
	})
	wnd.SetFramebufferSizeCallback(func(_ *glfw.Window, w, h int) {
		v.Lock()
		v.sizePixels = math.Size{W: w, H: h}
		v.Unlock()
		gl.Viewport(0, 0, w, h)
		gl.ClearColor(kClearColorR, kClearColorG, kClearColorB, 1.0)
		gl.Clear(gl.COLOR_BUFFER_BIT)
	})
	wnd.SetCursorPosCallback(func(w *glfw.Window, x, y float64) {
		p := cursorPoint(w.GetCursorPos())
		v.Lock()
		if v.pendingMouseMoveEvent == nil {
			v.pendingMouseMoveEvent = &gxui.MouseEvent{}
			driver.Call(func() {
				v.Lock()
				ev := *v.pendingMouseMoveEvent
				v.pendingMouseMoveEvent = nil
				v.Unlock()
				v.onMouseMove.Fire(ev)
			})
		}
		v.pendingMouseMoveEvent.Point = p
		v.pendingMouseMoveEvent.State = getMouseState(w)
		v.Unlock()
	})
	wnd.SetCursorEnterCallback(func(w *glfw.Window, entered bool) {
		p := cursorPoint(w.GetCursorPos())
		ev := gxui.MouseEvent{
			Point: p,
		}
		ev.State = getMouseState(w)
		if entered {
			v.onMouseEnter.Fire(ev)
		} else {
			v.onMouseExit.Fire(ev)
		}
	})
	wnd.SetScrollCallback(func(w *glfw.Window, xoff, yoff float64) {
		p := cursorPoint(w.GetCursorPos())
		v.Lock()
		if v.pendingMouseScrollEvent == nil {
			v.pendingMouseScrollEvent = &gxui.MouseEvent{}
			driver.Call(func() {
				v.Lock()
				ev := *v.pendingMouseScrollEvent
				v.pendingMouseScrollEvent = nil
				ev.ScrollX, ev.ScrollY = int(v.scrollAccumX), int(v.scrollAccumY)
				if ev.ScrollX != 0 || ev.ScrollY != 0 {
					v.scrollAccumX -= float64(ev.ScrollX)
					v.scrollAccumY -= float64(ev.ScrollY)
					v.Unlock()
					v.onMouseScroll.Fire(ev)
				} else {
					v.Unlock()
				}
			})
		}
		v.pendingMouseScrollEvent.Point = p
		v.scrollAccumX += xoff * platform.ScrollSpeed
		v.scrollAccumY += yoff * platform.ScrollSpeed
		v.pendingMouseScrollEvent.State = getMouseState(w)
		v.Unlock()
	})
	wnd.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mod glfw.ModifierKey) {
		p := cursorPoint(w.GetCursorPos())
		ev := gxui.MouseEvent{
			Point:    p,
			Modifier: translateKeyboardModifier(mod),
		}
		ev.Button = translateMouseButton(button)
		ev.State = getMouseState(w)
		if action == glfw.Press {
			v.onMouseDown.Fire(ev)
		} else {
			v.onMouseUp.Fire(ev)
		}
	})
	wnd.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
		ev := gxui.KeyboardEvent{
			Key:      translateKeyboardKey(key),
			Modifier: translateKeyboardModifier(mods),
		}
		switch action {
		case glfw.Press:
			v.onKeyDown.Fire(ev)
		case glfw.Release:
			v.onKeyUp.Fire(ev)
		case glfw.Repeat:
			v.onKeyRepeat.Fire(ev)
		}
	})
	wnd.SetCharModsCallback(func(w *glfw.Window, char rune, mods glfw.ModifierKey) {
		if !unicode.IsControl(char) &&
			!unicode.IsGraphic(char) &&
			!unicode.IsLetter(char) &&
			!unicode.IsMark(char) &&
			!unicode.IsNumber(char) &&
			!unicode.IsPunct(char) &&
			!unicode.IsSpace(char) &&
			!unicode.IsSymbol(char) {
			return // Weird unicode character. Ignore
		}

		ev := gxui.KeyStrokeEvent{
			Character: char,
			Modifier:  translateKeyboardModifier(mods),
		}
		v.onKeyStroke.Fire(ev)
	})
	wnd.SetRefreshCallback(func(w *glfw.Window) {
		if v.canvas != nil {
			v.render()
		}
	})

	fw, fh := wnd.GetFramebufferSize()
	posX, posY := wnd.GetPos()

	// Pre-multiplied alpha blending
	gl.BlendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA)
	gl.Enable(gl.BLEND)
	gl.Enable(gl.SCISSOR_TEST)
	gl.Viewport(0, 0, fw, fh)
	gl.Scissor(0, 0, int32(fw), int32(fh))
	gl.ClearColor(kClearColorR, kClearColorG, kClearColorB, 1.0)
	gl.Clear(gl.COLOR_BUFFER_BIT)
	wnd.SwapBuffers()

	v.window = wnd
	v.driver = driver
	v.onClose = driver.createAppEvent(func() {})
	v.onResize = driver.createAppEvent(func() {})
	v.onMouseMove = gxui.CreateEvent(func(gxui.MouseEvent) {})
	v.onMouseEnter = driver.createAppEvent(func(gxui.MouseEvent) {})
	v.onMouseExit = driver.createAppEvent(func(gxui.MouseEvent) {})
	v.onMouseDown = driver.createAppEvent(func(gxui.MouseEvent) {})
	v.onMouseUp = driver.createAppEvent(func(gxui.MouseEvent) {})
	v.onMouseScroll = gxui.CreateEvent(func(gxui.MouseEvent) {})
	v.onKeyDown = driver.createAppEvent(func(gxui.KeyboardEvent) {})
	v.onKeyUp = driver.createAppEvent(func(gxui.KeyboardEvent) {})
	v.onKeyRepeat = driver.createAppEvent(func(gxui.KeyboardEvent) {})
	v.onKeyStroke = driver.createAppEvent(func(gxui.KeyStrokeEvent) {})
	v.onDestroy = driver.createDriverEvent(func() {})
	v.sizeDipsUnscaled = math.Size{W: width, H: height}
	v.sizeDips = v.sizeDipsUnscaled.ScaleS(1 / v.scaling)
	v.sizePixels = math.Size{W: fw, H: fh}
	v.position = math.Point{X: posX, Y: posY}
	return v
}
示例#3
0
文件: web.go 项目: shibukawa/nanovgo
func main() {
	err := glfw.Init(gl.ContextWatcher)
	if err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	glfw.WindowHint(glfw.StencilBits, 1)
	glfw.WindowHint(glfw.Samples, 4)

	window, err := glfw.CreateWindow(1000*0.6, 600*0.6, "NanoVGo", nil, nil)
	if err != nil {
		panic(err)
	}
	window.SetKeyCallback(key)
	window.MakeContextCurrent()

	ctx, err := nanovgo.NewContext(0)
	defer ctx.Delete()

	if err != nil {
		panic(err)
	}

	demoData := LoadDemo(ctx)

	glfw.SwapInterval(0)

	fps := perfgraph.NewPerfGraph("Frame Time", "sans")

	for !window.ShouldClose() {
		t, _ := fps.UpdateGraph()

		fbWidth, fbHeight := window.GetFramebufferSize()
		winWidth, winHeight := window.GetSize()
		mx, my := window.GetCursorPos()

		pixelRatio := float32(fbWidth) / float32(winWidth)
		gl.Viewport(0, 0, fbWidth, fbHeight)
		if premult {
			gl.ClearColor(0, 0, 0, 0)
		} else {
			gl.ClearColor(0.3, 0.3, 0.32, 1.0)
		}
		gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
		gl.Enable(gl.BLEND)
		gl.BlendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA)
		gl.Enable(gl.CULL_FACE)
		gl.Disable(gl.DEPTH_TEST)

		ctx.BeginFrame(winWidth, winHeight, pixelRatio)

		demo.RenderDemo(ctx, float32(mx), float32(my), float32(winWidth), float32(winHeight), t, blowup, demoData)
		fps.RenderGraph(ctx, 5, 5)

		ctx.EndFrame()

		gl.Enable(gl.DEPTH_TEST)
		window.SwapBuffers()
		glfw.PollEvents()
	}

	demoData.FreeData(ctx)
}
示例#4
0
func main() {
	if err := glfw.Init(gl.ContextWatcher); err != nil {
		panic(err)
	}
	defer glfw.Terminate()

	window, err := glfw.CreateWindow(400, 400, "", nil, nil)
	if err != nil {
		panic(err)
	}
	window.MakeContextCurrent()

	glfw.SwapInterval(1) // Vsync.

	framebufferSizeCallback := func(w *glfw.Window, framebufferSize0, framebufferSize1 int) {
		gl.Viewport(0, 0, framebufferSize0, framebufferSize1)

		var windowSize [2]int
		windowSize[0], windowSize[1] = w.GetSize()
		_, _ = windowSize[0], windowSize[1]

		/*inputEvent := InputEvent{
			Pointer:    windowPointer,
			EventTypes: map[EventType]struct{}{AXIS_EVENT: struct{}{}},
			InputId:    0,
			Buttons:    nil,
			Sliders:    nil,
			Axes:       []float64{float64(windowSize[0]), float64(windowSize[1])},
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)*/
	}
	{
		var framebufferSize [2]int
		framebufferSize[0], framebufferSize[1] = window.GetFramebufferSize()
		framebufferSizeCallback(window, framebufferSize[0], framebufferSize[1])
	}
	window.SetFramebufferSizeCallback(framebufferSizeCallback)

	var inputEventQueue []events.InputEvent
	mousePointer = &events.Pointer{VirtualCategory: events.POINTING}
	keyboardPointer = &events.Pointer{VirtualCategory: events.TYPING}

	window.SetMouseMovementCallback(func(w *glfw.Window, xpos, ypos, xdelta, ydelta float64) {
		inputEvent := events.InputEvent{
			Pointer:    mousePointer,
			EventTypes: map[events.EventType]struct{}{events.SLIDER_EVENT: {}},
			InputId:    0,
			Buttons:    nil,
			Sliders:    []float64{xdelta, ydelta},
		}
		if w.GetInputMode(glfw.CursorMode) != glfw.CursorDisabled {
			inputEvent.EventTypes[events.AXIS_EVENT] = struct{}{}
			inputEvent.Axes = []float64{xpos, ypos}
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	window.SetScrollCallback(func(w *glfw.Window, xoff float64, yoff float64) {
		inputEvent := events.InputEvent{
			Pointer:    mousePointer,
			EventTypes: map[events.EventType]struct{}{events.SLIDER_EVENT: {}},
			InputId:    2,
			Buttons:    nil,
			Sliders:    []float64{yoff, xoff},
			Axes:       nil,
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	window.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
		inputEvent := events.InputEvent{
			Pointer:     mousePointer,
			EventTypes:  map[events.EventType]struct{}{events.BUTTON_EVENT: {}},
			InputId:     uint16(button),
			Buttons:     []bool{action != glfw.Release},
			Sliders:     nil,
			Axes:        nil,
			ModifierKey: uint8(mods),
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scancode int, action glfw.Action, mods glfw.ModifierKey) {
		inputEvent := events.InputEvent{
			Pointer:     keyboardPointer,
			EventTypes:  map[events.EventType]struct{}{events.BUTTON_EVENT: {}},
			InputId:     uint16(key),
			Buttons:     []bool{action != glfw.Release},
			Sliders:     nil,
			Axes:        nil,
			ModifierKey: uint8(mods),
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)

		// HACK.
		switch {
		case key == glfw.Key1 && action == glfw.Press:
			window.SetInputMode(glfw.CursorMode, glfw.CursorNormal)
		case key == glfw.Key2 && action == glfw.Press:
			window.SetInputMode(glfw.CursorMode, glfw.CursorHidden)
		case key == glfw.Key3 && action == glfw.Press:
			window.SetInputMode(glfw.CursorMode, glfw.CursorDisabled)
		}
	})

	window.SetCharCallback(func(w *glfw.Window, char rune) {
		inputEvent := events.InputEvent{
			Pointer:    keyboardPointer,
			EventTypes: map[events.EventType]struct{}{events.CHARACTER_EVENT: {}},
			InputId:    uint16(char),
			Buttons:    nil,
			Sliders:    nil,
			Axes:       nil,
		}
		inputEventQueue = events.EnqueueInputEvent(inputEventQueue, inputEvent)
	})

	gl.ClearColor(0.85, 0.85, 0.85, 1)

	for !window.ShouldClose() {
		glfw.PollEvents()

		// Process Input.
		inputEventQueue = processInputEventQueue(inputEventQueue)

		gl.Clear(gl.COLOR_BUFFER_BIT)

		mousePointer.Render()

		window.SwapBuffers()
		runtime.Gosched()
	}
}
示例#5
0
func NewScreen(width, height int, caption string, resizable, fullScreen bool) *Screen {
	screen := &Screen{
		//cursor:  glfw.CursorNormal,
		caption: caption,
	}

	if runtime.GOARCH == "js" {
		glfw.WindowHint(glfw.Hint(0x00021101), 1) // enable stencil for nanovgo
	}
	glfw.WindowHint(glfw.Samples, 4)
	//glfw.WindowHint(glfw.RedBits, 8)
	//glfw.WindowHint(glfw.GreenBits, 8)
	//glfw.WindowHint(glfw.BlueBits, 8)
	glfw.WindowHint(glfw.AlphaBits, 8)
	//glfw.WindowHint(glfw.StencilBits, 8)
	//glfw.WindowHint(glfw.DepthBits, 8)
	//glfw.WindowHint(glfw.Visible, 0)
	if resizable {
		//glfw.WindowHint(glfw.Resizable, 1)
	} else {
		//glfw.WindowHint(glfw.Resizable, 0)
	}

	var err error
	if fullScreen {
		monitor := glfw.GetPrimaryMonitor()
		mode := monitor.GetVideoMode()
		screen.window, err = glfw.CreateWindow(mode.Width, mode.Height, caption, monitor, nil)
	} else {
		screen.window, err = glfw.CreateWindow(width, height, caption, nil, nil)
	}
	if err != nil {
		panic(err)
	}
	screen.window.MakeContextCurrent()
	gl.Viewport(0, 0, screen.fbW, screen.fbH)
	gl.ClearColor(0, 0, 0, 1)
	gl.Clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)
	glfw.SwapInterval(0)
	screen.window.SwapBuffers()

	/* Poll for events once before starting a potentially
	   lengthy loading process. This is needed to be
	   classified as "interactive" by other software such
	   as iTerm2 */

	if runtime.GOOS == "darwin" {
		glfw.PollEvents()
	}

	screen.window.SetCursorPosCallback(func(w *glfw.Window, xpos, ypos float64) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.cursorPositionCallbackEvent(xpos, ypos)
		}
	})

	screen.window.SetMouseButtonCallback(func(w *glfw.Window, button glfw.MouseButton, action glfw.Action, mods glfw.ModifierKey) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.mouseButtonCallbackEvent(button, action, mods)
		}
	})

	screen.window.SetKeyCallback(func(w *glfw.Window, key glfw.Key, scanCode int, action glfw.Action, mods glfw.ModifierKey) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.keyCallbackEvent(key, scanCode, action, mods)
		}
	})

	screen.window.SetCharCallback(func(w *glfw.Window, char rune) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.charCallbackEvent(char)
		}
	})

	screen.window.SetPreeditCallback(func(w *glfw.Window, text []rune, blocks []int, focusedBlock int) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.preeditCallbackEvent(text, blocks, focusedBlock)
		}
	})

	screen.window.SetIMEStatusCallback(func(w *glfw.Window) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.imeStatusCallbackEvent()
		}
	})

	screen.window.SetDropCallback(func(w *glfw.Window, names []string) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.dropCallbackEvent(names)
		}
	})

	screen.window.SetScrollCallback(func(w *glfw.Window, xoff float64, yoff float64) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.scrollCallbackEvent(float32(xoff), float32(yoff))
		}
	})

	screen.window.SetFramebufferSizeCallback(func(w *glfw.Window, width int, height int) {
		if screen, ok := nanoguiScreens[w]; ok {
			screen.resizeCallbackEvent(width, height)
		}
	})

	screen.Initialize(screen.window, true)
	InitWidget(screen, nil)
	return screen
}