[PATCH 3/4] d3drm: Initial support for storing animation keys
Nikolay Sivov
nsivov at codeweavers.com
Tue Jul 4 02:43:13 CDT 2017
Signed-off-by: Nikolay Sivov <nsivov at codeweavers.com>
---
dlls/d3drm/d3drm_private.h | 23 ++++++
dlls/d3drm/frame.c | 185 +++++++++++++++++++++++++++++++++++++++++++--
dlls/d3drm/meshbuilder.c | 2 +-
dlls/d3drm/tests/d3drm.c | 11 +--
4 files changed, 208 insertions(+), 13 deletions(-)
diff --git a/dlls/d3drm/d3drm_private.h b/dlls/d3drm/d3drm_private.h
index 1ce29e592e..067c0e6ffe 100644
--- a/dlls/d3drm/d3drm_private.h
+++ b/dlls/d3drm/d3drm_private.h
@@ -208,6 +208,24 @@ struct d3drm_material
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_object obj;
@@ -217,6 +235,9 @@ struct d3drm_animation
IDirect3DRM *d3drm;
IDirect3DRMFrame3 *frame;
D3DRMANIMATIONOPTIONS options;
+ struct d3drm_animation_keys position;
+ struct d3drm_animation_keys scale;
+ struct d3drm_animation_keys rotate;
};
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));
}
+BOOL d3drm_array_reserve(void **elements, SIZE_T *capacity, SIZE_T element_count, SIZE_T element_size) DECLSPEC_HIDDEN;
+
#endif /* __D3DRM_PRIVATE_INCLUDED__ */
diff --git a/dlls/d3drm/frame.c b/dlls/d3drm/frame.c
index f6b0a1fe14..fe339a2239 100644
--- a/dlls/d3drm/frame.c
+++ b/dlls/d3drm/frame.c
@@ -3095,6 +3095,9 @@ static ULONG WINAPI d3drm_animation2_Release(IDirect3DRMAnimation2 *iface)
{
d3drm_object_cleanup((IDirect3DRMObject *)&animation->IDirect3DRMAnimation_iface, &animation->obj);
IDirect3DRM_Release(animation->d3drm);
+ HeapFree(GetProcessHeap(), 0, animation->position.keys);
+ HeapFree(GetProcessHeap(), 0, animation->scale.keys);
+ HeapFree(GetProcessHeap(), 0, animation->rotate.keys);
HeapFree(GetProcessHeap(), 0, animation);
}
@@ -3288,11 +3291,133 @@ static HRESULT WINAPI d3drm_animation1_SetOptions(IDirect3DRMAnimation *iface, D
return d3drm_animation2_SetOptions(&animation->IDirect3DRMAnimation2_iface, options);
}
+static int d3drm_animation_cmp_min(const struct d3drm_animation_keys *keys, D3DVALUE left, D3DVALUE right, DWORD *cur)
+{
+ if (left == right)
+ {
+ while (*cur > 0 && left == keys->keys[*cur - 1].time)
+ (*cur)--;
+ return 0;
+ }
+
+ return (left < right) ? -1 : 1;
+}
+
+static int d3drm_animation_cmp_max(const struct d3drm_animation_keys *keys, D3DVALUE left, D3DVALUE right, DWORD *cur)
+{
+ if (left == right)
+ {
+ while (*cur < keys->count - 1 && left == keys->keys[*cur + 1].time)
+ (*cur)++;
+ return 0;
+ }
+
+ return (left < right) ? -1 : 1;
+}
+
+static DWORD d3drm_animation_get_index(struct d3drm_animation_keys *keys, D3DVALUE time,
+ int (*compare_func)(const struct d3drm_animation_keys *keys, D3DVALUE left, D3DVALUE right, DWORD *cur))
+{
+ int min = 0, max = keys->count - 1;
+ DWORD cur;
+
+ while (min <= max)
+ {
+ int cmp;
+
+ cur = (min + max) / 2;
+
+ cmp = compare_func(keys, time, keys->keys[cur].time, &cur);
+ if (cmp == 0)
+ break;
+
+ if (cmp < 0)
+ max = cur - 1;
+ else
+ min = cur + 1;
+ }
+
+ return cur;
+}
+
+static DWORD d3drm_animation_get_insert_position(struct d3drm_animation_keys *keys, D3DVALUE time)
+{
+ if (keys->count == 0)
+ return 0;
+
+ if (time < keys->keys[0].time)
+ return 0;
+
+ if (time >= keys->keys[keys->count - 1].time)
+ return keys->count;
+
+ return d3drm_animation_get_index(keys, time, d3drm_animation_cmp_max);
+}
+
+static BOOL d3drm_animation_get_range(struct d3drm_animation_keys *keys, D3DVALUE time_min, D3DVALUE time_max,
+ DWORD *min, DWORD *max)
+{
+ if (keys->count == 0)
+ return FALSE;
+
+ if (time_min > keys->keys[keys->count - 1].time || time_max < keys->keys[0].time)
+ return FALSE;
+
+ *min = d3drm_animation_get_index(keys, time_min, d3drm_animation_cmp_min);
+ *max = d3drm_animation_get_index(keys, time_max, d3drm_animation_cmp_max);
+
+ return TRUE;
+}
+
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;
+ DWORD 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)
@@ -3482,11 +3607,61 @@ static HRESULT WINAPI d3drm_animation2_ModifyKey(IDirect3DRMAnimation2 *iface, D
}
static HRESULT WINAPI d3drm_animation2_GetKeys(IDirect3DRMAnimation2 *iface, D3DVALUE time_min, D3DVALUE time_max,
- DWORD *key_count, D3DRMANIMATIONKEY *keys)
+ DWORD *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);
+ DWORD min, max, cur = 0, i;
- return E_NOTIMPL;
+ TRACE("iface %p, time min %.e, time max %.e, count %p, keys %p.\n", iface, time_min, time_max, count, keys);
+
+ if (!count)
+ return D3DRMERR_BADVALUE;
+
+ *count = 0;
+
+ if (d3drm_animation_get_range(&animation->rotate, time_min, time_max, &min, &max))
+ {
+ *count += max - min + 1;
+
+ for (i = min; i <= max && keys; i++, cur++)
+ {
+ keys[cur].dwSize = sizeof(*keys);
+ keys[cur].dwKeyType = D3DRMANIMATION_ROTATEKEY;
+ keys[cur].dvTime = animation->rotate.keys[i].time;
+ keys[cur].dwID = 0; /* FIXME */
+ keys[cur].u.dqRotateKey = animation->rotate.keys[i].u.rotate;
+ }
+ }
+
+ if (d3drm_animation_get_range(&animation->position, time_min, time_max, &min, &max))
+ {
+ *count += max - min + 1;
+
+ for (i = min; i <= max && keys; i++, cur++)
+ {
+ keys[cur].dwSize = sizeof(*keys);
+ keys[cur].dwKeyType = D3DRMANIMATION_POSITIONKEY;
+ keys[cur].dvTime = animation->position.keys[i].time;
+ keys[cur].dwID = 0; /* FIXME */
+ keys[cur].u.dvPositionKey = animation->position.keys[i].u.position;
+ }
+ }
+
+ if (d3drm_animation_get_range(&animation->scale, time_min, time_max, &min, &max))
+ {
+ *count += max - min + 1;
+
+ for (i = min; i <= max && keys; i++, cur++)
+ {
+ keys[cur].dwSize = sizeof(*keys);
+ keys[cur].dwKeyType = D3DRMANIMATION_SCALEKEY;
+ keys[cur].dvTime = animation->scale.keys[i].time;
+ keys[cur].dwID = 0; /* FIXME */
+ keys[cur].u.dvScaleKey = animation->scale.keys[i].u.scale;
+ }
+ }
+
+ return *count ? D3DRM_OK : D3DRMERR_NOSUCHKEY;
}
static const struct IDirect3DRMAnimationVtbl d3drm_animation1_vtbl =
diff --git a/dlls/d3drm/meshbuilder.c b/dlls/d3drm/meshbuilder.c
index e8e7f7e0f2..bb37678785 100644
--- a/dlls/d3drm/meshbuilder.c
+++ b/dlls/d3drm/meshbuilder.c
@@ -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;
void *new_elements;
diff --git a/dlls/d3drm/tests/d3drm.c b/dlls/d3drm/tests/d3drm.c
index 5fea2f0459..f19558e248 100644
--- a/dlls/d3drm/tests/d3drm.c
+++ b/dlls/d3drm/tests/d3drm.c
@@ -6885,11 +6885,8 @@ static void test_animation(void)
/* Key management. */
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);
-if (hr == S_OK)
-{
hr = IDirect3DRMAnimation_AddScaleKey(animation, 0.0f, 1.0f, 2.0f, 1.0f);
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);
+ todo_wine
+ {
switch (keys[i].dwKeyType)
{
case D3DRMANIMATION_ROTATEKEY:
@@ -6955,6 +6954,7 @@ if (hr == S_OK)
ok(0, "%u: unknown key type %d.\n", i, keys[i].dwKeyType);
}
}
+ }
/* No keys in this range. */
count = 10;
@@ -6970,17 +6970,14 @@ if (hr == S_OK)
count = 10;
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 0.0f, &count, NULL);
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);
hr = IDirect3DRMAnimation2_GetKeys(animation2, 0.0f, 100.0f, NULL, NULL);
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
/* Time is 0-based. */
- count = 123;
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, NULL, NULL);
ok(hr == D3DRMERR_BADVALUE, "Unexpected hr %#x.\n", hr);
- ok(count == 123, "Unexpected key count %u.\n", count);
count = 10;
hr = IDirect3DRMAnimation2_GetKeys(animation2, -100.0f, -50.0f, &count, NULL);
@@ -7018,7 +7015,7 @@ if (hr == S_OK)
key.dwKeyType = D3DRMANIMATION_POSITIONKEY;
hr = IDirect3DRMAnimation2_AddKey(animation2, &key);
ok(SUCCEEDED(hr), "Failed to add key, hr %#x.\n", hr);
-}
+
IDirect3DRMAnimation2_Release(animation2);
IDirect3DRMAnimation_Release(animation);
--
2.13.2
More information about the wine-patches
mailing list