Skip to content

Commit

Permalink
Fixes #3. Adds Entity Style. Begins work on #6
Browse files Browse the repository at this point in the history
  • Loading branch information
EriKWDev committed Apr 6, 2021
1 parent 572a850 commit c50947e
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 54 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/unittests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,5 @@ jobs:
with:
nim-version: ${{ matrix.nim }}

- run: nimble test -Y
- name: Run nimble test
run: nimble test -Y
8 changes: 2 additions & 6 deletions src/nanim.nim
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,14 @@ import
nanim/rendering,

# Entities
nanim/entities/circle,
nanim/entities/rectangle,
nanim/entities/text,
nanim/entities/engon,
nanim/entities/scene_entity
nanim/entities


export
core,
animation,
rendering,
circle, rectangle, text, engon, scene_entity
entities

# exporting these doesn't make sense in a normal library, but I can't bother importing them in every scene
import lenientops, glm
Expand Down
103 changes: 93 additions & 10 deletions src/nanim/core.nim
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,30 @@ type
AngleMode* = enum
amDegrees, amRadians

StyleMode* = enum
smSolidColor, smPaintPattern, smNone

Style* = ref tuple
fillMode: StyleMode
fillColor: Color
fillPattern: proc(context: NVGContext): Paint

strokeMode: StyleMode
strokeColor: Color
strokePattern: proc(context: NVGContext): Paint
strokeWidth: float

winding: PathWinding
lineCap: LineCapJoin
lineJoin: LineCapJoin
compositeOperation: CompositeOperation

Entity* = ref object of RootObj
points*: seq[Vec3[float]]

tension*: float
cornerRadius*: float
style*: Style

position*: Vec3[float]
rotation*: float
Expand Down Expand Up @@ -73,31 +92,80 @@ proc `$`*(entity: Entity): string =
" tension: " & $(entity.tension)


func newStyle*(): Style =
new(result)
result.fillMode = smPaintPattern
result.fillColor = rgb(255, 56, 116)
result.fillPattern = defaultPattern

result.strokeMode = smSolidColor
result.strokeColor = rgb(230, 26, 94)
result.strokePattern = defaultPattern
result.strokeWidth = 2.0

result.winding = pwCCW
result.lineCap = lcjRound
result.lineJoin = lcjMiter
result.compositeOperation = coSourceOver


proc setStyle*(context: NVGContext, style: Style) =
case style.fillMode:
of smSolidColor:
context.fillColor(style.fillColor)
of smPaintPattern:
context.fillPaint(style.fillPattern(context))
of smNone: discard

context.strokeWidth(style.strokeWidth)
case style.strokeMode:
of smSolidColor:
context.strokeColor(style.strokeColor)
of smPaintPattern:
context.strokePaint(style.strokePattern(context))
of smNone: context.strokeWidth(0.0)

context.pathWinding(style.winding)
context.lineJoin(style.lineJoin)
context.lineCap(style.lineCap)
context.globalCompositeOperation(style.compositeOperation)


proc executeStyle*(context: NVGContext, style: Style) =
case style.fillMode:
of smSolidColor, smPaintPattern:
context.fill()
of smNone: discard

case style.strokeMode:
of smSolidColor, smPaintPattern:
context.stroke()
of smNone: discard


proc applyStyle*(context: NVGContext, style: Style) =
context.setStyle(style)
context.executeStyle(style)


method draw*(entity: Entity, scene: Scene) {.base.} =
let context = scene.context
context.beginPath()

if entity.tension > 0:
context.drawPointsWithTension(entity.points, entity.tension)
else:
context.drawPointsWithRoundedCornerRadius(entity.points, entity.cornerRadius)

context.closePath()

# context.fillColor(rgb(255, 56, 116))
context.fillPaint(context.gridPattern())
context.fill()

context.strokeColor(rgb(230, 26, 94))
context.strokeWidth(5)
context.stroke()
context.applyStyle(entity.style)


func init*(entity: Entity) =
entity.points = @[]
entity.children = @[]
entity.tension = 0.0
entity.cornerRadius = 20.0
entity.style = newStyle()
entity.position = vec3(0.0, 0.0, 0.0)
entity.rotation = 0.0
entity.scaling = vec3(1.0, 1.0, 1.0)
Expand Down Expand Up @@ -343,6 +411,17 @@ proc setCornerRadius*(entity: Entity, cornerRadius: float = 0.0): Tween =
result = newTween(interpolators)


proc fill*(context: NVGContext, width: cfloat, height: cfloat, color: Color = rgb(255, 255, 255)) =
context.save()
context.fillColor(color)
context.beginPath()
context.resetTransform()
context.rect(0, 0, width, height)
context.closePath()
context.fill()
context.restore()


proc init(scene: Scene) =
scene.time = 0.0
scene.restartTime = 0.0
Expand All @@ -356,7 +435,11 @@ proc init(scene: Scene) =
vec4[float](0,0,1,0),
vec4[float](0,0,0,1))
scene.done = false
scene.background = proc(scene: Scene) = clearWithColor(rgb(255, 255, 255))

scene.background =
proc(scene: Scene) =
scene.context.fill(scene.width.cfloat, scene.height.cfloat, rgb(255, 255, 255))

scene.foreground = proc(scene: Scene) = discard


