d3drm: Initial support for storing animation keys.
Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
9f16e42e20
commit
6704fc8b20
|
@ -208,6 +208,24 @@ struct d3drm_material
|
||||||
struct color_rgb ambient;
|
struct color_rgb ambient;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct d3drm_animation_key
|
||||||
|
{
|
||||||
|
D3DVALUE time;
|
||||||
|
union
|
||||||
|
{
|
||||||
|
D3DVECTOR position;
|
||||||
|
D3DVECTOR scale;
|
||||||
|
D3DRMQUATERNION rotate;
|
||||||
|
} u;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct d3drm_animation_keys
|
||||||
|
{
|
||||||
|
struct d3drm_animation_key *keys;
|
||||||
|
SIZE_T count;
|
||||||
|
SIZE_T size;
|
||||||
|
};
|
||||||
|
|
||||||
struct d3drm_animation
|
struct d3drm_animation
|
||||||
{
|
{
|
||||||
struct d3drm_object obj;
|
struct d3drm_object obj;
|
||||||
|
@ -217,6 +235,9 @@ struct d3drm_animation
|
||||||
IDirect3DRM *d3drm;
|
IDirect3DRM *d3drm;
|
||||||
IDirect3DRMFrame3 *frame;
|
IDirect3DRMFrame3 *frame;
|
||||||
D3DRMANIMATIONOPTIONS options;
|
D3DRMANIMATIONOPTIONS options;
|
||||||
|
struct d3drm_animation_keys position;
|
||||||
|
struct d3drm_animation_keys scale;
|
||||||
|
struct d3drm_animation_keys rotate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct d3drm_wrap
|
struct d3drm_wrap
|
||||||
|
@ -282,4 +303,6 @@ static inline void d3drm_set_color(D3DCOLOR *color, float r, float g, float b, f
|
||||||
d3drm_color_component(b), d3drm_color_component(a));
|
d3drm_color_component(b), d3drm_color_component(a));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
#endif /* __D3DRM_PRIVATE_INCLUDED__ */
|
#endif /* __D3DRM_PRIVATE_INCLUDED__ */
|
||||||
|
|
|
@ -3095,6 +3095,9 @@ static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface)
|
||||||
{
|
{
|
||||||
d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
|
d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
|
||||||
IDirect3DRM_Release(animation->d3drm);
|
IDirect3DRM_Release(animation->d3drm);
|
||||||
|
HeapFree(GetProcessHeap(), 0, animation->rotate.keys);
|
||||||
|
HeapFree(GetProcessHeap(), 0, animation->scale.keys);
|
||||||
|
HeapFree(GetProcessHeap(), 0, animation->position.keys);
|
||||||
HeapFree(GetProcessHeap(), 0, animation);
|
HeapFree(GetProcessHeap(), 0, animation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3288,11 +3291,126 @@ static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D
|
||||||
return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
|
return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static SIZE_T d3drm_animation_lookup_key(const struct d3drm_animation_key *keys,
|
||||||
|
SIZE_T count, D3DVALUE time)
|
||||||
|
{
|
||||||
|
SIZE_T start = 0, cur = 0, end = count;
|
||||||
|
|
||||||
|
while (start < end)
|
||||||
|
{
|
||||||
|
cur = start + (end - start) / 2;
|
||||||
|
|
||||||
|
if (time == keys[cur].time)
|
||||||
|
return cur;
|
||||||
|
|
||||||
|
if (time < keys[cur].time)
|
||||||
|
end = cur;
|
||||||
|
else
|
||||||
|
start = cur + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return cur;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIZE_T d3drm_animation_get_index_min(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
|
||||||
|
{
|
||||||
|
SIZE_T i;
|
||||||
|
|
||||||
|
i = d3drm_animation_lookup_key(keys, count, time);
|
||||||
|
while (i > 0 && keys[i - 1].time == time)
|
||||||
|
--i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIZE_T d3drm_animation_get_index_max(const struct d3drm_animation_key *keys, SIZE_T count, D3DVALUE time)
|
||||||
|
{
|
||||||
|
SIZE_T i;
|
||||||
|
|
||||||
|
i = d3drm_animation_lookup_key(keys, count, time);
|
||||||
|
while (i < count - 1 && keys[i + 1].time == time)
|
||||||
|
++i;
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SIZE_T d3drm_animation_get_insert_position(const struct d3drm_animation_keys *keys, D3DVALUE time)
|
||||||
|
{
|
||||||
|
if (!keys->count || time < keys->keys[0].time)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (time >= keys->keys[keys->count - 1].time)
|
||||||
|
return keys->count;
|
||||||
|
|
||||||
|
return d3drm_animation_get_index_max(keys->keys, keys->count, time);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct d3drm_animation_key *d3drm_animation_get_range(const struct d3drm_animation_keys *keys,
|
||||||
|
D3DVALUE time_min, D3DVALUE time_max, SIZE_T *count)
|
||||||
|
{
|
||||||
|
SIZE_T min, max;
|
||||||
|
|
||||||
|
if (!keys->count || time_max < keys->keys[0].time
|
||||||
|
|| time_min > keys->keys[keys->count - 1].time)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
min = d3drm_animation_get_index_min(keys->keys, keys->count, time_min);
|
||||||
|
max = d3drm_animation_get_index_max(&keys->keys[min], keys->count - min, time_max);
|
||||||
|
|
||||||
|
*count = max - min + 1;
|
||||||
|
|
||||||
|
return &keys->keys[min];
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
|
static HRESULT WINAPI d3drm_animation2_AddKey(IDirect3DRMAnimation2 *iface, D3DRMANIMATIONKEY *key)
|
||||||
{
|
{
|
||||||
FIXME("iface %p, key %p.\n", iface, key);
|
struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
|
||||||
|
struct d3drm_animation_keys *keys;
|
||||||
|
SIZE_T index;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
TRACE("iface %p, key %p.\n", iface, key);
|
||||||
|
|
||||||
|
if (!key || key->dwSize != sizeof(*key))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
switch (key->dwKeyType)
|
||||||
|
{
|
||||||
|
case D3DRMANIMATION_POSITIONKEY:
|
||||||
|
keys = &animation->position;
|
||||||
|
break;
|
||||||
|
case D3DRMANIMATION_SCALEKEY:
|
||||||
|
keys = &animation->scale;
|
||||||
|
break;
|
||||||
|
case D3DRMANIMATION_ROTATEKEY:
|
||||||
|
keys = &animation->rotate;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return E_INVALIDARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
index = d3drm_animation_get_insert_position(keys, key->dvTime);
|
||||||
|
|
||||||
|
if (!d3drm_array_reserve((void **)&keys->keys, &keys->size, keys->count + 1, sizeof(*keys->keys)))
|
||||||
|
return E_OUTOFMEMORY;
|
||||||
|
|
||||||
|
if (index < keys->count)
|
||||||
|
memmove(&keys->keys[index + 1], &keys->keys[index], sizeof(*keys->keys) * (keys->count - index));
|
||||||
|
keys->keys[index].time = key->dvTime;
|
||||||
|
switch (key->dwKeyType)
|
||||||
|
{
|
||||||
|
case D3DRMANIMATION_POSITIONKEY:
|
||||||
|
keys->keys[index].u.position = key->u.dvPositionKey;
|
||||||
|
break;
|
||||||
|
case D3DRMANIMATION_SCALEKEY:
|
||||||
|
keys->keys[index].u.scale = key->u.dvScaleKey;
|
||||||
|
break;
|
||||||
|
case D3DRMANIMATION_ROTATEKEY:
|
||||||
|
keys->keys[index].u.rotate = key->u.dqRotateKey;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
++keys->count;
|
||||||
|
|
||||||
|
return D3DRM_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI d3drm_animation2_AddRotateKey(IDirect3DRMAnimation2 *iface, D3DVALUE time, D3DRMQUATERNION *q)
|
static HRESULT WINAPI d3drm_animation2_AddRotateKey(IDirect3DRMAnimation2 *iface, D3DVALUE time, D3DRMQUATERNION *q)
|
||||||
|
@ -3484,9 +3602,70 @@ static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D
|
||||||
static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
|
static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
|
||||||
DWORD *key_count, D3DRMANIMATIONKEY *keys)
|
DWORD *key_count, D3DRMANIMATIONKEY *keys)
|
||||||
{
|
{
|
||||||
FIXME("iface %p, time min %.e, time max %.e, count %p, keys %p.\n", iface, time_min, time_max, key_count, keys);
|
struct d3drm_animation *animation = impl_from_IDirect3DRMAnimation2(iface);
|
||||||
|
const struct d3drm_animation_key *key;
|
||||||
|
SIZE_T count, i;
|
||||||
|
|
||||||
return E_NOTIMPL;
|
TRACE("iface %p, time min %.8e, time max %.8e, key_count %p, keys %p.\n",
|
||||||
|
iface, time_min, time_max, key_count, keys);
|
||||||
|
|
||||||
|
if (!key_count)
|
||||||
|
return D3DRMERR_BADVALUE;
|
||||||
|
|
||||||
|
*key_count = 0;
|
||||||
|
|
||||||
|
if ((key = d3drm_animation_get_range(&animation->rotate, time_min, time_max, &count)))
|
||||||
|
{
|
||||||
|
if (keys)
|
||||||
|
{
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
keys[i].dwSize = sizeof(*keys);
|
||||||
|
keys[i].dwKeyType = D3DRMANIMATION_ROTATEKEY;
|
||||||
|
keys[i].dvTime = key[i].time;
|
||||||
|
keys[i].dwID = 0; /* FIXME */
|
||||||
|
keys[i].u.dqRotateKey = key[i].u.rotate;
|
||||||
|
}
|
||||||
|
keys += count;
|
||||||
|
}
|
||||||
|
*key_count += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key = d3drm_animation_get_range(&animation->position, time_min, time_max, &count)))
|
||||||
|
{
|
||||||
|
if (keys)
|
||||||
|
{
|
||||||
|
for (i = 0; i < count; ++i)
|
||||||
|
{
|
||||||
|
keys[i].dwSize = sizeof(*keys);
|
||||||
|
keys[i].dwKeyType = D3DRMANIMATION_POSITIONKEY;
|
||||||
|
keys[i].dvTime = key[i].time;
|
||||||
|
keys[i].dwID = 0; /* FIXME */
|
||||||
|
keys[i].u.dvPositionKey = key[i].u.position;
|
||||||
|
}
|
||||||
|
keys += count;
|
||||||
|
}
|
||||||
|
*key_count += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((key = d3drm_animation_get_range(&animation->scale, time_min, time_max, &count)))
|
||||||
|
{
|
||||||
|
if (keys)
|
||||||
|
{
|
||||||
|
for (i = 0; keys && i < count; ++i)
|
||||||
|
{
|
||||||
|
keys[i].dwSize = sizeof(*keys);
|
||||||
|
keys[i].dwKeyType = D3DRMANIMATION_SCALEKEY;
|
||||||
|
keys[i].dvTime = key[i].time;
|
||||||
|
keys[i].dwID = 0; /* FIXME */
|
||||||
|
keys[i].u.dvScaleKey = key[i].u.scale;
|
||||||
|
}
|
||||||
|
keys += count;
|
||||||
|
}
|
||||||
|
*key_count += count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return *key_count ? D3DRM_OK : D3DRMERR_NOSUCHKEY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
|
static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
|
||||||
|
|
|
@ -260,7 +260,7 @@ char templates[] = {
|
||||||
"}"
|
"}"
|
||||||
};
|
};
|
||||||
|
|
||||||
static BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size)
|
BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size)
|
||||||
{
|
{
|
||||||
SIZE_T new_capacity, max_capacity;
|
SIZE_T new_capacity, max_capacity;
|
||||||
void *new_elements;
|
void *new_elements;
|
||||||
|
|
|
@ -6885,11 +6885,8 @@ static void test_animation(void)
|
||||||
|
|
||||||
/* Key management. */
|
/* Key management. */
|
||||||
hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 1.0f, 0.0f, 0.0f);
|
hr = IDirect3DRMAnimation_AddPositionKey(animation, 0.0f, 1.0f, 0.0f, 0.0f);
|
||||||
todo_wine
|
|
||||||
ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
|
ok(SUCCEEDED(hr), "Failed to add position key, hr %#x.\n", hr);
|
||||||
|
|
||||||
if (hr == S_OK)
|
|
||||||
{
|
|
||||||
hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
|
hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
|
||||||
ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr);
|
ok(SUCCEEDED(hr), "Failed to add scale key, hr %#x.\n", hr);
|
||||||
|
|
||||||
|
@ -6940,6 +6937,8 @@ if (hr == S_OK)
|
||||||
{
|
{
|
||||||
ok(keys[i].dwSize == sizeof(*keys), "%u: unexpected dwSize value %u.\n", i, keys[i].dwSize);
|
ok(keys[i].dwSize == sizeof(*keys), "%u: unexpected dwSize value %u.\n", i, keys[i].dwSize);
|
||||||
|
|
||||||
|
todo_wine
|
||||||
|
{
|
||||||
switch (keys[i].dwKeyType)
|
switch (keys[i].dwKeyType)
|
||||||
{
|
{
|
||||||
case D3DRMANIMATION_ROTATEKEY:
|
case D3DRMANIMATION_ROTATEKEY:
|
||||||
|
@ -6955,6 +6954,7 @@ if (hr == S_OK)
|
||||||
ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType);
|
ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* No keys in this range. */
|
/* No keys in this range. */
|
||||||
count = 10;
|
count = 10;
|
||||||
|
@ -6970,17 +6970,14 @@ if (hr == S_OK)
|
||||||
count = 10;
|
count = 10;
|
||||||
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL);
|
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL);
|
||||||
ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
|
ok(SUCCEEDED(hr), "Failed to get animation keys, hr %#x.\n", hr);
|
||||||
ok(hr == S_OK, "Failed to get animation keys, hr %#x.\n", hr);
|
|
||||||
ok(count == 4, "Unexpected key count %u.\n", count);
|
ok(count == 4, "Unexpected key count %u.\n", count);
|
||||||
|
|
||||||
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL);
|
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL);
|
||||||
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
|
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
|
||||||
|
|
||||||
/* Time is 0-based. */
|
/* Time is 0-based. */
|
||||||
count = 123;
|
|
||||||
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL);
|
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL);
|
||||||
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
|
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
|
||||||
ok(count == 123, "Unexpected key count %u.\n", count);
|
|
||||||
|
|
||||||
count = 10;
|
count = 10;
|
||||||
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL);
|
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL);
|
||||||
|
@ -7018,7 +7015,7 @@ if (hr == S_OK)
|
||||||
key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
|
key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
|
||||||
hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
|
hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
|
||||||
ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr);
|
ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr);
|
||||||
}
|
|
||||||
IDirect3DRMAnimation2_Release(animation2);
|
IDirect3DRMAnimation2_Release(animation2);
|
||||||
IDirect3DRMAnimation_Release(animation);
|
IDirect3DRMAnimation_Release(animation);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue