void RotateSelected::visit(const scene::INodePtr& node) const
{
    ITransformNodePtr transformNode = Node_getTransformNode(node);

    if (transformNode) 
    {
        // Upcast the instance onto a Transformable
        ITransformablePtr transformable = Node_getTransformable(node);

        if (transformable)
        {
            // The object is not scaled or translated explicitly
            // A translation might occur due to the rotation around a pivot point
            transformable->setType(TRANSFORM_PRIMITIVE);
            transformable->setScale(c_scale_identity);
            transformable->setTranslation(c_translation_identity);

            // Pass the rotation quaternion and the world pivot, 
            // unless we're rotating each object around their own center
            transformable->setRotation(_rotation, 
                _freeObjectRotation ? transformable->getUntransformedOrigin() : _worldPivot, 
                node->localToWorld());
        }
    }
}
예제 #2
0
void ModelExporter::processLight(const scene::INodePtr& node)
{
	// Export lights as small polyhedron
	static const double EXTENTS = 8.0;
	std::vector<model::ModelPolygon> polys;

	Vertex3f up(0, 0, EXTENTS);
	Vertex3f down(0, 0, -EXTENTS);
	Vertex3f north(0, EXTENTS, 0);
	Vertex3f south(0, -EXTENTS, 0);
	Vertex3f east(EXTENTS, 0, 0);
	Vertex3f west(-EXTENTS, 0, 0);

	// Upper semi-diamond
	polys.push_back(createPolyCCW(up, south, east));
	polys.push_back(createPolyCCW(up, east, north));
	polys.push_back(createPolyCCW(up, north, west));
	polys.push_back(createPolyCCW(up, west, south));

	// Lower semi-diamond
	polys.push_back(createPolyCCW(down, south, west));
	polys.push_back(createPolyCCW(down, west, north));
	polys.push_back(createPolyCCW(down, north, east));
	polys.push_back(createPolyCCW(down, east, south));

	Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform);

	_exporter->addPolygons("lights/default", polys, exportTransform);
}
예제 #3
0
bool MapImporter::addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity)
{
	_nodes.insert(NodeMap::value_type(
		NodeIndexPair(_entityCount, _primitiveCount), primitive));

	_primitiveCount++;

	if (_dialog && _dialogEventLimiter.readyForEvent())
    {
		_dialog->setTextAndFraction(
            _dlgEntityText + "Primitive " + string::to_string(_primitiveCount),
			getProgressFraction()
        );
    }

	if (Node_getEntity(entity)->isContainer())
	{
		entity->addChildNode(primitive);
		return true;
	}
	else
	{
		return false;
	}
}
void ScaleSelected::visit(const scene::INodePtr& node) const {
    ITransformNodePtr transformNode = Node_getTransformNode(node);
    if(transformNode != 0)
    {
      ITransformablePtr transform = Node_getTransformable(node);
      if(transform != 0)
      {
        transform->setType(TRANSFORM_PRIMITIVE);
        transform->setScale(c_scale_identity);
        transform->setTranslation(c_translation_identity);

        transform->setType(TRANSFORM_PRIMITIVE);
        transform->setScale(m_scale);
        {
          EditablePtr editable = Node_getEditable(node);
          const Matrix4& localPivot = editable != 0 ? editable->getLocalPivot() : Matrix4::getIdentity();

          Vector3 parent_translation;
          translation_for_pivoted_scale(
            parent_translation,
            m_scale,
            m_world_pivot,
			node->localToWorld().getMultipliedBy(localPivot),
			transformNode->localToParent().getMultipliedBy(localPivot)
          );

          transform->setTranslation(parent_translation);
        }
      }
    }
}
예제 #5
0
void GraphTreeModel::updateSelectionStatus(const scene::INodePtr& node,
										   const NotifySelectionUpdateFunc& notifySelectionChanged)
{
	NodeMap::const_iterator found = _nodemap.find(scene::INodeWeakPtr(node));

	GraphTreeNodePtr foundNode;

	if (found == _nodemap.end())
	{
		// The node is not in our map, it might have been previously hidden
		if (node->visible())
		{
			foundNode = insert(node);
		}
	}
	else
	{
		foundNode = found->second;
	}

	if (foundNode)
	{
		notifySelectionChanged(foundNode->getIter(), Node_isSelected(node));
	}
}
예제 #6
0
	void visit(const scene::INodePtr& node) const {
		BrushNodePtr brush = std::dynamic_pointer_cast<BrushNode>(node);

		if (brush != NULL && node->visible()) {
			brush->setClipPlane(_plane);
		}
	}
예제 #7
0
void InfoFileExporter::visit(const scene::INodePtr& node)
{
    // Don't export the layer settings for models and particles, as they are not there
    // at map load/parse time - these shouldn't even be passed in here
    assert(node && !Node_isModel(node) && !particles::isParticleNode(node));

    // Open a Node block
    _stream << "\t\t" << InfoFile::NODE << " { ";

    scene::LayerList layers = node->getLayers();

    // Write a space-separated list of node IDs
    for (scene::LayerList::const_iterator i = layers.begin(); i != layers.end(); ++i)
    {
        _stream << *i << " ";
    }
    
    // Close the Node block
    _stream << "}";

    // Write additional node info, for easier debugging of layer issues
    _stream << " // " << getNodeInfo(node);

    _stream << std::endl;

    _layerInfoCount++;
}
예제 #8
0
    virtual bool pre(const scene::INodePtr& node)
    {
        NamespacedPtr namespaced = Node_getNamespaced(node);
        if (!namespaced)
        {
            return true;
        }

        INamespace* foreignNamespace = namespaced->getNamespace();

        // Do not reconnect to same namespace, this causes invalid name changes
        if (foreignNamespace == _nspace)
        {
            rWarning() << "ConnectNamespacedWalker: node '" << node->name()
                       << "' is already attached to namespace at " << _nspace
                       << std::endl;

            return true;
        }
        else if (foreignNamespace)
        {
            // The node is already connected to a different namespace, disconnect
            namespaced->disconnectNameObservers();
            namespaced->detachNames();
            namespaced->setNamespace(NULL);
        }

        // Set the namespace reference and add all "names"
        namespaced->setNamespace(_nspace);
        namespaced->attachNames();

        return true;
    }
예제 #9
0
void Namespace::ensureNoConflicts(const scene::INodePtr& root)
{
    // Instantiate a new, temporary namespace for the nodes below root
    Namespace foreignNamespace;

    // Move all nodes below (and including) root into this temporary namespace
    foreignNamespace.connect(root);

    // Collect all namespaced items from the foreign root
    GatherNamespacedWalker walker;
    root->traverse(walker);

    rDebug() << "Namespace::ensureNoConflicts(): imported set of "
             << walker.result.size() << " namespaced nodes" << std::endl;

    // Build a union set containing all imported names and all existing names.
    // We need to know all existing names to ensure that newly created names are
    // unique in *both* namespaces
    UniqueNameSet allNames = _uniqueNames;
    allNames.merge(foreignNamespace._uniqueNames);

    // Process each object in the to-be-imported tree of nodes, ensuring that it
    // has a unique name
    for (const NamespacedPtr& n : walker.result)
    {
        // If the imported node conflicts with a name in THIS namespace, then it
        // needs to be given a new name which is unique in BOTH namespaces.
        if (_uniqueNames.nameExists(n->getName()))
        {
            // Name exists in the target namespace, get a new name
            std::string uniqueName = allNames.insertUnique(n->getName());

            rMessage() << "Namespace::ensureNoConflicts(): '" << n->getName()
                       << "' already exists in this namespace. Rename it to '"
                       << uniqueName << "'\n";

            // Change the name of the imported node, this should trigger all
            // observers in the foreign namespace
            n->changeName(uniqueName);
        }
        else
        {
            // Name does not exist yet, insert it into the local combined
            // namespace (but not our destination namespace, this will be
            // populated in the subsequent call to connect()).
            allNames.insert(n->getName());
        }
    }

    // at this point, all names in the foreign namespace have been converted to
    // something unique in this namespace. The calling code can now move the
    // nodes into this namespace without name conflicts

    // Disconnect the root from the foreign namespace again, it will be destroyed now
    foreignNamespace.disconnect(root);
}
예제 #10
0
		bool pre(const scene::INodePtr& node) {
			SelectablePtr selectable = Node_getSelectable(node);

			// If a visible selectable was found and the path depth is appropriate, add it
			if (selectable != NULL && node->visible()) {
				_targetList.push_back(node);
			}

			return true;
		}
