added manyloc test suite; --path now relative to project dir if not absolute
This commit is contained in:
parent
4f09794be9
commit
75b508032b
51 changed files with 9286 additions and 5 deletions
281
tests/manyloc/keineschweine/lib/sg_gui.nim
Normal file
281
tests/manyloc/keineschweine/lib/sg_gui.nim
Normal file
|
|
@ -0,0 +1,281 @@
|
|||
import
|
||||
sfml, sfml_colors,
|
||||
input_helpers, sg_packets
|
||||
from strutils import countlines
|
||||
{.deadCodeElim: on.}
|
||||
type
|
||||
PGuiContainer* = ref TGuiContainer
|
||||
TGuiContainer* = object of TObject
|
||||
position: TVector2f
|
||||
activeEntry: PTextEntry
|
||||
widgets: seq[PGuiObject]
|
||||
buttons: seq[PButton]
|
||||
PGuiObject* = ref TGuiObject
|
||||
TGuiObject* = object of TObject
|
||||
PButton* = ref TButton
|
||||
TButton* = object of TGuiObject
|
||||
enabled: bool
|
||||
bg*: sfml.PRectangleShape
|
||||
text*: PText
|
||||
onClick*: TButtonClicked
|
||||
bounds: TFloatRect
|
||||
PButtonCollection* = ref TButtonCollection
|
||||
TButtonCollection* = object of TGuiContainer
|
||||
PTextEntry* = ref TTextEntry
|
||||
TTextEntry* = object of TButton
|
||||
inputClient: input_helpers.PTextInput
|
||||
PMessageArea* = ref TMessageArea
|
||||
TMessageArea* = object of TGuiObject
|
||||
pos: TVector2f
|
||||
messages: seq[TMessage]
|
||||
texts: seq[PText]
|
||||
scrollBack*: int
|
||||
sizeVisible*: int
|
||||
direction*: int
|
||||
TMessage = object
|
||||
color: TColor
|
||||
text: string
|
||||
lines: int
|
||||
TButtonClicked = proc(button: PButton)
|
||||
var
|
||||
guiFont* = newFont("data/fnt/LiberationMono-Regular.ttf")
|
||||
messageProto* = newText("", guiFont, 16)
|
||||
let
|
||||
vectorZeroF* = vec2f(0.0, 0.0)
|
||||
|
||||
proc newGuiContainer*(): PGuiContainer
|
||||
proc newGuiContainer*(pos: TVector2f): PGuiContainer {.inline.}
|
||||
proc free*(container: PGuiContainer)
|
||||
proc add*(container: PGuiContainer; widget: PGuiObject)
|
||||
proc clearButtons*(container: PGuiContainer)
|
||||
proc click*(container: PGuiContainer; position: TVector2f)
|
||||
proc setActive*(container: PGuiContainer; entry: PTextEntry)
|
||||
proc setPosition*(container: PGuiContainer; position: TVector2f)
|
||||
|
||||
proc update*(container: PGuiContainer; dt: float)
|
||||
proc draw*(window: PRenderWindow; container: PGuiContainer) {.inline.}
|
||||
|
||||
proc newMessageArea*(container: PGuiContainer; position: TVector2f): PMessageArea {.discardable.}
|
||||
proc add*(m: PMessageArea; msg: ScChat)
|
||||
|
||||
proc draw*(window: PRenderWindow; b: PButton) {.inline.}
|
||||
proc click*(b: PButton; p: TVector2f)
|
||||
proc setPosition*(b: PButton; p: TVector2f)
|
||||
proc setString*(b: PButton; s: string) {.inline.}
|
||||
|
||||
proc newButton*(container: PGuiContainer; text: string; position: TVector2f;
|
||||
onClick: TButtonClicked; startEnabled: bool = true): PButton {.discardable.}
|
||||
proc init(b: PButton; text: string; position: TVector2f; onClick: TButtonClicked)
|
||||
proc setEnabled*(b: PButton; enabled: bool)
|
||||
proc disable*(b: PButton) {.inline.}
|
||||
proc enable*(b: PButton) {.inline.}
|
||||
|
||||
proc newTextEntry*(container: PGuiContainer; text: string;
|
||||
position: TVector2f; onEnter: TInputFinishedProc = nil): PTextEntry {.discardable.}
|
||||
proc init(t: PTextEntry; text: string; onEnter: TInputFinishedProc)
|
||||
proc draw*(window: PRenderWindow, t: PTextEntry) {.inline.}
|
||||
proc setActive*(t: PTextEntry) {.inline.}
|
||||
proc clearText*(t: PTextEntry) {.inline.}
|
||||
proc getText*(t: PTextEntry): string {.inline.}
|
||||
|
||||
proc update*(m: PMessageArea)
|
||||
|
||||
if guiFont == nil:
|
||||
echo("Could not load font, crying softly to myself.")
|
||||
quit(1)
|
||||
|
||||
proc newGuiContainer*(): PGuiContainer =
|
||||
new(result, free)
|
||||
result.widgets = @[]
|
||||
result.buttons = @[]
|
||||
proc newGuiContainer*(pos: TVector2f): PGuiContainer =
|
||||
result = newGuiContainer()
|
||||
result.setPosition pos
|
||||
proc free*(container: PGuiContainer) =
|
||||
container.widgets = nil
|
||||
container.buttons = nil
|
||||
proc add*(container: PGuiContainer; widget: PGuiObject) =
|
||||
container.widgets.add(widget)
|
||||
proc add*(container: PGuiContainer; button: PButton) =
|
||||
if container.isNil: return
|
||||
container.buttons.add(button)
|
||||
proc clearButtons*(container: PGuiContainer) =
|
||||
container.buttons.setLen 0
|
||||
proc click*(container: PGuiContainer; position: TVector2f) =
|
||||
for b in container.buttons:
|
||||
click(b, position)
|
||||
proc setActive*(container: PGuiContainer; entry: PTextEntry) =
|
||||
container.activeEntry = entry
|
||||
setActive(entry)
|
||||
proc setPosition*(container: PGuiContainer; position: TVector2f) =
|
||||
container.position = position
|
||||
|
||||
|
||||
proc update*(container: PGuiContainer; dt: float) =
|
||||
if not container.activeEntry.isNil:
|
||||
container.activeEntry.setString(container.activeEntry.getText())
|
||||
proc draw*(window: PRenderWindow; container: PGuiContainer) =
|
||||
for b in container.buttons:
|
||||
window.draw b
|
||||
|
||||
proc free(c: PButton) =
|
||||
c.bg.destroy()
|
||||
c.text.destroy()
|
||||
c.bg = nil
|
||||
c.text = nil
|
||||
c.onClick = nil
|
||||
proc newButton*(container: PGuiContainer; text: string;
|
||||
position: TVector2f; onClick: TButtonClicked;
|
||||
startEnabled: bool = true): PButton =
|
||||
new(result, free)
|
||||
init(result,
|
||||
text,
|
||||
if not container.isNil: position + container.position else: position,
|
||||
onClick)
|
||||
container.add result
|
||||
if not startEnabled: disable(result)
|
||||
|
||||
proc init(b: PButton; text: string; position: TVector2f; onClick: TButtonClicked) =
|
||||
b.bg = newRectangleShape()
|
||||
b.bg.setSize(vec2f(80.0, 16.0))
|
||||
b.bg.setFillColor(color(20, 30, 15))
|
||||
b.text = newText(text, guiFont, 16)
|
||||
b.onClick = onClick
|
||||
b.setPosition(position)
|
||||
b.enabled = true
|
||||
proc copy*(c: PButton): PButton =
|
||||
new(result, free)
|
||||
result.bg = c.bg.copy()
|
||||
result.text = c.text.copy()
|
||||
result.onClick = c.onClick
|
||||
result.setPosition(result.bg.getPosition())
|
||||
|
||||
proc setEnabled*(b: PButton; enabled: bool) =
|
||||
b.enabled = enabled
|
||||
if enabled:
|
||||
b.text.setColor(White)
|
||||
else:
|
||||
b.text.setColor(Gray)
|
||||
proc enable*(b: PButton) = setEnabled(b, true)
|
||||
proc disable*(b: PButton) = setEnabled(b, false)
|
||||
|
||||
proc draw*(window: PRenderWindow; b: PButton) =
|
||||
window.draw b.bg
|
||||
window.draw b.text
|
||||
proc setPosition*(b: PButton, p: TVector2f) =
|
||||
b.bg.setPosition(p)
|
||||
b.text.setPosition(p)
|
||||
b.bounds = b.text.getGlobalBounds()
|
||||
proc setString*(b: PButton; s: string) =
|
||||
b.text.setString(s)
|
||||
proc click*(b: PButton, p: TVector2f) =
|
||||
if b.enabled and (addr b.bounds).contains(p.x, p.y):
|
||||
b.onClick(b)
|
||||
|
||||
proc free(obj: PTextEntry) =
|
||||
free(PButton(obj))
|
||||
proc newTextEntry*(container: PGuiContainer; text: string;
|
||||
position: TVector2F; onEnter: TInputFinishedProc = nil): PTextEntry =
|
||||
new(result, free)
|
||||
init(PButton(result), text, position + container.position, proc(b: PButton) =
|
||||
setActive(container, PTextEntry(b)))
|
||||
init(result, text, onEnter)
|
||||
container.add result
|
||||
proc init(t: PTextEntry; text: string; onEnter: TInputFinishedProc) =
|
||||
t.inputClient = newTextInput(text, text.len, onEnter)
|
||||
proc draw(window: PRenderWindow; t: PTextEntry) =
|
||||
window.draw PButton(t)
|
||||
proc clearText*(t: PTextEntry) =
|
||||
t.inputClient.clear()
|
||||
proc getText*(t: PTextEntry): string =
|
||||
return t.inputClient.text
|
||||
proc setActive*(t: PTextEntry) =
|
||||
if not t.isNil and not t.inputClient.isNil:
|
||||
input_helpers.setActive(t.inputClient)
|
||||
|
||||
|
||||
discard """proc newMessageArea*(container: PGuiContainer; position: TVector2f): PMessageArea =
|
||||
new(result)
|
||||
result.messages = @[]
|
||||
result.pos = position
|
||||
container.add(result)
|
||||
proc add*(m: PMessageArea, text: string): PText =
|
||||
result = messageProto.copy()
|
||||
result.setString(text)
|
||||
m.messages.add(result)
|
||||
let nmsgs = len(m.messages)
|
||||
var pos = vec2f(m.pos.x, m.pos.y)
|
||||
for i in countdown(nmsgs - 1, max(nmsgs - 30, 0)):
|
||||
setPosition(m.messages[i], pos)
|
||||
pos.y -= 16.0
|
||||
|
||||
proc draw*(window: PRenderWindow; m: PMessageArea) =
|
||||
let nmsgs = len(m.messages)
|
||||
if nmsgs == 0: return
|
||||
for i in countdown(nmsgs - 1, max(nmsgs - 30, 0)):
|
||||
window.draw(m.messages[i])
|
||||
"""
|
||||
proc newMessageArea*(container: PGuiContainer; position: TVector2f): PMessageArea =
|
||||
new(result)
|
||||
result.messages = @[]
|
||||
result.texts = @[]
|
||||
result.pos = position + container.position
|
||||
result.sizeVisible = 10
|
||||
result.scrollBack = 0
|
||||
result.direction = -1 ## to push old messages up
|
||||
container.add(result)
|
||||
|
||||
proc add*(m: PMessageArea, msg: ScChat) =
|
||||
const prependName = {CPub, CPriv}
|
||||
var mmm: TMessage
|
||||
if msg.kind in prependName:
|
||||
mmm.text = "<"
|
||||
mmm.text.add msg.fromPlayer
|
||||
mmm.text.add "> "
|
||||
mmm.text.add msg.text
|
||||
else:
|
||||
mmm.text = msg.text
|
||||
case msg.kind
|
||||
of CPub: mmm.color = RoyalBlue
|
||||
of CPriv, CSystem: mmm.color = Green
|
||||
of CError: mmm.color = Red
|
||||
|
||||
mmm.lines = countLines(mmm.text)+1
|
||||
|
||||
m.messages.add mmm
|
||||
update m
|
||||
proc add*(m: PMessageArea, msg: string) {.inline.} =
|
||||
var chat = newScChat(kind = CSystem, text = msg)
|
||||
add(m, chat)
|
||||
|
||||
proc proctor*(m: PText; msg: ptr TMessage; pos: ptr TVector2f) =
|
||||
m.setString msg.text
|
||||
m.setColor msg.color
|
||||
m.setPosition pos[]
|
||||
proc update*(m: PMessageArea) =
|
||||
if m.texts.len < m.sizeVisible:
|
||||
echo "adding ", m.sizeVisible - m.texts.len, " fields"
|
||||
for i in 1..m.sizeVisible - m.texts.len:
|
||||
var t = messageProto.copy()
|
||||
m.texts.add messageProto.copy()
|
||||
elif m.texts.len > m.sizeVisible:
|
||||
echo "cutting ", m.texts.len - m.sizeVisible, " fields"
|
||||
for i in m.sizeVisible.. < m.texts.len:
|
||||
m.texts.pop().destroy()
|
||||
let nmsgs = m.messages.len()
|
||||
if m.sizeVisible == 0 or nmsgs == 0:
|
||||
echo "no messages? ", m.sizeVisible, ", ", nmsgs
|
||||
return
|
||||
var pos = vec2f(m.pos.x, m.pos.y)
|
||||
for i in 0.. min(m.sizeVisible, nmsgs)-1:
|
||||
##echo nmsgs - i - 1 - m.scrollBack
|
||||
let msg = addr m.messages[nmsgs - i - 1 - m.scrollBack]
|
||||
proctor(m.texts[i], msg, addr pos)
|
||||
pos.y += (16 * m.direction * msg.lines).cfloat
|
||||
|
||||
proc draw*(window: PRenderWindow; m: PMessageArea) =
|
||||
let nmsgs = len(m.texts)
|
||||
if nmsgs == 0: return
|
||||
for i in countdown(nmsgs - 1, max(nmsgs - m.sizeVisible, 0)):
|
||||
window.draw m.texts[i]
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue