Skip to content

Instantly share code, notes, and snippets.

@zacharycarter
Created March 30, 2017 17:20
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zacharycarter/8a80dd9c6757b3cf50e4f14533eaca7a to your computer and use it in GitHub Desktop.
Save zacharycarter/8a80dd9c6757b3cf50e4f14533eaca7a to your computer and use it in GitHub Desktop.
import
frag/graphics/two_d/texture,
frag/graphics/two_d/vertex
import
attachment_vertices,
frag_spine,
spine,
util
type
AttachmentLoader* = ref object
super*: spAttachmentLoader
atlasAttachmentLoader*: ptr spAtlasAttachmentLoader
type
CreateAttachmentCallback = proc(loader: ptr spAttachmentLoader, skin: ptr spSkin, `type`: spAttachmentType, name, path: cstring): ptr spAttachment {.cdecl.}
DisposeCallback = proc(loader: ptr spAttachmentLoader) {.cdecl.}
ConfigureAttachmentCallback = proc(loader: ptr spAttachmentLoader, attachment: ptr spAttachment) {.cdecl.}
DisposeAttachmentCallback = proc(loader: ptr spAttachmentLoader, attachment: ptr spAttachment) {.cdecl.}
proc createAttachmentFunc(loader: ptr spAttachmentLoader, skin: ptr spSkin, `type`: spAttachmentType, name, path: cstring): ptr spAttachment {.cdecl.} =
let self = cast[AttachmentLoader](loader)
spAttachmentLoader_createAttachment(addr(self.atlasAttachmentLoader.super), skin, `type`, name, path)
proc disposeFunc(loader: ptr spAttachmentLoader) {.cdecl.} =
discard
proc configureAttachmentFunc(loader: ptr spAttachmentLoader, attachment: ptr spAttachment) {.cdecl.} =
attachment.attachmentLoader = loader
echo repr attachment.`type`
case attachment.`type`:
of SP_ATTACHMENT_REGION:
echo "HERE"
of SP_ATTACHMENT_MESH:
var meshAttachment = cast[ptr spMeshAttachment](attachment)
var region = cast[ptr spAtlasRegion](meshAttachment.rendererObject)
var attachmentVertices = AttachmentVertices(
texture: cast[Texture](region.page.rendererObject),
renderData: RenderData(
vertices: @[],
indices: convertToSeq[uint16, cushort](meshAttachment.triangles, meshAttachment.trianglesCount)
)
)
var ii = 0
for i in 0..<meshAttachment.super.worldVerticesLength:
attachmentVertices.renderData.vertices.add(
PosUVColorVertex(
u: meshAttachment.uvs.offset(ii)[0],
v: meshAttachment.uvs.offset(ii + 1)[0]
)
)
inc(ii, 2)
meshAttachment.rendererObject = cast[pointer](attachmentVertices)
else:
discard
proc disposeAttachmentFunc(loader: ptr spAttachmentLoader, attachment: ptr spAttachment) {.cdecl.} =
discard
var disposeFuncPtr : DisposeCallback = disposeFunc
var createAttachmentFuncPtr : CreateAttachmentCallback = createAttachmentFunc
var configureAttachmentFuncPtr : ConfigureAttachmentCallback = configureAttachmentFunc
var disposeAttachmentFuncPtr : DisposeAttachmentCallback = disposeAttachmentFunc
proc create*(atlas: ptr spAtlas): AttachmentLoader =
result = AttachmentLoader()
spAttachmentLoader_init(addr result.super, disposeFuncPtr, createAttachmentFuncPtr, configureAttachmentFuncPtr, disposeAttachmentFuncPtr)
result.atlasAttachmentLoader = spAtlasAttachmentLoader_create(atlas)
import
frag/graphics/two_d/texture,
frag/graphics/two_d/vertex
type
AttachmentVertices* = ref object
texture*: Texture
renderData*: RenderData
RenderData* = ref object
vertices*: seq[PosUVColorVertex]
indices*: seq[uint16]
{.experimental.}
import
events,
strutils
import
bgfxdotnim,
sdl2 as sdl
import
frag,
frag/events/app_event_handler,
frag/config,
frag/graphics/camera,
frag/graphics/two_d/vertex,
frag/graphics/window,
frag/logger,
frag/modules/graphics
import
frag_spine/attachment_loader,
frag_spine/attachment_vertices,
frag_spine/spine,
frag_spine/frag_spine,
frag_spine/spine_spritebatch
type
App = ref object
eventHandler: AppEventHandler
batch: SpineSpriteBatch
camera: Camera
const SPINE_MESH_VERTEX_COUNT_MAX = 1000
var drawable : SkeletonDrawable
var skeletonData : ptr spSkeletonData
var atlas : ptr spAtlas
var worldVertices: seq[cfloat] = newSeq[cfloat](1000)
var vertexArray: seq[PosUvColorVertex] = @[]
var triangleArray: seq[uint16] = @[]
var lastBlendMode: spBlendMode
const WIDTH = 960
const HEIGHT = 540
proc resize*(e: EventArgs) =
let event = SDLEventMessage(e).event
let sdlEventData = event.sdlEventData
# let app = cast[App](event.userData)
let graphics = event.graphics
graphics.setViewRect(0, 0, 0, uint16 sdlEventData.window.data1, uint16 sdlEventData.window.data2)
proc initializeApp(app: App, ctx: Frag) =
logDebug "Initializing app..."
app.eventHandler = AppEventHandler()
app.eventHandler.init(resize)
atlas = spAtlas_createFromFile("../spine-runtimes/examples/vine/export/vine.atlas", nil)
let attachmentLoader = cast[ptr spAttachmentLoader](attachment_loader.create(atlas))
let json = spSkeletonJson_createWithLoader(attachmentLoader)
json.scale = 0.5
skeletonData = spSkeletonJson_readSkeletonDataFile(json, "../spine-runtimes/examples/vine/export/vine.json")
spSkeletonJson_dispose(json)
#spBone_setYDown(1)
drawable = SkeletonDrawable(
skeleton: spSkeleton_create(skeletonData),
animationState: spAnimationState_create(spAnimationStateData_create(skeletonData)),
timeScale: 1,
ownsAnimationData: true
)
drawable.skeleton.x = 300
drawable.skeleton.y = 25
spSkeleton_updateWorldTransform(drawable.skeleton)
discard spAnimationState_setAnimationByName(drawable.animationState, 0, "animation", 1)
app.batch = SpineSpriteBatch(
blendSrcFunc: BlendFunc.SrcAlpha,
blendDstFunc: BlendFunc.InvSrcAlpha,
blendingEnabled: true
)
app.batch.init(1000, 0)
app.camera = Camera()
app.camera.init(0)
app.camera.ortho(1.0, WIDTH, HEIGHT)
logDebug "App initialized."
proc updateApp(app:App, ctx: Frag, deltaTime: float) =
app.camera.update()
app.batch.setProjectionMatrix(app.camera.combined)
if not drawable.isNil:
spSkeleton_update(drawable.skeleton, deltaTime)
spAnimationState_update(drawable.animationState, deltaTime * drawable.timeScale)
spAnimationState_apply(drawable.animationState, drawable.skeleton)
spSkeleton_updateWorldTransform(drawable.skeleton)
proc renderApp(app: App, ctx: Frag, deltaTime: float) =
ctx.graphics.clearView(0, ClearMode.Color.ord or ClearMode.Depth.ord, 0x303030ff, 1.0, 0)
app.batch.begin()
vertexArray.setLen(0)
var texture: Texture
var vertex = PosUVColorVertex()
if not drawable.isNil:
for i in 0..<drawable.skeleton.slotsCount:
let slot = drawable.skeleton.drawOrder.offset(i)[0]
let attachment = slot.attachment
if attachment.isNil:
continue
let blendMode = slot.data.blendMode
if blendMode != lastBlendMode:
echo "HERE"
app.batch.draw(texture, vertexArray, triangleArray)
vertexArray.setLen(0)
triangleArray.setLen(0)
lastBlendMode = blendMode
if attachment.`type` == SP_ATTACHMENT_REGION:
echo "HERE"
discard
elif attachment.`type` == SP_ATTACHMENT_MESH:
let mesh = cast[ptr spMeshAttachment](attachment)
if mesh.super.worldVerticesLength > 1000:
continue
let attachmentVertices = cast[AttachmentVertices](mesh.rendererObject)
texture = attachmentVertices.texture
spMeshAttachment_computeWorldVertices(mesh, slot, addr worldVertices[0])
triangleArray.add(attachmentVertices.renderData.indices)
let r = (drawable.skeleton.r * slot.r * 255).uint8
let g = (drawable.skeleton.g * slot.g * 255).uint8
let b = (drawable.skeleton.b * slot.b * 255).uint8
let a = (drawable.skeleton.a * slot.a * 255).uint8
vertex.abgr = (`shl`(a.uint8, 24) or `shl`(b.uint8, 16) or `shl`(g.uint8, 8) or r).uint32
vertex.abgr = 0xFFFFFFFF.uint32
#[for i in 0..<mesh.trianglesCount:
let index = `shl`(mesh.triangles.offset(i)[0], 1)
vertex.x = worldVertices[index.int]
vertex.y = worldVertices[index.int + 1]
vertex.z = 0
vertex.u = mesh.uvs.offset(index.int)[0]
vertex.v = mesh.uvs.offset(index.int + 1)[0]
vertexArray.add(vertex)]#
var w = 0
for i in 0..<`shr`(mesh.super.worldVerticesLength, 1):
attachmentVertices.renderData.vertices[i].x = worldVertices[w]
attachmentVertices.renderData.vertices[i].y = worldVertices[w + 1]
attachmentVertices.renderData.vertices[i].abgr = 0xFFFFFFFF.uint32
inc(w, 2)
vertexArray.add(attachmentVertices.renderData.vertices)
app.batch.draw(texture, vertexArray, triangleArray)
app.batch.`end`()
vertexArray.setLen(0)
triangleArray.setLen(0)
proc shutdownApp(app: App, ctx: Frag) =
logDebug "Shutting down app..."
logDebug "App shut down."
startFrag[App](Config(
rootWindowTitle: "FRAG Spine example 00",
rootWindowPosX: window.posUndefined, rootWindowPosY: window.posUndefined,
rootWindowWidth: 960, rootWindowHeight: 540,
resetFlags: ResetFlag.VSync,
logFileName: "example00.log",
assetRoot: "../assets",
debugMode: BGFX_DEBUG_TEXT
))
import
bgfxdotnim as bgfx
import
frag/logger,
frag/math/fpu_math as fpumath,
frag/modules/graphics,
frag/graphics/types,
frag/graphics/two_d/texture,
frag/graphics/two_d/texture_atlas,
frag/graphics/two_d/texture_region,
frag/graphics/two_d/vertex
when defined(windows):
import
frag/graphics/two_d/dx/fs_default_dx11,
frag/graphics/two_d/dx/vs_default_dx11
else:
import
frag/graphics/two_d/gl/fs_default,
frag/graphics/two_d/gl/vs_default
type
SpineSpriteBatch* = ref object
vertices: seq[PosUVColorVertex]
maxSprites: int
lastTexture: Texture
drawing: bool
programHandle: bgfx_program_handle_t
ibh: bgfx_dynamic_index_buffer_handle_t
vDecl: ptr bgfx_vertex_decl_t
texHandle: bgfx_uniform_handle_t
view: uint8
blendSrcFunc*, blendDstFunc*: BlendFunc
blendingEnabled*: bool
projectionMatrix*: fpumath.Mat4
proc setProjectionMatrix*(batch: SpineSpriteBatch, projectionMatrix: fpumath.Mat4) =
discard
batch.projectionMatrix = projectionMatrix
bgfx_set_view_transform(batch.view, nil, addr batch.projectionMatrix[0])
proc flush(SpineSpriteBatch: SpineSpriteBatch) =
if SpineSpriteBatch.lastTexture.isNil:
return
discard bgfx_touch(0)
let spriteCount = SpineSpriteBatch.vertices.len / 4
var vb : bgfx_transient_vertex_buffer_t
bgfx_alloc_transient_vertex_buffer(addr vb, uint32 SpineSpriteBatch.vertices.len, SpineSpriteBatch.vDecl);
copyMem(vb.data, addr SpineSpriteBatch.vertices[0], sizeof(PosUVColorVertex) * SpineSpriteBatch.vertices.len)
bgfx_set_texture(0, SpineSpriteBatch.texHandle, SpineSpriteBatch.lastTexture.handle, high(uint32))
bgfx_set_transient_vertex_buffer(addr vb, 0u32, uint32 SpineSpriteBatch.vertices.len)
var mtx: fpumath.Mat4
mtxIdentity(mtx)
discard bgfx_set_transform(addr mtx[0], 1)
if SpineSpriteBatch.blendingEnabled:
bgfx_set_state(0'u64 or BGFX_STATE_CULL_CCW or BGFX_STATE_RGB_WRITE or BGFX_STATE_ALPHA_WRITE or BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA
, BGFX_STATE_BLEND_INV_SRC_ALPHA), 0)
discard bgfx_submit(SpineSpriteBatch.view, SpineSpriteBatch.programHandle, 0, false)
SpineSpriteBatch.vertices.setLen(0)
proc switchTexture(SpineSpriteBatch: SpineSpriteBatch, texture: Texture) =
flush(SpineSpriteBatch)
SpineSpriteBatch.lastTexture = texture
proc drawRegion*(SpineSpriteBatch: SpineSpriteBatch, textureRegion: TextureRegion, x, y: float32, color: uint32 = 0xffffffff'u32) =
if not SpineSpriteBatch.drawing:
logError "SpineSpriteBatch not in drawing mode. Call begin before calling draw."
return
let texture = textureRegion.texture
if texture != SpineSpriteBatch.lastTexture:
switchTexture(SpineSpriteBatch, texture)
SpineSpriteBatch.vertices.add([
PosUVColorVertex(x: x, y: y, z: 0.0'f32, u:textureRegion.u, v:textureRegion.v, abgr: color ),
PosUVColorVertex(x: x + float textureRegion.regionWidth, y: y, z: 0.0'f32, u:textureRegion.u2, v:textureRegion.v, abgr: color ),
PosUVColorVertex(x: x + float textureRegion.regionWidth, y: y + float textureRegion.regionHeight, z: 0.0'f32, u:textureRegion.u2, v:textureRegion.v2, abgr: color ),
PosUVColorVertex(x: x, y: y + float textureRegion.regionHeight, z: 0.0'f32, u:textureRegion.u, v:textureRegion.v2, abgr: color ),
])
proc draw*(SpineSpriteBatch: SpineSpriteBatch, texture: Texture, vertices: openArray[PosUVColorVertex]) =
if not SpineSpriteBatch.drawing:
logError "SpineSpriteBatch not in drawing mode. Call begin before calling draw."
return
if texture != SpineSpriteBatch.lastTexture:
switchTexture(SpineSpriteBatch, texture)
SpineSpriteBatch.vertices.add(vertices)
proc draw*(SpineSpriteBatch: SpineSpriteBatch, texture: Texture, vertices: seq[PosUVColorVertex], indices: var seq[uint16]) =
if not SpineSpriteBatch.drawing:
logError "SpineSpriteBatch not in drawing mode. Call begin before calling draw."
return
if texture != SpineSpriteBatch.lastTexture:
switchTexture(SpineSpriteBatch, texture)
bgfx_update_dynamic_index_buffer(SpineSpriteBatch.ibh, 0, bgfx_copy(addr indices[0], uint32 indices.len * sizeof(uint16)))
SpineSpriteBatch.vertices.add(vertices)
proc init*(SpineSpriteBatch: SpineSpriteBatch, maxSprites: int, view: uint8) =
SpineSpriteBatch.drawing = false
SpineSpriteBatch.maxSprites = maxSprites
SpineSpriteBatch.vertices = @[]
SpineSpriteBatch.view = view
mtxIdentity(SpineSpriteBatch.projectionMatrix)
SpineSpriteBatch.vDecl = create(bgfx_vertex_decl_t)
#let indicesCount = maxSprites * 6
#var indexdata = newSeq[uint16](indicesCount)
#var i = 0
#var j = 0u16
#while i < indicesCount:
# indexdata[i] = j
# indexdata[i + 1] = j + 1
# indexdata[i + 2] = j + 2
# indexdata[i + 3] = j + 3
# indexdata[i + 4] = j
# indexdata[i + 5] = j + 2
# inc(j, 4)
# inc(i, 6)
#SpineSpriteBatch.ibh = bgfx_create_index_buffer(bgfx_copy(addr indexdata[0], uint32 indexdata.len * sizeof(uint16)), BGFX_BUFFER_NONE)
bgfx_set_dynamic_index_buffer(SpineSpriteBatch.ibh, 0, 0)
bgfx_vertex_decl_begin(SpineSpriteBatch.vDecl, BGFX_RENDERER_TYPE_NOOP)
bgfx_vertex_decl_add(SpineSpriteBatch.vDecl, BGFX_ATTRIB_POSITION, 3, BGFX_ATTRIB_TYPE_FLOAT, false, false)
bgfx_vertex_decl_add(SpineSpriteBatch.vDecl, BGFX_ATTRIB_TEXCOORD0, 2, BGFX_ATTRIB_TYPE_FLOAT, false, false)
bgfx_vertex_decl_add(SpineSpriteBatch.vDecl, BGFX_ATTRIB_COLOR0, 4, BGFX_ATTRIB_TYPE_UINT8, true, false)
bgfx_vertex_decl_end(SpineSpriteBatch.vDecl)
SpineSpriteBatch.texHandle = bgfx_create_uniform("s_texColor", BGFX_UNIFORM_TYPE_INT1, 1)
var vsh, fsh : bgfx_shader_handle_t
when defined(windows):
case bgfx_get_renderer_type()
of BGFX_RENDERER_TYPE_DIRECT3D11:
vsh = bgfx_create_shader(bgfx_make_ref(addr vs_default_dx11.vs[0], uint32 sizeof(vs_default_dx11.vs)))
fsh = bgfx_create_shader(bgfx_make_ref(addr fs_default_dx11.fs[0], uint32 sizeof(fs_default_dx11.fs)))
else:
discard
else:
vsh = bgfx_create_shader(bgfx_make_ref(addr vs_default.vs[0], uint32 sizeof(vs_default.vs)))
fsh = bgfx_create_shader(bgfx_make_ref(addr fs_default.fs[0], uint32 sizeof(fs_default.fs)))
SpineSpriteBatch.programHandle = bgfx_create_program(vsh, fsh, true)
proc begin*(SpineSpriteBatch: SpineSpriteBatch) =
if SpineSpriteBatch.drawing:
logError "SpineSpriteBatch is already in drawing mode. Call end before calling begin."
return
SpineSpriteBatch.drawing = true
proc `end`*(SpineSpriteBatch: SpineSpriteBatch) =
if not SpineSpriteBatch.drawing:
logError "SpineSpriteBatch is not currently in drawing mode. Call begin before calling end."
return
if SpineSpriteBatch.vertices.len > 0:
flush(SpineSpriteBatch)
SpineSpriteBatch.lastTexture = nil
SpineSpriteBatch.drawing = false
proc dispose*(SpineSpriteBatch: SpineSpriteBatch) =
bgfx_destroy_uniform(SpineSpriteBatch.texHandle)
bgfx_destroy_dynamic_index_buffer(SpineSpriteBatch.ibh)
let rendererType = bgfx_get_renderer_type()
if rendererType in [BGFX_RENDERER_TYPE_OPENGL, BGFX_RENDERER_TYPE_OPENGLES]:
bgfx_destroy_program(SpineSpriteBatch.programHandle)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment