Jump to content
The Dark Mod Forums

MapExpressions


Recommended Posts

I suggest dividing the external interface to the Model Selector into two functions -- the current one which is used for choosing a NEW model, and displays all of the extra options, and a new one which is used for choosing an EXISTING model, which displays no extra options (and could theoretically not bother expanding skins either).

 

Obviously the two functions would need to return different types, I suggest keeping the ModelCreationSettings (or whatever it is called) for the new model function, and just returning a string model name for the existing model function.

Link to comment
Share on other sites

  • Replies 314
  • Created
  • Last Reply

Top Posters In This Topic

But you have to set showOptions to false first, and if you set that one to false, you should already understand that the results in the returned structure are meaningless.

 

I think I will now add the "add clipBrush" option to the right-click-menu.

Link to comment
Share on other sites

How can I iterate the SelectionList? The SelectionList is a template (is there more than one?), and the iterator is templated to, so I don't know how to use the iterator. Same problem with a->name. Where is the actual instance of the SelectionList?

	for(iterator a = SelectionList.begin(), a != SelectionList.end(), a++) { 
	 // TODO: to be replaced by inheritance-based class detection 
	 if (!string_equal_nocase(a->name, "func_static")) { 
		 nonModel = true; 
		 break; 
	 } 
 }

Link to comment
Share on other sites

The SelectionList is a private member of the SelectionSystem, so you shouldn't be directly iterating over it. The way to traverse the current selection is to call

GlobalSelectionSystem().foreachSelected(Visitor& visitor);

What do you intend to do? Maybe there is already existing functionality, that I know of?

Link to comment
Share on other sites

I want the menu button "create MonsterClip" to work when one or more models are selected. So I want to check the SelectionList for non models and switch the button sensible/insensible. When called I'd like to create the monsterClip for every item in the SelectionList.

Link to comment
Share on other sites

I see. Best thing is to write a Visitor then:

typedef std::vector<scene::Path> InstanceList;

class ModelFinder :
  public SelectionSystem::Visitor
{
  InstanceList& _targetList;
public:
  ModelFinder(InstanceList& targetList) :
 _targetList(targetList)
  {}

  void visit(scene::Instance& instance) const {
   Entity* entity = Node_getEntity(instance.path().top());
   if (entity != NULL && isModel(entity)) {
		_targetList.push_back(instance.path());
   }
  }
};

// somewhere else in the code
{
InstanceList modelList;
ModelFinder visitor(modelList);
GlobalSelectionSystem().foreachSelected(visitor);

if (modelList.size() > 0) {
   // One or more models found
}
}

I don't know if the above code works, I haven't compiled it. ;) Could be that I forgot to add a "mutable" keyword in the visitor class due to that stupid "const" declaration in the abstract base class.

Link to comment
Share on other sites

Ah, not really intended. You're right, this has to be considered of course. A boolean flag set to true in the visitor class or anything else what comes to your mind will do the trick, I guess. :)

Link to comment
Share on other sites

You can declare your bool as mutable:

class ModuleFinder :
  public SelectionSystem::Visitor
{
  mutable _nonModelFound;
public:
  // bleh
};

This mutable keyword can be used to make members writable even in const member methods. It's of course bad style to use it (in well-designed code it shouldn't be used at all, imo), but I guess it's ok in this case.

 

If you're feeling ambitious, you can of course change the SelectionSystem::Visitor abstract base class and remove the const keyword. I don't see why visitors need to be const while traversing the selection.

Link to comment
Share on other sites

You can recognise models like this:

  • Instance is an Entity
  • Entity has spawnarg "classname" == "func_static"
  • Entity has non-empty spawnarg "name"
  • Entity has non-empty spawnarg "model" != "name"

I think the best thing would be to extend the Entity interface (defined in ientity.h) to include a

virtual bool isModel() const = 0;

method to check whether this entity is a model. If you don't want to dig that deep, I can add this method for you, as I'm very familiar with the various Entity classes.

Link to comment
Share on other sites

I'd be gratefull if you do that, since I really don't entirely know the Scenegraph yet. Especially after you said how to recognize models.

An Instance can be an entity? I thought an Instance was a path with rootnode, entity and primitives (nodes).

Non-empty spawnarg name? in ientity.h: STRING_CONSTANT(Name, "Entity");

I obviously get some things wrong here...

Link to comment
Share on other sites

Sorry, if I confused you about the Instances. It's easy to get lost in the scenegraph, speaking from my own experience. I only recently wrapped my head about the inner workings and I'm still not entirely enlightened about a few things.

 

The scenegraph consists of scene::Nodes, which build up a tree. In theory, each node can have one or more child nodes. The topmost node is called the scenegraph root. There are several scene::Node classes in DarkRadiant, each with a different set of properties.

  • RootNode (represents the scenegraph root)
  • BrushNode
  • PatchNode
  • Doom3GroupNode (the most complex of these all)
  • EclassModelNode
  • GenericEntityNode
  • LightNode
  • MD5ModelNode
  • PicoModelNode

The Doom3GroupNode, EclassModelNode, GenericEntityNode and LightNode are Entities. They can have spawnargs (key/value pairs). To recognise a node as Entity, call Node_getEntity() or Node_isEntity(). This will try to cast the INodePtr onto an Entity*.

 

An Instance is not a path, but an instance has a path. The path is used to lookup the instance in the scenegraph, it's some sort of unique ID. Every node needs a path before it can be instantiated.

 

