Animation & blend file: Preliminary support for actions.
This commit is contained in:
parent
fc39a93a94
commit
45cc6dac00
2 changed files with 110 additions and 0 deletions
|
@ -293,10 +293,70 @@ proc idPropertiesToJsonTable(prop: FNode): Table[string, JsonNode] =
|
|||
else: discard
|
||||
prop = prop.next
|
||||
|
||||
proc loadFCurveImpl(self: BlendLoader, fcurve: FNode): (string, AnimationChannel) =
|
||||
let path = fcurve.rna_path.str
|
||||
let chan = new AnimationChannel
|
||||
let path_parts = path.rsplit('.',1)
|
||||
if path_parts.len == 1:
|
||||
chan.channel_type = ChObject
|
||||
else:
|
||||
if path.startswith "key_blocks[":
|
||||
chan.channel_type = ChShape
|
||||
chan.name = path.split('"')[1]
|
||||
elif path.startswith "pose.bones[":
|
||||
return # TODO
|
||||
else:
|
||||
echo "Warning: unknown channel path ", path
|
||||
return
|
||||
chan.property = case path_parts[^1]:
|
||||
of "value": PropValue
|
||||
of "location": PropPosition
|
||||
of "rotation_euler": PropRotationEuler
|
||||
of "rotation_quaternion": PropRotationQuaternion
|
||||
of "scale": PropScale
|
||||
else:
|
||||
echo "Warning: unknown property ", path
|
||||
return
|
||||
chan.index = fcurve.array_index.i32[0]
|
||||
if chan.property == PropRotationQuaternion:
|
||||
chan.index = (chan.index - 1) and 3
|
||||
let count = fcurve.totvert.i32[0]
|
||||
for i,floats in fcurve.bezt[0 ..< count].vec:
|
||||
let fs = floats.f32
|
||||
chan.points.add BezierPoint(
|
||||
# left_handle: vec2(fs[0], fs[1]),
|
||||
co: vec2(fs[3], fs[4]),
|
||||
# right_handle: vec2(fs[6], fs[7]),
|
||||
)
|
||||
if chan.property != PropValue:
|
||||
return (&"{path}[{chan.index}]", chan)
|
||||
else:
|
||||
return (path, chan)
|
||||
|
||||
proc loadActionImpl(self: BlendLoader, acn: FNode): Action =
|
||||
new(result)
|
||||
let flags = acn.flag.i32[0]
|
||||
result.manual_range = (flags and 4096).bool
|
||||
result.frame_start = acn.frame_start.f32[0]
|
||||
result.frame_end = acn.frame_end.f32[0]
|
||||
var curve = acn.curves.first
|
||||
while curve.valid:
|
||||
let (path, ch) = self.loadFCurveImpl(curve)
|
||||
if ch != nil:
|
||||
result.channels[path] = ch
|
||||
curve = curve.next
|
||||
|
||||
proc loadAction*(self: BlendLoader, name: string): Action =
|
||||
for n in self.blend_file.named_blocks["AC"]:
|
||||
if n.id.name.str.strip2 == name:
|
||||
return self.loadActionImpl(n)
|
||||
raise KeyError.newException &"Could not find action '{name}'"
|
||||
|
||||
proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, string) =
|
||||
let name = obn.id.name.str.strip2
|
||||
let data = obn.data
|
||||
let ob = case obn["type"].i16[0]:
|
||||
var shape_key_adt: FNode
|
||||
of BMesh.int16:
|
||||
var ob = self.engine.new_mesh(name=name)
|
||||
let mat_count = obn.totcol.i32[0]
|
||||
|
@ -377,6 +437,8 @@ proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, s
|
|||
if v.vtype == Tangent and v.attname notin tangents:
|
||||
tangents.add v.attname
|
||||
|
||||
if data.key.valid:
|
||||
shape_key_adt = data.key.adt
|
||||
# TODO: defer this by storing the name of the mesh as hash
|
||||
# (maybe the address too)
|
||||
|
||||
|
@ -514,6 +576,20 @@ proc loadObjectImpl(self: BlendLoader, scene: Scene, obn: FNode): (GameObject, s
|
|||
|
||||
ob.object_color = obn.col.f32.vec4
|
||||
|
||||
var animation_datas: seq[FNode]
|
||||
for adt in [obn.adt, shape_key_adt]:
|
||||
if adt.valid:
|
||||
animation_datas.add adt
|
||||
# TODO: make animation strips. we'll just merge the actions for now.
|
||||
for adt in animation_datas:
|
||||
if adt.action.valid:
|
||||
let ac = self.loadActionImpl(adt.action)
|
||||
if ob.action == nil:
|
||||
ob.action = ac
|
||||
else:
|
||||
for k,v in ac.channels:
|
||||
ob.action.channels[k] = v
|
||||
|
||||
let prop = obn.id.properties
|
||||
if prop.valid:
|
||||
ob.properties = idPropertiesToJsonTable(prop.data.group.first)
|
||||
|
|
|
@ -125,6 +125,7 @@ type
|
|||
# probe_cube*: Probe
|
||||
# probe_planar*: Probe
|
||||
properties*: Table[string, JsonNode]
|
||||
action*: Action # TODO: remove when strips are implemented
|
||||
# animation_strips*: seq[AnimationStrip]
|
||||
name*: string
|
||||
original_name*: string
|
||||
|
@ -823,6 +824,39 @@ type
|
|||
cache_dir_bc*: string ## Cache directory for writing bc
|
||||
cache_dir_astc*: string ## Cache directory for writing astc
|
||||
|
||||
# action.nim
|
||||
|
||||
Action* = ref object
|
||||
manual_range*: bool
|
||||
frame_start*, frame_end*: float32
|
||||
channels*: OrderedTable[string, AnimationChannel]
|
||||
|
||||
ChannelType* = enum
|
||||
ChObject
|
||||
ChPose
|
||||
ChShape
|
||||
ChObProperty
|
||||
|
||||
ChannelProperty* = enum
|
||||
PropValue
|
||||
PropPosition
|
||||
PropRotationEuler
|
||||
PropRotationQuaternion
|
||||
PropScale
|
||||
|
||||
AnimationChannel* = ref object
|
||||
channel_type*: ChannelType
|
||||
name*: string
|
||||
property*: ChannelProperty
|
||||
property_name*: string
|
||||
index*: int
|
||||
points*: seq[BezierPoint]
|
||||
last_eval_point*: int
|
||||
|
||||
BezierPoint* = object
|
||||
# left_handle*: Vec2
|
||||
co*: Vec2
|
||||
# right_handle*: Vec2
|
||||
|
||||
# INCOMPLETE
|
||||
|
||||
|
|
Loading…
Reference in a new issue