void LayoutEngine::addFloat(BoxPtr float_box) { ASSERT_LOG(!float_list_.empty(), "Empty float list."); if(float_box->getStyleNode()->getFloat() == Float::LEFT) { float_list_.top().left_.emplace_back(float_box); } else { float_list_.top().right_.emplace_back(float_box); } }
void Border::createBorder(){ INFO("Creating Border ..."); glm::vec3 pos; BoxPtr obj; // Back & Front Wall for (int i = 0; i < NUMBLKX; i++) { for (int j = 0; j < NUMBLKY; j++) { pos = glm::vec3(MINX + E_LEN/2 + i * E_LEN, MINY + E_LEN/2 + j * E_LEN, MAXZ - E_LEN/2); obj = BoxPtr(new Box(pos, glm::vec3(0), 0)); obj->setup(); obj->setCollisionID(1); CollisionManager::addCollisionObjectToGrid(obj); pos = glm::vec3(MINX + E_LEN/2 + i * E_LEN, MINY + E_LEN/2 + j * E_LEN, MINZ + E_LEN/2); obj = BoxPtr(new Box(pos, glm::vec3(0), 0)); obj->setup(); obj->setCollisionID(1); CollisionManager::addCollisionObjectToGrid(obj); } } // Left & Right Wall for (int i = 1; i < NUMBLKZ - 1; i++) { for (int j = 0; j < NUMBLKY; j++) { pos = glm::vec3(MINX + E_LEN/2, MINY + E_LEN/2 + j * E_LEN, MINZ + E_LEN/2 + i*E_LEN); obj = BoxPtr(new Box(pos, glm::vec3(0), 0)); obj->setup(); obj->setCollisionID(1); CollisionManager::addCollisionObjectToGrid(obj); pos = glm::vec3(MAXX - E_LEN/2, MINY + E_LEN/2 + j * E_LEN, MINZ + E_LEN/2 + i*E_LEN); obj = BoxPtr(new Box(pos, glm::vec3(0), 0)); obj->setup(); obj->setCollisionID(1); CollisionManager::addCollisionObjectToGrid(obj); } } }
TextBox::TextBox(const BoxPtr& parent, const StyleNodePtr& node, const RootBoxPtr& root) : Box(BoxId::TEXT, parent, node, root), txt_(std::dynamic_pointer_cast<Text>(node->getNode())), lines_(), shadows_() { auto shadows = parent->getStyleNode()->getTextShadow(); if(shadows) { // Process shadows in reverse order. for(auto it = shadows->getShadows().crbegin(); it != shadows->getShadows().crend(); ++it) { const css::TextShadow& shadow = *it; float xo = shadow.getOffset()[0].compute() / LayoutEngine::getFixedPointScaleFloat(); float yo = shadow.getOffset()[1].compute() / LayoutEngine::getFixedPointScaleFloat(); float br = shadow.getBlur().compute() / LayoutEngine::getFixedPointScaleFloat(); KRE::ColorPtr color = shadow.getColor().compute(); shadows_.emplace_back(xo, yo, br, color); } } txt_->transformText(getStyleNode(), true); }
void Box::addAbsoluteElement(LayoutEngine& eng, const Dimensions& containing, BoxPtr abs_box) { absolute_boxes_.emplace_back(abs_box); abs_box->layout(eng, containing); }
void InlineBlockBox::handlePostChildLayout(LayoutEngine& eng, BoxPtr child) { // Called after every child is laid out. setContentHeight(getHeight() + child->getHeight() + child->getMBPBottom()); }
/** * \brief Collision Partikel mit einer Box. * \param box zu testende Box */ void ParticleSystem::collide(ParticlePtr part, BoxPtr box) { //sphere in das lokale koordinatensystem der box bringen Vector3<float> particlePos = part->getPosition() - box->getRigidBody()->getPosition(); Quaternion boxOri = box->getRigidBody()->getOrientation(); const Quaternion& boxInvOri = boxOri.inverse(); particlePos = qRotate(particlePos, boxInvOri); //test auf collision mit den 6 seiten der box unsigned int cnt = 0; float rad = 3.0f; float right = dot(particlePos, Vector3<float>(1,0,0)) + rad; float left = dot(particlePos, Vector3<float>(-1,0,0)) - rad; float front = dot(particlePos, Vector3<float>(0,0,1)) + rad; float back = dot(particlePos, Vector3<float>(0,0,-1)) - rad; float top = dot(particlePos, Vector3<float>(0,1,0)) + rad; float bottom = dot(particlePos, Vector3<float>(0,-1,0)) - rad; float dR = box->getWidth()/2 - right + rad; float dL = box->getWidth()/2 - left + rad; float dF = box->getDepth()/2 - front + rad; float dBa = box->getDepth()/2 - back + rad; float dT = box->getHeight()/2 - top + rad; float dBo = box->getHeight()/2 - bottom + rad; if (right >= 0 && dR >= 0) { cnt ++; if (right > box->getWidth()/2) particlePos[X] = box->getWidth()/2; else particlePos[X] = right ; } if (left > 0 && dL >= 0) { cnt ++; if(left > box->getWidth()/2) particlePos[X] = -box->getWidth()/2; else particlePos[X] = -left ; } if (front >= 0 && dF >= 0) { cnt ++; if (front > box->getDepth()/2) particlePos[Z] = box->getDepth()/2; else particlePos[Z] = front; } if (back > 0 && dBa >= 0) { cnt ++; if (back > box->getDepth()/2) particlePos[Z] = -box->getDepth()/2; else particlePos[Z] = -back; } if (top >= 0 && dT >= 0) { cnt ++; if (top > box->getHeight()/2) particlePos[Y] = box->getHeight()/2; else particlePos[Y] = top; } if (bottom > 0 && dBo >= 0) { cnt ++; if (bottom > box->getHeight()/2) particlePos[Y] = -box->getHeight()/2; else particlePos[Y] = -bottom ; } //test auf collision if (cnt >= 3) { //berechnung normalB und contactPoint const Vector3<float>& contactPoint = qRotate(particlePos, boxOri) + box->getRigidBody()->getPosition(); //cout << "C: " << contactPoint << endl; //cout << "P: " << part->getPosition() << endl; Vector3<float> normalB = part->getPosition() - contactPoint; //cout << normalB.length() <<"\n"; //if (normalB.length() != 0) normalB.normalize(); // folgender Abschnitt aus: // CollisionSystem::collisionResponse(part, sphere, contactPoint, normalB); //berechnung der relativen geschwindigkeit in richtung normalB const Vector3<float>& velocityA = part->getVelocity(); const Vector3<float>& velocityB = box->getRigidBody()->getVelocity(); Vector3<float> velA = part->getVelocity(); Vector3<float> forceA = part->getForce(); // const Vector3<float>& rA = contactPoint - part->getPosition(); // vorher: particlePos! // const Vector3<float>& rB = contactPoint - box->getPosition(); const Vector3<float>& vA = velocityA; const Vector3<float>& vB = velocityB; const Vector3<float>& vR = vA - vB; float vN = dot(vR, normalB); //------------------Behandlung für colliding contact--------------------------------------- if (vN <= 0.5) { //--------------------neue Behandlung aus Sphere kopiert------------------------- float vDoN = dot(velA, normalB); Vector3<float> vS = normalB * vDoN; float fDoN = dot(forceA, normalB); Vector3<float> fS = normalB * fDoN; Vector3<float> force = part->getForce(); force.normalize(); if (dot (force, normalB) > 0 ){ part->setVelocity(part->getVelocity() - vS); part->setVelocity(part->getVelocity() * 0.75); // Wert: 0.75 part->addForce((-1.0) * fS); part->setForce(part->getForce() * 0.75); // Wert: 0.75 part->setIsColliding(true); } //------------------------------------------------------------------------------ ////berechnung der impuls-kraft in richtung normalB ////float damping = (0.01f + box->getBounciness()) / 2.0f; //float damping = 0.12f; //float invMassA, invMassB = 0.0f; ////Matrix<float> invTensorA(3,3); ////Matrix<float> invTensorB = box->getInvWorldInertiaTensor(); ////test ob dynamisch //if(part->getIsDynamicFlag()) //{ // invMassA = part->getInvMass(); //} //else // invMassA = 0.0; // //if(box->getRigidBody()->getIsDynamicFlag()) //{ // invMassB = box->getInvMass(); // //invTensorB = box->getRigidBody()->getInvWorldInertiaTensor(); //} //else // invMassB = 0.0; //float fNum = -(/*1+*/damping)*(dot(normalB,(velocityA - velocityB))); //float fDenom = invMassA + invMassB;// + dot(crossA,uA)+dot(crossB,uB); //float impulseMagnitude = fNum / fDenom; //if (impulseMagnitude < 0){ //Vector3<float> impulseForce = impulseMagnitude * normalB; ///*impulseForce.normalize(); //float vDoI = dot(velA, impulseForce); //float fDoI = dot(forceA, impulseForce); //Vec3 vS = impulseForce * vDoI; //Vec3 fS = impulseForce * fDoI;*/ ////part->setVelocity(part->getVelocity()[X], 0.0f, part->getVelocity()[Z]); ////part->setVelocity(part->getVelocity() - vS); ////part->addForce(fS); ////setzen der linaren momente //if (part->getInvMass()!=0) //{ //part->setVelocity(part->getVelocity() - impulseForce/invMassA); //part->setIsColliding(true); //} ////part->setVelocity(part->getVelocity() + (impulseForce / invMassB)); // //} } } }
void BlockBox::handlePostChildLayout(LayoutEngine& eng, BoxPtr child) { // Called after every child is laid out. //std::cerr << "t: " << (child->getTop()/65536.f) << ", h: " << (child->getHeight()/65536.f) << ", mbp-b: " << (child->getMBPBottom()/65536.f) << "\n"; setContentHeight(child->getTop() + child->getHeight() + child->getMBPBottom()); }
std::vector<BoxPtr> LayoutEngine::layoutChildren(const std::vector<StyleNodePtr>& children, BoxPtr parent) { StackManager<point> offset_manager(offset_, point(parent->getLeft(), parent->getTop()) + offset_.top()); std::vector<BoxPtr> res; for(auto it = children.begin(); it != children.end(); ++it) { auto child = *it; auto node = child->getNode(); ASSERT_LOG(node != nullptr, "Something went wrong, there was a StyleNode without an associated DOM node."); if(node->id() == NodeId::ELEMENT) { if(node->ignoreForLayout()) { continue; } // Adjust counters for list items as needed std::unique_ptr<StackManager<int>> li_manager; if(node->hasTag(ElementId::UL) || node->hasTag(ElementId::OL)) { li_manager.reset(new StackManager<int>(list_item_counter_, 0)); } if(node->hasTag(ElementId::LI) ) { auto &top = list_item_counter_.top(); ++top; } const Display display = child->getDisplay(); const Float cfloat = child->getFloat(); const Position position = child->getPosition(); if(display == Display::NONE) { // Do not create a box for this or it's children // early return continue; } if(position == Position::ABSOLUTE_POS) { // absolute positioned elements are taken out of the normal document flow parent->addAbsoluteElement(*this, parent->getDimensions(), std::make_shared<AbsoluteBox>(parent, child, root_)); } else if(position == Position::FIXED) { // fixed positioned elements are taken out of the normal document flow root_->addFixed(std::make_shared<BlockBox>(parent, child, root_)); } else { if(cfloat != Float::NONE) { // XXX need to add an offset to position for the float box based on body margin. // N.B. if the current display is one of the CssDisplay::TABLE* styles then this should be // a table box rather than a block box. Inline boxes are going to get wrapped in a BlockBox if(display == Display::BLOCK) { res.emplace_back(std::make_shared<BlockBox>(parent, child, root_)); } else if(display == Display::LIST_ITEM) { res.emplace_back(std::make_shared<ListItemBox>(parent, child, root_, list_item_counter_.top())); } else if(display == Display::TABLE) { //root_->addFloatBox(*this, std::make_shared<TableBox>(parent, child), cfloat, offset_.top().x, offset_.top().y + (open_box != nullptr ? open_box->getCursor().y : 0)); ASSERT_LOG(false, "Implement Table display"); } else { // default to using a block box to wrap content. res.emplace_back(std::make_shared<BlockBox>(parent, child, root_)); } continue; } switch(display) { case Display::NONE: // Do not create a box for this or it's children break; case Display::INLINE: { if(node->isReplaced()) { // replaced elements should generate a box. // XXX should these go into open_box? res.emplace_back(std::make_shared<InlineElementBox>(parent, child, root_)); } else { // find first and last text children std::vector<StyleNodePtr>::const_iterator first_text_child = child->getChildren().end(); std::vector<StyleNodePtr>::const_iterator last_text_child = child->getChildren().end(); for(auto it = child->getChildren().begin(); it != child->getChildren().end(); ++it) { if(*it != nullptr && (*it)->getNode()->id() == NodeId::TEXT) { if(first_text_child == child->getChildren().end()) { first_text_child = it; } last_text_child = it; } } // non-replaced elements we just generate children and add them. for(auto it = child->getChildren().begin(); it != child->getChildren().end(); ++it) { auto& inline_child = *it; NodePtr inline_node = inline_child->getNode(); if(inline_node != nullptr && inline_node->id() == NodeId::TEXT) { inline_child->inheritProperties(child); } } std::vector<BoxPtr> new_children = layoutChildren(child->getChildren(), parent); // alter border and padding to suit for(auto& box_child : new_children) { if(*first_text_child == box_child->getStyleNode()) { box_child->setFirstInlineChild(); } if(*last_text_child == box_child->getStyleNode()) { box_child->setLastInlineChild(); } } res.insert(res.end(), new_children.begin(), new_children.end()); } break; } case Display::BLOCK: { res.emplace_back(std::make_shared<BlockBox>(parent, child, root_)); break; } case Display::INLINE_BLOCK: { res.emplace_back(std::make_shared<InlineBlockBox>(parent, child, root_)); break; } case Display::LIST_ITEM: { res.emplace_back(std::make_shared<ListItemBox>(parent, child, root_, list_item_counter_.top())); break; } case Display::TABLE: case Display::INLINE_TABLE: case Display::TABLE_ROW_GROUP: case Display::TABLE_HEADER_GROUP: case Display::TABLE_FOOTER_GROUP: case Display::TABLE_ROW: case Display::TABLE_COLUMN_GROUP: case Display::TABLE_COLUMN: case Display::TABLE_CELL: case Display::TABLE_CAPTION: ASSERT_LOG(false, "FIXME: LayoutEngine::formatNode(): " << display_string(display)); break; default: ASSERT_LOG(false, "illegal display value: " << static_cast<int>(display)); break; } } } else if(node->id() == NodeId::TEXT) { res.emplace_back(std::make_shared<TextBox>(parent, child, root_)); } else { ASSERT_LOG(false, "Unhandled node id, only elements and text can be used in layout: " << static_cast<int>(node->id())); } } return res; }
void ListItemBox::handlePostChildLayout(LayoutEngine& eng, BoxPtr child) { setContentHeight(getHeight() + child->getHeight() + child->getMBPBottom()); }
BoxPtr Box::create( Node *parent, const Set *childNodes ) { BoxPtr result = new Box; parent->addChild( result ); // it's pretty natural to call this function passing childNodes == ScriptNode::selection(). // unfortunately nodes will be removed from the selection as we reparent // them, so we have to make a copy of childNodes so our iteration isn't befuddled by // the changing contents. we can use this opportunity to weed out anything in childNodes // which isn't a direct child of parent though. StandardSetPtr verifiedChildNodes = new StandardSet(); for( NodeIterator nodeIt( parent ); nodeIt != nodeIt.end(); nodeIt++ ) { if( childNodes->contains( nodeIt->get() ) ) { verifiedChildNodes->add( *nodeIt ); } } // when a node we're putting in the box has connections to // a node remaining outside, we need to reroute the connection // via an intermediate plug on the box. this mapping maps input // plugs (be they internal or external) to intermediate input plugs. typedef std::pair<const Plug *, Plug *> PlugPair; typedef std::map<const Plug *, Plug *> PlugMap; PlugMap plugMap; for( size_t i = 0, e = verifiedChildNodes->size(); i < e; i++ ) { Node *childNode = static_cast<Node *>( verifiedChildNodes->member( i ) ); // reroute any connections to external nodes for( RecursivePlugIterator plugIt( childNode ); plugIt != plugIt.end(); plugIt++ ) { Plug *plug = plugIt->get(); if( plug->direction() == Plug::In ) { Plug *input = plug->getInput<Plug>(); if( input && !verifiedChildNodes->contains( input->node() ) ) { PlugMap::const_iterator mapIt = plugMap.find( input ); if( mapIt == plugMap.end() ) { PlugPtr intermediateInput = plug->createCounterpart( result->promotedCounterpartName( plug ), Plug::In ); // we want intermediate inputs to appear on the same side of the node as the // equivalent internal plug, so we copy the relevant metadata over. copyMetadata( plug, intermediateInput.get() ); intermediateInput->setFlags( Plug::Dynamic, true ); result->addChild( intermediateInput ); intermediateInput->setInput( input ); mapIt = plugMap.insert( PlugPair( input, intermediateInput.get() ) ).first; } plug->setInput( mapIt->second ); plugIt.prune(); } } else { // take a copy of the outputs, because we might be modifying the // original as we iterate. Plug::OutputContainer outputs = plug->outputs(); if( !outputs.empty() ) { typedef Plug::OutputContainer::const_iterator OutputIterator; for( OutputIterator oIt = outputs.begin(), eIt = outputs.end(); oIt != eIt; oIt++ ) { Plug *output = *oIt; const Node *outputNode = output->node(); if( outputNode->parent<Node>() == parent && !verifiedChildNodes->contains( outputNode ) ) { PlugMap::const_iterator mapIt = plugMap.find( plug ); if( mapIt == plugMap.end() ) { PlugPtr intermediateOutput = plug->createCounterpart( result->promotedCounterpartName( plug ), Plug::Out ); copyMetadata( plug, intermediateOutput.get() ); intermediateOutput->setFlags( Plug::Dynamic, true ); result->addChild( intermediateOutput ); intermediateOutput->setInput( plug ); mapIt = plugMap.insert( PlugPair( plug, intermediateOutput.get() ) ).first; } output->setInput( mapIt->second ); } } plugIt.prune(); } } } // reparent the child under the Box. it's important that we do this after adding the intermediate // input plugs, so that when they are serialised and reloaded, the inputs to the box are set before // the inputs to the nodes inside the box - see GafferSceneTest.ShaderAssignmentTest.testAssignShaderFromOutsideBox // for a test case highlighting this necessity. result->addChild( childNode ); } return result; }