예제 #11
0
	void post(const scene::INodePtr& node)
	{
		if (node->isRoot())
		{
			return;
		}

		if (Node_isSelected(node))
		{
			// Clone the current node
			scene::INodePtr clone = map::Node_Clone(node);

			// Add the cloned node and its parent to the list
			_cloned.insert(Map::value_type(clone, node->getParent()));

			// Insert this node in the root
			_cloneRoot->addChildNode(clone);
		}
	}
예제 #12
0
void PlaneSelectableSelectPlanes::visit(const scene::INodePtr& node) const {
	// Skip hidden nodes
	if (!node->visible()) {
		return;
	}

	PlaneSelectablePtr planeSelectable = Node_getPlaneSelectable(node);
	if (planeSelectable != NULL) {
		planeSelectable->selectPlanes(_selector, _test, _selectedPlaneCallback);
	}
}
void ScaleComponentSelected::visit(const scene::INodePtr& node) const {
    ITransformablePtr transform = Node_getTransformable(node);
    if(transform != 0) {
      Vector3 parent_translation;
	  translation_for_pivoted_scale(parent_translation, m_scale, m_world_pivot, node->localToWorld(), Node_getTransformNode(node)->localToParent());

      transform->setType(TRANSFORM_COMPONENT);
      transform->setScale(m_scale);
      transform->setTranslation(parent_translation);
    }
}
예제 #14
0
파일: Map.cpp 프로젝트: Zbyl/DarkRadiant
 bool addPrimitiveToEntity(const scene::INodePtr& primitive, const scene::INodePtr& entity)
 {
     if (Node_getEntity(entity)->isContainer())
     {
         entity->addChildNode(primitive);
         return true;
     }
     else
     {
         return false;
     }
 }
예제 #15
0
	void visit(const scene::INodePtr& node) const {
		ASSERT_MESSAGE(_count <= _max, "Invalid _count in CollectSelectedBrushesBounds");

		// stop if the array is already full
		if (_count == _max) {
			return;
		}

		if (Node_isSelected(node) && Node_isBrush(node)) {
			_bounds[_count] = node->worldAABB();
			++_count;
		}
	}
예제 #16
0
	void post(const scene::INodePtr& node)
	{
		// greebo: We've traversed this subtree, now check if we had selected children
		if (!node->isRoot() && 
			!_stack.empty() && _stack.top() == false && 
			!Node_isSelected(node))
		{
			// No selected child nodes, hide this node
			hideSubgraph(node, _hide);
		}

		// Go upwards again, one level
		_stack.pop();
	}
예제 #17
0
파일: CamWnd.cpp 프로젝트: Zbyl/DarkRadiant
    bool pre(const scene::INodePtr& node) {

        if (!node->visible()) return false; // don't traverse hidden nodes

        if (Node_isBrush(node)) // this node is a floor
        {
            const AABB& aabb = node->worldAABB();

            float floorHeight = aabb.origin.z() + aabb.extents.z();

            if (floorHeight > _current && floorHeight < _bestUp) {
                _bestUp = floorHeight;
            }

            if (floorHeight < _current && floorHeight > _bestDown) {
                _bestDown = floorHeight;
            }

            return false;
        }

        return true;
    }
