public static void Remove(PtrLst *self, void *ptr) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); int oldCount = self->count; #endif void **arr = self->arr; int i = 0, len = self->count; while (i < len && arr[i] != ptr) { i += 1; } if (i < len) // arr[i] == p // for (len = self->count -= 1; i < len; i += 1) arr[i] = arr[i + 1]; { byte *src = (byte *)(arr + i); int size = self->size; int count = self->count -= 1; Mem.Memmove(src, src + size, (count - i) * size); } #if FDB else { Fdb.Error("{0:X} does not exist in PtrLst {1:X}", (ulong)ptr, (ulong)self); } Should.Equal("self->count", self->count, oldCount - 1); #endif }
public static void Init(PtrIntDict *self) { #if FDB Should.NotNull("self", self); self->type = Type; #endif self->tag = Tag.PtrIntDict; int level = self->level = 0; int len = self->len = Const.Lens[level]; self->count = 0; self->free = 0; // | (Entry)entries... | (int)arr... | // used entry: next: next entry in the bucket // free entry: next: next free entry int EntrySize = Const.EntrySize; var entries = self->entries = (Entry *)Mem.Malloc(len * (EntrySize + IntSize)); Entry *entry = null; for (int i = 0; i < len; i += 1) { entry = entries + i; entry->val = null; entry->next = i + 1; } entry->next = -1; // the last free entry int *arr = self->arr = (int *)((byte *)entries + len * EntrySize); for (int i = 0; i < len; i += 1) { arr[i] = -1; } }
public static void Init(Pool *self, int len) { #if FDB Should.NotNull("self", self); Should.GreaterThanZero("len", len); self->type = Type; #endif self->len = len; byte *arr = self->arr = (byte *)Mem.Malloc(len); self->shift = 0; // sentinel int *head = (int *)arr; head[0] = -1; // sentinelHead.prev = -1; head[1] = HeadSize + TailSize; // sentinelhead.next = HeadSize + TailSize; head[2] = 0; // sentinelHead.size = 0; head[3] = -1; // sentinelTail.size = -1; // to prevent merging // Fdb.Dump(arr, len); // sentinel firstFree sentinel int size = len - HeadSize - TailSize - HeadSize - TailSize - HeadSize; SetFreeMeta((int *)(arr + HeadSize + TailSize), 0, -1, size); // sentinel head = (int *)(arr + len - HeadSize); head[0] = -1; // prev = -1 will prevent merging head[1] = -1; head[2] = 0; PtrLst.Init(&self->dependentLst); #if FDB Verify(self); #endif }
public static void FillUvs(TpSpriteMeta *self, float *uvs) { #if FDB Should.NotNull("self", self); Should.NotNull("uvs", uvs); Should.TypeEqual("self", self->type, Type); Should.NotNull("self->atlas", self->atlas); Should.TypeEqual("self->atlas->type", self->atlas->type, TpAtlasMeta.Type); #endif float *size = self->atlas->size; float invSizeX = 1 / size[0], invSizeY = 1 / size[1]; float *uv = self->uv; float uvX = uv[0], uvY = uv[1], uvW = uv[2], uvH = uv[3]; if (self->rotated) { Vec2.Set(uvs, (uvX + uvW) * invSizeX, -uvY * invSizeY); Vec2.Set(uvs + 2, (uvX + uvW) * invSizeX, (-uvY - uvH) * invSizeY); Vec2.Set(uvs + 4, uvX * invSizeX, (-uvY - uvH) * invSizeY); Vec2.Set(uvs + 6, uvX * invSizeX, -uvY * invSizeY); } else { Vec2.Set(uvs, uvX * invSizeX, -uvY * invSizeY); Vec2.Set(uvs + 2, (uvX + uvW) * invSizeX, -uvY * invSizeY); Vec2.Set(uvs + 4, (uvX + uvW) * invSizeX, (-uvY - uvH) * invSizeY); Vec2.Set(uvs + 6, uvX * invSizeX, (-uvY - uvH) * invSizeY); } }
public static void Clear(PtrLst *self) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif self->count = 0; }
public static void SetTint(TpSprite *self, float r, float g, float b) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif Vec3.Set(self->color, r, g, b); }
public static void SetAlpha(TpSprite *self, float a) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif self->color[3] = a; }
public static void QuickSort(void **arr, int len, Cmp cmp) { #if FDB Should.NotNull("arr", arr); Should.GreaterThanZero("len", len); Should.NotNull("cmp", cmp); #endif QuickSort(arr, 0, len - 1, cmp); }
public static void SetRotation(TpSprite *self, float rotation) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif self->rot = rotation; self->isTransformDirty = true; }
public static void SetScale(TpSprite *self, float x, float y) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif Vec2.Set(self->scl, x, y); self->isTransformDirty = true; }
public static void SetPosition(TpSprite *self, float x, float y, float z) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); #endif Vec3.Set(self->pos, x, y, z); self->isTransformDirty = true; }
public static int BinarySearch(void **arr, int len, void *val, Cmp cmp) { #if FDB Should.NotNull("arr", arr); Should.GreaterThanZero("len", len); Should.NotNull("cmp", cmp); #endif return(BinarySearch(arr, 0, len - 1, val, cmp)); }
/** * | -1 | -1 | size | data... | -1 | * | size | */ static void SetUsedMeta(int *head, int size) { #if FDB Should.NotNull("head", head); Should.GreaterThanZero("size", size); #endif head[0] = -1; head[1] = -1; head[2] = size; int *tail = (int *)((byte *)(head + 3) + size); tail[0] = -1; }
public static void Verify(PtrLst *self) { Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); int len = Mem.Verify(self->arr) / sizeof(void *); Should.Equal("self->len", self->len, len); Should.InRange("self->count", self->count, 0, self->len); Should.Equal("self->size", self->size, sizeof(void *)); }
public static void MergeSort(void **arr, int len, Cmp cmp) { #if FDB Should.NotNull("arr", arr); Should.GreaterThanZero("len", len); Should.NotNull("cmp", cmp); #endif void **temp = stackalloc void *[len]; MergeSort(arr, temp, 0, len - 1, cmp); }
public static void Draw(void *node, float *parentMat, bool isParentTransformDirty) { #if FDB Should.NotNull("node", node); #endif switch (*(int *)node) { case Tag.TpSprite: TpSprite.Draw((TpSprite *)node, parentMat, isParentTransformDirty); return; case Tag.Group: Group.Draw((Group *)node, parentMat, isParentTransformDirty); return; } }
/** * | prev | next | size | data... | size | * | size | */ static void SetFreeMeta(int *head, int prev, int next, int size) { #if FDB Should.NotNull("head", head); Should.GreaterThanOrEqualTo("prev", prev, -1); Should.GreaterThanOrEqualTo("next", next, -1); Should.GreaterThanZero("size", size); #endif head[0] = prev; head[1] = next; head[2] = size; int *tail = (int *)((byte *)(head + 3) + size); tail[0] = size; }
public static void Init(PtrLst *self, int len) { #if FDB Should.NotNull("self", self); Should.GreaterThanZero("len", len); self->type = Type; #endif self->tag = Tag.PtrLst; self->len = len; self->count = 0; int size = self->size = sizeof(void *); self->arr = (void **)Mem.Malloc(len * size); }
public static void Verify(PtrIntDict *self) { Should.NotNull("self", self); Should.InRange("self->level", self->level, 0, Const.Lens.Length - 1); Should.Equal("self->len", self->len, Const.Lens[self->level]); Should.InRange("self->count", self->count, 0, self->len); Should.InRange("self->free", self->free, -1, self->len - 1); Mem.Verify(self->entries); Should.NotNull("self->arr", self->arr); int len = self->len; int count = self->count; int j = 0; for (int i = 0; i < len; i += 1) { var entry = self->entries + i; if (entry->val != null) // a real key { j += 1; } } Should.Equal("j", j, count); int freeCount = len - count; int free = self->free; while (free != -1) { freeCount -= 1; free = self->entries[free].next; } Should.Zero("freeCount", freeCount); j = 0; for (int i = 0; i < len; i += 1) { int idx = self->arr[i]; while (idx != -1) { var entry = self->entries + idx; Should.Equal("entry->hash % len", (uint)entry->hash % len, i); j += 1; idx = entry->next; } } // Fdb.Dump(self->arr, self->len * IntSize); // Fdb.Dump(self->entries, self->len * EntrySize, EntrySize); Should.Equal("j", j, count); }
public static void Draw(TpSprite *self, float *parentMat, bool isParentTransformDirty) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); Should.NotNull("self->spriteMeta", self->spriteMeta); #endif var bat = DrawCtx.GetBatch(self->spriteMeta->atlas->name); int vertIdx = bat.vertCount, triIdx = bat.triCount; bat.RequestQuota(4, 6); float *verts = self->verts; float *uvs = self->uvs; if (self->isTransformDirty) { float *mat = stackalloc float[6]; Mat2D.FromScalingRotationTranslation(mat, self->pos, self->scl, self->rot); TpSpriteMeta.FillQuad(self->spriteMeta, mat, self->verts); } var bVerts = bat.verts; var bUvs = bat.uvs; float z = self->pos[2]; bVerts[vertIdx].Set(verts[0], verts[1], z); bVerts[vertIdx + 1].Set(verts[2], verts[3], z); bVerts[vertIdx + 2].Set(verts[4], verts[5], z); bVerts[vertIdx + 3].Set(verts[6], verts[7], z); bUvs[vertIdx].Set(uvs[0], uvs[1]); bUvs[vertIdx + 1].Set(uvs[2], uvs[3]); bUvs[vertIdx + 2].Set(uvs[4], uvs[5]); bUvs[vertIdx + 3].Set(uvs[6], uvs[7]); float *color = self->color; var bColor = Vec4.Color(color, 0.5f); var bColors = bat.colors; bColors[vertIdx] = bColor; bColors[vertIdx + 1] = bColor; bColors[vertIdx + 2] = bColor; bColors[vertIdx + 3] = bColor; var bTris = bat.tris; bTris[triIdx] = vertIdx; bTris[triIdx + 1] = vertIdx + 1; bTris[triIdx + 2] = vertIdx + 2; bTris[triIdx + 3] = vertIdx; bTris[triIdx + 4] = vertIdx + 2; bTris[triIdx + 5] = vertIdx + 3; }
public static TpAtlasMeta *Init(TpAtlasMeta *self, string str) { #if FDB Should.NotNull("self", self); Should.NotNullOrEmpty("str", str); self->type = Type; #endif string[] segs = str.Split(','); int * nums = stackalloc int[segs.Length]; for (int j = 0, end = segs.Length; j < end; j += 1) { nums[j] = int.Parse(segs[j]); } int i = 0; self->name = nums[i++]; self->size[0] = nums[i++]; self->size[1] = nums[i++]; self->spriteCount = nums[i++]; self->sprites = (TpSpriteMeta *)Mem.Malloc(self->spriteCount * sizeof(TpSpriteMeta)); for (int j = 0, end = self->spriteCount; j < end; j += 1) { var sprite = self->sprites + j; #if FDB sprite->type = TpSpriteMeta.Type; #endif sprite->atlas = self; sprite->name = nums[i++]; sprite->rotated = nums[i++] != 0; sprite->size[0] = nums[i++]; sprite->size[1] = nums[i++]; sprite->pivot[0] = nums[i++]; sprite->pivot[1] = nums[i++]; sprite->quad[0] = nums[i++]; sprite->quad[1] = nums[i++]; sprite->quad[2] = nums[i++]; sprite->quad[3] = nums[i++]; sprite->uv[0] = nums[i++]; sprite->uv[1] = nums[i++]; sprite->uv[2] = nums[i++]; sprite->uv[3] = nums[i++]; sprite->border[0] = nums[i++]; sprite->border[1] = nums[i++]; sprite->border[2] = nums[i++]; sprite->border[3] = nums[i++]; } return(self); }
/** * | head | data... | tail | rightHead | data... | rightTail | * | size | | rightSize | * | newHead | data... | tail | * | newSize | * assume head is free and linked */ static void MergeRight(byte *arr, int *head) { #if FDB Should.NotNull("arr", arr); Should.NotNull("head", head); #endif int size = head[2]; int *rightHead = (int *)((byte *)head + HeadSize + size + TailSize); if (rightHead[0] == -1) { return; // since only the left most sentinel has head.prev = -1, we can check this to see if the node is used } RemoveFromFreeList(arr, rightHead); SetFreeMeta(head, size + TailSize + HeadSize + rightHead[2]); // do not need to insert since head is already in free list }
static void RemoveFromFreeList(byte *arr, int *head) { #if FDB Should.NotNull("arr", arr); Should.NotNull("head", head); #endif int prev = head[0], next = head[1]; if (prev != -1) { ((int *)(arr + prev))[1] = next; } if (next != -1) { ((int *)(arr + next))[0] = prev; } }
public static void Decon(TpAtlasMeta *self) { #if FDB Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); Should.NotNull("self->sprites", self->sprites); self->type = Fdb.NullType; for (int j = 0, end = self->spriteCount; j < end; j += 1) { var sprite = self->sprites + j; Should.TypeEqual("sprite->type", sprite->type, TpSpriteMeta.Type); sprite->type = Fdb.NullType; } #endif self->name = -1; Mem.Free(self->sprites); self->sprites = null; }
/** * | leftHead | data... | leftTail | head | data... | tail | * | leftSize | | size | * | newHead | data... | newTail | * | newSize | * assume the head is free and linked */ static int *MergeLeft(byte *arr, int *head) { #if FDB Should.NotNull("arr", arr); Should.NotNull("head", head); #endif int *leftTail = head - 1; int leftSize = *leftTail; if (leftSize == -1) { return(head); } RemoveFromFreeList(arr, head); int *leftHead = (int *)((byte *)leftTail - leftSize - HeadSize); SetFreeMeta(leftHead, leftSize + TailSize + HeadSize + head[2]); return(leftHead); }
// v0 - v1 // | \ | // v3 - v2 public static void FillQuad(TpSpriteMeta *self, float *mat, float *verts) { #if FDB Should.NotNull("self", self); Should.NotNull("verts", verts); Should.NotNull("mat", mat); Should.TypeEqual("self", self->type, Type); Should.NotNull("self->atlas", self->atlas); Should.TypeEqual("self->atlas->type", self->atlas->type, TpAtlasMeta.Type); #endif float *pivot = self->pivot; float pivotX = pivot[0], pivotY = pivot[1]; float *quad = self->quad; float quadX = quad[0], quadY = quad[1], quadW = quad[2], quadH = quad[3]; Vec2.TransformMat2D(verts, mat, -pivotX + quadX, pivotY - quadY); Vec2.TransformMat2D(verts + 2, mat, -pivotX + quadX + quadW, pivotY - quadY); Vec2.TransformMat2D(verts + 4, mat, -pivotX + quadX + quadW, pivotY - quadY - quadH); Vec2.TransformMat2D(verts + 6, mat, -pivotX + quadX, pivotY - quadY - quadH); }
public static void Init(TpSprite *self, TpSpriteMeta *spriteMeta) { #if FDB Should.NotNull("self", self); Should.NotNull("spriteMeta", spriteMeta); self->type = Type; #endif self->tag = Tag.TpSprite; Vec3.Zero(self->pos); Vec2.One(self->scl); self->rot = 0; self->isTransformDirty = true; // delay regen verts to first Draw Vec4.Set(self->color, 1, 1, 1, 0); TpSpriteMeta.FillUvs(spriteMeta, self->uvs); self->spriteMeta = spriteMeta; }
/** * | 0 | firstFreeHead.next | size | data... | size | * | size | */ static void SetFreeMetaAndInsert(byte *arr, int *head, int size) { #if FDB Should.NotNull("arr", arr); Should.NotNull("head", head); Should.GreaterThanZero("size", size); #endif int *firstFreeHead = (int *)arr; int firstFreeHeadNext; head[0] = 0; firstFreeHeadNext = head[1] = firstFreeHead[1]; head[2] = size; int pos = (int)((byte *)head - arr); if (firstFreeHeadNext != -1) { *(int *)(arr + firstFreeHeadNext) = pos; // firstFreeHead.next.prev = head } firstFreeHead[1] = pos; // firstFreeHead.next = head int *tail = (int *)((byte *)(head + 3) + size); tail[0] = size; }
public static void Verify(Pool *self) { Should.NotNull("self", self); Should.TypeEqual("self", self->type, Type); Should.GreaterThanZero("self->len", self->len); Should.Equal("self->HeadSize", HeadSize, 3 * sizeof(int)); Should.Equal("self->TailSize", TailSize, sizeof(int)); int len = Mem.Verify(self->arr); Should.Equal("self->len", self->len, len); // Fdb.Dump(self->arr, len); byte *arr = self->arr; int * head; head = (int *)(arr + self->len - HeadSize); Should.Equal("endHead->prev", head[0], -1); // head.prev = -1 Should.Equal("endHead->next", head[1], -1); // head.next = -1 Should.Equal("endHead->size", head[2], 0); // head.size = 0 head = (int *)arr; Should.Equal("firstHead->prev", head[0], -1); // head.prev = -1 Should.Equal("firstHead->size", head[2], 0); // head.size = 0 Should.Equal("firstTail->size", head[3], -1); // tail.size = -1 int curFree = head[1], lastFree = 0; var dict = new System.Collections.Generic.Dictionary <int, int>(); while (curFree != -1) { head = (int *)(arr + curFree); Should.Equal("head" + curFree + "->prev", head[0], lastFree); Should.Equal("tail->size", *(int *)((byte *)head + HeadSize + head[2]), head[2]); dict.Add(curFree, head[2]); lastFree = curFree; curFree = head[1]; } head = (int *)(arr + HeadSize + TailSize); int *end = (int *)(arr + self->len); while (head < end) { int pos = (int)((byte *)head - self->arr); int prev = head[0], next = head[1], size = head[2]; int *tail = (int *)((byte *)head + HeadSize + size); if (tail < end) { int tailVal = tail[0]; if (tailVal == -1) // in use { Should.False("dict.ContainsKey(pos)", dict.ContainsKey(pos)); Should.Equal("prev", prev, -1); Should.Equal("next", next, -1); Should.GreaterThanZero("size", size); } else // free { Should.True("dict.ContainsKey(pos)" + pos, dict.ContainsKey(pos)); Should.GreaterThanOrEqualTo("prev", prev, 0); Should.GreaterThanOrEqualTo("next", next, -1); Should.Equal("size", size, dict[pos]); dict.Remove(pos); } } else // head is end sentinel, no tail { Should.Equal("head", head, (int *)(arr + len - HeadSize)); Should.Equal("endHead->prev", head[0], -1); // head.prev = -1 Should.Equal("endHead->next", head[1], -1); // head.next = -1 Should.Equal("endHead->size", head[2], 0); // head.size = 0 } head = (int *)((byte *)head + HeadSize + size + TailSize); } Should.Zero("dict.Count", dict.Count); }
public static void Set(PtrIntDict *self, int hash, void *val) { #if FDB Verify(self); Should.NotNull("val", val); #endif int * arr = self->arr; long mod = (uint)hash % self->len; int idx = arr[mod], cur = idx; var entries = self->entries; Entry *entry = null; while (cur != -1) { entry = entries + cur; if (entry->hash == hash) // found the key { entry->val = val; #if FDB Verify(self); #endif return; } cur = entry->next; } // find a free entry int free = self->free; if (free == -1) // expand { int level = self->level += 1; int oldLen = self->len; int len = self->len = Const.Lens[level]; // rehash int EntrySize = Const.EntrySize; entries = self->entries = (Entry *)Mem.Realloc(entries, len * (EntrySize + IntSize)); arr = self->arr = (int *)((byte *)entries + len * EntrySize); for (int i = 0; i < len; i += 1) { arr[i] = -1; // clear the buckets } for (int i = 0; i < oldLen; i += 1) { entries[i].next = -1; // clear old links } for (int i = 0; i < oldLen; i += 1) // insert all old entries { entry = entries + i; mod = (uint)entry->hash % len; entry->next = arr[mod]; arr[mod] = i; } // link all new entries self->free = oldLen + 1; // point to new allocated entries for (int i = oldLen + 1; i < len; i += 1) { entry = entries + i; entry->val = null; entry->next = i + 1; } entry->next = -1; // the last free entry entry = entries + oldLen; idx = arr[mod = (uint)hash % len]; // different idx after expand free = oldLen; } else { entry = entries + free; self->free = entry->next; } entry->hash = hash; entry->next = idx; entry->val = val; arr[mod] = free; self->count += 1; #if FDB Verify(self); #endif }