Jump to content
The Dark Mod Forums

OrbWeaver

Active Developer
  • Posts

    8629
  • Joined

  • Last visited

  • Days Won

    65

Posts posted by OrbWeaver

  1. I notice that what Blender does is not lock or hide the mouse cursor, but allows it to move, then snaps it back to the other side of the window so you can drag infinitely in one direction. I.e. if you are dragging to the left, when the cursor reaches the left-hand window edge, it immediately re-appears at the right-hand window edge and continues moving to the left.

    I wonder if re-writing the code to use the Blender approach would solve the problem? Perhaps the back-end code can handle instantaneously changing the mouse pointer position more reliably than trying to lock it in place.

    • Like 1
  2. That bash script does not (as far as I can see) "extract all textures with specular maps". It extracts all materials to disk, then locates lines that include the word "specularmap" and blindly injects a couple of new material stages underneath. It does not identify the name of the material at all, and I'm not sure it will correctly handle materials where the specular map is part of a full stage block "{ blend specularmap ... }".

  3. Yes, if you change the internal path of a model you will need to update the map because the map only stores the model path as a string, it doesn't directly embed the model file.

    A .map file is just text so you could do this with search and replace in a text editor if you wanted.

  4. Integrating CC0 or public domain assets is trivial because those "licenses" impose no restrictions whatsoever, allowing you to integrate and re-license those assets under a more restrictive license like CC-BY-NC-SA. So there is no need to call out or identify CC0 or public domain assets, just integrate them with the rest of the mod and you're done.

    Including CC-BY-SA or other CC variants requires more care because those licenses don't allow re-licensing, meaning they have to be preserved as-is — i.e. you can't legally impose a "non-commercial only" restriction on an asset whose author chose to release it with a CC license which allows commercial use. If these assets were integrated they would need to be recorded somewhere along with their specific licenses.

  5. I upgraded from Windows 7 to Windows 10 for free. Does that not work anymore?

    If your objective is to keep running the same OS version for 15 years, I'm afraid you won't find Linux any better — as far as I know even Long Term Support releases don't go beyond 5 years unless you're a business who pays for extended support, and even that probably wouldn't give you more than 10 years.

    On the other hand, Linux upgrades are always free (assuming you're not using RHEL or another commercial distro), whereas Microsoft might require you to purchase an upgrade license.

    • Like 1
  6. You could try installing the Windows Subsystem for Linux and see if you can get a Linux build working on Windows. However I have no idea if WSL is comprehensive enough to allow you to build and run GUI apps using wxWidgets and OpenGL. I suspect it would be a fair amount of work to get the CMake build working, since it's never been tested on anything other than a regular Linux installation (AFAIK).

  7. Now I'm working with the FBX SDK and all the function arguments are pThis and pThat. At first I thought it meant "pointer" but then I see they're using the same prefix for bools and all other arguments. I guess it in fact means "parameter", because apparently I didn't know that the list of named arguments in parentheses after a function name are parameters, and I need all this visual clutter just to remind me of that fact.

    • Like 2
    • Haha 2
  8. Quote

    My complaint about that code is that all floating point numbers are snapped to integers with same tolerance.

    Indeed: there are already accuracy issues as soon as you use floats (especially single precision), and a hard-coded snap-to-integer behaviour seems to be reducing accuracy still further.

    Quote

    I do some mesh processing with halfedge data structures.
    When you have 10 local variables being halfedge handles, 5 local variables being face handles, and 5 local variables being vertex handles, it becomes much easier to understand what's going on if they start with "he" / "f" / "v" respectively.
    But this is very situational of course.

    That's actually a rare example of "App Hungarian notation" where the prefixes convey meaningful application-specific information, rather than just duplicating basic types like integer or float. It has been suggested that this was what HN was originally supposed to be, but everybody used it just to show primitive types which resulted in the whole convention becoming disliked.

    Quote

    Just starting pointers with 'p' and array-like stuff with 'a' is usually unnecessary, unless you have 3-4 levels (triple pointer or triple arrays), although in that case the code is smelly regardless or how you name variables 🤔

    Exactly, and it breaks down completely once you start using more complex types than primitive numbers. Knowing that something is a pointer is useless without knowing what it points to, knowing that something is an "obj" or a "struct" is similarly unhelpful, and once you start trying to expand the convention so that the prefixes can convey information about the actual object type, you will end up with complex multi-character encoded prefixes that nobody else will be able to understand.

    • Like 1
  9. On 2/9/2024 at 7:19 PM, Geep said:

    So: Do update the now-obsolete section of the user manual,

    I actually committed the relevant changes in source several months ago, but for some reason it looks like the generated HTML on the public user guide page hasn't update. I'll have to see if there is some problem with the CI script which is supposed to generate the web page from source control. I think the problem may be that the CI system is expecting the .html file to be included in source control directly (which it no longer is) rather than running AsciiDoctor itself.

    • Like 1
  10. I'm surprised to hear anyone is using Hungarian notation these days. It's one of the most derided, disliked, obsolete and useless naming conventions in programming. I don't think I've ever seen a modern programming guide or tutorial which advocates it (except perhaps in very limited situations like using "mSomething" to indicate a member variable).

    • Like 2
  11. I've very rarely seen setter methods which return values (unlike getters which obviously need to return the value they are "getting").

    What value should a setter return? The same value it was given as a parameter? That's entirely pointless because the calling code already has that value. It could return the previous value, but such a value isn't necessarily defined (and doesn't appear to be relevant in the case of writing something to a file).

    Sometimes setters return the object itself, so you can call them in a chain, e.g.

    myObject.setWidth(60).setHeight(20).setColour(RED);

    but it's not clear how that would work with writeFloat which isn't an object method to begin with.

    Quote

    all methods that return boolean always start with isSomethingSomething, etc.

    That's certainly common (and is a convention I use), but not universal. The C++ standard library doesn't use it, for example — to check if a vector is empty you call std::vector<T>::empty(), not isEmpty().

    • Like 2
  12. 16 hours ago, greebo said:

    Libxml2 is so widely used, that it's hard to imagine nobody else has this kind of trouble, so I'm still thinking it must be in the way we use it. Also, why just in Linux, it all doesn't make much sense.

    You're right, libxml2 can't be fundamentally broken since it is such a core dependency on Linux, plus the exact same XPath queries work perfectly fine even within our own XmlTest, so it must be something specific to how XML is being used within the registry setup.

    I found a couple of online sources which suggested that XPath queries might fail if the DTD doesn't validate, but we don't have any DTDs in our XML files and the XML_PARSE_DTDVALID option is not set by default in any case. Encodings are another possible culprit (especially since the problem seems to be OS-specific), but as far as I know encodings wouldn't change the parsing of characters like "[" or "@", and if the encoding was so fundamentally wrong that even regular 7-bit ASCII failed to parse, then how would "//game" ever be found? It seems that whatever the cause of the problem is, it is very well hidden within the API and would probably require building libxml2 from source and diving into it with the debugger to find out what is going wrong.

    16 hours ago, greebo said:

    Yes, I'd add them to the libs, and I'm probably going to set the PUGIXML_HEADER_ONLY flag, at least in Windows.

    Right, that sounds like the best approach. I'll set the HEADER_ONLY flag on Linux too then for consistency, and integrate it as a header-only dependency like libfmt.

    • Thanks 1
  13. Well I think I've gone as far as I can with this but libxml is simply not doing what it's supposed to. I can put code like this in the Game constructor:

            auto games = GlobalRegistry().findXPath("//game");
            assert(!games.empty()); // SUCCESS
            assert(games[0].getAttributeValue("name") == _name); // SUCCESS
            assert(!GlobalRegistry().findXPath("//game[@name='" + _name + "']").empty()); // FAIL

    The "//game" node is there, it has an attribute "name" with value "Doom 3 Demo" (or whatever the first game to be loaded is), but passing that exact name string back to an XPath query using the [@name='blah'] syntax just doesn't work, even though it used to work fine, and should work according to the XPath specification. I even dug down into the Document::findXPath function to see if something was being set in one of the C structures to indicate what is going wrong, but even though there is a lastError struct, it is empty. If there is any indication of the problem, it is buried deep within impenetrable and poorly-documented C structures.

    So, I am done with libxml and will look at C++ alternatives. 

    On 1/28/2024 at 5:03 AM, greebo said:

    I'd vote for pugixml, it seems to be still alive and has XPath support. It's what I've been using in the TDM game code too.

    If we were going to integrate this, what is the best way of doing so? I seem to recall from previous discussions you would prefer not to have git submodules linked into the repo, and it looks like pugixml is just one .cpp and one header file, so I guess the simplest approach is just to download the files and add them directly to the build in a suitable directory (like we do with the libfmt library).

  14. 9 hours ago, greebo said:

    Are you still investigating this? You seem to have gotten quite far already.

    Yes, I would like to find out what the issue is even if the ultimate decision is to use a different library in future.

    So far I have established that this line in Game.cpp is apparently working (no exception is thrown):

    		// Import the game file into the registry
    		GlobalRegistry().import(fullPath, "", Registry::treeStandard);

    but this (and any subsequent attempt to getKeyValue) then fails:

    		// Get the engine path
    		_enginePath = getKeyValue(enginePath);

    I can only think of two hypotheses:

    1. It's a timing issue or race condition: the import call is returning but something in libxml2 has not "finalised" the tree so it isn't ready to do XPath queries yet. I don't think there is any asynchronous or threaded code in the libxml2 API but who knows.
    2. There's something different about how XPath queries need to be formatted after merging. E.g. perhaps "//game" no longer works, and it has to have some other prefix.

    Further debugging is therefore needed.

    Edit: OK, there's definitely something weird going on with encodings. Adding a Registry::dump call into the Game constructor gives me output like this:

    output error : string is not in UTF-8
    output error : string is not in UTF-8
    eCrosshairs" ="mU" ���mU="SHIFT"/>< ="ToggleGrid" ="(&#xB3;R"/>< ="ToggleView" ="U" ���mU="SHIFT+CONTROL"/>< ="NextView" ="" ���mU="CONTROL"/>< ="ZoomIn" ="Delete"/>< ="ZoomOut" ="Insert"/>< ="CenterXYViews" ="" ���mU="CONTROL+SHIFT"/>< ="CenterXYView" ="" ���mU="CONTROL+ALT"/>< ="ToggleCubicClip" ="" ���mU="SHIFT"/>< ="ToggleCamera" ="U" ���mU="SHIFT+CONTROL"/>< ="TogTexLock" ="" ���mU="SHIFT"/>< ="DragVertices" ="U"/>< ="DragEdges" =""/>< ="DragFaces" =""/>< ="ToggleSelectionFocus" ="" ���mU="CONTROL"/>< ="ThickenPatchDialog" ="" ���mU="CONTROL"/>< ="ToggleShowAllLightRadii" ="" ���mU="CONTROL+SHIFT+ALT"/>< ="ToggleClipper" ="mU"/>< ="MouseTranslate" =""/>< ="MouseRotate" =""/>< ="MouseDrag" =""/>< ="NewOrthoView" ="" ���mU="CONTROL+ALT"/>< ="SetGrid0.125" ="" ���mU=""/>< ="SetGrid0.25" ="" ���mU=""/>< ="SetGrid0.5" ="" ���mU=""/>< ="SetGrid1" ="" ���mU=""/>< ="SetGrid2" ="U" ���mU=""/>< ="SetGrid4" ="" ���mU=""/>< ="SetGrid8" ="" ���mU=""/>< ="SetGrid16" ="" ���mU=""/>< ="SetGrid32" ="" ���mU=""/>< ="SetGrid64" ="" ���mU=""/>< ="SetGrid128" ="" ���mU=""/>< ="SetGrid256" ="" ���mU=""/>< ="ToggleTextureTool" ="" ���mU="CONTROL+ALT"/>< ="ToggleMainControl_TextureTool" ="" ���mU="CONTROL+ALT+SHIFT"/>< ="NormaliseTexture" ="" ���mU=""/>< ="TexToolGridUp" ="plus" ���mU="SHIFT"/>< ="TexToolGridDown" ="minus" ���mU="SHIFT"/>< ="TexToolMergeItems" ="" ���mU="Y&#x11D;mU"/>< ="GroupCycleBackward" ="ISO_Left_Tab" ���mU="SHIFT"/>< ="GroupCycleForward" ="" ���mU=""/>< ="RevertToWorldspawn" ="" ���mU="SHIFT"/>< ="SavePosition1" ="" ���mU="CONTROL+ALT"/>< ="SavePosition10" ="(&#xB3;R" ���mU="CONTROL+ALT"/>< ="SavePosition2" ="U" ���mU="CONTROL+ALT"/>< ="SavePosition3" ="" ���mU="CONTROL+ALT"/>< ="SavePosition4" ="" ���mU="CONTROL+ALT"/>< ="SavePosition5" ="" ���mU="CONTROL+ALT"/>< ="SavePosition6" ="" ���mU="CONTROL+ALT"/>< ="SavePosition7" ="" ���mU="CONTROL+ALT"/>< ="SavePosition8" ="" ���mU="CONTROL+ALT"/>< ="SavePosition9" ="" ���mU="CONTROL+ALT"/>< ="LoadPosition1" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition10" ="(&#xB3;R" ���mU="Y&#x11D;mU"/>< ="LoadPosition2" ="U" ���mU="Y&#x11D;mU"/>< ="LoadPosition3" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition4" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition5" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition6" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition7" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition8" ="" ���mU="Y&#x11D;mU"/>< ="LoadPosition9" ="" ���mU="Y&#x11D;mU"/>< ="ToggleOrthoBackgroundPanel" ="U" ���mU="Y&#x11D;mU"/>< ="ToggleRotationPivot" ="" ���mU="CONTROL"/>< ="ToggleAasVisualisationPanel" ="" ���mU="CONTROL+SHIFT"/>< ="GroupSelected" ="" ���mU="CONTROL+SHIFT"/>< ="UngroupSelected" ="" ���mU="CONTROL+SHIFT"/></mU><>
    

    Whereas with xmlParseFile there are no weird characters and the output just looks like properly formatted XML. I wonder if we have some nonstandard characters in our XML files for some reason.
     

    • Thanks 1
  15. I did some debugging in unit tests.

    The first problem is that although we have a basic XmlTest, it uses the full RadiantTest fixture which can only be constructed if the XML registry is working fine, so these basic XML tests are not runnable. I managed to fix that by changing the behaviour (on Linux only) to use TEST_BASE_PATH instead of _context.getTestResourcePath() to find the test resource files, so that RadiantTest is not required.

    This confirmed that the basic functionality of loading XML is working perfectly fine, even with the switch to xmlReadFile(). All of the XML tests pass, and I can load one of the game files in a unit test and examine its properties. So there is nothing fundamentally wrong with the XML structure being created by the new function call.

    The problem seems to be that within the Game class, any attempt to look up key values in the registry fail. Although each Game class is constructed successfully and imports its content, any searches for its own XPath root (e.g. "//game[@name='Doom 3 Demo']") return a list of 0 nodes, even though that exact XPath string can be used successfully within the basic XML test to find the <game> node which was loaded directly into an xml::Document. So there must be something going wrong with either when or how the .game file content is being merged into the global registry hierarchy.

  16. 20 minutes ago, 7318 said:

    I think this is the same error:

    I very much doubt it. You are building from source on Ubuntu whereas demagogue is reporting a problem with the released Windows build.

    I believe your error is the same one I encountered here: 

    This error is triggered by a change in Greebo's repo which I haven't yet merged, so if you build from my repo you should avoid this issue.

  17. For an as-yet unknown reason, this commit seems to break XML parsing on Linux:

    #6439: Use xmlReadFile instead of xmlParseFile which has been deprecated and removed. Privatise Document() constructor accepting an xmlDocPtr.

    As far as I can see, the commit is entirely correct. xmlParseFile is indeed deprecated, and the new usage of xmlReadFile matches what the libxml2 examples are suggesting. But the result is that although the xmlDoc* returned from the function is not NULL, nothing XML-related works, the entire registry system returns only empty values, and almost all of the tests are broken (because the main radiant core cannot be initialised without any registry values available). Changing back to xmlParseFile makes the problem go away but is an unsatisfactory solution because it specifically reintroduces a deprecated function call.

    I am not sure whether this is a bug in the specific version of libxml2 on my Ubuntu system, or something incorrect about how we are calling xmlReadFile (i.e. perhaps it requires an encoding or a particular non-default option to correctly process our XML files). Unfortunately like many of the core GNOME C libraries, the documentation is bare-bones and explains almost nothing (like what any of the parsing options actually mean), and I cannot see an obvious way to ask libxml2 to return meaningful errors, or to query exactly what might be wrong with a constructed xmlDoc* object.

    It makes me wonder if it would be better in the long term to ditch the reliance on libxml2 and instead use one of the light-weight C++ XML parsing libraries like RapidXml or pugixml instead. Not exactly a trivial change but might not be too cumbersome since the existing XML code is wrapped in our own xmlutil classes and not generally used directly by the rest of the codebase.

  18. 21 hours ago, nbohr1more said:

    The problem is that most TDM contributors would strongly object to allowing their work to be used by 3rd party commercial projects

    It's much simpler than that: TDM includes numerous 3rd-party assets which forbid commercial usage. Even if every single team member approved of a license change, it would still not be possible without identifying and removing all of those 3rd-party assets (and any derived assets based on them) and replacing them with free alternatives.

    21 hours ago, nbohr1more said:

    Debian and other similar distros need an easy way to allow users to install projects that are strictly non-commercial rather than forcing all open projects to permit 3rd parties to resell their work.

    They do. There are numerous easy ways to obtain and install non-FOSS projects on Debian. You can download and extract a tarball, run a dedicated installer, add a custom PPA from Ubuntu or some other source, install an AppImage, or install a FlatPak. You can even install non-FOSS projects directly from Debian using the non-free repository. At no point do they "force" anyone to do anything.

    What they don't allow is adding non-FOSS or otherwise restricted content into the main Debian repository, which is their right as a free software project.

  19. 1 hour ago, Fiver said:

    That's why I asked about the possibilities for option (2) as well: Debian may accept a "TDM-libre" version containing the game engine, a libre mission,

    I'm fairly sure they would accept this, if such a package could be produced.

    1 hour ago, Fiver said:

    and a built-in downloader functionality for the 2.3 GB of non-libre game data.

    They might accept this, but I'm not sure. If it's an installer that allows users to pick and choose optional packages, some of which may be non-free, this would probably be OK — in fact this is pretty much how the in-game mission downloader works. If it's a single installer that just "makes the rest of the game work", this might be seen as trying to evade the free software guidelines by indirectly packaging non-free content in an otherwise-free package. It might be necessary instead to package all of the non-free content in a separate DEB and put it into the non-free repository as an optional (Suggested/Recommended) extra.

    1 hour ago, Fiver said:

    Some software and games, e.g. SuperTuxKart, stores user data (addon tracks, screenshots, et.c.) into a sub-directory of the user's home directory ("~/.local/Share/supertuxkart"). Could TDM be modified to use a similar writable directory under the user's home where writing is necessary (missions, settings, savegames, et.c.), a directory that the system-wide installation will then use instead?

    Yes, this is the correct way to do things on Linux, and indeed how vanilla Doom 3 worked. In my opinion it would be much better if the Linux build of TDM worked like this, but I don't know how much work would be required to move away from the "everything in one writable directory" model that has been fairly solidly baked into the game implementation for many years.

×
×
  • Create New...