예제 #18
0
	bool pre(const scene::INodePtr& node) {
		if (node->visible()) {
			Brush* brush = Node_getBrush(node);

			if (brush != NULL && brush->hasShader(_name)) {
				Node_setSelected(node, true);
				return false; // don't traverse brushes
			}

			// not a suitable brush, traverse further
			return true;
		}
		else {
			return false; // don't traverse invisible nodes
		}
	}
예제 #19
0
	bool pre(const scene::INodePtr& node)
	{
		// Don't clone root items
		if (node->isRoot())
		{
			return true;
		}

		if (Node_isSelected(node))
		{
			// Don't traverse children of cloned nodes
			return false;
		}

		return true;
	}
예제 #20
0
	bool pre(const scene::INodePtr& node)
	{
		// Ignore hidden nodes
		if (!node->visible()) return false;

		Entity* entity = Node_getEntity(node);

		// Check if we have a selectable
		SelectablePtr selectable = Node_getSelectable(node);

		if (selectable != NULL)
		{
			switch (_mode)
			{
				case SelectionSystem::eEntity:
					if (entity != NULL && entity->getKeyValue("classname") != "worldspawn")
					{
						_selectable = selectable;
					}
					break;
				case SelectionSystem::ePrimitive:
					_selectable = selectable;
					break;
				case SelectionSystem::eComponent:
					// Check if we have a componentselectiontestable instance
					ComponentSelectionTestablePtr compSelTestable = 
						Node_getComponentSelectionTestable(node);

					// Only add it to the list if the instance has components and is already selected
					if (compSelTestable != NULL && selectable->isSelected())
					{
						_selectable = selectable;
					}
					break;
			}
		}
		
		// Do we have a groupnode? If yes, don't traverse the children
		if (entity != NULL && node_is_group(node) && 
			entity->getKeyValue("classname") != "worldspawn") 
		{
			// Don't traverse the children of this groupnode
			return false;
		}

		return true;
	}
예제 #21
0
bool EntitySelectByClassnameWalker::pre(const scene::INodePtr& node) {
	// don't traverse invisible nodes
	if (!node->visible()) return false; 

	Entity* entity = Node_getEntity(node);
	
	if (entity != NULL) {

		if (entityMatches(entity)) {
			// Got a matching entity
			Node_setSelected(node, true);
		}

		// Don't traverse entities
		return false;
	}

	// Not an entity, traverse
	return true;
}
예제 #22
0
void ModelExporter::processBrush(const scene::INodePtr& node)
{
	IBrush* brush = Node_getIBrush(node);

	if (brush == nullptr) return;

	Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform);

	for (std::size_t b = 0; b < brush->getNumFaces(); ++b)
	{
		const IFace& face = brush->getFace(b);

		const std::string& materialName = face.getShader();

		if (!isExportableMaterial(materialName)) continue;

		const IWinding& winding = face.getWinding();

		std::vector<model::ModelPolygon> polys;

		if (winding.size() < 3)
		{
			rWarning() << "Skipping face with less than 3 winding verts" << std::endl;
			continue;
		}

		// Create triangles for this winding 
		for (std::size_t i = 1; i < winding.size() - 1; ++i)
		{
			model::ModelPolygon poly;

			poly.a = convertWindingVertex(winding[i + 1]);
			poly.b = convertWindingVertex(winding[i]);
			poly.c = convertWindingVertex(winding[0]);

			polys.push_back(poly);
		}

		_exporter->addPolygons(materialName, polys, exportTransform);
	}
}
예제 #23
0
파일: CamWnd.cpp 프로젝트: Zbyl/DarkRadiant
    // The visitor function
    bool pre(const scene::INodePtr& node) {
        // Check if the node is filtered
        if (node->visible()) {
            SelectionTestablePtr selectionTestable = Node_getSelectionTestable(node);

            if (selectionTestable != NULL) {
                bool occluded;
                OccludeSelector selector(_bestIntersection, occluded);
                selectionTestable->testSelect(selector, _selectionTest);

                if (occluded) {
                    _node = node;
                }
            }
        }
        else {
            return false; // don't traverse filtered nodes
        }

        return true;
    }
