File: Doom3ModelDef.h

package info (click to toggle)
darkradiant 3.9.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 41,080 kB
  • sloc: cpp: 264,743; ansic: 10,659; python: 1,852; xml: 1,650; sh: 92; makefile: 21
file content (160 lines) | stat: -rw-r--r-- 4,047 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once

#include "ieclass.h"
#include "parser/DefTokeniser.h"
#include "decl/DeclarationBase.h"

namespace eclass
{

class Doom3ModelDef :
    public decl::DeclarationBase<IModelDef>
{
private:
    Ptr _parent;

    std::string _mesh;
    std::string _skin;
    Anims _anims;

public:
    using Ptr = std::shared_ptr<Doom3ModelDef>;

	Doom3ModelDef(const std::string& name) :
        DeclarationBase<IModelDef>(decl::Type::ModelDef, name)
	{}

    const std::string& getMesh() override
	{
        ensureParsed();
        return _mesh;
	}

    const IModelDef::Ptr& getParent() override
	{
        ensureParsed();
        return _parent;
	}

    const std::string& getSkin() override
	{
        ensureParsed();
        return _skin;
	}

    std::string getAnim(const std::string& animKey) override
	{
        ensureParsed();

        auto existing = _anims.find(animKey);
        return existing != _anims.end() ? existing->second : std::string();
	}

    const Anims& getAnims() override
	{
        ensureParsed();
        return _anims;
	}

protected:
    void onBeginParsing() override
    {
        clearContents();
    }

    // Reads the data from the given tokens into the member variables
    void parseFromTokens(parser::DefTokeniser& tokeniser) override
    {
        // State enum
        enum
        {
            NONE,   // usual state
            ANIM    // parsed anim, may get a { ... } block with further info
        } state = NONE;

        while (tokeniser.hasMoreTokens())
        {
            auto parameter = tokeniser.nextToken();

            if (parameter == "inherit")
            {
                inheritFrom(tokeniser.nextToken());
            }
            else if (parameter == "mesh")
            {
                _mesh = tokeniser.nextToken();
            }
            else if (parameter == "skin")
            {
                _skin = tokeniser.nextToken();
            }
            else if (parameter == "offset")
            {
                tokeniser.skipTokens(5);
            }
            else if (parameter == "channel")
            {
                // SYNTAX: "channel" <name> "(" <blah> [ <blah> ... ] ")"
                tokeniser.skipTokens(2);
                while (tokeniser.nextToken() != ")") continue;
            }
            else if (parameter == "anim")
            {
                // SYNTAX: "anim" <name> <md5file> [ "{" <blah> [ <blah> ... ] "}" ]
                auto animName = tokeniser.nextToken();
                auto file = tokeniser.nextToken();

                // Overwrite any existing animation with the same key
                _anims[animName] = file;
                state = ANIM; // check for the braces on the next iteration
            }
            else if (state == ANIM && parameter == "{")
            {
                // anim braces
                while (tokeniser.nextToken() != "}") continue;
                state = NONE;
            }
        }
    }

private:
    void clearContents()
    {
        // Don't clear the name
        _mesh.clear();
        _skin.clear();
        _parent.reset();
        _anims.clear();
    }

    void inheritFrom(const std::string& parentName)
    {
        auto parent = GlobalEntityClassManager().findModel(parentName);

        if (!parent)
        {
            rWarning() << "ModelDef " << getDeclName() << " inherits from unknown parent: " << parentName << std::endl;
            return;
        }

        _parent = parent;

        // greebo: Only inherit the "mesh" of the parent if the current declaration doesn't have one
        if (_mesh.empty())
        {
            _mesh = parent->getMesh();
        }

        // Only inherit the "skin" of the parent if the current declaration doesn't have one
        if (_skin.empty())
        {
            _skin = parent->getSkin();
        }

        // Append all inherited animations, if missing on the child
        const auto& parentAnims = parent->getAnims();
        _anims.insert(parentAnims.begin(), parentAnims.end());
    }
};

} // namespace