Created
March 30, 2017 17:20
-
-
Save zacharycarter/8a80dd9c6757b3cf50e4f14533eaca7a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{.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 | |
)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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