예제 #24
0
void GraphTreeModel::updateSelectionStatus(const Glib::RefPtr<Gtk::TreeSelection>& selection, const scene::INodePtr& node)
{
	NodeMap::const_iterator found = _nodemap.find(scene::INodeWeakPtr(node));

	GraphTreeNodePtr foundNode;

	if (found == _nodemap.end())
	{
		// The node is not in our map, it might have been previously hidden
		if (node->visible())
		{
			foundNode = insert(node);
		}
	}
	else
	{
		foundNode = found->second;
	}

	if (foundNode)
	{
		if (Node_isSelected(node))
		{
			// Select the row in the TreeView
			selection->select(foundNode->getIter());

			// Scroll to the row
			Gtk::TreeView* tv = selection->get_tree_view();

			Gtk::TreeModel::Path selectedPath(foundNode->getIter());

			tv->expand_to_path(selectedPath);
			tv->scroll_to_row(selectedPath, 0.3f);
		}
		else
		{
			selection->unselect(foundNode->getIter());
		}
	}
}
예제 #25
0
	bool pre(const scene::INodePtr& node)
	{
		// Check the selection status
		bool isSelected = Node_isSelected(node);

		// greebo: Don't check root nodes for selected state
		if (!node->isRoot() && isSelected)
		{
			// We have a selected instance, "remember" this by setting the parent 
			// stack element to TRUE
			if (!_stack.empty())
			{
				_stack.top() = true;
			}
		}

		// We are going one level deeper, add a new stack element for this subtree
		_stack.push(false);

		// Try to go deeper, but don't do this for deselected instances
		return !isSelected;
	}
예제 #26
0
void ModelExporter::processPatch(const scene::INodePtr& node)
{
	IPatch* patch = Node_getIPatch(node);

	if (patch == nullptr) return;

	const std::string& materialName = patch->getShader();

	if (!isExportableMaterial(materialName)) return;

	PatchMesh mesh = patch->getTesselatedPatchMesh();

	std::vector<model::ModelPolygon> polys;

	for (std::size_t h = 0; h < mesh.height - 1; ++h)
	{
		for (std::size_t w = 0; w < mesh.width - 1; ++w)
		{
			model::ModelPolygon poly;

			poly.a = convertPatchVertex(mesh.vertices[w + (h*mesh.width)]);
			poly.b = convertPatchVertex(mesh.vertices[w + 1 + (h*mesh.width)]);
			poly.c = convertPatchVertex(mesh.vertices[w + mesh.width + (h*mesh.width)]);

			polys.push_back(poly);
				
			poly.a = convertPatchVertex(mesh.vertices[w + 1 + (h*mesh.width)]);
			poly.b = convertPatchVertex(mesh.vertices[w + 1 + mesh.width + (h*mesh.width)]);
			poly.c = convertPatchVertex(mesh.vertices[w + mesh.width + (h*mesh.width)]);

			polys.push_back(poly);
		}
	}

	Matrix4 exportTransform = node->localToWorld().getPremultipliedBy(_centerTransform);

	_exporter->addPolygons(materialName, polys, exportTransform);
}
예제 #27
0
inline bool Node_hasChildren(scene::INodePtr node)
{
	return node->hasChildNodes();
}
예제 #28
0
void createCaps(Patch& patch, const scene::INodePtr& parent, EPatchCap type, const std::string& shader)
{
	if ((type == eCapEndCap || type == eCapIEndCap) && patch.getWidth() != 5)
	{
		rError() << "cannot create end-cap - patch width != 5" << std::endl;

		gtkutil::MessageBox::ShowError(_("Cannot create end-cap, patch must have a width of 5."),
			GlobalMainFrame().getTopLevelWindow());

		return;
	}

	if ((type == eCapBevel || type == eCapIBevel) && patch.getWidth() != 3)
	{
		gtkutil::MessageBox::ShowError(_("Cannot create bevel-cap, patch must have a width of 3."),
			GlobalMainFrame().getTopLevelWindow());

		rError() << "cannot create bevel-cap - patch width != 3" << std::endl;
		return;

	}

	if (type == eCapCylinder && patch.getWidth() != 9)
	{
		gtkutil::MessageBox::ShowError(_("Cannot create cylinder-cap, patch must have a width of 9."),
			GlobalMainFrame().getTopLevelWindow());

		rError() << "cannot create cylinder-cap - patch width != 9" << std::endl;
		return;
	}

	assert(parent != NULL);

	{
		scene::INodePtr cap(GlobalPatchCreator(DEF2).createPatch());
		parent->addChildNode(cap);

		Patch* capPatch = Node_getPatch(cap);
		assert(capPatch != NULL);

		patch.MakeCap(capPatch, type, ROW, true);
		capPatch->setShader(shader);

		// greebo: Avoid creating "degenerate" patches (all vertices merged in one 3D point)
		if (!capPatch->isDegenerate())
		{
			Node_setSelected(cap, true);
		}
		else
		{
			parent->removeChildNode(cap);
			rWarning() << "Prevented insertion of degenerate patch." << std::endl;
		}
	}

	{
		scene::INodePtr cap(GlobalPatchCreator(DEF2).createPatch());
		parent->addChildNode(cap);

		Patch* capPatch = Node_getPatch(cap);
		assert(capPatch != NULL);

		patch.MakeCap(capPatch, type, ROW, false);
		capPatch->setShader(shader);

		// greebo: Avoid creating "degenerate" patches (all vertices merged in one 3D point)
		if (!capPatch->isDegenerate())
		{
			Node_setSelected(cap, true);
		}
		else
		{
			parent->removeChildNode(cap);
			rWarning() << "Prevented insertion of degenerate patch." << std::endl;
		}
	}
}
예제 #29
0
파일: Map.cpp 프로젝트: Zbyl/DarkRadiant
 bool addEntity(const scene::INodePtr& entityNode)
 {
     _root->addChildNode(entityNode);
     return true;
 }
