void FW::popLogFile(void) { s_lock.enter(); if (s_logFiles.getSize()) { s_logStreams.getLast()->flush(); delete s_logFiles.removeLast(); delete s_logStreams.removeLast(); if (!s_logFiles.getSize()) { s_logFiles.reset(); s_logStreams.reset(); } } s_lock.leave(); }
Vec2i GLContext::getStringSize(const String& str) { // Split the string into lines. Array<String> lines; str.split('\n', lines, true); while (lines.getSize() && !lines.getLast().getLength()) lines.removeLast(); // Compute metrics. Vec2i strSize = 0; for (int i = 0; i < lines.getSize(); i++) { if (!lines[i].getLength()) lines[i] = " "; // To avoid lineSize.y being zero. SIZE size; if (!GetTextExtentPoint32(m_memdc, lines[i].getPtr(), lines[i].getLength(), &size)) failWin32Error("GetTextExtentPoint32"); Vec2i lineSize(size.cx + m_vgFontMetrics.tmOverhang, size.cy); strSize.x = max(strSize.x, lineSize.x); strSize.y += lineSize.y; } return strSize; }
static void shortenSubPath (Array<LineSection>& subPath, float amountAtStart, float amountAtEnd) { while (amountAtEnd > 0 && subPath.size() > 0) { LineSection& l = subPath.getReference (subPath.size() - 1); float dx = l.rx2 - l.rx1; float dy = l.ry2 - l.ry1; const float len = juce_hypot (dx, dy); if (len <= amountAtEnd && subPath.size() > 1) { LineSection& prev = subPath.getReference (subPath.size() - 2); prev.x2 = l.x2; prev.y2 = l.y2; subPath.removeLast(); amountAtEnd -= len; } else { const float prop = jmin (0.9999f, amountAtEnd / len); dx *= prop; dy *= prop; l.rx1 += dx; l.ry1 += dy; l.lx2 += dx; l.ly2 += dy; break; } } while (amountAtStart > 0 && subPath.size() > 0) { LineSection& l = subPath.getReference (0); float dx = l.rx2 - l.rx1; float dy = l.ry2 - l.ry1; const float len = juce_hypot (dx, dy); if (len <= amountAtStart && subPath.size() > 1) { LineSection& next = subPath.getReference (1); next.x1 = l.x1; next.y1 = l.y1; subPath.remove (0); amountAtStart -= len; } else { const float prop = jmin (0.9999f, amountAtStart / len); dx *= prop; dy *= prop; l.rx2 -= dx; l.ry2 -= dy; l.lx1 -= dx; l.ly1 -= dy; break; } } }
void FW::profilePop(void) { if (!s_profileStarted || s_profileStack.getSize() == 0) return; if (!Thread::isMain()) fail("profilePop() can only be used in the main thread!"); if (s_profileStack.getSize() > 1) s_profileTimers[s_profileStack.getLast()].timer.end(); s_profileStack.removeLast(); if (s_profileStack.getSize() == 1) s_profileTimers[s_profileStack.getLast()].timer.end(); }
void FW::popMemOwner(void) { #if FW_MEM_DEBUG U32 threadID = Thread::getID(); Array<const char*>* stack = s_memOwnerStacks.search(threadID); if (stack) { stack->removeLast(); if (!stack->getSize()) { s_memOwnerStacks.remove(threadID); if (!s_memOwnerStacks.getSize()) s_memOwnerStacks.reset(); } } #endif }
int main() { Array *array = new Array(20); for (int i = 0; i < 10; ++i) { array->addLast(i); } array->print(); array->add(1,100); array->addFirst(-1); array->print(); array->remove(2); array->print(); array->removeElement(4); array->print(); array->removeFirst(); array->print(); array->removeLast(); array->print(); return 0; }
Vec2i GLContext::drawLabel(const String& str, const Vec4f& pos, const Vec2f& align, U32 fgABGR, U32 bgABGR) { // Split the string into lines. Array<String> lines; str.split('\n', lines, true); while (lines.getSize() && !lines.getLast().getLength()) lines.removeLast(); // Compute metrics. Vec2i strSize = 0; for (int i = 0; i < lines.getSize(); i++) { if (!lines[i].getLength()) lines[i] = " "; // To avoid lineSize.y being zero. Vec2i lineSize = getStringSize(lines[i]); strSize.x = max(strSize.x, lineSize.x); strSize.y += lineSize.y; } // Empty or fully transparent => skip. if (strSize.x <= 0 || strSize.y <= 0 || ((fgABGR | bgABGR) & 0xFF000000) == 0) return strSize; // Initialize GL state. glPushAttrib(GL_ENABLE_BIT | GL_COLOR_BUFFER_BIT); glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // Draw each line. Vec4f fgColor = Vec4f::fromABGR(fgABGR); Vec4f bgColor = Vec4f::fromABGR(bgABGR); Vec2f linePos(0.0f, (F32)strSize.y); for (int i = 0; i < lines.getSize(); i++) { Vec2i lineSize = (lines.getSize() == 1) ? strSize : getStringSize(lines[i]); if (lineSize.x <= 0 || lineSize.y <= 0) continue; linePos.y -= (F32)lineSize.y; const Vec2i& texSize = uploadString(lines[i], lineSize); Vec4f tpos = m_vgXform * pos; Vec2f pixel = m_viewScale * tpos.w; tpos.x += (linePos.x - align.x * (F32)lineSize.x) * pixel.x; tpos.y += (linePos.y - align.y * (F32)strSize.y) * pixel.y; tpos.x = floor((tpos.x + tpos.w) / pixel.x + 0.5f) * pixel.x - tpos.w; tpos.y = floor((tpos.y + tpos.w) / pixel.y + 0.5f) * pixel.y - tpos.w; if (bgColor.w > 0.0f) for (int j = -1; j <= 1; j++) for (int k = -1; k <= 1; k++) drawString(tpos + Vec4f(Vec2f((F32)j, (F32)k) * pixel, 0.0f, 0.0f), lineSize, texSize, bgColor); if (fgColor.w > 0.0f) drawString(tpos, lineSize, texSize, fgColor); } // Clean up. glPopAttrib(); checkErrors(); return strSize; }
Fracture* VertPositionMutation::mutate(Fracture* fracture) { // get all verts that are not corners Array<Vertex*>* nonCorner = new Array<Vertex*>(); for(int i=0;i<fracture->getVerts()->getSize();i++) if(!fracture->getVerts()->get(i)->getIsCorner()) nonCorner->add(fracture->getVerts()->get(i)); int numVerts = nonCorner->getSize(); if(!numVerts) // if only corners return the original fracture return fracture; // get a random non-boundary vert int randVert = RNG::RandomInt(numVerts); Vertex* ranVert = nonCorner->get(randVert); // get the move amount and distance before making a jump real moveLimit = EvolutionSettings::getInstance()->getMaxMovePercent(); real distBeforeJump = EvolutionSettings::getInstance()->getDistBeforeJump(); if(ranVert->getBoundary()) { // move along boundary line Array<Edge*>* boundaryEdges = new Array<Edge*>(); for(int i=0;i<ranVert->getEdges()->getSize();i++) if(ranVert->getEdges()->get(i)->getIsBoundary()) boundaryEdges->add(ranVert->getEdges()->get(i)); // choose a random edge to move by int randDir = RNG::RandomInt(boundaryEdges->getSize()); Edge* edgeToMoveBy = boundaryEdges->get(randDir); // get the edge length real length = edgeToMoveBy->length(); // if the length is too small move the other direction // in the future this is going to check if it can jump i.e // it will jump around a corner. if(length < distBeforeJump) { for(int i=0;i<boundaryEdges->getSize();i++) { // this should always work since there should be at least // two boundary edges attached if(boundaryEdges->get(i)!=edgeToMoveBy) { edgeToMoveBy = boundaryEdges->get(i); i = boundaryEdges->getSize(); } } // recheck length and abort if the check fails real length = edgeToMoveBy->length(); if(length < distBeforeJump) return fracture; } // get a random mutation value real mutateScale = RNG::RandomFloat(moveLimit); // Get the two points on the edge to move on Point2 firstPoint = ranVert->getLocation(); Point2 secondPoint = edgeToMoveBy->getOtherPoint(ranVert->getID()); // calculate the vert's new location Point2 slope = secondPoint.minus(firstPoint); slope.scale(mutateScale); Point2 newLoc = firstPoint.add(slope); // set the new location ranVert->setLocation(newLoc); // tell the verts edges about its new location ranVert->updateEdges(); // clean up while(boundaryEdges->getSize()) boundaryEdges->removeLast(); delete boundaryEdges; } else { // maybe implement move along edges ??? // move about faces using barycentric coordinates // get the faces containing the point Array<Face*>* facesWithVert = fracture->getFacesWithVertex(ranVert); // create a face containing all points around the vert Face* faceToMutateAround = new Face(); for(int i=0;i<facesWithVert->getSize();i++) { Face* tmp = facesWithVert->get(i); for(int j=0;j<tmp->getEdges()->getSize();j++) if(!tmp->getEdges()->get(j)->eitherMatch(ranVert->getID())) faceToMutateAround->getEdges()->add(tmp->getEdges()->get(j)->copy()); for(int j=0;j<tmp->getVerts()->getSize();j++) if(tmp->getVerts()->get(j)->getID() != ranVert->getID()) faceToMutateAround->getVerts()->add(tmp->getVerts()->get(j)->copy(faceToMutateAround->getEdges())); } // create the container for the generated Tris Array<Tri*>* generatedTris = new Array<Tri*>(); // detect if the face is convex or not faceToMutateAround->detectIfConvex(); if(faceToMutateAround->getIsConvex()) { // TODO :: Do this the more efficient way // convex case mutation (easy) // generate tris for(int i=0;i<faceToMutateAround->getEdges()->getSize();i++) generatedTris->add(new Tri(faceToMutateAround->getEdges()->get(i),ranVert->getLocation(),ranVert->getID())); // create barycentric coordinates for mutation (2 * #tris) // TODO :: Combine this with the case below int numBarys = generatedTris->getSize()*2; real barys[numBarys]; for(int i=0;i<numBarys;i++) barys[i] = RNG::RandomFloat(moveLimit); // apply mutations Point2 newPos; newPos.xpos = 0.0; newPos.ypos = 0.0; int pointID = ranVert->getID(); for(int i=0;i<generatedTris->getSize();i++) { // get new position real baryOne = barys[i*2]; real baryTwo = barys[i*2-1]; real baryThree = 1.0 - baryOne - baryTwo; newPos = generatedTris->get(i)->interpolatePosition(baryOne,baryTwo,baryThree); // update the position in all the remaining tris for(int j=i;j<generatedTris->getSize();j++) generatedTris->get(j)->updatePosition(pointID,newPos); } // set new position of vert ranVert->setLocation(newPos); // update edges ranVert->updateEdges(); // clean up } else { // concave case mutation (harder) // create collection for trimesh shell Array<Vertex*>* vertsInView = new Array<Vertex*>(); Array<Vertex*>* sortedVertsInView = new Array<Vertex*>(); Array<Edge*>* trimeshShell = new Array<Edge*>(); // get all verts in view for(int i=0;i<faceToMutateAround->getVerts()->getSize();i++) { Vertex* vert = faceToMutateAround->getVerts()->get(i); // create a temp edge to check for intersections Edge* tmpEdge = new Edge(ranVert->getLocation(),vert->getLocation()); bool noIntersection = true; // check if intersections for(int i=0;i<faceToMutateAround->getEdges()->getSize();i++) if(faceToMutateAround->getEdges()->get(i)->intersects(tmpEdge)) noIntersection = false; // if no intersections add it to the list of verts in view if(noIntersection) vertsInView->add(vert); // Note :: vert is still a copy // clean up delete tmpEdge; } // sort verts Array<Integer>* sortedIDs = faceToMutateAround->sortVertIDsByPath(); for(int i=0;i<sortedIDs->getSize();i++) for(int j=0;j<vertsInView->getSize();i++) if(vertsInView->get(j)->getID() == sortedIDs->get(i).val) { sortedVertsInView->add(vertsInView->get(j)); j = vertsInView->getSize(); } // create shell from verts for(int i=0;i<sortedVertsInView->getSize();i++) { Vertex* one = sortedVertsInView->get(i); Vertex* two = i==sortedVertsInView->getSize()-1 ? sortedVertsInView->get(0) : sortedVertsInView->get(i+1); Edge* newEdge = new Edge(one->getLocation(),two->getLocation(),one->getID(),two->getID()); trimeshShell->add(newEdge); } // generate tris for(int i=0;i<trimeshShell->getSize();i++) generatedTris->add(new Tri(trimeshShell->get(i),ranVert->getLocation(),ranVert->getID())); // create barycentric coordinates for mutation (Only 2 for this case) // TODO :: Combine this with the case above //int numBarys = generatedTris->getSize()*2; int numBarys = 2; real barys[numBarys]; for(int i=0;i<numBarys;i++) barys[i] = RNG::RandomFloat(moveLimit); // apply mutations Point2 newPos; newPos.xpos = 0.0; newPos.ypos = 0.0; int pointID = ranVert->getID(); int ranTri = RNG::RandomInt(generatedTris->getSize()); //for(int i=0;i<generatedTris->getSize();i++) { // get new position //real baryOne = barys[i*2]; //real baryTwo = barys[i*2-1]; real baryOne = barys[0]; real baryTwo = barys[1]; real baryThree = 1.0 - baryOne - baryTwo; newPos = generatedTris->get(ranTri)->interpolatePosition(baryOne,baryTwo,baryThree); // update the position in all the remaining tris (skip for this step) // for(int j=i;j<generatedTris->getSize();j++) // generatedTris->get(j)->updatePosition(pointID,newPos); //} // set new position of vert ranVert->setLocation(newPos); // update edges ranVert->updateEdges(); // clean up while(vertsInView->getSize()) vertsInView->removeLast(); while(sortedIDs->getSize()) sortedIDs->removeLast(); while(sortedVertsInView->getSize()) sortedVertsInView->removeLast(); while(trimeshShell->getSize()) delete trimeshShell->removeLast(); delete vertsInView; delete trimeshShell; delete sortedVertsInView; delete sortedIDs; } // clean up while(nonCorner->getSize()) nonCorner->removeLast(); while(facesWithVert->getSize()) facesWithVert->removeLast(); while(generatedTris->getSize()) delete generatedTris->removeLast(); while(faceToMutateAround->getVerts()->getSize()) delete faceToMutateAround->getVerts()->removeLast(); while(faceToMutateAround->getEdges()->getSize()) delete faceToMutateAround->getEdges()->removeLast(); delete faceToMutateAround; delete generatedTris; delete facesWithVert; delete nonCorner; } return fracture; }