Expand Down
67 changes: 40 additions & 27 deletions src/nanim/drawing.nim
Original file line number Diff line number Diff line change
Expand Up @@ -57,58 +57,71 @@ proc drawPointsWithRoundedCornerRadius*(context: NVGContext, points: seq[Vec], c
context.arcTo(p1.x, p1.y, midPoint.x, midPoint.y, cornerRadius)


proc defaultPattern(context: NVGContext) =
proc defaultPatternDrawer*(context: NVGContext, width: float, height: float) =
context.beginPath()
context.circle(5, 1440-5, 3)
context.circle(width/2, height/2, width/2)
context.closePath()

context.fillColor(rgb(20, 20, 20))
context.fill()


proc offset(some: pointer; b: int): pointer {.inline.} =
result = cast[pointer](cast[int](some) + b)


var
patternPaint: Paint
hasGatheredPattern = false

proc gridPattern*(context: NVGContext, patternDrawer: proc(context: NVGContext) = defaultPattern, width: cint = 10, height: cint = 10): Paint =
# Impure, but worth it for the performance benefit...
if hasGatheredPattern:
proc gridPattern*(context: NVGContext,
patternDrawer: proc(context: NVGContext, width: float, height: float) = defaultPatternDrawer,
width: cint = 10,
height: cint = 10): Paint =

# Impure, but worth it for the performance benefit...
if hasGatheredPattern and false:
return patternPaint

let
bufferSize = width*height*4
oldTransformMatrix = context.currentTransform()
bufferSize = width * height * 4
tempContext = nvgCreateContext({nifStencilStrokes, nifDebug})

var
oldData = alloc0(bufferSize)
imageData = alloc0(bufferSize)
var imageData = alloc0(bufferSize)

context.endFrame()

glPixelStorei(GL_PACK_ALIGNMENT, 1)
glReadBuffer(GL_BACK)

glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, oldData)
# clear the region
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, imageData)

context.beginFrame(2880.cfloat, 1440.cfloat, 1)
patternDrawer(context)
context.endFrame()
# draw the pattern
let (frameBufferWidth, frameBufferHeight) = (2560, 1440)

tempContext.beginFrame(frameBufferWidth.cfloat, frameBufferHeight.cfloat, 1)
clearWithColor()
tempContext.translate(0, frameBufferHeight.float - height.float)
patternDrawer(tempContext, width.float, height.float)
tempContext.endFrame()

# read the region
glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, imageData)
var pixels: seq[uint8] = newSeq[uint8](bufferSize)
copyMem(pixels[0].unsafeAddr, imageData, bufferSize)

var pixels = newSeq[uint8](bufferSize)

# Flip the image
for y in 0..<height:
let
lineSize = width * 4
yDest = y * lineSize
ySrc = bufferSize - yDest - lineSize
copyMem(pixels[yDest].unsafeAddr, imageData.offset(ySrc), lineSize)

let image = context.createImageRGBA(width, height, {ifRepeatX, ifRepeatY, ifFlipY}, pixels)

patternPaint = context.imagePattern(0, 0, width.cfloat, height.cfloat, 0, image, 1.0)
hasGatheredPattern = true
result = patternPaint

context.beginFrame(2880.cfloat, 1440.cfloat, 1)
glDrawPixels(width, height, GL_RGBA, GL_UNSIGNED_BYTE, oldData)

dealloc(oldData)
dealloc(imageData)

context.transform(oldTransformMatrix.m[0], oldTransformMatrix.m[1], oldTransformMatrix.m[2],
oldTransformMatrix.m[3], oldTransformMatrix.m[4], oldTransformMatrix.m[5])

proc defaultPattern*(context: NVGContext): Paint =
context.gridPattern(defaultPatternDrawer, 10, 10)
10 changes: 10 additions & 0 deletions src/nanim/entities.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

import
nanim/entities/circle,
nanim/entities/rectangle,
nanim/entities/text,
nanim/entities/engon,
nanim/entities/scene_entity


export circle, rectangle, text, engon, scene_entity
10 changes: 2 additions & 8 deletions src/nanim/entities/text.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ type
proc init*(text: Text) =
init(text.Entity)
text.message = ""
text.style.fillMode = smSolidColor


method draw*(text: Text, scene: Scene) =
Expand All @@ -24,17 +25,10 @@ method draw*(text: Text, scene: Scene) =
context.fontSize(text.fontSize * 10)
context.fontFace(text.font)

context.setStyle(text.style)
context.beginPath()

context.fillColor(rgb(255, 56, 116))

context.strokeColor(rgb(230, 26, 94))
context.strokeWidth(20)

discard context.text(0, 0, text.message)
context.closePath()
context.stroke()
context.fill()


proc newText*(message: string = "",
Expand Down
10 changes: 8 additions & 2 deletions src/nanim/rendering.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ proc setupRendering(userScene: Scene, resizable: bool = true, width: int = 1920,
doAssert glInit()

glEnable(GL_MULTISAMPLE)
glEnable(GL_BLEND)
# glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

makeContextCurrent(scene.window)

Expand Down Expand Up @@ -247,6 +249,10 @@ proc render*(userScene: Scene) =
createVideo = true
width = 2880
height = 1440
of "2560p", "4k":
createVideo = true
width = 3840
height = 2160
else:
echo "Nanim (c) Copyright 2021 Erik Wilhem Gren"
echo ""
Expand All @@ -259,9 +265,9 @@ proc render*(userScene: Scene) =
echo " Enables video rendering mode. Will output video to renders/final.mp4"
echo " -fullhd, --1080p"
echo " Enables video rendering mode with 1080p settings"
echo " -2k, --1440p"
echo " --2k, --1440p"
echo " Enables video rendering mode with 1440p settings"
echo " -4k, --2160p"
echo " --4k, --2160p"
echo " Enables video rendering mode with 2160p settings"
echo " -w:WIDTH, --width:WIDTH"
echo " Sets width to WIDTH"
Expand Down

0 comments on commit c50947e

Please sign in to comment.