Subversion Repository Public Repository

Divide-Framework

This repository has no backups
This repository's network speed is throttled to 100KB/sec

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
161
162
163
164
165
166
167
#include "stdafx.h"

#include "Headers/Script.h"
#include "Headers/ScriptBindings.h"

#include "Core/Headers/Console.h"
#include "Core/Headers/StringHelper.h"
#include "Utility/Headers/Localization.h"
#include "Platform/File/Headers/FileManagement.h"
#include "Platform/File/Headers/FileUpdateMonitor.h"

namespace Divide {

namespace {
    UpdateListener s_fileWatcherListener([](const char* atomName, FileUpdateEvent evt) {
        Script::onScriptModify(atomName, evt);
    });
};

std::unique_ptr<FW::FileWatcher> Script::s_scriptFileWatcher;
Script::ScriptMap Script::s_scripts;
bool Script::s_scriptsReady = false;

Script::Script(const stringImpl& scriptPathOrCode, FileType fileType)
    : GUIDWrapper(),
      _script(nullptr),
      _scriptFileType(fileType)
{
    if (!scriptPathOrCode.empty()) {
        if (hasExtension(scriptPathOrCode, "chai")) {
            _scriptFile = splitPathToNameAndLocation(scriptPathOrCode);
        } else {
            _scriptSource = scriptPathOrCode;
        }
    }

    compile();
    bootstrap();
    extractAtoms();
    if (s_scriptsReady) {
        hashAlg::insert(s_scripts, std::make_pair(getGUID(), this));
    }
}

Script::~Script()
{
    if (s_scriptsReady) {
        ScriptMap::iterator it = s_scripts.find(getGUID());
        if (it != std::cend(s_scripts)) {
            s_scripts.erase(it);
        }
    }
}

void Script::idle() {
    if (!Config::Build::IS_SHIPPING_BUILD) {
        s_scriptFileWatcher->update();
    }
}

bool Script::onStartup() {
    s_scripts.reserve(100);
    s_scriptsReady = true;

    if (!Config::Build::IS_SHIPPING_BUILD) {
        s_scriptFileWatcher = std::make_unique<FW::FileWatcher>();
        s_fileWatcherListener.addIgnoredEndCharacter('~');
        s_fileWatcherListener.addIgnoredExtension("tmp");
        s_scriptFileWatcher->addWatch(Paths::Scripts::g_scriptsLocation, &s_fileWatcherListener);
        s_scriptFileWatcher->addWatch(Paths::Scripts::g_scriptsAtomsLocation, &s_fileWatcherListener);

        return s_scriptFileWatcher != nullptr;
    }

    return true;
}

bool Script::onShutdown() {
    s_scriptsReady = false;

    if (!Config::Build::IS_SHIPPING_BUILD) {
        s_scriptFileWatcher.reset();
        return s_scriptFileWatcher == nullptr;
    }

    s_scripts.clear();

    return true;
}

void Script::compile() {
    if (!_scriptFile._fileName.empty()) {
        readFile(_scriptFile._path + _scriptFile._fileName, _scriptSource, _scriptFileType);
    }
}

void Script::bootstrap() {
    const SysInfo& systemInfo = const_sysInfo();
    const stringImpl& path = systemInfo._pathAndFilename._path;

    std::vector<std::string> scriptpath{ path + Paths::Scripts::g_scriptsLocation,
                                         path + Paths::Scripts::g_scriptsAtomsLocation };

    _script = std::make_unique<chaiscript::ChaiScript>(create_chaiscript_stdlib(), scriptpath, scriptpath);
    _script->add(create_chaiscript_stl_extra());
    _script->add(chaiscript::fun(&Script::handleOutput), "handle_output");
}

void Script::preprocessIncludes(const stringImpl& source, I32 level /*= 0 */) {
    if (level > 32) {
        Console::errorfn(Locale::get(_ID("ERROR_SCRIPT_INCLUD_LIMIT")));
    }

    std::smatch matches;
    stringImpl line, include_file, include_string;

    istringstreamImpl input(source);
    while (std::getline(input, line)) {
        if (std::regex_search(line, matches, Paths::g_usePattern)) {
            include_file = Util::Trim(matches[1].str().c_str());
            _usedAtoms.push_back(include_file);

            // Open the atom file and add the code to the atom cache for future reference
            readFile(Paths::Scripts::g_scriptsLocation + include_file, include_string, FileType::TEXT);
            if (include_string.empty()) {
                readFile(Paths::Scripts::g_scriptsAtomsLocation + include_file, include_string, FileType::TEXT);
            }
            if (!include_string.empty()) {
                preprocessIncludes(include_string, level + 1);
            }
        }
    }
}

void Script::extractAtoms() {
    _usedAtoms.clear();
    if (!_scriptFile._fileName.empty()) {
        _usedAtoms.emplace_back(_scriptFile._fileName);
    }
    if (!_scriptSource.empty()) {
        preprocessIncludes(_scriptSource, 0);
    }
}

void Script::handleOutput(const std::string &msg) {
    Console::printfn(Locale::get(_ID("CONSOLE_SCRIPT_OUTPUT")), msg.c_str());
}

void Script::onScriptModify(const char* script, FileUpdateEvent& evt) {
    vectorImpl<Script*> scriptsToReload;

    for (ScriptMap::value_type it : s_scripts) {
        for (const stringImpl& atom : it.second->_usedAtoms) {
            if (Util::CompareIgnoreCase(atom, script)) {
                scriptsToReload.push_back(it.second);
                break;
            }
        }
    }

    for (Script* it : scriptsToReload) {
        it->compile();
        it->extractAtoms();
    }
}

}; //namespace Divide

Commits for Divide-Framework/trunk/Source Code/Scripting/Script.cpp

Diff revisions: vs.
Revision Author Commited Message
893 Diff Diff IonutCava picture IonutCava Sun 18 Jun, 2017 17:33:07 +0000

[Ionut]
- Initial implementation of a PipelineStateObject (holds shader program, rasterizer state, etc)
- Rework PCH implementation a bit because VS2017 no longer has a /ZM option

890 Diff Diff IonutCava picture IonutCava Sun 14 May, 2017 20:54:59 +0000

[Ionut]
- Add pre-compiled header support
- Initial code for per-stage tessellation computation

846 Diff Diff IonutCava picture IonutCava Fri 03 Feb, 2017 22:41:05 +0000

[IonutCava]
- More scripting work

845 Diff Diff IonutCava picture IonutCava Fri 03 Feb, 2017 14:36:26 +0000

[IonutCava]
- Hot reloading system cleanup
- More script system bug fixes

844 Diff Diff IonutCava picture IonutCava Thu 02 Feb, 2017 21:49:28 +0000

[IonutCava]
- More scripting prep work and experiments

843 Diff Diff IonutCava picture IonutCava Thu 02 Feb, 2017 17:03:33 +0000

[IonutCava]
- Add more matrix unit tests and fix discovered bugs
- Fix compile warning in ShaderProgram
- Rework script function binding and add unit test for this usecase

842 IonutCava picture IonutCava Wed 01 Feb, 2017 17:25:15 +0000

[IonutCava]
- Start to implement scripting support via ChaiScript: http://chaiscript.com/
- Cleanup DELEGATE_CBK alias