void BinaryTree_deleteAll(BinaryTree* self, void (*deleter)(void* item)) { smug_assert(_invariant(self)); if (!BinaryTree_isEmpty(self)) { _deleteContentsWithChildren(self->root, deleter); self->root = NULL; smug_assert(_invariant(self)); } }
void BinaryTree_removeAll(BinaryTree* self) { smug_assert(_invariant(self)); if (!BinaryTree_isEmpty(self)) { _deleteWithChildren(self->root); self->root = NULL; smug_assert(_invariant(self)); } }
void RenderQueue_delete(RenderQueue* self) { smug_assert(_invariant(self)); Map_doForEach(self->renderBatches, _deleteRenderBatchInMap); Map_delete(self->renderBatches); free(self); }
void* BinaryTree_find(BinaryTree* self, void* item) { smug_assert(_invariant(self)); BinaryTreeNode* node; _findNode(self, item, &node); return node == NULL ? NULL : node->item; }
RenderQueue* RenderQueue_new() { RenderQueue* newRenderQueue = allocate(RenderQueue); newRenderQueue->renderBatches = Map_new(Map_compareInts); smug_assert(_invariant(newRenderQueue)); return newRenderQueue; }
void Drawable_scaleXY(Drawable* self, Vector scales) { smug_assert(_invariant(self)); if (self->mShape != NULL) { Shape_scaleXY(self->mShape, scales); } }
void Drawable_scaleY(Drawable* self, float scale) { smug_assert(_invariant(self)); if (self->mShape != NULL) { Shape_scaleY(self->mShape, scale); } }
void BinaryTree_insert(BinaryTree* self, void* item) { smug_assert(_invariant(self)); if (BinaryTree_isEmpty(self)) { self->root = BinaryTreeNode_new(item); smug_assert(_invariant(self)); return; } BinaryTreeNode* current = self->root; int comp; while (TRUE) { comp = _compare(self, item, current->item); if (comp == 0) { return; } if (comp < 0) { if (current->left == NULL) { current->left = BinaryTreeNode_new(item); current->left->parent = current; smug_assert(_invariant(self)); return; } current = current->left; } if (comp > 0) { if (current->right == NULL) { current->right = BinaryTreeNode_new(item); current->right->parent = current; smug_assert(_invariant(self)); return; } current = current->right; } } }
BinaryTree* BinaryTree_new(int (*compare)(void*, void*)) { smug_assert(compare != NULL); BinaryTree* newTree = allocate(BinaryTree); newTree->root = NULL; newTree->compare = compare; newTree->comparePredicated = NULL; newTree->predicateData = NULL; smug_assert(_invariant(newTree)); return newTree; }
void PathName_addBase(PathName* self, PathName* base) { smug_assert(_invariant(self)); smug_assert(_invariant(base)); smug_assert(PathName_isRelative(self)); smug_assert(_invariant(self)); smug_assert(_invariant(base)); LinkedList* basePath; if (base->root) { self->root = String_newCopy(base->root); } basePath = LinkedList_deepCopy(base->path, String_newCopyVoid); LinkedList_concat(basePath, self->path); self->path = basePath; }
BinaryTree* BinaryTree_newPredicated(int (*comparePredicated)(void*, void*, void*), void* predicateData) { smug_assert(comparePredicated != NULL); BinaryTree* newTree = allocate(BinaryTree); newTree->root = NULL; newTree->compare = NULL; newTree->comparePredicated = comparePredicated; newTree->predicateData = predicateData; smug_assert(_invariant(newTree)); return newTree; }
/** Requires OpenGL to be initialized, and GL_VERTEX_ARRAY and * GL_TEXTURE_COORD_ARRAY to be enabled. */ void RenderQueue_render(RenderQueue* self) { smug_assert(_invariant(self)); MapIterator* iter = Map_getIterator(self->renderBatches); MapPair* pair = MapIterator_getNextPair(iter); while (pair != NULL) { glBindTexture(GL_TEXTURE_2D, *(int*)pair->key); RenderBatch_render((RenderBatch*)pair->value); pair = MapIterator_getNextPair(iter); } MapIterator_delete(iter); }
void RenderQueue_addDrawable(RenderQueue* self, Drawable* drawable, float positionX, float positionY) { smug_assert(_invariant(self)); Sprite* sprite = Drawable_getSprite(drawable); smug_assert(sprite != NULL); int id = Sprite_getTextureId(sprite); RenderBatch* renderBatch = (RenderBatch*)Map_get(self->renderBatches, &id); if (renderBatch == NULL) { renderBatch = RenderBatch_new(RENDERBATCH_INITIAL_SIZE, TRUE); Map_set(self->renderBatches, _allocInt(id), renderBatch); } Drawable_addRenderData(drawable, renderBatch, positionX, positionY); }
Drawable* Drawable_newBoxFromSize(Vector size) { Drawable* newObj = (Drawable*)malloc(sizeof(_Drawable)); Drawable_init(newObj); newObj->_writeBatchDataFunc = writeBatchData; newObj->_getDataSizeFunc = getDataSize; newObj->mShape = Shape_newFromRectangle(Rectangle_createFromXYWH(0, 0, Vector_getX(&size), Vector_getY(&size))); smug_assert(_invariant(newObj)); return newObj; /* smug_assert(GameObject_isExactType(newObj, SMUG_TYPE_SHAPE)); smug_assert(GameObject_isType(newObj, SMUG_TYPE_SHAPE)); smug_assert(GameObject_isType(newObj, SMUG_TYPE_DRAWABLE)); smug_assert(GameObject_isType(newObj, SMUG_TYPE_POSITION)); smug_assert(GameObject_isType(newObj, SMUG_TYPE_OBJECT)); */ }
BinaryTreeIterator* BinaryTree_getIterator(BinaryTree* self) { smug_assert(_invariant(self)); BinaryTreeIterator* newIter = allocate(BinaryTreeIterator); newIter->current = self->root; if (self->root == NULL) { return newIter; } while (newIter->current->left != NULL) { newIter->current = newIter->current->left; } return newIter; }
PathName* PathName_newCopy(PathName* self) { PathName* newPn; smug_assert(_invariant(self)); newPn = (PathName*)malloc(sizeof(PathName)); if (self->root) { newPn->root = String_newCopy(self->root); } if (self->bareName) { newPn->bareName = String_newCopy(self->bareName); if (self->extension) { newPn->extension = String_newCopy(self->extension); } } newPn->path = LinkedList_deepCopy(self->path, String_newCopyVoid); smug_assert(_invariant(newPn)); return newPn; }
String* PathName_getAsString(PathName* self) { smug_assert(_invariant(self)); String* path; String* fullPath; path = String_newJoin(self->path, _getSeparator()); if (self->root != NULL) { fullPath = String_newConcat(self->root, path); String_delete(path); } else { fullPath = path; } return fullPath; }
void PathName_delete(PathName* self) { smug_assert(_invariant(self)); if (self->root) { String_delete(self->root); } if (self->bareName) { String_delete(self->bareName); if (self->extension) { String_delete(self->extension); } } LinkedList_deleteContents(self->path, String_deleteVoid); LinkedList_delete(self->path); free(self); }
void Drawable_setAnchorPoint(Drawable* self, Vector point) { smug_assert(_invariant(self)); if (self->mShape != NULL) { Rectangle rect = Shape_getAsRectangle(self->mShape); smug_printf("Moving shape by vector. Before: (%f, %f, %f, %f)", Rectangle_getX(&rect), Rectangle_getY(&rect), Rectangle_getW(&rect), Rectangle_getH(&rect)); smug_printf("New vector: (%f, %f)", Vector_getX(&point), Vector_getY(&point)); smug_printf("Old vector: (%f, %f)", Vector_getX(&self->mAnchorPoint), Vector_getY(&self->mAnchorPoint)); Vector v = Vector_sub(point, self->mAnchorPoint); smug_printf("Moving by vector: (%f, %f)", Vector_getX(&v), Vector_getY(&v)); v = Vector_multiply(v, -1.0); smug_printf("Moving by negative vector: (%f, %f)", Vector_getX(&v), Vector_getY(&v)); Shape_moveByVector(self->mShape, v); rect = Shape_getAsRectangle(self->mShape); smug_printf("Moved shape by vector. After: (%f, %f, %f, %f)", Rectangle_getX(&rect), Rectangle_getY(&rect), Rectangle_getW(&rect), Rectangle_getH(&rect)); self->mAnchorPoint = point; } }
String* PathName_getFileName(PathName* self) { String* ret; String* temp; smug_assert(_invariant(self)); if (NULL == self->bareName) return NULL; if (NULL == self->extension || String_isEmpty(self->extension)) { ret = String_newCopy(self->bareName); } else { temp = String_newConcat(self->bareName, _getDot()); ret = String_newConcat(temp, self->extension); String_delete(temp); } return ret; }
BOOL PathName_isFile(PathName* self) { smug_assert(_invariant(self)); return (NULL != self->bareName); }
BOOL PathName_isAbsolute(PathName* self) { smug_assert(_invariant(self)); return (NULL != self->root); }
BOOL PathName_isRelative(PathName* self) { smug_assert(_invariant(self)); return (NULL == self->root); }
String* PathName_getBareName(PathName* self) { smug_assert(_invariant(self)); if (NULL == self->bareName) return NULL; return String_newCopy(self->bareName); }
void RenderQueue_clear(RenderQueue* self) { smug_assert(_invariant(self)); Map_doForEach(self->renderBatches, _clearRenderBatchInMap); }
PathName* PathName_new(String* string, BOOL isFile) { PathName* newPn; int pos; String* pathWoRoot; String* separators; String* fileName; // Validate the path. if (!_validPath(string)) return NULL; separators = String_new("\\/"); newPn = (PathName*)malloc(sizeof(PathName)); // Check the root. pos = String_findChar(string, ':'); if (1 == pos) { // This is a Windows absolute path. newPn->root = String_newSubString(string, 0, 3); pos = 3; } else if (String_findChar(string, '/') == 0 || String_findChar(string, '\\') == 0) { // This is a Unix absolute path. newPn->root = String_new("/"); pos = 1; } else { // This is a relative path. newPn->root = NULL; pos = 0; } // Parse the rest of the path. pathWoRoot = String_newSubString(string, pos, -1); newPn->path = String_splitMultiSep(pathWoRoot, separators); String_delete(pathWoRoot); if (isFile) { // Get the file name. if (String_isEmpty((String*)newPn->path->last->item)) { // This was supposed to be a file, but the path ended in '/' or '\' String_delete(separators); PathName_delete(newPn); return NULL; } fileName = (String*)newPn->path->last->item; LinkedList_remove(newPn->path, newPn->path->last); // Find the extension, if there is one. pos = String_findCharReverse(fileName, '.'); if (-1 == pos) { // No extension (no '.' in file name). newPn->bareName = fileName; newPn->extension = NULL; } else { // At least one '.' in file name. Separate out extension. newPn->bareName = String_newSubString(fileName, 0, pos); newPn->extension = String_newSubString(fileName, pos + 1, -1); String_delete(fileName); } } else { // No file name. newPn->bareName = NULL; newPn->extension = NULL; if (String_isEmpty((String*)newPn->path->last->item)) { // The string ended in '/' or '\'. Last path element is empty, so remove it. String_delete((String*)newPn->path->last->item); LinkedList_remove(newPn->path, newPn->path->last); } } String_delete(separators); smug_assert(_invariant(newPn)); return newPn; }
void Drawable_setSprite(Drawable* self, struct Sprite* sprite) { smug_assert(_invariant(self)); self->mSprite = sprite; self->mUseColor = FALSE; }
String* PathName_getExtension(PathName* self) { smug_assert(_invariant(self)); if (NULL == self->extension) return NULL; return String_newCopy(self->extension); }
static void writeBatchData(Drawable* drawable, BatchData* batchdata, unsigned int start) { smug_assert(_invariant(drawable)); smug_assert(GameObject_isType((GameObject*)drawable, SMUG_TYPE_DRAWABLE)); static unsigned int vertexstart, colorstart, texturestart; static float x1, x2, y1, y2; static float r, g, b, a; static float tx1, ty1, tx2, ty2; static Sprite* sprite = NULL; static Point dpos; static Shape* shape; static Rectangle box; static Color color; static BOOL useColor; vertexstart = start*2; colorstart = start*4; texturestart = start*2; Drawable_getShape(drawable, &shape); box = Shape_getAsRectangle(shape); // write vertices in anti-clockwise order PositionedObject_getPosForDrawing((GameObject*)drawable, &dpos); x1 = Point_getX(dpos) + Rectangle_getX(&box); y1 = Point_getY(dpos) + Rectangle_getY(&box); x2 = Point_getX(dpos) + Rectangle_getW(&box); y2 = Point_getY(dpos) + Rectangle_getH(&box); batchdata->vertexData[vertexstart + 0 * 2 + 0] = x1; batchdata->vertexData[vertexstart + 0 * 2 + 1] = y1; batchdata->vertexData[vertexstart + 1 * 2 + 0] = x1; batchdata->vertexData[vertexstart + 1 * 2 + 1] = y2; batchdata->vertexData[vertexstart + 2 * 2 + 0] = x2; batchdata->vertexData[vertexstart + 2 * 2 + 1] = y2; batchdata->vertexData[vertexstart + 3 * 2 + 0] = x2; batchdata->vertexData[vertexstart + 3 * 2 + 1] = y1; #ifdef SMUG_GLES batchdata->vertexData[vertexstart + 4 * 2 + 0] = x1; batchdata->vertexData[vertexstart + 4 * 2 + 1] = y1; batchdata->vertexData[vertexstart + 5 * 2 + 0] = x2; batchdata->vertexData[vertexstart + 5 * 2 + 1] = y2; #endif /* SMUG_GLES */ Drawable_getUseColor(drawable, &useColor); Drawable_getColor(drawable, &color); a = Color_Af(color); if (useColor) { // write colordata r = Color_Rf(color); g = Color_Gf(color); b = Color_Bf(color); } else { r = 1.0f; g = 1.0f; b = 1.0f; } batchdata->colorData[colorstart + 0 * 4 + 0] = r; batchdata->colorData[colorstart + 0 * 4 + 1] = g; batchdata->colorData[colorstart + 0 * 4 + 2] = b; batchdata->colorData[colorstart + 0 * 4 + 3] = a; batchdata->colorData[colorstart + 1 * 4 + 0] = r; batchdata->colorData[colorstart + 1 * 4 + 1] = g; batchdata->colorData[colorstart + 1 * 4 + 2] = b; batchdata->colorData[colorstart + 1 * 4 + 3] = a; batchdata->colorData[colorstart + 2 * 4 + 0] = r; batchdata->colorData[colorstart + 2 * 4 + 1] = g; batchdata->colorData[colorstart + 2 * 4 + 2] = b; batchdata->colorData[colorstart + 2 * 4 + 3] = a; batchdata->colorData[colorstart + 3 * 4 + 0] = r; batchdata->colorData[colorstart + 3 * 4 + 1] = g; batchdata->colorData[colorstart + 3 * 4 + 2] = b; batchdata->colorData[colorstart + 3 * 4 + 3] = a; #ifdef SMUG_GLES batchdata->colorData[colorstart + 4 * 4 + 0] = r; batchdata->colorData[colorstart + 4 * 4 + 1] = g; batchdata->colorData[colorstart + 4 * 4 + 2] = b; batchdata->colorData[colorstart + 4 * 4 + 3] = a; batchdata->colorData[colorstart + 5 * 4 + 0] = r; batchdata->colorData[colorstart + 5 * 4 + 1] = g; batchdata->colorData[colorstart + 5 * 4 + 2] = b; batchdata->colorData[colorstart + 5 * 4 + 3] = a; #endif /* SMUG_GLES */ // write texture data only if sprite exists if ((sprite = Drawable_getSprite(drawable)) == NULL) { return; } tx1 = Rectangle_getX(&sprite->rect) * sprite->texture->px; ty1 = Rectangle_getY(&sprite->rect) * sprite->texture->py; tx2 = tx1 + Rectangle_getW(&sprite->rect) * sprite->texture->px; ty2 = ty1 + Rectangle_getH(&sprite->rect) * sprite->texture->py; batchdata->textureData[texturestart + 0 * 2 + 0] = tx1; batchdata->textureData[texturestart + 0 * 2 + 1] = ty1; batchdata->textureData[texturestart + 1 * 2 + 0] = tx1; batchdata->textureData[texturestart + 1 * 2 + 1] = ty2; batchdata->textureData[texturestart + 2 * 2 + 0] = tx2; batchdata->textureData[texturestart + 2 * 2 + 1] = ty2; batchdata->textureData[texturestart + 3 * 2 + 0] = tx2; batchdata->textureData[texturestart + 3 * 2 + 1] = ty1; #ifdef SMUG_GLES batchdata->textureData[texturestart + 4 * 2 + 0] = tx1; batchdata->textureData[texturestart + 4 * 2 + 1] = ty1; batchdata->textureData[texturestart + 5 * 2 + 0] = tx2; batchdata->textureData[texturestart + 5 * 2 + 1] = ty2; #endif /* SMUG_GLES */ }
Vector Drawable_getAnchorPoint(Drawable* self) { smug_assert(_invariant(self)); return self->mAnchorPoint; }