예제 #30
0
void BrushByPlaneClipper::visit(const scene::INodePtr& node) const {
	// Don't clip invisible nodes
	if (!node->visible()) {
		return;
	}

	// Try to cast the instance onto a brush
	Brush* brush = Node_getBrush(node);

	// Return if not brush
	if (brush == NULL) {
		return;
	}

	Plane3 plane(_p0, _p1, _p2);
	if (!plane.isValid()) {
		return;
	}

	// greebo: Analyse the brush to find out which shader is the most used one
	getMostUsedTexturing(brush);

	BrushSplitType split = Brush_classifyPlane(*brush, _split == eFront ? -plane : plane);

	if (split.counts[ePlaneBack] && split.counts[ePlaneFront]) {
		// the plane intersects this brush
		if (_split == eFrontAndBack) {
			scene::INodePtr brushNode = GlobalBrushCreator().createBrush();

			assert(brushNode != NULL);

			Brush* fragment = Node_getBrush(brushNode);
			assert(fragment != NULL);
			fragment->copy(*brush);

			FacePtr newFace = fragment->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

			if (newFace != NULL && _split != eFront) {
				newFace->flipWinding();
			}

			fragment->removeEmptyFaces();
			ASSERT_MESSAGE(!fragment->empty(), "brush left with no faces after split");

			// Mark this brush for insertion
			_insertList.insert(InsertMap::value_type(brushNode, node->getParent()));
		}

		FacePtr newFace = brush->addPlane(_p0, _p1, _p2, _mostUsedShader, _mostUsedProjection);

		if (newFace != NULL && _split == eFront) {
			newFace->flipWinding();
		}

		brush->removeEmptyFaces();
		ASSERT_MESSAGE(!brush->empty(), "brush left with no faces after split");
	}
	// the plane does not intersect this brush
	else if (_split != eFrontAndBack && split.counts[ePlaneBack] != 0) {
		// the brush is "behind" the plane
		_deleteList.insert(node);
	}
}