(I'm just realizing, that I don't explain that very well here, so hopefully I'm not confusing you even more. Sorry about that. ;))

 

Forget the bit about STRING_CONSTANT, this is mostly legacy stuff and I'm almost sure we can remove that. It was used to implement a home-grown type-cast system similar to C++'s dynamic_cast.

 

I will implement that function, I'll post back here when it's done. :)

Link to comment
Share on other sites

Ok, the latest SVN revision features the isModel() method. Call it on the Entity:

Entity* entity = Node_getEntity(scene::INodePtr);
if (entity->isModel()) {
  // blah
}

You'll need to recompile almost everything as many other files are depending on the ientity.h header, that's why it took me so long ;)

 

Btw: there is also a wiki page on the DarkRadiant scenegraph, perhaps this helps to clarify things.

Link to comment
Share on other sites

I use the wiki actively all the time (otherwise I would by far haven't come as far as I have). According to your explanation the scenegraph is no real node structure with child/parent nodes, but a derivation structure with a base class and derived subclasses. Is that correct?

 

You implemented that quite fast 8-|

I hope the sync won't require many manual merges...

Link to comment
Share on other sites

radiant/ui/ortho/OrthoContextMenu.cpp: In member function 'void ui::OrthoContextMenu::checkMonsterClip()':
radiant/ui/ortho/OrthoContextMenu.cpp:154: error: no matching function for call to 'SelectionSystem::foreachSelected(ui::ModelFinder (&)())'
include/iselection.h:143: note: candidates are: virtual void SelectionSystem::foreachSelected(const SelectionSystem::Visitor&) const
radiant/ui/ortho/OrthoContextMenu.cpp:157: error: request for member 'modelList' in 'ui::visitor', which is of non-class type 'ui::ModelFinder ()()'
radiant/ui/ortho/OrthoContextMenu.cpp:157: error: request for member 'onlyModels' in 'ui::visitor', which is of non-class type 'ui::ModelFinder ()()'

I get this error message that says that my visitor is no class.

typedef std::vector<scene::Path> InstanceList;
class ModelFinder : public SelectionSystem::Visitor {
InstanceList targetList;
bool onlyModels;
public:
ModelFinder() :
		onlyModels(true)
{}
void visit(scene::Instance& instance) {
	Entity* entity = Node_getEntity(instance.path().top());
	if (entity->isModel()) {
		targetList.push_back(instance.path());
	}
	else {
		onlyModels = false;
	}}};

But this is obviously a class. For completeness here the lines that cause the error:

ModelFinder visitor();
GlobalSelectionSystem().foreachSelected(visitor);

I have really no idea what the reason is, as this is really just a normal class. Any ideas?

Link to comment
Share on other sites

After changing this Visitor::visitor from const to nonconst, a LOT of dependencies need to be changed too. At some point (after changing a lot of functions from const to non const) gcc spits this out

radiant/brush/BrushVisit.h: In function 'const Functor& Scene_forEachSelectedBrush(const Functor&) [with Functor = BrushForEachFace]':
radiant/brush/BrushVisit.h:162:   instantiated from 'const Functor& Scene_ForEachSelectedBrush_ForEachFace(scene::Graph&, const Functor&) [with Functor = FaceSetShader]'
radiant/brushmanip.cpp:385:   instantiated from here
radiant/brush/BrushVisit.h:25: error: no matching function for call to 'SelectionSystem::foreachSelected(BrushSelectedVisitor<BrushForEachFace>)'
include/iselection.h:143: note: candidates are: virtual void SelectionSystem::foreachSelected(SelectionSystem::Visitor&) const

But these functions seem to comply.

I did a lot trial-and-error on the functions in those files but at some point gcc always spits out a similar message. I start to wonder if it's a good idea to make the Visitor::visit nonconst...

If someone wants to take a look, I uploaded a diff: monsterClipDiff.diff

Some hint what's wrong would be helpful.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share


  • Recent Status Updates

    • Gilkar

      When I was a young man my father was so ignorant I could hardly stand to have him around. As I grew older I was amazed at how much the old man had learned in such a short time.
      · 0 replies
    • jaxa

      RTX 3090 Super, RTX 3070 Ti 16 GB, RTX 2060 12 GB
      https://wccftech.com/nvidia-launching-rtx-3090-super-rtx-3070-ti-16gb-and-rtx-2060-12gb-by-january-2022/
      · 0 replies
    • duzenko

      CPU benchmark time - compiling DarkRadiant (2nd run)
      i5 8600K 6C/6T@4.4GHz DDR4 2x2133MHz 9MB cache
      Parallel builds: 1. 3:57 Parallel builds: 6 (default). 2:28 r5 1600AF 6C/12T@3.3GHz DDR4 1x2666MHz 16 MB cache, temp folder on HDD
      Parallel builds: 1. 5:05 Parallel builds: 4. 2:47 Parallel builds: 6. 2:55 Parallel builds: 12 (default). 2:57
      · 6 replies
    • nbohr1more

      Status updates are back so it is also a good time to return to contests!
      https://forums.thedarkmod.com/index.php?/topic/21095-christmas-connections-contest-2021
       
      · 0 replies
    • freyk

      Having seen the new scifi stuff from bladeghost/scythwraith, want to continue the cyberpunk project. Only one problem, can't map.
      · 1 reply
×
×
  • Create New...