diff -Nru doomsday-stable-2.0.3.2464+xenial/appveyor.yml doomsday-stable-2.1.0.2900+xenial/appveyor.yml --- doomsday-stable-2.0.3.2464+xenial/appveyor.yml 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/appveyor.yml 2018-12-11 07:08:16.000000000 +0000 @@ -1,7 +1,7 @@ # Build configuration for AppVeyor CI Windows builds configuration: Release platform: Win32 -os: Visual Studio 2015 +os: Visual Studio 2017 environment: DENG_DEPEND_PATH: c:\projects\doomsday-engine\deps before_build: @@ -10,7 +10,7 @@ - 7z x deps.7z - md build-ci - cd build-ci - - cmake -G "Visual Studio 14 2015" -DQMAKE=C:\Qt\5.6\msvc2015\bin\qmake.exe -DFMOD_DIR="c:\projects\doomsday-engine\deps\FMOD Ex" -DDENG_ENABLE_TESTS=ON -DDENG_ENABLE_TURBO=ON ..\doomsday + - cmake -G "Visual Studio 15 2017" -DQMAKE=C:\Qt\5.6\msvc2015\bin\qmake.exe -DDENG_ENABLE_TESTS=ON -DDENG_ENABLE_TURBO=ON ..\doomsday build: parallel: true verbosity: minimal diff -Nru doomsday-stable-2.0.3.2464+xenial/debian/changelog doomsday-stable-2.1.0.2900+xenial/debian/changelog --- doomsday-stable-2.0.3.2464+xenial/debian/changelog 2017-10-01 00:40:36.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/debian/changelog 2018-12-11 07:08:12.000000000 +0000 @@ -1,6 +1,6 @@ -doomsday-stable (2.0.3.2464+xenial) xenial; urgency=medium +doomsday-stable (2.1.0.2900+xenial) xenial; urgency=medium - * New release: Stable build 2464. - * Sort input file list + * New release: Stable build 2900. + * Changed release type to "Stable" - -- Jaakko Keränen (skyjake) Sun, 01 Oct 2017 03:40:08 +0300 + -- Jaakko Keränen (skyjake) Tue, 11 Dec 2018 09:08:12 +0200 diff -Nru doomsday-stable-2.0.3.2464+xenial/debian/compat doomsday-stable-2.1.0.2900+xenial/debian/compat --- doomsday-stable-2.0.3.2464+xenial/debian/compat 2017-10-01 00:40:36.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/debian/compat 2018-12-11 07:08:12.000000000 +0000 @@ -1 +1 @@ -9 +10 diff -Nru doomsday-stable-2.0.3.2464+xenial/debian/copyright doomsday-stable-2.1.0.2900+xenial/debian/copyright --- doomsday-stable-2.0.3.2464+xenial/debian/copyright 2017-10-01 00:40:36.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/debian/copyright 2018-12-11 07:08:12.000000000 +0000 @@ -8,7 +8,7 @@ License: GPL-2.0+ Files: debian/* -Copyright: 2017 Jaakko Keränen (skyjake) +Copyright: 2018 Jaakko Keränen (skyjake) License: GPL-2.0+ License: GPL-2.0+ diff -Nru doomsday-stable-2.0.3.2464+xenial/debian/rules doomsday-stable-2.1.0.2900+xenial/debian/rules --- doomsday-stable-2.0.3.2464+xenial/debian/rules 2017-10-01 00:40:36.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/debian/rules 2018-12-11 07:08:12.000000000 +0000 @@ -8,7 +8,7 @@ cd builddir && QTCHOOSER_RUNTOOL=qmake QT_SELECT=5 cmake \ -DQMAKE=qtchooser \ -DCMAKE_BUILD_TYPE=Release \ - -DDENG_BUILD=2464 \ + -DDENG_BUILD=2900 \ -DCMAKE_CXX_FLAGS=-std=c++11 \ -DDENG_ENABLE_COTIRE=OFF \ ../doomsday diff -Nru doomsday-stable-2.0.3.2464+xenial/distrib/autobuild.py doomsday-stable-2.1.0.2900+xenial/distrib/autobuild.py --- doomsday-stable-2.0.3.2464+xenial/distrib/autobuild.py 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/distrib/autobuild.py 2018-12-11 07:08:16.000000000 +0000 @@ -210,7 +210,7 @@ # Check distribution. system_command("lsb_release -a | perl -n -e 'm/Codename:\s(.+)/ && print $1' > /tmp/distroname") hostDistro = file('/tmp/distroname', 'rt').read() - distros = ['xenial', 'zesty'] + distros = ['xenial', 'bionic'] for distro in distros: os.chdir(os.path.join(builder.config.DISTRIB_DIR)) @@ -292,137 +292,139 @@ os.system("~/Scripts/mirror-tree.py %s %s" % (aptDir, os.path.join(builder.config.EVENT_DIR, 'apt'))) -def write_html_page(outPath, title, content): - f = file(outPath, 'wt') - print >> f, "" - print >> f, '' - print >> f, "%s" % title - print >> f, "" - print >> f, "" - print >> f, "
" - print >> f, "

%s

" % title - print >> f, content - print >> f, "
" - print >> f, "" - - -def write_report_html(tag): - ev = builder.Event(tag) - write_html_page(ev.file_path('index.html'), 'Build %i' % ev.number(), - ev.html_description(False)) +# def write_html_page(outPath, title, content): +# f = file(outPath, 'wt') +# print >> f, "" +# print >> f, '' +# print >> f, "%s" % title +# print >> f, "" +# print >> f, "" +# print >> f, "
" +# print >> f, "

%s

" % title +# print >> f, content +# print >> f, "
" +# print >> f, "" +# +# +# def write_report_html(tag): +# ev = builder.Event(tag) +# write_html_page(ev.file_path('index.html'), 'Build %i' % ev.number(), +# ev.html_description(False)) def update_feed(): """Generate events.rss into the event directory.""" - - feedName = os.path.join(builder.config.EVENT_DIR, "events.rss") - print "Updating feed in %s..." % feedName - - out = file(feedName, 'wt') - print >> out, '' - print >> out, '' - print >> out, '' - - print >> out, 'Doomsday Engine Builds' - print >> out, 'http://dengine.net/' - print >> out, '' % builder.config.BUILD_URI - print >> out, 'Automated binary builds of the Doomsday Engine.' - print >> out, 'en-us' - print >> out, 'skyjake@users.sourceforge.net (Jaakko Keränen)' - print >> out, '%s' % time.strftime(builder.config.RFC_TIME, - time.gmtime(builder.find_newest_event()['time'])) - print >> out, 'autobuild.py' - print >> out, '180' # 3 hours - - allEvents = [] - - for timestamp, ev in builder.events_by_time(): - allEvents.append((timestamp, ev)) - print >> out, '' - print >> out, 'Build %i' % ev.number() - print >> out, '%s/%s/' % ("http://files.dengine.net/builds", ev.name) - print >> out, 'skyjake@users.sourceforge.net (skyjake)' - print >> out, '%s' % time.strftime(builder.config.RFC_TIME, time.gmtime(timestamp)) - print >> out, '%s' % ev.text_summary() - print >> out, '%s' % ev.html_description() - print >> out, '%s' % ev.tag() - print >> out, '' - - write_report_html(ev.tag()) - - # Close. - print >> out, '' - print >> out, '' - - # Write a index page for all the builds. - versions = {} - text = '' - text += '

Latest Builds

' - text += '
' - for timestamp, ev in allEvents: - eventVersion = '.'.join(ev.version().split('.')[:2]) - if eventVersion in versions: - versions[eventVersion].append(ev) - else: - versions[eventVersion] = [ev] - text += '' % (ev.release_type(), ev.number(), ev.number(), - time.strftime('%b %d', time.gmtime(timestamp)), ev.version()) - text += '
' - - text += '

Versions

' - for version in versions.keys(): - text += '

%s

' % version - text += '
' - for ev in versions[version]: - text += '' % (ev.release_type(), ev.number(), ev.number(), - time.strftime('%b %d', time.gmtime(ev.timestamp())), ev.version()) - text += '
' - - write_html_page(os.path.join(builder.config.EVENT_DIR, "index.html"), - 'Doomsday Autobuilder', text) + pass +# feedName = os.path.join(builder.config.EVENT_DIR, "events.rss") +# print "Updating feed in %s..." % feedName +# +# out = file(feedName, 'wt') +# print >> out, '' +# print >> out, '' +# print >> out, '' +# +# print >> out, 'Doomsday Engine Builds' +# print >> out, 'http://dengine.net/' +# print >> out, '' % builder.config.BUILD_URI +# print >> out, 'Automated binary builds of the Doomsday Engine.' +# print >> out, 'en-us' +# print >> out, 'skyjake@users.sourceforge.net (Jaakko Keränen)' +# print >> out, '%s' % time.strftime(builder.config.RFC_TIME, +# time.gmtime(builder.find_newest_event()['time'])) +# print >> out, 'autobuild.py' +# print >> out, '180' # 3 hours +# +# allEvents = [] +# +# for timestamp, ev in builder.events_by_time(): +# allEvents.append((timestamp, ev)) +# print >> out, '' +# print >> out, 'Build %i' % ev.number() +# print >> out, '%s/%s/' % ("http://files.dengine.net/builds", ev.name) +# print >> out, 'skyjake@users.sourceforge.net (skyjake)' +# print >> out, '%s' % time.strftime(builder.config.RFC_TIME, time.gmtime(timestamp)) +# print >> out, '%s' % ev.text_summary() +# print >> out, '%s' % ev.html_description() +# print >> out, '%s' % ev.tag() +# print >> out, '' +# +# write_report_html(ev.tag()) +# +# # Close. +# print >> out, '' +# print >> out, '' +# +# # Write a index page for all the builds. +# versions = {} +# text = '' +# text += '

Latest Builds

' +# text += '
' +# for timestamp, ev in allEvents: +# eventVersion = '.'.join(ev.version().split('.')[:2]) +# if eventVersion in versions: +# versions[eventVersion].append(ev) +# else: +# versions[eventVersion] = [ev] +# text += '' % (ev.release_type(), ev.number(), ev.number(), +# time.strftime('%b %d', time.gmtime(timestamp)), ev.version()) +# text += '
' +# +# text += '

Versions

' +# for version in versions.keys(): +# text += '

%s

' % version +# text += '
' +# for ev in versions[version]: +# text += '' % (ev.release_type(), ev.number(), ev.number(), +# time.strftime('%b %d', time.gmtime(ev.timestamp())), ev.version()) +# text += '
' +# +# write_html_page(os.path.join(builder.config.EVENT_DIR, "index.html"), +# 'Doomsday Autobuilder', text) def update_xml_feed(): - """Generate events.xml into the event directory.""" - - feedName = os.path.join(builder.config.EVENT_DIR, "events.xml") - print "Updating XML feed in %s..." % feedName - - out = file(feedName, 'wt') - print >> out, '' - print >> out, '' - for timestamp, ev in builder.events_by_time(): - print >> out, ev.xml_description() - print >> out, '' - - -def purge_apt_repository(atLeastSeconds): - for d in ['i386', 'amd64']: - binDir = os.path.join(builder.config.APT_REPO_DIR, builder.config.APT_DIST + '/main/binary-') + d - print 'Pruning binary apt directory', binDir - # Find the old files. - for fn in os.listdir(binDir): - if fn[-4:] != '.deb': continue - debPath = os.path.join(binDir, fn) - ct = os.stat(debPath).st_ctime - if time.time() - ct >= atLeastSeconds: - print 'Deleting', debPath - os.remove(debPath) + pass +# """Generate events.xml into the event directory.""" +# +# feedName = os.path.join(builder.config.EVENT_DIR, "events.xml") +# print "Updating XML feed in %s..." % feedName +# +# out = file(feedName, 'wt') +# print >> out, '' +# print >> out, '' +# for timestamp, ev in builder.events_by_time(): +# print >> out, ev.xml_description() +# print >> out, '' + + +# def purge_apt_repository(atLeastSeconds): +# for d in ['i386', 'amd64']: +# binDir = os.path.join(builder.config.APT_REPO_DIR, builder.config.APT_DIST + '/main/binary-') + d +# print 'Pruning binary apt directory', binDir +# # Find the old files. +# for fn in os.listdir(binDir): +# if fn[-4:] != '.deb': continue +# debPath = os.path.join(binDir, fn) +# ct = os.stat(debPath).st_ctime +# if time.time() - ct >= atLeastSeconds: +# print 'Deleting', debPath +# os.remove(debPath) def purge_obsolete(): - """Purge old builds from the event directory (old > 12 weeks).""" - threshold = 3600 * 24 * 7 * 12 + """Purge old builds from the event directory (old > 4 weeks).""" + threshold = 3600 * 24 * 7 * 4 - # Also purge the apt repository if one has been specified. - if builder.config.APT_REPO_DIR: - purge_apt_repository(threshold) + # We'll keep a small number of events unpurgable. + totalCount = len(builder.find_old_events(0)) # Purge the old events. - print 'Deleting build events older than 12 weeks...' + print 'Deleting build events older than 4 weeks...' for ev in builder.find_old_events(threshold): - print ev.tag() - shutil.rmtree(ev.path()) + if totalCount > 5: + print ev.tag() + shutil.rmtree(ev.path()) + totalCount -= 1 print 'Purge done.' @@ -461,29 +463,29 @@ system_command('doxygen api.doxy >/dev/null 2>../../doxyissues-api.txt') system_command('wc -l ../../doxyissues-api.txt') - print >> sys.stderr, "\nInternal Win32 docs..." - os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/client')) - system_command('doxygen client-win32.doxy >/dev/null 2>../../doxyissues-win32.txt') - system_command('wc -l ../../doxyissues-win32.txt') - - print >> sys.stderr, "\nInternal Mac/Unix docs..." - system_command('doxygen client-mac.doxy >/dev/null 2>../../doxyissues-mac.txt') - system_command('wc -l ../../doxyissues-mac.txt') - - print >> sys.stderr, "\nDoom plugin docs..." - os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/doom')) - system_command('doxygen doom.doxy >/dev/null 2>../../../doxyissues-doom.txt') - system_command('wc -l ../../../doxyissues-doom.txt') - - print >> sys.stderr, "\nHeretic plugin docs..." - os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/heretic')) - system_command('doxygen heretic.doxy >/dev/null 2>../../../doxyissues-heretic.txt') - system_command('wc -l ../../../doxyissues-heretic.txt') - - print >> sys.stderr, "\nHexen plugin docs..." - os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/hexen')) - system_command('doxygen hexen.doxy >/dev/null 2>../../../doxyissues-hexen.txt') - system_command('wc -l ../../../doxyissues-hexen.txt') + # print >> sys.stderr, "\nInternal Win32 docs..." + # os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/client')) + # system_command('doxygen client-win32.doxy >/dev/null 2>../../doxyissues-win32.txt') + # system_command('wc -l ../../doxyissues-win32.txt') + # + # print >> sys.stderr, "\nInternal Mac/Unix docs..." + # system_command('doxygen client-mac.doxy >/dev/null 2>../../doxyissues-mac.txt') + # system_command('wc -l ../../doxyissues-mac.txt') + # + # print >> sys.stderr, "\nDoom plugin docs..." + # os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/doom')) + # system_command('doxygen doom.doxy >/dev/null 2>../../../doxyissues-doom.txt') + # system_command('wc -l ../../../doxyissues-doom.txt') + # + # print >> sys.stderr, "\nHeretic plugin docs..." + # os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/heretic')) + # system_command('doxygen heretic.doxy >/dev/null 2>../../../doxyissues-heretic.txt') + # system_command('wc -l ../../../doxyissues-heretic.txt') + # + # print >> sys.stderr, "\nHexen plugin docs..." + # os.chdir(os.path.join(builder.config.DISTRIB_DIR, '../doomsday/apps/plugins/hexen')) + # system_command('doxygen hexen.doxy >/dev/null 2>../../../doxyissues-hexen.txt') + # system_command('wc -l ../../../doxyissues-hexen.txt') def generate_wiki(): diff -Nru doomsday-stable-2.0.3.2464+xenial/distrib/builder/event.py doomsday-stable-2.1.0.2900+xenial/distrib/builder/event.py --- doomsday-stable-2.0.3.2464+xenial/distrib/builder/event.py 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/distrib/builder/event.py 2018-12-11 07:08:16.000000000 +0000 @@ -417,64 +417,64 @@ else: return "http://files.dengine.net/builds/" + self.name - def xml_description(self): - msg = '' - msg += '%i' % self.number() - msg += '%s' % self.text_timestamp() - msg += '%s' % config.BUILD_AUTHOR_NAME - msg += '%s' % config.BUILD_AUTHOR_EMAIL - msg += '%s' % self.release_type() - files = self.list_package_files() - msg += '%i' % len(files) - - # These logs were already linked to. - includedLogs = [] - - distribVersion = None - - # Packages. - for fn in files: - msg += '' % self.package_type(fn) - msg += '%s' % self.packageName[self.package_from_filename(fn)] - msg += '%s' % self.version_from_filename(fn) - msg += '%s' % self.platId[self.os_from_filename(fn)[2]] - msg += '%s' % self.download_uri(fn) - msg += '%s' % self.download_fallback_uri(fn) - logName = self.compressed_log_filename(fn) - if os.path.exists(self.file_path(logName)): - msg += self.xml_log(logName) - includedLogs.append(logName) - msg += '' - - if distribVersion is None: - distribVersion = self.version_from_filename(fn) - - # Any other logs we might want to include? - for osName, osExt, osIdent in self.oses: - for pkg in self.packages: - logName = log_filename(pkg, osIdent) - if os.path.exists(self.file_path(logName)) and logName not in includedLogs: - # Add an entry for this. - msg += '' % self.package_type(logName) - msg += '%s' % self.packageName[pkg] - if self.version_from_filename(logName): - msg += '%s' % self.version_from_filename(logName) - if distribVersion is None: - distribVersion = self.version_from_filename(logName) - msg += '%s' % self.platId[osIdent] - msg += self.xml_log(logName) - msg += '' - - if distribVersion: - msg += '%s' % self.release_notes_uri(distribVersion) - msg += '%s' % self.changelog_uri(distribVersion) - - # Commits. - chgFn = self.file_path('changes.xml') - if os.path.exists(chgFn): - msg += file(chgFn, 'rt').read() - - return msg + '' + # def xml_description(self): + # msg = '' + # msg += '%i' % self.number() + # msg += '%s' % self.text_timestamp() + # msg += '%s' % config.BUILD_AUTHOR_NAME + # msg += '%s' % config.BUILD_AUTHOR_EMAIL + # msg += '%s' % self.release_type() + # files = self.list_package_files() + # msg += '%i' % len(files) + # + # # These logs were already linked to. + # includedLogs = [] + # + # distribVersion = None + # + # # Packages. + # for fn in files: + # msg += '' % self.package_type(fn) + # msg += '%s' % self.packageName[self.package_from_filename(fn)] + # msg += '%s' % self.version_from_filename(fn) + # msg += '%s' % self.platId[self.os_from_filename(fn)[2]] + # msg += '%s' % self.download_uri(fn) + # msg += '%s' % self.download_fallback_uri(fn) + # logName = self.compressed_log_filename(fn) + # if os.path.exists(self.file_path(logName)): + # msg += self.xml_log(logName) + # includedLogs.append(logName) + # msg += '' + # + # if distribVersion is None: + # distribVersion = self.version_from_filename(fn) + # + # # Any other logs we might want to include? + # for osName, osExt, osIdent in self.oses: + # for pkg in self.packages: + # logName = log_filename(pkg, osIdent) + # if os.path.exists(self.file_path(logName)) and logName not in includedLogs: + # # Add an entry for this. + # msg += '' % self.package_type(logName) + # msg += '%s' % self.packageName[pkg] + # if self.version_from_filename(logName): + # msg += '%s' % self.version_from_filename(logName) + # if distribVersion is None: + # distribVersion = self.version_from_filename(logName) + # msg += '%s' % self.platId[osIdent] + # msg += self.xml_log(logName) + # msg += '' + # + # if distribVersion: + # msg += '%s' % self.release_notes_uri(distribVersion) + # msg += '%s' % self.changelog_uri(distribVersion) + # + # # Commits. + # chgFn = self.file_path('changes.xml') + # if os.path.exists(chgFn): + # msg += file(chgFn, 'rt').read() + # + # return msg + '' def find_newest_event(): diff -Nru doomsday-stable-2.0.3.2464+xenial/distrib/platform_release.py doomsday-stable-2.1.0.2900+xenial/distrib/platform_release.py --- doomsday-stable-2.0.3.2464+xenial/distrib/platform_release.py 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/distrib/platform_release.py 2018-12-11 07:08:16.000000000 +0000 @@ -107,7 +107,11 @@ def mac_os_8_or_later(): - return mac_os_version() in ['10.8', '10.9', '10.10', '10.11', '10.12'] + try: + v = mac_os_version().split('.') + return int(v[1]) >= 8 + except: + return False def mac_target_ext(): diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_base.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_base.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_base.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_base.h 2018-12-11 07:08:17.000000000 +0000 @@ -43,7 +43,7 @@ /// @} // The Base API. -DENG_API_TYPEDEF(Base) // v2 +DENG_API_TYPEDEF(Base) { de_api_t api; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_fontrender.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_fontrender.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_fontrender.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_fontrender.h 2018-12-11 07:08:17.000000000 +0000 @@ -192,7 +192,7 @@ * @param alignFlags @ref alignmentFlags * @param _textFlags @ref drawTextFlags */ - void (*DrawText3)(const char* text, const Point2Raw* _origin, int alignFlags, short _textFlags); + void (*DrawText3)(const char* text, const Point2Raw* _origin, int alignFlags, uint16_t _textFlags); void (*DrawTextXY3)(const char* text, int x, int y, int alignFlags, short flags); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_gl.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_gl.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_gl.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_gl.h 2018-12-11 07:08:17.000000000 +0000 @@ -47,9 +47,15 @@ DGL_CURRENT_COLOR_A, DGL_CURRENT_COLOR_RGBA, - // List modes - DGL_COMPILE = 0x3000, - DGL_COMPILE_AND_EXECUTE, + DGL_FOG_MODE, + DGL_FOG_START, + DGL_FOG_END, + DGL_FOG_DENSITY, + DGL_FOG_COLOR, + + DGL_LINE_WIDTH, + DGL_POINT_SIZE, + DGL_ALPHA_LIMIT, // Matrices DGL_MODELVIEW = 0x4000, @@ -60,10 +66,16 @@ DGL_TEXTURE_2D = 0x5000, DGL_SCISSOR_TEST, DGL_FOG, - DGL_MODULATE_ADD_COMBINE, DGL_MODULATE_TEXTURE, DGL_LINE_SMOOTH, DGL_POINT_SMOOTH, + DGL_BLEND, + DGL_DEPTH_TEST, + DGL_DEPTH_WRITE, + DGL_ALPHA_TEST, + + DGL_TEXTURE0 = 0x5100, + DGL_TEXTURE1, // Blending functions DGL_ZERO = 0x6000, @@ -76,11 +88,20 @@ DGL_ONE_MINUS_SRC_COLOR, DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA, - DGL_UNUSED1, // DGL_SRC_ALPHA_SATURATE DGL_ADD, DGL_SUBTRACT, DGL_REVERSE_SUBTRACT, + // Comparison functions + DGL_NEVER = 0x7000, + DGL_ALWAYS, + DGL_EQUAL, + DGL_NOT_EQUAL, + DGL_LESS, + DGL_GREATER, + DGL_LEQUAL, + DGL_GEQUAL, + // Miscellaneous DGL_MIN_FILTER = 0xF000, DGL_MAG_FILTER, @@ -94,17 +115,21 @@ DGL_CLAMP, DGL_CLAMP_TO_EDGE, DGL_REPEAT, - DGL_LINE_WIDTH, - DGL_POINT_SIZE + DGL_EXP, + DGL_EXP2, + DGL_NONE, + DGL_BACK, + DGL_FRONT, + DGL_FLUSH_BACKTRACE, }; // Types. typedef unsigned char DGLubyte; -typedef int DGLint; -typedef unsigned int DGLuint; -typedef int DGLsizei; -typedef double DGLdouble; -typedef unsigned int DGLenum; +typedef int DGLint; +typedef unsigned int DGLuint; +typedef int DGLsizei; +typedef double DGLdouble; +typedef unsigned int DGLenum; /// Texture formats. typedef enum dgltexformat_e { @@ -118,13 +143,15 @@ /// Primitive types. typedef enum dglprimtype_e { + DGL_NO_PRIMITIVE, DGL_LINES, + DGL_LINE_STRIP, + DGL_LINE_LOOP, DGL_TRIANGLES, DGL_TRIANGLE_FAN, DGL_TRIANGLE_STRIP, DGL_QUADS, - DGL_QUAD_STRIP, - DGL_POINTS + DGL_POINTS, } dglprimtype_t; #define DDNUM_BLENDMODES 9 @@ -255,10 +282,11 @@ void (*SetScissor)(RectRaw const *rect); void (*SetScissor2)(int x, int y, int width, int height); - void (*MatrixMode)(int mode); + void (*MatrixMode)(DGLenum mode); void (*PushMatrix)(void); void (*PopMatrix)(void); void (*LoadIdentity)(void); + void (*LoadMatrix)(float const *matrix4x4); void (*Translatef)(float x, float y, float z); void (*Rotatef)(float angle, float x, float y, float z); @@ -266,10 +294,6 @@ void (*Begin)(dglprimtype_t type); void (*End)(void); - dd_bool (*NewList)(DGLuint list, int mode); - DGLuint (*EndList)(void); - void (*CallList)(DGLuint list); - void (*DeleteLists)(DGLuint list, int range); void (*SetNoMaterial)(void); void (*SetMaterialUI)(world_Material *mat, DGLint wrapS, DGLint wrapT); @@ -292,7 +316,7 @@ void (*Color4fv)(const float* vec); void (*TexCoord2f)(byte target, float s, float t); - void (*TexCoord2fv)(byte target, float* vec); + void (*TexCoord2fv)(byte target, float const *vec); void (*Vertex2f)(float x, float y); void (*Vertex2fv)(const float* vec); @@ -330,9 +354,15 @@ * be created dynamically. */ int (*Bind)(DGLuint texture); + void (*DeleteTextures)(int num, const DGLuint* names); + void (*Fogi)(DGLenum property, int value); + void (*Fogf)(DGLenum property, float value); + void (*Fogfv)(DGLenum property, float const *values); + void (*UseFog)(int yes); + void (*SetFilter)(dd_bool enable); void (*SetFilterColor)(float r, float g, float b, float a); void (*ConfigureBorderedProjection2)(dgl_borderedprojectionstate_t* bp, int flags, int width, int height, int availWidth, int availHeight, scalemode_t overrideMode, float stretchEpsilon); @@ -365,15 +395,12 @@ #define DGL_PushMatrix _api_GL.PushMatrix #define DGL_PopMatrix _api_GL.PopMatrix #define DGL_LoadIdentity _api_GL.LoadIdentity +#define DGL_LoadMatrix _api_GL.LoadMatrix #define DGL_Translatef _api_GL.Translatef #define DGL_Rotatef _api_GL.Rotatef #define DGL_Scalef _api_GL.Scalef #define DGL_Begin _api_GL.Begin #define DGL_End _api_GL.End -#define DGL_NewList _api_GL.NewList -#define DGL_EndList _api_GL.EndList -#define DGL_CallList _api_GL.CallList -#define DGL_DeleteLists _api_GL.DeleteLists #define DGL_SetNoMaterial _api_GL.SetNoMaterial #define DGL_SetMaterialUI _api_GL.SetMaterialUI #define DGL_SetPatch _api_GL.SetPatch @@ -414,6 +441,9 @@ #define DGL_NewTextureWithParams _api_GL.NewTextureWithParams #define DGL_Bind _api_GL.Bind #define DGL_DeleteTextures _api_GL.DeleteTextures +#define DGL_Fogi _api_GL.Fogi +#define DGL_Fogf _api_GL.Fogf +#define DGL_Fogfv _api_GL.Fogfv #define GL_UseFog _api_GL.UseFog #define GL_SetFilter _api_GL.SetFilter #define GL_SetFilterColor _api_GL.SetFilterColor diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/apis.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/apis.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/apis.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/apis.h 2018-12-11 07:08:17.000000000 +0000 @@ -71,7 +71,8 @@ DE_API_BASE_v1 = 0, // 1.10 DE_API_BASE_v2 = 1, // 1.14 DE_API_BASE_v3 = 2, // 2.0 - DE_API_BASE = DE_API_BASE_v3, + DE_API_BASE_v4 = 3, // 2.1 + DE_API_BASE = DE_API_BASE_v4, DE_API_BINDING_v1 = 100, // 1.10 DE_API_BINDING_v2 = 101, // 1.15 @@ -106,7 +107,8 @@ DE_API_GL_v1 = 800, // 1.10 DE_API_GL_v2 = 801, // 1.13 DE_API_GL_v3 = 802, // 1.15 - DE_API_GL = DE_API_GL_v3, + DE_API_GL_v4 = 803, // 2.1 + DE_API_GL = DE_API_GL_v4, DE_API_INFINE_v1 = 900, // 1.10 DE_API_INFINE = DE_API_INFINE_v1, @@ -193,4 +195,11 @@ DENG_ASSERT(_api_##Name.api.id == Ident); \ break; +#if defined (DENG_STATIC_LINK) +#define DENG_SYMBOL_PTR(var, symbolName) \ + if (!qstrcmp(var, #symbolName)) { \ + return reinterpret_cast(symbolName); \ + } +#endif + #endif // DOOMSDAY_APIS_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_uri.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_uri.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/api_uri.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/api_uri.h 2018-12-11 07:08:17.000000000 +0000 @@ -187,7 +187,7 @@ */ UriWrapper* (*SetUri2)(UriWrapper* uri, char const* path, resourceclassid_t defaultResourceClass); - UriWrapper* (*SetUri)(UriWrapper* uri, char const* path/* defaultResourceClass = RC_UNKNOWN*/); + UriWrapper* (*SetUri)(UriWrapper* uri, char const* path/* defaultResourceClass = RC_IMPLICIT*/); UriWrapper* (*SetUriStr)(UriWrapper* uri, ddstring_t const* path); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/dd_share.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/dd_share.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/dd_share.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/dd_share.h 2018-12-11 07:08:17.000000000 +0000 @@ -127,43 +127,63 @@ #define DD_ULONG(x) ((uint32_t) DD_LONG(x)) ///@} -/// Integer values for Set/Get enum { - DD_FIRST_VALUE = -1, + DD_FIRST_VALUE = 0, + + DD_NOVIDEO = DD_FIRST_VALUE, DD_NETGAME, - DD_SERVER, + DD_SERVER, ///< Running in server mode + listening. DD_CLIENT, - DD_ALLOW_FRAMES, DD_CONSOLEPLAYER, DD_DISPLAYPLAYER, - DD_MIPMAPPING, - DD_SMOOTH_IMAGES, - DD_DEFAULT_RES_X_obsolete, - DD_DEFAULT_RES_Y_obsolete, - DD_UNUSED1, - DD_MOUSE_INVERSE_Y, - DD_FULLBRIGHT, ///< Render everything fullbright? - DD_CCMD_RETURN_obsolete, - DD_GAME_READY, - DD_DEDICATED, - DD_NOVIDEO, - DD_NUMMOBJTYPES, DD_GOTFRAME, - DD_PLAYBACK, DD_NUMSOUNDS, - DD_UNUSED18, // DD_NUMMUSIC, - DD_UNUSED12, // DD_NUMLUMPS + + // Server-only: + DD_SERVER_ALLOW_FRAMES, + + // Client-only: + DD_RENDER_FULLBRIGHT, ///< Render everything fullbright? + DD_GAME_READY, + DD_PLAYBACK, DD_CLIENT_PAUSED, - DD_WEAPON_OFFSET_SCALE_Y, ///< 1000x - DD_UNUSED5, - DD_GAME_DRAW_HUD_HINT, ///< Doomsday advises not to draw the HUD. + DD_WEAPON_OFFSET_SCALE_Y, ///< 1000x + DD_GAME_DRAW_HUD_HINT, ///< Doomsday advises not to draw the HUD. DD_SYMBOLIC_ECHO, - DD_MAX_TEXTURE_UNITS, DD_FIXEDCOLORMAP_ATTENUATE, + DD_LAST_VALUE, - DD_CURRENT_CLIENT_FINALE_ID, - DD_USING_HEAD_TRACKING + // Other values: + DD_GAME_EXPORTS = 0x1000, + DD_SHIFT_DOWN, + + DD_WINDOW_WIDTH = 0x1100, + DD_WINDOW_HEIGHT, + DD_WINDOW_HANDLE, + DD_USING_HEAD_TRACKING, + DD_DYNLIGHT_TEXTURE, + DD_PSPRITE_OFFSET_X, ///< 10x + DD_PSPRITE_OFFSET_Y, ///< 10x + DD_PSPRITE_LIGHTLEVEL_MULTIPLIER, + DD_TORCH_RED, + DD_TORCH_GREEN, + DD_TORCH_BLUE, + + DD_DEFS = 0x1200, ///< engine definition database (DED) + DD_NUMMOBJTYPES, + + DD_CURRENT_CLIENT_FINALE_ID = 0x1300, + + DD_GAMETIC = 0x1400, + DD_MAP_BOUNDING_BOX, + DD_MAP_MUSIC, + DD_MAP_MIN_X, + DD_MAP_MIN_Y, + DD_MAP_MAX_X, + DD_MAP_MAX_Y, + DD_MAP_POLYOBJ_COUNT, + DD_MAP_GRAVITY, }; //------------------------------------------------------------------------ @@ -425,10 +445,10 @@ #define DDMF_VIEWALIGN 0x00000010 #define DDMF_FITTOP 0x00000020 ///< Don't let the sprite go into the ceiling. #define DDMF_NOFITBOTTOM 0x00000040 -//#define DDMF_UNUSED1 0x00000080 // Formerly DDMF_NOBLOCKMAP -//#define DDMF_LIGHTSCALE 0x00000180 ///< Light scale (0: full, 3: 1/4). -//#define DDMF_LIGHTOFFSET 0x0000f000 ///< How to offset light (along Z axis). -//#define DDMF_RESERVED 0x00030000 // Don't touch these!! (translation class). +#define DDMF_MOVEBLOCKEDX 0x00000080 ///< Indicates that mobj was unable to move last tick. +#define DDMF_MOVEBLOCKEDY 0x00000100 ///< Indicates that mobj was unable to move last tick. +#define DDMF_MOVEBLOCKEDZ 0x00000200 ///< Indicates that mobj was unable to move last tick. +#define DDMF_MOVEBLOCKED 0x00000380 ///< Combination of XYZ move blocked. #define DDMF_BOB 0x00040000 ///< Bob the Z coord up and down. #define DDMF_LOWGRAVITY 0x00080000 ///< 1/8th gravity (predict). #define DDMF_MISSILE 0x00100000 ///< Client removes mobj upon impact. @@ -441,7 +461,7 @@ #define DDMF_REMOTE 0x80000000 ///< This mobj is really on the server. /// Clear masks (flags the game plugin is not allowed to touch). -#define DDMF_CLEAR_MASK 0xc0000000 +#define DDMF_CLEAR_MASK 0xc0000380 //#define DDMF_LIGHTSCALESHIFT 7 //#define DDMF_LIGHTOFFSETSHIFT 12 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/def_share.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/def_share.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/api/def_share.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/api/def_share.h 2018-12-11 07:08:17.000000000 +0000 @@ -113,10 +113,11 @@ * @ingroup defs apiFlags */ ///@{ -#define MIF_FOG 0x1 ///< Fog is used in the map. -#define MIF_DRAW_SPHERE 0x2 ///< Always draw the sky sphere. -#define MIF_NO_INTERMISSION 0x4 ///< Skip any intermission between maps. -#define MIF_LIGHTNING 0x8 ///< Lightning is used in the map. +#define MIF_FOG 0x1 ///< Fog is used in the map. +#define MIF_DRAW_SPHERE 0x2 ///< Always draw the sky sphere. +#define MIF_NO_INTERMISSION 0x4 ///< Skip any intermission between maps. +#define MIF_LIGHTNING 0x8 ///< Lightning is used in the map. +#define MIF_SPAWN_ALL_FIREMACES 0x10 ///< Heretic: Spawn all firemaces (disable randomness). ///@} #define DDLT_MAX_APARAMS 10 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/client-mac.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/client-mac.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/client-mac.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/client-mac.doxy 2018-12-11 07:08:17.000000000 +0000 @@ -2,7 +2,7 @@ @INCLUDE = ../../doomsday.doxy PROJECT_NAME = "Doomsday Client" -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 PROJECT_BRIEF = "Internal documentation (macOS)" PROJECT_LOGO = ../../doc/apidoc-logo.png HTML_STYLESHEET = ../../doxygen.css diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/client-win32.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/client-win32.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/client-win32.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/client-win32.doxy 2018-12-11 07:08:17.000000000 +0000 @@ -2,7 +2,7 @@ @INCLUDE = ../../doomsday.doxy PROJECT_NAME = "Doomsday Client" -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 PROJECT_BRIEF = "Internal documentation (Windows)" PROJECT_LOGO = ../../doc/apidoc-logo.png HTML_STYLESHEET = ../../doxygen.css diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/CMakeLists.txt 2018-12-11 07:08:17.000000000 +0000 @@ -7,7 +7,8 @@ set (DENG_ENABLE_PK3S ON) include (../../cmake/Config.cmake) -# Dependencies. +# Dependencies -------------------------------------------------------------------------- + find_package (DengAppfw) find_package (DengDoomsday) find_package (Amethyst QUIET) @@ -16,6 +17,8 @@ find_package (DirectX) endif () +# Sources and includes ------------------------------------------------------------------ + include_directories (include ${DENG_API_DIR}) add_definitions (-D__DOOMSDAY__=1 -D__CLIENT__=1) @@ -40,7 +43,10 @@ deng_merge_sources (ui_home src/ui/home/*.cpp) deng_merge_sources (ui_infine src/ui/infine/*.cpp) deng_merge_sources (ui_widgets src/ui/widgets/*.cpp) -deng_merge_sources (updater src/updater/*.cpp) +if (NOT IOS) + add_definitions (-DDENG_HAVE_UPDATER) + deng_merge_sources (updater src/updater/*.cpp) +endif () deng_merge_sources (world src/world/*.cpp) deng_merge_sources (world_base src/world/base/*.cpp) deng_merge_sources (world_bsp src/world/bsp/*.cpp) @@ -61,10 +67,11 @@ deng_merge_sources (unix src/unix/*.cpp) endif () +# Documentation sources. if (AMETHYST_FOUND) if (APPLE) set (readme "${CMAKE_CURRENT_BINARY_DIR}/Read Me.html") - deng_add_amedoc (HTML ${readme} ${DENG_SOURCE_DIR}/doc/readme readme.ame) + deng_add_amedoc (HTML "${readme}" ${DENG_SOURCE_DIR}/doc/readme readme.ame) install (FILES ${readme} DESTINATION .) list (APPEND SOURCES ${readme}) else () @@ -90,12 +97,36 @@ deng_add_package (net.dengine.client) +if (IOS) + set (MACX_RESOURCES + doomsday.pk3 + ) + + file (WRITE ${CMAKE_CURRENT_BINARY_DIR}/qt_plugin_import.cpp + "#include + Q_IMPORT_PLUGIN(QIOSIntegrationPlugin) + Q_IMPORT_PLUGIN(QGifPlugin) + Q_IMPORT_PLUGIN(QICNSPlugin) + Q_IMPORT_PLUGIN(QJpegPlugin) + Q_IMPORT_PLUGIN(QTgaPlugin)") + list (APPEND src ${CMAKE_CURRENT_BINARY_DIR}/qt_plugin_import.cpp) + + file (GLOB IOS_ICON_FILES res/ios/AppIcon*.png) + + list (APPEND src + res/ios/LaunchScreen.xib + ${IOS_ICON_FILES} + ) +endif () + # OS X: Packages and other resources to bundle with the application. -set (MACX_RESOURCES - res/macx/deng.icns - res/macx/English.lproj - doomsday.pk3 -) +if (APPLE AND NOT IOS) + set (MACX_RESOURCES + res/macx/deng.icns + res/macx/English.lproj + doomsday.pk3 + ) +endif () # Windows: Use Qt resources. if (WIN32) @@ -108,9 +139,57 @@ # There's some old code here so relax the warnings a bit. relaxed_warnings (client) -# Libraries. -target_link_libraries (client PUBLIC Deng::libappfw Deng::libdoomsday) -if (APPLE) +# Libraries ----------------------------------------------------------------------------- + +if (IOS) + link_framework (client PUBLIC CoreFoundation) + link_framework (client PUBLIC QuartzCore) + link_framework (client PUBLIC CoreGraphics) + link_framework (client PUBLIC CoreText) + link_framework (client PUBLIC Foundation) + link_framework (client PUBLIC ImageIO) + link_framework (client PUBLIC MobileCoreServices) + link_framework (client PUBLIC Security) + link_framework (client PUBLIC UIKit) + + # Static Qt libraries. + target_link_libraries (client PUBLIC + debug ${QT_LIBS}/libqtlibpng_debug.a + debug ${QT_LIBS}/libqtharfbuzz_debug.a + debug ${QT_LIBS}/libqtfreetype_debug.a + debug ${QT_LIBS}/libqtpcre_debug.a + debug ${QT_LIBS}/libQt5FontDatabaseSupport_debug.a + debug ${QT_LIBS}/libQt5GraphicsSupport_debug.a + debug ${QT_LIBS}/libQt5ClipboardSupport_debug.a + debug ${QT_PLUGINS}/platforms/libqios_debug.a + debug ${QT_PLUGINS}/imageformats/libqgif_debug.a + debug ${QT_PLUGINS}/imageformats/libqicns_debug.a + debug ${QT_PLUGINS}/imageformats/libqtga_debug.a + debug ${QT_PLUGINS}/imageformats/libqjpeg_debug.a + + optimized ${QT_LIBS}/libqtlibpng.a + optimized ${QT_LIBS}/libqtharfbuzz.a + optimized ${QT_LIBS}/libqtfreetype.a + optimized ${QT_LIBS}/libqtpcre.a + optimized ${QT_LIBS}/libQt5FontDatabaseSupport.a + optimized ${QT_LIBS}/libQt5GraphicsSupport.a + optimized ${QT_LIBS}/libQt5ClipboardSupport.a + optimized ${QT_PLUGINS}/platforms/libqios.a + optimized ${QT_PLUGINS}/imageformats/libqgif.a + optimized ${QT_PLUGINS}/imageformats/libqicns.a + optimized ${QT_PLUGINS}/imageformats/libqtga.a + optimized ${QT_PLUGINS}/imageformats/libqjpeg.a + + importdeh + importidtech1 + importudmf + doom + doom64 + heretic + hexen + audio_fmod + ) +elseif (APPLE) link_framework (client PUBLIC Cocoa) if (DENG_HAVE_QTKIT) link_framework (client PUBLIC QTKit) # MusicPlayer @@ -126,17 +205,21 @@ target_link_libraries (client PUBLIC DirectX) endif () -# Deployment ----------------------------------------------------------------- +target_link_libraries (client PUBLIC Deng::libappfw Deng::libdoomsday) + +# Deployment ---------------------------------------------------------------------------- if (WIN32 OR APPLE) set_property (TARGET client PROPERTY OUTPUT_NAME "Doomsday") set (MACOSX_BUNDLE_BUNDLE_EXECUTABLE "Doomsday") - set (MACOSX_BUNDLE_ICON_FILE "deng.icns") + if (NOT IOS) + set (MACOSX_BUNDLE_ICON_FILE "deng.icns") + endif () else () set_property (TARGET client PROPERTY OUTPUT_NAME "doomsday") endif () -if (UNIX AND NOT APPLE) +if (UNIX_LINUX) configure_file (doomsday-engine.desktop.in net.dengine.Doomsday.desktop) install (PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/net.dengine.Doomsday.desktop DESTINATION share/applications) @@ -145,11 +228,10 @@ endif () if (WIN32) - # WIX generator requires setting this manually. + # WIX generator requires setting Start Menu shortcut manually. set_property (INSTALL "bin/$" PROPERTY CPACK_START_MENU_SHORTCUTS "Doomsday Engine" ) - # Also include OpenSSL support. if (OPENSSL_DIR) find_file (OPENSSL_LIBEAY libeay32.dll @@ -166,7 +248,17 @@ endif () endif () -if (APPLE) +if (IOS) + set_target_properties (client PROPERTIES + LINK_FLAGS "-Wl,-e,_qt_main_wrapper" + RESOURCE "res/ios/LaunchScreen.xib;${IOS_ICON_FILES}" + MACOSX_BUNDLE_INFO_PLIST iOSBundleInfo.plist.in + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2" + XCODE_ATTRIBUTE_COMBINE_HIDPI_IMAGES NO + ) +endif () + +if (APPLE AND NOT IOS) deng_install_bundle_deps (client Deng::libcore Deng::libshell Deng::libgui Deng::libappfw Deng::liblegacy Deng::libdoomsday Deng::libgamefw @@ -178,7 +270,11 @@ # work on them -- plugins are already self-contained. get_property (outName TARGET client PROPERTY OUTPUT_NAME) set (stageDir "${DENG_BUILD_STAGING_DIR}/DengPlugins") - set (destDir "${outName}.app/Contents/PlugIns/Doomsday") + if (IOS) + set (destDir "${outName}.app/PlugIns") + else () + set (destDir "${outName}.app/Contents/PlugIns/Doomsday") + endif () install (CODE "execute_process (COMMAND ${CMAKE_COMMAND} -E remove_directory \"\${CMAKE_INSTALL_PREFIX}/${destDir}\")") deng_install_deployqt (client) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/audio/audiosystem.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/audio/audiosystem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/audio/audiosystem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/audio/audiosystem.h 2018-12-11 07:08:17.000000000 +0000 @@ -131,11 +131,11 @@ /** * Start playing a song. The chosen interface depends on what's available and what * kind of resources have been associated with the song. Any previously playing song - * is stopped. + * is stopped. If the song is already playing, no changes are applied. * * @param definition Music definition describing which associated music file to play. * - * @return Non-zero if the song is successfully played. + * @return Non-zero if the song is successfully played (or already playing). */ int playMusic(de::Record const &definition, bool looped = false); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/client/clientsubsector.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/client/clientsubsector.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/client/clientsubsector.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/client/clientsubsector.h 2018-12-11 07:08:17.000000000 +0000 @@ -92,8 +92,8 @@ * * @param callback Function to call for each edge loop. */ - de::LoopResult forAllEdgeLoops(std::function func); - de::LoopResult forAllEdgeLoops(std::function func) const; + de::LoopResult forAllEdgeLoops(const std::function &func); + de::LoopResult forAllEdgeLoops(const std::function &func) const; //- Audio environment ------------------------------------------------------------------- diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/clientapp.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/clientapp.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/clientapp.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/clientapp.h 2018-12-11 07:08:17.000000000 +0000 @@ -25,7 +25,6 @@ #include class AudioSystem; -class BusyRunner; class ClientPlayer; class ClientResources; class ClientServerWorld; @@ -37,6 +36,11 @@ class ServerLink; class Updater; +#if !defined (DENG_MOBILE) +# define DENG_HAVE_BUSYRUNNER 1 +class BusyRunner; +#endif + /** * The client application. */ @@ -75,11 +79,9 @@ static void alert(de::String const &msg, de::LogEntry::Level level = de::LogEntry::Message); static ClientPlayer &player(int console); - static de::LoopResult forLocalPlayers(std::function func); + static de::LoopResult forLocalPlayers(const std::function &func); static ClientApp & app(); - static BusyRunner & busyRunner(); - static Updater & updater(); static ConfigProfiles & logSettings(); static ConfigProfiles & networkSettings(); static ConfigProfiles & audioSettings(); ///< @todo Belongs in AudioSystem. @@ -93,10 +95,18 @@ static ClientResources & resources(); static ClientServerWorld & world(); +#if defined (DENG_HAVE_BUSYRUNNER) + static BusyRunner & busyRunner(); +#endif + static bool hasInputSystem(); static bool hasRenderSystem(); static bool hasAudioSystem(); +#if defined (DENG_HAVE_UPDATER) + static Updater &updater(); +#endif + public slots: void openHomepageInBrowser(); void openInBrowser(QUrl url); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/clientplayer.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/clientplayer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/clientplayer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/clientplayer.h 2018-12-11 07:08:17.000000000 +0000 @@ -50,11 +50,11 @@ struct DemoTimer { bool first; - de::dint begintime; + int begintime; bool canwrite; ///< @c false until Handshake packet. - de::dint cameratimer; - de::dint pausetime; - de::dfloat fov; + int cameratimer; + int pausetime; + float fov; }; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/dd_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/dd_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/dd_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/dd_main.h 2018-12-11 07:08:17.000000000 +0000 @@ -39,7 +39,7 @@ namespace de { class File1; } extern de::dint verbose; -extern de::dint isDedicated; +extern de::dint isDedicated; // true if __SERVER__ #ifdef __CLIENT__ extern de::dint symbolicEchoMode; #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gl_deferredapi.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gl_deferredapi.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gl_deferredapi.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gl_deferredapi.h 2018-12-11 07:08:17.000000000 +0000 @@ -43,19 +43,9 @@ extern "C" { #endif -//#define glEnable(x) Deferred_glEnable(x) -//#define glDisable(x) Deferred_glDisable(x) -//#define glDeleteTextures(x, y) Deferred_glDeleteTextures(x, y) -//#define glFogi(x, y) Deferred_glFogi(x, y) -//#define glFogf(x, y) Deferred_glFogf(x, y) -//#define glFogfv(x, y) Deferred_glFogfv(x, y) - void Deferred_glEnable(GLenum e); void Deferred_glDisable(GLenum e); void Deferred_glDeleteTextures(GLsizei num, const GLuint* names); -void Deferred_glFogi(GLenum p, GLint v); -void Deferred_glFogf(GLenum p, GLfloat v); -void Deferred_glFogfv(GLenum p, const GLfloat* v); #ifdef __cplusplus } // extern "C" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gl_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gl_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gl_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gl_main.h 2018-12-11 07:08:17.000000000 +0000 @@ -49,9 +49,6 @@ #define MINTEXWIDTH 8 #define MINTEXHEIGHT 8 -DENG_EXTERN_C int numTexUnits; -DENG_EXTERN_C dd_bool envModAdd; -//DENG_EXTERN_C int viewph, viewpw, viewpx, viewpy; DENG_EXTERN_C float vid_gamma, vid_bright, vid_contrast; DENG_EXTERN_C int r_detail; @@ -61,6 +58,8 @@ # define DENG_ASSERT_GL_CONTEXT_ACTIVE() #endif +#define Sys_GLCheckError() Sys_GLCheckErrorArgs(__FILE__, __LINE__) + #ifdef _DEBUG # define LIBDENG_ASSERT_GL_TEXTURE_ISBOUND(tex) { \ GLint p; \ @@ -134,12 +133,6 @@ de::Rangef GL_DepthClipRange(); /** - * Returns the projection matrix that is used for rendering the current frame's - * 3D portions. - */ -de::Matrix4f GL_GetProjectionMatrix(); - -/** * The first selected unit is active after this call. */ void GL_SelectTexUnits(int count); @@ -175,13 +168,6 @@ void GL_ShutdownRefresh(); /** - * Configure the GL state for the specified texture modulation mode. - * - * @param mode Modulation mode ident. - */ -void GL_ModulateTexture(int mode); - -/** * Enables or disables vsync. May cause the OpenGL surface to be recreated. * * @param on @c true to enable vsync, @c false to disable. @@ -319,9 +305,25 @@ colorpaletteid_t paletteId, float *brightX, float *brightY, struct ColorRawf_s *color, float *lumSize); -void DGL_AssertNotInPrimitive(void); +// DGL internal API --------------------------------------------------------------------- + +void DGL_Shutdown(); +unsigned int DGL_BatchMaxSize(); +void DGL_BeginFrame(); +void DGL_Flush(); +void DGL_AssertNotInPrimitive(void); +de::Matrix4f DGL_Matrix(DGLenum matrixMode); +void DGL_CurrentColor(DGLubyte *rgba); +void DGL_CurrentColor(float *rgba); +void DGL_ModulateTexture(int mode); +void DGL_SetModulationColor(de::Vector4f const &modColor); +de::Vector4f DGL_ModulationColor(); +void DGL_FogParams(de::GLUniform &fogRange, de::GLUniform &fogColor); +void DGL_DepthFunc(DGLenum depthFunc); +void DGL_CullFace(DGLenum cull); + +// Console commands --------------------------------------------------------------------- -// Console commands. D_CMD(UpdateGammaRamp); #endif // DENG_GL_MAIN_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gltextureunit.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gltextureunit.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/gltextureunit.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/gltextureunit.h 2018-12-11 07:08:17.000000000 +0000 @@ -25,16 +25,12 @@ #include #include +namespace de { + /** * Of the available GL texture units, only this many will be utilized. - * - * @todo Find a more suitable home (here because all other GL-domain headers - * also include system headers, which aren't needed in components whose API(s) - * do not depend on them (and pollute on Windows)). */ -#define MAX_TEX_UNITS 2 // More aren't currently used. - -namespace de { +#define MAX_TEX_UNITS 2 // Classic renderer only uses two. /** * GL Texture unit config. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/sys_opengl.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/sys_opengl.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/gl/sys_opengl.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/gl/sys_opengl.h 2018-12-11 07:08:17.000000000 +0000 @@ -80,19 +80,13 @@ * High-level GL state information. */ typedef struct gl_state_s { - /// Global config: - //int multisampleFormat; - /// Current state: - dd_bool currentUseFog; float currentLineWidth; float currentPointSize; /// Feature (abstract) availability bits: /// Vendor and implementation agnostic. struct { - uint blendSubtract : 1; - uint genMipmap : 1; uint texCompression : 1; uint texFilterAniso : 1; } features; @@ -119,19 +113,6 @@ extern gl_state_t GL_state; -/*#ifdef WIN32 -//extern PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT; -extern PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB; -#endif -*/ -/* -#if defined(LIBGUI_USE_GLENTRYPOINTS) -extern PFNGLBLENDEQUATIONEXTPROC glBlendEquationEXT; -extern PFNGLLOCKARRAYSEXTPROC glLockArraysEXT; -extern PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT; -#endif -*/ - #ifndef GL_ATI_texture_env_combine3 #define GL_MODULATE_ADD_ATI 0x8744 #define GL_MODULATE_SIGNED_ADD_ATI 0x8745 @@ -164,7 +145,7 @@ */ void Sys_GLPrintExtensions(void); -dd_bool Sys_GLCheckError(void); +dd_bool Sys_GLCheckErrorArgs(char const *file, int line); #endif // __CLIENT__ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/macx/cursor_macx.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/macx/cursor_macx.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/macx/cursor_macx.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/macx/cursor_macx.h 2018-12-11 07:08:17.000000000 +0000 @@ -20,6 +20,8 @@ #ifndef CLIENT_MACX_CURSOR_H #define CLIENT_MACX_CURSOR_H +#if !defined (DENG_IOS) + /** * Show or hide the mouse cursor. * @@ -27,4 +29,6 @@ */ void Cursor_Show(bool show); +#endif + #endif // CLIENT_MACX_CURSOR_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/net_buf.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/net_buf.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/net_buf.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/net_buf.h 2018-12-11 07:08:17.000000000 +0000 @@ -75,19 +75,64 @@ */ Reader1* Reader_NewWithNetworkBuffer(void); +/* + * Functions: + */ + +/** + * Initialize the low-level network subsystem. This is called always during startup (via + * Sys_Init()). + */ +void N_Init(void); + +/** + * Shut down the low-level network interface. Called during engine shutdown (not before). + */ +void N_Shutdown(void); + +/** + * Empties the message buffers. + */ +void N_ClearMessages(void); + +/** + * Send the data in the netbuffer. The message is sent over a reliable and ordered + * connection. + * + * Handles broadcasts using recursion. + * Clients can only send packets to the server. + */ +void N_SendPacket(int flags); + +/** + * An attempt is made to extract a message from the message queue. + * + * @return @c true if a message successful. + */ +dd_bool N_GetPacket(void); + +/** + * @return The player number that corresponds network node @a id. + */ +int N_IdentifyPlayer(nodeid_t id); + +/** + * Print low-level information about the network buffer. + */ +void N_PrintBufferInfo(void); + +/** + * Print status information about the workings of data compression in the network buffer. + */ +void N_PrintTransmissionStats(void); + /** - * Functions. + * Adds the given netmessage_s to the queue of received messages. Uses a mutex to + * synchronize access to the message queue. + * + * @note This is called in the network receiver thread. */ -void N_Init(void); -void N_Shutdown(void); -void N_ClearMessages(void); -void N_SendPacket(int flags); -dd_bool N_GetPacket(void); -int N_IdentifyPlayer(nodeid_t id); -void N_PrintBufferInfo(void); -void N_PrintTransmissionStats(void); -void N_PostMessage(netmessage_t *msg); -void N_AddSentBytes(size_t bytes); +void N_PostMessage(netmessage_t *msg); #ifdef __cplusplus } // extern "C" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/serverlink.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/serverlink.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/serverlink.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/serverlink.h 2018-12-11 07:08:17.000000000 +0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include #include "network/net_main.h" @@ -38,7 +39,7 @@ public: DENG2_DEFINE_AUDIENCE2(DiscoveryUpdate, void linkDiscoveryUpdate(ServerLink const &link)) - DENG2_DEFINE_AUDIENCE2(PingResponse, void pingResponse(de::Address const &, de::TimeDelta)) + DENG2_DEFINE_AUDIENCE2(PingResponse, void pingResponse(de::Address const &, de::TimeSpan)) DENG2_DEFINE_AUDIENCE2(MapOutline, void mapOutlineReceived(de::Address const &, de::shell::MapOutlinePacket const &)) DENG2_DEFINE_AUDIENCE2(Join, void networkGameJoined()) @@ -56,6 +57,8 @@ public: ServerLink(Flags flags = DiscoverLocalServers); + de::shell::PackageDownloader &packageDownloader(); + void clear(); /** @@ -66,7 +69,7 @@ * @param info Server to join. This should be one of the servers that have * previously been found via discovery. */ - void connectToServerAndChangeGame(de::shell::ServerInfo info); + void connectToServerAndChangeGameAsync(de::shell::ServerInfo info); /** * Acquire a game profile that describes the game on a multiplayer server. @@ -82,17 +85,17 @@ * The callback is called in the main thread (from the app * event loop). */ - void acquireServerProfile(de::Address const &address, - std::function resultHandler); + void acquireServerProfileAsync(de::Address const &address, + std::function resultHandler); - void acquireServerProfile(de::String const &domain, - std::function resultHandler); + void acquireServerProfileAsync(de::String const &domain, + std::function resultHandler); void requestMapOutline(de::Address const &address); void ping(de::Address const &address); - void connectDomain(de::String const &domain, de::TimeDelta const &timeout = 0) override; + void connectDomain(de::String const &domain, de::TimeSpan const &timeout = 0) override; void connectHost(de::Address const &address) override; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/sys_network.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/sys_network.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/network/sys_network.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/network/sys_network.h 2018-12-11 07:08:17.000000000 +0000 @@ -37,15 +37,10 @@ extern dd_bool allowSending; extern int maxQueuePackets; -//extern char *nptIPAddress; -//extern int nptIPPort; - ServerLink &Net_ServerLink(void); void N_Register(void); void N_PrintInfo(void); -//int N_GetHostCount(void); -//dd_bool N_GetHostInfo(int index, de::shell::ServerInfo &info); void N_PrintNetworkStatus(void); #endif // CLIENT_SYSTEM_NETWORK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/model.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/model.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/model.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/model.h 2018-12-11 07:08:17.000000000 +0000 @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -50,7 +50,7 @@ { de::String name; ///< Name of the sequence. de::Record const *def; ///< Record describing the sequence (in asset metadata). - de::Scheduler *timeline = nullptr; ///< Script timeline (owned). + de::Timeline *timeline = nullptr; ///< Script timeline (owned). de::String sharedTimeline; ///< Name of shared timeline (if specified). AnimSequence(de::String const &n, de::Record const &d); @@ -102,7 +102,7 @@ StateAnims animations; /// Shared timelines (not sequence-specific). Owned. - QHash timelines; + QHash timelines; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Model::Flags) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/modelrenderer.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/modelrenderer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/modelrenderer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/modelrenderer.h 2018-12-11 07:08:17.000000000 +0000 @@ -23,7 +23,7 @@ #include #include #include -#include +#include #include #include diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/playerweaponanimator.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/playerweaponanimator.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/playerweaponanimator.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/playerweaponanimator.h 2018-12-11 07:08:17.000000000 +0000 @@ -54,7 +54,7 @@ void setupVisPSprite(vispsprite_t &spr) const; - void advanceTime(de::TimeDelta const &elapsed); + void advanceTime(de::TimeSpan const &elapsed); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/projectedtexturedata.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/projectedtexturedata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/projectedtexturedata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/projectedtexturedata.h 2018-12-11 07:08:17.000000000 +0000 @@ -29,7 +29,7 @@ */ struct ProjectedTextureData { - DGLuint texture; + DGLuint texture = 0; de::Vector2f topLeft; de::Vector2f bottomRight; de::Vector4f color; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rendersystem.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rendersystem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rendersystem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rendersystem.h 2018-12-11 07:08:17.000000000 +0000 @@ -57,6 +57,8 @@ de::GLShaderBank &shaders(); de::ImageBank &images(); de::GLUniform const &uMapTime() const; + de::GLUniform &uProjectionMatrix() const; + de::GLUniform &uViewMatrix() const; render::Environment &environment(); ModelRenderer &modelRenderer(); SkyDrawable &sky(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_font.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_font.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_font.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_font.h 2018-12-11 07:08:17.000000000 +0000 @@ -1,7 +1,7 @@ /** @file rend_font.h * - * @authors Copyright © 2003-2017 Jaakko Keränen * @authors Copyright © 2007-2013 Daniel Swanson + * @authors Copyright © 2003-2017 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_main.h 2018-12-11 07:08:17.000000000 +0000 @@ -49,15 +49,13 @@ } // Multiplicative blending for dynamic lights? -#define IS_MUL (dynlightBlend != 1 && !fogParams.usingFog) +#define IS_MUL (dynlightBlend != 1 && !fogParams.usingFog) -#define MTEX_DETAILS_ENABLED (r_detail && useMultiTexDetails && \ - DED_Definitions()->details.size() > 0) -#define IS_MTEX_DETAILS (MTEX_DETAILS_ENABLED && numTexUnits > 1) -#define IS_MTEX_LIGHTS (!IS_MTEX_DETAILS && !fogParams.usingFog && useMultiTexLights \ - && numTexUnits > 1 && envModAdd) +#define MTEX_DETAILS_ENABLED (r_detail && DED_Definitions()->details.size() > 0) +#define IS_MTEX_DETAILS (MTEX_DETAILS_ENABLED) +#define IS_MTEX_LIGHTS (!IS_MTEX_DETAILS && !fogParams.usingFog) -#define GLOW_HEIGHT_MAX (1024.f) /// Absolute maximum +#define GLOW_HEIGHT_MAX (1024.f) /// Absolute maximum #define OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN (.05f) @@ -80,9 +78,11 @@ DENG_EXTERN_C byte smoothTexAnim, devMobjVLights; DENG_EXTERN_C int renderTextures; /// @c 0= no textures, @c 1= normal mode, @c 2= lighting debug +#if defined (DENG_OPENGL) DENG_EXTERN_C int renderWireframe; -DENG_EXTERN_C int useMultiTexLights; -DENG_EXTERN_C int useMultiTexDetails; +#endif +//DENG_EXTERN_C int useMultiTexLights; +//DENG_EXTERN_C int useMultiTexDetails; DENG_EXTERN_C int dynlightBlend; @@ -179,7 +179,16 @@ de::Vector3d Rend_EyeOrigin(); -#define Rend_PointDist2D(c) (fabs((vOrigin.z-(c)[VY])*viewsidex - (vOrigin.x-(c)[VX])*viewsidey)) +/** + * Returns the projection matrix that is used for rendering the current frame's + * 3D portions. + */ +de::Matrix4f Rend_GetProjectionMatrix(); + +#define Rend_PointDist2D(c) (abs((vOrigin.z-(c)[VY])*viewsidex - (vOrigin.x-(c)[VX])*viewsidey)) + +void Rend_SetFixedView(int consoleNum, float yaw, float pitch, float fov, de::Vector2f viewportSize); +void Rend_UnsetFixedView(); /** * The DOOM lighting model applies a light level delta to everything when diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_model.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_model.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/rend_model.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/rend_model.h 2018-12-11 07:08:17.000000000 +0000 @@ -74,7 +74,7 @@ DENG_EXTERN_C de::dint frameInter; DENG_EXTERN_C de::dfloat modelAspectMod; DENG_EXTERN_C de::dint mirrorHudModels; -DENG_EXTERN_C de::dint modelShinyMultitex; +//DENG_EXTERN_C de::dint modelShinyMultitex; DENG_EXTERN_C de::dfloat modelSpinSpeed; DENG_EXTERN_C de::dint maxModelDistance; DENG_EXTERN_C de::dfloat rendModelLOD; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/stateanimator.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/stateanimator.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/stateanimator.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/stateanimator.h 2018-12-11 07:08:17.000000000 +0000 @@ -25,11 +25,13 @@ #include #include #include +#include namespace render { /** - * State-based object animator for `ModelDrawable`s. + * State-based object animator for `ModelDrawable`s. Triggers animation sequences + * based on state changes and damage points received by the owner. * * Used for both mobjs and psprites. The state and movement of the object * determine which animation sequences are started. @@ -47,11 +49,18 @@ DENG2_ERROR(DefinitionError); public: + StateAnimator(); StateAnimator(de::DotPath const &id, Model const &model); Model const &model() const; /** + * Returns the script scheduler specific to this animator. A new scheduler will + * be created the first time this is called. + */ + de::Scheduler &scheduler(); + + /** * Sets the namespace of the animator's owner. Available as a variable in * animation scripts. * @@ -69,13 +78,15 @@ void triggerDamage(int points, struct mobj_s const *inflictor); - void startSequence(int animationId, int priority, bool looping, - de::String const &node = ""); + void startAnimation(int animationId, int priority, bool looping, + de::String const &node = ""); + + int animationId(de::String const &name) const; de::ModelDrawable::Appearance const &appearance() const; // ModelDrawable::Animator - void advanceTime(de::TimeDelta const &elapsed) override; + void advanceTime(de::TimeSpan const &elapsed) override; de::ddouble currentTime(int index) const override; de::Vector4f extraRotationForNode(de::String const &nodeName) const override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/vectorlightdata.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/vectorlightdata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/vectorlightdata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/vectorlightdata.h 2018-12-11 07:08:17.000000000 +0000 @@ -28,14 +28,14 @@ */ struct VectorLightData { - de::dfloat approxDist; ///< Only an approximation. - de::Vector3f direction; ///< Normalized vector from light origin to illumination point. - de::Vector3f color; ///< How intense the light is (0..1, RGB). - de::dfloat offset; - de::dfloat lightSide; - de::dfloat darkSide; ///< Factors for world light. - bool affectedByAmbient; - struct mobj_s const *sourceMobj; ///< Originating mobj, or nullptr. + float approxDist = 0.f; ///< Only an approximation. + de::Vector3f direction; ///< Normalized vector from light origin to illumination point. + de::Vector3f color; ///< How intense the light is (0..1, RGB). + float offset = 0.f; + float lightSide = 0.f; + float darkSide = 0.f; ///< Factors for world light. + bool affectedByAmbient = false; + struct mobj_s const *sourceMobj = nullptr; ///< Originating mobj, or nullptr. }; #endif // CLIENT_RENDER_VECTORLIGHTDATA_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/viewports.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/viewports.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/viewports.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/viewports.h 2018-12-11 07:08:17.000000000 +0000 @@ -85,10 +85,11 @@ */ de::Vector3f frontVec, upVec, sideVec; /* to the left */ - float viewCos, viewSin; + float viewCos = 0.f; + float viewSin = 0.f; de::Rectanglei window, windowTarget, windowOld; - float windowInter; + float windowInter = 0.f; }; enum ViewPortLayer { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/vissprite.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/vissprite.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/render/vissprite.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/render/vissprite.h 2018-12-11 07:08:17.000000000 +0000 @@ -51,20 +51,20 @@ struct VisEntityPose { de::Vector3d origin; - de::dfloat topZ; ///< Global top Z coordinate (origin Z is the bottom). - de::Vector3d srvo; ///< Short-range visual offset. - coord_t distance; ///< Distance from viewer. - de::dfloat yaw; - de::dfloat extraYawAngle; - de::dfloat yawAngleOffset; ///< @todo We do not need three sets of angles... - de::dfloat pitch; - de::dfloat extraPitchAngle; - de::dfloat pitchAngleOffset; - de::dfloat extraScale; - bool viewAligned; - bool mirrored; ///< If true the model will be mirrored about its Z axis (in model space). + float topZ = 0.f; ///< Global top Z coordinate (origin Z is the bottom). + de::Vector3d srvo; ///< Short-range visual offset. + coord_t distance = 0.0; ///< Distance from viewer. + float yaw = 0.f; + float extraYawAngle = 0.f; + float yawAngleOffset = 0.f; ///< @todo We do not need three sets of angles... + float pitch = 0.f; + float extraPitchAngle = 0.f; + float pitchAngleOffset = 0.f; + float extraScale = 0.f; + bool viewAligned = false; + bool mirrored = false; ///< If true the model will be mirrored about its Z axis (in model space). - VisEntityPose() { de::zap(*this); } + VisEntityPose() = default; VisEntityPose(de::Vector3d const &origin_, de::Vector3d const &visOffset, bool viewAlign_ = false, @@ -99,7 +99,7 @@ de::Vector4f ambientColor; de::duint vLightListIdx = 0; - VisEntityLighting() {} + VisEntityLighting() = default; VisEntityLighting(de::Vector4f const &ambientColor, de::duint lightListIndex) : ambientColor(ambientColor) @@ -115,8 +115,8 @@ */ struct vissprite_t { - vissprite_t *prev; - vissprite_t *next; + vissprite_t *prev = nullptr; + vissprite_t *next = nullptr; visspritetype_t type; VisEntityPose pose; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/abstractfont.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/abstractfont.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/abstractfont.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/abstractfont.h 2018-12-11 07:08:17.000000000 +0000 @@ -51,7 +51,7 @@ enum Flag { Colorize = 0x1, ///< Can be colored. - Shadowed = 0x2 ///< A shaodw is embedded in the font. + Shadowed = 0x2 ///< A shadow is embedded in the font. }; Q_DECLARE_FLAGS(Flags, Flag) @@ -76,15 +76,14 @@ /// @return Returns a copy of the font's flags. Flags flags() const; - virtual int ascent(); - virtual int descent(); - virtual int lineSpacing(); + virtual int ascent() const; + virtual int descent() const; + virtual int lineSpacing() const; + virtual de::Rectanglei const &glyphPosCoords(uchar ch) const = 0; + virtual de::Rectanglei const &glyphTexCoords(uchar ch) const = 0; - virtual void glInit(); - virtual void glDeinit(); - - virtual de::Rectanglei const &glyphPosCoords(uchar ch) = 0; - virtual de::Rectanglei const &glyphTexCoords(uchar ch) = 0; + virtual void glInit() const; + virtual void glDeinit() const; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractFont::Flags) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/bitmapfont.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/bitmapfont.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/bitmapfont.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/bitmapfont.h 2018-12-11 07:08:17.000000000 +0000 @@ -44,15 +44,15 @@ de::Vector2i const &textureDimensions() const; de::Vector2ui const &textureMargin() const; - int ascent(); - int descent(); - int lineSpacing(); + int ascent() const override; + int descent() const override; + int lineSpacing() const override; - void glInit(); - void glDeinit(); + de::Rectanglei const &glyphPosCoords(uchar ch) const override; + de::Rectanglei const &glyphTexCoords(uchar ch) const override; - de::Rectanglei const &glyphPosCoords(uchar ch); - de::Rectanglei const &glyphTexCoords(uchar ch); + void glInit() const override; + void glDeinit() const override; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/clientmaterial.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/clientmaterial.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/clientmaterial.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/clientmaterial.h 2018-12-11 07:08:17.000000000 +0000 @@ -45,7 +45,9 @@ */ ClientMaterial(world::MaterialManifest &manifest); - ~ClientMaterial(); + ~ClientMaterial() override; + + bool isAnimated() const override; /** * Returns a human-friendly, textual description of the full material configuration. @@ -200,7 +202,7 @@ * * @param func Callback to make for each Decoration. */ - de::LoopResult forAllDecorations(std::function func) const; + de::LoopResult forAllDecorations(const std::function &func) const; /** * Add a new (light) decoration to the material. @@ -242,7 +244,7 @@ * * @param func Callback to make for each Animator. */ - de::LoopResult forAllAnimators(std::function func) const; + de::LoopResult forAllAnimators(const std::function &func) const; /** * Destroy all the MaterialAnimators for the material. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/compositebitmapfont.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/compositebitmapfont.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/compositebitmapfont.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/compositebitmapfont.h 2018-12-11 07:08:17.000000000 +0000 @@ -63,20 +63,20 @@ */ void rebuildFromDef(struct ded_compositefont_s const &def); - int ascent(); - int descent(); - int lineSpacing(); + int ascent() const override; + int descent() const override; + int lineSpacing() const override; - void glInit(); - void glDeinit(); + void glInit() const override; + void glDeinit() const override; - de::Rectanglei const &glyphPosCoords(uchar ch); - de::Rectanglei const &glyphTexCoords(uchar ch); + de::Rectanglei const &glyphPosCoords(uchar ch) const override; + de::Rectanglei const &glyphTexCoords(uchar ch) const override; - patchid_t glyphPatch(uchar ch); + patchid_t glyphPatch(uchar ch) const; void glyphSetPatch(uchar ch, de::String encodedPatchName); - TextureVariant *glyphTexture(uchar ch); - uint glyphTextureBorder(uchar ch); + TextureVariant *glyphTexture(uchar ch) const; + uint glyphTextureBorder(uchar ch) const; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/idtech1image.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/idtech1image.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/resource/idtech1image.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/resource/idtech1image.h 2018-12-11 07:08:17.000000000 +0000 @@ -64,6 +64,7 @@ ColorizedByFamily = 0x1, Downscale50Percent = 0x2, NullImageIfFails = 0x4, // by default returns a small fallback image + AlwaysTryLoad = 0x8, DefaultLogoFlags = ColorizedByFamily | Downscale50Percent, }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientrootwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientrootwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientrootwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientrootwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -21,6 +21,7 @@ #include #include +#include class ClientWindow; @@ -33,12 +34,16 @@ ClientRootWidget(de::GLWindow *window = 0); ClientWindow &window(); + de::PackageIconBank &packageIconBank(); void update() override; void addOnTop(de::GuiWidget *widget) override; void dispatchLatestMousePosition() override; void handleEventAsFallback(de::Event const &event) override; + +private: + DENG2_PRIVATE(d) }; #endif // DENG_CLIENTROOTWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientstyle.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientstyle.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientstyle.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientstyle.h 2018-12-11 07:08:17.000000000 +0000 @@ -28,9 +28,11 @@ public: ClientStyle(); - de::GuiWidget *sharedBlurWidget() const; + de::GuiWidget *sharedBlurWidget() const override; de::ui::Stylist &emptyMenuLabelStylist() const; + void performUpdate() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientwindow.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientwindow.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/clientwindow.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/clientwindow.h 2018-12-11 07:08:17.000000000 +0000 @@ -144,11 +144,11 @@ enum FadeDirection { FadeFromBlack, FadeToBlack }; - void fadeContent(FadeDirection fadeDirection, de::TimeDelta const &duration); + void fadeContent(FadeDirection fadeDirection, de::TimeSpan const &duration); de::FadeToBlackWidget *contentFade(); - void fadeInTaskBarBlur(de::TimeDelta span); - void fadeOutTaskBarBlur(de::TimeDelta span); + void fadeInTaskBarBlur(de::TimeSpan span); + void fadeOutTaskBarBlur(de::TimeSpan span); void updateRootSize(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/createprofiledialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/createprofiledialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/createprofiledialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/createprofiledialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -21,11 +21,14 @@ #include #include +#include /** * Dialog for creating a game profile. */ -class CreateProfileDialog : public de::InputDialog +class CreateProfileDialog + : public de::InputDialog + , public de::IPersistent { public: CreateProfileDialog(de::String const &gameFamily); @@ -42,6 +45,11 @@ de::String profileName() const; + // Implements IPersistent. + void operator>>(de::PersistentState &toState) const; + void operator<<(de::PersistentState const &fromState); + +public: static CreateProfileDialog *editProfile(de::String const &gameFamily, GameProfile &profile); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/downloaddialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/downloaddialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/downloaddialog.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/downloaddialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,49 @@ +/** + * @file downloaddialog.h + * Dialog for downloads. @ingroup ui + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef DENG_CLIENT_DOWNLOADDIALOG_H +#define DENG_CLIENT_DOWNLOADDIALOG_H + +#include +#include + +/** + * Dialog for downloading content. + */ +class DownloadDialog : public de::DialogWidget +{ +public: + DownloadDialog(de::String const &name = de::String()); + + ~DownloadDialog(); + + de::ProgressWidget &progressIndicator(); + + virtual void cancel() = 0; + +protected: + void updateStyle() override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // DENG_CLIENT_DOWNLOADDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/filedownloaddialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/filedownloaddialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/filedownloaddialog.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/filedownloaddialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,43 @@ +/** @file filedownloaddialog.h Dialog for monitoring file download progress. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG_CLIENT_FILEDOWNLOADDIALOG_H +#define DENG_CLIENT_FILEDOWNLOADDIALOG_H + +#include "downloaddialog.h" +#include + +/** + * Dialog for monitoring file downloads. + * @ingroup ui + */ +class FileDownloadDialog : public DownloadDialog +{ +public: + FileDownloadDialog(de::shell::PackageDownloader &downloader); + + void cancel() override; + +protected: + void finish(int result) override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // DENG_CLIENT_FILEDOWNLOADDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/manualconnectiondialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/manualconnectiondialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/manualconnectiondialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/manualconnectiondialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -44,8 +44,8 @@ void enableJoinWhenSelected(bool joinWhenSelected); // Implements IPersistent. - void operator >> (de::PersistentState &toState) const; - void operator << (de::PersistentState const &fromState); + void operator>>(de::PersistentState &toState) const; + void operator<<(de::PersistentState const &fromState); signals: void selected(de::ui::Item const *); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/packageinfodialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/packageinfodialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/packageinfodialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/packageinfodialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -29,8 +29,11 @@ Q_OBJECT public: - PackageInfoDialog(de::String const &packageId); - PackageInfoDialog(de::File const *packageFile); + enum Mode { EnableActions, InformationOnly }; + +public: + PackageInfoDialog(de::String const &packageId, Mode mode); + PackageInfoDialog(de::File const *packageFile, Mode mode); protected: void prepare() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/packagesdialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/packagesdialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/packagesdialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/packagesdialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -20,6 +20,7 @@ #define DENG_CLIENT_PACKAGESDIALOG_H #include +#include /** * Package selection UI. @@ -31,13 +32,11 @@ public: PackagesDialog(de::String const &titleText = ""); - void setGame(de::String const &gameId); +// void setGame(de::String const &gameId); + void setProfile(const GameProfile &profile); void setSelectedPackages(de::StringList packages); de::StringList selectedPackages() const; -public slots: - void refreshPackages(); - protected: void preparePanelForOpening() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/repositorybrowserdialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/repositorybrowserdialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/repositorybrowserdialog.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/repositorybrowserdialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,40 @@ +/** @file repositorybrowserdialog.h Remote package repository browser. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG_CLIENT_REPOSITORYBROWSERDIALOG_H +#define DENG_CLIENT_REPOSITORYBROWSERDIALOG_H + +#include + +/** + * Remote package repository browser. + * @ingroup ui + */ +class RepositoryBrowserDialog : public de::DialogWidget +{ +public: + RepositoryBrowserDialog(); + +protected: + void finish(int result) override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // DENG_CLIENT_REPOSITORYBROWSERDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/videosettingsdialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/videosettingsdialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/dialogs/videosettingsdialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/dialogs/videosettingsdialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -33,11 +33,14 @@ protected slots: void resetToDefaults(); +#if !defined (DENG_MOBILE) void changeMode(uint selected); void changeColorDepth(uint selected); + void changeRefreshRate(uint selected); void showColorAdjustments(); void showWindowMenu(); void applyModeToWindow(); +#endif private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/gamecolumnwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/gamecolumnwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/gamecolumnwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/gamecolumnwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -39,8 +39,15 @@ void setHighlighted(bool highlighted) override; // Implements IPersistent. - void operator >> (de::PersistentState &toState) const; - void operator << (de::PersistentState const &fromState); + void operator>>(de::PersistentState &toState) const override; + void operator<<(de::PersistentState const &fromState) override; + +public: + static const de::String SORT_GAME_ID; + static const de::String SORT_MODS; + static const de::String SORT_RECENTLY_PLAYED; + static const de::String SORT_RELEASE_DATE; + static const de::String SORT_TITLE; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/homewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/homewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/homewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/homewidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -40,8 +40,8 @@ bool dispatchEvent(de::Event const &event, bool (de::Widget::*memberFunc)(de::Event const &)) override; - void moveOnscreen(de::TimeDelta span = 1.5); - void moveOffscreen(de::TimeDelta span = 1.5); + void moveOnscreen(de::TimeSpan span = 1.5); + void moveOffscreen(de::TimeSpan span = 1.5); // Events. void update() override; @@ -56,6 +56,9 @@ void tabChanged(); void mouseActivityInColumn(QObject const *); +protected: + void updateStyle() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/packagescolumnwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/packagescolumnwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/home/packagescolumnwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/home/packagescolumnwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -23,12 +23,20 @@ class PackagesColumnWidget : public ColumnWidget { + Q_OBJECT + public: PackagesColumnWidget(); + int availablePackageCount() const; + de::String tabHeading() const override; + de::String tabShortcut() const override; void setHighlighted(bool highlighted) override; +signals: + void availablePackageCountChanged(int count); + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/postprocessing.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/postprocessing.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/postprocessing.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/postprocessing.h 2018-12-11 07:08:17.000000000 +0000 @@ -50,9 +50,9 @@ * @param fxPostShader Name of the shader under "fx.post". * @param span Duration of the fade in animation. */ - void fadeInShader(de::String const &fxPostShader, de::TimeDelta const &span); + void fadeInShader(de::String const &fxPostShader, de::TimeSpan const &span); - void fadeOut(de::TimeDelta const &span); + void fadeOut(de::TimeSpan const &span); /** * Sets a constant opacity factor that is applied in addition to the fade. @@ -63,12 +63,8 @@ void glInit(); void glDeinit(); - void update(); - - //void beginFrame(); void draw(de::Matrix4f const &mvpMatrix, de::GLTexture const &frame); - //void endFrame(); public: static void consoleRegister(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/consolewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/consolewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/consolewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/consolewidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -86,7 +86,9 @@ void focusOnCommandLine(); void closeMenu(); void commandWasEntered(de::String const &); +#if !defined (DENG_MOBILE) void copyLogPathToClipboard(); +#endif protected slots: void logContentHeightIncreased(int delta); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/cvarnativepathwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/cvarnativepathwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/cvarnativepathwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/cvarnativepathwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -19,44 +19,22 @@ #ifndef DENG_CLIENT_CVARNATIVEPATHWIDGET_H #define DENG_CLIENT_CVARNATIVEPATHWIDGET_H -#include +#include "nativepathwidget.h" #include "icvarwidget.h" /** * Console variable that contains a native path. */ -class CVarNativePathWidget : public de::AuxButtonWidget, public ICVarWidget +class CVarNativePathWidget : public NativePathWidget, public ICVarWidget { Q_OBJECT public: CVarNativePathWidget(char const *cvarPath); - - /** - * Sets all the file types that can be selected using the widget. Each entry in - * the list should be formatted as "Description (*.ext *.ext2)". - * - * The default is "All files (*)". - * - * @param filters Allowed file types. - */ - void setFilters(de::StringList const &filters); - - /** - * Sets the text that is shown as the current selection when nothing has been - * selected. - * - * @param text Blank text placeholder. - */ - void setBlankText(de::String const &text); - char const *cvarPath() const; public slots: void updateFromCVar(); - void chooseUsingNativeFileDialog(); - void clearPath(); - void showActionsPopup(); protected slots: void setCVarValueFromWidget(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/gamewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/gamewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/gamewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/gamewidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -32,15 +32,6 @@ public: GameWidget(de::String const &name = "game"); - /* - * Convenience method for changing and immediately applying a new GL - * viewport. The viewport is automatically normalized in relation to the - * root view size. - * - * This is only intended to support old graphics code that doesn't use libgui. - */ - //void glApplyViewport(de::Rectanglei const &rect); - /** * Pauses the game, if one is currently running and pausing is allowed. */ @@ -48,6 +39,8 @@ void drawComposited(); + void renderCubeMap(uint size, de::String const &outputImagePath); + // Events. void viewResized() override; void update() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/homeitemwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/homeitemwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/homeitemwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/homeitemwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -39,6 +39,7 @@ { NonAnimatedHeight = 0, AnimatedHeight = 0x1, + WithoutIcon = 0x2, }; Q_DECLARE_FLAGS(Flags, Flag) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/homemenuwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/homemenuwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/homemenuwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/homemenuwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -44,6 +44,8 @@ */ de::ui::DataPos selectedIndex() const; + const de::ui::Item *selectedItem() const; + /** * @brief setSelectedIndex * @param index diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/nativepathwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/nativepathwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/nativepathwidget.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/nativepathwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,70 @@ +/** @file nativepathwidget.h Widget for selecting a native path. + * + * @authors Copyright (c) 2014-2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG_CLIENT_UI_NATIVEPATHWIDGET_H +#define DENG_CLIENT_UI_NATIVEPATHWIDGET_H + +#include + +/** + * Console variable that contains a native path. + */ +class NativePathWidget : public de::AuxButtonWidget +{ + Q_OBJECT + +public: + DENG2_DEFINE_AUDIENCE2(UserChange, void pathChangedByUser(NativePathWidget &)) + +public: + NativePathWidget(); + + /** + * Sets all the file types that can be selected using the widget. Each entry in + * the list should be formatted as "Description (*.ext *.ext2)". + * + * The default is "All files (*)". + * + * @param filters Allowed file types. + */ + void setFilters(const de::StringList &filters); + + /** + * Sets the text that is shown as the current selection when nothing has been + * selected. + * + * @param blankText Blank text placeholder. + */ + void setBlankText(const de::String &blankText); + + void setPrompt(const de::String &promptText); + + void setPath(const de::NativePath &path); + + de::NativePath path() const; + +public slots: + void chooseUsingNativeFileDialog(); + void clearPath(); + void showActionsPopup(); + +private: + DENG2_PRIVATE(d) +}; + +#endif // DENG_CLIENT_UI_NATIVEPATHWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/packagesbuttonwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/packagesbuttonwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/packagesbuttonwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/packagesbuttonwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -41,6 +41,7 @@ void setSetupCallback(std::function func); void setLabelPrefix(de::String const &labelPrefix); void setNoneLabel(de::String const &noneLabel); + void setOverrideLabel(de::String const &overrideLabel); void setPackages(de::StringList packageIds); de::StringList packages() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/packageswidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/packageswidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/packageswidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/packageswidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -61,6 +61,7 @@ de::ProgressWidget &progress(); void setManualPackageIds(de::StringList manualPackageIds); + void setAllowPackageInfoActions(bool allowActions); void setRightClickToOpenContextMenu(bool enable); void setHiddenTags(de::StringList hiddenTags); void setPopulationEnabled(bool enable); @@ -116,11 +117,8 @@ void update(); // Implements IPersistent. - void operator >> (de::PersistentState &toState) const; - void operator << (de::PersistentState const &fromState); - -public slots: - void refreshPackages(); + void operator>>(de::PersistentState &toState) const; + void operator<<(de::PersistentState const &fromState); signals: void itemCountChanged(unsigned int shownItems, unsigned int totalItems); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/privilegedlogwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -36,6 +36,9 @@ void showLog(); void hideLog(); +protected: + void updateStyle() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/sidebarwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/sidebarwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/sidebarwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/sidebarwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -36,11 +36,11 @@ SidebarWidget(de::String const &title, de::String const &name = de::String()); de::SequentialLayout &layout(); - de::LabelWidget &title(); + de::LabelWidget & title(); de::ScrollAreaWidget &containerWidget(); - de::ButtonWidget &closeButton(); - de::IndirectRule &firstColumnWidth(); - de::Rule const &maximumOfAllGroupFirstColumns() const; + de::ButtonWidget & closeButton(); + de::IndirectRule & firstColumnWidth(); + de::Rule const & maximumOfAllGroupFirstColumns() const; protected: /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/taskbarwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/taskbarwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/widgets/taskbarwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/widgets/taskbarwidget.h 2018-12-11 07:08:17.000000000 +0000 @@ -62,11 +62,13 @@ void openMultiplayerMenu(); void unloadGame(); void showAbout(); - void showUpdaterSettings(); void showOrHideHome(); void connectToServerManually(); void showTutorial(); void openPackagesSidebar(); +#if defined (DENG_HAVE_UPDATER) + void showUpdaterSettings(); +#endif protected slots: void updateCommandLineLayout(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/zonedebug.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/zonedebug.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/ui/zonedebug.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/ui/zonedebug.h 2018-12-11 07:08:17.000000000 +0000 @@ -23,7 +23,7 @@ #define CLIENT_ZONEDEBUG_H #include -#ifdef DENG_DEBUG +#if defined (DENG_DEBUG) && defined (DENG_OPENGL) #ifdef __cplusplus extern "C" { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/downloaddialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/downloaddialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/downloaddialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/downloaddialog.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/** - * @file downloaddialog.h - * Dialog that downloads a distribution package. @ingroup updater - * - * @authors Copyright © 2012-2017 Jaakko Keränen - * @authors Copyright © 2013 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef DENG_CLIENT_DOWNLOADDIALOG_H -#define DENG_CLIENT_DOWNLOADDIALOG_H - -#include - -class QNetworkReply; - -/** - * Dialog for downloading an update in the background and then starting - * the (re)installation process. - */ -class DownloadDialog : public de::DialogWidget -{ - Q_OBJECT - -public: - DownloadDialog(de::String downloadUri, de::String fallbackUri); - ~DownloadDialog(); - - /** - * Returns the path of the downloaded file. - * - * @return Path, or an empty string if the download did not finish - * successfully. - */ - de::String downloadedFilePath() const; - - bool isReadyToInstall() const; - bool isFailed() const; - -public: - static bool isDownloadInProgress(); - static DownloadDialog ¤tDownload(); - static void showCompletedDownload(); - -signals: - void downloadProgress(int percentage); - void downloadFailed(QString uri); - -public slots: - void replyMetaDataChanged(); - void progress(qint64 received, qint64 total); - void finished(QNetworkReply *); - void cancel(); - -private: - DENG2_PRIVATE(d) -}; - -#endif // DENG_CLIENT_DOWNLOADDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/updatedownloaddialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/updatedownloaddialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/updatedownloaddialog.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/updatedownloaddialog.h 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,71 @@ +/** + * @file updatedownloaddialog.h + * Dialog that downloads a distribution package. @ingroup updater + * + * @authors Copyright © 2012-2017 Jaakko Keränen + * @authors Copyright © 2013 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG_CLIENT_UPDATEDOWNLOADDIALOG_H +#define DENG_CLIENT_UPDATEDOWNLOADDIALOG_H + +#include "ui/dialogs/downloaddialog.h" + +class QNetworkReply; + +/** + * Dialog for downloading an update in the background and then starting + * the (re)installation process. + */ +class UpdateDownloadDialog : public DownloadDialog +{ + Q_OBJECT + +public: + UpdateDownloadDialog(de::String downloadUri, de::String fallbackUri); + ~UpdateDownloadDialog(); + + /** + * Returns the path of the downloaded file. + * + * @return Path, or an empty string if the download did not finish + * successfully. + */ + de::String downloadedFilePath() const; + + bool isReadyToInstall() const; + bool isFailed() const; + +public: + static bool isDownloadInProgress(); + static UpdateDownloadDialog ¤tDownload(); + static void showCompletedDownload(); + +signals: + void downloadProgress(int percentage); + void downloadFailed(QString uri); + +public slots: + void replyMetaDataChanged(); + void progress(qint64 received, qint64 total); + void finished(QNetworkReply *); + void cancel() override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // DENG_CLIENT_UPDATEDOWNLOADDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/updatersettings.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/updatersettings.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/updater/updatersettings.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/updater/updatersettings.h 2018-12-11 07:08:17.000000000 +0000 @@ -46,7 +46,8 @@ enum Channel { Stable = 0, - Unstable = 1 + Unstable = 1, + StableOrCandidate = 2, }; public: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/clientserverworld.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/clientserverworld.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/clientserverworld.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/clientserverworld.h 2018-12-11 07:08:17.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,8 @@ */ void update(); + de::Scheduler &scheduler(); + /** * Provides access to the currently loaded map. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/lineowner.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/lineowner.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/lineowner.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/lineowner.h 2018-12-11 07:08:17.000000000 +0000 @@ -61,7 +61,7 @@ * * @see prev() */ - inline bool hasPrev() const { return &prev() != this; } + inline bool hasPrev() const { return prev() != this; } /** * Returns @c true iff the next line owner in the ring (clockwise) is not @@ -69,16 +69,16 @@ * * @see next() */ - inline bool hasNext() const { return &next() != this; } + inline bool hasNext() const { return next() != this; } /** * Navigate to the adjacent line owner in the ring (if any). Note this may * be the same LineOwner. */ - LineOwner &navigate(de::ClockDirection dir = de::Anticlockwise) { return *_link[dir]; } + LineOwner *navigate(de::ClockDirection dir = de::Anticlockwise) { return _link[dir]; } /// @copydoc navigate() - LineOwner const &navigate(de::ClockDirection dir = de::Anticlockwise) const { return *_link[dir]; } + const LineOwner *navigate(de::ClockDirection dir = de::Anticlockwise) const { return _link[dir]; } /** * Returns the previous line owner in the ring (anticlockwise). Note that @@ -86,10 +86,10 @@ * * @see hasPrev() */ - inline LineOwner &prev() { return navigate(de::Anticlockwise); } + inline LineOwner *prev() { return navigate(de::Anticlockwise); } /// @copydoc prev() - inline LineOwner const &prev() const { return navigate(de::Anticlockwise); } + inline const LineOwner *prev() const { return navigate(de::Anticlockwise); } /** * Returns the next line owner in the ring (clockwise). Note that this may @@ -97,13 +97,13 @@ * * @see hasNext() */ - inline LineOwner &next() { return navigate(de::Clockwise); } + inline LineOwner *next() { return navigate(de::Clockwise); } /// @copydoc next() - inline LineOwner const &next() const { return navigate(de::Clockwise); } + inline const LineOwner *next() const { return navigate(de::Clockwise); } - inline LineOwner *prevPtr() { return _link[de::Anticlockwise]; } - inline LineOwner *nextPtr() { return _link[de::Clockwise]; } +// inline LineOwner *prevPtr() { return _link[de::Anticlockwise]; } +// inline LineOwner *nextPtr() { return _link[de::Clockwise]; } /** * Returns the line "owner". diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/map.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/map.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/map.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/map.h 2018-12-11 07:08:17.000000000 +0000 @@ -67,6 +67,8 @@ #endif #endif // 0 +namespace de { class Info; } + namespace world { class Blockmap; @@ -201,7 +203,11 @@ void serializeInternalState(de::Writer &to) const override; - void deserializeInternalState(de::Reader &from, world::IThinkerMapping const &thinkerMapping) override; + void deserializeInternalState(de::Reader &from, IThinkerMapping const &thinkerMapping) override; + + de::String objectsDescription() const; + + void restoreObjects(de::Info const &objState, IThinkerMapping const &thinkerMapping) const; public: //- Light sources -------------------------------------------------------------- diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/p_object.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/p_object.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/p_object.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/p_object.h 2018-12-11 07:08:17.000000000 +0000 @@ -44,7 +44,7 @@ } class Plane; -#define MOBJ_SIZE gx.mobjSize +#define MOBJ_SIZE gx.GetInteger(DD_MOBJ_SIZE) class MobjThinker : public ThinkerT { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/sector.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/sector.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/sector.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/sector.h 2018-12-11 07:08:17.000000000 +0000 @@ -238,7 +238,7 @@ * * @param callback Function to call for each Subsector. */ - de::LoopResult forAllSubsectors(std::function callback) const; + de::LoopResult forAllSubsectors(const std::function &callback) const; /** * Generate a new Subsector from the given set of map @a subspaces. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/thinkers.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/thinkers.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/include/world/thinkers.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/include/world/thinkers.h 2018-12-11 07:08:17.000000000 +0000 @@ -125,7 +125,8 @@ } // namespace world -dd_bool Thinker_HasMobjFunc(thinkfunc_t func); +bool Thinker_IsMobj(thinker_t const *th); +bool Thinker_IsMobjFunc(thinkfunc_t func); world::Map &Thinker_Map(thinker_t const &th); /** diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/CHANGELOG.txt" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/CHANGELOG.txt" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/CHANGELOG.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/CHANGELOG.txt" 2018-12-11 07:08:17.000000000 +0000 @@ -0,0 +1,97 @@ +GeneralUser GS Revision History + +Changes for v1.471 +<> Fixed missing chimes (C6) in Power and Orchestral drum kits. +<> Fixed Marimba crashing MuseScore. + +Changes for v1.47 +<> Unified the FluidSynth and MuseScore versions into a single version now that MuseScore bug #72091 (https://musescore.org/node/72091) has been fixed. This version has also been verified (and slightly tweaked) to work with the latest SynthFont2, which now supports SoundFont 2.01 modulators! Requires SynthFont2 2.0.3.2 or later, or VSTSynthFont 1.081 or later. + +Changes for v1.46 +<> Fixed high-pitched squeal in Electric Grand +<> Improved kicks and snares in Standard, Standard 2, Room, Power and Electronic drum kits +<> Balanced C5 sample in the Bassoon to fit better with the adjacent samples +<> Improved the Harpsichord and fixed weird loop buzz +<> Improved the Tremolo Strings +<> Slight tweak to attack on Accordion +<> Improved clicking loops in Fretless Bass +<> Fixed bad loops in all strings +<> Fixed Recorder release (it was too short) +<> Fixed weird attack and velocity->filter response in Chiffer Lead +<> Fixed release in upper extreme range of Muted Trumpet +<> Fixed flat loop in Acoustic Bass + +Changes for v1.45 + +<> Tweaked velocity scaling in FluidSynth version to be less extreme between FF and PP playing. +<> Fixed Slap Bass 1 & 2 release to avoid clicks in FluidSynth. + +Changes for v1.44 + +<> New license +<> Fixed loops in Concert Choir +<> Improved Bagpipes +<> FluidSynth/MuseScore version: improved programming of harpsichord, trumpet, trombone, muted trumpet, and pan flute. +<> MuseScore version: adjusted balance of orchestral instruments +<> MuseScore version: modified default drum kit with orchestral bass drum, snare and cymbals. + + +Changes for v1.43 + +<> Various improvements +<> Re-worked strings in Live/Audigy version +<> Separate versions for Live/Audigy, FluidSynth and other software synths +<> Removed brand and product name references from presets + + +Changes for v1.4 + +<> Countless samples have been replaced, improved, cleaned, re-looped, etc. +<> Just as many instruments have been reworked, rebalanced, etc. +<> Improved overall instrument volume and balance +<> Previous versions of GeneralUser GS only allowed 20% of the total reverb and chorus effects to be used (this is the default setting in the SoundFont specification). Setting reverb (CC91) or chorus (CC93) to max value (127) now allows 100% of the effect to be heard. +<> Added self-test mode (activated by playing "GUTest.mid") +<> There are too many improvements in this bank to list, you will have to hear it for yourself :) + + +Changes for v1.35 + +<> Made compatible with Sound Blaster Audigy and EMU APS. +<> Minor tweaks. + + +Changes for v1.3 + +<> Combined AWE32/64 and Live! versions into one bank compatible with both sound cards. +<> Resampled Marimba. +<> Standard snare now sounds much more realistic. +<> Cymbals act appropriately when played soft, making decent-sounding cymbal rolls possible. +<> Replaced Synth Brass 1, Square Lead and Sawtooth lead. The old Square Lead and Sawtooth lead can be found in bank 12. +<> Countless other modifications to instruments in the bank, including balance fixes. + + +Changes for v1.2 + +Both versions: +<> Adjusted piano 1 and 2 brightness. +<> Adjusted tuning of Marimba -- attack still sounds strange in Live! version, can't figure out why. +<> Fixed crackling in Clean Guitar (and variants). +<> Increased volume of high Trumpet notes. +<> Other small changes. + +Live! version: +<> Fixed Hi-hat cutoff bug that showed up courtesy of the Creative Labs driver. +<> Fixed bad attack on Harpsichord sound. +<> Fixed some more synth sounds that weren't right because the Live! driver screwed up the filter settings. + + +Changes for v1.1 + +Both versions: +<> Reworked the string ensemble using same samples. Sounds more full now and is in stereo. +<> Adjusted balance/envelopes of some woodwinds. +<> Made orchestral snare velocity sensitive. +<> Other small tweaks here and there. + +Live! version: +<> Fixed some synth sounds that weren't right because the Live! driver screwed up the filter settings. \ No newline at end of file Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/GeneralUser GS v1.471.sf2 and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/GeneralUser GS v1.471.sf2 differ diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43-Drumsets.ins" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43-Drumsets.ins" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43-Drumsets.ins" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43-Drumsets.ins" 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,357 @@ + +; ---------------------------------------------------------------------- + +.Patch Names + + +[GeneralUser GS 1.43-Drumsets] +0=Standard 1 +1=Standard 2 +8=Room +16=Power +24=Electronic +25=808/909 +26=Dance +32=Jazz +40=Brush +48=Orchestra +56=SFX + +; ---------------------------------------------------------------------- + +.Note Names + + +[GeneralUser GS 1.43-Standard 2 Set] +35=Kick 1 +36=Kick 2 +38=Snare 1 +40=Snare 2 + +[GeneralUser GS 1.43-SFX Set] +39=High Q +40=Slap +41=Scratch Push +42=Scratch Pull +43=Sticks +44=Square Click +45=Metronome Click +46=Metronome Bell +47=Guitar Sliding Finger +48=Guitar Cutting Noise (Down) +49=Guitar Cutting Noise (Up) +50=String Slap of Double Bass +51=Flute Key click +52=Laughing +53=Screaming +54=Punch +55=Heart Beat +56=Footsteps 1 +57=Footsteps 2 +58=Applause +59=Door Creaking +60=Door +61=Scratch +62=Windchime +63=Car-Engine +64=Car-Stop +65=Car-Pass +66=Car-Crash +67=Siren +68=Train +69=Jetplane +70=Helicopter +71=Starship +72=Gun Shot +73=Machine Gun +74=Lasergun +75=Explosion +76=Dog +77=Horse-Gallop +78=Birds +79=Rain +80=Thunder +81=Wind +82=Seashore +83=Stream +84=Bubble + +[GeneralUser GS 1.43-Power Set] +36=Power Kick +38=Power Snare +41=Room Low Tom 2 +43=Room Low Tom 1 +45=Room Mid Tom 2 +47=Room Mid Tom 1 +48=Room Hi Tom 2 +50=Room Hi Tom 1 + +[GeneralUser GS 1.43-Orchestra Set] +27=Closed Hi Hat +28=Pedal Hi Hat +29=Open Hi Hat +30=Ride Cymbal +36=Concert Bass Drum +38=Concert Snare +39=Castanets +40=Concert Snare +41=Timpani F +42=Timpani F# +43=Timpani G +44=Timpani G# +45=Timpani A +46=Timpani A# +47=Timpani B +48=Timpani C +49=Timpani C# +50=Timpani D +51=Timpani D# +52=Timpani E +53=Timpani F +57=Concert Cymbal 2 +59=Concert Cymbal 1 +88=Applause + +[GeneralUser GS 1.43-Electronic Set] +36=Elec. Kick +38=Elec. Snare +40=Gated Snare +41=Elec. Low Tom 2 +42=Elec. Closed Hat +43=Elec. Low Tom 1 +44=Elec. Pedal Hat +45=Elec. Mid Tom 2 +46=Elec. Open Hat +47=Elec. Mid Tom 1 +48=Elec. Hi Tom 2 +50=Elec. Hi Tom 1 +52=Reverse Cymbal + +[GeneralUser GS 1.43-Brush Set] +38=Brush Tap +39=Brush Slap +40=Brush Swirl + +[GeneralUser GS 1.43-Room Set] +41=Room Low Tom 2 +43=Room Low Tom 1 +45=Room Mid Tom 2 +47=Room Mid Tom 1 +48=Room Hi Tom 2 +50=Room Hi Tom 1 + +[GeneralUser GS 1.43-808/909 Set] +35=TR-808 Kick +36=TR-909 Kick +37=TR-808 Rim Shot +38=TR-808 Snare +40=TR-909 Snare +41=TR-808 Low Tom 2 +42=TR-808 Closed Hat +43=TR-808 Low TOm 1 +44=TR-808 Pedal Hat +45=TR-808 Mid Tom 2 +46=TR-808 Open Hat +47=TR-808 Mid Tom 1 +48=TR-808 Hi Tom 2 +49=TR-808 Cymbal +50=TR-808 Hi Tom 1 +56=TR-808 Cowbell +62=TR-808 High Conga +63=TR-808 Mid Conga +64=TR-808 Low Conga +70=TR-808 Maracas +75=TR-808 Claves + +[GeneralUser GS 1.43-Jazz Set] +35=Kick Drum 2 +36=Kick Drum 1 +37=Side Stick +38=Snare Drum 1 +40=Snare Drum 2 +41=Low Tom 2 +43=Low Tom 1 +45=Mid Tom 2 +47=Mid Tom 1 +48=High Tom 2 +50=High Tom 1 + +[GeneralUser GS 1.43-Dance Set] +36=Dance Kick +38=Dance Snare +40=TR-909 Snare +41=Elec. Low Tom 2 +42=TR-909 Closed Hat +43=Elec. Low Tom 1 +44=TR-909 Pedal Hat +45=Elec. Mid Tom 2 +46=TR-909 Open Hat +47=Elec. Mid Tom 1 +48=Elec. Hi Tom 2 +50=Elec. Hi Tom 1 + +; ---------------------------------------------------------------------- + +.Controller Names + + +[GeneralUser GS 1.43-Controllers] +0=0-Bank Select +1=1-Modulation +5=5-Portamento time +6=6-Data Entry (MSB) +7=7-Volume +10=10-Pan +11=11-Expression +32=32-Bank Select +38=38-Data Entry (LSB) +64=64-Hold 1 +65=65-Portamento +66=66-Sostenuto +67=67-Soft +91=91-Effect1 depth (Reverb) +93=93-Effect3 depth (Chorus) +98=98-Sel. LSB/MSB +99=99-Init. LSB/MSB +100=100-RPN LSB +101=101-RPN MSB +121=121-Reset All Controllers +123=123-All Notes Off + +; ---------------------------------------------------------------------- + +.Instrument Definitions + + +[GeneralUser GS 1.43-Drumsets] +BankSelMethod=1 +Control=GeneralUser GS 1.43-Controllers +Patch[*]=GeneralUser GS 1.43-Drumsets +Key[*,1]=GeneralUser GS 1.43-Standard 2 Set +Key[*,2]=0..127 +Key[*,3]=0..127 +Key[*,4]=0..127 +Key[*,5]=0..127 +Key[*,6]=0..127 +Key[*,7]=0..127 +Key[*,8]=GeneralUser GS 1.43-Room Set +Key[*,9]=0..127 +Key[*,10]=0..127 +Key[*,11]=0..127 +Key[*,12]=0..127 +Key[*,13]=0..127 +Key[*,14]=0..127 +Key[*,15]=0..127 +Key[*,16]=GeneralUser GS 1.43-Power Set +Key[*,17]=0..127 +Key[*,18]=0..127 +Key[*,19]=0..127 +Key[*,20]=0..127 +Key[*,21]=0..127 +Key[*,22]=0..127 +Key[*,23]=0..127 +Key[*,24]=GeneralUser GS 1.43-Electronic Set +Key[*,25]=GeneralUser GS 1.43-808/909 Set +Key[*,26]=GeneralUser GS 1.43-Dance Set +Key[*,27]=0..127 +Key[*,28]=0..127 +Key[*,29]=0..127 +Key[*,30]=0..127 +Key[*,31]=0..127 +Key[*,32]=GeneralUser GS 1.43-Jazz Set +Key[*,33]=0..127 +Key[*,34]=0..127 +Key[*,35]=0..127 +Key[*,36]=0..127 +Key[*,37]=0..127 +Key[*,38]=0..127 +Key[*,39]=0..127 +Key[*,40]=GeneralUser GS 1.43-Brush Set +Key[*,41]=0..127 +Key[*,42]=0..127 +Key[*,43]=0..127 +Key[*,44]=0..127 +Key[*,45]=0..127 +Key[*,46]=0..127 +Key[*,47]=0..127 +Key[*,48]=GeneralUser GS 1.43-Orchestra Set +Key[*,49]=0..127 +Key[*,50]=0..127 +Key[*,51]=0..127 +Key[*,52]=0..127 +Key[*,53]=0..127 +Key[*,54]=0..127 +Key[*,55]=0..127 +Key[*,56]=GeneralUser GS 1.43-SFX Set +Key[*,57]=0..127 +Key[*,58]=0..127 +Key[*,59]=0..127 +Key[*,60]=0..127 +Key[*,61]=0..127 +Key[*,62]=0..127 +Key[*,63]=0..127 +Key[*,64]=0..127 +Key[*,65]=0..127 +Key[*,66]=0..127 +Key[*,67]=0..127 +Key[*,68]=0..127 +Key[*,69]=0..127 +Key[*,70]=0..127 +Key[*,71]=0..127 +Key[*,72]=0..127 +Key[*,73]=0..127 +Key[*,74]=0..127 +Key[*,75]=0..127 +Key[*,76]=0..127 +Key[*,77]=0..127 +Key[*,78]=0..127 +Key[*,79]=0..127 +Key[*,80]=0..127 +Key[*,81]=0..127 +Key[*,82]=0..127 +Key[*,83]=0..127 +Key[*,84]=0..127 +Key[*,85]=0..127 +Key[*,86]=0..127 +Key[*,87]=0..127 +Key[*,88]=0..127 +Key[*,89]=0..127 +Key[*,90]=0..127 +Key[*,91]=0..127 +Key[*,92]=0..127 +Key[*,93]=0..127 +Key[*,94]=0..127 +Key[*,95]=0..127 +Key[*,96]=0..127 +Key[*,97]=0..127 +Key[*,98]=0..127 +Key[*,99]=0..127 +Key[*,100]=0..127 +Key[*,101]=0..127 +Key[*,102]=0..127 +Key[*,103]=0..127 +Key[*,104]=0..127 +Key[*,105]=0..127 +Key[*,106]=0..127 +Key[*,107]=0..127 +Key[*,108]=0..127 +Key[*,109]=0..127 +Key[*,110]=0..127 +Key[*,111]=0..127 +Key[*,112]=0..127 +Key[*,113]=0..127 +Key[*,114]=0..127 +Key[*,115]=0..127 +Key[*,116]=0..127 +Key[*,117]=0..127 +Key[*,118]=0..127 +Key[*,119]=0..127 +Key[*,120]=0..127 +Key[*,121]=0..127 +Key[*,122]=0..127 +Key[*,123]=0..127 +Key[*,124]=0..127 +Key[*,125]=0..127 +Key[*,126]=0..127 +Key[*,127]=0..127 +Drum[*,*]=1 diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43.ins" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43.ins" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43.ins" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Cakewalk_SONAR/GeneralUser GS 1.43.ins" 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,476 @@ + +; ---------------------------------------------------------------------- + +.Patch Names + + +[GeneralUser GS 1.43-Capital Tones] +0=Stereo Grand +1=Bright Grand +2=Electric Grand +3=Honky-Tonk +4=Tine Electric Piano +5=FM Electric Piano +6=Harpsichord +7=Clavinet +8=Celeste +9=Glockenspiel +10=Music Box +11=Vibraphone +12=Marimba +13=Xylophone +14=Tubular Bells +15=Dulcimer +16=Tonewheel Organ +17=Percussive Organ +18=Rock Organ +19=Pipe Organ +20=Reed Organ +21=Accordian +22=Harmonica +23=Bandoneon +24=Nylon Guitar +25=Steel Guitar +26=Jazz Guitar +27=Clean Guitar +28=Muted Guitar +29=Overdrive Guitar +30=Distortion Guitar +31=Guitar Harmonics +32=Acoustic Bass +33=Finger Bass +34=Pick Bass +35=Fretless Bass +36=Slap Bass 1 +37=Slap Bass 2 +38=Synth Bass 1 +39=Synth Bass 2 +40=Violin +41=Viola +42=Cello +43=Double Bass +44=St. Trem. Strings +45=Pizzicato Strings +46=Orchestral Harp +47=Timpani +48=St. Strings Fast +49=St. Strings Slow +50=Synth Strings 1 +51=Synth Strings 2 +52=Concert Choir +53=Voice Oohs +54=Synth Voice +55=Orchestra Hit +56=Trumpet +57=Trombone +58=Tuba +59=Muted Trumpet +60=French Horns +61=Brass Section +62=Synth Brass 1 +63=Synth Brass 2 +64=Soprano Sax +65=Alto Sax +66=Tenor Sax +67=Baritone Sax +68=Oboe +69=English Horn +70=Bassoon +71=Clarinet +72=Piccolo +73=Flute +74=Recorder +75=Pan Flute +76=Bottle Blow +77=Shakuhachi +78=Irish Tin Whistle +79=Ocarina +80=Square Lead +81=Saw Lead +82=Synth Calliope +83=Chiffer Lead +84=Charang +85=Solo Vox +86=5th Saw Wave +87=Bass & Lead +88=Fantasia +89=Warm Pad +90=Polysynth +91=Space Voice +92=Bowed Glass +93=Metal Pad +94=Halo Pad +95=Sweep Pad +96=Ice Rain +97=Soundtrack +98=Crystal +99=Atmosphere +100=Brightness +101=Goblin +102=Echo Drops +103=Star Theme +104=Sitar +105=Banjo +106=Shamisen +107=Koto +108=Kalimba +109=Bagpipes +110=Fiddle +111=Shenai +112=Tinker Bell +113=Agogo +114=Steel Drums +115=Wood Block +116=Taiko Drum +117=Melodic Tom +118=Synth Drum +119=Reverse Cymbal +120=Fret Noise +121=Breath Noise +122=Seashore +123=Birds +124=Telephone 1 +125=Helicopter +126=Applause +127=Gun Shot + +[GeneralUser GS 1.43-Bank 1] +38=Synth Bass 101 +44=Mono Strings Trem +48=Mono Strings Fast +49=Mono Strings Slow +52=Concert Choir Mono +57=Trombone 2 +60=Solo French Horn +61=Brass Section Mono +80=Square Wave +81=Saw Wave +98=Synth Mallet +120=Cut Noise +121=Fl. Key Click +122=Rain +123=Dog +124=Telephone 2 +125=Car-Engine +126=Laughing +127=Machine Gun + +[GeneralUser GS 1.43-Bank 2] +44=St Strings 2 Trem +48=St Strings 2 Fast +49=St Strings 2 Slow +102=Echo Pan +120=String Slap +122=Thunder +123=Horse Gallop +124=Door Creaking +125=Car-Stop +126=Scream +127=Lasergun + +[GeneralUser GS 1.43-Bank 3] +122=Howling Winds +123=Bird 2 +124=Door +125=Car-Pass +126=Punch +127=Explosion + +[GeneralUser GS 1.43-Bank 4] +122=Stream +123=Scratch +125=Car-Crash +126=Heart Beat + +[GeneralUser GS 1.43-Bank 5] +122=Bubbles +124=Windchime +125=Siren +126=Footsteps + +[GeneralUser GS 1.43-Bank 6] +125=Train + +[GeneralUser GS 1.43-Bank 7] +125=Jet Plane + +[GeneralUser GS 1.43-Bank 8] +0=Stereo Grand Wet +1=Bright Grand Wet +2=Electric Grand Wet +3=Honky-Tonk Wet +4=Chorused Tine EP +5=Chorused FM EP +6=Coupled Harpsichord +11=Vibraphone Wet +12=Marimba Wet +14=Church Bells +16=Detuned Tnwl. Organ +17=Detuned Perc. Organ +19=Pipe Organ 2 +21=Italian Accordian +24=Ukulele +25=12-String Guitar +26=Hawaiian Guitar +27=Chorused Clean Gt. +28=Funk Guitar +30=Feedback Guitar +31=Guitar Feedback +38=Synth Bass 3 +39=Synth Bass 4 +48=Orchestra Pad +50=Synth Strings 3 +61=Brass Section 2 +62=Synth Brass 3 +63=Synth Brass 4 +80=Sine Wave +81=Doctor Solo +107=Taisho Koto +115=Castanets +116=Concert Bass Drum +117=Melodic Tom 2 +118=808 Tom +125=Starship + +[GeneralUser GS 1.43-Bank 9] +14=Carillon +125=Burst Noise + +[GeneralUser GS 1.43-Bank 11] +0=Piano & Str.-Fade +1=Piano & Str.-Sus +4=Tine & FM EPs +5=Piano & FM EP +8=Tinkling Bells +14=Bell Tower +38=Techno Bass +39=Pulse Bass +49=Stereo Strings Velo +50=Synth Strings 4 +51=Synth Strings 5 +61=Brass Section 3 +78=Whistlin' +81=Sawtooth Stab +87=Doctor's Solo +88=Harpsi Pad +89=Solar Wind +96=Mystery Pad +98=Synth Chime +100=Bright Saw Stack +119=Cymbal Crash +121=Filter Snap +127=Interference + +[GeneralUser GS 1.43-Bank 12] +0=Bell Piano +4=Bell Tine EP +10=Christmas Bells +27=Clean Guitar 2 +28=Mean Saw Bass +48=Full Orchestra +49=Mono Strings Velo +80=Square Lead 2 +81=Saw Lead 2 +88=Fantasia 2 +89=Solar Wind 2 +119=Tambourine +122=White Noise Wave +127=Shooting Star + +[GeneralUser GS 1.43-Bank 13] +48=Woodwind Choir +49=St Strings 2 Velo +80=Square Lead 3 +81=Saw Lead 3 +88=Night Vision + +[GeneralUser GS 1.43-Bank 16] +0=Stereo Grand Dry +4=Tine EP Wet +5=FM EP Wet +6=Harpsichord Wet +25=Mandolin + +[GeneralUser GS 1.43-Bank 120] +0=Standard Drums +1=Standard Drums 2 +8=Room Drums +16=Power Drums +24=Electronic Drums +25=808/909 Drums +26=Dance Drums +32=Jazz Drums +40=Brush Drums +48=Orchestral Perc. +56=SFX Kit + +; ---------------------------------------------------------------------- + +.Note Names + + +; ---------------------------------------------------------------------- + +.Controller Names + + +[GeneralUser GS 1.43-Controllers] +0=0-Bank Select +1=1-Modulation +5=5-Portamento time +6=6-Data Entry (MSB) +7=7-Volume +10=10-Pan +11=11-Expression +32=32-Bank Select +38=38-Data Entry (LSB) +64=64-Hold 1 +65=65-Portamento +66=66-Sostenuto +67=67-Soft +91=91-Reverb Depth +93=93-Chorus Depth +98=98-Sel. LSB/MSB +99=99-Init. LSB/MSB +100=100-RPN LSB +101=101-RPN MSB +121=121-Reset All Controllers +123=123-All Notes Off + +; ---------------------------------------------------------------------- + +.Instrument Definitions + + +[GeneralUser GS 1.43] +BankSelMethod=1 +Control=GeneralUser GS 1.43-Controllers +Patch[0]=GeneralUser GS 1.43-Capital Tones +Patch[1]=GeneralUser GS 1.43-Bank 1 +Patch[2]=GeneralUser GS 1.43-Bank 2 +Patch[3]=GeneralUser GS 1.43-Bank 3 +Patch[4]=GeneralUser GS 1.43-Bank 4 +Patch[5]=GeneralUser GS 1.43-Bank 5 +Patch[6]=GeneralUser GS 1.43-Bank 6 +Patch[7]=GeneralUser GS 1.43-Bank 7 +Patch[8]=GeneralUser GS 1.43-Bank 8 +Patch[9]=GeneralUser GS 1.43-Bank 9 +Patch[10]=0..127 +Patch[11]=GeneralUser GS 1.43-Bank 11 +Patch[12]=GeneralUser GS 1.43-Bank 12 +Patch[13]=GeneralUser GS 1.43-Bank 13 +Patch[14]=0..127 +Patch[15]=0..127 +Patch[16]=GeneralUser GS 1.43-Bank 16 +Patch[17]=0..127 +Patch[18]=0..127 +Patch[19]=0..127 +Patch[20]=0..127 +Patch[21]=0..127 +Patch[22]=0..127 +Patch[23]=0..127 +Patch[24]=0..127 +Patch[25]=0..127 +Patch[26]=0..127 +Patch[27]=0..127 +Patch[28]=0..127 +Patch[29]=0..127 +Patch[30]=0..127 +Patch[31]=0..127 +Patch[32]=0..127 +Patch[33]=0..127 +Patch[34]=0..127 +Patch[35]=0..127 +Patch[36]=0..127 +Patch[37]=0..127 +Patch[38]=0..127 +Patch[39]=0..127 +Patch[40]=0..127 +Patch[41]=0..127 +Patch[42]=0..127 +Patch[43]=0..127 +Patch[44]=0..127 +Patch[45]=0..127 +Patch[46]=0..127 +Patch[47]=0..127 +Patch[48]=0..127 +Patch[49]=0..127 +Patch[50]=0..127 +Patch[51]=0..127 +Patch[52]=0..127 +Patch[53]=0..127 +Patch[54]=0..127 +Patch[55]=0..127 +Patch[56]=0..127 +Patch[57]=0..127 +Patch[58]=0..127 +Patch[59]=0..127 +Patch[60]=0..127 +Patch[61]=0..127 +Patch[62]=0..127 +Patch[63]=0..127 +Patch[64]=0..127 +Patch[65]=0..127 +Patch[66]=0..127 +Patch[67]=0..127 +Patch[68]=0..127 +Patch[69]=0..127 +Patch[70]=0..127 +Patch[71]=0..127 +Patch[72]=0..127 +Patch[73]=0..127 +Patch[74]=0..127 +Patch[75]=0..127 +Patch[76]=0..127 +Patch[77]=0..127 +Patch[78]=0..127 +Patch[79]=0..127 +Patch[80]=0..127 +Patch[81]=0..127 +Patch[82]=0..127 +Patch[83]=0..127 +Patch[84]=0..127 +Patch[85]=0..127 +Patch[86]=0..127 +Patch[87]=0..127 +Patch[88]=0..127 +Patch[89]=0..127 +Patch[90]=0..127 +Patch[91]=0..127 +Patch[92]=0..127 +Patch[93]=0..127 +Patch[94]=0..127 +Patch[95]=0..127 +Patch[96]=0..127 +Patch[97]=0..127 +Patch[98]=0..127 +Patch[99]=0..127 +Patch[100]=0..127 +Patch[101]=0..127 +Patch[102]=0..127 +Patch[103]=0..127 +Patch[104]=0..127 +Patch[105]=0..127 +Patch[106]=0..127 +Patch[107]=0..127 +Patch[108]=0..127 +Patch[109]=0..127 +Patch[110]=0..127 +Patch[111]=0..127 +Patch[112]=0..127 +Patch[113]=0..127 +Patch[114]=0..127 +Patch[115]=0..127 +Patch[116]=0..127 +Patch[117]=0..127 +Patch[118]=0..127 +Patch[119]=0..127 +Patch[120]=GeneralUser GS 1.43-Bank 120 +Patch[121]=0..127 +Patch[122]=0..127 +Patch[123]=0..127 +Patch[124]=0..127 +Patch[125]=0..127 +Patch[126]=0..127 +Patch[127]=0..127 +Patch[*]=GeneralUser GS 1.43-Capital Tones Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/GU1.43 Percussion Map.pdf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/GU1.43 Percussion Map.pdf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Rosegarden/GeneralUser_GS_1.43.rgd and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/instrument lists/Rosegarden/GeneralUser_GS_1.43.rgd differ diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/LICENSE.txt" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/LICENSE.txt" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/LICENSE.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/LICENSE.txt" 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,25 @@ +*** GeneralUser GS v1.471 *** +*** License v2.0 *** + +** License of the complete work ** +You may use GeneralUser GS without restriction for your own music creation, private or commercial. This SoundFont bank is provided to the community free of charge. Please feel free to use it in your software projects, and to modify the SoundFont bank or its packaging to suit your needs. + +** License of contained samples ** +GeneralUser GS inherits the usage rights of the samples contained within, all of which allow full use in music production, including the ability to make profit from musical recordings created with GeneralUser GS. + +Many of the samples are original, but some were taken from other banks freely (and legally) available on the Internet from various SoundFont websites. Because GeneralUser GS originated as a personal project with no intention for publication, I cannot be 100% sure where all of the samples originated, although I do know that none of them came from commercially published SoundFont packages or sample CDs. Regardless, many "free" SoundFonts available on the web may indeed contain samples of questionable origin. My understanding of the copyrights of all samples is only as good as the information provided by the original sources. If you become aware of any restricted samples being used in GeneralUser GS, please let me know so I can replace them. + +This uncertainty may concern you if you intend to use GeneralUser GS in a commercial software product. That being said, I have never received any complaint regarding sample ownership since I published the original GeneralUser GS back in 2000, and as far as I am aware, neither have any of the companies creating commercial software products using GeneralUser GS. + +** More info ** +If you plan to feature GeneralUser GS on your own website, please do not link directly to my download files. Either link to my website, or provide your own local copy instead. + +I hope you enjoy GeneralUser GS! This SoundFont bank is the product of many years of hard work. + +You can find updates to GeneralUser GS and more of my virtual instruments at: +http://www.schristiancollins.com + +I can be reached at: s_chriscollins@hotmail.com. + +Thank you! +-~Chris diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/README.txt" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/README.txt" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/README.txt" 1970-01-01 00:00:00.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/audio/GeneralUser GS.471/README.txt" 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,41 @@ +********************************* +*** GeneralUser GS v1.471 *** +*** By S. Christian Collins *** +*** 2/7/2017 *** +********************************* + +GeneralUser GS is a GM and GS compatible SoundFont bank for composing, playing MIDI files, and retro gaming. It features 259 instrument presets and 11 drum kits, all while possessing a very low memory footprint (less than 30 MB of RAM). Due to its clever, detailed sound programming, GeneralUser GS can sound as good or better than SoundFonts that are 2-3 times its size. + +I decided on the name "GeneralUser" because the bank was designed to sound well with all kinds of music rather than specializing in only a few styles, thereby benefiting the general user. It's not a great name, but that's what I came up with almost 20 years ago, and I haven't bothered to change it. + + ++---------------+ +| Compatibility | ++---------------+ + +Although GeneralUser GS was originally designed for use with Sound Blaster audio cards, the most recent development has been focused on SoundFont-compatible software instead. The current version of GeneralUser GS requires a SoundFont synth with support for SoundFont 2.01 modulators. Compatible synths include FluidSynth 1.0.9 or later (and other software that uses FluidSynth such as Qsynth, LMMS, and ScummVM, just to name a few), MuseScore 2.0.3 or later, SynthFont2 2.0.3.0 or later, and VSTSynthFont 1.080 or later. + +While the current version of GeneralUser GS can be used with the hardware synthesizer found in many Sound Blaster audio cards, you will achieve better results using a version that was designed especially for this hardware (available at http://www.schristiancollins.com/generaluser.php). + +Most other SoundFont synths do not support all of the programming I have used in GeneralUser GS and will cause many of the presets to sound incorrect. For these unsupported SoundFont synths, you can download an older "SoftSynth" version of GeneralUser GS from my website that cuts out a lot of the special programming and is less likely to result in broken-sounding presets. + + ++--------------+ +| Installation | ++--------------+ + +Please follow your synth/sound card's documentation for instructions on loading GeneralUser GS as the default GM/GS bank. This usually requires GeneralUser GS to be loaded into bank 0, and any other SoundFonts loaded into bank 0 to be removed prior. + + ++---------------+ +| Miscellaneous | ++---------------+ + +Instrument list files are currently provided for Cakewalk SONAR (Windows) and Rosegarden (Linux) sequencers in the "instrument lists" folder. If you create an instrument list for any other sequencers, please e-mail them to me at s_chriscollins@hotmail.com and I will include them in the next release package. + +I have also provided some free MIDI files in the "demo MIDIs" folder for your listening enjoyment. Please feel free to send me more of those as well :) + +You can find updates to GeneralUser GS and more of my virtual instruments at http://www.schristiancollins.com. I can be reached at s_chriscollins@hotmail.com, but please don't send me questions that are easily answered by your sound hardware/software's documentation. I won't have time to answer every question that I receive. + +Thank you! +-~Chris Collins diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/colors.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/colors.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/colors.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/colors.dei 2018-12-11 07:08:18.000000000 +0000 @@ -40,6 +40,7 @@ } popup { + color outline { rgb $= gui.colorAlpha(text.rgb, 0.5) } info { color background { rgb <0.933, 0.933, 0.933> } color glow { rgb $= inverted.glow.rgb } @@ -79,9 +80,9 @@ log { color normal { rgb <0.85, 0.85, 0.8> } color highlight { rgb <1.0, 1.0, 1.0> } - color dimmed { + color dimmed { condition: Version.OS != 'windows' - rgb <0.65, 0.65, 0.62> + rgb <0.65, 0.65, 0.62> } color dimmed { # Apply some extra black because we don't have a Light style @@ -112,15 +113,15 @@ home { color background.tint { rgb <0.48, 0.50, 0.49> } - + color icon.shadow { rgb $= label.shadow.rgb } color icon.doom { rgb <1.0, 0.7, 0.2> } color icon.heretic { rgb <0.4, 0.7, 0.25> } color icon.hexen { rgb <1.0, 0.25, 0.1> } color icon.other { rgb <1.0, 1.0, 1.0> } - + item.background { - color selected.inverted { + color selected.inverted { rgb $= gui.colorMix(accent.rgb, text.rgb, 0.35) } } diff -Nru "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/Apache License.txt" "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/Apache License.txt" --- "/tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/Apache License.txt" 2017-10-01 00:40:13.000000000 +0000 +++ "/tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/Apache License.txt" 1970-01-01 00:00:00.000000000 +0000 @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. \ No newline at end of file diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OFL.txt doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OFL.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OFL.txt 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OFL.txt 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,92 @@ +Copyright 2010, 2012, 2014 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name ‘Source’. +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-BoldItalic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-BoldItalic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Bold.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Bold.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Italic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Italic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-LightItalic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-LightItalic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Light.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Light.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Regular.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/OpenSans-Regular.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-BoldItalic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-BoldItalic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Bold.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Bold.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Italic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Italic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-LightItalic.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-LightItalic.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Light.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Light.ttf differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Regular.ttf and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts/SourceSansPro-Regular.ttf differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/fonts.dei 2018-12-11 07:08:18.000000000 +0000 @@ -1,37 +1,41 @@ # Fonts for the default UI style # # - family: font family name -# - size can be "pt" or "px", defaults to "pt" +# - size can be "pt" or "px", defaults to "pt" # - weight: normal, bold, light # - style: normal, italic # - transform: normal, uppercase, lowercase -script { +script { import Version, gui, DisplayMode - - # Load the Open Sans font contained in this pack. - def loadOpenSans() + + # Load the fonts contained in this pack. + def loadFonts() import App fontDir = __file__.fileNamePath() / "fonts" - # Sadly, light fonts seem to not work in Qt presently. - for style in ['Regular', 'Bold', 'Italic', 'BoldItalic'] #'Light', 'LightItalic' - App.loadFont(fontDir / ("OpenSans-%s.ttf" % style)) - end + fontStyles = ['Regular', 'Bold', 'Italic', 'BoldItalic'] + # Light fonts are a bit too thin for low-res displays. + if DisplayMode.PIXEL_RATIO > 1 + fontStyles += ['Light', 'LightItalic'] + end + for style in fontStyles + App.loadFont(fontDir / ("SourceSansPro-%s.ttf" % style)) + end end } group { condition: Version.OS == 'windows' - - script { loadOpenSans() } + + script { loadFonts() } font default { - family: Open Sans + family: Source Sans Pro size: 12pt weight: normal - style: normal + style: normal } - + font monospace inherits default { family: Courier New size: 10pt @@ -39,26 +43,31 @@ } group { - condition: Version.OS == 'macx' + condition: Version.OS == 'macx' or Version.OS == 'ios' script { # Define mappings for native font styles and weights. import App + if Version.OS == 'macx' + prefix = '.SFNS' + else + prefix = '.SFUI' + end App.addFontMapping("SF UI Text", { - ['regular', 25]: '.SFNSText-Light', - ['regular', 50]: '.SFNSText-Regular', - ['regular', 75]: '.SFNSText-Bold', - ['italic', 25]: '.SFNSText-LightItalic', - ['italic', 50]: '.SFNSText-Italic', - ['italic', 75]: '.SFNSText-BoldItalic' + ['regular', 25]: prefix + 'Text-Light', + ['regular', 50]: prefix + 'Text-Regular', + ['regular', 75]: prefix + 'Text-Bold', + ['italic', 25]: prefix + 'Text-LightItalic', + ['italic', 50]: prefix + 'Text-Italic', + ['italic', 75]: prefix + 'Text-BoldItalic' }) App.addFontMapping("SF UI Display", { - ['regular', 25]: '.SFNSDisplay-Light', - ['regular', 50]: '.SFNSDisplay-Regular', - ['regular', 75]: '.SFNSDisplay-Bold', - ['italic', 25]: '.SFNSText-LightItalic', # Only non-italic available. - ['italic', 50]: '.SFNSText-Italic', - ['italic', 75]: '.SFNSText-BoldItalic' + ['regular', 25]: prefix + 'Display-Light', + ['regular', 50]: prefix + 'Display-Regular', + ['regular', 75]: prefix + 'Display-Bold', + ['italic', 25]: prefix + 'Text-LightItalic', # Only non-italic available. + ['italic', 50]: prefix + 'Text-Italic', + ['italic', 75]: prefix + 'Text-BoldItalic' }) App.addFontMapping("Menlo", { ['regular', 25]: 'Menlo-Regular', @@ -69,17 +78,17 @@ ['italic', 75]: 'Menlo-BoldItalic' }) } - + font default { family: SF UI Text - size $: gui.scale('16pt', DisplayMode.DPI_FACTOR) + size $: gui.scale('16pt', DisplayMode.PIXEL_RATIO) weight: normal style: normal } - + font monospace inherits default { family: Menlo - size $: gui.scale('12pt', DisplayMode.DPI_FACTOR) + size $: gui.scale('12pt', DisplayMode.PIXEL_RATIO) } } @@ -88,14 +97,14 @@ font default { family: Liberation Sans - size $: gui.scale("13pt", DisplayMode.DPI_FACTOR) + size $: gui.scale("13pt", DisplayMode.PIXEL_RATIO) weight: normal style: normal } font monospace inherits default { family: FreeMono - size $: gui.scale("9pt", DisplayMode.DPI_FACTOR) + size $: gui.scale("9pt", DisplayMode.PIXEL_RATIO) } } @@ -109,11 +118,11 @@ } script { - if Version.OS == 'macx' + if Version.OS == 'macx' or Version.OS == 'ios' # Use the larger variant. title.family = "SF UI Display" heading.family = "SF UI Display" - end + end } font small inherits default { @@ -143,15 +152,15 @@ size $: gui.scale(self.size, 0.5) } font label inherits default { - condition: Version.OS == 'macx' + #condition: Version.OS == 'macx' or Version.OS == 'ios' size $: gui.scale(self.size, 0.7) transform: uppercase } - font label inherits small { - condition: Version.OS != 'macx' - weight: bold - } - font annotation inherits small {} + #font label inherits small { + # condition: Version.OS != 'macx' and Version.OS != 'ios' + # weight: bold + #} + font annotation inherits small {} } choice { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/images.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/images.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/images.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/images.dei 2018-12-11 07:08:18.000000000 +0000 @@ -15,9 +15,9 @@ # With HiDPI displays use the 2x versions of the logo. group { - condition: DisplayMode.DPI_FACTOR == 2 - image px128 { path = "graphics/deng-logo-256.png" } - image px256 { path = "graphics/deng-logo-512.png" } + condition: DisplayMode.PIXEL_RATIO >= 2 + image px128 { path = "graphics/deng-logo-256.png" pointRatio = 0.5 } + image px256 { path = "graphics/deng-logo-512.png" pointRatio = 0.5 } } game { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/Info 2018-12-11 07:08:18.000000000 +0000 @@ -1,4 +1,4 @@ title: Doomsday Default UI Style -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core ui style diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/rules.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/rules.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/rules.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/defaultstyle.pack/rules.dei 2018-12-11 07:08:18.000000000 +0000 @@ -1,8 +1,7 @@ # Length rules for the default UI style script { - import DisplayMode - UNIT = 4.0 * DisplayMode.DPI_FACTOR + UNIT = 4.0 } rule unit { constant $= UNIT } @@ -26,12 +25,16 @@ document { rule progress { constant $= UNIT * 30 } + rule line.width { constant $= UNIT * 250 } rule popup.width { constant $= UNIT * 120 } } editor { rule width { constant $= UNIT * 60 } - rule completion.height { constant $= UNIT * 100 } + completion { + rule height { constant $= UNIT * 100 } + rule linewidth { constant $= UNIT * 80 } + } } progress { @@ -44,6 +47,10 @@ rule editor { constant $= UNIT * 20 } } +choice { + rule item.width.max { constant $= UNIT * 100 } +} + list { rule width { constant $= UNIT * 120 } } @@ -58,8 +65,9 @@ rule multiplayer.width { constant $= UNIT * 80 } packages { - rule left.width { constant $= UNIT * 100 } - rule right.width { constant $= UNIT * 115 } + rule left.minheight { constant $= UNIT * 40 } + rule left.width { constant $= UNIT * 100 } + rule right.width { constant $= UNIT * 115 } } packageinfo { rule content.minheight { constant $= UNIT * 100 } @@ -95,10 +103,13 @@ } home { - rule column.width { constant $= UNIT * 125 } - rule popup.width { constant $= UNIT * 175 } - rule popup.height { constant $= UNIT * 120 } - rule progress { constant $= UNIT * 60 } + rule header.logo.width { constant $= UNIT * 40 } + rule header.logo.height { constant $= UNIT * 30 } + rule column.width { constant $= UNIT * 125 } + rule column.content.width { constant $= UNIT * 100 } + rule popup.width { constant $= UNIT * 175 } + rule popup.height { constant $= UNIT * 120 } + rule progress { constant $= UNIT * 60 } } gameselection { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/Info 2018-12-11 07:08:17.000000000 +0000 @@ -1,7 +1,7 @@ # Client's primary resources title: Doomsday Client -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core client diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.de doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,80 +0,0 @@ -# DOOMSDAY CLIENT BOOTSTRAP -# -# This script is executed after the client application has been fully -# initialized, immediately after subsystems are all ready. No game is -# loaded at this stage, although all plugins have been enumerated. -# The window is not yet visible -- no GL operations can be performed. -# Config has already been loaded from persistent storage. - -import Version, App, Config, Input, SavedSession - -def bindDefaultConsoleTildeKey() - Input.bindEvent("global:key-tilde-down+key-shift-up", "taskbar") - Input.bindEvent("console:key-tilde-down+key-shift-up", "taskbar") -end - -def bindWindowsMenuKey() - Input.bindEvent("global:key-winmenu-down", "taskbar") -end - -def runLegacySavegameConversion(newGame) - if newGame == 'null-game': return - # Schedule conversion of all legacy savegames located. - # TODO: Improve this logic so that conversion tasks are done only when necessary. - SavedSession.convertAll(newGame) -end - -def runPluginLoadHooks(newGame) - if newGame == 'null-game': return - try - gameConf = Config.plugin[App.gamePlugin()] - for func in gameConf.onNextLoad: func() - # These are single-shot hooks. - gameConf.onNextLoad = [] - catch: pass -end - -def isUpgradedToBuild(number) - return Version.OLD_VERSION[3] < number and Version.BUILD >= number -end - -def addOnLoadHookForAllGames(function) - for plug in subrecords(Config.plugin).values() - plug.onNextLoad += [function] - end -end - -def upgradeMaintenance() - if not 'OLD_VERSION' in Version: return - - # Ensure that the default Tilde binding is present when upgrading - # from an older version. - if isUpgradedToBuild(920) - # Register a single-shot hook that ensures the binding is present - # after a game has been loaded the next time. This must be done - # per-plugin as the bindings are stored separately for each. - # Config is persistent so these will be remembered even after - # shutting down the app. - addOnLoadHookForAllGames(bindDefaultConsoleTildeKey) - end - - # Add the default Menu key bindings. - if isUpgradedToBuild(1479) - addOnLoadHookForAllGames(bindWindowsMenuKey) - end -end - -# -# BOOT SEQUENCE -# - -# During launch we will perform any necessary maintenance tasks. -upgradeMaintenance() - -# Whenever a game is added, we'll schedule legacy savegame conversion tasks. -App.audienceForGameAddition += [runLegacySavegameConversion] - -# Whenever a game is loaded, we'll run pending hooks. -App.audienceForGameChange += [runPluginLoadHooks] - -import controllers diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.ds doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/bootstrap.ds 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,123 @@ +# DOOMSDAY CLIENT BOOTSTRAP +# +# This script is executed after the client application has been fully +# initialized, immediately after subsystems are all ready. No game is +# loaded at this stage, although all plugins have been enumerated. +# The window is not yet visible -- no GL operations can be performed. +# Config has already been loaded from persistent storage. + +import Version, App, Config, Input, SavedSession +import utils + +def bindDefaultConsoleTildeKey() + Input.bindEvent("global:key-tilde-down+key-shift-up", "taskbar") + Input.bindEvent("console:key-tilde-down+key-shift-up", "taskbar") +end + +def bindWindowsMenuKey() + Input.bindEvent("global:key-winmenu-down", "taskbar") +end + +def runLegacySavegameConversion(newGame) + if newGame == 'null-game': return + # Schedule conversion of all legacy savegames located. + # TODO: Improve this logic so that conversion tasks are done only when necessary. + SavedSession.convertAll(newGame) +end + +def runPluginLoadHooks(newGame) + if newGame == 'null-game': return + try + gameConf = Config.plugin[App.gamePlugin()] + for func in gameConf.onNextLoad: func() + # These are single-shot hooks. + gameConf.onNextLoad = [] + catch: pass +end + +def isUpgradedToBuild(number) + return Version.OLD_VERSION[3] < number and Version.BUILD >= number +end + +def addOnLoadHookForAllGames(function) + for plug in subrecords(Config.plugin).values() + plug.onNextLoad += [function] + end +end + +def cleanPackageFolders() + # Config.resource.iwadFolder was used previously for IWADs + # (non-recursive), but now everything can be put in + # Config.resource.packageFolder and recursing is specified + # separately. + try + res = Config.resource + if res.iwadFolder + res.packageFolder = utils.makeArray(res.packageFolder) + folders = utils.makeArray(res.iwadFolder) + print 'Cleaning up IWAD folders:', folders + for folder in folders + res.recursedFolders[folder] = False + if not folder in res.packageFolder + res.packageFolder = [folder] + res.packageFolder + end + end + res.iwadFolder = '' + import FS + FS.refreshPackageFolders() + end + catch Error, er + print "Problem in cleanPackageFolders:", er + end +end + +def upgradeMaintenance() + if not 'OLD_VERSION' in Version: return + + # Ensure that the default Tilde binding is present when upgrading + # from an older version. + if isUpgradedToBuild(920) + # Register a single-shot hook that ensures the binding is present + # after a game has been loaded the next time. This must be done + # per-plugin as the bindings are stored separately for each. + # Config is persistent so these will be remembered even after + # shutting down the app. + addOnLoadHookForAllGames(bindDefaultConsoleTildeKey) + end + + # Add the default Menu key bindings. + if isUpgradedToBuild(1479) + addOnLoadHookForAllGames(bindWindowsMenuKey) + end + + cleanPackageFolders() +end + +def cacheDataFiles() + # Make an unzipped copy of the default soundfont, if it is missing. + cacheFolder = File('/home/cache') + sf2Name = 'default.sf2' + if not cacheFolder.locate(sf2Name) + dest = cacheFolder.replace(sf2Name) + dest.write(File('/packs/net.dengine.client/audio/GeneralUser GS.471/GeneralUser GS v1.471.sf2').read()) + dest.flush() + end +end + +# +# BOOT SEQUENCE +# + +# During launch we will perform any necessary maintenance tasks. +upgradeMaintenance() + +# Make native copies of data files. +cacheDataFiles() + +# Whenever a game is added, we'll schedule legacy savegame conversion tasks. +App.audienceForGameAddition += [runLegacySavegameConversion] + +# Whenever a game is loaded, we'll run pending hooks. +App.audienceForGameChange += [runPluginLoadHooks] + +import controllers diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.de doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,134 +0,0 @@ -# The Doomsday Engine Project -- Doomsday Client -# -# Copyright (c) 2013-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# CONFIGURATION FOR THE DOOMSDAY CLIENT -# -# This module contains configuration related scripts for the client -# application. It is automatically imported by Config and used as needed. - -import gui -import Version -import Updater -import Log - -def setDefaults(d) - # Applies the client's defaults. - # - d: Record where to set the values. - - gui.setDefaults(d) - - # Additional Log defaults. - d.log.filterBySubsystem = False - d.log.showMetadata = False - - record d.alert() - generic = Log.WARNING - resource = Log.WARNING - map = Log.WARNING - script = Log.WARNING - gl = Log.WARNING - audio = Log.WARNING - input = Log.WARNING - network = Log.WARNING - - # Alert notification dismissed after 3 minutes by default. - autoHide = 3 * 60 - end - - # Home. - record d.home() - showUnplayableGames = True - showColumnDescription = True - record columns() - doom = True - heretic = True - hexen = True - otherGames = True - multiplayer = True - end - end - - # Input defaults. - record d.input() - record mouse - mouse.syncSensitivity = True - end - - # Defaults for the automatic updater. - record d.updater() - frequency = Updater.WEEKLY - if Version.STABLE - channel = Updater.CHANNEL_STABLE - else - channel = Updater.CHANNEL_UNSTABLE - end - lastChecked = Time("") - onlyManually = (Version.OS == 'unix') - autoDownload = False - delete = True - downloadPath = "${DEFAULT}" - deleteAtStartup = "" - end - - # Console defaults. - record d.console() - snap = True - script = False - end - - # Resource settings. - record d.resource() - # Local packaegs are disabled by default in MP games. - localPackages = False - localPackagesForGame = {} - # Textures. - noHighResTex = False - noHighResPatches = False - highResWithPWAD = True - end - - # Renderer settings. - record d.render() - pixelDensity = 1.0 # Overall pixel density. - - # LensFx settings. - record fx - record fx.resize - fx.resize.factor = 1.0 - end - - # VR/3D settings. - record d.vr() - record oculusRift - oculusRift.pixelDensity = 1.0 - end - - # Audio settings. - record d.audio() - soundPlugin = 'fmod' - if Version.OS == 'macx' - musicPlugin = 'fluidsynth' - cdPlugin = 'dummy' - else - musicPlugin = 'fmod' - cdPlugin = 'fmod' - end - record fmod - fmod.speakerMode = '' # defaults to stereo - end -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.ds doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/clientconfig.ds 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,143 @@ +# The Doomsday Engine Project -- Doomsday Client +# +# Copyright (c) 2013-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# CONFIGURATION FOR THE DOOMSDAY CLIENT +# +# This module contains configuration related scripts for the client +# application. It is automatically imported by Config and used as needed. + +import gui +import Version +import Updater +import Log + +def setDefaults(d) + # Applies the client's defaults. + # - d: Record where to set the values. + + gui.setDefaults(d) + + # Additional Log defaults. + d.log.filterBySubsystem = False + d.log.showMetadata = False + + record d.alert() + generic = Log.WARNING + resource = Log.WARNING + map = Log.WARNING + script = Log.WARNING + gl = Log.WARNING + audio = Log.WARNING + input = Log.WARNING + network = Log.WARNING + + # Alert notification dismissed after 3 minutes by default. + autoHide = 3 * 60 + end + + # Home. + record d.home() + showUnplayableGames = True + showColumnDescription = True + sortBy = 'release' + sortAscending = True + sortCustomSeparately = True + record columns() + doom = True + heretic = True + hexen = True + otherGames = True + multiplayer = True + end + end + + # Input defaults. + record d.input() + record mouse + mouse.syncSensitivity = True + end + + # Defaults for the automatic updater. + record d.updater() + frequency = Updater.WEEKLY + if Version.STABLE + channel = Updater.CHANNEL_STABLE + else + channel = Updater.CHANNEL_UNSTABLE + end + lastChecked = Time("") + onlyManually = (Version.OS == 'unix') + autoDownload = False + delete = True + downloadPath = "${DEFAULT}" + deleteAtStartup = "" + end + + # Console defaults. + record d.console() + snap = True + script = False + end + + # Resource settings. + record d.resource() + browserRepository = 'idgames mirror (Idaho, USA)' + + # Local packages are disabled by default in MP games. + localPackages = False + localPackagesForGame = {} + + # Textures. + noHighResTex = False + noHighResPatches = False + highResWithPWAD = True + end + + # Renderer settings. + record d.render() + pixelDensity = 1.0 # Overall pixel density. + + # LensFx settings. + record fx + record fx.resize + fx.resize.factor = 1.0 + end + + # VR/3D settings. + record d.vr() + record oculusRift + oculusRift.pixelDensity = 1.0 + end + + # Audio settings. + record d.audio() + output = 0 + channels = 16 + soundPlugin = 'fmod' + musicPlugin = 'fluidsynth' + cdPlugin = 'dummy' + if Version.OS == 'windows' + cdPlugin = 'winmm' + elsif Version.OS == 'ios' + musicPlugin = 'fmod' + end + record fmod + fmod.speakerMode = '' # defaults to stereo + pauseOnFocus = True + end +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.de doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,404 +0,0 @@ -# Gamepad Controller Presets - -import App, Input, Console, Version - -def event(context, button, command, repeat=False, condition=None) - # Bind an event to a console command. - if condition: condition = ' + ' + condition - else: condition = '' - if 'hat' in button - Input.bindEvent('%s:%s%s' % [context, button, condition], command) - else - Input.bindEvent('%s:%s-down%s' % [context, button, condition], command) - if repeat: Input.bindEvent('%s:%s-repeat%s' % [context, button, condition], command) - end -end - -def control(ctl, impulse, inverse=False, condition=None) - # Bind a control to a player impulse. - if inverse: ctl += '-inverse' - if condition: ctl += ' + ' + condition - Input.bindControl(ctl, 'local1-%s' % impulse) -end - -record Gamepad() - def __init__(id, regex) - # Arguments: - # id: Identifier of the controller. - # regex: One or more regexes (Text, or Array of Texts) - # for matching against the joystick name. - self.id = id - self.regex = regex - end - - def bind(); end - - def register() - regs = self.regex - if typeof(regs) != 'Array': regs = [regs] - for reg in regs - Input.controllerPresets[reg] = Record(self) - end - end - - def resetDeadzones() - for var in Console.listVars('input-joy-.*-deadzone') - Console.set(var, Input.DEFAULT_STICK_DEADZONE) - end - for var in Console.listVars('input-joy-.*-factor') - Console.set(var, Input.DEFAULT_STICK_FACTOR) - end - for var in Console.listVars('input-joy-.*-offset') - Console.set(var, 0) - end - end -end - -record GenericGamepad(Gamepad) - def __init__(): self.Gamepad->__init__('Generic', '') - def bind() - print 'Bindings for GenericGamePad:', self.id - self.resetDeadzones() - end -end - -record PS3Gamepad(Gamepad) - def __init__(id, regex): self.Gamepad->__init__(id, regex) - def bind() - # Names for buttons and other controls. - x = 'joy-button15' - o = 'joy-button14' - tri = 'joy-button13' - sqr = 'joy-button16' - play = 'joy-button4' - select = 'joy-button1' - leftPress = 'joy-button2' - rightPress = 'joy-button3' - up = 'joy-button5' - down = 'joy-button7' - left = 'joy-button8' - right = 'joy-button6' - L1 = 'joy-button11' - L2 = 'joy-button9' - R1 = 'joy-button12' - R2 = 'joy-button10' - leftHoriz = 'joy-x' - leftVert = 'joy-y' - rightHoriz = 'joy-z' - rightVert = 'joy-w' - - # Common controls, suitable for all games. - event('shortcut', play, 'menu') - - event('menu', o, 'menuback') - event('menu', x, 'menuselect') - event('menu', up, 'menuup', repeat=True) - event('menu', down, 'menudown', repeat=True) - event('menu', left, 'menuleft', repeat=True) - event('menu', right, 'menuright', repeat=True) - - event('game', L1, 'pause') - event('game', o, 'impulse jump') - event('game', sqr, 'impulse use') - event('game', up, 'impulse nextweapon') - event('game', down, 'impulse prevweapon') - event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') - event('game', select, 'impulse automap') - - control(R1, 'flymode') # modifier 2 - control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') - event('game', rightPress, 'impulse falldown', condition='modifier-2-down') - - control(leftHoriz, 'sidestep') - control(leftVert, 'walk', inverse=True) - control(rightHoriz, 'turn') - control(rightVert, 'look', inverse=True, condition='modifier-2-up') - control(x, 'attack') - control(R2, 'attack') - control(L2, 'speed') - - event('map', rightPress, 'impulse follow') - event('map', leftPress, 'impulse rotate') - - control(rightHoriz, 'mappanx') - control(rightVert, 'mappany', inverse=True) - control(R2, 'mapzoom') - control(R1, 'mapzoom', inverse=True) - - # Inventory controls for Heretic and Hexen. - if App.gamePlugin() in ['heretic', 'hexen'] - event('game', left, 'impulse previtem') - event('game', right, 'impulse nextitem') - event('game', tri, 'impulse useitem') - end - - self.resetDeadzones() - - # Deadzones. - for axis in ['x', 'y', 'z', 'w'] - Console.set('input-joy-%s-deadzone' % axis, 0.15) - end - end -end - -record PS4Gamepad(Gamepad) - def __init__(id, regex): self.Gamepad->__init__(id, regex) - def bind() - # Names for buttons and other controls. - sqr = 'joy-button1' - x = 'joy-button2' - o = 'joy-button3' - tri = 'joy-button4' - pad = 'joy-button14' - options = 'joy-button10' - share = 'joy-button9' - ps = 'joy-button13' - leftPress = 'joy-button11' - rightPress = 'joy-button12' - up = 'joy-hat1-angle0' - down = 'joy-hat1-angle4' - left = 'joy-hat1-angle6' - right = 'joy-hat1-angle2' - L1 = 'joy-button5' - R1 = 'joy-button6' - L2 = 'joy-button7' - R2 = 'joy-button8' - leftHoriz = 'joy-x' - leftVert = 'joy-y' - rightHoriz = 'joy-z' - rightVert = 'joy-axis06' - - # Common controls, suitable for all games. - event('shortcut', options, 'menu') - - event('menu', o, 'menuback') - event('menu', x, 'menuselect') - event('menu', up, 'menuup', repeat=True) - event('menu', down, 'menudown', repeat=True) - event('menu', left, 'menuleft', repeat=True) - event('menu', right, 'menuright', repeat=True) - - event('game', L1, 'pause') - event('game', o, 'impulse jump') - event('game', sqr, 'impulse use') - event('game', up, 'impulse nextweapon') - event('game', down, 'impulse prevweapon') - event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') - event('game', pad, 'impulse automap') - - control(R1, 'flymode') # modifier 2 - control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') - event('game', rightPress, 'impulse falldown', condition='modifier-2-down') - - control(leftHoriz, 'sidestep') - control(leftVert, 'walk', inverse=True) - control(rightHoriz, 'turn') - control(rightVert, 'look', inverse=True, condition='modifier-2-up') - control(x, 'attack') - control(R2, 'attack') - control(L2, 'speed') - - event('map', rightPress, 'impulse follow') - event('map', leftPress, 'impulse rotate') - - control(rightHoriz, 'mappanx') - control(rightVert, 'mappany', inverse=True) - control(R2, 'mapzoom') - control(R1, 'mapzoom', inverse=True) - - # Inventory controls for Heretic and Hexen. - if App.gamePlugin() in ['heretic', 'hexen'] - event('game', left, 'impulse previtem') - event('game', right, 'impulse nextitem') - event('game', tri, 'impulse useitem') - end - - self.resetDeadzones() - - # Deadzones. - for axis in ['x', 'y', 'z', 'axis06'] - Console.set('input-joy-%s-deadzone' % axis, 0.15) - end - end -end - -record XboxWindowsGamepad(Gamepad) - # Xbox One controller with default Windows game controller setup. - def __init__(id, regex): self.Gamepad->__init__(id, regex) - def bind() - # Names for buttons and other controls. - a = 'joy-button1' - b = 'joy-button2' - x = 'joy-button3' - y = 'joy-button4' - leftPress = 'joy-button9' - rightPress = 'joy-button10' - menu = 'joy-button8' - view = 'joy-button7' - up = 'joy-hat1-angle0' - down = 'joy-hat1-angle4' - left = 'joy-hat1-angle6' - right = 'joy-hat1-angle2' - LB = 'joy-button5' - RB = 'joy-button6' - thruster = 'joy-z' - leftHoriz = 'joy-x' - leftVert = 'joy-y' - rightHoriz = 'joy-w' - rightVert = 'joy-axis05' - - # Common controls, suitable for all games. - event('shortcut', menu, 'menu') - - event('menu', b, 'menuback') - event('menu', a, 'menuselect') - event('menu', up, 'menuup', repeat=True) - event('menu', down, 'menudown', repeat=True) - event('menu', left, 'menuleft', repeat=True) - event('menu', right, 'menuright', repeat=True) - - event('game', leftPress, 'pause') - event('game', view, 'impulse automap') - event('game', b, 'impulse jump') - event('game', x, 'impulse use') - event('game', up, 'impulse nextweapon') - event('game', down, 'impulse prevweapon') - event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') - - control(RB, 'flymode') # modifier 2 - control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') - event('game', rightPress, 'impulse falldown', condition='modifier-2-down') - - control(leftHoriz, 'sidestep') - control(leftVert, 'walk', inverse=True) - control(rightHoriz, 'turn') - control(rightVert, 'look', inverse=True, condition='modifier-2-up') - control(a, 'attack') - control(thruster, 'attack') - control(LB, 'speed') - - event('map', rightPress, 'impulse follow') - event('map', leftPress, 'impulse rotate') - - control(rightHoriz, 'mappanx') - control(rightVert, 'mappany', inverse=True) - control(thruster, 'mapzoom') - #control(RB, 'mapzoom', inverse=True) - - # Inventory controls for Heretic and Hexen. - if App.gamePlugin() in ['heretic', 'hexen'] - event('game', left, 'impulse previtem') - event('game', right, 'impulse nextitem') - event('game', y, 'impulse useitem') - end - - self.resetDeadzones() - - # Deadzones. - for axis in ['x', 'y', 'w', 'axis05'] - Console.set('input-joy-%s-deadzone' % axis, 0.15) - end - end -end - -record XboxMacGamepad(Gamepad) - # Configures presets suitable for the Xbox One controller used with - # the "360Controller" driver on macOS (driver defaults): - # https://github.com/360Controller/360Controller - def __init__(id, regex): self.Gamepad->__init__(id, regex) - def bind() - # Names for buttons and other controls. - a = 'joy-button1' - b = 'joy-button2' - x = 'joy-button3' - y = 'joy-button4' - leftPress = 'joy-button7' - rightPress = 'joy-button8' - menu = 'joy-button9' - view = 'joy-button10' - xbox = 'joy-button11' - up = 'joy-button12' - down = 'joy-button13' - left = 'joy-button14' - right = 'joy-button15' - LB = 'joy-button5' - RB = 'joy-button6' - LT = 'joy-z' - RT = 'joy-axis06' - leftHoriz = 'joy-x' - leftVert = 'joy-y' - rightHoriz = 'joy-w' - rightVert = 'joy-axis05' - - # Common controls, suitable for all games. - event('shortcut', menu, 'menu') - event('shortcut', xbox, 'menu') - - event('menu', b, 'menuback') - event('menu', a, 'menuselect') - event('menu', up, 'menuup', repeat=True) - event('menu', down, 'menudown', repeat=True) - event('menu', left, 'menuleft', repeat=True) - event('menu', right, 'menuright', repeat=True) - - event('game', LB, 'pause') - event('game', view, 'impulse automap') - event('game', b, 'impulse jump') - event('game', x, 'impulse use') - event('game', up, 'impulse nextweapon') - event('game', down, 'impulse prevweapon') - event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') - - control(RB, 'flymode') # modifier 2 - control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') - event('game', rightPress, 'impulse falldown', condition='modifier-2-down') - - control(leftHoriz, 'sidestep') - control(leftVert, 'walk', inverse=True) - control(rightHoriz, 'turn') - control(rightVert, 'look', inverse=True, condition='modifier-2-up') - control(a, 'attack') - control(RT, 'attack') - control(LT, 'speed') - - event('map', rightPress, 'impulse follow') - event('map', leftPress, 'impulse rotate') - - control(rightHoriz, 'mappanx') - control(rightVert, 'mappany', inverse=True) - control(RT, 'mapzoom') - control(RB, 'mapzoom', inverse=True) - - # Inventory controls for Heretic and Hexen. - if App.gamePlugin() in ['heretic', 'hexen'] - event('game', left, 'impulse previtem') - event('game', right, 'impulse nextitem') - event('game', y, 'impulse useitem') - end - - self.resetDeadzones() - - # Deadzones. - for axis in ['x', 'y', 'w', 'axis05'] - Console.set('input-joy-%s-deadzone' % axis, 0.15) - end - - # Thrusters are stick axes, but we want them to go from 0 to 1. - Console.set('input-%s-factor' % LT, Input.DEFAULT_STICK_FACTOR/2) - Console.set('input-%s-offset' % LT, 0.5) - Console.set('input-%s-factor' % RT, Input.DEFAULT_STICK_FACTOR/2) - Console.set('input-%s-offset' % RT, 0.5) - end -end - -# Platform-independent controllers: -GenericGamepad().register() -PS3Gamepad('PS3', ['PLAYSTATION\(R\)3 Controller']).register() -PS4Gamepad('PS4', ['Wireless Controller']).register() - -# Platform-specific configs: -if Version.OS == 'windows' - XboxWindowsGamepad('Xbox One', ['.*Xbox One For Windows.*']).register() -elsif Version.OS == 'macx' - XboxMacGamepad('Xbox One/360 (360Controller)', ['.*Xbox (360|One).*']).register() -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.ds doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/controllers.ds 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,404 @@ +# Gamepad Controller Presets + +import App, Input, Console, Version + +def event(context, button, command, repeat=False, condition=None) + # Bind an event to a console command. + if condition: condition = ' + ' + condition + else: condition = '' + if 'hat' in button + Input.bindEvent('%s:%s%s' % [context, button, condition], command) + else + Input.bindEvent('%s:%s-down%s' % [context, button, condition], command) + if repeat: Input.bindEvent('%s:%s-repeat%s' % [context, button, condition], command) + end +end + +def control(ctl, impulse, inverse=False, condition=None) + # Bind a control to a player impulse. + if inverse: ctl += '-inverse' + if condition: ctl += ' + ' + condition + Input.bindControl(ctl, 'local1-%s' % impulse) +end + +record Gamepad() + def __init__(id, regex) + # Arguments: + # id: Identifier of the controller. + # regex: One or more regexes (Text, or Array of Texts) + # for matching against the joystick name. + self.id = id + self.regex = regex + end + + def bind(); end + + def register() + regs = self.regex + if typeof(regs) != 'Array': regs = [regs] + for reg in regs + Input.controllerPresets[reg] = Record(self) + end + end + + def resetDeadzones() + for var in Console.listVars('input-joy-.*-deadzone') + Console.set(var, Input.DEFAULT_STICK_DEADZONE) + end + for var in Console.listVars('input-joy-.*-factor') + Console.set(var, Input.DEFAULT_STICK_FACTOR) + end + for var in Console.listVars('input-joy-.*-offset') + Console.set(var, 0) + end + end +end + +record GenericGamepad(Gamepad) + def __init__(): self.Gamepad->__init__('Generic', '') + def bind() + print 'Bindings for GenericGamePad:', self.id + self.resetDeadzones() + end +end + +record PS3Gamepad(Gamepad) + def __init__(id, regex): self.Gamepad->__init__(id, regex) + def bind() + # Names for buttons and other controls. + x = 'joy-button15' + o = 'joy-button14' + tri = 'joy-button13' + sqr = 'joy-button16' + play = 'joy-button4' + select = 'joy-button1' + leftPress = 'joy-button2' + rightPress = 'joy-button3' + up = 'joy-button5' + down = 'joy-button7' + left = 'joy-button8' + right = 'joy-button6' + L1 = 'joy-button11' + L2 = 'joy-button9' + R1 = 'joy-button12' + R2 = 'joy-button10' + leftHoriz = 'joy-x' + leftVert = 'joy-y' + rightHoriz = 'joy-z' + rightVert = 'joy-w' + + # Common controls, suitable for all games. + event('shortcut', play, 'menu') + + event('menu', o, 'menuback') + event('menu', x, 'menuselect') + event('menu', up, 'menuup', repeat=True) + event('menu', down, 'menudown', repeat=True) + event('menu', left, 'menuleft', repeat=True) + event('menu', right, 'menuright', repeat=True) + + event('game', L1, 'pause') + event('game', o, 'impulse jump') + event('game', sqr, 'impulse use') + event('game', up, 'impulse nextweapon') + event('game', down, 'impulse prevweapon') + event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') + event('game', select, 'impulse automap') + + control(R1, 'flymode') # modifier 2 + control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') + event('game', rightPress, 'impulse falldown', condition='modifier-2-down') + + control(leftHoriz, 'sidestep') + control(leftVert, 'walk', inverse=True) + control(rightHoriz, 'turn') + control(rightVert, 'look', inverse=True, condition='modifier-2-up') + control(x, 'attack') + control(R2, 'attack') + control(L2, 'speed') + + event('map', rightPress, 'impulse follow') + event('map', leftPress, 'impulse rotate') + + control(rightHoriz, 'mappanx') + control(rightVert, 'mappany', inverse=True) + control(R2, 'mapzoom') + control(R1, 'mapzoom', inverse=True) + + # Inventory controls for Heretic and Hexen. + if App.gamePlugin() in ['heretic', 'hexen'] + event('game', left, 'impulse previtem') + event('game', right, 'impulse nextitem') + event('game', tri, 'impulse useitem') + end + + self.resetDeadzones() + + # Deadzones. + for axis in ['x', 'y', 'z', 'w'] + Console.set('input-joy-%s-deadzone' % axis, 0.15) + end + end +end + +record PS4Gamepad(Gamepad) + def __init__(id, regex): self.Gamepad->__init__(id, regex) + def bind() + # Names for buttons and other controls. + sqr = 'joy-button1' + x = 'joy-button2' + o = 'joy-button3' + tri = 'joy-button4' + pad = 'joy-button14' + options = 'joy-button10' + share = 'joy-button9' + ps = 'joy-button13' + leftPress = 'joy-button11' + rightPress = 'joy-button12' + up = 'joy-hat1-angle0' + down = 'joy-hat1-angle4' + left = 'joy-hat1-angle6' + right = 'joy-hat1-angle2' + L1 = 'joy-button5' + R1 = 'joy-button6' + L2 = 'joy-button7' + R2 = 'joy-button8' + leftHoriz = 'joy-x' + leftVert = 'joy-y' + rightHoriz = 'joy-z' + rightVert = 'joy-axis06' + + # Common controls, suitable for all games. + event('shortcut', options, 'menu') + + event('menu', o, 'menuback') + event('menu', x, 'menuselect') + event('menu', up, 'menuup', repeat=True) + event('menu', down, 'menudown', repeat=True) + event('menu', left, 'menuleft', repeat=True) + event('menu', right, 'menuright', repeat=True) + + event('game', L1, 'pause') + event('game', o, 'impulse jump') + event('game', sqr, 'impulse use') + event('game', up, 'impulse nextweapon') + event('game', down, 'impulse prevweapon') + event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') + event('game', pad, 'impulse automap') + + control(R1, 'flymode') # modifier 2 + control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') + event('game', rightPress, 'impulse falldown', condition='modifier-2-down') + + control(leftHoriz, 'sidestep') + control(leftVert, 'walk', inverse=True) + control(rightHoriz, 'turn') + control(rightVert, 'look', inverse=True, condition='modifier-2-up') + control(x, 'attack') + control(R2, 'attack') + control(L2, 'speed') + + event('map', rightPress, 'impulse follow') + event('map', leftPress, 'impulse rotate') + + control(rightHoriz, 'mappanx') + control(rightVert, 'mappany', inverse=True) + control(R2, 'mapzoom') + control(R1, 'mapzoom', inverse=True) + + # Inventory controls for Heretic and Hexen. + if App.gamePlugin() in ['heretic', 'hexen'] + event('game', left, 'impulse previtem') + event('game', right, 'impulse nextitem') + event('game', tri, 'impulse useitem') + end + + self.resetDeadzones() + + # Deadzones. + for axis in ['x', 'y', 'z', 'axis06'] + Console.set('input-joy-%s-deadzone' % axis, 0.15) + end + end +end + +record XboxWindowsGamepad(Gamepad) + # Xbox One controller with default Windows game controller setup. + def __init__(id, regex): self.Gamepad->__init__(id, regex) + def bind() + # Names for buttons and other controls. + a = 'joy-button1' + b = 'joy-button2' + x = 'joy-button3' + y = 'joy-button4' + leftPress = 'joy-button9' + rightPress = 'joy-button10' + menu = 'joy-button8' + view = 'joy-button7' + up = 'joy-hat1-angle0' + down = 'joy-hat1-angle4' + left = 'joy-hat1-angle6' + right = 'joy-hat1-angle2' + LB = 'joy-button5' + RB = 'joy-button6' + thruster = 'joy-z' + leftHoriz = 'joy-x' + leftVert = 'joy-y' + rightHoriz = 'joy-w' + rightVert = 'joy-axis05' + + # Common controls, suitable for all games. + event('shortcut', menu, 'menu') + + event('menu', b, 'menuback') + event('menu', a, 'menuselect') + event('menu', up, 'menuup', repeat=True) + event('menu', down, 'menudown', repeat=True) + event('menu', left, 'menuleft', repeat=True) + event('menu', right, 'menuright', repeat=True) + + event('game', leftPress, 'pause') + event('game', view, 'impulse automap') + event('game', b, 'impulse jump') + event('game', x, 'impulse use') + event('game', up, 'impulse nextweapon') + event('game', down, 'impulse prevweapon') + event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') + + control(RB, 'flymode') # modifier 2 + control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') + event('game', rightPress, 'impulse falldown', condition='modifier-2-down') + + control(leftHoriz, 'sidestep') + control(leftVert, 'walk', inverse=True) + control(rightHoriz, 'turn') + control(rightVert, 'look', inverse=True, condition='modifier-2-up') + control(a, 'attack') + control(thruster, 'attack') + control(LB, 'speed') + + event('map', rightPress, 'impulse follow') + event('map', leftPress, 'impulse rotate') + + control(rightHoriz, 'mappanx') + control(rightVert, 'mappany', inverse=True) + control(thruster, 'mapzoom') + #control(RB, 'mapzoom', inverse=True) + + # Inventory controls for Heretic and Hexen. + if App.gamePlugin() in ['heretic', 'hexen'] + event('game', left, 'impulse previtem') + event('game', right, 'impulse nextitem') + event('game', y, 'impulse useitem') + end + + self.resetDeadzones() + + # Deadzones. + for axis in ['x', 'y', 'w', 'axis05'] + Console.set('input-joy-%s-deadzone' % axis, 0.15) + end + end +end + +record XboxMacGamepad(Gamepad) + # Configures presets suitable for the Xbox One controller used with + # the "360Controller" driver on macOS (driver defaults): + # https://github.com/360Controller/360Controller + def __init__(id, regex): self.Gamepad->__init__(id, regex) + def bind() + # Names for buttons and other controls. + a = 'joy-button1' + b = 'joy-button2' + x = 'joy-button3' + y = 'joy-button4' + leftPress = 'joy-button7' + rightPress = 'joy-button8' + menu = 'joy-button9' + view = 'joy-button10' + xbox = 'joy-button11' + up = 'joy-button12' + down = 'joy-button13' + left = 'joy-button14' + right = 'joy-button15' + LB = 'joy-button5' + RB = 'joy-button6' + LT = 'joy-z' + RT = 'joy-axis06' + leftHoriz = 'joy-x' + leftVert = 'joy-y' + rightHoriz = 'joy-w' + rightVert = 'joy-axis05' + + # Common controls, suitable for all games. + event('shortcut', menu, 'menu') + event('shortcut', xbox, 'menu') + + event('menu', b, 'menuback') + event('menu', a, 'menuselect') + event('menu', up, 'menuup', repeat=True) + event('menu', down, 'menudown', repeat=True) + event('menu', left, 'menuleft', repeat=True) + event('menu', right, 'menuright', repeat=True) + + event('game', LB, 'pause') + event('game', view, 'impulse automap') + event('game', b, 'impulse jump') + event('game', x, 'impulse use') + event('game', up, 'impulse nextweapon') + event('game', down, 'impulse prevweapon') + event('game', rightPress, 'impulse lookcenter', condition='modifier-2-up') + + control(RB, 'flymode') # modifier 2 + control(rightVert, 'zfly', inverse=True, condition='modifier-2-down') + event('game', rightPress, 'impulse falldown', condition='modifier-2-down') + + control(leftHoriz, 'sidestep') + control(leftVert, 'walk', inverse=True) + control(rightHoriz, 'turn') + control(rightVert, 'look', inverse=True, condition='modifier-2-up') + control(a, 'attack') + control(RT, 'attack') + control(LT, 'speed') + + event('map', rightPress, 'impulse follow') + event('map', leftPress, 'impulse rotate') + + control(rightHoriz, 'mappanx') + control(rightVert, 'mappany', inverse=True) + control(RT, 'mapzoom') + control(RB, 'mapzoom', inverse=True) + + # Inventory controls for Heretic and Hexen. + if App.gamePlugin() in ['heretic', 'hexen'] + event('game', left, 'impulse previtem') + event('game', right, 'impulse nextitem') + event('game', y, 'impulse useitem') + end + + self.resetDeadzones() + + # Deadzones. + for axis in ['x', 'y', 'w', 'axis05'] + Console.set('input-joy-%s-deadzone' % axis, 0.15) + end + + # Thrusters are stick axes, but we want them to go from 0 to 1. + Console.set('input-%s-factor' % LT, Input.DEFAULT_STICK_FACTOR/2) + Console.set('input-%s-offset' % LT, 0.5) + Console.set('input-%s-factor' % RT, Input.DEFAULT_STICK_FACTOR/2) + Console.set('input-%s-offset' % RT, 0.5) + end +end + +# Platform-independent controllers: +GenericGamepad().register() +PS3Gamepad('PS3', ['PLAYSTATION\(R\)3 Controller']).register() +PS4Gamepad('PS4', ['Wireless Controller']).register() + +# Platform-specific configs: +if Version.OS == 'windows' + XboxWindowsGamepad('Xbox One', ['.*Xbox One For Windows.*']).register() +elsif Version.OS == 'macx' + XboxMacGamepad('Xbox One/360 (360Controller)', ['.*Xbox (360|One).*']).register() +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.de doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,33 +0,0 @@ -# The Doomsday Engine Project -- Doomsday Client -# -# Copyright (c) 2014-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# UPDATER -# -# This module provides access to the built-in automatic updater of the -# Doomsday Client. - -# Update frequency. -const DAILY = 0 -const BIWEEKLY = 1 -const WEEKLY = 2 -const MONTHLY = 3 -const AT_STARTUP = 4 - -# Update release channel. -const CHANNEL_STABLE = 0 -const CHANNEL_UNSTABLE = 1 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.ds doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/modules/Updater.ds 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,33 @@ +# The Doomsday Engine Project -- Doomsday Client +# +# Copyright (c) 2014-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# UPDATER +# +# This module provides access to the built-in automatic updater of the +# Doomsday Client. + +# Update frequency. +const DAILY = 0 +const BIWEEKLY = 1 +const WEEKLY = 2 +const MONTHLY = 3 +const AT_STARTUP = 4 + +# Update release channel. +const CHANNEL_STABLE = 0 +const CHANNEL_UNSTABLE = 1 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/Info 2018-12-11 07:08:18.000000000 +0000 @@ -1,6 +1,6 @@ # General resources for the renderer title: Doomsday Renderer -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/Info 2018-12-11 07:08:18.000000000 +0000 @@ -1,5 +1,5 @@ title: Doomsday Default Lens Flares -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core fx diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders/lensflares.vsh doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders/lensflares.vsh --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders/lensflares.vsh 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders/lensflares.vsh 2018-12-11 07:08:18.000000000 +0000 @@ -1,35 +1,35 @@ -uniform highp mat4 uMvpMatrix; -uniform highp vec4 uActiveRect; // (x-scale, y-scale, x-offset, y-offset) -uniform highp vec2 uViewUnit; -uniform highp vec2 uPixelAsUv; +uniform mat4 uMvpMatrix; +uniform vec4 uActiveRect; // (x-scale, y-scale, x-offset, y-offset) +uniform vec2 uViewUnit; +uniform vec2 uPixelAsUv; uniform sampler2D uDepthBuf; -attribute highp vec4 aVertex; -attribute highp vec4 aColor; -attribute highp vec2 aUV; -attribute highp vec2 aUV2; -attribute highp vec2 aUV3; +in vec4 aVertex; +in vec4 aColor; +in vec2 aUV; +in vec2 aUV2; +in vec2 aUV3; -varying highp vec4 vColor; -varying highp vec2 vUV; +out vec4 vColor; +out vec2 vUV; -bool isOccluded(highp vec2 uv) { +bool isOccluded(vec2 uv) { // Apply a possible viewport transformation. uv = uv * uActiveRect.xy + uActiveRect.zw; - float depth = texture2D(uDepthBuf, uv).r; + float depth = texture(uDepthBuf, uv).r; return (depth < (gl_Position.z/gl_Position.w + 1.0) / 2.0); } float occlusionLevel() { - highp vec2 depthUv = gl_Position.xy / gl_Position.w / 2.0 + vec2(0.5, 0.5); + vec2 depthUv = gl_Position.xy / gl_Position.w / 2.0 + vec2(0.5, 0.5); float occ = 0.0; - if(!isOccluded(depthUv)) occ += 0.2; - if(!isOccluded(depthUv + vec2(uPixelAsUv.x * 4.0, uPixelAsUv.y))) occ += 0.2; - if(!isOccluded(depthUv - vec2(uPixelAsUv.x * 4.0, uPixelAsUv.y))) occ += 0.2; - if(!isOccluded(depthUv + vec2(uPixelAsUv.x, uPixelAsUv.y * 4.0))) occ += 0.2; - if(!isOccluded(depthUv - vec2(uPixelAsUv.x, uPixelAsUv.y * 4.0))) occ += 0.2; + if (!isOccluded(depthUv)) occ += 0.2; + if (!isOccluded(depthUv + vec2(uPixelAsUv.x * 4.0, uPixelAsUv.y))) occ += 0.2; + if (!isOccluded(depthUv - vec2(uPixelAsUv.x * 4.0, uPixelAsUv.y))) occ += 0.2; + if (!isOccluded(depthUv + vec2(uPixelAsUv.x, uPixelAsUv.y * 4.0))) occ += 0.2; + if (!isOccluded(depthUv - vec2(uPixelAsUv.x, uPixelAsUv.y * 4.0))) occ += 0.2; return occ; } @@ -41,7 +41,7 @@ // Is the origin occluded in the depth buffer? float ocl = occlusionLevel(); - if(ocl <= 0.0) { + if (ocl <= 0.0) { // Occluded! Make it invisibile and leave the quad zero-sized. vUV = aUV; vColor = vec4(0.0, 0.0, 0.0, 0.0); @@ -52,7 +52,7 @@ } // Position on the axis that passes through the center of the view. - highp float axisPos = aUV3.s; + float axisPos = aUV3.s; gl_Position.xy *= axisPos; // Position the quad corners. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/lensflares.pack/shaders.dei 2018-12-11 07:08:18.000000000 +0000 @@ -8,15 +8,15 @@ uniform sampler2D uTex; uniform sampler2D uDepthBuf; - varying highp vec4 vColor; - varying highp vec2 vUV; + in vec4 vColor; + in vec2 vUV; void main(void) { - highp vec4 tex = texture2D(uTex, vUV); - gl_FragColor = tex * vColor; + vec4 tex = texture(uTex, vUV); + out_FragColor = tex * vColor; // Discard fragments without alpha. - if(gl_FragColor.a <= 0.0) { + if (out_FragColor.a <= 0.0) { discard; } }" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/debug.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/debug.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/debug.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/debug.dei 2018-12-11 07:08:18.000000000 +0000 @@ -3,12 +3,12 @@ # Visualize alpha information. shader alpha { vertex = " - uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + uniform mat4 uMvpMatrix; + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; + out vec2 vUV; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -17,12 +17,12 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; + in vec2 vUV; + in vec4 vColor; void main(void) { - highp vec4 col = vColor * texture2D(uTex, vUV); - gl_FragColor = vec4(col.a, col.a, col.a, 1.0); + vec4 col = vColor * texture(uTex, vUV); + out_FragColor = vec4(col.a, col.a, col.a, 1.0); }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl.dei 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl.dei 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,4 @@ +# Shader for the DGL drawing routines that emulate OpenGL 1.x behavior. +shader dgl.draw { + path = "dgl_draw" +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.fsh doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.fsh --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.fsh 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.fsh 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,181 @@ +/* + * The Doomsday Engine Project + * Common OpenGL Shaders: Legacy DGL Drawing + * + * Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "../include/fog.glsl" + +uniform int uTexEnabled[DGL_BATCH_MAX]; +uniform int uTexMode[DGL_BATCH_MAX]; +uniform vec4 uTexModeColor[DGL_BATCH_MAX]; +uniform float uAlphaLimit[DGL_BATCH_MAX]; +uniform sampler2D uTex0[DGL_BATCH_MAX]; +uniform sampler2D uTex1[DGL_BATCH_MAX]; + +flat DENG_VAR int vBatchIndex; +DENG_VAR vec4 vColor; +DENG_VAR vec2 vTexCoord[2]; + +vec4 sampleTexture0(int batchIndex, vec2 uv) +{ + switch (batchIndex) + { + case 0: return texture(uTex0[0], uv); + case 1: return texture(uTex0[1], uv); + case 2: return texture(uTex0[2], uv); + case 3: return texture(uTex0[3], uv); + case 4: return texture(uTex0[4], uv); + case 5: return texture(uTex0[5], uv); + case 6: return texture(uTex0[6], uv); + case 7: return texture(uTex0[7], uv); +#if DGL_BATCH_MAX > 8 + case 8: return texture(uTex0[8], uv); +#endif +#if DGL_BATCH_MAX > 9 + case 9: return texture(uTex0[9], uv); +#endif +#if DGL_BATCH_MAX > 10 + case 10: return texture(uTex0[10], uv); +#endif +#if DGL_BATCH_MAX > 11 + case 11: return texture(uTex0[11], uv); +#endif +#if DGL_BATCH_MAX > 12 + case 12: return texture(uTex0[12], uv); +#endif +#if DGL_BATCH_MAX > 13 + case 13: return texture(uTex0[13], uv); +#endif +#if DGL_BATCH_MAX > 14 + case 14: return texture(uTex0[14], uv); +#endif +#if DGL_BATCH_MAX > 15 + case 15: return texture(uTex0[15], uv); +#endif + } +} + +vec4 sampleTexture1(int batchIndex, vec2 uv) +{ + switch (batchIndex) + { + case 0: return texture(uTex1[0], uv); + case 1: return texture(uTex1[1], uv); + case 2: return texture(uTex1[2], uv); + case 3: return texture(uTex1[3], uv); + case 4: return texture(uTex1[4], uv); + case 5: return texture(uTex1[5], uv); + case 6: return texture(uTex1[6], uv); + case 7: return texture(uTex1[7], uv); +#if DGL_BATCH_MAX > 8 + case 8: return texture(uTex1[8], uv); +#endif +#if DGL_BATCH_MAX > 9 + case 9: return texture(uTex1[9], uv); +#endif +#if DGL_BATCH_MAX > 10 + case 10: return texture(uTex1[10], uv); +#endif +#if DGL_BATCH_MAX > 11 + case 11: return texture(uTex1[11], uv); +#endif +#if DGL_BATCH_MAX > 12 + case 12: return texture(uTex1[12], uv); +#endif +#if DGL_BATCH_MAX > 13 + case 13: return texture(uTex1[13], uv); +#endif +#if DGL_BATCH_MAX > 14 + case 14: return texture(uTex1[14], uv); +#endif +#if DGL_BATCH_MAX > 15 + case 15: return texture(uTex1[15], uv); +#endif + } +} +void main() +{ + out_FragColor = vColor; + + // Colors from textures. + vec4 texColor[2] = vec4[2](vec4(1.0), vec4(1.0)); + if ((uTexEnabled[vBatchIndex] & 0x1) != 0) + { + texColor[0] = sampleTexture0(vBatchIndex, vTexCoord[0]); + } + if ((uTexEnabled[vBatchIndex] & 0x2) != 0) + { + texColor[1] = sampleTexture1(vBatchIndex, vTexCoord[1]); + } + + // Modulate the texture colors in the requested manner. + switch (uTexMode[vBatchIndex]) + { + case 0: + // No modulation: just replace with texture. + out_FragColor = texColor[0]; + break; + case 1: + // Normal texture modulation with primary color. + out_FragColor *= texColor[0]; + break; + case 2: + // Texture interpolation and modulation with primary color. + out_FragColor.rgb *= + mix(texColor[0].rgb, texColor[1].rgb, uTexModeColor[vBatchIndex].a); + break; + case 3: + // Texture interpolation. + out_FragColor.rgb = mix(texColor[0].rgb, texColor[1].rgb, uTexModeColor[vBatchIndex].a); + break; + case 4: + // Sector light, dynamic light, and texture. + out_FragColor.rgb += texColor[0].a * uTexModeColor[vBatchIndex].rgb; + out_FragColor *= texColor[1]; + break; + case 6: + // Simple dynlight addition (add to primary color). + out_FragColor.rgb += texColor[0].a * uTexModeColor[vBatchIndex].rgb; + break; + case 8: + // Texture and Detail. + out_FragColor *= texColor[0]; + out_FragColor.rgb *= texColor[1].rgb * 2.0; + break; + case 10: + // Sector light * texture + dynamic light. + out_FragColor *= texColor[0]; + out_FragColor.rgb += texColor[1].rgb * uTexModeColor[vBatchIndex].rgb; + break; + case 11: + // Normal modulation, alpha of 2nd stage. + // Tex0: texture + // Tex1: shiny texture + out_FragColor.rgb *= texColor[1].rgb; + out_FragColor.a *= texColor[0].a; + break; + } + + // Alpha test. + if (out_FragColor.a <= uAlphaLimit[vBatchIndex]) + { + discard; + } + + applyFog(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.vsh doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.vsh --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.vsh 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/dgl/dgl_draw.vsh 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,57 @@ +/* + * The Doomsday Engine Project + * Common OpenGL Shaders: Legacy DGL Drawing + * + * Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +DENG_LAYOUT_LOC(0) DENG_ATTRIB vec4 aVertex; +DENG_LAYOUT_LOC(1) DENG_ATTRIB vec4 aColor; +DENG_LAYOUT_LOC(2) DENG_ATTRIB vec2 aTexCoord[2]; +DENG_LAYOUT_LOC(4) DENG_ATTRIB vec2 aFragOffset; +DENG_LAYOUT_LOC(5) DENG_ATTRIB float aBatchIndex; + +uniform vec2 uFragmentSize; // used for line width +uniform mat4 uMvpMatrix[DGL_BATCH_MAX]; +uniform mat4 uTexMatrix0[DGL_BATCH_MAX]; +uniform mat4 uTexMatrix1[DGL_BATCH_MAX]; + +flat DENG_VAR int vBatchIndex; +DENG_VAR vec4 vColor; +DENG_VAR vec2 vTexCoord[2]; + +vec2 transformTexCoord(const mat4 matrix, const vec2 tc) +{ + vec4 coord = vec4(tc.s, tc.t, 0.0, 1.0); + return (matrix * coord).xy; +} + +void main() +{ + vBatchIndex = int(aBatchIndex + 0.5); + + gl_Position = uMvpMatrix[vBatchIndex] * aVertex; + + if (uFragmentSize != vec2(0.0)) + { + gl_Position.xy += + normalize(mat2(uMvpMatrix[vBatchIndex]) * aFragOffset) * uFragmentSize * gl_Position.w; + } + + vColor = aColor; + vTexCoord[0] = transformTexCoord(uTexMatrix0[vBatchIndex], aTexCoord[0]); + vTexCoord[1] = transformTexCoord(uTexMatrix1[vBatchIndex], aTexCoord[1]); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/bloom.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/bloom.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/bloom.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/bloom.dei 2018-12-11 07:08:18.000000000 +0000 @@ -2,14 +2,14 @@ # (given a configurable threshold for brightness). fx.bloom { common = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor; - uniform highp vec4 uWindow; + uniform mat4 uMvpMatrix; + uniform vec4 uColor; + uniform vec4 uWindow; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; + in vec4 aVertex; + in vec2 aUV; - varying highp vec2 vUV; + out vec2 vUV; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -20,37 +20,37 @@ vertex $= fx.bloom.common fragment = " uniform sampler2D uTex; - uniform highp float uIntensity; - uniform highp float uThreshold; - uniform highp vec2 uBlurStep; + uniform float uIntensity; + uniform float uThreshold; + uniform vec2 uBlurStep; - varying highp vec2 vUV; + in vec2 vUV; void main(void) { - highp vec4 sum = vec4(0.0); + vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s - 7.0 * uBlurStep.s, vUV.t)) * 0.0249; - sum += texture2D(uTex, vec2(vUV.s - 6.0 * uBlurStep.s, vUV.t)) * 0.0367; - sum += texture2D(uTex, vec2(vUV.s - 5.0 * uBlurStep.s, vUV.t)) * 0.0498; - sum += texture2D(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.0660; - sum += texture2D(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.0803; - sum += texture2D(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.0915; - sum += texture2D(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.0996; - sum += texture2D(uTex, vUV) * 0.1027; - sum += texture2D(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.0996; - sum += texture2D(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.0915; - sum += texture2D(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.0803; - sum += texture2D(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.0660; - sum += texture2D(uTex, vec2(vUV.s + 5.0 * uBlurStep.s, vUV.t)) * 0.0498; - sum += texture2D(uTex, vec2(vUV.s + 6.0 * uBlurStep.s, vUV.t)) * 0.0367; - sum += texture2D(uTex, vec2(vUV.s + 7.0 * uBlurStep.s, vUV.t)) * 0.0249; + sum += texture(uTex, vec2(vUV.s - 7.0 * uBlurStep.s, vUV.t)) * 0.0249; + sum += texture(uTex, vec2(vUV.s - 6.0 * uBlurStep.s, vUV.t)) * 0.0367; + sum += texture(uTex, vec2(vUV.s - 5.0 * uBlurStep.s, vUV.t)) * 0.0498; + sum += texture(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.0660; + sum += texture(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.0803; + sum += texture(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.0915; + sum += texture(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.0996; + sum += texture(uTex, vUV) * 0.1027; + sum += texture(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.0996; + sum += texture(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.0915; + sum += texture(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.0803; + sum += texture(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.0660; + sum += texture(uTex, vec2(vUV.s + 5.0 * uBlurStep.s, vUV.t)) * 0.0498; + sum += texture(uTex, vec2(vUV.s + 6.0 * uBlurStep.s, vUV.t)) * 0.0367; + sum += texture(uTex, vec2(vUV.s + 7.0 * uBlurStep.s, vUV.t)) * 0.0249; // Apply a threshold that gets rid of dark, non-luminous pixels. - highp float intens = max(sum.r, max(sum.g, sum.b)); + float intens = max(sum.r, max(sum.g, sum.b)); intens = (intens - uThreshold) * uIntensity; - gl_FragColor = vec4(vec3(intens) * normalize(sum.rgb + 0.2), 1.0); + out_FragColor = vec4(vec3(intens) * normalize(sum.rgb + 0.2), 1.0); }" } @@ -58,30 +58,30 @@ vertex $= fx.bloom.common fragment = " uniform sampler2D uTex; - uniform highp vec2 uBlurStep; + uniform vec2 uBlurStep; - varying highp vec2 vUV; + in vec2 vUV; void main(void) { - highp vec4 sum = vec4(0.0); + vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 7.0 * uBlurStep.t)) * 0.0249; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 6.0 * uBlurStep.t)) * 0.0367; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 5.0 * uBlurStep.t)) * 0.0498; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.0660; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.0803; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.0915; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.0996; - sum += texture2D(uTex, vUV) * 0.1027; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.0996; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.0915; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.0803; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.0660; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 5.0 * uBlurStep.t)) * 0.0498; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 6.0 * uBlurStep.t)) * 0.0367; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 7.0 * uBlurStep.t)) * 0.0249; + sum += texture(uTex, vec2(vUV.s, vUV.t - 7.0 * uBlurStep.t)) * 0.0249; + sum += texture(uTex, vec2(vUV.s, vUV.t - 6.0 * uBlurStep.t)) * 0.0367; + sum += texture(uTex, vec2(vUV.s, vUV.t - 5.0 * uBlurStep.t)) * 0.0498; + sum += texture(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.0660; + sum += texture(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.0803; + sum += texture(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.0915; + sum += texture(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.0996; + sum += texture(uTex, vUV) * 0.1027; + sum += texture(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.0996; + sum += texture(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.0915; + sum += texture(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.0803; + sum += texture(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.0660; + sum += texture(uTex, vec2(vUV.s, vUV.t + 5.0 * uBlurStep.t)) * 0.0498; + sum += texture(uTex, vec2(vUV.s, vUV.t + 6.0 * uBlurStep.t)) * 0.0367; + sum += texture(uTex, vec2(vUV.s, vUV.t + 7.0 * uBlurStep.t)) * 0.0249; - gl_FragColor = sum; + out_FragColor = sum; }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/blur.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/blur.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/blur.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/blur.dei 2018-12-11 07:08:18.000000000 +0000 @@ -4,16 +4,16 @@ blur { # Both passes use the same vertex shader. common = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor; - uniform highp vec4 uWindow; - - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; + uniform mat4 uMvpMatrix; + uniform vec4 uColor; + uniform vec4 uWindow; + + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + out vec2 vUV; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -25,24 +25,24 @@ vertex $= fx.blur.common fragment = " uniform sampler2D uTex; - uniform highp vec2 uBlurStep; + uniform vec2 uBlurStep; - varying highp vec2 vUV; - varying highp vec4 vColor; + in vec2 vUV; + in vec4 vColor; void main(void) { - highp vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.05; - sum += texture2D(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.154; - sum += texture2D(uTex, vUV) * 0.165; - sum += texture2D(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.154; - sum += texture2D(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.05; - gl_FragColor = sum; - gl_FragColor.a = 1.0; + vec4 sum = vec4(0.0); + sum += texture(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.05; + sum += texture(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.154; + sum += texture(uTex, vUV) * 0.165; + sum += texture(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.154; + sum += texture(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.05; + out_FragColor = sum; + out_FragColor.a = 1.0; }" } @@ -50,23 +50,23 @@ vertex $= fx.blur.common fragment = " uniform sampler2D uTex; - uniform highp vec2 uBlurStep; + uniform vec2 uBlurStep; - varying highp vec2 vUV; - varying highp vec4 vColor; + in vec2 vUV; + in vec4 vColor; void main(void) { - highp vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.05; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.154; - sum += texture2D(uTex, vUV) * 0.165; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.154; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.05; - gl_FragColor = sum * vColor; + vec4 sum = vec4(0.0); + sum += texture(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.05; + sum += texture(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.154; + sum += texture(uTex, vUV) * 0.165; + sum += texture(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.154; + sum += texture(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.05; + out_FragColor = sum * vColor; }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/post.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/post.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/post.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/fx/post.dei 2018-12-11 07:08:18.000000000 +0000 @@ -2,63 +2,107 @@ # Post-processing shaders need to have uFadeInOut (0..1) for # fading the effect in/out. post { - shader monochrome { - vertex = " - uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - varying highp vec2 vUV; + commonVertex = " + uniform mat4 uMvpMatrix; + in vec4 aVertex; + in vec2 aUV; + out vec2 vUV; + void main(void) { + gl_Position = uMvpMatrix * aVertex; + vUV = aUV; + } + " - void main(void) { - gl_Position = uMvpMatrix * aVertex; - vUV = aUV; - }" + shader monochrome { + vertex $= fx.post.commonVertex fragment = " uniform sampler2D uTex; - uniform highp float uFadeInOut; - varying highp vec2 vUV; + uniform float uFadeInOut; + in vec2 vUV; void main(void) { - highp vec4 original = texture2D(uTex, vUV); - highp float intens = + vec4 original = texture(uTex, vUV); + float intens = (0.2125 * original.r) + (0.7154 * original.g) + (0.0721 * original.b); - gl_FragColor = vec4(vec3(intens), 1.0); - if(uFadeInOut < 1.0) { - gl_FragColor = mix(original, gl_FragColor, uFadeInOut); + out_FragColor = vec4(vec3(intens), 1.0); + if (uFadeInOut < 1.0) { + out_FragColor = mix(original, out_FragColor, uFadeInOut); } - }" + } + " } shader monochrome.inverted { - vertex = " - uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - varying highp vec2 vUV; - - void main(void) { - gl_Position = uMvpMatrix * aVertex; - vUV = aUV; - }" + vertex $= fx.post.commonVertex fragment = " uniform sampler2D uTex; - uniform highp float uFadeInOut; - varying highp vec2 vUV; + uniform float uFadeInOut; + in vec2 vUV; void main(void) { - highp vec4 original = texture2D(uTex, vUV); - highp float intens = + vec4 original = texture(uTex, vUV); + float intens = (0.2125 * original.r) + (0.7154 * original.g) + - (0.0721 * original.b); - - gl_FragColor = vec4(vec3(1.0 - intens), 1.0); - if(uFadeInOut < 1.0) { - gl_FragColor = mix(original, gl_FragColor, uFadeInOut); + (0.0721 * original.b); + out_FragColor = vec4(vec3(1.0 - intens), 1.0); + if (uFadeInOut < 1.0) { + out_FragColor = mix(original, out_FragColor, uFadeInOut); + } + } + " + } + + shader colorize.gold { + vertex $= fx.post.commonVertex + fragment = " + #include '../include/hsv.glsl' + uniform sampler2D uTex; + uniform float uFadeInOut; + in vec2 vUV; + + void main(void) { + vec4 original = texture(uTex, vUV); + vec4 colorized = rgbToHsv(original); + colorized.x = 40.0; // Fix hue to gold. + colorized.y = 1.0; // Full saturation. + colorized.z = pow(colorized.z, 1.75); // Darker curve. + colorized = hsvToRgb(colorized); + if (uFadeInOut < 1.0) { + out_FragColor = mix(original, colorized, uFadeInOut); + } + else { + out_FragColor = colorized; } - }" - } + } + " + } + + shader colorize.inverted.gold { + vertex $= fx.post.commonVertex + fragment = " + #include '../include/hsv.glsl' + uniform sampler2D uTex; + uniform float uFadeInOut; + in vec2 vUV; + + void main(void) { + vec4 original = texture(uTex, vUV); + vec4 colorized = rgbToHsv(original); + colorized.x = 40.0; // Fix hue to gold. + colorized.y = 1.0; // Full saturation. + colorized.z = 1.0 - colorized.z; // Invert value. + colorized = hsvToRgb(colorized); + if (uFadeInOut < 1.0) { + out_FragColor = mix(original, colorized, uFadeInOut); + } + else { + out_FragColor = colorized; + } + } + " + } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/generic.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/generic.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/generic.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/generic.dei 2018-12-11 07:08:18.000000000 +0000 @@ -4,30 +4,30 @@ # matrix. shader color_ucolor { vertex = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - varying highp vec4 vColor; + uniform mat4 uMvpMatrix; + uniform vec4 uColor; + in vec4 aVertex; + in vec4 aColor; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; vColor = uColor * aColor; }" fragment = " - varying highp vec4 vColor; + in vec4 vColor; void main(void) { - gl_FragColor = vColor; + out_FragColor = vColor; }" } shader texture { vertex = " - uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - varying highp vec2 vUV; + uniform mat4 uMvpMatrix; + in vec4 aVertex; + in vec2 aUV; + out vec2 vUV; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -35,10 +35,10 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; + in vec2 vUV; void main(void) { - gl_FragColor = texture2D(uTex, vUV); + out_FragColor = texture(uTex, vUV); }" } @@ -47,12 +47,12 @@ # combined model-view-projection matrix. shader color { vertex = " - uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + uniform mat4 uMvpMatrix; + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; + out vec2 vUV; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -61,11 +61,11 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; + in vec2 vUV; + in vec4 vColor; void main(void) { - gl_FragColor = vColor * texture2D(uTex, vUV); + out_FragColor = vColor * texture(uTex, vUV); }" } @@ -74,13 +74,13 @@ # combined model-view-projection matrix. shader color_ucolor { vertex = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + uniform mat4 uMvpMatrix; + uniform vec4 uColor; + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; + out vec2 vUV; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -89,40 +89,41 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; + in vec2 vUV; + in vec4 vColor; void main(void) { - gl_FragColor = vColor * texture2D(uTex, vUV); + out_FragColor = vColor * texture(uTex, vUV); }" } shader hsv.color_ucolor inherits generic.textured.color_ucolor { vertex = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + uniform mat4 uMvpMatrix; + uniform vec4 uColor; + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; + out vec2 vUV; + out vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; vUV = aUV; vColor = aColor * uColor; }" - include.fragment fragment = " + #include 'include/hsv.glsl' + uniform sampler2D uTex; - uniform highp float uSaturation; - varying highp vec2 vUV; - varying highp vec4 vColor; + uniform float uSaturation; + in vec2 vUV; + in vec4 vColor; void main(void) { - highp vec4 hsv = rgbToHsv(texture2D(uTex, vUV)); + vec4 hsv = rgbToHsv(texture(uTex, vUV)); hsv.y *= uSaturation; - gl_FragColor = vColor * hsvToRgb(hsv); + out_FragColor = vColor * hsvToRgb(hsv); }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/fog.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/fog.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/fog.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/fog.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -18,21 +18,21 @@ * http://www.gnu.org/licenses */ -uniform highp vec4 uFogRange; // startDepth, fogDepth, nearclip, farclip -uniform highp vec4 uFogColor; // set alpha to zero to disable fog +uniform vec4 uFogRange; // startDepth, fogDepth, nearclip, farclip +uniform vec4 uFogColor; // set alpha to zero to disable fog void applyFog() { - if(uFogColor.a > 0.0) - { - highp float near = uFogRange.z; - highp float far = uFogRange.w; - + if (uFogColor.a > 0.0) { + float pNear = uFogRange.z; + float pFar = uFogRange.w; + float pDepth = pFar - pNear; + // First convert the fragment Z back to view space. - highp float zNorm = gl_FragCoord.z * 2.0 - 1.0; - highp float zEye = -2.0 * far * near / (zNorm * (far - near) - (far + near)); - - highp float fogAmount = clamp((zEye - uFogRange.x) / uFogRange.y, 0.0, 1.0); - gl_FragColor.rgb = mix(gl_FragColor.rgb, uFogColor.rgb, fogAmount); + float zNorm = 2.0 * gl_FragCoord.z - 1.0; + float zEye = 2.0 * pNear * pFar / (pFar + pNear - zNorm * pDepth); + + float fogAmount = clamp((zEye - uFogRange.x) / uFogRange.y, 0.0, 1.0); + out_FragColor.rgb = mix(out_FragColor.rgb, uFogColor.rgb, fogAmount); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/hsv.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/hsv.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/hsv.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/hsv.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -21,101 +21,86 @@ /** * Converts an RGBA value to HSVA. Hue uses degrees as the unit. */ -highp vec4 rgbToHsv(highp vec4 rgb) +vec4 rgbToHsv(vec4 rgb) { - highp vec4 hsv; + vec4 hsv; hsv.a = rgb.a; - highp float rgbMin = min(min(rgb.r, rgb.g), rgb.b); - highp float rgbMax = max(max(rgb.r, rgb.g), rgb.b); - highp float delta = rgbMax - rgbMin; + float rgbMin = min(min(rgb.r, rgb.g), rgb.b); + float rgbMax = max(max(rgb.r, rgb.g), rgb.b); + float delta = rgbMax - rgbMin; hsv.z = rgbMax; - if (delta < 0.00001) - { + if (delta < 0.00001) { hsv.xy = vec2(0.0); return hsv; } - if (rgbMax > 0.0) - { + if (rgbMax > 0.0) { hsv.y = delta / rgbMax; } - else - { + else { hsv.xy = vec2(0.0); return hsv; } - if (rgb.r >= rgbMax) - { + if (rgb.r >= rgbMax) { hsv.x = (rgb.g - rgb.b) / delta; } - else - { - if (rgb.g >= rgbMax) - { + else { + if (rgb.g >= rgbMax) { hsv.x = 2.0 + (rgb.b - rgb.r) / delta; } - else - { + else { hsv.x = 4.0 + (rgb.r - rgb.g) / delta; } } hsv.x *= 60.0; - if (hsv.x < 0.0) - { + if (hsv.x < 0.0) { hsv.x += 360.0; } return hsv; } -highp vec4 hsvToRgb(highp vec4 hsv) +vec4 hsvToRgb(vec4 hsv) { - highp vec4 rgb; + vec4 rgb; rgb.a = hsv.a; - if (hsv.y <= 0.0) - { + if (hsv.y <= 0.0) { rgb.rgb = vec3(hsv.z); return rgb; } - highp float hh = hsv.x; + float hh = hsv.x; if (hh >= 360.0) hh = 0.0; hh /= 60.0; - highp float ff = fract(hh); - highp float p = hsv.z * (1.0 - hsv.y); - highp float q = hsv.z * (1.0 - (hsv.y * ff)); - highp float t = hsv.z * (1.0 - (hsv.y * (1.0 - ff))); + float ff = fract(hh); + float p = hsv.z * (1.0 - hsv.y); + float q = hsv.z * (1.0 - (hsv.y * ff)); + float t = hsv.z * (1.0 - (hsv.y * (1.0 - ff))); int i = int(hh); - if (i == 0) - { + if (i == 0) { rgb.rgb = vec3(hsv.z, t, p); } - else if (i == 1) - { + else if (i == 1) { rgb.rgb = vec3(q, hsv.z, p); } - else if (i == 2) - { + else if (i == 2) { rgb.rgb = vec3(p, hsv.z, t); } - else if (i == 3) - { + else if (i == 3) { rgb.rgb = vec3(p, q, hsv.z); } - else if (i == 4) - { + else if (i == 4) { rgb.rgb = vec3(t, p, hsv.z); } - else - { + else { rgb.rgb = vec3(hsv.z, p, q); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/lighting.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/lighting.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/lighting.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/lighting.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -18,37 +18,40 @@ * http://www.gnu.org/licenses */ -uniform highp float uSpecular; // factor for specular lights -uniform highp float uEmission; // factor for emissive light -uniform highp float uGlossiness; - -uniform highp vec4 uAmbientLight; -uniform highp vec4 uLightIntensities[4]; // colored -uniform highp vec3 uLightDirs[4]; // model space -uniform highp vec3 uEyePos; // model space +uniform float uSpecular; // factor for specular lights +uniform float uEmission; // factor for emissive light +uniform float uGlossiness; + +uniform vec4 uAmbientLight; +uniform vec4 uLightIntensities[4]; // colored +uniform vec3 uLightDirs[4]; // model space +uniform vec3 uEyePos; // model space -varying highp vec3 vEyeDir; // from vertex, in model space +#ifdef DENG_VERTEX_SHADER +out vec3 vEyeDir; // from vertex, in model space +#else +in vec3 vEyeDir; +#endif #ifdef DENG_VERTEX_SHADER -void calculateEyeDirection(highp vec4 vertex) +void calculateEyeDirection(vec4 vertex) { vEyeDir = uEyePos - vertex.xyz/vertex.w; } #endif // DENG_VERTEX_SHADER -highp vec3 diffuseLightContrib(int index, highp vec3 msNormal) +vec3 diffuseLightContrib(int index, vec3 msNormal) { - if(uLightIntensities[index].a <= 0.001) - { + if (uLightIntensities[index].a <= 0.001) { return vec3(0.0); // too dim } - highp float d = dot(msNormal, uLightDirs[index]); + float d = dot(msNormal, uLightDirs[index]); return max(d, 0.0) * uLightIntensities[index].rgb; } -highp vec3 diffuseLight(highp vec3 msNormal) +vec3 diffuseLight(vec3 msNormal) { return (uAmbientLight.rgb + diffuseLightContrib(0, msNormal) + @@ -59,29 +62,27 @@ #ifdef DENG_HAVE_UTEX -highp vec3 specularLightContrib(highp vec4 specGloss, int index, highp vec3 msNormal) +vec3 specularLightContrib(vec4 specGloss, int index, vec3 msNormal) { - if(uLightIntensities[index].a <= 0.001) // a == max of rgb - { + if (uLightIntensities[index].a <= 0.001) { // a == max of rgb return vec3(0.0); // Too dim. } - highp vec3 reflectedDir = reflect(-uLightDirs[index], msNormal); - highp float refDot = dot(normalize(vEyeDir), reflectedDir); - if(refDot <= 0.0) - { + vec3 reflectedDir = reflect(-uLightDirs[index], msNormal); + float refDot = dot(normalize(vEyeDir), reflectedDir); + if (refDot <= 0.0) { return vec3(0.0); // Wrong way. } - highp float gloss = max(1.0, uGlossiness * specGloss.a); - highp float specPower = min(pow(refDot, gloss), 1.0); + float gloss = max(1.0, uGlossiness * specGloss.a); + float specPower = min(pow(refDot, gloss), 1.0); return uSpecular * uLightIntensities[index].rgb * specPower * specGloss.rgb; } -highp vec4 specularGloss(highp vec2 specularUV) +vec4 specularGloss(vec2 specularUV) { - return texture2D(uTex, specularUV); + return texture(uTex, specularUV); } -highp vec3 specularLight(highp vec4 specGloss, highp vec3 msNormal) +vec3 specularLight(vec4 specGloss, vec3 msNormal) { return specularLightContrib(specGloss, 0, msNormal) + specularLightContrib(specGloss, 1, msNormal) + @@ -89,9 +90,9 @@ specularLightContrib(specGloss, 3, msNormal); } -highp vec4 emittedLight(highp vec2 emissiveUV) +vec4 emittedLight(vec2 emissiveUV) { - highp vec4 emission = uEmission * texture2D(uTex, emissiveUV); + vec4 emission = uEmission * texture(uTex, emissiveUV); emission.a = 0.0; // Does not contribute to alpha. return emission; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/reflection.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/reflection.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/reflection.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/reflection.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -27,8 +27,9 @@ #define MAX_REFLECTION_BIAS 5.0 uniform samplerCube uReflectionTex; -uniform highp mat4 uReflectionMatrix; -uniform highp float uReflectionBlur; +uniform mat4 uReflectionMatrix; +uniform float uReflection; +uniform float uReflectionBlur; /* * Given the tangent space @a surfaceNormal, determines the reflection @@ -36,34 +37,35 @@ * the fragment's tangent space matrix. @a bias is the mipmap bias for the * reflection. */ -highp vec3 reflectedColorBiased(highp vec3 msNormal, float bias) +vec3 reflectedColorBiased(vec3 msNormal, float bias) { // The reflection cube exists in local space, so we will use vectors // relative to the object's origin. - highp vec3 reflectedDir = reflect(normalize(vEyeDir), msNormal); + vec3 reflectedDir = reflect(normalize(vEyeDir), msNormal); reflectedDir = (uReflectionMatrix * vec4(reflectedDir, 0.0)).xyz; // Match world space directions. reflectedDir.z = -reflectedDir.z; reflectedDir.y = -reflectedDir.y; - return textureCube(uReflectionTex, reflectedDir, min(bias, MAX_REFLECTION_BIAS)).rgb; + return uReflection * texture(uReflectionTex, reflectedDir, + min(bias, MAX_REFLECTION_BIAS)).rgb; } -highp vec3 reflectedColor(highp vec3 msNormal) +vec3 reflectedColor(vec3 msNormal) { return reflectedColorBiased(msNormal, 0.0); } -highp vec4 diffuseAndReflectedLight(highp vec4 diffuseFactor, highp vec2 diffuseUV, - highp vec4 specGloss, highp vec3 msNormal) +vec4 diffuseAndReflectedLight(vec4 diffuseFactor, vec2 diffuseUV, + vec4 specGloss, vec3 msNormal) { // Reflection. - highp float mipBias = uReflectionBlur * (1.0 - specGloss.a); - highp vec3 reflection = specGloss.rgb * reflectedColorBiased(msNormal, mipBias); + float mipBias = uReflectionBlur * (1.0 - specGloss.a); + vec3 reflection = specGloss.rgb * reflectedColorBiased(msNormal, mipBias); // Diffuse. Surface opacity is also determined here. - highp vec4 color = diffuseFactor * vec4(diffuseLight(msNormal), 1.0) * - texture2D(uTex, diffuseUV); + vec4 color = diffuseFactor * vec4(diffuseLight(msNormal), 1.0) * + texture(uTex, diffuseUV); return color + vec4(reflection, 0.0); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/skeletal.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/skeletal.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/skeletal.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/skeletal.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -18,16 +18,16 @@ * http://www.gnu.org/licenses */ -uniform highp mat4 uBoneMatrices[64]; +uniform mat4 uBoneMatrices[64]; -attribute highp vec4 aBoneIDs; -attribute highp vec4 aBoneWeights; +in vec4 aBoneIDs; +in vec4 aBoneWeights; /* * Calculates the bone matrix for the current vertex. Bones and their weights * are determined by vertex attributes. */ -highp mat4 vertexBoneTransform() +mat4 vertexBoneTransform() { return uBoneMatrices[int(aBoneIDs.x + 0.5)] * aBoneWeights.x + uBoneMatrices[int(aBoneIDs.y + 0.5)] * aBoneWeights.y + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/tangentspace.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/tangentspace.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/tangentspace.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/tangentspace.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -18,22 +18,22 @@ * http://www.gnu.org/licenses */ -varying highp vec3 vTSNormal; -varying highp vec3 vTSTangent; -varying highp vec3 vTSBitangent; - #ifdef DENG_VERTEX_SHADER -attribute highp vec3 aNormal; -attribute highp vec3 aTangent; -attribute highp vec3 aBitangent; +in vec3 aNormal; +in vec3 aTangent; +in vec3 aBitangent; + +out vec3 vTSNormal; +out vec3 vTSTangent; +out vec3 vTSBitangent; -highp vec3 transformVector(highp vec3 dir, highp mat4 matrix) +vec3 transformVector(vec3 dir, mat4 matrix) { return (matrix * vec4(dir, 0.0)).xyz; } -void setTangentSpace(highp mat4 modelSpace) +void setTangentSpace(mat4 modelSpace) { vTSNormal = transformVector(aNormal, modelSpace); vTSTangent = transformVector(aTangent, modelSpace); @@ -44,12 +44,16 @@ #ifdef DENG_FRAGMENT_SHADER -highp mat3 fragmentTangentSpace() +in vec3 vTSNormal; +in vec3 vTSTangent; +in vec3 vTSBitangent; + +mat3 fragmentTangentSpace() { return mat3(normalize(vTSTangent), normalize(vTSBitangent), normalize(vTSNormal)); } -highp vec3 modelSpaceNormalVector(highp vec2 uv) +vec3 modelSpaceNormalVector(vec2 uv) { return fragmentTangentSpace() * normalVector(uv); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/texture.glsl doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/texture.glsl --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/texture.glsl 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/include/texture.glsl 2018-12-11 07:08:18.000000000 +0000 @@ -25,12 +25,12 @@ /* * Maps the normalized @a uv to the rectangle defined by @a bounds. */ -highp vec2 mapToBounds(highp vec2 uv, highp vec4 bounds) +vec2 mapToBounds(vec2 uv, vec4 bounds) { return bounds.xy + uv * bounds.zw; } -highp vec3 normalVector(highp vec2 uv) +vec3 normalVector(vec2 uv) { - return normalize((texture2D(uTex, uv).xyz * 2.0) - 1.0); + return normalize((texture(uTex, uv).xyz * 2.0) - 1.0); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/model.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/model.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/model.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/model.dei 2018-12-11 07:08:18.000000000 +0000 @@ -10,6 +10,7 @@ variable uSpecular { value = 1 } variable uEmission { value = 0 } variable uGlossiness { value = 100 } + variable uReflection { value = 1 } variable uReflectionBlur { value = 10 } variable uMapTime {} @@ -21,27 +22,27 @@ include/skeletal.glsl, include/lighting.glsl> vertex = " - uniform highp mat4 uMvpMatrix; + uniform mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - attribute highp vec2 aUV; - attribute highp vec4 aBounds; // diffuse map - attribute highp vec4 aBounds2; // normal map - attribute highp vec4 aBounds3; // specular map - attribute highp vec4 aBounds4; // emission map - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[4]; + in vec4 aVertex; + in vec4 aColor; + in vec2 aUV; + in vec4 aBounds; // diffuse map + in vec4 aBounds2; // normal map + in vec4 aBounds3; // specular map + in vec4 aBounds4; // emission map + + out vec4 vColor; + out vec2 vUV; + out vec4 vUVBounds[4]; void main(void) { - highp mat4 bone = vertexBoneTransform(); + mat4 bone = vertexBoneTransform(); setTangentSpace(bone); // Vertex position. - highp vec4 modelPos = bone * aVertex; + vec4 modelPos = bone * aVertex; calculateEyeDirection(modelPos); gl_Position = uMvpMatrix * modelPos; @@ -54,7 +55,9 @@ vUVBounds[3] = aBounds4; }" - defines $= {'PREDEF_TRANSFORM_UV(uv)': ''} + defines $= {'PREDEF_TRANSFORM_UV(uv)' : '', + 'PREDEF_TRANSFORM_EMISSION(color)' : '', + 'PREDEF_TRANSFORM_ALPHA(alpha)' : ''} include.fragment fragment = " - uniform highp vec3 uColor; // diffuse color multiplier - uniform highp float uAlpha; // diffuse alpha multiplier - uniform highp float uAlphaLimit; // alpha test to discard fragments - uniform highp vec2 uOffsetUV; - uniform highp float uMapTime; - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[4]; - + uniform vec3 uColor; // diffuse color multiplier + uniform float uAlpha; // diffuse alpha multiplier + uniform float uAlphaLimit; // alpha test to discard fragments + uniform vec2 uOffsetUV; + uniform float uMapTime; + + in vec4 vColor; + in vec2 vUV; + in vec4 vUVBounds[4]; + void main(void) { // Calculate UV at the fragment (wrapped inside the bounds). - highp vec2 wrappedUV = vUV + uOffsetUV; + vec2 wrappedUV = vUV + uOffsetUV; + #if defined (PREDEF_TRANSFORM_UV) PREDEF_TRANSFORM_UV(wrappedUV); + #endif wrappedUV = fract(wrappedUV); - highp vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); - highp vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); - highp vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); - highp vec2 emissiveUV = mapToBounds(wrappedUV, vUVBounds[3]); + + vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); + vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); + vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); + vec2 emissiveUV = mapToBounds(wrappedUV, vUVBounds[3]); - highp vec3 msNormal = modelSpaceNormalVector(normalUV); - highp vec4 specGloss = specularGloss(specularUV); + vec3 msNormal = modelSpaceNormalVector(normalUV); + vec4 specGloss = specularGloss(specularUV); - gl_FragColor = diffuseAndReflectedLight( - vColor * vec4(uColor, uAlpha), uv, specGloss, msNormal); - - if(gl_FragColor.a < uAlphaLimit) discard; - - gl_FragColor.rgb += specularLight(specGloss, msNormal); - gl_FragColor += emittedLight(emissiveUV); + float alphaFactor = uAlpha; + #if defined (PREDEF_TRANSFORM_ALPHA) + PREDEF_TRANSFORM_ALPHA(alphaFactor); + #endif + out_FragColor = diffuseAndReflectedLight( + vColor * vec4(uColor, alphaFactor), uv, specGloss, msNormal); + + if (out_FragColor.a < uAlphaLimit) discard; + + out_FragColor.rgb += specularLight(specGloss, msNormal); + + // Emitted light. + vec4 emitted = emittedLight(emissiveUV); + #if defined (PREDEF_TRANSFORM_EMISSION) + PREDEF_TRANSFORM_EMISSION(emitted); + #endif + out_FragColor += emitted; applyFog(); }" @@ -103,37 +119,39 @@ shader opaque.generic inherits model.skeletal.generic { variable uAlphaLimit { value = 0.5 } fragment = " - uniform highp vec3 uColor; // diffuse color multiplier - uniform highp float uAlpha; - uniform highp float uAlphaLimit; // alpha test to discard fragments - uniform highp vec2 uOffsetUV; - uniform highp float uMapTime; + uniform vec3 uColor; // diffuse color multiplier + uniform float uAlpha; + uniform float uAlphaLimit; // alpha test to discard fragments + uniform vec2 uOffsetUV; + uniform float uMapTime; - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[4]; + in vec4 vColor; + in vec2 vUV; + in vec4 vUVBounds[4]; void main(void) { // Calculate UV at the fragment (wrapped inside the bounds). - highp vec2 wrappedUV = vUV + uOffsetUV; + vec2 wrappedUV = vUV + uOffsetUV; + #if defined (PREDEF_TRANSFORM_UV) PREDEF_TRANSFORM_UV(wrappedUV); + #endif wrappedUV = fract(wrappedUV); - highp vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); - highp vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); - highp vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); - highp vec2 emissiveUV = mapToBounds(wrappedUV, vUVBounds[3]); + vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); + vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); + vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); + vec2 emissiveUV = mapToBounds(wrappedUV, vUVBounds[3]); - highp vec3 msNormal = modelSpaceNormalVector(normalUV); - highp vec4 specGloss = specularGloss(specularUV); + vec3 msNormal = modelSpaceNormalVector(normalUV); + vec4 specGloss = specularGloss(specularUV); - gl_FragColor = diffuseAndReflectedLight( + out_FragColor = diffuseAndReflectedLight( vColor * vec4(uColor, uAlpha), uv, specGloss, msNormal); - if(gl_FragColor.a < uAlphaLimit) discard; + if (out_FragColor.a < uAlphaLimit) discard; - gl_FragColor.rgb += specularLight(specGloss, msNormal); - gl_FragColor += emittedLight(emissiveUV); + out_FragColor.rgb += specularLight(specGloss, msNormal); + out_FragColor += emittedLight(emissiveUV); applyFog(); }" @@ -162,26 +180,26 @@ include/skeletal.glsl, include/lighting.glsl> vertex = " - uniform highp mat4 uMvpMatrix; + uniform mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - attribute highp vec2 aUV; - attribute highp vec4 aBounds; // diffuse map - attribute highp vec4 aBounds2; // normal map - attribute highp vec4 aBounds3; // specular map - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[3]; + in vec4 aVertex; + in vec4 aColor; + in vec2 aUV; + in vec4 aBounds; // diffuse map + in vec4 aBounds2; // normal map + in vec4 aBounds3; // specular map + + out vec4 vColor; + out vec2 vUV; + out vec4 vUVBounds[3]; void main(void) { - highp mat4 bone = vertexBoneTransform(); + mat4 bone = vertexBoneTransform(); setTangentSpace(bone); // Vertex position. - highp vec4 modelPos = bone * aVertex; + vec4 modelPos = bone * aVertex; calculateEyeDirection(modelPos); gl_Position = uMvpMatrix * modelPos; @@ -199,36 +217,38 @@ include/reflection.glsl, include/fog.glsl> fragment = " - uniform highp float uAlphaLimit; - uniform highp float uAlpha; - uniform highp vec3 uColor; // diffuse color multiplier - uniform highp vec2 uOffsetUV; - uniform highp float uMapTime; - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[3]; + uniform float uAlphaLimit; + uniform float uAlpha; + uniform vec3 uColor; // diffuse color multiplier + uniform vec2 uOffsetUV; + uniform float uMapTime; + + in vec4 vColor; + in vec2 vUV; + in vec4 vUVBounds[3]; void main(void) { // Calculate UV at the fragment (wrapped inside the bounds). - highp vec2 wrappedUV = vUV + uOffsetUV; + vec2 wrappedUV = vUV + uOffsetUV; + #if defined (PREDEF_TRANSFORM_UV) PREDEF_TRANSFORM_UV(wrappedUV); + #endif wrappedUV = fract(wrappedUV); - highp vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); - highp vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); - highp vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); + vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); + vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); + vec2 specularUV = mapToBounds(wrappedUV, vUVBounds[2]); - highp vec3 msNormal = modelSpaceNormalVector(normalUV); - highp vec4 specGloss = specularGloss(specularUV); + vec3 msNormal = modelSpaceNormalVector(normalUV); + vec4 specGloss = specularGloss(specularUV); - gl_FragColor = diffuseAndReflectedLight( + out_FragColor = diffuseAndReflectedLight( vColor * vec4(uColor, uAlpha), uv, specGloss, msNormal); - if(gl_FragColor.a < uAlphaLimit) discard; + if (out_FragColor.a < uAlphaLimit) discard; - gl_FragColor.rgb += specularLight(specGloss, msNormal); + out_FragColor.rgb += specularLight(specGloss, msNormal); - gl_FragColor.a = uAlpha; + out_FragColor.a = uAlpha; applyFog(); }" @@ -251,25 +271,25 @@ include/skeletal.glsl, include/lighting.glsl> vertex = " - uniform highp mat4 uMvpMatrix; + uniform mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - attribute highp vec2 aUV; - attribute highp vec4 aBounds; // diffuse map - attribute highp vec4 aBounds2; // normal map - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[2]; + in vec4 aVertex; + in vec4 aColor; + in vec2 aUV; + in vec4 aBounds; // diffuse map + in vec4 aBounds2; // normal map + + out vec4 vColor; + out vec2 vUV; + out vec4 vUVBounds[2]; void main(void) { - highp mat4 bone = vertexBoneTransform(); + mat4 bone = vertexBoneTransform(); setTangentSpace(bone); // Vertex position. - highp vec4 modelPos = bone * aVertex; + vec4 modelPos = bone * aVertex; calculateEyeDirection(modelPos); gl_Position = uMvpMatrix * modelPos; @@ -285,31 +305,33 @@ include/lighting.glsl, include/fog.glsl> fragment = " - uniform highp float uAlphaLimit; - uniform highp float uAlpha; - uniform highp vec3 uColor; // diffuse color multiplier - uniform highp vec2 uOffsetUV; - uniform highp float uMapTime; - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds[2]; + uniform float uAlphaLimit; + uniform float uAlpha; + uniform vec3 uColor; // diffuse color multiplier + uniform vec2 uOffsetUV; + uniform float uMapTime; + + in vec4 vColor; + in vec2 vUV; + in vec4 vUVBounds[2]; void main(void) { // Calculate UV at the fragment (wrapped inside the bounds). - highp vec2 wrappedUV = vUV + uOffsetUV; + vec2 wrappedUV = vUV + uOffsetUV; + #if defined (PREDEF_TRANSFORM_UV) PREDEF_TRANSFORM_UV(wrappedUV); + #endif wrappedUV = fract(wrappedUV); - highp vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); - highp vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); + vec2 uv = mapToBounds(wrappedUV, vUVBounds[0]); + vec2 normalUV = mapToBounds(wrappedUV, vUVBounds[1]); - highp vec3 msNormal = modelSpaceNormalVector(normalUV); - gl_FragColor = vColor * vec4(uColor * diffuseLight(msNormal), 1.0) - * texture2D(uTex, uv); - if(gl_FragColor.a < uAlphaLimit) discard; + vec3 msNormal = modelSpaceNormalVector(normalUV); + out_FragColor = vColor * vec4(uColor * diffuseLight(msNormal), 1.0) + * texture(uTex, uv); + if (out_FragColor.a < uAlphaLimit) discard; - gl_FragColor.a = uAlpha; + out_FragColor.a = uAlpha; applyFog(); }" @@ -328,27 +350,28 @@ # Mapping when used with ModelDrawable. textureMapping - defines $= {'PREDEF_TRANSFORM_UV(uv)': ''} + defines $= {'PREDEF_TRANSFORM_UV(uv)' : '', + 'PREDEF_TRANSFORM_ALPHA(alpha)' : ''} include.vertex vertex = " - uniform highp mat4 uMvpMatrix; + uniform mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - attribute highp vec2 aUV; - attribute highp vec4 aBounds; // diffuse map - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds; + in vec4 aVertex; + in vec4 aColor; + in vec2 aUV; + in vec4 aBounds; // diffuse map + + out vec4 vColor; + out vec2 vUV; + out vec4 vUVBounds; void main(void) { - highp mat4 bone = vertexBoneTransform(); + mat4 bone = vertexBoneTransform(); // Vertex position. - highp vec4 modelPos = bone * aVertex; + vec4 modelPos = bone * aVertex; gl_Position = uMvpMatrix * modelPos; vColor = aColor; @@ -358,28 +381,34 @@ include.fragment fragment = " - uniform highp float uAlphaLimit; - uniform highp float uAlpha; - uniform highp vec3 uColor; // diffuse color multiplier - uniform highp vec2 uOffsetUV; - uniform highp float uMapTime; - - varying highp vec4 vColor; - varying highp vec2 vUV; - varying highp vec4 vUVBounds; + uniform float uAlphaLimit; + uniform float uAlpha; + uniform vec3 uColor; // diffuse color multiplier + uniform vec2 uOffsetUV; + uniform float uMapTime; + + in vec4 vColor; + in vec2 vUV; + in vec4 vUVBounds; void main(void) { // Calculate UV at the fragment (wrapped inside the bounds). - highp vec2 wrappedUV = vUV + uOffsetUV; + vec2 wrappedUV = vUV + uOffsetUV; + #if defined (PREDEF_TRANSFORM_UV) PREDEF_TRANSFORM_UV(wrappedUV); + #endif wrappedUV = fract(wrappedUV); - highp vec2 uv = mapToBounds(wrappedUV, vUVBounds); + vec2 uv = mapToBounds(wrappedUV, vUVBounds); - highp vec4 diffuse = vColor * texture2D(uTex, uv); - if(diffuse.a < uAlphaLimit) discard; + vec4 diffuse = vColor * texture(uTex, uv); + if (diffuse.a < uAlphaLimit) discard; - gl_FragColor = diffuse * vec4(uColor, uAlpha); + float alphaFactor = uAlpha; + #if defined (PREDEF_TRANSFORM_ALPHA) + PREDEF_TRANSFORM_ALPHA(alphaFactor); + #endif + out_FragColor = diffuse * vec4(uColor, alphaFactor); }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/ui.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/ui.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/ui.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders/ui.dei 2018-12-11 07:08:18.000000000 +0000 @@ -2,20 +2,20 @@ # Shader for UI widgets. shader guiwidget.batch { vertex = " - uniform highp mat4 uMvpMatrix; - uniform highp vec4 uColor[DENG_MAX_BATCH_UNIFORMS]; - uniform highp float uSaturation[DENG_MAX_BATCH_UNIFORMS]; - uniform highp vec4 uScissorRect[DENG_MAX_BATCH_UNIFORMS]; + uniform mat4 uMvpMatrix; + uniform vec4 uColor[DENG_MAX_BATCH_UNIFORMS]; + uniform float uSaturation[DENG_MAX_BATCH_UNIFORMS]; + uniform vec4 uScissorRect[DENG_MAX_BATCH_UNIFORMS]; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - attribute highp float aIndex; // uColor + in vec4 aVertex; + in vec2 aUV; + in vec4 aColor; + in float aIndex; // uColor - varying highp vec2 vUV; - varying highp vec4 vColor; - varying highp vec4 vScissor; - varying highp float vSaturation; + out vec2 vUV; + out vec4 vColor; + out vec4 vScissor; + out float vSaturation; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -26,32 +26,33 @@ vScissor = uScissorRect[index]; vSaturation = uSaturation[index]; }" - include.fragment fragment = " + #include 'include/hsv.glsl' + uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; - varying highp vec4 vScissor; - varying highp float vSaturation; - + in vec2 vUV; + in vec4 vColor; + in vec4 vScissor; + in float vSaturation; + void main(void) { // Check the scissor first. if (gl_FragCoord.x < vScissor.x || gl_FragCoord.x > vScissor.z || gl_FragCoord.y < vScissor.y || gl_FragCoord.y > vScissor.w) { discard; } - gl_FragColor = texture2D(uTex, vUV); + out_FragColor = texture(uTex, vUV); // Optionally adjust color saturation. if (vSaturation < 1.0) { - highp vec4 hsv = rgbToHsv(gl_FragColor); + highp vec4 hsv = rgbToHsv(out_FragColor); hsv.y *= vSaturation; - gl_FragColor = hsvToRgb(hsv); + out_FragColor = hsvToRgb(hsv); } // Final vertex color. - gl_FragColor *= vColor; + out_FragColor *= vColor; }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/net.dengine.client.pack/renderer.pack/shaders.dei 2018-12-11 07:08:18.000000000 +0000 @@ -8,6 +8,7 @@ # - vertex: source of the vertex shader # - fragment: source of the fragment shader +@include @include @include @include Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon20x20@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon20x20@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon20x20@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon20x20@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon20x20@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon20x20@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon20x20~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon20x20~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon29x29@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon29x29@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon29x29@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon29x29@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon29x29@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon29x29@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon29x29~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon29x29~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon40x40@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon40x40@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon40x40@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon40x40@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon40x40@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon40x40@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon40x40~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon40x40~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon50x50@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon50x50@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon50x50~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon50x50~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon57x57@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon57x57@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon57x57.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon57x57.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon60x60@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon60x60@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon60x60@3x~car.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon60x60@3x~car.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon60x60@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon60x60@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon72x72@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon72x72@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon72x72~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon72x72~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon76x76@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon76x76@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon76x76~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon76x76~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/AppIcon83.5x83.5@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/AppIcon83.5x83.5@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/Doomsday.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/Doomsday.png differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/LaunchScreen.xib doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/LaunchScreen.xib --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/ios/LaunchScreen.xib 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/ios/LaunchScreen.xib 2018-12-11 07:08:18.000000000 +0000 @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/macx/English.lproj/InfoPlist.strings and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/macx/English.lproj/InfoPlist.strings differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/qml/client.qrc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/qml/client.qrc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/qml/client.qrc 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/qml/client.qrc 2018-12-11 07:08:19.000000000 +0000 @@ -0,0 +1,5 @@ + + + main.qml + + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/qml/main.qml doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/qml/main.qml --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/qml/main.qml 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/qml/main.qml 2018-12-11 07:08:19.000000000 +0000 @@ -0,0 +1,91 @@ +import QtQuick 2.7 +import Doomsday 1.0 + +Item { + width: 320 + height: 480 + + ClientWindow { + id: mainWin + x: 0 + y: 0 + width: parent.width + height: parent.height + focus: true + /*SequentialAnimation on t { + NumberAnimation { to: 1; duration: 2500; easing.type: Easing.InQuad } + NumberAnimation { to: 0; duration: 2500; easing.type: Easing.OutQuad } + loops: Animation.Infinite + running: true + }*/ + onTextEntryRequest: { + console.log("text entry requested"); + keyInput.focus = true; + } + onTextEntryDismiss: { + console.log("text entry dismissed"); + keyInput.focus = false; + mainWin.focus = true; + } + + Connections { + target: Qt.inputMethod + onVisibleChanged: { + if (Qt.inputMethod.visible) { + mainWin.height = parent.height - Qt.inputMethod.keyboardRectangle.height; + console.log("update dimensions:", mainWin.height); + mainWin.dimensionsChanged(); + } + else { + console.log("inputMethod visibility:", Qt.inputMethod.visible); + mainWin.userFinishedTextEntry(); + keyInput.focus = false; + mainWin.focus = true; + mainWin.height = parent.height; + mainWin.dimensionsChanged(); + } + } + } + } + + /*Rectangle { + color: Qt.rgba(1, 1, 1, 0.7) + radius: 10 + border.width: 1 + border.color: "white" + anchors.fill: label + anchors.margins: -10 + } + + Text { + id: label + color: "black" + wrapMode: Text.WordWrap + text: mainWin.activeFocus? "I have active focus!" : "I do not have active focus" + anchors.right: parent.right + anchors.left: parent.left + anchors.bottom: parent.bottom + anchors.margins: 20 + }*/ + + MultiPointTouchArea { + anchors.fill: parent + onPressed: mainWin.onTouchPressed(touchPoints) + onUpdated: mainWin.onTouchUpdated(touchPoints) + onReleased: mainWin.onTouchReleased(touchPoints) + } + + TextInput { + id: keyInput + visible: false + onTextChanged: { + mainWin.userEnteredText(text); + } +// onFocusChanged: { +// if (!focus) { +// mainWin.height = parent.height; +// mainWin.dimensionsChanged(); +// } +// } + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/windows/doomsday.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/windows/doomsday.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/res/windows/doomsday.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/res/windows/doomsday.rc 2018-12-11 07:08:19.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2009 Daniel Swanson + *\author Copyright (c) 2008-2009 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -82,7 +82,7 @@ " VALUE ""FileDescription"", ""Doomsday Engine\0""\r\n" " VALUE ""FileVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", ""Doomsday Engine\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""Doomsday.exe\0""\r\n" " VALUE ""ProductName"", ""Doomsday Engine\0""\r\n" " VALUE ""ProductVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" @@ -128,11 +128,11 @@ BEGIN BLOCK "040904E4" BEGIN - VALUE "CompanyName", "Open Source Developer, Jaakko Keränen\0" + VALUE "CompanyName", "Open Source Developer, Jaakko Keränen\0" VALUE "FileDescription", "Doomsday Engine\0" VALUE "FileVersion", DOOMSDAY_VERSION_TEXT "\0" VALUE "InternalName", "Doomsday Engine\0" - VALUE "LegalCopyright", "Copyright © 2003-2016, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "Doomsday.exe\0" VALUE "ProductName", "Doomsday Engine\0" VALUE "ProductVersion", DOOMSDAY_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/api_map.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/api_map.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/api_map.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/api_map.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -1392,14 +1392,14 @@ DENG_EXTERN_C dd_bool P_MapExists(char const *uriCString) { if(!uriCString || !uriCString[0]) return false; - return App_Resources().mapManifests().tryFindMapManifest(de::Uri(uriCString, RC_NULL)) != nullptr; + return App_Resources().mapManifests().tryFindMapManifest(de::makeUri(uriCString)) != nullptr; } #undef P_MapIsCustom DENG_EXTERN_C dd_bool P_MapIsCustom(char const *uriCString) { if(!uriCString || !uriCString[0]) return false; - if(res::MapManifest const *mapDef = App_Resources().mapManifests().tryFindMapManifest(de::Uri(uriCString, RC_NULL))) + if(res::MapManifest const *mapDef = App_Resources().mapManifests().tryFindMapManifest(de::makeUri(uriCString))) { return mapDef->sourceFile()->hasCustom(); } @@ -1410,7 +1410,7 @@ DENG_EXTERN_C AutoStr *P_MapSourceFile(char const *uriCString) { if(!uriCString || !uriCString[0]) return nullptr; - if(res::MapManifest const *mapDef = App_Resources().mapManifests().tryFindMapManifest(de::Uri(uriCString, RC_NULL))) + if(res::MapManifest const *mapDef = App_Resources().mapManifests().tryFindMapManifest(de::makeUri(uriCString))) { return AutoStr_FromTextStd(mapDef->sourceFile()->composePath().toUtf8().constData()); } @@ -1445,7 +1445,7 @@ } #endif - return (dd_bool) App_World().changeMap(de::Uri(uriCString, RC_NULL)); + return (dd_bool) App_World().changeMap(de::makeUri(uriCString)); } #undef P_CountMapObjs diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/audiodriver.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/audiodriver.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/audiodriver.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/audiodriver.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -57,9 +57,7 @@ LibraryFile *found = nullptr; Library_ForAll([&name, &found] (LibraryFile &lib) { - // Plugins are native files. - if (is(lib.source()) && - lib.hasUnderscoreName(name)) + if (lib.hasUnderscoreName(name)) { found = &lib; return LoopAbort; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/base/audiosystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/base/audiosystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/base/audiosystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/base/audiosystem.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -51,10 +51,12 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include @@ -190,6 +192,8 @@ , DENG2_OBSERVES(audio::SfxSampleCache, SampleRemove) #endif { + Record module; + #ifdef __CLIENT__ AudioDriver drivers[AUDIODRIVER_COUNT]; @@ -204,7 +208,7 @@ */ audiodriverid_t chooseAudioDriver() { - CommandLine &cmdLine = App::commandLine(); + CommandLine &cmdLine = CommandLine::get(); // No audio output? if (::isDedicated) @@ -310,7 +314,10 @@ { activeInterfaces.clear(); - if (App::commandLine().has("-nosound")) + // The audio drivers may use Audio.outputs to declare which outputs are available. + module.set("outputs", new DictionaryValue); + + if (CommandLine::get().has("-nosound")) return false; audiodriverid_t defaultDriverId = chooseAudioDriver(); @@ -339,6 +346,8 @@ drivers[i].deinitialize(); } + module.set("outputs", new DictionaryValue); + // Unload the plugins after everything has been shut down. for (AudioDriver &driver : drivers) { @@ -466,12 +475,12 @@ activeInterfaces << ifs; // a copy is made } - String userSfx = App::config("audio.soundPlugin"); - String userMusic = App::config("audio.musicPlugin"); - String userCD = App::config("audio.cdPlugin"); + String userSfx = Config::get("audio.soundPlugin"); + String userMusic = Config::get("audio.musicPlugin"); + String userCD = Config::get("audio.cdPlugin"); // Command line options may also be used to specify which plugin to use. - CommandLine &cmdLine = App::commandLine(); + CommandLine &cmdLine = CommandLine::get(); if (auto arg = cmdLine.check("-isfx", 1)) { userSfx = arg.params.at(0); @@ -640,6 +649,8 @@ { theAudioSystem = thisPublic; + ScriptSystem::get().addNativeModule("Audio", module); + #ifdef __CLIENT__ DoomsdayApp::app().audienceForGameUnload() += this; sfxSampleCache.audienceForSampleRemove() += this; @@ -720,7 +731,8 @@ if (iMusic->PlayFile) { // Write the data to disk and play from there. - File &file = App::rootFolder().replaceFile(composeMusicBufferFilename(path.fileNameExtension())); + File &file = FS::rootFolder().replaceFile( + composeMusicBufferFilename(path.fileNameExtension())); Block buf(hndl->length()); hndl->read(buf.data(), buf.size()); file << buf; @@ -765,7 +777,7 @@ // Lump is in DOOM's MUS format. We must first convert it to MIDI. if (!canPlayMUS) return -1; - File &midi = App::rootFolder().replaceFile(composeMusicBufferFilename(".mid")); + File &midi = FS::rootFolder().replaceFile(composeMusicBufferFilename(".mid")); // Read the lump, convert to MIDI and output to a temp file in the working directory. // Use a filename with the .mid extension so that any player which relies on the it @@ -812,7 +824,7 @@ // Failed to write the lump... return 0; } - return iMusic->PlayFile(App::rootFolder().locate(bufName) + return iMusic->PlayFile(FS::rootFolder().locate(bufName) .as().nativePath().toUtf8(), looped); } @@ -850,7 +862,7 @@ musCurrentSong = ""; musPaused = false; - CommandLine &cmdLine = App::commandLine(); + CommandLine &cmdLine = CommandLine::get(); if (::isDedicated || cmdLine.has("-nomusic")) { LOG_AUDIO_NOTE("Music disabled"); @@ -930,7 +942,7 @@ if (sfxAvail) return; // Check if sound has been disabled with a command line option. - if (App::commandLine().has("-nosfx")) + if (CommandLine::get().has("-nosfx")) { LOG_AUDIO_NOTE("Sound effects disabled"); return; @@ -1089,14 +1101,19 @@ // Create channels according to the current mode. void initSfxChannels() { - dint numChannels = SOUND_CHANNEL_COUNT_DEFAULT; // The -sfxchan option can be used to change the number of channels. if (CommandLine_CheckWith("-sfxchan", 1)) { - numChannels = de::clamp(1, String(CommandLine_Next()).toInt(), SOUND_CHANNEL_COUNT_MAX); - LOG_AUDIO_NOTE("Initialized %i sound effect channels") << numChannels; + Config::get().set("audio.channels", String(CommandLine_Next()).toInt()); + + //numChannels = de::clamp(1, String(CommandLine_Next()).toInt(), SOUND_CHANNEL_COUNT_MAX); } + dint numChannels = Config::get().geti("audio.channels", SOUND_CHANNEL_COUNT_DEFAULT); + numChannels = Rangei(1, SOUND_CHANNEL_COUNT_MAX).clamp(numChannels); + + LOG_AUDIO_NOTE("Initializing %i sound effect channels") << numChannels; + // Allocate and init the channels. sfxChannels.reset(new audio::SfxChannels(numChannels)); createSfxChannels(); @@ -1621,7 +1638,7 @@ { LOG_AS("AudioSystem"); - CommandLine &cmdLine = App::commandLine(); + CommandLine &cmdLine = CommandLine::get(); if (cmdLine.has("-nosound") || cmdLine.has("-noaudio")) return; @@ -1752,7 +1769,10 @@ // We will not restart the currently playing song. if (definition.gets("id") == d->musCurrentSong && musicIsPlaying()) - return false; + { + // This is not a failure, though, since the right music is played. + return true; + } // Stop the currently playing song. stopMusic(); @@ -1806,7 +1826,7 @@ // Next, try non-MUS lumps. canPlayMUS = false; - // Note: Intentionally falls through to MUSP_MUS. + // Note: Intentionally falls through to MUSP_MUS. case MUSP_MUS: if (d->playMusicLump(App_FileSystem().lumpNumForName(definition.gets("lumpName")), @@ -1850,15 +1870,13 @@ LOG_AS("AudioSystem"); NativePath path(musMidiFontPath); -#ifdef MACOSX - // On macOS we can try to use the basic DLS soundfont that's part of CoreAudio. if (path.isEmpty()) { - path = "/System/Library/Components/CoreAudio.component/Contents/Resources/gs_instruments.dls"; + // The bootstrap script copies the default GeneralUser GS soundfont from the + // client's package so it can be loaded by FluidSynth. + path = App::app().nativeHomePath()/"cache/default.sf2"; } -#endif - - d->setMusicProperty(AUDIOP_SOUNDFONT_FILENAME, path.expand().toString().toLatin1().constData()); + d->setMusicProperty(AUDIOP_SOUNDFONT_FILENAME, path.expand().toString().toUtf8().constData()); } bool AudioSystem::sfxIsAvailable() const @@ -2616,6 +2634,31 @@ App_AudioSystem().updateMusicMidiFont(); } +D_CMD(ReverbParameters) +{ + DENG2_UNUSED2(src, argc); + + dfloat args[NUM_REVERB_DATA]; + + args[SFXLP_REVERB_VOLUME ] = String(argv[1]).toFloat(); + args[SFXLP_REVERB_SPACE ] = String(argv[2]).toFloat(); + args[SFXLP_REVERB_DECAY ] = String(argv[3]).toFloat(); + args[SFXLP_REVERB_DAMPING] = String(argv[4]).toFloat(); + + LOG_SCR_MSG("Setting reverb parameters:\n" + "- volume: %f\n" + "- space: %f\n" + "- decay: %f\n" + "- damping: %f") + << args[SFXLP_REVERB_VOLUME ] + << args[SFXLP_REVERB_SPACE ] + << args[SFXLP_REVERB_DECAY ] + << args[SFXLP_REVERB_DAMPING]; + + App_AudioSystem().sfx()->Listenerv(SFXLP_REVERB, args); + + return true; +} #endif // __CLIENT__ void AudioSystem::consoleRegister() // static @@ -2642,6 +2685,8 @@ C_CMD_FLAGS("playmusic", nullptr, PlayMusic, CMDF_NO_DEDICATED); C_CMD_FLAGS("stopmusic", "", StopMusic, CMDF_NO_DEDICATED); + C_CMD("reverbparams", "ffff", ReverbParameters); + // Debug: C_VAR_INT ("sound-info", &showSoundInfo, 0, 0, 1); #endif @@ -2724,7 +2769,7 @@ if (musicId >= 0 && musicId < DED_Definitions()->musics.size()) { - Record const &def = DED_Definitions()->musics[musicId]; + const Record &def = DED_Definitions()->musics[musicId]; return Mus_Start(def, looped); } return false; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/sfxchannel.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/sfxchannel.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/sfxchannel.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/sfxchannel.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -59,20 +59,21 @@ Vector3d findOrigin() const { // Originless sounds have no fixed/moveable emission point. - if(flags & SFXCF_NO_ORIGIN) + if (flags & SFXCF_NO_ORIGIN) { return Vector3d(); } // When tracking an emitter - use it's origin. - if(emitter) + if (emitter) { Vector3d point(emitter->origin); // Position on the Z axis at the map-object's center? - if(Thinker_HasMobjFunc(emitter->thinker.function)) + if (Thinker_IsMobj(&emitter->thinker)) + { point.z += emitter->height / 2; - + } return point; } @@ -99,7 +100,7 @@ sfxbuffer_t &SfxChannel::buffer() { - if(d->buffer) return *d->buffer; + if (d->buffer) return *d->buffer; /// @throw MissingBufferError No sound buffer is currently assigned. throw MissingBufferError("SfxChannel::buffer", "No sound buffer is assigned"); } @@ -116,7 +117,7 @@ void SfxChannel::stop() { - if(!d->buffer) return; + if (!d->buffer) return; /// @todo AudioSystem should observe. -ds App_AudioSystem().sfx()->Stop(d->buffer); @@ -177,10 +178,10 @@ dfloat SfxChannel::priority() const { - if(!d->buffer || !(d->buffer->flags & SFXBF_PLAYING)) + if (!d->buffer || !(d->buffer->flags & SFXBF_PLAYING)) return SFX_LOWEST_PRIORITY; - if(d->flags & SFXCF_NO_ORIGIN) + if (d->flags & SFXCF_NO_ORIGIN) return App_AudioSystem().rateSoundPriority(0, 0, d->volume, d->startTime); // d->origin is set to emitter->xyz during updates. @@ -192,13 +193,13 @@ { // If no sound buffer is assigned we've no need to update. sfxbuffer_t *sbuf = d->buffer; - if(!sbuf) return; + if (!sbuf) return; // Disabled? - if(d->flags & SFXCF_NO_UPDATE) return; + if (d->flags & SFXCF_NO_UPDATE) return; // Update the sound origin if needed. - if(d->emitter) + if (d->emitter) { d->updateOrigin(); } @@ -206,11 +207,11 @@ // Frequency is common to both 2D and 3D sounds. App_AudioSystem().sfx()->Set(sbuf, SFXBP_FREQUENCY, d->frequency); - if(sbuf->flags & SFXBF_3D) + if (sbuf->flags & SFXBF_3D) { // Volume is affected only by maxvol. App_AudioSystem().sfx()->Set(sbuf, SFXBP_VOLUME, d->volume * ::sfxVolume / 255.0f); - if(d->emitter && d->emitter == App_AudioSystem().sfxListener()) + if (d->emitter && d->emitter == App_AudioSystem().sfxListener()) { // Emitted by the listener object. Go to relative position mode // and set the position to (0,0,0). @@ -228,8 +229,8 @@ } // If the sound is emitted by the listener, speed is zero. - if(d->emitter && d->emitter != App_AudioSystem().sfxListener() && - Thinker_HasMobjFunc(d->emitter->thinker.function)) + if (d->emitter && d->emitter != App_AudioSystem().sfxListener() && + Thinker_IsMobj(&d->emitter->thinker)) { dfloat vec[3]; vec[0] = d->emitter->mom[0] * TICSPERSEC; @@ -250,7 +251,7 @@ dfloat pan = 0; // This is a 2D buffer. - if((d->flags & SFXCF_NO_ORIGIN) || + if ((d->flags & SFXCF_NO_ORIGIN) || (d->emitter && d->emitter == App_AudioSystem().sfxListener())) { dist = 1; @@ -260,12 +261,12 @@ { // Calculate roll-off attenuation. [.125/(.125+x), x=0..1] dist = Mobj_ApproxPointDistance(App_AudioSystem().sfxListener(), d->origin); - if(dist < ::soundMinDist || (d->flags & SFXCF_NO_ATTENUATION)) + if (dist < ::soundMinDist || (d->flags & SFXCF_NO_ATTENUATION)) { // No distance attenuation. dist = 1; } - else if(dist > ::soundMaxDist) + else if (dist > ::soundMaxDist) { // Can't be heard. dist = 0; @@ -280,16 +281,16 @@ } // And pan, too. Calculate angle from listener to emitter. - if(mobj_t *listener = App_AudioSystem().sfxListener()) + if (mobj_t *listener = App_AudioSystem().sfxListener()) { dfloat angle = (M_PointToAngle2(listener->origin, d->origin) - listener->angle) / (dfloat) ANGLE_MAX * 360; // We want a signed angle. - if(angle > 180) + if (angle > 180) angle -= 360; // Front half. - if(angle <= 90 && angle >= -90) + if (angle <= 90 && angle >= -90) { pan = -angle / 90; } @@ -338,10 +339,10 @@ /// @todo support dynamically resizing in both directions. -ds void resize(dint newSize) { - if(newSize < 0) newSize = 0; + if (newSize < 0) newSize = 0; clearAll(); - for(dint i = 0; i < newSize; ++i) + for (dint i = 0; i < newSize; ++i) { all << new SfxChannel; } @@ -365,10 +366,10 @@ dint count = 0; forAll([&id, &count] (SfxChannel &ch) { - if(ch.hasBuffer()) + if (ch.hasBuffer()) { sfxbuffer_t &sbuf = ch.buffer(); - if((sbuf.flags & SFXBF_PLAYING) && sbuf.sample && sbuf.sample->id == id) + if ((sbuf.flags & SFXBF_PLAYING) && sbuf.sample && sbuf.sample->id == id) { count += 1; } @@ -380,27 +381,27 @@ SfxChannel *SfxChannels::tryFindVacant(bool use3D, dint bytes, dint rate, dint sampleId) const { - for(SfxChannel *ch : d->all) + for (SfxChannel *ch : d->all) { - if(!ch->hasBuffer()) continue; + if (!ch->hasBuffer()) continue; sfxbuffer_t const &sbuf = ch->buffer(); - if((sbuf.flags & SFXBF_PLAYING) + if ((sbuf.flags & SFXBF_PLAYING) || use3D != ((sbuf.flags & SFXBF_3D) != 0) || sbuf.bytes != bytes || sbuf.rate != rate) continue; // What about the sample? - if(sampleId > 0) + if (sampleId > 0) { - if(!sbuf.sample || sbuf.sample->id != sampleId) + if (!sbuf.sample || sbuf.sample->id != sampleId) continue; } - else if(sampleId == 0) + else if (sampleId == 0) { // We're trying to find a channel with no sample already loaded. - if(sbuf.sample) + if (sbuf.sample) continue; } @@ -415,7 +416,7 @@ { forAll([] (SfxChannel &ch) { - if(ch.hasBuffer() && (ch.buffer().flags & SFXBF_PLAYING)) + if (ch.hasBuffer() && (ch.buffer().flags & SFXBF_PLAYING)) { App_AudioSystem().sfx()->Refresh(&ch.buffer()); } @@ -425,9 +426,9 @@ LoopResult SfxChannels::forAll(std::function func) const { - for(SfxChannel *ch : d->all) + for (SfxChannel *ch : d->all) { - if(auto result = func(*ch)) return result; + if (auto result = func(*ch)) return result; } return LoopContinue; } @@ -443,32 +444,32 @@ void Sfx_ChannelDrawer() { - if(!::showSoundInfo) return; + if (!::showSoundInfo) return; DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Go into screen projection mode. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); FR_SetColorAndAlpha(1, 1, 0, 1); dint const lh = FR_SingleLineHeight("Q"); - if(!App_AudioSystem().sfxIsAvailable()) + if (!App_AudioSystem().sfxIsAvailable()) { FR_DrawTextXY("Sfx disabled", 0, 0); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); return; } - if(::refMonitor) + if (::refMonitor) FR_DrawTextXY("!", 0, 0); // Sample cache information. @@ -483,7 +484,7 @@ dint idx = 0; App_AudioSystem().sfxChannels().forAll([&lh, &idx] (audio::SfxChannel &ch) { - if(ch.hasBuffer() && (ch.buffer().flags & SFXBF_PLAYING)) + if (ch.hasBuffer() && (ch.buffer().flags & SFXBF_PLAYING)) { FR_SetColor(1, 1, 1); } @@ -493,7 +494,7 @@ } Block emitterText; - if(ch.emitter()) + if (ch.emitter()) { emitterText = ( " mobj:" + String::number(ch.emitter()->thinker.id) + " pos:" + ch.origin().asText() @@ -511,7 +512,7 @@ emitterText.constData()); FR_DrawTextXY(buf, 5, lh * (1 + idx * 2)); - if(ch.hasBuffer()) + if (ch.hasBuffer()) { sfxbuffer_t &sbuf = ch.buffer(); @@ -532,9 +533,9 @@ return LoopContinue; }); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); // Back to the original. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/sys_audiod_sdlmixer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/sys_audiod_sdlmixer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/audio/sys_audiod_sdlmixer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/audio/sys_audiod_sdlmixer.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -64,7 +64,8 @@ void DS_SDLMixer_Music_Stop(void); int DS_SDLMixer_Music_PlayFile(const char* fileName, int looped); -dd_bool sdlInitOk = false; +static dd_bool sdlInitOk = false; +static float musicVolume = 1.f; audiodriver_t audiod_sdlmixer = { DS_SDLMixerInit, @@ -134,7 +135,7 @@ */ static unsigned int getBufLength(sfxbuffer_t* buf) { - if(!buf) + if (!buf) return 0; return 1000 * buf->sample->numSamples / buf->freq; @@ -147,10 +148,10 @@ SDL_version compVer; const SDL_version* linkVer; - if(sdlInitOk) + if (sdlInitOk) return true; - if(SDL_InitSubSystem(SDL_INIT_AUDIO)) + if (SDL_InitSubSystem(SDL_INIT_AUDIO)) { LOG_AUDIO_ERROR("Error initializing SDL audio: %s") << SDL_GetError(); return false; @@ -159,7 +160,7 @@ SDL_MIXER_VERSION(&compVer); linkVer = Mix_Linked_Version(); - if(SDL_VERSIONNUM(linkVer->major, linkVer->minor, linkVer->patch) > + if (SDL_VERSIONNUM(linkVer->major, linkVer->minor, linkVer->patch) > SDL_VERSIONNUM(compVer.major, compVer.minor, compVer.patch)) { LOG_AUDIO_WARNING("Linked version of SDL_mixer (%u.%u.%u) is " @@ -168,7 +169,7 @@ << compVer.major << compVer.minor << compVer.patch; } - if(Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024)) + if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, MIX_DEFAULT_FORMAT, 2, 1024)) { LOG_AUDIO_ERROR("Failed initializing SDL_mixer: %s") << Mix_GetError(); return false; @@ -198,12 +199,12 @@ void DS_SDLMixerShutdown(void) { - if(!sdlInitOk) + if (!sdlInitOk) return; usedChannels.clear(); - if(lastMusic) + if (lastMusic) { Mix_HaltMusic(); Mix_FreeMusic(lastMusic); @@ -265,7 +266,7 @@ Mix_HaltChannel(buf->cursor); usedChannels[buf->cursor] = false; - if(buf) + if (buf) Z_Free(buf); } @@ -275,14 +276,14 @@ char* conv = NULL; size_t size; - if(!buf || !sample) + if (!buf || !sample) return; // Wha? // Does the buffer already have a sample loaded? - if(buf->sample) + if (buf->sample) { // Is the same one? - if(buf->sample->id == sample->id) + if (buf->sample->id == sample->id) return; // Free the existing data. @@ -291,7 +292,7 @@ } size = 8 + 4 + 8 + 16 + 8 + sample->size; - if(size <= sizeof(localBuf)) + if (size <= sizeof(localBuf)) { conv = localBuf; } @@ -329,13 +330,13 @@ memcpy(conv + 44, sample->data, sample->size); buf->ptr = Mix_LoadWAV_RW(SDL_RWFromMem(conv, 44 + sample->size), 1); - if(!buf->ptr) + if (!buf->ptr) { LOG_AS("DS_SDLMixer_SFX_Load"); LOG_AUDIO_WARNING("Failed loading sample: %s") << Mix_GetError(); } - if(conv != localBuf) + if (conv != localBuf) { M_Free(conv); } @@ -348,7 +349,7 @@ */ void DS_SDLMixer_SFX_Reset(sfxbuffer_t* buf) { - if(!buf) + if (!buf) return; DS_SDLMixer_SFX_Stop(buf); @@ -362,7 +363,7 @@ void DS_SDLMixer_SFX_Play(sfxbuffer_t* buf) { // Playing is quite impossible without a sample. - if(!buf || !buf->sample) + if (!buf || !buf->sample) return; // Update the volume at which the sample will be played. @@ -378,7 +379,7 @@ void DS_SDLMixer_SFX_Stop(sfxbuffer_t* buf) { - if(!buf || !buf->sample) + if (!buf || !buf->sample) return; Mix_HaltChannel(buf->cursor); @@ -390,7 +391,7 @@ unsigned int nowTime; // Can only be done if there is a sample and the buffer is playing. - if(!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) + if (!buf || !buf->sample || !(buf->flags & SFXBF_PLAYING)) return; nowTime = Timer_RealMilliseconds(); @@ -401,7 +402,7 @@ * since the millisecond counter overflows. It only affects sounds that * are playing while the overflow happens, though. */ - if(!(buf->flags & SFXBF_REPEAT) && nowTime >= buf->endTime) + if (!(buf->flags & SFXBF_REPEAT) && nowTime >= buf->endTime) { // Time for the sound to stop. buf->flags &= ~SFXBF_PLAYING; @@ -412,10 +413,10 @@ { int right; - if(!buf) + if (!buf) return; - switch(prop) + switch (prop) { case SFXBP_VOLUME: // 'written' is used for storing the volume of the channel. @@ -469,13 +470,17 @@ void DS_SDLMixer_Music_Set(int prop, float value) { - if(!sdlInitOk) + if (!sdlInitOk) return; - switch(prop) + switch (prop) { case MUSIP_VOLUME: - Mix_VolumeMusic((int) (MIX_MAX_VOLUME * value)); + musicVolume = value; + if (Mix_PlayingMusic()) + { + Mix_VolumeMusic((int)(MIX_MAX_VOLUME * value)); + } break; default: @@ -485,10 +490,10 @@ int DS_SDLMixer_Music_Get(int prop, void* value) { - if(!sdlInitOk) + if (!sdlInitOk) return false; - switch(prop) + switch (prop) { case MUSIP_ID: strcpy((char *) value, "SDLMixer::Music"); @@ -505,10 +510,10 @@ void DS_SDLMixer_Music_Pause(int pause) { - if(!sdlInitOk) + if (!sdlInitOk) return; - if(pause) + if (pause) Mix_PauseMusic(); else Mix_ResumeMusic(); @@ -516,7 +521,7 @@ void DS_SDLMixer_Music_Stop(void) { - if(!sdlInitOk) + if (!sdlInitOk) return; Mix_HaltMusic(); @@ -524,24 +529,29 @@ int DS_SDLMixer_Music_PlayFile(const char* filename, int looped) { - if(!sdlInitOk) + if (!sdlInitOk) return false; // Free any previously loaded music. - if(lastMusic) + if (lastMusic) { Mix_HaltMusic(); Mix_FreeMusic(lastMusic); } - if(!(lastMusic = Mix_LoadMUS(filename))) + if (!(lastMusic = Mix_LoadMUS(filename))) { LOG_AS("DS_SDLMixer_Music_PlayFile"); LOG_AUDIO_ERROR("Failed to load music: %s") << Mix_GetError(); return false; } - return !Mix_PlayMusic(lastMusic, looped ? -1 : 1); + int result = !Mix_PlayMusic(lastMusic, looped ? -1 : 1); + if (result) + { + Mix_VolumeMusic((int)(MIX_MAX_VOLUME * musicVolume)); + } + return result; } #endif // DENG_DISABLE_SDLMIXER diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/busyrunner.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/busyrunner.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/busyrunner.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/busyrunner.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -49,7 +49,7 @@ static bool animatedTransitionActive(int busyMode) { - return (!novideo && !isDedicated && !netGame && !(busyMode & BUSYF_STARTUP) && + return (!novideo && !netGame && !(busyMode & BUSYF_STARTUP) && rTransitionTics > 0 && (busyMode & BUSYF_TRANSITION)); } @@ -347,7 +347,9 @@ DoomsdayApp::app().busyMode().taskRunner() && App::inMainThread()) { +#if !defined (DENG_MOBILE) ClientWindow::main().busy().renderTransitionFrame(); +#endif } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/client/clientsubsector.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/client/clientsubsector.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/client/clientsubsector.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/client/clientsubsector.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -1027,10 +1027,10 @@ ds.markForUpdate(false); - // Clear any existing decorations. qDeleteAll(ds.decorations); ds.decorations.clear(); + // Clear any existing decorations. if (surface.hasMaterial()) { Vector2f materialOrigin; @@ -1471,7 +1471,7 @@ return (bool(d->boundaryData->outerLoop) ? 1 : 0) + d->boundaryData->innerLoops.count(); } -LoopResult ClientSubsector::forAllEdgeLoops(std::function func) +LoopResult ClientSubsector::forAllEdgeLoops(const std::function &func) { d->initBoundaryDataIfNeeded(); DENG2_ASSERT(bool(d->boundaryData->outerLoop)); @@ -1487,7 +1487,7 @@ return LoopContinue; } -LoopResult ClientSubsector::forAllEdgeLoops(std::function func) const +LoopResult ClientSubsector::forAllEdgeLoops(const std::function &func) const { d->initBoundaryDataIfNeeded(); DENG2_ASSERT(bool(d->boundaryData->outerLoop)); @@ -1848,14 +1848,16 @@ { LOG_AS("ClientSubsector::decorate"); - auto decorateFunc = [this] (Surface &surface) - { - d->decorate(surface); - return LoopContinue; - }; + if (!hasDecorations()) return; + +// auto decorateFunc = [this] (Surface &surface) +// { +// d->decorate(surface); +// return LoopContinue; +// }; // Surfaces of the edge loops. - forAllEdgeLoops([this, &decorateFunc] (ClEdgeLoop const &loop) + forAllEdgeLoops([this/*, &decorateFunc*/] (ClEdgeLoop const &loop) { SubsectorCirculator it(&loop.first()); do diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/client/cl_mobj.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/client/cl_mobj.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/client/cl_mobj.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/client/cl_mobj.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -536,7 +536,7 @@ // different than the server-side floor. if (!d->dPlayer && onFloor && gx.MobjCheckPositionXYZ) { - if (coord_t *floorZ = (coord_t *) gx.GetVariable(DD_TM_FLOOR_Z)) + if (coord_t *floorZ = (coord_t *) gx.GetPointer(DD_TM_FLOOR_Z)) { gx.MobjCheckPositionXYZ(d, d->origin[VX], d->origin[VY], DDMAXFLOAT); d->origin[VZ] = d->floorZ = *floorZ; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/clientapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/clientapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/clientapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/clientapp.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -85,7 +86,7 @@ #include "ui/viewcompositor.h" #include "ui/widgets/taskbarwidget.h" #include "updater.h" -#include "updater/downloaddialog.h" +#include "updater/updatedownloaddialog.h" #include "world/contact.h" #include "world/map.h" #include "world/p_players.h" @@ -113,11 +114,15 @@ { if (!ClientWindowSystem::mainExists()) return; +#if !defined (DENG_MOBILE) // Show the main window. This causes initialization to finish (in busy mode) // as the canvas is visible and ready for initialization. ClientWindowSystem::main().show(); +#endif +#if defined (DENG_HAVE_UPDATER) ClientApp::updater().setupUI(); +#endif } static Value *Function_App_GamePlugin(Context &, Function::ArgumentValues const &) @@ -149,8 +154,12 @@ , DENG2_OBSERVES(DoomsdayApp, PeriodicAutosave) { Binder binder; +#if defined (DENG_HAVE_UPDATER) QScopedPointer updater; +#endif +#if defined (DENG_HAVE_BUSYRUNNER) BusyRunner busyRunner; +#endif ConfigProfiles audioSettings; ConfigProfiles networkSettings; ConfigProfiles logSettings; @@ -264,7 +273,9 @@ DENG2_ASSERT("Unclean shutdown: exception in ~ClientApp"!=0); } +#if defined (DENG_HAVE_UPDATER) updater.reset(); +#endif delete inputSys; delete resources; delete winSys; @@ -290,7 +301,9 @@ // If an update has been downloaded and is ready to go, we should // re-show the dialog now that the user has saved the game as prompted. LOG_DEBUG("Game saved"); - DownloadDialog::showCompletedDownload(); +#if defined (DENG_HAVE_UPDATER) + UpdateDownloadDialog::showCompletedDownload(); +#endif break; case DD_NOTIFY_PSPRITE_STATE_CHANGED: @@ -351,6 +364,9 @@ // Write cvars and bindings to .cfg files. Con_SaveDefaults(); + // Disallow further saving of bindings until another game is loaded. + Con_SetAllowed(0); + R_ClearViewData(); world::R_DestroyContactLists(); P_ClearPlayerImpulses(); @@ -386,6 +402,21 @@ } ClientWindow::main().console().zeroLogHeight(); + + if (!newGame.isNull()) + { + // Auto-start the game? + auto const *prof = self().currentGameProfile(); + if (prof && prof->autoStartMap()) + { + LOG_NOTE("Starting in %s as configured in the game profile") + << prof->autoStartMap(); + + Con_Executef(CMDS_DDAY, false, "setdefaultskill %i; setmap %s", + prof->autoStartSkill(), + prof->autoStartMap().toUtf8().constData()); + } + } } void periodicAutosave() @@ -402,7 +433,7 @@ */ void setupAppMenu() { -#ifdef MACOSX +#if defined (MACOSX) nativeAppMenu.reset(new NativeMenu); #endif } @@ -430,7 +461,10 @@ .define(Prof::ConfigVariable, "home.columns.heretic") .define(Prof::ConfigVariable, "home.columns.hexen") .define(Prof::ConfigVariable, "home.columns.otherGames") - .define(Prof::ConfigVariable, "home.columns.multiplayer"); + .define(Prof::ConfigVariable, "home.columns.multiplayer") + .define(Prof::ConfigVariable, "home.sortBy") + .define(Prof::ConfigVariable, "home.sortAscending") + .define(Prof::ConfigVariable, "home.sortCustomSeparately"); /// @todo These belong in their respective subsystems. @@ -452,7 +486,10 @@ .define(Prof::StringCVar, "music-soundfont", "") .define(Prof::ConfigVariable, "audio.soundPlugin") .define(Prof::ConfigVariable, "audio.musicPlugin") - .define(Prof::ConfigVariable, "audio.cdPlugin"); + .define(Prof::ConfigVariable, "audio.cdPlugin") + .define(Prof::ConfigVariable, "audio.channels") + .define(Prof::ConfigVariable, "audio.pauseOnFocus") + .define(Prof::ConfigVariable, "audio.output"); } #ifdef UNIX @@ -479,10 +516,15 @@ } #endif - String pathForMapClientState(String const &mapId) + String mapClientStatePath(String const &mapId) const { return String("maps/%1ClientState").arg(mapId); } + + String mapObjectStatePath(String const &mapId) const + { + return String("maps/%1ObjectState").arg(mapId); + } }; ClientApp::ClientApp(int &argc, char **argv) @@ -505,10 +547,11 @@ // We must presently set the current game manually (the collection is global). setGame(games().nullGame()); - d->binder.init(scriptSystem().nativeModule("App")) + d->binder.init(scriptSystem()["App"]) << DENG2_FUNC_NOARG (App_GamePlugin, "gamePlugin") << DENG2_FUNC_NOARG (App_Quit, "quit"); +#if !defined (DENG_MOBILE) /// @todo Remove the splash screen when file system indexing can be done as /// a background task and the main window can be opened instantly. -jk QPixmap const pixmap(doomsdaySplashXpm); @@ -519,6 +562,7 @@ QColor(90, 110, 95)); processEvents(); splash->deleteLater(); +#endif } void ClientApp::initialize() @@ -597,8 +641,10 @@ WindowSystem::setAppWindowSystem(*d->winSys); addSystem(*d->winSys); +#if defined (DENG_HAVE_UPDATER) // Check for updates automatically. d->updater.reset(new Updater); +#endif // Create the resource system. d->resources = new ClientResources; @@ -606,8 +652,10 @@ plugins().loadAll(); - // Create the main window. + // On mobile, the window is instantiated via QML. +#if !defined (DENG_MOBILE) d->winSys->createWindow()->setTitle(DD_ComposeMainWindowTitle()); +#endif d->setupAppMenu(); @@ -624,6 +672,8 @@ void ClientApp::preFrame() { + DGL_BeginFrame(); + // Frame synchronous I/O operations. App_AudioSystem().startFrame(); @@ -698,10 +748,20 @@ try { + String const mapId = session.mapUri().path(); + // Internal map state. - File &file = toFolder.replaceFile(d->pathForMapClientState(session.mapUri().path())); - Writer writer(file); - world().map().serializeInternalState(writer.withHeader()); + { + File &file = toFolder.replaceFile(d->mapClientStatePath(mapId)); + Writer writer(file); + world().map().serializeInternalState(writer.withHeader()); + } + + // Object state. + { + File &file = toFolder.replaceFile(d->mapObjectStatePath(mapId)); + file << world().map().objectsDescription().toUtf8(); // plain text + } } catch (Error const &er) { @@ -714,10 +774,12 @@ { DoomsdayApp::gameSessionWasLoaded(session, fromFolder); + String const mapId = session.mapUri().path(); + + // Internal map state. This might be missing. try { - // Internal map state. This might be missing. - if (File const *file = fromFolder.tryLocate(d->pathForMapClientState(session.mapUri().path()))) + if (File const *file = fromFolder.tryLocate(d->mapClientStatePath(mapId))) { DENG2_ASSERT(session.thinkerMapping() != nullptr); @@ -730,6 +792,24 @@ { LOGDEV_MAP_WARNING("Internal map state not deserialized: %s") << er.asText(); } + + // Restore object state. + try + { + if (File const *file = fromFolder.tryLocate(d->mapObjectStatePath(mapId))) + { + // Parse the info and cross-check with current state. + world().map().restoreObjects(Info(*file), *session.thinkerMapping()); + } + else + { + LOGDEV_MSG("\"%s\" not found") << d->mapObjectStatePath(mapId); + } + } + catch (Error const &er) + { + LOGDEV_MAP_WARNING("Object state check error: %s") << er.asText(); + } } ClientPlayer &ClientApp::player(int console) // static @@ -737,7 +817,7 @@ return DoomsdayApp::players().at(console).as(); } -LoopResult ClientApp::forLocalPlayers(std::function func) // static +LoopResult ClientApp::forLocalPlayers(const std::function &func) // static { auto const &players = DoomsdayApp::players(); for (int i = 0; i < players.count(); ++i) @@ -776,16 +856,20 @@ return *clientAppSingleton; } -BusyRunner &ClientApp::busyRunner() -{ - return app().d->busyRunner; -} - +#if defined (DENG_HAVE_UPDATER) Updater &ClientApp::updater() { DENG2_ASSERT(!app().d->updater.isNull()); return *app().d->updater; } +#endif + +#if defined (DENG_HAVE_BUSYRUNNER) +BusyRunner &ClientApp::busyRunner() +{ + return app().d->busyRunner; +} +#endif ConfigProfiles &ClientApp::logSettings() { @@ -885,12 +969,14 @@ void ClientApp::openInBrowser(QUrl url) { +#if !defined (DENG_MOBILE) // Get out of fullscreen mode. int windowed[] = { ClientWindow::Fullscreen, false, ClientWindow::End }; ClientWindow::main().changeAttributes(windowed); +#endif QDesktopServices::openUrl(url); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/clientplayer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/clientplayer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/clientplayer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/clientplayer.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -43,7 +43,6 @@ : Base(i) , playerWeaponAnimator(i) { - zap(viewport); zap(clPlayerState); zap(demoTimer); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/con_config.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/con_config.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/con_config.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/con_config.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -68,8 +68,8 @@ else { out.writeText(String::format("# %s %s / " DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_TEXT "\n", - (char const *) gx.GetVariable(DD_PLUGIN_NAME), - (char const *) gx.GetVariable(DD_PLUGIN_VERSION_SHORT))); + (char const *) gx.GetPointer(DD_PLUGIN_NAME), + (char const *) gx.GetPointer(DD_PLUGIN_VERSION_SHORT))); } out.writeText("# This configuration file is generated automatically. Each line is a\n" @@ -281,7 +281,14 @@ void Con_SetAllowed(int flags) { - flagsAllow |= flags & (CPCF_ALLOW_SAVE_STATE | CPCF_ALLOW_SAVE_BINDINGS); + if (flags != 0) + { + flagsAllow |= flags & (CPCF_ALLOW_SAVE_STATE | CPCF_ALLOW_SAVE_BINDINGS); + } + else + { + flagsAllow = 0; + } } bool Con_ParseCommands(File const &file, int flags) @@ -312,7 +319,7 @@ if (CommandLine_CheckWith("-config", 1)) { - path = App::fileSystem().accessNativeLocation(CommandLine_NextAsPath(), File::Write); + path = FS::accessNativeLocation(CommandLine_NextAsPath(), File::Write); } else { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/configprofiles.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/configprofiles.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/configprofiles.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/configprofiles.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -221,11 +221,11 @@ DENG2_ASSERT(confDefaults.has(name)); Variable const &var = confDefaults[name]; - if (var.value().is()) + if (is(var.value())) { return var.value().asNumber(); } - else if (var.value().is()) + else if (is(var.value())) { return var.value().asText(); } @@ -270,7 +270,7 @@ case ConfigVariable: { Value const &cfgValue = Config::get(st.name).value(); - if (cfgValue.is()) + if (is(cfgValue)) { val = cfgValue.asNumber(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_loop.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_loop.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_loop.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_loop.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -327,7 +327,7 @@ /// @var optimalDelta is integer on purpose: we're measuring time at a 1 ms accuracy, /// so we can't use fractions of a millisecond. - duint const optimalDelta = (::maxFrameRate > 0 ? 1000 / ::maxFrameRate : 1); + duint const optimalDelta = duint(::maxFrameRate > 0? 1000/::maxFrameRate : 1); if (Sys_IsShuttingDown()) return; // No need for finesse. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -138,7 +139,7 @@ # include "ui/home/homewidget.h" # include "updater.h" -# include "updater/downloaddialog.h" +# include "updater/updatedownloaddialog.h" #endif #ifdef __SERVER__ # include "network/net_main.h" @@ -408,8 +409,8 @@ #undef SEP_CHAR } - scheme.addSearchPath(SearchPath(de::Uri("$(App.DataPath)/", RC_NULL), SearchPath::NoDescend)); - scheme.addSearchPath(SearchPath(de::Uri("$(App.DataPath)/$(GamePlugin.Name)/", RC_NULL), SearchPath::NoDescend)); + scheme.addSearchPath(SearchPath(de::makeUri("$(App.DataPath)/"), SearchPath::NoDescend)); + scheme.addSearchPath(SearchPath(de::makeUri("$(App.DataPath)/$(GamePlugin.Name)/"), SearchPath::NoDescend)); } #endif @@ -470,7 +471,7 @@ for (dint i = 0; i < searchPathCount; ++i) { - scheme.addSearchPath(SearchPath(de::Uri(def.searchPaths[i], RC_NULL), def.searchPathFlags)); + scheme.addSearchPath(SearchPath(de::makeUri(def.searchPaths[i]), def.searchPathFlags)); } if (def.optOverridePath && CommandLine_CheckWith(def.optOverridePath, 1)) @@ -513,7 +514,7 @@ dd_vsnprintf(buff, sizeof(buff), error, argptr); va_end(argptr); -#ifdef __CLIENT__ +#if defined (__CLIENT__) && defined (DENG_HAVE_BUSYRUNNER) if (!ClientApp::busyRunner().inWorkerThread()) { Sys_MessageBox(MBT_ERROR, DOOMSDAY_NICENAME, buff, 0); @@ -545,7 +546,7 @@ { DoomsdayApp::app().busyMode().abort(buff); -#ifdef __CLIENT__ +#if defined (__CLIENT__) && defined (DENG_HAVE_BUSYRUNNER) if (ClientApp::busyRunner().inWorkerThread()) { // We should not continue to execute the worker any more. @@ -601,6 +602,8 @@ //Sys_Shutdown(); DD_Shutdown(); + Garbage_ForgetAndLeak(); // At this point, it's too late. + // Get outta here. exit(1); } @@ -794,7 +797,7 @@ } else { - configFile = App::rootFolder().tryLocate(App_CurrentGame().mainConfig()); + configFile = FS::tryLocate(App_CurrentGame().mainConfig()); Con_SetDefaultPath(App_CurrentGame().mainConfig()); // This will be missing on the first launch. @@ -811,7 +814,7 @@ ClientApp::inputSystem().bindGameDefaults(); // Read bindings for this game and merge with the working set. - if ((configFile = App::rootFolder().tryLocate(App_CurrentGame().bindingConfig())) + if ((configFile = FS::tryLocate(App_CurrentGame().bindingConfig())) != nullptr) { Con_ParseCommands(*configFile); @@ -938,15 +941,25 @@ // The argument can be a game ID or a profile name. if (games.contains(param)) { - Game &game = games[param]; - automaticProfile = DoomsdayApp::gameProfiles().find(game.title()).as(); + auto &prof = DoomsdayApp::gameProfiles().find(games[param].title()).as(); + prof.setLastPlayedAt(); + automaticProfile = prof; + } + else if (auto *prof = maybeAs(DoomsdayApp::gameProfiles().tryFind(param))) + { + prof->setLastPlayedAt(); + automaticProfile = *prof; } - else if (auto const *prof = DoomsdayApp::gameProfiles().tryFind(param)) + + // Packages from the command line. + foreach (String packageId, PackageLoader::get().loadedFromCommandLine()) { - automaticProfile = prof->as(); + StringList pkgs = automaticProfile.packages(); + pkgs << packageId; + automaticProfile.setPackages(pkgs); } - // Append the packages specified on the command line. + // Also append the packages specified as files on the command line. foreach (File *f, DoomsdayApp::app().filesFromCommandLine()) { String packageId; @@ -1341,13 +1354,18 @@ // // Make sure all files have been found so we can determine which games are playable. - Folder::waitForPopulation(); - DoomsdayApp::bundles().waitForEverythingIdentified(); + /*Folder::waitForPopulation( + #if defined (__SERVER__) + Folder::BlockingMainThread + #endif + ); + DoomsdayApp::bundles().waitForEverythingIdentified();*/ + FS::waitForIdle(); /*String foundPath = App_FileSystem().findPath(de::Uri("doomsday.pk3", RC_PACKAGE), RLF_DEFAULT, App_ResourceClass(RC_PACKAGE)); foundPath = App_BasePath() / foundPath; // Ensure the path is absolute. - File1 *loadedFile = File1::tryLoad(de::Uri(foundPath, RC_NULL)); + File1 *loadedFile = File1::tryLoad(de::makeUri(foundPath)); DENG2_ASSERT(loadedFile); DENG2_UNUSED(loadedFile);*/ @@ -1590,71 +1608,40 @@ dint *writePtr; }; -ddvalue_t ddValues[DD_LAST_VALUE - DD_FIRST_VALUE - 1] = { +static ddvalue_t ddValues[DD_LAST_VALUE - DD_FIRST_VALUE] = { + {&novideo, 0}, {&netGame, 0}, - {&isServer, 0}, // An *open* server? + {&isServer, 0}, // An *open* server? {&isClient, 0}, + {&consolePlayer, &consolePlayer}, + {&displayPlayer, 0}, // use R_SetViewPortPlayer() to change + {&gotFrame, 0}, + {0, 0}, // pointer updated when queried (DED sound def count) + #ifdef __SERVER__ {&allowFrames, &allowFrames}, #else {0, 0}, #endif - {&consolePlayer, &consolePlayer}, - {&displayPlayer, 0 /*&displayPlayer*/}, // use R_SetViewPortPlayer() instead -#ifdef __CLIENT__ - {&mipmapping, 0}, - {&filterUI, 0}, - {0, 0}, // defResX - {0, 0}, // defResY -#else - {0, 0}, - {0, 0}, - {0, 0}, - {0, 0}, -#endif - {0, 0}, - {0, 0}, //{&mouseInverseY, &mouseInverseY}, + #ifdef __CLIENT__ {&levelFullBright, &levelFullBright}, -#else - {0, 0}, -#endif - {0, 0}, // &CmdReturnValue -#ifdef __CLIENT__ {&gameReady, &gameReady}, -#else - {0, 0}, -#endif - {&isDedicated, 0}, - {&novideo, 0}, - {0, 0}, - {&gotFrame, 0}, -#ifdef __CLIENT__ {&playback, 0}, -#else - {0, 0}, -#endif - {&DED_Definitions()->sounds.count.num, 0}, - {0, 0}, - {0, 0}, -#ifdef __CLIENT__ {&clientPaused, &clientPaused}, {&weaponOffsetScaleY, &weaponOffsetScaleY}, + {&gameDrawHUD, 0}, + {&symbolicEchoMode, &symbolicEchoMode}, + {&rendLightAttenuateFixedColormap, &rendLightAttenuateFixedColormap}, #else {0, 0}, {0, 0}, -#endif {0, 0}, -#ifdef __CLIENT__ - {&gameDrawHUD, 0}, - {&symbolicEchoMode, &symbolicEchoMode}, - {&numTexUnits, 0}, - {&rendLightAttenuateFixedColormap, &rendLightAttenuateFixedColormap} -#else {0, 0}, {0, 0}, {0, 0}, - {0, 0} + {0, 0}, + {0, 0}, #endif }; @@ -1700,10 +1687,17 @@ default: break; } - if (ddvalue >= DD_LAST_VALUE || ddvalue <= DD_FIRST_VALUE) + if (ddvalue >= DD_LAST_VALUE || ddvalue < DD_FIRST_VALUE) { return 0; } + + // Update pointers. + if (ddvalue == DD_NUMSOUNDS) + { + ddValues[ddvalue].readPtr = &DED_Definitions()->sounds.count.num; + } + if (ddValues[ddvalue].readPtr == 0) { return 0; @@ -1717,7 +1711,7 @@ */ void DD_SetInteger(dint ddvalue, dint parm) { - if (ddvalue <= DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) + if (ddvalue < DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) { return; } @@ -1745,7 +1739,7 @@ case DD_GAME_EXPORTS: return &gx; - case DD_POLYOBJ_COUNT: + case DD_MAP_POLYOBJ_COUNT: value = App_World().hasMap()? App_World().map().polyobjCount() : 0; return &value; @@ -1779,7 +1773,7 @@ /*case DD_CPLAYER_THRUST_MUL: return &cplrThrustMul;*/ - case DD_GRAVITY: + case DD_MAP_GRAVITY: valueD = App_World().hasMap()? App_World().map().gravity() : 0; return &valueD; @@ -1822,7 +1816,7 @@ default: break; } - if (ddvalue >= DD_LAST_VALUE || ddvalue <= DD_FIRST_VALUE) + if (ddvalue >= DD_LAST_VALUE || ddvalue < DD_FIRST_VALUE) { return 0; } @@ -1838,7 +1832,7 @@ #undef DD_SetVariable void DD_SetVariable(dint ddvalue, void *parm) { - if (ddvalue <= DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) + if (ddvalue < DD_FIRST_VALUE || ddvalue >= DD_LAST_VALUE) { switch (ddvalue) { @@ -1846,7 +1840,7 @@ cplrThrustMul = *(dfloat*) parm; return;*/ - case DD_GRAVITY: + case DD_MAP_GRAVITY: if (App_World().hasMap()) App_World().map().setGravity(*(coord_t*) parm); return; @@ -1983,28 +1977,30 @@ << String::join(game.profile().unavailablePackages(), ", "); return true; } - if (!DoomsdayApp::app().changeGame(game.profile(), DD_ActivateGameWorker)) + if (DoomsdayApp::app().changeGame(game.profile(), DD_ActivateGameWorker)) { - return false; + game.profile().setLastPlayedAt(); + continue; } - continue; + return false; } // It could also be a game profile. - if (auto const *profile = DoomsdayApp::gameProfiles().tryFind(searchTerm)) + if (auto *profile = DoomsdayApp::gameProfiles().tryFind(searchTerm)) { - auto const &gameProf = profile->as(); + auto &gameProf = profile->as(); if (!gameProf.isPlayable()) { LOG_SCR_ERROR("Profile \"%s\" is missing one or more required packages: ") << String::join(gameProf.unavailablePackages(), ", "); return true; } - if (!DoomsdayApp::app().changeGame(gameProf, DD_ActivateGameWorker)) + if (DoomsdayApp::app().changeGame(gameProf, DD_ActivateGameWorker)) { - return false; + gameProf.setLastPlayedAt(); + continue; } - continue; + return false; } try @@ -2174,7 +2170,7 @@ RLF_MATCH_EXTENSION, App_ResourceClass(RC_PACKAGE)); foundPath = App_BasePath() / foundPath; // Ensure the path is absolute. - if (File1::tryUnload(de::Uri(foundPath, RC_NULL))) + if (File1::tryUnload(de::makeUri(foundPath))) { didUnloadFiles = true; } @@ -2217,7 +2213,7 @@ return true; } -#ifdef __CLIENT__ +#if defined (DENG_HAVE_UPDATER) D_CMD(CheckForUpdates) { @@ -2253,7 +2249,7 @@ return true; } -#endif // __CLIENT__ +#endif // DENG_HAVE_UPDATER D_CMD(Version) { @@ -2266,7 +2262,7 @@ // Print the version info of the current game if loaded. if (App_GameLoaded()) { - LOG_SCR_MSG(_E(l) "Game: " _E(.) "%s") << (char const *) gx.GetVariable(DD_PLUGIN_VERSION_LONG); + LOG_SCR_MSG(_E(l) "Game: " _E(.) "%s") << (char const *) gx.GetPointer(DD_PLUGIN_VERSION_LONG); } // Additional information for developers. @@ -2282,12 +2278,12 @@ { DENG2_UNUSED2(src, argc); -#ifdef __CLIENT__ - if (DownloadDialog::isDownloadInProgress()) +#if defined (DENG_HAVE_UPDATER) + if (UpdateDownloadDialog::isDownloadInProgress()) { LOG_WARNING("Cannot quit while downloading an update"); ClientWindow::main().taskBar().openAndPauseGame(); - DownloadDialog::currentDownload().open(); + UpdateDownloadDialog::currentDownload().open(); return false; } #endif @@ -2332,7 +2328,7 @@ #endif */ - LOG_SCR_NOTE(_E(b) DOOMSDAY_NICENAME " %s Console") << Version::currentBuild().asHumanReadableText(); + LOG_SCR_NOTE(_E(b) DOOMSDAY_NICENAME " %s Console") << Version::currentBuild().compactNumber(); #define TABBED(A, B) "\n" _E(Ta) _E(b) " " << A << " " _E(.) _E(Tb) << B @@ -2475,10 +2471,13 @@ #ifdef __CLIENT__ C_CMD("clear", "", Clear); + +#if defined (DENG_HAVE_UPDATER) C_CMD("update", "", CheckForUpdates); C_CMD("updateandnotify", "", CheckForUpdatesAndNotify); C_CMD("updatesettings", "", ShowUpdateSettings); C_CMD("lastupdated", "", LastUpdated); +#endif C_CMD_FLAGS("conclose", "", OpenClose, CMDF_NO_DEDICATED); C_CMD_FLAGS("conopen", "", OpenClose, CMDF_NO_DEDICATED); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_pinit.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_pinit.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/dd_pinit.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/dd_pinit.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -86,7 +86,7 @@ { de::String title = DOOMSDAY_NICENAME " " + Version::currentBuild().compactNumber(); - if(App_GameLoaded() && gx.GetVariable) + if(App_GameLoaded() && gx.GetPointer) { title = App_CurrentGame().title() + " - " + title; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/def_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/def_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/def_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/def_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -594,7 +594,7 @@ if (!CommandLine_Exists("-noauto")) { FS1::PathList foundPaths; - if (fileSys().findAllPaths(de::Uri("$(App.DefsPath)/$(GamePlugin.Name)/auto/*.ded", RC_NULL).resolved(), 0, foundPaths)) + if (fileSys().findAllPaths(de::makeUri("$(App.DefsPath)/$(GamePlugin.Name)/auto/*.ded").resolved(), 0, foundPaths)) { for (FS1::PathListItem const &found : foundPaths) { @@ -612,9 +612,10 @@ { if (bundle->format() == DataBundle::Ded) { + String const bundleRoot = bundle->rootPath(); for (Value const *path : bundle->packageMetadata().geta("dataFiles").elements()) { - readDefinitionFile(path->asText()); + readDefinitionFile(bundleRoot / path->asText()); } } } @@ -770,7 +771,7 @@ static bool decorationIsCompatible(Record const &decorDef, de::Uri const &textureUri, bool materialIsCustom) { - if (de::Uri(decorDef.gets("texture"), RC_NULL) != textureUri) + if (de::makeUri(decorDef.gets("texture")) != textureUri) return false; if (materialIsCustom) @@ -802,10 +803,10 @@ { Record const &st = decorDef.stage(k); - defineLightmap(de::Uri(st.gets("lightmapUp"), RC_NULL)); - defineLightmap(de::Uri(st.gets("lightmapDown"), RC_NULL)); - defineLightmap(de::Uri(st.gets("lightmapSide"), RC_NULL)); - defineFlaremap(de::Uri(st.gets("haloTexture"), RC_NULL)); + defineLightmap(de::makeUri(st.gets("lightmapUp"))); + defineLightmap(de::makeUri(st.gets("lightmapDown"))); + defineLightmap(de::makeUri(st.gets("lightmapSide"))); + defineFlaremap(de::makeUri(st.gets("haloTexture"))); } material.addDecoration(LightMaterialDecoration::fromDef(decorDef.def())); @@ -1312,10 +1313,10 @@ Record const &st = defn::MaterialDecoration(decorDef.light(k)).stage(0); if (Vector3f(st.geta("color")) != Vector3f(0, 0, 0)) { - defineLightmap(de::Uri(st["lightmapUp"], RC_NULL)); - defineLightmap(de::Uri(st["lightmapDown"], RC_NULL)); - defineLightmap(de::Uri(st["lightmapSide"], RC_NULL)); - defineFlaremap(de::Uri(st["haloTexture"], RC_NULL)); + defineLightmap(de::makeUri(st["lightmapUp"])); + defineLightmap(de::makeUri(st["lightmapDown"])); + defineLightmap(de::makeUri(st["lightmapSide"])); + defineFlaremap(de::makeUri(st["haloTexture"])); } } } @@ -1409,24 +1410,30 @@ } // Music. - for (dint i = 0; i < defs.musics.size(); ++i) + for (int i = defs.musics.size() - 1; i >= 0; --i) { - Record *mus = &defs.musics[i]; - // Make sure duplicate defs overwrite the earliest. - Record *earliest = &defs.musics[defs.getMusicNum(mus->gets("id").toUtf8().constData())]; - - if (earliest == mus) continue; + const Record &mus = defs.musics[i]; - earliest->set("lumpName", mus->gets("lumpName")); - earliest->set("cdTrack", mus->geti("cdTrack")); + // Make sure duplicate defs overwrite contents from the earlier ones. + // IDs can't be fully trusted because music definitions are sometimes + // generated by idtech1importer, so they might have IDs that don't + // match the vanilla IDs. - if (!mus->gets("path").isEmpty()) + for (int k = i - 1; k >= 0; --k) { - earliest->set("path", mus->gets("path")); - } - else if (!earliest->gets("path").isEmpty()) - { - earliest->set("path", ""); + Record &earlier = defs.musics[k]; + + if (mus.gets("id").compareWithoutCase(earlier.gets("id")) == 0) + { + earlier.set("lumpName", mus.gets("lumpName")); + earlier.set("cdTrack", mus.geti("cdTrack")); + earlier.set("path", mus.gets("path")); + } + else if (mus.gets("lumpName").compareWithoutCase(earlier.gets("lumpName")) == 0) + { + earlier.set("path", mus.gets("path")); + earlier.set("cdTrack", mus.geti("cdTrack")); + } } } @@ -1798,7 +1805,7 @@ { try { - l->iparm[k] = world::Materials::get().materialManifest(de::Uri(def->iparmStr[k], RC_NULL)).id(); + l->iparm[k] = world::Materials::get().materialManifest(de::makeUri(def->iparmStr[k])).id(); } catch (Resources::MissingResourceManifestError const &) {} // Ignore this error. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/dgl_common.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/dgl_common.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/dgl_common.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/dgl_common.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #include "api_gl.h" @@ -38,6 +40,163 @@ using namespace de; +struct DGLState +{ + int matrixMode = 0; + QVector matrixStacks[4]; + + int activeTexture = 0; + bool enableTexture[2] { true, false }; + int textureModulation = 1; + Vector4f textureModulationColor; + + bool enableFog = false; + DGLenum fogMode = DGL_LINEAR; + float fogStart = 0; + float fogEnd = 0; + float fogDensity = 0; + Vector4f fogColor; + bool flushBacktrace = false; + + DGLState() + { + // The matrix stacks initially contain identity matrices. + for (auto &stack : matrixStacks) + { + stack.append(Matrix4f()); + } + } + + int stackIndex(DGLenum id) const + { + switch (id) + { + case DGL_TEXTURE0: + return 2; + + case DGL_TEXTURE1: + return 3; + + case DGL_TEXTURE: + return 2 + activeTexture; + + default: { + int const index = int(id) - DGL_MODELVIEW; + DENG2_ASSERT(index >= 0 && index < 2); + return index; } + } + } + + void pushMatrix() + { + auto &stack = matrixStacks[matrixMode]; + stack.push_back(stack.back()); + } + + void popMatrix() + { + auto &stack = matrixStacks[matrixMode]; + DENG2_ASSERT(stack.size() > 1); + stack.pop_back(); + } + + void loadMatrix(Matrix4f const &mat) + { + auto &stack = matrixStacks[matrixMode]; + DENG2_ASSERT(!stack.isEmpty()); + stack.back() = mat; + } + + void multMatrix(Matrix4f const &mat) + { + auto &stack = matrixStacks[matrixMode]; + DENG2_ASSERT(!stack.isEmpty()); + stack.back() = stack.back() * mat; + } +}; + +static DGLState dgl; + +Matrix4f DGL_Matrix(DGLenum matrixMode) +{ + return dgl.matrixStacks[dgl.stackIndex(matrixMode)].back(); +} + +void DGL_SetModulationColor(Vector4f const &modColor) +{ + dgl.textureModulationColor = modColor; +} + +Vector4f DGL_ModulationColor() +{ + return dgl.textureModulationColor; +} + +void DGL_FogParams(GLUniform &fogRange, GLUniform &fogColor) +{ + if (dgl.enableFog) + { + fogColor = Vector4f(dgl.fogColor[0], + dgl.fogColor[1], + dgl.fogColor[2], + 1.f); + + // TODO: Implement EXP and EXP2 fog modes. This is LINEAR. + + Rangef const depthPlanes = GL_DepthClipRange(); + float const fogDepth = dgl.fogEnd - dgl.fogStart; + fogRange = Vector4f(dgl.fogStart, + fogDepth, + depthPlanes.start, + depthPlanes.end); + } + else + { + fogColor = Vector4f(); + } +} + +void DGL_DepthFunc(DGLenum depthFunc) +{ + using namespace de::gl; + + static const Comparison funcs[] = { + Never, + Always, + Equal, + NotEqual, + Less, + Greater, + LessOrEqual, + GreaterOrEqual + }; + + DENG2_ASSERT(depthFunc >= DGL_NEVER && depthFunc <= DGL_GEQUAL); + + const auto f = funcs[depthFunc - DGL_NEVER]; + if (GLState::current().depthFunc() != f) + { + DGL_Flush(); + GLState::current().setDepthFunc(f); + } +} + +void DGL_CullFace(DGLenum cull) +{ + const auto c = + ( cull == DGL_NONE ? gl::None + : cull == DGL_BACK ? gl::Back + : cull == DGL_FRONT ? gl::Front + : gl::None ); + + if (GLState::current().cull() != c) + { + DGL_Flush(); + GLState::current().setCull(c); + } +} + +#if 0 /** * Requires a texture environment mode that can add and multiply. * Nvidia's and ATI's appropriate extensions are supported, other cards will @@ -113,15 +272,38 @@ // This is a single-pass mode. The alpha should remain unmodified // during the light stage. if(activate) - { // Replace: primAlpha. + { + // Replace: primAlpha. LIBGUI_GL.glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA, GL_REPLACE); LIBGUI_GL.glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA, GL_PREVIOUS); LIBGUI_GL.glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA, GL_SRC_ALPHA); } } +#endif -void GL_ModulateTexture(int mode) +void DGL_ModulateTexture(int mode) { + dgl.textureModulation = mode; + + switch (mode) + { + default: + qDebug() << "DGL_ModulateTexture: texture modulation mode" << mode << "not implemented"; + break; + + case 0: + case 1: + case 2: + case 3: + case 4: + case 6: + case 8: + case 10: + case 11: + break; + } + +#if 0 DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); @@ -305,6 +487,7 @@ default: break; } +#endif } /*void GL_BlendOp(int op) @@ -337,7 +520,7 @@ { if(!rect) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); GameWidget &game = ClientWindow::main().game(); @@ -347,11 +530,12 @@ // has been set to cover the game widget area, so we can set the scissor relative // to it. - auto norm = GuiWidget::normalizedRect(Rectanglei(rect->origin.x, rect->origin.y, - rect->size.width, rect->size.height), - Rectanglei::fromSize(game.rule().recti().size())); + auto const norm = GuiWidget::normalizedRect(Rectanglei(rect->origin.x, rect->origin.y, + rect->size.width, rect->size.height), + Rectanglei::fromSize(game.rule().recti().size())); - GLState::current().setNormalizedScissor(norm).apply(); + DGL_Flush(); + GLState::current().setNormalizedScissor(norm); } #undef DGL_SetScissor2 @@ -368,52 +552,81 @@ #undef DGL_GetIntegerv dd_bool DGL_GetIntegerv(int name, int *v) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG_ASSERT_IN_MAIN_THREAD(); + //DENG_ASSERT_GL_CONTEXT_ACTIVE(); float color[4]; switch(name) { - case DGL_MODULATE_ADD_COMBINE: - *v = GLInfo::extensions().NV_texture_env_combine4 || GLInfo::extensions().ATI_texture_env_combine3; + case DGL_ACTIVE_TEXTURE: + *v = dgl.activeTexture; + break; + + case DGL_TEXTURE_2D: + *v = (dgl.enableTexture[dgl.activeTexture]? 1 : 0); + break; + + case DGL_TEXTURE0: + *v = dgl.enableTexture[0]? 1 : 0; + break; + + case DGL_TEXTURE1: + *v = dgl.enableTexture[1]? 1 : 0; + break; + + case DGL_MODULATE_TEXTURE: + *v = dgl.textureModulation; break; +// case DGL_MODULATE_ADD_COMBINE: +// qDebug() << "DGL_GetIntegerv: tex env not available"; +// //*v = GLInfo::extensions().NV_texture_env_combine4 || GLInfo::extensions().ATI_texture_env_combine3; +// break; + case DGL_SCISSOR_TEST: *(GLint *) v = GLState::current().scissor(); break; case DGL_FOG: - *v = GL_state.currentUseFog; + *v = (dgl.enableFog? 1 : 0); + break; + + case DGL_FOG_MODE: + *v = int(dgl.fogMode); break; case DGL_CURRENT_COLOR_R: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = int(color[0] * 255); break; case DGL_CURRENT_COLOR_G: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = int(color[1] * 255); break; case DGL_CURRENT_COLOR_B: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = int(color[2] * 255); break; case DGL_CURRENT_COLOR_A: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = int(color[3] * 255); break; case DGL_CURRENT_COLOR_RGBA: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); - for(int i = 0; i < 4; ++i) + DGL_CurrentColor(color); + for (int i = 0; i < 4; ++i) { v[i] = int(color[i] * 255); } break; + case DGL_FLUSH_BACKTRACE: + *v = dgl.flushBacktrace ? 1 : 0; + break; + default: return false; } @@ -432,17 +645,22 @@ #undef DGL_SetInteger dd_bool DGL_SetInteger(int name, int value) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - switch(name) { case DGL_ACTIVE_TEXTURE: - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + byte(value)); + DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT(value >= 0); + DENG2_ASSERT(value < MAX_TEX_UNITS); + dgl.activeTexture = value; + LIBGUI_GL.glActiveTexture(GLenum(GL_TEXTURE0 + value)); break; case DGL_MODULATE_TEXTURE: - GL_ModulateTexture(value); + DGL_ModulateTexture(value); + break; + + case DGL_FLUSH_BACKTRACE: + dgl.flushBacktrace = true; break; default: @@ -455,40 +673,63 @@ #undef DGL_GetFloatv dd_bool DGL_GetFloatv(int name, float *v) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG_ASSERT_IN_MAIN_THREAD(); + //DENG_ASSERT_GL_CONTEXT_ACTIVE(); float color[4]; - switch(name) + switch (name) { case DGL_CURRENT_COLOR_R: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = color[0]; break; case DGL_CURRENT_COLOR_G: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = color[1]; break; case DGL_CURRENT_COLOR_B: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = color[2]; break; case DGL_CURRENT_COLOR_A: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); + DGL_CurrentColor(color); *v = color[3]; break; case DGL_CURRENT_COLOR_RGBA: - LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, color); - for(int i = 0; i < 4; ++i) + DGL_CurrentColor(v); + break; + + case DGL_FOG_START: + v[0] = dgl.fogStart; + break; + + case DGL_FOG_END: + v[0] = dgl.fogEnd; + break; + + case DGL_FOG_DENSITY: + v[0] = dgl.fogDensity; + break; + + case DGL_FOG_COLOR: + for (int i = 0; i < 4; ++i) { - v[i] = color[i]; + v[i] = dgl.fogColor[i]; } break; + case DGL_LINE_WIDTH: + v[0] = GL_state.currentLineWidth; + break; + + case DGL_POINT_SIZE: + v[0] = GL_state.currentPointSize; + break; + default: return false; } @@ -499,35 +740,35 @@ #undef DGL_GetFloat float DGL_GetFloat(int name) { - switch(name) - { - case DGL_LINE_WIDTH: - return GL_state.currentLineWidth; - - case DGL_POINT_SIZE: - return GL_state.currentPointSize; - - default: - return 0; - } + float value = 0.f; + DGL_GetFloatv(name, &value); + return value; } #undef DGL_SetFloat dd_bool DGL_SetFloat(int name, float value) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - switch(name) { case DGL_LINE_WIDTH: - GL_state.currentLineWidth = value; - LIBGUI_GL.glLineWidth(value); + if (!fequal(value, GL_state.currentLineWidth)) + { + DGL_Flush(); + GL_state.currentLineWidth = value; + } break; case DGL_POINT_SIZE: GL_state.currentPointSize = value; +#if defined (DENG_OPENGL) + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); LIBGUI_GL.glPointSize(value); +#endif + break; + + case DGL_ALPHA_LIMIT: + // No flushing required. + GLState::current().setAlphaLimit(value); break; default: @@ -540,126 +781,219 @@ #undef DGL_PushState void DGL_PushState(void) { + DGL_Flush(); GLState::push(); } #undef DGL_PopState void DGL_PopState(void) { + DGL_Flush(); GLState::pop(); - - // Make sure the restored state is immediately in effect. - GLState::current().apply(); } #undef DGL_Enable int DGL_Enable(int cap) { - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - switch(cap) + switch (cap) { - case DGL_TEXTURE_2D: - Deferred_glEnable(GL_TEXTURE_2D); - break; - - case DGL_FOG: - Deferred_glEnable(GL_FOG); - GL_state.currentUseFog = true; - break; - - case DGL_SCISSOR_TEST: - //glEnable(GL_SCISSOR_TEST); - break; - - case DGL_LINE_SMOOTH: - Deferred_glEnable(GL_LINE_SMOOTH); - break; + case DGL_BLEND: + if (!GLState::current().blend()) + { + DGL_Flush(); + GLState::current().setBlend(true); + } + break; + + case DGL_ALPHA_TEST: + // No flushing required. + GLState::current().setAlphaTest(true); + break; + + case DGL_DEPTH_TEST: + if (!GLState::current().depthTest()) + { + DGL_Flush(); + GLState::current().setDepthTest(true); + } + break; + + case DGL_DEPTH_WRITE: + if (!GLState::current().depthWrite()) + { + DGL_Flush(); + GLState::current().setDepthWrite(true); + } + break; + + case DGL_TEXTURE_2D: dgl.enableTexture[dgl.activeTexture] = true; break; + + case DGL_TEXTURE0: + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + dgl.enableTexture[0] = true; + break; + + case DGL_TEXTURE1: + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + dgl.enableTexture[1] = true; + break; + + case DGL_FOG: + if (!dgl.enableFog) + { + DGL_Flush(); + dgl.enableFog = true; + } + break; + + case DGL_SCISSOR_TEST: + //glEnable(GL_SCISSOR_TEST); + break; + + case DGL_LINE_SMOOTH: +#if defined(DENG_OPENGL) + Deferred_glEnable(GL_LINE_SMOOTH); +#endif + break; - case DGL_POINT_SMOOTH: - Deferred_glEnable(GL_POINT_SMOOTH); - break; + case DGL_POINT_SMOOTH: + //Deferred_glEnable(GL_POINT_SMOOTH); + // TODO: Not needed? + break; - default: - DENG_ASSERT(!"DGL_Enable: Invalid cap"); - return 0; + default: DENG_ASSERT(!"DGL_Enable: Invalid cap"); return 0; } + LIBGUI_ASSERT_GL_OK(); return 1; } #undef DGL_Disable void DGL_Disable(int cap) { - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - switch(cap) + switch (cap) { - case DGL_TEXTURE_2D: - Deferred_glDisable(GL_TEXTURE_2D); - break; - - case DGL_FOG: - Deferred_glDisable(GL_FOG); - GL_state.currentUseFog = false; - break; - - case DGL_SCISSOR_TEST: - //glDisable(GL_SCISSOR_TEST); - GLState::current().clearScissor().apply(); - break; - - case DGL_LINE_SMOOTH: - Deferred_glDisable(GL_LINE_SMOOTH); - break; + case DGL_BLEND: + if (GLState::current().blend()) + { + DGL_Flush(); + GLState::current().setBlend(false); + } + break; + + case DGL_DEPTH_TEST: + if (GLState::current().depthTest()) + { + DGL_Flush(); + GLState::current().setDepthTest(false); + } + break; + + case DGL_DEPTH_WRITE: + if (GLState::current().depthWrite()) + { + DGL_Flush(); + GLState::current().setDepthWrite(false); + } + break; + + case DGL_ALPHA_TEST: + // No flushing required. + GLState::current().setAlphaTest(false); + break; + + case DGL_TEXTURE_2D: dgl.enableTexture[dgl.activeTexture] = false; break; + + case DGL_TEXTURE0: + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + dgl.enableTexture[0] = false; + break; + + case DGL_TEXTURE1: + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + dgl.enableTexture[1] = false; + break; + + case DGL_FOG: + if (dgl.enableFog) + { + DGL_Flush(); + dgl.enableFog = false; + } + break; + + case DGL_SCISSOR_TEST: + DGL_Flush(); + GLState::current().clearScissor(); + break; + + case DGL_LINE_SMOOTH: +#if defined(DENG_OPENGL) + Deferred_glDisable(GL_LINE_SMOOTH); +#endif + break; - case DGL_POINT_SMOOTH: - Deferred_glDisable(GL_POINT_SMOOTH); - break; + case DGL_POINT_SMOOTH: +#if defined(DENG_OPENGL) + Deferred_glDisable(GL_POINT_SMOOTH); +#endif + break; - default: - DENG_ASSERT(!"DGL_Disable: Invalid cap"); - break; + default: DENG_ASSERT(!"DGL_Disable: Invalid cap"); break; } + + LIBGUI_ASSERT_GL_OK(); } #undef DGL_BlendOp void DGL_BlendOp(int op) { - GLState::current().setBlendOp(op == DGL_SUBTRACT ? gl::Subtract : - op == DGL_REVERSE_SUBTRACT ? gl::ReverseSubtract : - gl::Add) - .apply(); + const auto glop = op == DGL_SUBTRACT ? gl::Subtract : + op == DGL_REVERSE_SUBTRACT ? gl::ReverseSubtract : + gl::Add; + if (GLState::current().blendOp() != glop) + { + DGL_Flush(); + GLState::current().setBlendOp(glop); + } } #undef DGL_BlendFunc void DGL_BlendFunc(int param1, int param2) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - GLState::current().setBlendFunc(param1 == DGL_ZERO ? gl::Zero : - param1 == DGL_ONE ? gl::One : - param1 == DGL_DST_COLOR ? gl::DestColor : - param1 == DGL_ONE_MINUS_DST_COLOR ? gl::OneMinusDestColor : - param1 == DGL_SRC_ALPHA ? gl::SrcAlpha : - param1 == DGL_ONE_MINUS_SRC_ALPHA ? gl::OneMinusSrcAlpha : - param1 == DGL_DST_ALPHA ? gl::DestAlpha : - param1 == DGL_ONE_MINUS_DST_ALPHA ? gl::OneMinusDestAlpha : - gl::Zero - , - param2 == DGL_ZERO ? gl::Zero : - param2 == DGL_ONE ? gl::One : - param2 == DGL_SRC_COLOR ? gl::SrcColor : - param2 == DGL_ONE_MINUS_SRC_COLOR ? gl::OneMinusSrcColor : - param2 == DGL_SRC_ALPHA ? gl::SrcAlpha : - param2 == DGL_ONE_MINUS_SRC_ALPHA ? gl::OneMinusSrcAlpha : - param2 == DGL_DST_ALPHA ? gl::DestAlpha : - param2 == DGL_ONE_MINUS_DST_ALPHA ? gl::OneMinusDestAlpha : - gl::Zero) - .apply(); + const auto src = param1 == DGL_ZERO ? gl::Zero : + param1 == DGL_ONE ? gl::One : + param1 == DGL_DST_COLOR ? gl::DestColor : + param1 == DGL_ONE_MINUS_DST_COLOR ? gl::OneMinusDestColor : + param1 == DGL_SRC_ALPHA ? gl::SrcAlpha : + param1 == DGL_ONE_MINUS_SRC_ALPHA ? gl::OneMinusSrcAlpha : + param1 == DGL_DST_ALPHA ? gl::DestAlpha : + param1 == DGL_ONE_MINUS_DST_ALPHA ? gl::OneMinusDestAlpha : + gl::Zero; + + const auto dst = param2 == DGL_ZERO ? gl::Zero : + param2 == DGL_ONE ? gl::One : + param2 == DGL_SRC_COLOR ? gl::SrcColor : + param2 == DGL_ONE_MINUS_SRC_COLOR ? gl::OneMinusSrcColor : + param2 == DGL_SRC_ALPHA ? gl::SrcAlpha : + param2 == DGL_ONE_MINUS_SRC_ALPHA ? gl::OneMinusSrcAlpha : + param2 == DGL_DST_ALPHA ? gl::DestAlpha : + param2 == DGL_ONE_MINUS_DST_ALPHA ? gl::OneMinusDestAlpha : + gl::Zero; + + auto &st = GLState::current(); + if (st.blendFunc() != gl::BlendFunc(src, dst)) + { + DGL_Flush(); + GLState::current().setBlendFunc(src, dst); + } } #undef DGL_BlendMode @@ -668,32 +1002,6 @@ GL_BlendMode(mode); } -#undef DGL_MatrixMode -void DGL_MatrixMode(int mode) -{ - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - DENG_ASSERT(mode == DGL_PROJECTION || mode == DGL_TEXTURE || mode == DGL_MODELVIEW); - - LIBGUI_GL.glMatrixMode(mode == DGL_PROJECTION ? GL_PROJECTION : - mode == DGL_TEXTURE ? GL_TEXTURE : - GL_MODELVIEW); -} - -#undef DGL_PushMatrix -void DGL_PushMatrix(void) -{ - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - - LIBGUI_GL.glPushMatrix(); - -#if _DEBUG - if(LIBGUI_GL.glGetError() == GL_STACK_OVERFLOW) - App_Error("DG_PushMatrix: Stack overflow.\n"); -#endif -} - #undef DGL_SetNoMaterial void DGL_SetNoMaterial(void) { @@ -705,13 +1013,17 @@ switch(cap) { case DGL_CLAMP: - case DGL_CLAMP_TO_EDGE: return gl::ClampToEdge; + case DGL_CLAMP_TO_EDGE: + return gl::ClampToEdge; + + case DGL_REPEAT: + return gl::Repeat; - case DGL_REPEAT: return gl::Repeat; default: - App_Error("DGL_ToGLWrapCap: Unknown cap value %i.", (int)cap); - exit(1); // Unreachable. + DENG2_ASSERT(!"DGL_ToGLWrapCap: Unknown cap value"); + break; } + return gl::ClampToEdge; } #undef DGL_SetMaterialUI @@ -762,63 +1074,116 @@ GL_SetRawImage(lumpNum, DGL_ToGLWrapCap(wrapS), DGL_ToGLWrapCap(wrapT)); } +#undef DGL_MatrixMode +void DGL_MatrixMode(DGLenum mode) +{ + //DENG2_ASSERT_IN_RENDER_THREAD(); + + dgl.matrixMode = dgl.stackIndex(mode); +} + +#undef DGL_PushMatrix +void DGL_PushMatrix(void) +{ + //DENG2_ASSERT_IN_RENDER_THREAD(); + + dgl.pushMatrix(); +} + #undef DGL_PopMatrix void DGL_PopMatrix(void) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - - LIBGUI_GL.glPopMatrix(); + //DENG2_ASSERT_IN_RENDER_THREAD(); -#if _DEBUG - if(LIBGUI_GL.glGetError() == GL_STACK_UNDERFLOW) - App_Error("DG_PopMatrix: Stack underflow.\n"); -#endif + dgl.popMatrix(); } #undef DGL_LoadIdentity void DGL_LoadIdentity(void) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG2_ASSERT_IN_RENDER_THREAD(); + + dgl.loadMatrix(Matrix4f()); +} + +#undef DGL_LoadMatrix +void DGL_LoadMatrix(float const *matrix4x4) +{ + //DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glLoadIdentity(); + dgl.loadMatrix(Matrix4f(matrix4x4)); } #undef DGL_Translatef void DGL_Translatef(float x, float y, float z) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glTranslatef(x, y, z); + dgl.multMatrix(Matrix4f::translate(Vector3f(x, y, z))); } #undef DGL_Rotatef void DGL_Rotatef(float angle, float x, float y, float z) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glRotatef(angle, x, y, z); + dgl.multMatrix(Matrix4f::rotate(angle, Vector3f(x, y, z))); } #undef DGL_Scalef void DGL_Scalef(float x, float y, float z) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glScalef(x, y, z); + dgl.multMatrix(Matrix4f::scale(Vector3f(x, y, z))); } #undef DGL_Ortho void DGL_Ortho(float left, float top, float right, float bottom, float znear, float zfar) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + //DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glOrtho(left, right, bottom, top, znear, zfar); + dgl.multMatrix(Matrix4f::ortho(left, right, top, bottom, znear, zfar)); +} + +#undef DGL_Fogi +void DGL_Fogi(DGLenum property, int value) +{ + switch (property) + { + case DGL_FOG_MODE: + dgl.fogMode = DGLenum(value); + break; + } +} + +#undef DGL_Fogfv +void DGL_Fogfv(DGLenum property, float const *values) +{ + switch (property) + { + case DGL_FOG_START: + dgl.fogStart = values[0]; + break; + + case DGL_FOG_END: + dgl.fogEnd = values[0]; + break; + + case DGL_FOG_DENSITY: + dgl.fogDensity = values[0]; + break; + + case DGL_FOG_COLOR: + dgl.fogColor = Vector4f(values); + break; + } +} + +#undef DGL_Fogf +void DGL_Fogf(DGLenum property, float value) +{ + DGL_Fogfv(property, &value); } #undef DGL_DeleteTextures @@ -826,7 +1191,7 @@ { if(!num || !names) return; - Deferred_glDeleteTextures(num, (GLuint const *) names); + Deferred_glDeleteTextures(num, names); } #undef DGL_Bind @@ -842,6 +1207,9 @@ uint8_t const *pixels, int flags, int minFilter, int magFilter, int anisoFilter, int wrapS, int wrapT) { +#if defined (DENG_OPENGL_ES) +# define GL_CLAMP GL_CLAMP_TO_EDGE +#endif return GL_NewTextureWithParams(format, width, height, (uint8_t *)pixels, flags, 0, (minFilter == DGL_LINEAR ? GL_LINEAR : minFilter == DGL_NEAREST ? GL_NEAREST : @@ -855,15 +1223,14 @@ wrapS == DGL_CLAMP_TO_EDGE ? GL_CLAMP_TO_EDGE : GL_REPEAT), (wrapT == DGL_CLAMP ? GL_CLAMP : wrapT == DGL_CLAMP_TO_EDGE ? GL_CLAMP_TO_EDGE : GL_REPEAT)); +#if defined (DENG_OPENGL_ES) +# undef GL_CLAMP +#endif } // dgl_draw.cpp DENG_EXTERN_C void DGL_Begin(dglprimtype_t mode); DENG_EXTERN_C void DGL_End(void); -DENG_EXTERN_C dd_bool DGL_NewList(DGLuint list, int mode); -DENG_EXTERN_C DGLuint DGL_EndList(void); -DENG_EXTERN_C void DGL_CallList(DGLuint list); -DENG_EXTERN_C void DGL_DeleteLists(DGLuint list, int range); DENG_EXTERN_C void DGL_Color3ub(DGLubyte r, DGLubyte g, DGLubyte b); DENG_EXTERN_C void DGL_Color3ubv(const DGLubyte* vec); DENG_EXTERN_C void DGL_Color4ub(DGLubyte r, DGLubyte g, DGLubyte b, DGLubyte a); @@ -873,7 +1240,7 @@ DENG_EXTERN_C void DGL_Color4f(float r, float g, float b, float a); DENG_EXTERN_C void DGL_Color4fv(const float* vec); DENG_EXTERN_C void DGL_TexCoord2f(byte target, float s, float t); -DENG_EXTERN_C void DGL_TexCoord2fv(byte target, float* vec); +DENG_EXTERN_C void DGL_TexCoord2fv(byte target, float const *vec); DENG_EXTERN_C void DGL_Vertex2f(float x, float y); DENG_EXTERN_C void DGL_Vertex2fv(const float* vec); DENG_EXTERN_C void DGL_Vertex3f(float x, float y, float z); @@ -923,15 +1290,12 @@ DGL_PushMatrix, DGL_PopMatrix, DGL_LoadIdentity, + DGL_LoadMatrix, DGL_Translatef, DGL_Rotatef, DGL_Scalef, DGL_Begin, DGL_End, - DGL_NewList, - DGL_EndList, - DGL_CallList, - DGL_DeleteLists, DGL_SetNoMaterial, DGL_SetMaterialUI, DGL_SetPatch, @@ -972,6 +1336,9 @@ DGL_NewTextureWithParams, DGL_Bind, DGL_DeleteTextures, + DGL_Fogi, + DGL_Fogf, + DGL_Fogfv, GL_UseFog, GL_SetFilter, GL_SetFilterColor, @@ -979,5 +1346,5 @@ GL_ConfigureBorderedProjection, GL_BeginBorderedProjection, GL_EndBorderedProjection, - GL_ResetViewEffects + GL_ResetViewEffects, }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/dgl_draw.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/dgl_draw.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/dgl_draw.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/dgl_draw.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -1,4 +1,6 @@ -/** @file dgl_draw.cpp Drawing Operations and Vertex Arrays. +/** @file dgl_draw.cpp Drawing operations and vertex arrays. + * + * Emulates OpenGL 1.x drawing for legacy code. * * @authors Copyright © 2003-2017 Jaakko Keränen * @authors Copyright © 2007-2015 Daniel Swanson @@ -17,8 +19,6 @@ * http://www.gnu.org/licenses */ -#define DENG_NO_API_MACROS_GL - #include "de_base.h" #include "gl/gl_main.h" @@ -26,326 +26,933 @@ #include #include #include +#include +#include +#include +#include #include "sys_system.h" #include "gl/gl_draw.h" #include "gl/sys_opengl.h" +#include "clientapp.h" using namespace de; -static int primLevel = 0; -static DGLuint inList = 0; -#ifdef _DEBUG -static dd_bool inPrim = false; -#endif +constexpr uint MAX_TEX_COORDS = 2; +constexpr int MAX_BATCH = 16; + +static unsigned s_drawCallCount = 0; +static unsigned s_primSwitchCount = 0; +static unsigned s_minBatchLength = 0; +static unsigned s_maxBatchLength = 0; +static unsigned s_totalBatchCount = 0; -dd_bool GL_NewList(DGLuint list, int mode) +struct DGLDrawState { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + struct Vertex + { + float vertex[3]; + uint8_t color[4]; + struct { float s, t; } texCoord[MAX_TEX_COORDS]; + float fragOffset[2]; // Multiplied by uFragmentOffset + float batchIndex; + }; + + // Indices for vertex attribute arrays. + enum { + VAA_VERTEX, + VAA_COLOR, + VAA_TEXCOORD0, + VAA_TEXCOORD1, + VAA_FRAG_OFFSET, + VAA_BATCH_INDEX, + NUM_VERTEX_ATTRIB_ARRAYS + }; + + dglprimtype_t primType = DGL_NO_PRIMITIVE; + dglprimtype_t batchPrimType = DGL_NO_PRIMITIVE; + int primIndex = 0; + duint batchMaxSize; + duint currentBatchIndex; + bool resetPrimitive = false; + Vertex currentVertex = { + {0.f, 0.f, 0.f}, + {255, 255, 255, 255}, + {{0.f, 0.f}, {0.f, 0.f}}, + {0.f, 0.f}, + 0.f}; + Vertex primVertices[4]; + QVector vertices; - // We enter a New/End list section. -#ifdef _DEBUG - if(inList) - App_Error("GL_NewList: Already in list"); - Sys_GLCheckError(); -#endif + struct GLData + { + GLProgram shader; + + GLState batchState; + Matrix4f batchMvpMatrix[MAX_BATCH]; + Matrix4f batchTexMatrix0[MAX_BATCH]; + Matrix4f batchTexMatrix1[MAX_BATCH]; + int batchTexEnabled[MAX_BATCH]; + int batchTexMode[MAX_BATCH]; + Vector4f batchTexModeColor[MAX_BATCH]; + float batchAlphaLimit[MAX_BATCH]; + int batchTexture0[MAX_BATCH]; + int batchTexture1[MAX_BATCH]; + + // Batched uniforms: + GLUniform uMvpMatrix; + GLUniform uTexMatrix0; + GLUniform uTexMatrix1; + GLUniform uTexEnabled; + GLUniform uTexMode; + GLUniform uTexModeColor; + GLUniform uAlphaLimit; + + GLUniform uFragmentSize; + GLUniform uFogRange; + GLUniform uFogColor; - if(list) - { // A specific list id was requested. Is it free? - if(LIBGUI_GL.glIsList(list)) + struct DrawBuffer { -#if _DEBUG - App_Error("GL_NewList: List %u already in use.", (unsigned int) list); + GLuint vertexArray = 0; + GLBuffer arrayData; + + void release() + { +#if defined (DENG_HAVE_VAOS) + LIBGUI_GL.glDeleteVertexArrays(1, &vertexArray); #endif + arrayData.clear(); + } + }; + + GLData(duint batchSize) + : uMvpMatrix { "uMvpMatrix", GLUniform::Mat4Array , batchSize } + , uTexMatrix0 { "uTexMatrix0", GLUniform::Mat4Array , batchSize } + , uTexMatrix1 { "uTexMatrix1", GLUniform::Mat4Array , batchSize } + , uTexEnabled { "uTexEnabled", GLUniform::IntArray , batchSize } + , uTexMode { "uTexMode", GLUniform::IntArray , batchSize } + , uTexModeColor { "uTexModeColor", GLUniform::Vec4Array , batchSize } + , uAlphaLimit { "uAlphaLimit", GLUniform::FloatArray, batchSize } + , uFragmentSize { "uFragmentSize", GLUniform::Vec2 } + , uFogRange { "uFogRange", GLUniform::Vec4 } + , uFogColor { "uFogColor", GLUniform::Vec4 } + {} + + QVector buffers; + int bufferPos = 0; + }; + std::unique_ptr gl; + + DGLDrawState() + { + clearVertices(); + } + + void checkPrimitiveReset() + { + if (resetPrimitive) + { + DENG2_ASSERT(!vertices.empty()); + DENG2_ASSERT(glPrimitive(batchPrimType) == GL_TRIANGLE_STRIP); + + // When committing multiple triangle strips, add a disconnection + // between batches. + vertices.push_back(vertices.back()); + vertices.push_back(currentVertex); + resetPrimitive = false; + } + } + + void commitLine(Vertex start, Vertex end) + { + const Vector2f lineDir = (Vector2f(end.vertex) - Vector2f(start.vertex)).normalize(); + const Vector2f lineNormal{-lineDir.y, lineDir.x}; + + const bool disjoint = !vertices.empty(); + if (disjoint) + { + vertices.push_back(vertices.back()); + } + + // Start cap. + { + start.fragOffset[0] = -lineNormal.x; + start.fragOffset[1] = -lineNormal.y; + vertices.push_back(start); + if (disjoint) + { + vertices.push_back(start); + } + start.fragOffset[0] = lineNormal.x; + start.fragOffset[1] = lineNormal.y; + vertices.push_back(start); + } + + // End cap. + { + end.fragOffset[0] = -lineNormal.x; + end.fragOffset[1] = -lineNormal.y; + vertices.push_back(end); + end.fragOffset[0] = lineNormal.x; + end.fragOffset[1] = lineNormal.y; + vertices.push_back(end); + } + } + + void commitVertex() + { + currentVertex.batchIndex = float(currentBatchIndex); + ++primIndex; + + switch (primType) + { + case DGL_QUADS: + primVertices[primIndex - 1] = currentVertex; + if (primIndex == 4) + { + /* 4 vertices become 6: + + 0--1 0--1 5 + | | \ | |\ + | | => \| | \ + 3--2 2 4--3 */ + + vertices.push_back(primVertices[0]); + vertices.push_back(primVertices[1]); + vertices.push_back(primVertices[2]); + + vertices.push_back(primVertices[0]); + vertices.push_back(primVertices[2]); + vertices.push_back(primVertices[3]); + + primIndex = 0; + } + break; + + case DGL_LINES: + primVertices[primIndex - 1] = currentVertex; + if (primIndex == 2) + { + commitLine(primVertices[0], primVertices[1]); + primIndex = 0; + } + break; + + case DGL_LINE_LOOP: + case DGL_LINE_STRIP: + if (primIndex == 1) + { + // Remember the first one for a loop. + primVertices[0] = currentVertex; + } + if (primIndex > 1) + { + // Continue from the previous vertex. + commitLine(primVertices[1], currentVertex); + } + primVertices[1] = currentVertex; + break; + + case DGL_TRIANGLE_FAN: + if (primIndex == 1) + { + if (!vertices.empty()) + { + resetPrimitive = true; + } + checkPrimitiveReset(); + + // Fan origin. + primVertices[0] = currentVertex; + } + else if (primIndex > 2) + { + vertices.push_back(primVertices[0]); + } + vertices.push_back(currentVertex); + break; + + default: + checkPrimitiveReset(); + vertices.push_back(currentVertex); + break; + } + } + + void clearPrimitive() + { + primIndex = 0; + primType = DGL_NO_PRIMITIVE; + } + + void clearVertices() + { + // currentVertex is unaffected. + vertices.clear(); + clearPrimitive(); + currentBatchIndex = 0; + resetPrimitive = false; + } + + inline int numVertices() const + { + return vertices.size(); + } + + static Vector4ub colorFromFloat(const Vector4f &color) + { + Vector4i rgba = (color * 255 + Vector4f(0.5f, 0.5f, 0.5f, 0.5f)) + .toVector4i() + .max(Vector4i(0, 0, 0, 0)) + .min(Vector4i(255, 255, 255, 255)); + return Vector4ub(dbyte(rgba.x), dbyte(rgba.y), dbyte(rgba.z), dbyte(rgba.w)); + } + + void beginPrimitive(dglprimtype_t primitive) + { + glInit(); + + DENG2_ASSERT(primType == DGL_NO_PRIMITIVE); + + if (batchPrimType != DGL_NO_PRIMITIVE && !isCompatible(batchPrimType, primitive)) + { + ++s_primSwitchCount; + flushBatches(); + } + else + { + if (currentBatchIndex == MAX_BATCH - 1) + { + flushBatches(); + } + } + + // We enter a Begin/End section. + batchPrimType = primType = primitive; + + beginBatch(); + } + + void endPrimitive() + { + if (primType != DGL_NO_PRIMITIVE && !vertices.empty()) + { + if (primType == DGL_LINE_LOOP) + { + // Close the loop. + commitLine(currentVertex, primVertices[0]); + } + resetPrimitive = true; + DENG2_ASSERT(!vertices.empty()); + endBatch(); + } + clearPrimitive(); + } + + void getBoundTextures(int &id0, int &id1) + { + auto &GL = LIBGUI_GL; + GL.glActiveTexture(GL_TEXTURE0); + GL.glGetIntegerv(GL_TEXTURE_BINDING_2D, &id0); + GL.glActiveTexture(GL_TEXTURE1); + GL.glGetIntegerv(GL_TEXTURE_BINDING_2D, &id1); + GL.glActiveTexture(GLenum(GL_TEXTURE0 + DGL_GetInteger(DGL_ACTIVE_TEXTURE))); + } + + static inline bool isLinePrimitive(DGLenum p) + { + return p == DGL_LINES || p == DGL_LINE_STRIP || p == DGL_LINE_LOOP; + } + + static inline bool isCompatible(DGLenum p1, DGLenum p2) + { + // Lines are not considered separate because they need the uFragmentSize uniform + // for calculating thickness offsets. + if (isLinePrimitive(p1) != isLinePrimitive(p2)) + { return false; } + return glPrimitive(p1) == glPrimitive(p2); } - else + + void beginBatch() { - // Just get a new list id, it doesn't matter. - list = LIBGUI_GL.glGenLists(1); + const duint idx = currentBatchIndex; + + auto &dynamicState = GLState::current(); + + if (idx == 0) + { + gl->batchState = dynamicState; + zap(gl->batchTexture0); + zap(gl->batchTexture1); + } + else + { +#if defined (DENG2_DEBUG) + // GLState must not change while batches are begin collected. + // (Apart from the dynamic properties.) + GLState bat = gl->batchState; + GLState cur = dynamicState; + for (auto *st : {&bat, &cur}) + { + st->setAlphaLimit(0.f); + st->setAlphaTest(false); + } + DENG2_ASSERT(bat == cur); +#endif + } + + gl->batchMvpMatrix[idx] = DGL_Matrix(DGL_PROJECTION) * DGL_Matrix(DGL_MODELVIEW); + gl->batchTexMatrix0[idx] = DGL_Matrix(DGL_TEXTURE0); + gl->batchTexMatrix1[idx] = DGL_Matrix(DGL_TEXTURE1); + gl->batchTexEnabled[idx] = + (DGL_GetInteger(DGL_TEXTURE0) ? 0x1 : 0) | (DGL_GetInteger(DGL_TEXTURE1) ? 0x2 : 0); + gl->batchTexMode[idx] = DGL_GetInteger(DGL_MODULATE_TEXTURE); + gl->batchTexModeColor[idx] = DGL_ModulationColor(); + gl->batchAlphaLimit[idx] = (dynamicState.alphaTest() ? dynamicState.alphaLimit() : -1.f); + + // TODO: There is no need to use OpenGL to remember the bound textures. + // However, all DGL textures must be bound via DGL_Bind and not directly via OpenGL. + + getBoundTextures(gl->batchTexture0[idx], gl->batchTexture1[idx]); } - LIBGUI_GL.glNewList(list, mode == DGL_COMPILE? GL_COMPILE : GL_COMPILE_AND_EXECUTE); - inList = list; - return true; -} + void endBatch() + { + currentBatchIndex++; + if (currentBatchIndex == batchMaxSize) + { + flushBatches(); + } + } -DGLuint GL_EndList(void) -{ - DGLuint currentList = inList; + void flushBatches() + { +#if defined (DENG2_DEBUG) + if (DGL_GetInteger(DGL_FLUSH_BACKTRACE)) + { + DENG2_PRINT_BACKTRACE(); + } +#endif + if (currentBatchIndex > 0) + { + drawBatches(); + } + clearVertices(); + } - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + void glInit() + { + DENG_ASSERT_GL_CONTEXT_ACTIVE(); + + if (!gl) + { + batchMaxSize = DGL_BatchMaxSize(); + + gl.reset(new GLData(batchMaxSize)); + + // Set up the shader. + ClientApp::shaders().build(gl->shader, "dgl.draw") + << gl->uFragmentSize + << gl->uMvpMatrix + << gl->uTexMatrix0 + << gl->uTexMatrix1 + << gl->uTexEnabled + << gl->uTexMode + << gl->uTexModeColor + << gl->uAlphaLimit + << gl->uFogRange + << gl->uFogColor; + + auto &GL = LIBGUI_GL; + + // Sampler uniforms. + { + int samplers[2][MAX_BATCH]; + for (int i = 0; i < batchMaxSize; ++i) + { + samplers[0][i] = i; + samplers[1][i] = batchMaxSize + i; + } + + auto prog = gl->shader.glName(); + GL.glUseProgram(prog); + GL.glUniform1iv(GL.glGetUniformLocation(prog, "uTex0[0]"), GLsizei(batchMaxSize), samplers[0]); + LIBGUI_ASSERT_GL_OK(); + GL.glUniform1iv(GL.glGetUniformLocation(prog, "uTex1[0]"), GLsizei(batchMaxSize), samplers[1]); + LIBGUI_ASSERT_GL_OK(); + GL.glUseProgram(0); + } + } + } - LIBGUI_GL.glEndList(); -#ifdef _DEBUG - inList = 0; - Sys_GLCheckError(); + void glDeinit() + { + if (gl) + { + foreach (GLData::DrawBuffer *dbuf, gl->buffers) + { + dbuf->release(); + delete dbuf; + } + gl.reset(); + } + } + + GLData::DrawBuffer &nextBuffer() + { + if (gl->bufferPos == gl->buffers.size()) + { + auto *dbuf = new GLData::DrawBuffer; + + // Vertex array object. +#if defined (DENG_HAVE_VAOS) + { + auto &GL = LIBGUI_GL; + GL.glGenVertexArrays(1, &dbuf->vertexArray); + GL.glBindVertexArray(dbuf->vertexArray); + for (uint i = 0; i < NUM_VERTEX_ATTRIB_ARRAYS; ++i) + { + GL.glEnableVertexAttribArray(i); + } + GL.glBindVertexArray(0); + } #endif - return currentList; + gl->buffers.append(dbuf); + } + return *gl->buffers[gl->bufferPos++]; + } + + void glBindArrays() + { + const uint stride = sizeof(Vertex); + auto &GL = LIBGUI_GL; + + // Upload the vertex data. + GLData::DrawBuffer &buf = nextBuffer(); + buf.arrayData.setData(&vertices[0], sizeof(Vertex) * vertices.size(), gl::Dynamic); + +#if defined (DENG_HAVE_VAOS) + GL.glBindVertexArray(buf.vertexArray); +#else + for (uint i = 0; i < NUM_VERTEX_ATTRIB_ARRAYS; ++i) + { + GL.glEnableVertexAttribArray(i); + } +#endif + LIBGUI_ASSERT_GL_OK(); + + GL.glBindBuffer(GL_ARRAY_BUFFER, buf.arrayData.glName()); + LIBGUI_ASSERT_GL_OK(); + + // Updated pointers. + GL.glVertexAttribPointer(VAA_VERTEX, 3, GL_FLOAT, GL_FALSE, stride, DENG2_OFFSET_PTR(Vertex, vertex)); + GL.glVertexAttribPointer(VAA_COLOR, 4, GL_UNSIGNED_BYTE, GL_TRUE, stride, DENG2_OFFSET_PTR(Vertex, color)); + GL.glVertexAttribPointer(VAA_TEXCOORD0, 2, GL_FLOAT, GL_FALSE, stride, DENG2_OFFSET_PTR(Vertex, texCoord[0])); + GL.glVertexAttribPointer(VAA_TEXCOORD1, 2, GL_FLOAT, GL_FALSE, stride, DENG2_OFFSET_PTR(Vertex, texCoord[1])); + GL.glVertexAttribPointer(VAA_FRAG_OFFSET, 2, GL_FLOAT, GL_FALSE, stride, DENG2_OFFSET_PTR(Vertex, fragOffset[0])); + GL.glVertexAttribPointer(VAA_BATCH_INDEX, 1, GL_FLOAT, GL_FALSE, stride, DENG2_OFFSET_PTR(Vertex, batchIndex)); + LIBGUI_ASSERT_GL_OK(); + + GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + void glUnbindArrays() + { + auto &GL = LIBGUI_GL; + +#if defined (DENG_HAVE_VAOS) + GL.glBindVertexArray(0); +#else + for (uint i = 0; i < NUM_VERTEX_ATTRIB_ARRAYS; ++i) + { + GL.glDisableVertexAttribArray(i); + LIBGUI_ASSERT_GL_OK(); + } +#endif + } + + void glBindBatchTextures(duint count) + { + auto &GL = LIBGUI_GL; + for (duint i = 0; i < count; ++i) + { + GL.glActiveTexture(GLenum(GL_TEXTURE0 + i)); + GL.glBindTexture(GL_TEXTURE_2D, GLuint(gl->batchTexture0[i])); + GL.glActiveTexture(GLenum(GL_TEXTURE0 + batchMaxSize + i)); + GL.glBindTexture(GL_TEXTURE_2D, GLuint(gl->batchTexture1[i])); + } + } + + static GLenum glPrimitive(DGLenum primitive) + { + switch (primitive) + { + case DGL_POINTS: return GL_POINTS; + case DGL_LINES: return GL_TRIANGLE_STRIP; + case DGL_LINE_LOOP: return GL_TRIANGLE_STRIP; + case DGL_LINE_STRIP: return GL_TRIANGLE_STRIP; + case DGL_TRIANGLES: return GL_TRIANGLES; + case DGL_TRIANGLE_FAN: return GL_TRIANGLE_STRIP; + case DGL_TRIANGLE_STRIP: return GL_TRIANGLE_STRIP; + case DGL_QUADS: return GL_TRIANGLES; + + case DGL_NO_PRIMITIVE: /*DENG2_ASSERT(!"No primitive type specified");*/ break; + } + return GL_NONE; + } + + /** + * Draws all the primitives currently stored in the vertex array. + */ + void drawBatches() + { + const auto batchLength = duint(currentBatchIndex); + + s_minBatchLength = de::min(s_minBatchLength, batchLength); + s_maxBatchLength = de::max(s_maxBatchLength, batchLength); + s_totalBatchCount += batchLength; + + int oldTex[2]; + getBoundTextures(oldTex[0], oldTex[1]); + + glBindBatchTextures(batchLength); + + // Batched uniforms. + gl->uMvpMatrix.set(gl->batchMvpMatrix, batchLength); + gl->uTexMatrix0.set(gl->batchTexMatrix0, batchLength); + gl->uTexMatrix1.set(gl->batchTexMatrix1, batchLength); + gl->uTexEnabled.set(gl->batchTexEnabled, batchLength); + gl->uTexMode.set(gl->batchTexMode, batchLength); + gl->uTexModeColor.set(gl->batchTexModeColor, batchLength); + gl->uAlphaLimit.set(gl->batchAlphaLimit, batchLength); + + const GLState &glState = gl->batchState; + + // Non-batched uniforms. + if (isLinePrimitive(batchPrimType)) + { + gl->uFragmentSize = Vector2f(GL_state.currentLineWidth, GL_state.currentLineWidth) / + glState.target().size(); + } + else + { + gl->uFragmentSize = Vector2f(); + } + DGL_FogParams(gl->uFogRange, gl->uFogColor); + + auto &GL = LIBGUI_GL; + + glState.apply(); + + glBindArrays(); + gl->shader.beginUse(); + DENG2_ASSERT(gl->shader.validate()); + GL.glDrawArrays(glPrimitive(batchPrimType), 0, numVertices()); ++s_drawCallCount; + gl->shader.endUse(); + LIBGUI_ASSERT_GL_OK(); + glUnbindArrays(); + + // Restore the previously bound OpenGL textures. + { + GL.glActiveTexture(GL_TEXTURE0); + GL.glBindTexture(GL_TEXTURE_2D, GLuint(oldTex[0])); + GL.glActiveTexture(GL_TEXTURE1); + GL.glBindTexture(GL_TEXTURE_2D, GLuint(oldTex[1])); + GL.glActiveTexture(GLenum(GL_TEXTURE0 + DGL_GetInteger(DGL_ACTIVE_TEXTURE))); + } + } +}; + +static DGLDrawState dglDraw; + +unsigned int DGL_BatchMaxSize() +{ + auto &GL = LIBGUI_GL; + + // This determines how long DGL batch draws can be. + int maxFragSamplers; + GL.glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, &maxFragSamplers); + + return duint(de::min(MAX_BATCH, de::max(8, maxFragSamplers / 2))); // DGL needs two per draw. } -void GL_CallList(DGLuint list) +void DGL_Shutdown() { - if(!list) return; // We do not consider zero a valid list id. + dglDraw.glDeinit(); +} - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); +void DGL_BeginFrame() +{ +// qDebug() << "draw calls:" << s_drawCallCount << "prim switch:" << s_primSwitchCount +// << "batch min/max/avg:" << s_minBatchLength << s_maxBatchLength +// << (s_drawCallCount ? float(s_totalBatchCount) / float(s_drawCallCount) : 0.f); - LIBGUI_GL.glCallList(list); + s_drawCallCount = 0; + s_totalBatchCount = 0; + s_primSwitchCount = 0; + s_maxBatchLength = 0; + s_minBatchLength = std::numeric_limits::max(); + + if (dglDraw.gl) + { + // Reuse buffers every frame. + dglDraw.gl->bufferPos = 0; + } } -void GL_DeleteLists(DGLuint list, int range) +void DGL_Flush() { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + // Finish all batched draws. + dglDraw.flushBatches(); +} - LIBGUI_GL.glDeleteLists(list, range); +void DGL_CurrentColor(DGLubyte *rgba) +{ + std::memcpy(rgba, dglDraw.currentVertex.color, 4); +} + +void DGL_CurrentColor(float *rgba) +{ + Vector4f colorf = Vector4ub(dglDraw.currentVertex.color).toVector4f() / 255.0; + std::memcpy(rgba, colorf.constPtr(), sizeof(float) * 4); } #undef DGL_Color3ub DENG_EXTERN_C void DGL_Color3ub(DGLubyte r, DGLubyte g, DGLubyte b) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor3ub(r, g, b); + dglDraw.currentVertex.color[0] = r; + dglDraw.currentVertex.color[1] = g; + dglDraw.currentVertex.color[2] = b; + dglDraw.currentVertex.color[3] = 255; } #undef DGL_Color3ubv -DENG_EXTERN_C void DGL_Color3ubv(const DGLubyte* vec) +DENG_EXTERN_C void DGL_Color3ubv(DGLubyte const *vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor3ubv(vec); + dglDraw.currentVertex.color[0] = vec[0]; + dglDraw.currentVertex.color[1] = vec[1]; + dglDraw.currentVertex.color[2] = vec[2]; + dglDraw.currentVertex.color[3] = 255; } #undef DGL_Color4ub DENG_EXTERN_C void DGL_Color4ub(DGLubyte r, DGLubyte g, DGLubyte b, DGLubyte a) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor4ub(r, g, b, a); + dglDraw.currentVertex.color[0] = r; + dglDraw.currentVertex.color[1] = g; + dglDraw.currentVertex.color[2] = b; + dglDraw.currentVertex.color[3] = a; } #undef DGL_Color4ubv -DENG_EXTERN_C void DGL_Color4ubv(const DGLubyte* vec) +DENG_EXTERN_C void DGL_Color4ubv(DGLubyte const *vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor4ubv(vec); + dglDraw.currentVertex.color[0] = vec[0]; + dglDraw.currentVertex.color[1] = vec[1]; + dglDraw.currentVertex.color[2] = vec[2]; + dglDraw.currentVertex.color[3] = vec[3]; } #undef DGL_Color3f DENG_EXTERN_C void DGL_Color3f(float r, float g, float b) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor3f(r, g, b); + const auto color = DGLDrawState::colorFromFloat({r, g, b, 1.f}); + dglDraw.currentVertex.color[0] = color.x; + dglDraw.currentVertex.color[1] = color.y; + dglDraw.currentVertex.color[2] = color.z; + dglDraw.currentVertex.color[3] = color.w; } #undef DGL_Color3fv -DENG_EXTERN_C void DGL_Color3fv(const float* vec) +DENG_EXTERN_C void DGL_Color3fv(float const *vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor3fv(vec); + const auto color = DGLDrawState::colorFromFloat({Vector3f(vec), 1.f}); + dglDraw.currentVertex.color[0] = color.x; + dglDraw.currentVertex.color[1] = color.y; + dglDraw.currentVertex.color[2] = color.z; + dglDraw.currentVertex.color[3] = color.w; } #undef DGL_Color4f DENG_EXTERN_C void DGL_Color4f(float r, float g, float b, float a) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor4f(r, g, b, a); + const auto color = DGLDrawState::colorFromFloat({r, g, b, a}); + dglDraw.currentVertex.color[0] = color.x; + dglDraw.currentVertex.color[1] = color.y; + dglDraw.currentVertex.color[2] = color.z; + dglDraw.currentVertex.color[3] = color.w; } #undef DGL_Color4fv -DENG_EXTERN_C void DGL_Color4fv(const float* vec) +DENG_EXTERN_C void DGL_Color4fv(float const *vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glColor4fv(vec); + const auto color = DGLDrawState::colorFromFloat(vec); + dglDraw.currentVertex.color[0] = color.x; + dglDraw.currentVertex.color[1] = color.y; + dglDraw.currentVertex.color[2] = color.z; + dglDraw.currentVertex.color[3] = color.w; } #undef DGL_TexCoord2f DENG_EXTERN_C void DGL_TexCoord2f(byte target, float s, float t) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); + DENG2_ASSERT(target < MAX_TEX_COORDS); - LIBGUI_GL.glMultiTexCoord2f(GL_TEXTURE0 + target, s, t); + if (target < MAX_TEX_COORDS) + { + dglDraw.currentVertex.texCoord[target].s = s; + dglDraw.currentVertex.texCoord[target].t = t; + } } #undef DGL_TexCoord2fv -DENG_EXTERN_C void DGL_TexCoord2fv(byte target, float* vec) +DENG_EXTERN_C void DGL_TexCoord2fv(byte target, float const *vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); + DENG2_ASSERT(target < MAX_TEX_COORDS); - LIBGUI_GL.glMultiTexCoord2fv(GL_TEXTURE0 + target, vec); + if (target < MAX_TEX_COORDS) + { + dglDraw.currentVertex.texCoord[target].s = vec[0]; + dglDraw.currentVertex.texCoord[target].t = vec[1]; + } } #undef DGL_Vertex2f DENG_EXTERN_C void DGL_Vertex2f(float x, float y) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glVertex2f(x, y); + dglDraw.currentVertex.vertex[0] = x; + dglDraw.currentVertex.vertex[1] = y; + dglDraw.currentVertex.vertex[2] = 0.f; + dglDraw.commitVertex(); } #undef DGL_Vertex2fv DENG_EXTERN_C void DGL_Vertex2fv(const float* vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glVertex2fv(vec); + if (vec) + { + dglDraw.currentVertex.vertex[0] = vec[0]; + dglDraw.currentVertex.vertex[1] = vec[1]; + dglDraw.currentVertex.vertex[2] = 0.f; + } + dglDraw.commitVertex(); } #undef DGL_Vertex3f DENG_EXTERN_C void DGL_Vertex3f(float x, float y, float z) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); + + dglDraw.currentVertex.vertex[0] = x; + dglDraw.currentVertex.vertex[1] = y; + dglDraw.currentVertex.vertex[2] = z; - LIBGUI_GL.glVertex3f(x, y, z); + dglDraw.commitVertex(); } #undef DGL_Vertex3fv DENG_EXTERN_C void DGL_Vertex3fv(const float* vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); - LIBGUI_GL.glVertex3fv(vec); + if (vec) + { + dglDraw.currentVertex.vertex[0] = vec[0]; + dglDraw.currentVertex.vertex[1] = vec[1]; + dglDraw.currentVertex.vertex[2] = vec[2]; + } + dglDraw.commitVertex(); } #undef DGL_Vertices2ftv DENG_EXTERN_C void DGL_Vertices2ftv(int num, const dgl_ft2vertex_t* vec) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); for(; num > 0; num--, vec++) { - LIBGUI_GL.glTexCoord2fv(vec->tex); - LIBGUI_GL.glVertex2fv(vec->pos); + DGL_TexCoord2fv(0, vec->tex); + DGL_Vertex2fv(vec->pos); } } #undef DGL_Vertices3ftv DENG_EXTERN_C void DGL_Vertices3ftv(int num, const dgl_ft3vertex_t* vec) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); for(; num > 0; num--, vec++) { - LIBGUI_GL.glTexCoord2fv(vec->tex); - LIBGUI_GL.glVertex3fv(vec->pos); + DGL_TexCoord2fv(0, vec->tex); + DGL_Vertex3fv(vec->pos); } } #undef DGL_Vertices3fctv DENG_EXTERN_C void DGL_Vertices3fctv(int num, const dgl_fct3vertex_t* vec) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); for(; num > 0; num--, vec++) { - LIBGUI_GL.glColor4fv(vec->color); - LIBGUI_GL.glTexCoord2fv(vec->tex); - LIBGUI_GL.glVertex3fv(vec->pos); + DGL_Color4fv(vec->color); + DGL_TexCoord2fv(0, vec->tex); + DGL_Vertex3fv(vec->pos); } } #undef DGL_Begin DENG_EXTERN_C void DGL_Begin(dglprimtype_t mode) { - if(novideo) - return; + if (novideo) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - // We enter a Begin/End section. - primLevel++; - -#ifdef _DEBUG - if(inPrim) - App_Error("OpenGL: already inPrim"); - inPrim = true; - Sys_GLCheckError(); -#endif - - LIBGUI_GL.glBegin(mode == DGL_POINTS ? GL_POINTS : mode == - DGL_LINES ? GL_LINES : mode == - DGL_TRIANGLES ? GL_TRIANGLES : mode == - DGL_TRIANGLE_FAN ? GL_TRIANGLE_FAN : mode == - DGL_TRIANGLE_STRIP ? GL_TRIANGLE_STRIP : mode == - DGL_QUAD_STRIP ? GL_QUAD_STRIP : GL_QUADS); + dglDraw.beginPrimitive(mode); } void DGL_AssertNotInPrimitive(void) { - DENG_ASSERT(!inPrim); + DENG_ASSERT(dglDraw.primType == DGL_NO_PRIMITIVE); } #undef DGL_End DENG_EXTERN_C void DGL_End(void) { - if(novideo) - return; + if (novideo) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - if(primLevel > 0) - { - primLevel--; - LIBGUI_GL.glEnd(); - } - -#ifdef _DEBUG - inPrim = false; - Sys_GLCheckError(); -#endif -} - -#undef DGL_NewList -DENG_EXTERN_C dd_bool DGL_NewList(DGLuint list, int mode) -{ - return GL_NewList(list, mode); -} - -#undef DGL_EndList -DENG_EXTERN_C DGLuint DGL_EndList(void) -{ - return GL_EndList(); -} - -#undef DGL_CallList -DENG_EXTERN_C void DGL_CallList(DGLuint list) -{ - GL_CallList(list); -} - -#undef DGL_DeleteLists -DENG_EXTERN_C void DGL_DeleteLists(DGLuint list, int range) -{ - GL_DeleteLists(list, range); + dglDraw.endPrimitive(); } #undef DGL_DrawLine @@ -358,7 +965,7 @@ #undef DGL_DrawRect DENG_EXTERN_C void DGL_DrawRect(RectRaw const *rect) { - if(!rect) return; + if (!rect) return; GL_DrawRect(Rectanglei::fromSize(Vector2i(rect->origin.xy), Vector2ui(rect->size.width, rect->size.height))); } @@ -385,9 +992,8 @@ DENG_EXTERN_C void DGL_DrawRectf2Color(double x, double y, double w, double h, float r, float g, float b, float a) { DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glColor4f(r, g, b, a); + DGL_Color4f(r, g, b, a); GL_DrawRectf2(x, y, w, h); } @@ -418,15 +1024,15 @@ if(!tl || !tr || !br || !bl || (color && !(color[CA] > 0))) return; DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); if(color) DGL_Color4fv(color); - LIBGUI_GL.glBegin(GL_LINE_LOOP); - LIBGUI_GL.glVertex2iv((const GLint*)tl->xy); - LIBGUI_GL.glVertex2iv((const GLint*)tr->xy); - LIBGUI_GL.glVertex2iv((const GLint*)br->xy); - LIBGUI_GL.glVertex2iv((const GLint*)bl->xy); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINE_STRIP); + DGL_Vertex2f(tl->x, tl->y); + DGL_Vertex2f(tr->x, tr->y); + DGL_Vertex2f(br->x, br->y); + DGL_Vertex2f(bl->x, bl->y); + DGL_Vertex2f(tl->x, tl->y); + DGL_End(); } #undef DGL_DrawQuad2Outline diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_deferredapi.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_deferredapi.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_deferredapi.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_deferredapi.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -25,11 +25,12 @@ #include #include +#include #include "gl/gl_defer.h" static dd_bool __inline mustDefer(void) { - return !Sys_InMainThread(); + return !de::GuiApp::inRenderThread(); } static void GL_CALL deng_glEnable(GLenum e) @@ -47,21 +48,6 @@ LIBGUI_GL.glDeleteTextures(num, names); } -static void GL_CALL deng_glFogi(GLenum p, GLint v) -{ - LIBGUI_GL.glFogi(p, v); -} - -static void GL_CALL deng_glFogf(GLenum p, GLfloat v) -{ - LIBGUI_GL.glFogf(p, v); -} - -static void GL_CALL deng_glFogfv(GLenum p, GLfloat const *v) -{ - LIBGUI_GL.glFogfv(p, v); -} - #define GL_CALL1(form, func, x) \ if(mustDefer()) GL_Defer_##form(func, x); else func(x); #define GL_CALL2(form, func, x, y) \ @@ -82,17 +68,3 @@ GL_CALL2(uintArray, deng_glDeleteTextures, num, names); } -DENG_EXTERN_C void Deferred_glFogi(GLenum p, GLint v) -{ - GL_CALL2(i, deng_glFogi, p, v); -} - -DENG_EXTERN_C void Deferred_glFogf(GLenum p, GLfloat v) -{ - GL_CALL2(f, deng_glFogf, p, v); -} - -DENG_EXTERN_C void Deferred_glFogfv(GLenum p, GLfloat const *v) -{ - GL_CALL2(fv4, deng_glFogfv, p, v); -} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_draw.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_draw.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_draw.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_draw.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -41,26 +41,25 @@ void GL_DrawRectWithCoords(Rectanglei const &rect, Vector2i const coords[4]) { - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); // Top left. - if(coords) LIBGUI_GL.glTexCoord2i(coords[0].x, coords[0].y); - LIBGUI_GL.glVertex2f(rect.topLeft.x, rect.topLeft.y); + if(coords) DGL_TexCoord2f(0, coords[0].x, coords[0].y); + DGL_Vertex2f(rect.topLeft.x, rect.topLeft.y); // Top Right. - if(coords) LIBGUI_GL.glTexCoord2i(coords[1].x, coords[1].y); - LIBGUI_GL.glVertex2f(rect.topRight().x, rect.topRight().y); + if(coords) DGL_TexCoord2f(0, coords[1].x, coords[1].y); + DGL_Vertex2f(rect.topRight().x, rect.topRight().y); // Bottom right. - if(coords) LIBGUI_GL.glTexCoord2i(coords[2].x, coords[2].y); - LIBGUI_GL.glVertex2f(rect.bottomRight.x, rect.bottomRight.y); + if(coords) DGL_TexCoord2f(0, coords[2].x, coords[2].y); + DGL_Vertex2f(rect.bottomRight.x, rect.bottomRight.y); // Bottom left. - if(coords) LIBGUI_GL.glTexCoord2i(coords[3].x, coords[3].y); - LIBGUI_GL.glVertex2f(rect.bottomLeft().x, rect.bottomLeft().y); - LIBGUI_GL.glEnd(); + if(coords) DGL_TexCoord2f(0, coords[3].x, coords[3].y); + DGL_Vertex2f(rect.bottomLeft().x, rect.bottomLeft().y); + DGL_End(); } void GL_DrawRect(Rectanglei const &rect) @@ -79,26 +78,25 @@ { if(!rect) return; - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); // Upper left. - if(coords) LIBGUI_GL.glTexCoord2dv((GLdouble*)coords[0].xy); - LIBGUI_GL.glVertex2d(rect->origin.x, rect->origin.y); + if(coords) DGL_TexCoord2f(0, coords[0].x, coords[0].y); + DGL_Vertex2f(rect->origin.x, rect->origin.y); // Upper Right. - if(coords) LIBGUI_GL.glTexCoord2dv((GLdouble*)coords[1].xy); - LIBGUI_GL.glVertex2d(rect->origin.x + rect->size.width, rect->origin.y); + if(coords) DGL_TexCoord2f(0, coords[1].x, coords[1].y); + DGL_Vertex2f(rect->origin.x + rect->size.width, rect->origin.y); // Lower right. - if(coords) LIBGUI_GL.glTexCoord2dv((GLdouble*)coords[2].xy); - LIBGUI_GL.glVertex2d(rect->origin.x + rect->size.width, rect->origin.y + rect->size.height); + if(coords) DGL_TexCoord2f(0, coords[2].x, coords[2].y); + DGL_Vertex2f(rect->origin.x + rect->size.width, rect->origin.y + rect->size.height); // Lower left. - if(coords) LIBGUI_GL.glTexCoord2dv((GLdouble*)coords[3].xy); - LIBGUI_GL.glVertex2d(rect->origin.x, rect->origin.y + rect->size.height); - LIBGUI_GL.glEnd(); + if(coords) DGL_TexCoord2f(0, coords[3].x, coords[3].y); + DGL_Vertex2f(rect->origin.x, rect->origin.y + rect->size.height); + DGL_End(); } void GL_DrawRectf(const RectRawf* rect) @@ -127,7 +125,7 @@ void GL_DrawRectf2Color(double x, double y, double w, double h, float r, float g, float b, float a) { - LIBGUI_GL.glColor4f(r, g, b, a); + DGL_Color4f(r, g, b, a); GL_DrawRectf2(x, y, w, h); } @@ -137,41 +135,39 @@ { if(topAlpha <= 0 && bottomAlpha <= 0) return; - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); // Top color. - LIBGUI_GL.glColor4f(topColor[0], topColor[1], topColor[2], topAlpha); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex2f(x, y); - LIBGUI_GL.glTexCoord2f(width / (float) texW, 0); - LIBGUI_GL.glVertex2f(x + width, y); + DGL_Color4f(topColor[0], topColor[1], topColor[2], topAlpha); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex2f(x, y); + DGL_TexCoord2f(0, width / (float) texW, 0); + DGL_Vertex2f(x + width, y); // Bottom color. - LIBGUI_GL.glColor4f(bottomColor[0], bottomColor[1], bottomColor[2], bottomAlpha); - LIBGUI_GL.glTexCoord2f(width / (float) texW, height / (float) texH); - LIBGUI_GL.glVertex2f(x + width, y + height); - LIBGUI_GL.glTexCoord2f(0, height / (float) texH); - LIBGUI_GL.glVertex2f(x, y + height); - LIBGUI_GL.glEnd(); + DGL_Color4f(bottomColor[0], bottomColor[1], bottomColor[2], bottomAlpha); + DGL_TexCoord2f(0, width / (float) texW, height / (float) texH); + DGL_Vertex2f(x + width, y + height); + DGL_TexCoord2f(0, 0, height / (float) texH); + DGL_Vertex2f(x, y + height); + DGL_End(); } void GL_DrawRectf2Tiled(double x, double y, double w, double h, int tw, int th) { - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex2d(x, y); - LIBGUI_GL.glTexCoord2f(w / (float) tw, 0); - LIBGUI_GL.glVertex2d(x + w, y); - LIBGUI_GL.glTexCoord2f(w / (float) tw, h / (float) th); - LIBGUI_GL.glVertex2d(x + w, y + h); - LIBGUI_GL.glTexCoord2f(0, h / (float) th); - LIBGUI_GL.glVertex2d(x, y + h); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex2f(x, y); + DGL_TexCoord2f(0, w / (float) tw, 0); + DGL_Vertex2f(x + w, y); + DGL_TexCoord2f(0, w / (float) tw, h / (float) th); + DGL_Vertex2f(x + w, y + h); + DGL_TexCoord2f(0, 0, h / (float) th); + DGL_Vertex2f(x, y + h); + DGL_End(); } void GL_DrawCutRectfTiled(const RectRawf* rect, int tw, int th, int txoff, int tyoff, @@ -188,21 +184,20 @@ float lefth = cutRect->origin.x - rect->origin.x; float righth = rect->origin.x + rect->size.width - (cutRect->origin.x + cutRect->size.width); - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); if(toph > 0) { // The top rectangle. - LIBGUI_GL.glTexCoord2f(txo, tyo); - LIBGUI_GL.glVertex2f(rect->origin.x, rect->origin.y); - LIBGUI_GL.glTexCoord2f(txo + (rect->size.width / ftw), tyo); - LIBGUI_GL.glVertex2f(rect->origin.x + rect->size.width, rect->origin.y); - LIBGUI_GL.glTexCoord2f(txo + (rect->size.width / ftw), tyo + (toph / fth)); - LIBGUI_GL.glVertex2f(rect->origin.x + rect->size.width, rect->origin.y + toph); - LIBGUI_GL.glTexCoord2f(txo, tyo + (toph / fth)); - LIBGUI_GL.glVertex2f(rect->origin.x, rect->origin.y + toph); + DGL_TexCoord2f(0, txo, tyo); + DGL_Vertex2f(rect->origin.x, rect->origin.y); + DGL_TexCoord2f(0, txo + (rect->size.width / ftw), tyo); + DGL_Vertex2f(rect->origin.x + rect->size.width, rect->origin.y); + DGL_TexCoord2f(0, txo + (rect->size.width / ftw), tyo + (toph / fth)); + DGL_Vertex2f(rect->origin.x + rect->size.width, rect->origin.y + toph); + DGL_TexCoord2f(0, txo, tyo + (toph / fth)); + DGL_Vertex2f(rect->origin.x, rect->origin.y + toph); } if(lefth > 0 && sideh > 0) @@ -210,14 +205,14 @@ float yoff = toph / fth; // The left rectangle. - LIBGUI_GL.glTexCoord2f(txo, yoff + tyo); - LIBGUI_GL.glVertex2f(rect->origin.x, rect->origin.y + toph); - LIBGUI_GL.glTexCoord2f(txo + (lefth / ftw), yoff + tyo); - LIBGUI_GL.glVertex2f(rect->origin.x + lefth, rect->origin.y + toph); - LIBGUI_GL.glTexCoord2f(txo + (lefth / ftw), yoff + tyo + sideh / fth); - LIBGUI_GL.glVertex2f(rect->origin.x + lefth, rect->origin.y + toph + sideh); - LIBGUI_GL.glTexCoord2f(txo, yoff + tyo + sideh / fth); - LIBGUI_GL.glVertex2f(rect->origin.x, rect->origin.y + toph + sideh); + DGL_TexCoord2f(0, txo, yoff + tyo); + DGL_Vertex2f(rect->origin.x, rect->origin.y + toph); + DGL_TexCoord2f(0, txo + (lefth / ftw), yoff + tyo); + DGL_Vertex2f(rect->origin.x + lefth, rect->origin.y + toph); + DGL_TexCoord2f(0, txo + (lefth / ftw), yoff + tyo + sideh / fth); + DGL_Vertex2f(rect->origin.x + lefth, rect->origin.y + toph + sideh); + DGL_TexCoord2f(0, txo, yoff + tyo + sideh / fth); + DGL_Vertex2f(rect->origin.x, rect->origin.y + toph + sideh); } if(righth > 0 && sideh > 0) @@ -227,14 +222,14 @@ float yoff = toph / fth; // The left rectangle. - LIBGUI_GL.glTexCoord2f(xoff + txo, yoff + tyo); - LIBGUI_GL.glVertex2f(ox, rect->origin.y + toph); - LIBGUI_GL.glTexCoord2f(xoff + txo + righth / ftw, yoff + tyo); - LIBGUI_GL.glVertex2f(ox + righth, rect->origin.y + toph); - LIBGUI_GL.glTexCoord2f(xoff + txo + righth / ftw, yoff + tyo + sideh / fth); - LIBGUI_GL.glVertex2f(ox + righth, rect->origin.y + toph + sideh); - LIBGUI_GL.glTexCoord2f(xoff + txo, yoff + tyo + sideh / fth); - LIBGUI_GL.glVertex2f(ox, rect->origin.y + toph + sideh); + DGL_TexCoord2f(0, xoff + txo, yoff + tyo); + DGL_Vertex2f(ox, rect->origin.y + toph); + DGL_TexCoord2f(0, xoff + txo + righth / ftw, yoff + tyo); + DGL_Vertex2f(ox + righth, rect->origin.y + toph); + DGL_TexCoord2f(0, xoff + txo + righth / ftw, yoff + tyo + sideh / fth); + DGL_Vertex2f(ox + righth, rect->origin.y + toph + sideh); + DGL_TexCoord2f(0, xoff + txo, yoff + tyo + sideh / fth); + DGL_Vertex2f(ox, rect->origin.y + toph + sideh); } if(bottomh > 0) @@ -242,16 +237,16 @@ float oy = rect->origin.y + toph + sideh; float yoff = (toph + sideh) / fth; - LIBGUI_GL.glTexCoord2f(txo, yoff + tyo); - LIBGUI_GL.glVertex2f(rect->origin.x, oy); - LIBGUI_GL.glTexCoord2f(txo + rect->size.width / ftw, yoff + tyo); - LIBGUI_GL.glVertex2f(rect->origin.x + rect->size.width, oy); - LIBGUI_GL.glTexCoord2f(txo + rect->size.width / ftw, yoff + tyo + bottomh / fth); - LIBGUI_GL.glVertex2f(rect->origin.x + rect->size.width, oy + bottomh); - LIBGUI_GL.glTexCoord2f(txo, yoff + tyo + bottomh / fth); - LIBGUI_GL.glVertex2f(rect->origin.x, oy + bottomh); + DGL_TexCoord2f(0, txo, yoff + tyo); + DGL_Vertex2f(rect->origin.x, oy); + DGL_TexCoord2f(0, txo + rect->size.width / ftw, yoff + tyo); + DGL_Vertex2f(rect->origin.x + rect->size.width, oy); + DGL_TexCoord2f(0, txo + rect->size.width / ftw, yoff + tyo + bottomh / fth); + DGL_Vertex2f(rect->origin.x + rect->size.width, oy + bottomh); + DGL_TexCoord2f(0, txo, yoff + tyo + bottomh / fth); + DGL_Vertex2f(rect->origin.x, oy + bottomh); } - LIBGUI_GL.glEnd(); + DGL_End(); } void GL_DrawCutRectf2Tiled(double x, double y, double w, double h, int tw, int th, @@ -278,14 +273,13 @@ void GL_DrawLine(float x1, float y1, float x2, float y2, float r, float g, float b, float a) { - DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glColor4f(r, g, b, a); - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex2f(x1, y1); - LIBGUI_GL.glVertex2f(x2, y2); - LIBGUI_GL.glEnd(); + DGL_Color4f(r, g, b, a); + DGL_Begin(DGL_LINES); + DGL_Vertex2f(x1, y1); + DGL_Vertex2f(x2, y2); + DGL_End(); } #undef GL_ResetViewEffects @@ -293,7 +287,7 @@ { GL_SetFilter(false); Con_Executef(CMDS_DDAY, true, "postfx %i none", consolePlayer); - DD_SetInteger(DD_FULLBRIGHT, false); + DD_SetInteger(DD_RENDER_FULLBRIGHT, false); } #undef GL_ConfigureBorderedProjection2 @@ -331,11 +325,11 @@ DENG_EXTERN_C void GL_BeginBorderedProjection(dgl_borderedprojectionstate_t* bp) { DENG_ASSERT(bp != 0); - if(!bp) return; + if (!bp) return; - if(SCALEMODE_STRETCH == bp->scaleMode) return; + if (bp->scaleMode == SCALEMODE_STRETCH) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); /** @@ -344,41 +338,41 @@ * an aspect-corrected space of availWidth x availHeight and centered * on the larger of the horizontal and vertical axes. */ - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); DGL_Ortho(0, 0, bp->availWidth, bp->availHeight, -1, 1); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - GLState::push(); + DGL_PushState(); - if(bp->isPillarBoxed) + if (bp->isPillarBoxed) { // "Pillarbox": int offset = int((bp->availWidth - bp->scaleFactor * bp->width) / 2 + .5f); - if(bp->flags & BPF_OVERDRAW_CLIP) + if (bp->flags & BPF_OVERDRAW_CLIP) { DGL_SetScissor2(offset, 0, int(bp->scaleFactor * bp->width), bp->availHeight); } - LIBGUI_GL.glTranslatef(offset, 0, 0); - LIBGUI_GL.glScalef(bp->scaleFactor, bp->scaleFactor * 1.2f, 1); + DGL_Translatef(offset, 0, 0); + DGL_Scalef(bp->scaleFactor, bp->scaleFactor * 1.2f, 1); } else { // "Letterbox": int offset = int((bp->availHeight - bp->scaleFactor * 1.2f * bp->height) / 2 + .5f); - if(bp->flags & BPF_OVERDRAW_CLIP) + if (bp->flags & BPF_OVERDRAW_CLIP) { DGL_SetScissor2(0, offset, bp->availWidth, int(bp->scaleFactor * 1.2f * bp->height)); } - LIBGUI_GL.glTranslatef(0, offset, 0); - LIBGUI_GL.glScalef(bp->scaleFactor, bp->scaleFactor * 1.2f, 1); + DGL_Translatef(0, offset, 0); + DGL_Scalef(bp->scaleFactor, bp->scaleFactor * 1.2f, 1); } } @@ -388,26 +382,26 @@ DENG_ASSERT(bp != 0); if(!bp) return; - if(SCALEMODE_STRETCH == bp->scaleMode) return; + if (SCALEMODE_STRETCH == bp->scaleMode) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - GLState::pop().apply(); + DGL_PopState(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); - if(bp->flags & BPF_OVERDRAW_MASK) + if (bp->flags & BPF_OVERDRAW_MASK) { // It shouldn't be necessary to bind the "not-texture" but the game // may have left whatever GL texture state it was using on. As this // isn't cleaned up until drawing control returns to the engine we // must explicitly disable it here. GL_SetNoTexture(); - LIBGUI_GL.glColor4f(0, 0, 0, 1); + DGL_Color4f(0, 0, 0, 1); - if(bp->isPillarBoxed) + if (bp->isPillarBoxed) { // "Pillarbox": int w = int((bp->availWidth - bp->scaleFactor * bp->width) / 2 + .5f); @@ -423,6 +417,6 @@ } } - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_drawvectorgraphic.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_drawvectorgraphic.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_drawvectorgraphic.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_drawvectorgraphic.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -139,7 +139,7 @@ { uint i; if(!svgInited) return; - if(DD_GetInteger(DD_NOVIDEO) || DD_GetInteger(DD_DEDICATED)) return; // Nothing to do. + if(DD_GetInteger(DD_NOVIDEO)) return; // Nothing to do. for(i = 0; i < svgCount; ++i) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -28,6 +28,7 @@ #include "de_base.h" #include "gl/gl_main.h" +#include "api_gl.h" #include #include @@ -76,8 +77,6 @@ extern dint maxnumnodes; extern dd_bool fillOutlines; -dint numTexUnits = 1; -dd_bool envModAdd; ///< TexEnv: modulate and add is available. dint test3dfx; dint r_detail = true; ///< Draw detail textures (if available). @@ -198,24 +197,23 @@ void GL_FinishFrame() { - if(ClientApp::vr().mode() == VRConfig::OculusRift) return; + if (ClientApp::vr().mode() == VRConfig::OculusRift) return; + + DENG2_ASSERT_IN_RENDER_THREAD(); + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); // Check for color adjustment changes. - if(oldgamma != vid_gamma || oldcontrast != vid_contrast || oldbright != vid_bright) + if (oldgamma != vid_gamma || oldcontrast != vid_contrast || oldbright != vid_bright) { GL_SetGamma(); } - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - +#if !defined (DENG_MOBILE) // Wait until the right time to show the frame so that the realized // frame rate is exactly right. LIBGUI_GL.glFlush(); DD_WaitForOptimalUpdateTime(); - - // Blit screen to video. - //ClientWindow::main().swapBuffers(); +#endif } static void printConfiguration() @@ -227,7 +225,7 @@ { LOG_GL_VERBOSE(" Multisampling format: %i") << GL_state.multisampleFormat; }*/ - LOG_GL_VERBOSE(" Multitexturing: %s") << (numTexUnits > 1? (envModAdd? "full" : "partial") : "not available"); + //LOG_GL_VERBOSE(" Multitexturing: %s") << (numTexUnits > 1? (envModAdd? "full" : "partial") : "not available"); LOG_GL_VERBOSE(" Texture Anisotropy: %s") << (GL_state.features.texFilterAniso? "variable" : "fixed"); LOG_GL_VERBOSE(" Texture Compression: %b") << GL_state.features.texCompression; } @@ -243,11 +241,6 @@ gamma_support = !CommandLine_Check("-noramp"); - // We are simple people; two texture units is enough. - numTexUnits = de::min(GLInfo::limits().maxTexUnits, MAX_TEX_UNITS); - envModAdd = (GLInfo::extensions().NV_texture_env_combine4 || - GLInfo::extensions().ATI_texture_env_combine3); - GL_InitDeferredTask(); // Model renderer must be initialized early as it may need to configure @@ -337,8 +330,8 @@ Rend_ModelShutdown(); LensFx_Shutdown(); Rend_Reset(); - GL_ShutdownRefresh(); + DGL_Shutdown(); // Shutdown OpenGL. Sys_GLShutdown(); @@ -353,36 +346,36 @@ glFarClip = 16500; DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + + //DGL_SetInteger(DGL_FLUSH_BACKTRACE, true); // Here we configure the OpenGL state and set the projection matrix. - GLState::current() - .setCull(gl::None) - .setDepthTest(false) - .apply(); - - //glDisable(GL_TEXTURE_1D); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - LIBGUI_GL.glDisable(GL_TEXTURE_CUBE_MAP); + DGL_CullFace(DGL_NONE); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); // The projection matrix. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, 320, 200, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, 320, 200, -1, 1); // Default state for the white fog is off. - fogParams.usingFog = false; - LIBGUI_GL.glDisable(GL_FOG); - LIBGUI_GL.glFogi(GL_FOG_MODE, (fogModeDefault == 0 ? GL_LINEAR : - fogModeDefault == 1 ? GL_EXP : GL_EXP2)); - LIBGUI_GL.glFogf(GL_FOG_START, DEFAULT_FOG_START); - LIBGUI_GL.glFogf(GL_FOG_END, DEFAULT_FOG_END); - LIBGUI_GL.glFogf(GL_FOG_DENSITY, DEFAULT_FOG_DENSITY); - fogParams.fogColor[0] = DEFAULT_FOG_COLOR_RED; - fogParams.fogColor[1] = DEFAULT_FOG_COLOR_GREEN; - fogParams.fogColor[2] = DEFAULT_FOG_COLOR_BLUE; - fogParams.fogColor[3] = 1; - LIBGUI_GL.glFogfv(GL_FOG_COLOR, fogParams.fogColor); + { + fogParams.usingFog = false; + fogParams.fogColor[0] = DEFAULT_FOG_COLOR_RED; + fogParams.fogColor[1] = DEFAULT_FOG_COLOR_GREEN; + fogParams.fogColor[2] = DEFAULT_FOG_COLOR_BLUE; + fogParams.fogColor[3] = 1.f; + } + DGL_Disable(DGL_FOG); + DGL_Fogi(DGL_FOG_MODE, (fogModeDefault == 0 ? DGL_LINEAR : + fogModeDefault == 1 ? DGL_EXP : DGL_EXP2)); + DGL_Fogf(DGL_FOG_START, DEFAULT_FOG_START); + DGL_Fogf(DGL_FOG_END, DEFAULT_FOG_END); + DGL_Fogf(DGL_FOG_DENSITY, DEFAULT_FOG_DENSITY); + DGL_Fogfv(DGL_FOG_COLOR, fogParams.fogColor); + + LIBGUI_ASSERT_GL_OK(); } Rangef GL_DepthClipRange() @@ -390,25 +383,15 @@ return Rangef(glNearClip, glFarClip); } -Matrix4f GL_GetProjectionMatrix() -{ - dfloat const fov = Rend_FieldOfView(); - //Vector2f const size(viewpw, viewph); - Vector2f const size = R_Console3DViewRect(displayPlayer).size(); - yfov = vrCfg().verticalFieldOfView(fov, size); - return vrCfg().projectionMatrix(Rend_FieldOfView(), size, glNearClip, glFarClip) * - Matrix4f::scale(Vector3f(1, 1, -1)); -} - void GL_ProjectionMatrix() { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Actually shift the player viewpoint // We'd like to have a left-handed coordinate system. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glLoadMatrixf(GL_GetProjectionMatrix().values()); + DGL_MatrixMode(DGL_PROJECTION); + DGL_LoadMatrix(Rend_GetProjectionMatrix().values()); } void GL_SetupFogFromMapInfo(Record const *mapInfo) @@ -455,22 +438,20 @@ void GL_SelectTexUnits(dint count) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - for(dint i = numTexUnits - 1; i >= count; i--) + for (dint i = MAX_TEX_UNITS - 1; i >= count; i--) { - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + i); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE0 + i); } // Enable the selected units. - for(dint i = count - 1; i >= 0; i--) + for (dint i = count - 1; i >= 0; i--) { - if(i >= numTexUnits) continue; + if (i >= MAX_TEX_UNITS) continue; - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + i); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE0 + i); } } @@ -517,69 +498,59 @@ void GL_BlendMode(blendmode_t mode) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); switch(mode) { case BM_ZEROALPHA: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::One, gl::Zero) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_ONE, DGL_ZERO); break; case BM_ADD: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::SrcAlpha, gl::One) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE); break; case BM_DARK: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::DestColor, gl::OneMinusSrcAlpha) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_DST_COLOR, DGL_ONE_MINUS_SRC_ALPHA); break; case BM_SUBTRACT: - GLState::current().setBlendOp(gl::Subtract) - .setBlendFunc(gl::One, gl::SrcAlpha) - .apply(); + DGL_BlendOp(DGL_SUBTRACT); + DGL_BlendFunc(DGL_ONE, DGL_SRC_ALPHA); break; case BM_ALPHA_SUBTRACT: - GLState::current().setBlendOp(gl::Subtract) - .setBlendFunc(gl::SrcAlpha, gl::One) - .apply(); + DGL_BlendOp(DGL_SUBTRACT); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE); break; case BM_REVERSE_SUBTRACT: - GLState::current().setBlendOp(gl::ReverseSubtract) - .setBlendFunc(gl::SrcAlpha, gl::One) - .apply(); + DGL_BlendOp(DGL_REVERSE_SUBTRACT); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE); break; case BM_MUL: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::Zero, gl::SrcColor) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_ZERO, DGL_SRC_COLOR); break; case BM_INVERSE: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::OneMinusDestColor, gl::OneMinusSrcColor) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_ONE_MINUS_DST_COLOR, DGL_ONE_MINUS_SRC_COLOR); break; case BM_INVERSE_MUL: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::Zero, gl::OneMinusSrcColor) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_ZERO, DGL_ONE_MINUS_SRC_COLOR); break; default: - GLState::current().setBlendOp(gl::Add) - .setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha) - .apply(); + DGL_BlendOp(DGL_ADD); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); break; } } @@ -783,7 +754,7 @@ static inline MaterialVariantSpec const &pspriteMaterialSpec(dint tClass, dint tMap) { return resSys().materialSpec(PSpriteContext, 0, 1, tClass, tMap, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, - 0, 1, 0, false, true, true, false); + 0, -2, 0, false, true, true, false); } void GL_SetMaterialUI2(world::Material *material, gl::Wrapping wrapS, gl::Wrapping wrapT) @@ -826,7 +797,9 @@ void GL_BindTexture(TextureVariant *vtexture) { - if(ClientApp::busyRunner().inWorkerThread()) return; +#if defined (DENG_HAVE_BUSYRUNNER) + if (ClientApp::busyRunner().inWorkerThread()) return; +#endif // Ensure we have a prepared texture. duint glTexName = vtexture? vtexture->prepare() : 0; @@ -836,11 +809,11 @@ return; } - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); LIBGUI_GL.glBindTexture(GL_TEXTURE_2D, glTexName); - Sys_GLCheckError(); + LIBGUI_ASSERT_GL_OK(); // Apply dynamic adjustments to the GL texture state according to our spec. TextureVariantSpec const &spec = vtexture->spec(); @@ -855,13 +828,18 @@ LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(spec.variant.logicalAnisoLevel())); } + LIBGUI_ASSERT_GL_OK(); } } void GL_BindTextureUnmanaged(GLuint glName, gl::Wrapping wrapS, gl::Wrapping wrapT, gl::Filter filter) { - if(ClientApp::busyRunner().inWorkerThread()) return; +#if defined (DENG_HAVE_BUSYRUNNER) + if (ClientApp::busyRunner().inWorkerThread()) return; +#endif + + LIBGUI_ASSERT_GL_OK(); if(glName == 0) { @@ -869,11 +847,11 @@ return; } - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); LIBGUI_GL.glBindTexture(GL_TEXTURE_2D, glName); - Sys_GLCheckError(); + LIBGUI_ASSERT_GL_OK(); LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_Wrap(wrapS)); LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_Wrap(wrapT)); @@ -882,6 +860,7 @@ { LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(texAniso)); } + LIBGUI_ASSERT_GL_OK(); } void GL_Bind(GLTextureUnit const &glTU) @@ -909,17 +888,19 @@ { if(!glTU.hasTexture()) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + dbyte(unit)); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, unit); GL_Bind(glTU); } void GL_SetNoTexture() { +#if defined (DENG_HAVE_BUSYRUNNER) if(ClientApp::busyRunner().inWorkerThread()) return; +#endif - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); /// @todo Don't actually change the current binding. Instead we should disable @@ -975,7 +956,7 @@ } duint8 *GL_ConvertBuffer(duint8 const *in, dint width, dint height, dint informat, - colorpaletteid_t paletteId, dint outformat) + colorpaletteid_t paletteId, dint outformat) { DENG2_ASSERT(in); @@ -1225,6 +1206,8 @@ */ } +#if !defined (DENG_MOBILE) + D_CMD(SetRes) { DENG2_UNUSED3(src, argc, argv); @@ -1345,6 +1328,8 @@ return win->changeAttributes(attribs); } +#endif // !DENG_MOBILE + D_CMD(DisplayModeInfo) { DENG2_UNUSED3(src, argc, argv); @@ -1371,10 +1356,13 @@ .arg(win->windowRect().topLeft.asText()) .arg(win->windowRect().size().asText()) .arg(win->fullscreenSize().asText()); + +#if !defined (DENG_MOBILE) str += String("\n fullscreen:%1 centered:%2 maximized:%3") .arg(DENG2_BOOL_YESNO( win->isFullScreen() )) .arg(DENG2_BOOL_YESNO( win->isCentered() )) .arg(DENG2_BOOL_YESNO( win->isMaximized() )); +#endif LOG_GL_MSG("%s") << str; return true; @@ -1447,7 +1435,7 @@ } fogParams.fogColor[3] = 1; - Deferred_glFogfv(GL_FOG_COLOR, fogParams.fogColor); + DGL_Fogfv(DGL_FOG_COLOR, fogParams.fogColor); LOG_GL_VERBOSE("Fog color set"); return true; } @@ -1455,20 +1443,20 @@ { fogParams.fogStart = (GLfloat) strtod(argv[2], nullptr); - Deferred_glFogf(GL_FOG_START, fogParams.fogStart); + DGL_Fogf(DGL_FOG_START, fogParams.fogStart); LOG_GL_VERBOSE("Fog start distance set"); return true; } if(!stricmp(argv[1], "end") && argc == 3) { fogParams.fogEnd = (GLfloat) strtod(argv[2], nullptr); - Deferred_glFogf(GL_FOG_END, fogParams.fogEnd); + DGL_Fogf(DGL_FOG_END, fogParams.fogEnd); LOG_GL_VERBOSE("Fog end distance set"); return true; } if(!stricmp(argv[1], "density") && argc == 3) { - Deferred_glFogf(GL_FOG_DENSITY, (GLfloat) strtod(argv[2], nullptr)); + DGL_Fogf(DGL_FOG_DENSITY, (GLfloat) strtod(argv[2], nullptr)); LOG_GL_VERBOSE("Fog density set"); return true; } @@ -1476,19 +1464,19 @@ { if(!stricmp(argv[2], "linear")) { - Deferred_glFogi(GL_FOG_MODE, GL_LINEAR); + DGL_Fogi(DGL_FOG_MODE, DGL_LINEAR); LOG_GL_VERBOSE("Fog mode set to linear"); return true; } if(!stricmp(argv[2], "exp")) { - Deferred_glFogi(GL_FOG_MODE, GL_EXP); + DGL_Fogi(DGL_FOG_MODE, DGL_EXP); LOG_GL_VERBOSE("Fog mode set to exp"); return true; } if(!stricmp(argv[2], "exp2")) { - Deferred_glFogi(GL_FOG_MODE, GL_EXP2); + DGL_Fogi(DGL_FOG_MODE, DGL_EXP2); LOG_GL_VERBOSE("Fog mode set to exp2"); return true; } @@ -1500,7 +1488,9 @@ void GL_Register() { // Cvars +#if defined (DENG_OPENGL) C_VAR_INT ("rend-dev-wireframe", &renderWireframe, CVF_NO_ARCHIVE, 0, 2); +#endif C_VAR_INT ("rend-fog-default", &fogModeDefault, 0, 0, 2); // * Render-HUD @@ -1525,6 +1515,7 @@ C_CMD_FLAGS("fog", nullptr, Fog, CMDF_NO_NULLGAME|CMDF_NO_DEDICATED); C_CMD ("displaymode", "", DisplayModeInfo); C_CMD ("listdisplaymodes", "", ListDisplayModes); +#if !defined (DENG_MOBILE) C_CMD ("setcolordepth", "i", SetBPP); C_CMD ("setbpp", "i", SetBPP); C_CMD ("setres", "ii", SetRes); @@ -1535,4 +1526,5 @@ C_CMD ("togglemaximized", "", ToggleMaximized); C_CMD ("togglecentered", "", ToggleCentered); C_CMD ("centerwindow", "", CenterWindow); +#endif } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_tex.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_tex.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/gl_tex.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/gl_tex.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -355,8 +355,6 @@ case GL_FLOAT: sizeIn = sizeof(GLfloat); break; - case GL_BITMAP: - // Not implemented yet. default: return NULL; } @@ -385,8 +383,6 @@ case GL_FLOAT: sizeOut = sizeof(GLfloat); break; - case GL_BITMAP: - // Not implemented yet. default: return NULL; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/svg.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/svg.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/svg.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/svg.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -49,7 +49,7 @@ svgid_t id; /// GL display list containing all commands for drawing all primitives (no state changes). - DGLuint dlist; + //DGLuint dlist; /// Set of lines for this graphic. uint lineCount; @@ -85,119 +85,119 @@ static void draw(const Svg* svg) { - GLenum nextPrimType, primType = GL_LINE_STRIP; - const SvgLine* lIt; - uint i; + dglprimtype_t nextPrimType, primType = DGL_LINE_STRIP; DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - lIt = svg->lines; - for(i = 0; i < svg->lineCount; ++i, lIt++) + SvgLine const *lIt = svg->lines; + for (uint i = 0; i < svg->lineCount; ++i, lIt++) { - if(lIt->numPoints != 2) + if (lIt->numPoints != 2) { - nextPrimType = SvgLine_IsLoop(lIt)? GL_LINE_LOOP : GL_LINE_STRIP; + nextPrimType = SvgLine_IsLoop(lIt)? DGL_LINE_LOOP : DGL_LINE_STRIP; // Do we need to end the current primitive? - if(primType == GL_LINES) + if (primType == DGL_LINES) { - LIBGUI_GL.glEnd(); // 2-vertex set ends. + DGL_End(); // 2-vertex set ends. } // A new n-vertex primitive begins. - LIBGUI_GL.glBegin(nextPrimType); + DGL_Begin(nextPrimType); } else { // Do we need to start a new 2-vertex primitive set? - if(primType != GL_LINES) + if (primType != DGL_LINES) { - primType = GL_LINES; - LIBGUI_GL.glBegin(GL_LINES); + primType = DGL_LINES; + DGL_Begin(DGL_LINES); } } // Write the vertex data. - if(lIt->head) + if (lIt->head) { const SvgLinePoint* pIt = lIt->head; do { /// @todo Use TexGen? - LIBGUI_GL.glTexCoord2dv((const GLdouble*)pIt->coords.xy); - LIBGUI_GL.glVertex2dv((const GLdouble*)pIt->coords.xy); - } while(NULL != (pIt = pIt->next) && pIt != lIt->head); + DGL_TexCoord2f(0, pIt->coords.x, pIt->coords.y);; + DGL_Vertex2f(pIt->coords.x, pIt->coords.y); + } + while (NULL != (pIt = pIt->next) && pIt != lIt->head); } - if(lIt->numPoints != 2) + if (lIt->numPoints != 2) { - LIBGUI_GL.glEnd(); // N-vertex primitive ends. + DGL_End(); // N-vertex primitive ends. } } - if(primType == GL_LINES) + if (primType == DGL_LINES) { // Close any remaining open 2-vertex set. - LIBGUI_GL.glEnd(); + DGL_End(); } } -static DGLuint constructDisplayList(DGLuint name, const Svg* svg) +/*static DGLuint constructDisplayList(DGLuint name, const Svg* svg) { - if(GL_NewList(name, DGL_COMPILE)) + if (GL_NewList(name, DGL_COMPILE)) { draw(svg); return GL_EndList(); } return 0; -} +}*/ void Svg_Draw(Svg* svg) { assert(svg); - if(novideo || isDedicated) + if (novideo) { assert(0); // Should not have been called! return; } // Have we uploaded our draw-optimized representation yet? - if(svg->dlist) + /*if (svg->dlist) { // Draw! GL_CallList(svg->dlist); return; - } + }*/ // Draw manually in so-called 'immediate' mode. draw(svg); } -dd_bool Svg_Prepare(Svg* svg) -{ +dd_bool Svg_Prepare(Svg *) +{/* assert(svg); - if(!novideo && !isDedicated) + if (!novideo && !isDedicated) { - if(!svg->dlist) + if (!svg->dlist) { svg->dlist = constructDisplayList(0, svg); } } - return !!svg->dlist; + return !!svg->dlist;*/ + return true; } void Svg_Unload(Svg* svg) { assert(svg); - if(novideo || isDedicated) return; + if (novideo) return; - if(svg->dlist) + /*if (svg->dlist) { GL_DeleteLists(svg->dlist, 1); svg->dlist = 0; - } + }*/ } Svg* Svg_FromDef(svgid_t uniqueId, const def_svgline_t* lines, uint lineCount) @@ -211,31 +211,31 @@ uint i, j; Svg* svg; - if(!lines || lineCount == 0) return NULL; + if (!lines || lineCount == 0) return NULL; svg = (Svg*)malloc(sizeof(*svg)); - if(!svg) Libdeng_BadAlloc(); + if (!svg) Libdeng_BadAlloc(); svg->id = uniqueId; - svg->dlist = 0; + //svg->dlist = 0; // Count how many lines and points we actually need. finalLineCount = 0; finalPointCount = 0; slIt = lines; - for(i = 0; i < lineCount; ++i, slIt++) + for (i = 0; i < lineCount; ++i, slIt++) { // Skip lines with missing vertices... - if(slIt->numPoints < 2) continue; + if (slIt->numPoints < 2) continue; ++finalLineCount; finalPointCount += slIt->numPoints; - if(slIt->numPoints > 2) + if (slIt->numPoints > 2) { // If the end point is equal to the start point, we'll ommit it and // set this line up as a loop. - if(FEQUAL(slIt->points[slIt->numPoints-1].x, slIt->points[0].x) && + if (FEQUAL(slIt->points[slIt->numPoints-1].x, slIt->points[0].x) && FEQUAL(slIt->points[slIt->numPoints-1].y, slIt->points[0].y)) { finalPointCount -= 1; @@ -251,30 +251,30 @@ // Allocate the final point set. svg->numPoints = finalPointCount; svg->points = (SvgLinePoint*)malloc(sizeof(*svg->points) * svg->numPoints); - if(!svg->points) Libdeng_BadAlloc(); + if (!svg->points) Libdeng_BadAlloc(); // Allocate the final line set. svg->lineCount = finalLineCount; svg->lines = (SvgLine*)malloc(sizeof(*svg->lines) * finalLineCount); - if(!svg->lines) Libdeng_BadAlloc(); + if (!svg->lines) Libdeng_BadAlloc(); // Setup the lines. slIt = lines; dlIt = svg->lines; dpIt = svg->points; - for(i = 0; i < lineCount; ++i, slIt++) + for (i = 0; i < lineCount; ++i, slIt++) { // Skip lines with missing vertices... - if(slIt->numPoints < 2) continue; + if (slIt->numPoints < 2) continue; // Determine how many points we'll need. dlIt->numPoints = slIt->numPoints; lineIsLoop = false; - if(slIt->numPoints > 2) + if (slIt->numPoints > 2) { // If the end point is equal to the start point, we'll ommit it and // set this line up as a loop. - if(FEQUAL(slIt->points[slIt->numPoints-1].x, slIt->points[0].x) && + if (FEQUAL(slIt->points[slIt->numPoints-1].x, slIt->points[0].x) && FEQUAL(slIt->points[slIt->numPoints-1].y, slIt->points[0].y)) { dlIt->numPoints -= 1; @@ -286,7 +286,7 @@ spIt = slIt->points; dlIt->head = dpIt; prev = NULL; - for(j = 0; j < dlIt->numPoints; ++j, spIt++) + for (j = 0; j < dlIt->numPoints; ++j, spIt++) { SvgLinePoint* next = (j < dlIt->numPoints-1)? dpIt + 1 : NULL; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/sys_opengl.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/sys_opengl.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/sys_opengl.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/sys_opengl.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -32,7 +32,7 @@ #ifdef WIN32 # define GETPROC(Type, x) x = de::function_cast(wglGetProcAddress(#x)) -#elif defined(UNIX) && !defined(MACOSX) +#elif defined (DENG_X11) # include # undef None # define GETPROC(Type, x) x = de::function_cast(glXGetProcAddress((GLubyte const *)#x)) @@ -40,21 +40,6 @@ gl_state_t GL_state; -/* -#ifdef WIN32 -//PFNWGLSWAPINTERVALEXTPROC wglSwapIntervalEXT = NULL; -PFNWGLCHOOSEPIXELFORMATARBPROC wglChoosePixelFormatARB = NULL; -#endif -*/ - -/* -#ifdef LIBGUI_USE_GLENTRYPOINTS -PFNGLBLENDEQUATIONEXTPROC glBlendEquationEXT = NULL; -PFNGLLOCKARRAYSEXTPROC glLockArraysEXT = NULL; -PFNGLUNLOCKARRAYSEXTPROC glUnlockArraysEXT = NULL; -#endif -*/ - static dd_bool doneEarlyInit = false; static dd_bool sysOpenGLInited = false; static dd_bool firstTimeInit = true; @@ -68,41 +53,23 @@ GL_state.features.texFilterAniso = false; } - if(ext.EXT_blend_subtract) - { -#ifdef LIBGUI_USE_GLENTRYPOINTS - GETPROC(PFNGLBLENDEQUATIONEXTPROC, glBlendEquationEXT); - if(!glBlendEquationEXT) - GL_state.features.blendSubtract = false; -#endif - } - else - { - GL_state.features.blendSubtract = false; - } - if (CommandLine_Exists("-texcomp") && !CommandLine_Exists("-notexcomp")) { GL_state.features.texCompression = true; } #ifdef USE_TEXTURE_COMPRESSION_S3 // Enabled by default if available. - if(ext.EXT_texture_compression_s3tc) + if (ext.EXT_texture_compression_s3tc) { GLint iVal; LIBGUI_GL.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &iVal); - if(iVal == 0 || LIBGUI_GL.glGetError() != GL_NO_ERROR) + LIBGUI_ASSERT_GL_OK(); + if (iVal == 0)// || LIBGUI_GL.glGetError() != GL_NO_ERROR) GL_state.features.texCompression = false; } #else GL_state.features.texCompression = false; #endif - - // Automatic mipmap generation. - if(!ext.SGIS_generate_mipmap || CommandLine_Exists("-nosgm")) - { - GL_state.features.genMipmap = false; - } } #define TABBED(A, B) _E(Ta) " " _E(l) A _E(.) " " _E(Tb) << B << "\n" @@ -121,6 +88,8 @@ os << TABBED("Renderer:", (char const *) LIBGUI_GL.glGetString(GL_RENDERER)); os << TABBED("Vendor:", (char const *) LIBGUI_GL.glGetString(GL_VENDOR)); + LIBGUI_ASSERT_GL_OK(); + os << _E(T`) "Capabilities:\n"; GLint iVal; @@ -129,34 +98,31 @@ if(de::GLInfo::extensions().EXT_texture_compression_s3tc) { LIBGUI_GL.glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &iVal); + LIBGUI_ASSERT_GL_OK(); os << TABBED("Compressed texture formats:", iVal); } #endif os << TABBED("Use texture compression:", (GL_state.features.texCompression? "yes" : "no")); - LIBGUI_GL.glGetIntegerv(GL_MAX_TEXTURE_UNITS, &iVal); - os << TABBED("Available texture units:", iVal); + os << TABBED("Available texture units:", de::GLInfo::limits().maxTexUnits); if(de::GLInfo::extensions().EXT_texture_filter_anisotropic) { - LIBGUI_GL.glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &iVal); - os << TABBED("Maximum texture anisotropy:", iVal); + os << TABBED("Maximum texture anisotropy:", de::GLInfo::limits().maxTexFilterAniso); } else { os << _E(Ta) " Variable texture anisotropy unavailable."; } - LIBGUI_GL.glGetIntegerv(GL_MAX_TEXTURE_SIZE, &iVal); - os << TABBED("Maximum texture size:", iVal); + os << TABBED("Maximum texture size:", de::GLInfo::limits().maxTexSize); - GLfloat fVals[2]; - LIBGUI_GL.glGetFloatv(GL_LINE_WIDTH_GRANULARITY, fVals); - os << TABBED("Line width granularity:", fVals[0]); + os << TABBED("Line width granularity:", de::GLInfo::limits().smoothLineWidthGranularity); - LIBGUI_GL.glGetFloatv(GL_LINE_WIDTH_RANGE, fVals); - os << TABBED("Line width range:", fVals[0] << "..." << fVals[1]); + os << TABBED("Line width range:", + de::GLInfo::limits().smoothLineWidth.start << "..." << + de::GLInfo::limits().smoothLineWidth.end); return str.rightStrip(); @@ -175,18 +141,10 @@ if(novideo) return true; if(doneEarlyInit) return true; // Already been here?? - // Init assuming ideal configuration. - //GL_state.multisampleFormat = 0; // No valid default can be assumed at this time. - - GL_state.features.blendSubtract = true; - GL_state.features.genMipmap = true; - //GL_state.features.multisample = false; // We'll test for availability... GL_state.features.texCompression = false; GL_state.features.texFilterAniso = true; - GL_state.currentLineWidth = 1.5f; GL_state.currentPointSize = 1.5f; - GL_state.currentUseFog = false; doneEarlyInit = true; return true; @@ -207,6 +165,7 @@ if(firstTimeInit) { +#if defined (DENG_OPENGL) const GLubyte* versionStr = LIBGUI_GL.glGetString(GL_VERSION); double version = (versionStr? strtod((const char*) versionStr, NULL) : 0); if(version == 0) @@ -214,7 +173,7 @@ LOG_GL_WARNING("Failed to determine OpenGL version; driver reports: %s") << LIBGUI_GL.glGetString(GL_VERSION); } - else if(version < 2.0) + else if(version < 3.3) { if(!CommandLine_Exists("-noglcheck")) { @@ -226,10 +185,11 @@ } else { - LOG_GL_WARNING("OpenGL may be too old (2.0+ required, " + LOG_GL_WARNING("OpenGL may be too old (3.3+ required, " "but driver reports %s)") << LIBGUI_GL.glGetString(GL_VERSION); } } +#endif initialize(); printGLUInfo(); @@ -246,8 +206,8 @@ */ // Use nice quality for mipmaps please. - if(GL_state.features.genMipmap && de::GLInfo::extensions().SGIS_generate_mipmap) - LIBGUI_GL.glHint(GL_GENERATE_MIPMAP_HINT_SGIS, GL_NICEST); + //if(GL_state.features.genMipmap && de::GLInfo::extensions().SGIS_generate_mipmap) + //LIBGUI_GL.glHint(GL_GENERATE_MIPMAP_HINT, GL_NICEST); assert(!Sys_GLCheckError()); @@ -263,6 +223,8 @@ void Sys_GLConfigureDefaultState(void) { + LIBGUI_ASSERT_GL_OK(); + GLfloat fogcol[4] = { .54f, .54f, .54f, 1 }; /** @@ -279,52 +241,58 @@ DENG_ASSERT_GL_CONTEXT_ACTIVE(); LIBGUI_GL.glFrontFace(GL_CW); - de::GLState::current() - .setCull(de::gl::None) - .setDepthTest(false) - .setDepthFunc(de::gl::Less); + LIBGUI_ASSERT_GL_OK(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - LIBGUI_GL.glDisable(GL_TEXTURE_CUBE_MAP); + DGL_CullFace(DGL_NONE); + DGL_Disable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); + + DGL_Disable(DGL_TEXTURE_2D); + +#if defined (DENG_OPENGL) + LIBGUI_GL.glEnable(GL_TEXTURE_CUBE_MAP_SEAMLESS); + LIBGUI_ASSERT_GL_OK(); +#endif // The projection matrix. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_LoadIdentity(); // Initialize the modelview matrix. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_LoadIdentity(); // Also clear the texture matrix. - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_LoadIdentity(); + +// de::GLInfo::setLineWidth(GL_state.currentLineWidth); +#if defined (DENG_OPENGL) // Setup for antialiased lines/points. LIBGUI_GL.glEnable(GL_LINE_SMOOTH); + LIBGUI_ASSERT_GL_OK(); LIBGUI_GL.glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); - LIBGUI_GL.glLineWidth(GL_state.currentLineWidth); + LIBGUI_ASSERT_GL_OK(); - LIBGUI_GL.glEnable(GL_POINT_SMOOTH); - LIBGUI_GL.glHint(GL_POINT_SMOOTH_HINT, GL_NICEST); LIBGUI_GL.glPointSize(GL_state.currentPointSize); + LIBGUI_ASSERT_GL_OK(); - LIBGUI_GL.glShadeModel(GL_SMOOTH); + // Prefer good quality in texture compression. + LIBGUI_GL.glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); + LIBGUI_ASSERT_GL_OK(); +#endif // Default state for the white fog is off. - LIBGUI_GL.glDisable(GL_FOG); - LIBGUI_GL.glFogi(GL_FOG_MODE, GL_LINEAR); - LIBGUI_GL.glFogi(GL_FOG_END, 2100); // This should be tweaked a bit. - LIBGUI_GL.glFogfv(GL_FOG_COLOR, fogcol); - - LIBGUI_GL.glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); + DGL_Disable(DGL_FOG); + DGL_Fogi(DGL_FOG_MODE, GL_LINEAR); + DGL_Fogi(DGL_FOG_END, 2100); // This should be tweaked a bit. + DGL_Fogfv(DGL_FOG_COLOR, fogcol); - // Prefer good quality in texture compression. - LIBGUI_GL.glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); + LIBGUI_ASSERT_GL_OK(); // Configure the default GLState (bottom of the stack). - de::GLState::current() - .setBlendFunc(de::gl::SrcAlpha, de::gl::OneMinusSrcAlpha) - .apply(); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); } static de::String omitGLPrefix(de::String str) @@ -403,17 +371,11 @@ */ } -dd_bool Sys_GLCheckError() +dd_bool Sys_GLCheckErrorArgs(char const *file, int line) { + if (novideo) return false; #ifdef DENG_DEBUG - if(!novideo) - { - GLenum error = LIBGUI_GL.glGetError(); - if(error != GL_NO_ERROR) - { - LOGDEV_GL_ERROR("OpenGL error: 0x%x") << error; - } - } + de::GLInfo::checkError(file, line); #endif return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/texturecontent.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/texturecontent.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/gl/texturecontent.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/gl/texturecontent.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -40,7 +40,7 @@ static int BytesPerPixelFmt(dgltexformat_t format) { - switch(format) + switch (format) { case DGL_LUMINANCE: case DGL_COLOR_INDEX_8: return 1; @@ -57,13 +57,14 @@ } } +#if 0 /** * Given a pixel format return the number of bytes to store one pixel. * @pre Input data is of GL_UNSIGNED_BYTE type. */ static int BytesPerPixel(GLint format) { - switch(format) + switch (format) { case GL_COLOR_INDEX: case GL_STENCIL_INDEX: @@ -89,6 +90,7 @@ return 0; // Unreachable. } } +#endif void GL_InitTextureContent(texturecontent_t *content) { @@ -128,7 +130,7 @@ void GL_DestroyTextureContent(texturecontent_t *content) { DENG_ASSERT(content); - if(content->pixels) M_Free((uint8_t *)content->pixels); + if (content->pixels) M_Free((uint8_t *)content->pixels); M_Free(content); } @@ -150,9 +152,9 @@ bool const monochrome = (spec.flags & TSF_MONOCHROME) != 0; bool const scaleSharp = (spec.flags & TSF_UPSCALE_AND_SHARPEN) != 0; - if(spec.toAlpha) + if (spec.toAlpha) { - if(0 != image.paletteId) + if (0 != image.paletteId) { // Paletted. uint8_t *newPixels = GL_ConvertBuffer(image.pixels, image.size.x, image.size.y, @@ -167,28 +169,28 @@ Image_ConvertToLuminance(image, false /*discard alpha*/); long total = image.size.x * image.size.y; - for(long i = 0; i < total; ++i) + for (long i = 0; i < total; ++i) { image.pixels[total + i] = image.pixels[i]; image.pixels[i] = 255; } image.pixelSize = 2; } - else if(0 != image.paletteId) + else if (0 != image.paletteId) { - if(fillOutlines && (image.flags & IMGF_IS_MASKED)) + if (fillOutlines && (image.flags & IMGF_IS_MASKED)) { ColorOutlinesIdx(image.pixels, image.size.x, image.size.y); } - if(monochrome && !scaleSharp) + if (monochrome && !scaleSharp) { GL_DeSaturatePalettedImage(image.pixels, App_Resources().colorPalettes().colorPalette(image.paletteId), image.size.x, image.size.y); } - if(scaleSharp) + if (scaleSharp) { int scaleMethod = GL_ChooseSmartFilter(image.size.x, image.size.y, 0); bool origMasked = (image.flags & IMGF_IS_MASKED) != 0; @@ -197,7 +199,7 @@ uint8_t *newPixels = GL_ConvertBuffer(image.pixels, image.size.x, image.size.y, ((image.flags & IMGF_IS_MASKED)? 2 : 1), image.paletteId, 4); - if(newPixels != image.pixels) + if (newPixels != image.pixels) { M_Free(image.pixels); image.pixels = newPixels; @@ -206,7 +208,7 @@ image.flags &= ~IMGF_IS_MASKED; } - if(monochrome) + if (monochrome) { Desaturate(image.pixels, image.size.x, image.size.y, image.pixelSize); } @@ -215,7 +217,7 @@ newPixels = GL_SmartFilter(scaleMethod, image.pixels, image.size.x, image.size.y, 0, &newWidth, &newHeight); image.size = Vector2ui(newWidth, newHeight); - if(newPixels != image.pixels) + if (newPixels != image.pixels) { M_Free(image.pixels); image.pixels = newPixels; @@ -226,7 +228,7 @@ //BlackOutlines(image.pixels, image.size.x, image.size.y, image.pixelSize); // Back to paletted+alpha? - if(monochrome) + if (monochrome) { // No. We'll convert from RGB(+A) to Luminance(+A) and upload as is. // Replace the old buffer. @@ -239,13 +241,13 @@ (origMasked? 2 : 1), origPaletteId, 4); - if(newPixels != image.pixels) + if (newPixels != image.pixels) { M_Free(image.pixels); image.pixels = newPixels; image.pixelSize = (origMasked? 2 : 1); image.paletteId = origPaletteId; - if(origMasked) + if (origMasked) { image.flags |= IMGF_IS_MASKED; } @@ -253,9 +255,9 @@ } } } - else if(image.pixelSize > 2) + else if (image.pixelSize > 2) { - if(monochrome) + if (monochrome) { Image_ConvertToLuminance(image); AmplifyLuma(image.pixels, image.size.x, image.size.y, image.pixelSize == 2); @@ -265,11 +267,11 @@ /* * Choose the final GL texture format. */ - if(monochrome) + if (monochrome) { return image.pixelSize == 2? DGL_LUMINANCE_PLUS_A8 : DGL_LUMINANCE; } - if(image.paletteId) + if (image.paletteId) { return (image.flags & IMGF_IS_MASKED)? DGL_COLOR_INDEX_8_PLUS_A8 : DGL_COLOR_INDEX_8; } @@ -299,7 +301,7 @@ DENG_UNUSED(spec); // We want a luminance map. - if(image.pixelSize > 2) + if (image.pixelSize > 2) { Image_ConvertToLuminance(image, false /*discard alpha*/); } @@ -323,7 +325,7 @@ GL_InitTextureContent(&c); c.name = glTexName; - switch(spec.type) + switch (spec.type) { case TST_GENERAL: { variantspecification_t const &vspec = spec.variant; @@ -342,12 +344,12 @@ c.pixels = image.pixels; c.paletteId = image.paletteId; - if(noCompression || (image.size.x < 128 || image.size.y < 128)) + if (noCompression || (image.size.x < 128 || image.size.y < 128)) c.flags |= TXCF_NO_COMPRESSION; - if(vspec.gammaCorrection) c.flags |= TXCF_APPLY_GAMMACORRECTION; - if(vspec.noStretch) c.flags |= TXCF_UPLOAD_ARG_NOSTRETCH; - if(vspec.mipmapped) c.flags |= TXCF_MIPMAP; - if(noSmartFilter) c.flags |= TXCF_UPLOAD_ARG_NOSMARTFILTER; + if (vspec.gammaCorrection) c.flags |= TXCF_APPLY_GAMMACORRECTION; + if (vspec.noStretch) c.flags |= TXCF_UPLOAD_ARG_NOSTRETCH; + if (vspec.mipmapped) c.flags |= TXCF_MIPMAP; + if (noSmartFilter) c.flags |= TXCF_UPLOAD_ARG_NOSMARTFILTER; c.magFilter = vspec.glMagFilter(); c.minFilter = vspec.glMinFilter(); @@ -365,7 +367,7 @@ // Determine the gray mipmap factor. int grayMipmapFactor = dspec.contrast; - if(baMul != 1 || hiMul != 1 || loMul != 1) + if (baMul != 1 || hiMul != 1 || loMul != 1) { // Integrate the normalization factor with contrast. float const hiContrast = 1 - 1. / hiMul; @@ -385,7 +387,7 @@ c.flags = TXCF_GRAY_MIPMAP | TXCF_UPLOAD_ARG_NOSMARTFILTER; // Disable compression? - if(image.size.x < 128 || image.size.y < 128) + if (image.size.x < 128 || image.size.y < 128) c.flags |= TXCF_NO_COMPRESSION; c.grayMipmap = grayMipmapFactor; @@ -414,40 +416,61 @@ */ static GLint ChooseTextureFormat(dgltexformat_t format, dd_bool allowCompression) { - dd_bool compress = (allowCompression && GL_state.features.texCompression); +#if defined (DENG_OPENGL_ES) + + switch (format) + { + case DGL_RGB: + case DGL_COLOR_INDEX_8: + return GL_RGB8; + + case DGL_RGBA: + case DGL_COLOR_INDEX_8_PLUS_A8: + return GL_RGBA8; - switch(format) + default: + DENG2_ASSERT(!"ChooseTextureFormat: Invalid texture source format"); + return 0; + } + +#else + + dd_bool compress = (allowCompression && GL_state.features.texCompression); + + switch (format) { case DGL_RGB: case DGL_COLOR_INDEX_8: - if(!compress) + if (!compress) return GL_RGB8; #if USE_TEXTURE_COMPRESSION_S3 - if(GLInfo::extensions().EXT_texture_compression_s3tc) + if (GLInfo::extensions().EXT_texture_compression_s3tc) return GL_COMPRESSED_RGB_S3TC_DXT1_EXT; #endif return GL_COMPRESSED_RGB; case DGL_RGBA: case DGL_COLOR_INDEX_8_PLUS_A8: - if(!compress) + if (!compress) return GL_RGBA8; #if USE_TEXTURE_COMPRESSION_S3 - if(GLInfo::extensions().EXT_texture_compression_s3tc) + if (GLInfo::extensions().EXT_texture_compression_s3tc) return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT; #endif return GL_COMPRESSED_RGBA; - case DGL_LUMINANCE: + /*case DGL_LUMINANCE: return !compress ? GL_LUMINANCE : GL_COMPRESSED_LUMINANCE; case DGL_LUMINANCE_PLUS_A8: - return !compress ? GL_LUMINANCE_ALPHA : GL_COMPRESSED_LUMINANCE_ALPHA; + return !compress ? GL_LUMINANCE_ALPHA : GL_COMPRESSED_LUMINANCE_ALPHA;*/ default: - App_Error("ChooseTextureFormat: Invalid source format %i.", (int) format); + DENG2_ASSERT(!"ChooseTextureFormat: Invalid texture source format"); return 0; // Unreachable. } + +#endif } /** @@ -464,68 +487,101 @@ static dd_bool uploadTexture(int glFormat, int loadFormat, const uint8_t* pixels, int width, int height, int genMipmaps) { + GLenum const properties[8] = + { + GL_PACK_ROW_LENGTH, + GL_PACK_ALIGNMENT, + GL_PACK_SKIP_ROWS, + GL_PACK_SKIP_PIXELS, + GL_UNPACK_ROW_LENGTH, + GL_UNPACK_ALIGNMENT, + GL_UNPACK_SKIP_ROWS, + GL_UNPACK_SKIP_PIXELS, + }; + const int packRowLength = 0, packAlignment = 1, packSkipRows = 0, packSkipPixels = 0; const int unpackRowLength = 0, unpackAlignment = 1, unpackSkipRows = 0, unpackSkipPixels = 0; int mipLevel = 0; DENG_ASSERT(pixels); - if(!(GL_LUMINANCE_ALPHA == loadFormat || GL_LUMINANCE == loadFormat || + if (!(GL_LUMINANCE_ALPHA == loadFormat || GL_LUMINANCE == loadFormat || GL_RGB == loadFormat || GL_RGBA == loadFormat)) { throw Error("texturecontent_t::uploadTexture", "Unsupported load format " + String::number(loadFormat)); } // Can't operate on null texture. - if(width < 1 || height < 1) + if (width < 1 || height < 1) return false; // Check that the texture dimensions are valid. - if(width > GLInfo::limits().maxTexSize || height > GLInfo::limits().maxTexSize) + if (width > GLInfo::limits().maxTexSize || height > GLInfo::limits().maxTexSize) return false; // Negative indices signify a specific mipmap level is being uploaded. - if(genMipmaps < 0) + if (genMipmaps < 0) { mipLevel = -genMipmaps; genMipmaps = 0; } - DENG_ASSERT_IN_MAIN_THREAD(); + //DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - // Automatic mipmap generation? - if(GLInfo::extensions().SGIS_generate_mipmap && genMipmaps) - LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP_SGIS, GL_TRUE); + auto &GL = LIBGUI_GL; - LIBGUI_GL.glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); - LIBGUI_GL.glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)packRowLength); - LIBGUI_GL.glPixelStorei(GL_PACK_ALIGNMENT, (GLint)packAlignment); - LIBGUI_GL.glPixelStorei(GL_PACK_SKIP_ROWS, (GLint)packSkipRows); - LIBGUI_GL.glPixelStorei(GL_PACK_SKIP_PIXELS, (GLint)packSkipPixels); - LIBGUI_GL.glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)unpackRowLength); - LIBGUI_GL.glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint)unpackAlignment); - LIBGUI_GL.glPixelStorei(GL_UNPACK_SKIP_ROWS, (GLint)unpackSkipRows); - LIBGUI_GL.glPixelStorei(GL_UNPACK_SKIP_PIXELS, (GLint)unpackSkipPixels); + // Automatic mipmap generation? + /*if (genMipmaps) + { + GL.glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); + LIBGUI_ASSERT_GL_OK(); + }*/ + + //LIBGUI_GL.glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + GLint oldPixelStore[8]; + for (int i = 0; i < 8; ++i) + { + GL.glGetIntegerv(properties[i], &oldPixelStore[i]); + LIBGUI_ASSERT_GL_OK(); + } + + GL.glPixelStorei(GL_PACK_ROW_LENGTH, (GLint)packRowLength); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_PACK_ALIGNMENT, (GLint)packAlignment); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_PACK_SKIP_ROWS, (GLint)packSkipRows); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_PACK_SKIP_PIXELS, (GLint)packSkipPixels); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_UNPACK_ROW_LENGTH, (GLint)unpackRowLength); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_UNPACK_ALIGNMENT, (GLint)unpackAlignment); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_UNPACK_SKIP_ROWS, (GLint)unpackSkipRows); + LIBGUI_ASSERT_GL_OK(); + GL.glPixelStorei(GL_UNPACK_SKIP_PIXELS, (GLint)unpackSkipPixels); + LIBGUI_ASSERT_GL_OK(); - if(genMipmaps && !GLInfo::extensions().SGIS_generate_mipmap) +#if 0 + if (genMipmaps && !GLInfo::extensions().SGIS_generate_mipmap) { // Build all mipmap levels. int neww, newh, bpp, w, h; void* image, *newimage; bpp = BytesPerPixel(loadFormat); - if(bpp == 0) + if (bpp == 0) throw Error("texturecontent_t::uploadTexture", "Unknown GL format " + String::number(loadFormat)); GL_OptimalTextureSize(width, height, false, true, &w, &h); - if(w != width || h != height) + if (w != width || h != height) { // Must rescale image to get "top" mipmap texture image. image = GL_ScaleBufferEx(pixels, width, height, bpp, /*GL_UNSIGNED_BYTE,*/ unpackRowLength, unpackAlignment, unpackSkipRows, unpackSkipPixels, w, h, /*GL_UNSIGNED_BYTE,*/ packRowLength, packAlignment, packSkipRows, packSkipPixels); - if(!image) + if (!image) throw Error("texturecontent_t::uploadTexture", "Unknown error resizing mipmap level #0"); } else @@ -533,12 +589,12 @@ image = (void*) pixels; } - for(;;) + for (;;) { LIBGUI_GL.glTexImage2D(GL_TEXTURE_2D, mipLevel, (GLint)glFormat, w, h, 0, (GLint)loadFormat, GL_UNSIGNED_BYTE, image); - if(w == 1 && h == 1) + if (w == 1 && h == 1) break; ++mipLevel; @@ -548,10 +604,10 @@ unpackRowLength, unpackAlignment, unpackSkipRows, unpackSkipPixels, neww, newh, /*GL_UNSIGNED_BYTE,*/ packRowLength, packAlignment, packSkipRows, packSkipPixels); - if(!newimage) + if (!newimage) throw Error("texturecontent_t::uploadTexture", "Unknown error resizing mipmap level #" + String::number(mipLevel)); - if(image != pixels) + if (image != pixels) M_Free(image); image = newimage; @@ -559,16 +615,31 @@ h = newh; } - if(image != pixels) + if (image != pixels) M_Free(image); } else +#endif { - LIBGUI_GL.glTexImage2D(GL_TEXTURE_2D, mipLevel, (GLint)glFormat, (GLsizei)width, - (GLsizei)height, 0, (GLint)loadFormat, GL_UNSIGNED_BYTE, pixels); + LIBGUI_GL.glTexImage2D(GL_TEXTURE_2D, mipLevel, GLint(glFormat), + GLsizei(width), GLsizei(height), 0, + GLenum(loadFormat), GL_UNSIGNED_BYTE, pixels); + LIBGUI_ASSERT_GL_OK(); + + if (genMipmaps) + { + LIBGUI_GL.glGenerateMipmap(GL_TEXTURE_2D); + } + } + + //LIBGUI_GL.glPopClientAttrib(); + + for (int i = 0; i < 8; ++i) + { + GL.glPixelStorei(properties[i], oldPixelStore[i]); + LIBGUI_ASSERT_GL_OK(); } - LIBGUI_GL.glPopClientAttrib(); DENG_ASSERT(!Sys_GLCheckError()); return true; @@ -593,7 +664,7 @@ float invFactor; DENG_ASSERT(pixels); - if(!(GL_RGB == loadFormat || GL_LUMINANCE == loadFormat)) + if (!(GL_RGB == loadFormat || GL_LUMINANCE == loadFormat)) { throw Error("texturecontent_t::uploadTextureGrayMipmap", "Unsupported load format " + String::number(loadFormat)); } @@ -601,11 +672,11 @@ pixelSize = (loadFormat == GL_LUMINANCE? 1 : 3); // Can't operate on null texture. - if(width < 1 || height < 1) + if (width < 1 || height < 1) return false; // Check that the texture dimensions are valid. - if(width > GLInfo::limits().maxTexSize || height > GLInfo::limits().maxTexSize) + if (width > GLInfo::limits().maxTexSize || height > GLInfo::limits().maxTexSize) return false; numLevels = GL_NumMipmapLevels(width, height); @@ -619,7 +690,7 @@ // Initial fading. in = pixels; out = image; - for(i = 0; i < numpels; ++i) + for (i = 0; i < numpels; ++i) { *out++ = (uint8_t) MINMAX_OF(0, (*in * grayFactor + 127 * invFactor), 255); in += pixelSize; @@ -632,14 +703,14 @@ // Generate all mipmaps levels. w = width; h = height; - for(i = 0; i < numLevels; ++i) + for (i = 0; i < numLevels; ++i) { GL_DownMipmap8(image, faded, w, h, (i * 1.75f) / numLevels); // Go down one level. - if(w > 1) + if (w > 1) w /= 2; - if(h > 1) + if (h > 1) h /= 2; LIBGUI_GL.glTexImage2D(GL_TEXTURE_2D, i + 1, glFormat, w, h, 0, (GLint)loadFormat, @@ -657,13 +728,13 @@ /// @note Texture parameters will NOT be set here! void GL_UploadTextureContent(texturecontent_t const &content, gl::UploadMethod method) { - if(method == gl::Deferred) + if (method == gl::Deferred) { GL_DeferTextureUpload(&content); return; } - if(novideo) return; + if (novideo) return; // Do this right away. No need to take a copy. bool generateMipmaps = (content.flags & (TXCF_MIPMAP|TXCF_GRAY_MIPMAP)) != 0; @@ -672,36 +743,38 @@ bool noSmartFilter = (content.flags & TXCF_UPLOAD_ARG_NOSMARTFILTER) != 0; bool noStretch = (content.flags & TXCF_UPLOAD_ARG_NOSTRETCH) != 0; - int loadWidth = content.width, loadHeight = content.height; + int loadWidth = content.width; + int loadHeight = content.height; uint8_t const *loadPixels = content.pixels; - dgltexformat_t dglFormat = content.format; + dgltexformat_t dglFormat = content.format; - if(DGL_COLOR_INDEX_8 == dglFormat || DGL_COLOR_INDEX_8_PLUS_A8 == dglFormat) + // Convert a paletted source image to truecolor. + if (dglFormat == DGL_COLOR_INDEX_8 || dglFormat == DGL_COLOR_INDEX_8_PLUS_A8) { - // Convert a paletted source image to truecolor. uint8_t *newPixels = GL_ConvertBuffer(loadPixels, loadWidth, loadHeight, - DGL_COLOR_INDEX_8_PLUS_A8 == dglFormat ? 2 : 1, + dglFormat == DGL_COLOR_INDEX_8_PLUS_A8 ? 2 : 1, content.paletteId, - DGL_COLOR_INDEX_8_PLUS_A8 == dglFormat ? 4 : 3); - if(loadPixels != content.pixels) + dglFormat == DGL_COLOR_INDEX_8_PLUS_A8 ? 4 : 3); + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } loadPixels = newPixels; - dglFormat = DGL_COLOR_INDEX_8_PLUS_A8 == dglFormat ? DGL_RGBA : DGL_RGB; + dglFormat = (dglFormat == DGL_COLOR_INDEX_8_PLUS_A8 ? DGL_RGBA : DGL_RGB); } - if(DGL_RGBA == dglFormat || DGL_RGB == dglFormat) + // Gamma adjustment and smart filtering. + if (dglFormat == DGL_RGBA || dglFormat == DGL_RGB) { - int comps = (DGL_RGBA == dglFormat ? 4 : 3); + int comps = (dglFormat == DGL_RGBA ? 4 : 3); - if(applyTexGamma && texGamma > .0001f) + if (applyTexGamma && texGamma > .0001f) { uint8_t* dst, *localBuffer = 0; long const numPels = loadWidth * loadHeight; uint8_t const *src = loadPixels; - if(loadPixels == content.pixels) + if (loadPixels == content.pixels) { localBuffer = (uint8_t *) M_Malloc(comps * numPels); dst = localBuffer; @@ -711,21 +784,21 @@ dst = const_cast(loadPixels); } - for(long i = 0; i < numPels; ++i) + for (long i = 0; i < numPels; ++i) { dst[CR] = R_TexGammaLut(src[CR]); dst[CG] = R_TexGammaLut(src[CG]); dst[CB] = R_TexGammaLut(src[CB]); - if(comps == 4) + if (comps == 4) dst[CA] = src[CA]; dst += comps; src += comps; } - if(localBuffer) + if (localBuffer) { - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } @@ -733,13 +806,13 @@ } } - if(useSmartFilter && !noSmartFilter) + if (useSmartFilter && !noSmartFilter) { - if(comps == 3) + if (comps == 3) { // Need to add an alpha channel. uint8_t *newPixels = GL_ConvertBuffer(loadPixels, loadWidth, loadHeight, 3, 0, 4); - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } @@ -751,9 +824,9 @@ loadPixels, loadWidth, loadHeight, ICF_UPSCALE_SAMPLE_WRAP, &loadWidth, &loadHeight); - if(filtered != loadPixels) + if (filtered != loadPixels) { - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } @@ -762,48 +835,73 @@ } } - if(DGL_LUMINANCE_PLUS_A8 == dglFormat) + if (dglFormat == DGL_LUMINANCE && (content.flags & TXCF_CONVERT_8BIT_TO_ALPHA)) { // Needs converting. This adds some overhead. long const numPixels = content.width * content.height; - uint8_t *localBuffer = (uint8_t *) M_Malloc(2 * numPixels); + uint8_t *localBuffer = (uint8_t *) M_Malloc(4 * numPixels); + // Move the average color to the alpha channel, make the actual color white. uint8_t *pixel = localBuffer; - for(long i = 0; i < numPixels; ++i) + for (long i = 0; i < numPixels; ++i) { - pixel[0] = loadPixels[i]; - pixel[1] = loadPixels[numPixels + i]; - pixel += 2; + *pixel++ = 255; + *pixel++ = 255; + *pixel++ = 255; + *pixel++ = loadPixels[i]; } - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } loadPixels = localBuffer; + dglFormat = DGL_RGBA; } - - if(DGL_LUMINANCE == dglFormat && (content.flags & TXCF_CONVERT_8BIT_TO_ALPHA)) + else if (dglFormat == DGL_LUMINANCE) { // Needs converting. This adds some overhead. long const numPixels = content.width * content.height; - uint8_t *localBuffer = (uint8_t *) M_Malloc(2 * numPixels); + uint8_t *localBuffer = (uint8_t *) M_Malloc(3 * numPixels); // Move the average color to the alpha channel, make the actual color white. uint8_t *pixel = localBuffer; - for(long i = 0; i < numPixels; ++i) + for (long i = 0; i < numPixels; ++i) { - pixel[0] = 255; - pixel[1] = loadPixels[i]; - pixel += 2; + *pixel++ = loadPixels[i]; + *pixel++ = loadPixels[i]; + *pixel++ = loadPixels[i]; } - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } loadPixels = localBuffer; - dglFormat = DGL_LUMINANCE_PLUS_A8; + dglFormat = DGL_RGB; + } + + if (dglFormat == DGL_LUMINANCE_PLUS_A8) + { + // Needs converting. This adds some overhead. + long const numPixels = content.width * content.height; + uint8_t *localBuffer = (uint8_t *) M_Malloc(4 * numPixels); + + uint8_t *pixel = localBuffer; + for (long i = 0; i < numPixels; ++i) + { + *pixel++ = loadPixels[i]; + *pixel++ = loadPixels[i]; + *pixel++ = loadPixels[i]; + *pixel++ = loadPixels[numPixels + i]; + } + + if (loadPixels != content.pixels) + { + M_Free(const_cast(loadPixels)); + } + loadPixels = localBuffer; + dglFormat = DGL_RGBA; } // Calculate the final dimensions for the texture, as required by @@ -814,23 +912,23 @@ &loadWidth, &loadHeight); // Do we need to resize? - if(width != loadWidth || height != loadHeight) + if (width != loadWidth || height != loadHeight) { int comps = BytesPerPixelFmt(dglFormat); - if(noStretch) + if (noStretch) { // Copy the texture into a power-of-two canvas. uint8_t *localBuffer = (uint8_t *) M_Calloc(comps * loadWidth * loadHeight); // Copy line by line. - for(int i = 0; i < height; ++i) + for (int i = 0; i < height; ++i) { std::memcpy(localBuffer + loadWidth * comps * i, loadPixels + width * comps * i, comps * width); } - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } @@ -841,7 +939,7 @@ // Stretch into a new power-of-two texture. uint8_t *newPixels = GL_ScaleBuffer(loadPixels, width, height, comps, loadWidth, loadHeight); - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } @@ -849,7 +947,7 @@ } } - DENG_ASSERT_IN_MAIN_THREAD(); + //DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); LIBGUI_GL.glBindTexture(GL_TEXTURE_2D, content.name); @@ -857,16 +955,18 @@ LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, content.magFilter); LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, content.wrap[0]); LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, content.wrap[1]); - if(GL_state.features.texFilterAniso) + if (GL_state.features.texFilterAniso) LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, GL_GetTexAnisoMul(content.anisoFilter)); - if(!(content.flags & TXCF_GRAY_MIPMAP)) + DENG2_ASSERT(dglFormat == DGL_RGB || dglFormat == DGL_RGBA); + + if (!(content.flags & TXCF_GRAY_MIPMAP)) { GLint loadFormat; - switch(dglFormat) + switch (dglFormat) { - case DGL_LUMINANCE_PLUS_A8: loadFormat = GL_LUMINANCE_ALPHA; break; - case DGL_LUMINANCE: loadFormat = GL_LUMINANCE; break; + //case DGL_LUMINANCE_PLUS_A8: loadFormat = GL_LUMINANCE_ALPHA; break; + //case DGL_LUMINANCE: loadFormat = GL_LUMINANCE; break; case DGL_RGB: loadFormat = GL_RGB; break; case DGL_RGBA: loadFormat = GL_RGBA; break; default: @@ -875,7 +975,7 @@ GLint glFormat = ChooseTextureFormat(dglFormat, !noCompression); - if(!uploadTexture(glFormat, loadFormat, loadPixels, loadWidth, loadHeight, + if (!uploadTexture(glFormat, loadFormat, loadPixels, loadWidth, loadHeight, generateMipmaps ? true : false)) { throw Error("GL_UploadTextureContent", QString("TexImage failed (%1:%2 fmt%3)") @@ -889,18 +989,18 @@ // Special fade-to-gray luminance texture (used for details). GLint glFormat, loadFormat; - switch(dglFormat) + switch (dglFormat) { - case DGL_LUMINANCE: loadFormat = GL_LUMINANCE; break; + //case DGL_LUMINANCE: loadFormat = GL_LUMINANCE; break; case DGL_RGB: loadFormat = GL_RGB; break; default: throw Error("GL_UploadTextureContent", QString("Unknown format %1").arg(int(dglFormat))); } - glFormat = ChooseTextureFormat(DGL_LUMINANCE, !noCompression); + glFormat = ChooseTextureFormat(dglFormat, !noCompression); - if(!uploadTextureGrayMipmap(glFormat, loadFormat, loadPixels, loadWidth, loadHeight, - content.grayMipmap * reciprocal255)) + if (!uploadTextureGrayMipmap(glFormat, loadFormat, loadPixels, loadWidth, loadHeight, + content.grayMipmap * reciprocal255)) { throw Error("GL_UploadTextureContent", QString("TexImageGrayMipmap failed (%1:%2 fmt%3)") .arg(content.name) @@ -909,7 +1009,7 @@ } } - if(loadPixels != content.pixels) + if (loadPixels != content.pixels) { M_Free(const_cast(loadPixels)); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/macx/cursor_macx.mm doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/macx/cursor_macx.mm --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/macx/cursor_macx.mm 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/macx/cursor_macx.mm 2018-12-11 07:08:19.000000000 +0000 @@ -17,6 +17,8 @@ * http://www.gnu.org/licenses */ +#if !defined (DENG_IOS) + #include void Cursor_Show(bool show) @@ -30,3 +32,5 @@ [NSCursor hide]; } } + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/main_client.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/main_client.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/main_client.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/main_client.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -50,17 +50,48 @@ #include #include +#if defined (DENG_STATIC_LINK) + +#include +#include + +Q_IMPORT_PLUGIN(QIOSIntegrationPlugin) +Q_IMPORT_PLUGIN(QGifPlugin) +Q_IMPORT_PLUGIN(QJpegPlugin) +Q_IMPORT_PLUGIN(QTgaPlugin) +Q_IMPORT_PLUGIN(QtQuick2Plugin) +Q_IMPORT_PLUGIN(QtQuickControls2Plugin) +Q_IMPORT_PLUGIN(QtQuickLayoutsPlugin) +Q_IMPORT_PLUGIN(QtQuickTemplates2Plugin) +Q_IMPORT_PLUGIN(QtQuick2WindowPlugin) + +DENG2_IMPORT_LIBRARY(importidtech1) +DENG2_IMPORT_LIBRARY(importudmf) +DENG2_IMPORT_LIBRARY(importdeh) +DENG2_IMPORT_LIBRARY(audio_fmod) +DENG2_IMPORT_LIBRARY(doom) +//DENG2_IMPORT_LIBRARY(heretic) +//DENG2_IMPORT_LIBRARY(hexen) +//DENG2_IMPORT_LIBRARY(doom64) + +#endif + +#if defined (DENG_MOBILE) +# include +# include "ui/clientwindow.h" +#endif + /** * Application entry point. */ -int main(int argc, char** argv) +int main(int argc, char **argv) { int exitCode = 0; { ClientApp::setDefaultOpenGLFormat(); ClientApp clientApp(argc, argv); - + /** * @todo Translations are presently disabled because lupdate can't seem to * parse tr strings from inside private implementation classes. Workaround @@ -76,6 +107,17 @@ try { clientApp.initialize(); + +#if defined (DENG_MOBILE) + // On mobile, Qt Quick is actually in charge of drawing the screen. + // GLWindow is just an item that draws the UI background. + qmlRegisterType>("Doomsday", 1, 0, "ClientWindow"); + QQuickView view; + view.setResizeMode(QQuickView::SizeRootObjectToView); + view.setSource(QUrl("qrc:///qml/main.qml")); + view.show(); +#endif + exitCode = clientApp.execLoop(); } catch(de::Error const &er) @@ -89,16 +131,22 @@ } // Check that all reference-counted objects have been deleted. -#ifdef DENG2_DEBUG -# ifdef DENG_USE_COUNTED_TRACING - if(de::Counted::totalCount > 0) + #if defined (DENG2_DEBUG) { - de::Counted::printAllocs(); + #if defined (DENG_USE_COUNTED_TRACING) + { + if(de::Counted::totalCount > 0) + { + de::Counted::printAllocs(); + } + } + #else + { + DENG2_ASSERT(de::Counted::totalCount == 0); + } + #endif } -# else - DENG2_ASSERT(de::Counted::totalCount == 0); -# endif -#endif + #endif return exitCode; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/masterserver.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/masterserver.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/masterserver.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/masterserver.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -54,10 +54,7 @@ static QString masterUrl(char const *suffix = 0) { - String u = App::config().gets("apiUrl"); - if (!u.startsWith("http")) u = "http://" + u; - if (!u.endsWith("/")) u += "/"; - u += "master_server"; + String u = App::apiUrl() + "master_server"; if (suffix) u += suffix; return u; } @@ -219,7 +216,7 @@ try { std::unique_ptr entryValue(Value::constructFrom(entry)); - if (!entryValue->is()) + if (!is(*entryValue)) { LOG_NET_WARNING("Server information was in unexpected format"); continue; @@ -283,7 +280,7 @@ } DENG2_ASSERT(worker); - worker->newJob(MasterWorker::ANNOUNCE, info); + worker->newJob(MasterWorker::ANNOUNCE, info.asRecord()); #else DENG_UNUSED(isOpen); #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/net_buf.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/net_buf.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/net_buf.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/net_buf.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef __CLIENT__ # include "network/sys_network.h" @@ -57,21 +58,11 @@ // the message queue. static mutex_t msgMutex; -// Number of bytes of outgoing data transmitted. -static dsize numOutBytes; - -// Number of bytes sent over the network (compressed). -static dsize numSentBytes; - reader_s *Reader_NewWithNetworkBuffer() { return Reader_NewWithBuffer((byte const *) netBuffer.msg.data, netBuffer.length); } -/** - * Initialize the low-level network subsystem. This is called always - * during startup (via Sys_Init()). - */ void N_Init() { // Create a mutex for the message queue. @@ -83,10 +74,6 @@ N_MasterInit(); } -/** - * Shut down the low-level network interface. Called during engine - * shutdown (not before). - */ void N_Shutdown() { // Any queued messages will be destroyed. @@ -106,7 +93,7 @@ * * @return @c true if successful. */ -dd_bool N_LockQueue(dd_bool doAcquire) +static dd_bool N_LockQueue(dd_bool doAcquire) { if(doAcquire) Sys_Lock(msgMutex); @@ -115,12 +102,6 @@ return true; } -/** - * Adds the given netmessage_s to the queue of received messages. - * We use a mutex to synchronize access to the message queue. - * - * @note This is called in the network receiver thread. - */ void N_PostMessage(netmessage_t *msg) { DENG2_ASSERT(msg); @@ -162,7 +143,7 @@ * * @return @c nullptr if no message is found. */ -netmessage_t *N_GetMessage() +static netmessage_t *N_GetMessage() { // This is the message we'll return. netmessage_t *msg = nullptr; @@ -205,10 +186,7 @@ return msg; } -/** - * Frees the message. - */ -void N_ReleaseMessage(netmessage_t *msg) +static void N_ReleaseMessage(netmessage_t *msg) { DENG2_ASSERT(msg); if(msg->handle) @@ -219,9 +197,6 @@ M_Free(msg); } -/** - * Empties the message buffers. - */ void N_ClearMessages() { if(!msgMutex) return; // Not initialized yet. @@ -244,13 +219,6 @@ ::entryCount = 0; } -/** - * Send the data in the netbuffer. The message is sent using an unreliable, - * nonsequential (i.e. fast) method. - * - * Handles broadcasts using recursion. - * Clients can only send stuff to the server. - */ void N_SendPacket(dint flags) { #ifdef __SERVER__ @@ -292,9 +260,6 @@ } #endif - // This is what will be sent. - ::numOutBytes += ::netBuffer.headerLength + ::netBuffer.length; - try { #ifdef __CLIENT__ @@ -311,14 +276,11 @@ } } -void N_AddSentBytes(dsize bytes) -{ - ::numSentBytes += bytes; -} +//void N_AddSentBytes(dsize bytes) +//{ +// ::numSentBytes += bytes; +//} -/** - * @return The player number that corresponds network node @a id. - */ dint N_IdentifyPlayer(nodeid_t id) { #ifdef __SERVER__ @@ -344,7 +306,7 @@ * @return The next message waiting in the incoming message queue. When the message * is no longer needed you must call N_ReleaseMessage() to delete it. */ -netmessage_t *N_GetNextMessage() +static netmessage_t *N_GetNextMessage() { netmessage_t *msg; while((msg = N_GetMessage()) != nullptr) @@ -354,11 +316,6 @@ return nullptr; // There are no more messages. } -/** - * An attempt is made to extract a message from the message queue. - * - * @return @c true if a message successfull. - */ dd_bool N_GetPacket() { // If there are net events pending, let's not return any packets @@ -399,31 +356,38 @@ return true; } -/** - * Print low-level information about the network buffer. - */ void N_PrintBufferInfo() { N_PrintTransmissionStats(); + + double const loopRate = Loop::get().rate(); + if (loopRate > 0) + { + LOG_NET_MSG("Event loop frequency: up to %.1f Hz") << loopRate; + } + else + { + LOG_NET_MSG("Event loop frequency: unlimited"); + } } -/** - * Print status information about the workings of data compression in the network buffer. - * - * @note Currently numOutBytes excludes transmission header, while numSentBytes includes - * every byte written to the socket. In other words, the efficiency includes protocol overhead. - */ void N_PrintTransmissionStats() { - if(::numOutBytes == 0) + auto const dataBytes = Socket::sentUncompressedBytes(); + auto const outBytes = Socket::sentBytes(); + auto const outRate = Socket::outputBytesPerSecond(); + + if (outBytes == 0) { - LOG_NET_MSG("Transmission efficiency: Nothing has been sent yet"); + LOG_NET_MSG("Nothing has been sent yet over the network"); } else { - LOG_NET_MSG("Transmission efficiency: %.3f%% (data: %i bytes, sent: %i bytes)") - << (100 - (100.0f * ::numSentBytes) / ::numOutBytes) - << ::numOutBytes - << ::numSentBytes; + LOG_NET_MSG("Average compression: %.3f%% (data: %.1f KB, out: %.1f KB)\n" + "Current output: %.1f KB/s") + << 100 * (1.0 - double(outBytes) / double(dataBytes)) + << dataBytes/1000.0 + << outBytes/1000.0 + << outRate/1000.0; } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/net_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/net_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/base/net_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/base/net_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -581,23 +581,23 @@ DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Go into screen projection mode. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(::fontFixed); FR_LoadDefaultAttrib(); FR_SetColorAndAlpha(1, 1, 1, 1); FR_DrawTextXY3(buf, x, y, ALIGN_TOPRIGHT, DTF_NO_EFFECTS); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); // Restore original matrix. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } #endif // __CLIENT__ @@ -619,7 +619,7 @@ // Draw the demo recording overlay. Net_DrawDemoOverlay(); -# ifdef DENG2_DEBUG +# if defined (DENG2_DEBUG) && defined (DENG_OPENGL) Z_DebugDrawer(); # endif #endif // __CLIENT__ @@ -836,8 +836,7 @@ String Net_UserAgent() { - return String(DOOMSDAY_NICENAME " " DOOMSDAY_VERSION_TEXT) - + " (" + de::Version::operatingSystem() + ")"; + return Version::currentBuild().userAgent(); } /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/serverlink.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/serverlink.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/serverlink.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/serverlink.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -27,10 +27,12 @@ #include "client/cl_def.h" #include "ui/clientwindow.h" #include "ui/widgets/taskbarwidget.h" +#include "ui/dialogs/filedownloaddialog.h" #include "dd_def.h" #include "dd_main.h" #include "clientapp.h" +#include #include #include #include @@ -75,12 +77,13 @@ Servers discovered; Servers fromMaster; QElapsedTimer pingTimer; - QList pings; + QList pings; int pingCounter; std::unique_ptr serverProfile; ///< Profile used when joining. std::function profileResultCallback; std::function profileResultCallbackWithAddress; - LoopCallback mainCall; + shell::PackageDownloader downloader; + LoopCallback deferred; // for deferred actions Impl(Public *i, Flags flags) : Base(i) @@ -119,7 +122,7 @@ { QVariant const response = parseJSON(String::fromUtf8(reply.mid(5))); std::unique_ptr rec(Value::constructFrom(response.toMap())); - if (!rec->is()) + if (!is(*rec)) { throw Error("ServerLink::handleInfoResponse", "Failed to parse response contents"); } @@ -148,7 +151,7 @@ if (prepareServerProfile(svAddress)) { LOG_NET_MSG("Received server's game profile from ") << svAddress; - mainCall.enqueue([this, svAddress] () + deferred.enqueue([this, svAddress] () { if (profileResultCallback) { @@ -240,7 +243,7 @@ fetching = true; N_MAPost(MAC_REQUEST); N_MAPost(MAC_WAIT); - mainCall.enqueue([this] () { checkMasterReply(); }); + deferred.enqueue([this] () { checkMasterReply(); }); } void checkMasterReply() @@ -265,7 +268,7 @@ else { // Check again later. - mainCall.enqueue([this] () { checkMasterReply(); }); + deferred.enqueue([this] () { checkMasterReply(); }); } } @@ -357,13 +360,18 @@ connect(this, SIGNAL(disconnected()), this, SLOT(linkDisconnected())); } +shell::PackageDownloader &ServerLink::packageDownloader() +{ + return d->downloader; +} + void ServerLink::clear() { d->finder->clear(); // TODO: clear all found servers } -void ServerLink::connectToServerAndChangeGame(shell::ServerInfo info) +void ServerLink::connectToServerAndChangeGameAsync(shell::ServerInfo info) { // Automatically leave the current MP game. if (netGame && isClient) @@ -371,11 +379,16 @@ disconnect(); } - // Get the profile for this. - // Use a delayed callback so that the UI is not blocked while we switch games. - acquireServerProfile(info.address(), - [this, info] (GameProfile const *serverProfile) + // Forming the connection is a multi-step asynchronous procedure. The app's event + // loop is running between each of these steps so the UI is never frozen. The first + // step is to acquire the server's game profile. + + acquireServerProfileAsync(info.address(), + [this, info] (GameProfile const *serverProfile) { + auto &win = ClientWindow::main(); + win.glActivate(); + if (!serverProfile) { // Hmm, oopsie? @@ -386,10 +399,12 @@ return; } - auto &win = ClientWindow::main(); - win.glActivate(); + // Profile acquired! Figure out if the profile can be started locally. + LOG_NET_MSG("Received server's game profile"); + LOG_NET_VERBOSE(serverProfile->toInfoSource()); - // If additional packages are configured, set up the ad-hoc profile. + // If additional packages are configured, set up the ad-hoc profile with the + // local additions. GameProfile const *joinProfile = serverProfile; auto const localPackages = serverProfile->game().localMultiplayerPackages(); if (localPackages.count()) @@ -414,36 +429,75 @@ joinProfile = &adhoc; } - if (!joinProfile->isPlayable()) + // The server makes certain packages available for clients to download. + d->downloader.mountServerRepository(info, [this, joinProfile, info] (filesys::Link const *) { - String const errorMsg = tr("Server's game \"%1\" is not playable on this system. " - "The following packages are unavailable:\n\n%2") - .arg(info.gameId()) - .arg(String::join(de::map(joinProfile->unavailablePackages(), - Package::splitToHumanReadable), "\n")); - LOG_NET_ERROR("Failed to join %s: ") << info.address() << errorMsg; - d->reportError(errorMsg); - return; - } + // Now we know all the files that the server will be providing. + // If we are missing any of the packages, download a copy from the server. - BusyMode_FreezeGameForBusyMode(); - win.taskBar().close(); + LOG_RES_MSG("Received metadata about server files"); + + StringList const neededPackages = joinProfile->unavailablePackages(); + LOG_RES_MSG("Packages needed to join: ") + << String::join(neededPackages, " "); - DoomsdayApp::app().changeGame(*joinProfile, DD_ActivateGameWorker); + // Show the download popup. + auto *dlPopup = new FileDownloadDialog(d->downloader); + dlPopup->setDeleteAfterDismissed(true); + ClientWindow::main().root().addOnTop(dlPopup); + dlPopup->open(DialogWidget::Modal); - connectHost(info.address()); + // Request contents of missing packages. + d->downloader.download(neededPackages, + [this, dlPopup, joinProfile, info] () + { + auto &win = ClientWindow::main(); + win.glActivate(); + + dlPopup->close(); + if (d->downloader.isCancelled()) + { + d->downloader.unmountServerRepository(); + return; + } + + if (!joinProfile->isPlayable()) + { + String const errorMsg = tr("Server's game \"%1\" is not playable on this system. " + "The following packages are unavailable:\n\n%2") + .arg(info.gameId()) + .arg(String::join(de::map(joinProfile->unavailablePackages(), + Package::splitToHumanReadable), "\n")); + LOG_NET_ERROR("Failed to join %s: ") << info.address() << errorMsg; + d->downloader.unmountServerRepository(); + d->reportError(errorMsg); + return; + } - win.glDone(); + // Everything is finally good to go. + + BusyMode_FreezeGameForBusyMode(); + win.taskBar().close(); + DoomsdayApp::app().changeGame(*joinProfile, DD_ActivateGameWorker); + connectHost(info.address()); + + win.glDone(); + }); + + // We must wait after the downloads have finished. + // The user sees a popup while downloads are progressing, and has the + // option of cancelling. + }); }); } -void ServerLink::acquireServerProfile(Address const &address, - std::function resultHandler) +void ServerLink::acquireServerProfileAsync(Address const &address, + std::function resultHandler) { if (d->prepareServerProfile(address)) { // We already know everything that is needed for the profile. - d->mainCall.enqueue([this, resultHandler] () + d->deferred.enqueue([this, resultHandler] () { DENG2_ASSERT(d->serverProfile.get() != nullptr); resultHandler(d->serverProfile.get()); @@ -454,23 +508,23 @@ AbstractLink::connectHost(address); d->profileResultCallback = resultHandler; d->state = Discovering; - LOG_NET_MSG("Querying %s for full status") << address; + LOG_NET_MSG("Querying server %s for full status") << address; } } -void ServerLink::acquireServerProfile(String const &domain, - std::function resultHandler) +void ServerLink::acquireServerProfileAsync(String const &domain, + std::function resultHandler) { d->profileResultCallbackWithAddress = resultHandler; discover(domain); - LOG_NET_MSG("Querying %s for full status") << domain; + LOG_NET_MSG("Querying server %s for full status") << domain; } void ServerLink::requestMapOutline(Address const &address) { AbstractLink::connectHost(address); d->state = QueryingMapOutline; - LOG_NET_VERBOSE("Querying %s for map outline") << address; + LOG_NET_VERBOSE("Querying server %s for map outline") << address; } void ServerLink::ping(Address const &address) @@ -483,7 +537,7 @@ } } -void ServerLink::connectDomain(String const &domain, TimeDelta const &timeout) +void ServerLink::connectDomain(String const &domain, TimeSpan const &timeout) { LOG_AS("ServerLink::connectDomain"); @@ -528,7 +582,7 @@ DENG2_FOR_AUDIENCE2(Leave, i) i->networkGameLeft(); LOG_NET_NOTE("Link to server %s disconnected") << address(); - + d->downloader.unmountServerRepository(); AbstractLink::disconnect(); Net_StopGame(); @@ -698,7 +752,7 @@ if (packetData.size() == 4 && packetData == "Pong" && d->pingCounter-- > 0) { - d->pings.append(TimeDelta::fromMilliSeconds(d->pingTimer.elapsed())); + d->pings.append(TimeSpan::fromMilliSeconds(d->pingTimer.elapsed())); *this << ByteRefArray("Ping?", 5); d->pingTimer.restart(); } @@ -711,8 +765,8 @@ // Notify about the average ping time. if (d->pings.count()) { - TimeDelta average = 0; - for (TimeDelta i : d->pings) average += i; + TimeSpan average = 0; + for (TimeSpan i : d->pings) average += i; average /= d->pings.count(); DENG2_FOR_AUDIENCE2(PingResponse, i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/sys_network.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/sys_network.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/network/sys_network.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/network/sys_network.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -31,18 +31,12 @@ using namespace de; -//char *nptIPAddress = (char *) ""; ///< Address to connect to by default (cvar). -int nptIPPort = 0; ///< Port to connect to by default (cvar). - #ifdef _DEBUG D_CMD(NetFreqs); #endif void N_Register(void) { - //C_VAR_CHARPTR("net-ip-address", &nptIPAddress, 0, 0, 0); - //C_VAR_INT ("net-ip-port", &nptIPPort, CVF_NO_MAX, 0, 0); - #ifdef _DEBUG C_CMD("netfreq", NULL, NetFreqs); #endif @@ -53,24 +47,12 @@ return ClientApp::app().serverLink(); } -#if 0 -dd_bool N_GetHostInfo(int index, struct serverinfo_s *info) -{ - return Net_ServerLink().foundServerInfo(index, info); -} - -int N_GetHostCount(void) -{ - return Net_ServerLink().foundServerCount(); -} -#endif - /** * Called from "net info" (client-side). */ void N_PrintNetworkStatus(void) { - if(isClient) + if (isClient) { LOG_NET_NOTE(_E(b) "CLIENT: " _E(.) "Connected to server at %s") << Net_ServerLink().address(); } @@ -78,6 +60,5 @@ { LOG_NET_NOTE(_E(b) "OFFLINE: " _E(.) "Single-player mode"); } - N_PrintBufferInfo(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/api_render.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/api_render.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/api_render.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/api_render.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -127,7 +127,7 @@ static inline MaterialVariantSpec const &pspriteMaterialSpec_GetSpriteInfo() { return App_Resources().materialSpec(PSpriteContext, 0, 1, 0, 0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, - 0, 1, -1, false, true, true, false); + 0, -2, -1, false, true, true, false); } #undef R_GetSpriteInfo diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/billboard.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/billboard.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/billboard.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/billboard.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -54,28 +54,28 @@ static inline void drawQuad(dgl_vertex_t *v, dgl_color_t *c, dgl_texcoord_t *tc) { - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glColor4ubv(c[0].rgba); - LIBGUI_GL.glTexCoord2fv(tc[0].st); - LIBGUI_GL.glVertex3fv(v[0].xyz); - - LIBGUI_GL.glColor4ubv(c[1].rgba); - LIBGUI_GL.glTexCoord2fv(tc[1].st); - LIBGUI_GL.glVertex3fv(v[1].xyz); - - LIBGUI_GL.glColor4ubv(c[2].rgba); - LIBGUI_GL.glTexCoord2fv(tc[2].st); - LIBGUI_GL.glVertex3fv(v[2].xyz); - - LIBGUI_GL.glColor4ubv(c[3].rgba); - LIBGUI_GL.glTexCoord2fv(tc[3].st); - LIBGUI_GL.glVertex3fv(v[3].xyz); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_Color4ubv(c[0].rgba); + DGL_TexCoord2fv(0, tc[0].st); + DGL_Vertex3fv(v[0].xyz); + + DGL_Color4ubv(c[1].rgba); + DGL_TexCoord2fv(0, tc[1].st); + DGL_Vertex3fv(v[1].xyz); + + DGL_Color4ubv(c[2].rgba); + DGL_TexCoord2fv(0, tc[2].st); + DGL_Vertex3fv(v[2].xyz); + + DGL_Color4ubv(c[3].rgba); + DGL_TexCoord2fv(0, tc[3].st); + DGL_Vertex3fv(v[3].xyz); + DGL_End(); } void Rend_DrawMaskedWall(drawmaskedwallparams_t const &parms) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); TextureVariant *tex = nullptr; @@ -94,7 +94,7 @@ // This only happens when multitexturing is enabled. bool withDyn = false; dint normal = 0, dyn = 1; - if(parms.modTex && ::numTexUnits > 1) + if(parms.modTex) { if(IS_MUL) { @@ -108,34 +108,34 @@ } GL_SelectTexUnits(2); - GL_ModulateTexture(IS_MUL ? 4 : 5); + DGL_ModulateTexture(IS_MUL? 4 : 5); // The dynamic light. - LIBGUI_GL.glActiveTexture(IS_MUL ? GL_TEXTURE0 : GL_TEXTURE1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, IS_MUL? 0 : 1); /// @todo modTex may be the name of a "managed" texture. GL_BindTextureUnmanaged(renderTextures ? parms.modTex : 0, gl::ClampToEdge, gl::ClampToEdge); - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, parms.modColor); + DGL_SetModulationColor(parms.modColor); // The actual texture. - LIBGUI_GL.glActiveTexture(IS_MUL ? GL_TEXTURE1 : GL_TEXTURE0); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, IS_MUL? 1 : 0); GL_BindTexture(tex); withDyn = true; } else { - GL_ModulateTexture(1); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_ModulateTexture(1); + DGL_Enable(DGL_TEXTURE_2D); GL_BindTexture(tex); normal = 0; } GL_BlendMode(parms.blendMode); - GLenum normalTarget = normal? GL_TEXTURE1 : GL_TEXTURE0; - GLenum dynTarget = dyn? GL_TEXTURE1 : GL_TEXTURE0; + byte normalTarget = normal? 1 : 0; + byte dynTarget = dyn? 1 : 0; // Draw one quad. This is obviously not a very efficient way to render // lots of masked walls, but since 3D models and sprites must be @@ -143,82 +143,82 @@ // done about this. if(withDyn) { - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glColor4fv(parms.vertices[0].color); - LIBGUI_GL.glMultiTexCoord2f(normalTarget, parms.texCoord[0][0], parms.texCoord[1][1]); + DGL_Begin(DGL_QUADS); + DGL_Color4fv(parms.vertices[0].color); + DGL_TexCoord2f(normalTarget, parms.texCoord[0][0], parms.texCoord[1][1]); - LIBGUI_GL.glMultiTexCoord2f(dynTarget, parms.modTexCoord[0][0], parms.modTexCoord[1][1]); + DGL_TexCoord2f(dynTarget, parms.modTexCoord[0][0], parms.modTexCoord[1][1]); - LIBGUI_GL.glVertex3f(parms.vertices[0].pos[0], - parms.vertices[0].pos[2], - parms.vertices[0].pos[1]); + DGL_Vertex3f(parms.vertices[0].pos[0], + parms.vertices[0].pos[2], + parms.vertices[0].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[1].color); - LIBGUI_GL.glMultiTexCoord2f(normalTarget, parms.texCoord[0][0], parms.texCoord[0][1]); + DGL_Color4fv(parms.vertices[1].color); + DGL_TexCoord2f(normalTarget, parms.texCoord[0][0], parms.texCoord[0][1]); - LIBGUI_GL.glMultiTexCoord2f(dynTarget, parms.modTexCoord[0][0], parms.modTexCoord[0][1]); + DGL_TexCoord2f(dynTarget, parms.modTexCoord[0][0], parms.modTexCoord[0][1]); - LIBGUI_GL.glVertex3f(parms.vertices[1].pos[0], - parms.vertices[1].pos[2], - parms.vertices[1].pos[1]); + DGL_Vertex3f(parms.vertices[1].pos[0], + parms.vertices[1].pos[2], + parms.vertices[1].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[3].color); - LIBGUI_GL.glMultiTexCoord2f(normalTarget, parms.texCoord[1][0], parms.texCoord[0][1]); + DGL_Color4fv(parms.vertices[3].color); + DGL_TexCoord2f(normalTarget, parms.texCoord[1][0], parms.texCoord[0][1]); - LIBGUI_GL.glMultiTexCoord2f(dynTarget, parms.modTexCoord[1][0], parms.modTexCoord[0][1]); + DGL_TexCoord2f(dynTarget, parms.modTexCoord[1][0], parms.modTexCoord[0][1]); - LIBGUI_GL.glVertex3f(parms.vertices[3].pos[0], - parms.vertices[3].pos[2], - parms.vertices[3].pos[1]); + DGL_Vertex3f(parms.vertices[3].pos[0], + parms.vertices[3].pos[2], + parms.vertices[3].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[2].color); - LIBGUI_GL.glMultiTexCoord2f(normalTarget, parms.texCoord[1][0], parms.texCoord[1][1]); + DGL_Color4fv(parms.vertices[2].color); + DGL_TexCoord2f(normalTarget, parms.texCoord[1][0], parms.texCoord[1][1]); - LIBGUI_GL.glMultiTexCoord2f(dynTarget, parms.modTexCoord[1][0], parms.modTexCoord[1][1]); + DGL_TexCoord2f(dynTarget, parms.modTexCoord[1][0], parms.modTexCoord[1][1]); - LIBGUI_GL.glVertex3f(parms.vertices[2].pos[0], - parms.vertices[2].pos[2], - parms.vertices[2].pos[1]); - LIBGUI_GL.glEnd(); + DGL_Vertex3f(parms.vertices[2].pos[0], + parms.vertices[2].pos[2], + parms.vertices[2].pos[1]); + DGL_End(); // Restore normal GL state. GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } else { - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glColor4fv(parms.vertices[0].color); - LIBGUI_GL.glTexCoord2f(parms.texCoord[0][0], parms.texCoord[1][1]); + DGL_Begin(DGL_QUADS); + DGL_Color4fv(parms.vertices[0].color); + DGL_TexCoord2f(0, parms.texCoord[0][0], parms.texCoord[1][1]); - LIBGUI_GL.glVertex3f(parms.vertices[0].pos[0], + DGL_Vertex3f(parms.vertices[0].pos[0], parms.vertices[0].pos[2], parms.vertices[0].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[1].color); - LIBGUI_GL.glTexCoord2f(parms.texCoord[0][0], parms.texCoord[0][1]); + DGL_Color4fv(parms.vertices[1].color); + DGL_TexCoord2f(0, parms.texCoord[0][0], parms.texCoord[0][1]); - LIBGUI_GL.glVertex3f(parms.vertices[1].pos[0], + DGL_Vertex3f(parms.vertices[1].pos[0], parms.vertices[1].pos[2], parms.vertices[1].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[3].color); - LIBGUI_GL.glTexCoord2f(parms.texCoord[1][0], parms.texCoord[0][1]); + DGL_Color4fv(parms.vertices[3].color); + DGL_TexCoord2f(0, parms.texCoord[1][0], parms.texCoord[0][1]); - LIBGUI_GL.glVertex3f(parms.vertices[3].pos[0], + DGL_Vertex3f(parms.vertices[3].pos[0], parms.vertices[3].pos[2], parms.vertices[3].pos[1]); - LIBGUI_GL.glColor4fv(parms.vertices[2].color); - LIBGUI_GL.glTexCoord2f(parms.texCoord[1][0], parms.texCoord[1][1]); + DGL_Color4fv(parms.vertices[2].color); + DGL_TexCoord2f(0, parms.texCoord[1][0], parms.texCoord[1][1]); - LIBGUI_GL.glVertex3f(parms.vertices[2].pos[0], + DGL_Vertex3f(parms.vertices[2].pos[0], parms.vertices[2].pos[2], parms.vertices[2].pos[1]); - LIBGUI_GL.glEnd(); + DGL_End(); } - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); GL_BlendMode(BM_NORMAL); } @@ -296,13 +296,13 @@ void Rend_DrawPSprite(rendpspriteparams_t const &parms) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); if(::renderTextures == 1) { GL_SetPSprite(parms.mat, 0, 0); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); } else if(::renderTextures == 2) { @@ -314,7 +314,7 @@ matAnimator.prepare(); GL_BindTexture(matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); } // 0---1 @@ -361,27 +361,27 @@ tc[3].st[0] = parms.texOffset[0] * (parms.texFlip[0]? 1:0); tc[3].st[1] = parms.texOffset[1] * (!parms.texFlip[1]? 1:0); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glColor4ubv(c[0].rgba); - LIBGUI_GL.glTexCoord2fv(tc[0].st); - LIBGUI_GL.glVertex2fv(v1); - - LIBGUI_GL.glColor4ubv(c[1].rgba); - LIBGUI_GL.glTexCoord2fv(tc[1].st); - LIBGUI_GL.glVertex2fv(v2); - - LIBGUI_GL.glColor4ubv(c[2].rgba); - LIBGUI_GL.glTexCoord2fv(tc[2].st); - LIBGUI_GL.glVertex2fv(v3); - - LIBGUI_GL.glColor4ubv(c[3].rgba); - LIBGUI_GL.glTexCoord2fv(tc[3].st); - LIBGUI_GL.glVertex2fv(v4); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_Color4ubv(c[0].rgba); + DGL_TexCoord2fv(0, tc[0].st); + DGL_Vertex2fv(v1); + + DGL_Color4ubv(c[1].rgba); + DGL_TexCoord2fv(0, tc[1].st); + DGL_Vertex2fv(v2); + + DGL_Color4ubv(c[2].rgba); + DGL_TexCoord2fv(0, tc[2].st); + DGL_Vertex2fv(v3); + + DGL_Color4ubv(c[3].rgba); + DGL_TexCoord2fv(0, tc[3].st); + DGL_Vertex2fv(v4); + DGL_End(); if(renderTextures) { - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } } @@ -395,7 +395,7 @@ { drawspriteparams_t const &parm = *VS_SPRITE(&spr); - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); TextureVariant *tex = nullptr; @@ -434,7 +434,7 @@ if(renderTextures) { GL_BindTexture(tex); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); } else { @@ -465,14 +465,14 @@ /*#if _DEBUG // Draw the surface normal. - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glColor4f(1, 0, 0, 1); - LIBGUI_GL.glVertex3f(spriteCenter[0], spriteCenter[2], spriteCenter[1]); - LIBGUI_GL.glColor4f(1, 0, 0, 0); - LIBGUI_GL.glVertex3f(spriteCenter[0] + surfaceNormal[0] * 10, + DGL_Begin(DGL_LINES); + DGL_Color4f(1, 0, 0, 1); + DGL_Vertex3f(spriteCenter[0], spriteCenter[2], spriteCenter[1]); + DGL_Color4f(1, 0, 0, 0); + DGL_Vertex3f(spriteCenter[0] + surfaceNormal[0] * 10, spriteCenter[2] + surfaceNormal[2] * 10, spriteCenter[1] + surfaceNormal[1] * 10); - LIBGUI_GL.glEnd(); + DGL_End(); #endif*/ // All sprite vertices are co-plannar, so just copy the surface normal. @@ -503,11 +503,11 @@ { // We must set up a modelview transformation matrix. restoreMatrix = true; - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // Rotate around the center of the sprite. - LIBGUI_GL.glTranslatef(spriteCenter[0], spriteCenter[2], spriteCenter[1]); + DGL_Translatef(spriteCenter[0], spriteCenter[2], spriteCenter[1]); if(!spr.pose.viewAligned) { dfloat s_dx = v1[0] - v2[0]; @@ -530,7 +530,7 @@ spriteAngle + maxSpriteAngle); // Rotate along the sprite edge. - LIBGUI_GL.glRotatef(turnAngle, s_dx, 0, s_dy); + DGL_Rotatef(turnAngle, s_dx, 0, s_dy); } } else @@ -538,15 +538,15 @@ // Restricted view plane alignment. // This'll do, for now... Really it should notice both the // sprite angle and vpitch. - LIBGUI_GL.glRotatef(vpitch * .5f, s_dx, 0, s_dy); + DGL_Rotatef(vpitch * .5f, s_dx, 0, s_dy); } } else { // Normal rotation perpendicular to the view plane. - LIBGUI_GL.glRotatef(vpitch, viewsidex, 0, viewsidey); + DGL_Rotatef(vpitch, viewsidex, 0, viewsidey); } - LIBGUI_GL.glTranslatef(-spriteCenter[0], -spriteCenter[2], -spriteCenter[1]); + DGL_Translatef(-spriteCenter[0], -spriteCenter[2], -spriteCenter[1]); } // Need to change blending modes? @@ -560,8 +560,7 @@ !(parm.blendMode == BM_NORMAL || parm.blendMode == BM_ZEROALPHA)) { restoreZ = true; - //LIBGUI_GL.glDepthMask(GL_FALSE); - GLState::current().setDepthWrite(false).apply(); + DGL_Disable(DGL_DEPTH_WRITE); } dgl_vertex_t vs[4], *v = vs; @@ -600,23 +599,20 @@ if(renderTextures) { - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } if(devMobjVLights && spr.light.vLightListIdx) { // Draw the vlight vectors, for debug. - //LIBGUI_GL.glDisable(GL_DEPTH_TEST); - //LIBGUI_GL.glDisable(GL_CULL_FACE); - GLState::push() - .setDepthTest(false) - .setCull(gl::None) - .apply(); + DGL_PushState(); + DGL_Disable(DGL_DEPTH_TEST); + DGL_CullFace(DGL_NONE); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - LIBGUI_GL.glTranslatef(spr.pose.origin[0], spr.pose.origin[2], spr.pose.origin[1]); + DGL_Translatef(spr.pose.origin[0], spr.pose.origin[2], spr.pose.origin[1]); coord_t const distFromViewer = de::abs(spr.pose.distance); ClientApp::renderSystem().forAllVectorLights(spr.light.vLightListIdx, [&distFromViewer] (VectorLightData const &vlight) @@ -628,18 +624,16 @@ return LoopContinue; }); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); - //LIBGUI_GL.glEnable(GL_CULL_FACE); - //LIBGUI_GL.glEnable(GL_DEPTH_TEST); - GLState::pop().apply(); + DGL_PopState(); } // Need to restore the original modelview matrix? if(restoreMatrix) { - LIBGUI_GL.glPopMatrix(); + DGL_PopMatrix(); } // Change back to normal blending? @@ -651,8 +645,7 @@ // Enable Z-writing again? if(restoreZ) { - //LIBGUI_GL.glDepthMask(GL_TRUE); - GLState::current().setDepthWrite(true).apply(); + DGL_Enable(DGL_DEPTH_WRITE); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/blockmapvisual.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/blockmapvisual.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/blockmapvisual.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/blockmapvisual.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -52,16 +52,16 @@ { AABoxd const bounds = Mobj_Bounds(mob); - LIBGUI_GL.glVertex2f(bounds.minX, bounds.minY); - LIBGUI_GL.glVertex2f(bounds.maxX, bounds.minY); - LIBGUI_GL.glVertex2f(bounds.maxX, bounds.maxY); - LIBGUI_GL.glVertex2f(bounds.minX, bounds.maxY); + DGL_Vertex2f(bounds.minX, bounds.minY); + DGL_Vertex2f(bounds.maxX, bounds.minY); + DGL_Vertex2f(bounds.maxX, bounds.maxY); + DGL_Vertex2f(bounds.minX, bounds.maxY); } static void drawLine(Line const &line) { - LIBGUI_GL.glVertex2f(line.from().x(), line.from().y()); - LIBGUI_GL.glVertex2f(line.to ().x(), line.to ().y()); + DGL_Vertex2f(line.from().x(), line.from().y()); + DGL_Vertex2f(line.to ().x(), line.to ().y()); } static void drawSubspace(ConvexSubspace const &subspace) @@ -77,10 +77,10 @@ Vector2d start = hedge->origin(); Vector2d end = hedge->twin().origin(); - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glVertex2f(end.x, end.y); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Vertex2f(start.x, start.y); + DGL_Vertex2f(end.x, end.y); + DGL_End(); ddouble length = (end - start).length(); if (length > 0) @@ -89,21 +89,21 @@ Vector2d const normal(-unit.y, unit.x); GL_BindTextureUnmanaged(GL_PrepareLSTexture(LST_DYNAMIC)); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); GL_BlendMode(BM_ADD); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glTexCoord2f(0.75f, 0.5f); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glTexCoord2f(0.75f, 0.5f); - LIBGUI_GL.glVertex2f(end.x, end.y); - LIBGUI_GL.glTexCoord2f(0.75f, 1); - LIBGUI_GL.glVertex2f(end.x - normal.x * width, end.y - normal.y * width); - LIBGUI_GL.glTexCoord2f(0.75f, 1); - LIBGUI_GL.glVertex2f(start.x - normal.x * width, start.y - normal.y * width); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0.75f, 0.5f); + DGL_Vertex2f(start.x, start.y); + DGL_TexCoord2f(0, 0.75f, 0.5f); + DGL_Vertex2f(end.x, end.y); + DGL_TexCoord2f(0, 0.75f, 1); + DGL_Vertex2f(end.x - normal.x * width, end.y - normal.y * width); + DGL_TexCoord2f(0, 0.75f, 1); + DGL_Vertex2f(start.x - normal.x * width, start.y - normal.y * width); + DGL_End(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); GL_BlendMode(BM_NORMAL); } @@ -111,23 +111,23 @@ start = Vector2d(poly.bounds().minX, poly.bounds().minY); end = Vector2d(poly.bounds().maxX, poly.bounds().maxY); - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glVertex2f( end.x, start.y); - LIBGUI_GL.glVertex2f( end.x, start.y); - LIBGUI_GL.glVertex2f( end.x, end.y); - LIBGUI_GL.glVertex2f( end.x, end.y); - LIBGUI_GL.glVertex2f(start.x, end.y); - LIBGUI_GL.glVertex2f(start.x, end.y); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Vertex2f(start.x, start.y); + DGL_Vertex2f( end.x, start.y); + DGL_Vertex2f( end.x, start.y); + DGL_Vertex2f( end.x, end.y); + DGL_Vertex2f( end.x, end.y); + DGL_Vertex2f(start.x, end.y); + DGL_Vertex2f(start.x, end.y); + DGL_Vertex2f(start.x, start.y); + DGL_End(); } while ((hedge = &hedge->next()) != base); } static int drawCellLines(Blockmap const &bmap, BlockmapCell const &cell, void *) { - LIBGUI_GL.glBegin(GL_LINES); + DGL_Begin(DGL_LINES); bmap.forAllInCell(cell, [] (void *object) { Line &line = *(Line *)object; @@ -138,13 +138,13 @@ } return LoopContinue; }); - LIBGUI_GL.glEnd(); + DGL_End(); return false; // Continue iteration. } static int drawCellPolyobjs(Blockmap const &bmap, BlockmapCell const &cell, void *context) { - LIBGUI_GL.glBegin(GL_LINES); + DGL_Begin(DGL_LINES); bmap.forAllInCell(cell, [&context] (void *object) { Polyobj &pob = *(Polyobj *)object; @@ -158,13 +158,13 @@ } return LoopContinue; }); - LIBGUI_GL.glEnd(); + DGL_End(); return false; // Continue iteration. } static int drawCellMobjs(Blockmap const &bmap, BlockmapCell const &cell, void *) { - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); bmap.forAllInCell(cell, [] (void *object) { mobj_t &mob = *(mobj_t *)object; @@ -175,7 +175,7 @@ } return LoopContinue; }); - LIBGUI_GL.glEnd(); + DGL_End(); return false; // Continue iteration. } @@ -200,57 +200,57 @@ // Scale modelview matrix so we can express cell geometry // using a cell-sized unit coordinate space. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glScalef(bmap.cellSize(), bmap.cellSize(), 1); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Scalef(bmap.cellSize(), bmap.cellSize(), 1); /* * Draw the translucent quad which represents the "used" cells. */ - LIBGUI_GL.glColor4f(.25f, .25f, .25f, .66f); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glVertex2f(0, 0); - LIBGUI_GL.glVertex2f(dimensions.x, 0); - LIBGUI_GL.glVertex2f(dimensions.x, dimensions.y); - LIBGUI_GL.glVertex2f(0, dimensions.y); - LIBGUI_GL.glEnd(); + DGL_Color4f(.25f, .25f, .25f, .66f); + DGL_Begin(DGL_QUADS); + DGL_Vertex2f(0, 0); + DGL_Vertex2f(dimensions.x, 0); + DGL_Vertex2f(dimensions.x, dimensions.y); + DGL_Vertex2f(0, dimensions.y); + DGL_End(); /* * Draw the "null cells" over the top. */ - LIBGUI_GL.glColor4f(0, 0, 0, .95f); + DGL_Color4f(0, 0, 0, .95f); BlockmapCell cell; for (cell.y = 0; cell.y < dimensions.y; ++cell.y) for (cell.x = 0; cell.x < dimensions.x; ++cell.x) { if (bmap.cellElementCount(cell)) continue; - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glVertex2f(cell.x, cell.y); - LIBGUI_GL.glVertex2f(cell.x + 1, cell.y); - LIBGUI_GL.glVertex2f(cell.x + 1, cell.y + 1); - LIBGUI_GL.glVertex2f(cell.x, cell.y + 1); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_Vertex2f(cell.x, cell.y); + DGL_Vertex2f(cell.x + 1, cell.y); + DGL_Vertex2f(cell.x + 1, cell.y + 1); + DGL_Vertex2f(cell.x, cell.y + 1); + DGL_End(); } // Restore previous GL state. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } static void drawCellInfo(Vector2d const &origin_, char const *info) { - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); FR_SetShadowStrength(UI_SHADOW_STRENGTH); - Size2Raw size(16 + FR_TextWidth(info), - 16 + FR_SingleLineHeight(info)); + Size2Raw size = {{{16 + FR_TextWidth(info), + 16 + FR_SingleLineHeight(info)}}}; - Point2Raw origin(origin_.x, origin_.y); + Point2Raw origin = {{{int(origin_.x), int(origin_.y)}}}; origin.x -= size.width / 2; //UI_GradientEx(&origin, &size, 6, UI_Color(UIC_BG_MEDIUM), UI_Color(UIC_BG_LIGHT), .5f, .5f); //UI_DrawRectEx(&origin, &size, 6, false, UI_Color(UIC_BRD_HI), NULL, .5f, -1); @@ -260,14 +260,14 @@ UI_SetColor(UI_Color(UIC_TEXT)); UI_TextOutEx2(info, &origin, UI_Color(UIC_TITLE), 1, ALIGN_LEFT, DTF_ONLY_SHADOW); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } static void drawBlockmapInfo(Vector2d const &origin_, Blockmap const &blockmap) { - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); - Point2Raw origin(origin_.x, origin_.y); + Point2Raw origin = {{{int(origin_.x), int(origin_.y)}}}; FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); @@ -306,7 +306,7 @@ blockmap.bounds().maxX, blockmap.bounds().maxY); UI_TextOutEx2(buf, &origin, UI_Color(UIC_TEXT), 1, ALIGN_LEFT, DTF_ONLY_SHADOW); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } static void drawCellInfoBox(Vector2d const &origin, Blockmap const &blockmap, @@ -358,13 +358,13 @@ if (followMobj) { // Orient on the center of the followed Mobj. - LIBGUI_GL.glTranslated(-(vCell.x * cellDimensions.x), -(vCell.y * cellDimensions.y), 0); + DGL_Translatef(-(vCell.x * cellDimensions.x), -(vCell.y * cellDimensions.y), 0); } else { // Orient on center of the Blockmap. - LIBGUI_GL.glTranslated(-(cellDimensions.x * dimensions.x)/2, - -(cellDimensions.y * dimensions.y)/2, 0); + DGL_Translatef(-(cellDimensions.x * dimensions.x)/2, + -(cellDimensions.y * dimensions.y)/2, 0); } // First we'll draw a background showing the "null" cells. @@ -372,7 +372,7 @@ if (followMobj) { // Highlight cells the followed Mobj "touches". - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); BlockmapCell cell; for (cell.y = vCellBlock.min.y; cell.y < vCellBlock.max.y; ++cell.y) @@ -381,24 +381,24 @@ if (cell == vCell) { // The cell the followed Mobj is actually in. - LIBGUI_GL.glColor4f(.66f, .66f, 1, .66f); + DGL_Color4f(.66f, .66f, 1, .66f); } else { // A cell within the followed Mobj's extended collision range. - LIBGUI_GL.glColor4f(.33f, .33f, .66f, .33f); + DGL_Color4f(.33f, .33f, .66f, .33f); } Vector2d const start = cellDimensions * cell; Vector2d const end = start + cellDimensions; - LIBGUI_GL.glVertex2d(start.x, start.y); - LIBGUI_GL.glVertex2d( end.x, start.y); - LIBGUI_GL.glVertex2d( end.x, end.y); - LIBGUI_GL.glVertex2d(start.x, end.y); + DGL_Vertex2f(start.x, start.y); + DGL_Vertex2f( end.x, start.y); + DGL_Vertex2f( end.x, end.y); + DGL_Vertex2f(start.x, end.y); } - LIBGUI_GL.glEnd(); + DGL_End(); } /** @@ -406,23 +406,23 @@ * @note Gridmap uses a cell unit size of [width:1,height:1], so we need to * scale it up so it aligns correctly. */ - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glScaled(cellDimensions.x, cellDimensions.y, 1); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Scalef(cellDimensions.x, cellDimensions.y, 1); bmap.drawDebugVisual(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); /* * Draw the blockmap-linked data. * Translate the modelview matrix so that objects can be drawn using * the map space coordinates directly. */ - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glTranslated(-bmap.origin().x, -bmap.origin().y, 0); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Translatef(-bmap.origin().x, -bmap.origin().y, 0); if (cellDrawer) { @@ -435,7 +435,7 @@ // First, the cells outside the "touch" range (crimson). validCount++; - LIBGUI_GL.glColor4f(.33f, 0, 0, .75f); + DGL_Color4f(.33f, 0, 0, .75f); BlockmapCell cell; for (cell.y = 0; cell.y < dimensions.y; ++cell.y) for (cell.x = 0; cell.x < dimensions.x; ++cell.x) @@ -452,7 +452,7 @@ // Next, the cells within the "touch" range (orange). validCount++; - LIBGUI_GL.glColor3f(1, .5f, 0); + DGL_Color3f(1, .5f, 0); for (cell.y = vCellBlock.min.y; cell.y < vCellBlock.max.y; ++cell.y) for (cell.x = vCellBlock.min.x; cell.x < vCellBlock.max.x; ++cell.x) { @@ -464,7 +464,7 @@ // Lastly, the cell the followed Mobj is in (yellow). validCount++; - LIBGUI_GL.glColor3f(1, 1, 0); + DGL_Color3f(1, 1, 0); if (bmap.cellElementCount(vCell)) { cellDrawer(bmap, vCell, 0/*no params*/); @@ -474,7 +474,7 @@ { // Draw all cells without color coding. validCount++; - LIBGUI_GL.glColor4f(.33f, 0, 0, .75f); + DGL_Color4f(.33f, 0, 0, .75f); BlockmapCell cell; for (cell.y = 0; cell.y < dimensions.y; ++cell.y) for (cell.x = 0; cell.x < dimensions.x; ++cell.x) @@ -492,15 +492,15 @@ if (followMobj) { validCount++; - LIBGUI_GL.glColor3f(0, 1, 0); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Color3f(0, 1, 0); + DGL_Begin(DGL_QUADS); drawMobj(*followMobj); - LIBGUI_GL.glEnd(); + DGL_End(); } // Undo the map coordinate space translation. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } void Rend_BlockmapDebug() @@ -547,16 +547,16 @@ /* * Draw the blockmap. */ - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); // Orient on the center of the window. - LIBGUI_GL.glTranslatef((DENG_GAMEVIEW_WIDTH / 2), (DENG_GAMEVIEW_HEIGHT / 2), 0); + DGL_Translatef((DENG_GAMEVIEW_WIDTH / 2), (DENG_GAMEVIEW_HEIGHT / 2), 0); // Uniform scaling factor for this visual. float scale = bmapDebugSize / de::max(DENG_GAMEVIEW_HEIGHT / 100, 1); - LIBGUI_GL.glScalef(scale, -scale, 1); + DGL_Scalef(scale, -scale, 1); // If possible we'll tailor what we draw relative to the viewPlayer. mobj_t *followMobj = 0; @@ -568,16 +568,16 @@ // Draw! drawBlockmap(*blockmap, followMobj, cellDrawer); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); /* * Draw HUD info. */ - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); if (followMobj) { @@ -595,6 +595,6 @@ drawBlockmapInfo(Vector2d(DENG_GAMEVIEW_WIDTH - 10, DENG_GAMEVIEW_HEIGHT - 10), *blockmap); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/cameralensfx.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/cameralensfx.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/cameralensfx.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/cameralensfx.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -116,8 +116,7 @@ // Now that we've resolved multisampling, further rendering must be done without it. GLState::push() - .setTarget(player.viewCompositor().gameView().resolvedFramebuffer()) - .apply(); + .setTarget(player.viewCompositor().gameView().resolvedFramebuffer()); auto const &effects = player.fxStack().effects; @@ -145,7 +144,7 @@ effects.at(i)->endFrame(); } - GLState::pop().apply(); + GLState::pop(); } void LensFx_MarkLightVisibleInFrame(IPointLightSource const &lightSource) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/drawlist.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/drawlist.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/drawlist.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/drawlist.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -118,17 +118,14 @@ { DENG2_ASSERT(buffer); - auto &GL = LIBGUI_GL; - if (conditions & SetLightEnv) { // Use the correct texture and color for the light. - GL.glActiveTexture((conditions & SetLightEnv0)? GL_TEXTURE0 : GL_TEXTURE1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, (conditions & SetLightEnv0)? 0 : 1); GL_BindTextureUnmanaged(!renderTextures? 0 : primitive.modTexture, gl::ClampToEdge, gl::ClampToEdge); - Vector4f modColor4(primitive.modColor, 0.f); - GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, modColor4.constPtr()); + DGL_SetModulationColor(Vector4f(primitive.modColor, 0.f)); } if (conditions & SetMatrixTexture) @@ -136,24 +133,24 @@ // Primitive-specific texture translation & scale. if (conditions & SetMatrixTexture0) { - GL.glActiveTexture(GL_TEXTURE0); - GL.glMatrixMode(GL_TEXTURE); - GL.glPushMatrix(); - GL.glLoadIdentity(); - GL.glTranslatef(primitive.texOffset.x * primitive.texScale.x, - primitive.texOffset.y * primitive.texScale.y, 1); - GL.glScalef(primitive.texScale.x, primitive.texScale.y, 1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Translatef(primitive.texOffset.x * primitive.texScale.x, + primitive.texOffset.y * primitive.texScale.y, 1); + DGL_Scalef(primitive.texScale.x, primitive.texScale.y, 1); } if (conditions & SetMatrixTexture1) { - GL.glActiveTexture(GL_TEXTURE1); - GL.glMatrixMode(GL_TEXTURE); - GL.glPushMatrix(); - GL.glLoadIdentity(); - GL.glTranslatef(primitive.texOffset.x * primitive.texScale.x, - primitive.texOffset.y * primitive.texScale.y, 1); - GL.glScalef(primitive.texScale.x, primitive.texScale.y, 1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Translatef(primitive.texOffset.x * primitive.texScale.x, + primitive.texOffset.y * primitive.texScale.y, 1); + DGL_Scalef(primitive.texScale.x, primitive.texScale.y, 1); } } @@ -162,24 +159,24 @@ // Primitive-specific texture translation & scale. if (conditions & SetMatrixDTexture0) { - GL.glActiveTexture(GL_TEXTURE0); - GL.glMatrixMode(GL_TEXTURE); - GL.glPushMatrix(); - GL.glLoadIdentity(); - GL.glTranslatef(primitive.detailTexOffset.x * primitive.detailTexScale.x, - primitive.detailTexOffset.y * primitive.detailTexScale.y, 1); - GL.glScalef(primitive.detailTexScale.x, primitive.detailTexScale.y, 1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Translatef(primitive.detailTexOffset.x * primitive.detailTexScale.x, + primitive.detailTexOffset.y * primitive.detailTexScale.y, 1); + DGL_Scalef(primitive.detailTexScale.x, primitive.detailTexScale.y, 1); } if (conditions & SetMatrixDTexture1) { - GL.glActiveTexture(GL_TEXTURE1); - GL.glMatrixMode(GL_TEXTURE); - GL.glPushMatrix(); - GL.glLoadIdentity(); - GL.glTranslatef(primitive.detailTexOffset.x * primitive.detailTexScale.x, - primitive.detailTexOffset.y * primitive.detailTexScale.y, 1); - GL.glScalef(primitive.detailTexScale.x, primitive.detailTexScale.y, 1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Translatef(primitive.detailTexOffset.x * primitive.detailTexScale.x, + primitive.detailTexOffset.y * primitive.detailTexScale.y, 1); + DGL_Scalef(primitive.detailTexScale.x, primitive.detailTexScale.y, 1); } } @@ -189,12 +186,12 @@ GL_BlendMode(blendmode_t(primitive.flags_blendMode & BLEND_MODE_MASK)); } - GL.glBegin(primitive.type == gl::TriangleStrip? GL_TRIANGLE_STRIP : GL_TRIANGLE_FAN); + DGL_Begin(primitive.type == gl::TriangleStrip? DGL_TRIANGLE_STRIP : DGL_TRIANGLE_FAN); for (duint i = 0; i < numIndices; ++i) { duint const index = indices[i]; - for (dint k = 0; k < numTexUnits; ++k) + for (dint k = 0; k < MAX_TEX_UNITS; ++k) { Vector2f const *tc = nullptr; // No mapping. switch (texUnitMap[k]) @@ -208,35 +205,35 @@ if (tc) { - GL.glMultiTexCoord2f(GL_TEXTURE0 + k, tc[index].x, tc[index].y); + DGL_TexCoord2f(k, tc[index].x, tc[index].y); } } if (!(conditions & NoColor)) { Vector4ub const &color = buffer->colorCoords[index]; - GL.glColor4ub(color.x, color.y, color.z, color.w); + DGL_Color4ub(color.x, color.y, color.z, color.w); } Vector3f const &pos = buffer->posCoords[index]; - GL.glVertex3f(pos.x, pos.z, pos.y); + DGL_Vertex3f(pos.x, pos.z, pos.y); } - GL.glEnd(); + DGL_End(); // Restore the texture matrix if changed. if (conditions & SetMatrixDTexture) { if (conditions & SetMatrixDTexture0) { - GL.glActiveTexture(GL_TEXTURE0); - GL.glMatrixMode(GL_TEXTURE); - GL.glPopMatrix(); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } if (conditions & SetMatrixDTexture1) { - GL.glActiveTexture(GL_TEXTURE1); - GL.glMatrixMode(GL_TEXTURE); - GL.glPopMatrix(); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } } @@ -244,15 +241,15 @@ { if (conditions & SetMatrixTexture0) { - GL.glActiveTexture(GL_TEXTURE0); - GL.glMatrixMode(GL_TEXTURE); - GL.glPopMatrix(); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } if (conditions & SetMatrixTexture1) { - GL.glActiveTexture(GL_TEXTURE1); - GL.glMatrixMode(GL_TEXTURE); - GL.glPopMatrix(); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } } } @@ -373,15 +370,14 @@ if (spec.unit(TU_INTER).hasTexture()) { // Blend between two textures, modulate with primary color. - DENG2_ASSERT(numTexUnits >= 2); GL_SelectTexUnits(2); GL_BindTo(spec.unit(TU_PRIMARY), 0); GL_BindTo(spec.unit(TU_INTER ), 1); - GL_ModulateTexture(2); + DGL_ModulateTexture(2); dfloat color[4] = { 0, 0, 0, spec.unit(TU_INTER).opacity }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); + DGL_SetModulationColor(color); } else if (!spec.unit(TU_PRIMARY).hasTexture()) { @@ -393,7 +389,7 @@ // Normal modulation. GL_SelectTexUnits(1); GL_Bind(spec.unit(TU_PRIMARY)); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } if (spec.unit(TU_INTER).hasTexture()) @@ -431,14 +427,13 @@ return Skip; } - DENG2_ASSERT(numTexUnits >= 2); GL_SelectTexUnits(2); GL_BindTo(spec.unit(TU_PRIMARY), 0); GL_BindTo(spec.unit(TU_INTER ), 1); - GL_ModulateTexture(2); + DGL_ModulateTexture(2); dfloat color[4] = { 0, 0, 0, spec.unit(TU_INTER).opacity }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); + DGL_SetModulationColor(color); return SetMatrixTexture0 | SetMatrixTexture1; } case DM_BLENDED_FIRST_LIGHT: @@ -485,21 +480,20 @@ { // Mode 3 actually just disables the second texture stage, // which would modulate with primary color. - DENG2_ASSERT(numTexUnits >= 2); GL_SelectTexUnits(2); GL_BindTo(spec.unit(TU_PRIMARY), 0); GL_BindTo(spec.unit(TU_INTER ), 1); - GL_ModulateTexture(3); + DGL_ModulateTexture(3); dfloat color[4] = { 0, 0, 0, spec.unit(TU_INTER).opacity }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); + DGL_SetModulationColor(color); // Render all geometry. return SetMatrixTexture0 | SetMatrixTexture1; } // No modulation at all. GL_SelectTexUnits(1); GL_Bind(spec.unit(TU_PRIMARY)); - GL_ModulateTexture(0); + DGL_ModulateTexture(0); if (mode == DM_MOD_TEXTURE_MANY_LIGHTS) { return SetMatrixTexture0 | ManyLights; @@ -518,7 +512,7 @@ if (spec.unit(TU_PRIMARY_DETAIL).hasTexture()) { GL_SelectTexUnits(2); - GL_ModulateTexture(9); // Tex+Detail, no color. + DGL_ModulateTexture(9); // Tex+Detail, no color. GL_BindTo(spec.unit(TU_PRIMARY ), 0); GL_BindTo(spec.unit(TU_PRIMARY_DETAIL), 1); return SetMatrixTexture0 | SetMatrixDTexture1; @@ -526,7 +520,7 @@ else { GL_SelectTexUnits(1); - GL_ModulateTexture(0); + DGL_ModulateTexture(0); GL_Bind(spec.unit(TU_PRIMARY)); return SetMatrixTexture0; } @@ -554,7 +548,7 @@ if (spec.unit(TU_PRIMARY_DETAIL).hasTexture()) { GL_SelectTexUnits(2); - GL_ModulateTexture(8); + DGL_ModulateTexture(8); GL_BindTo(spec.unit(TU_PRIMARY ), 0); GL_BindTo(spec.unit(TU_PRIMARY_DETAIL), 1); return SetMatrixTexture0 | SetMatrixDTexture1; @@ -563,7 +557,7 @@ { // Normal modulation. GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); GL_Bind(spec.unit(TU_PRIMARY)); return SetMatrixTexture0; } @@ -588,7 +582,7 @@ GL_BindTo(spec.unit(TU_INTER_DETAIL ), 1); dfloat color[4] = { 0, 0, 0, spec.unit(TU_INTER_DETAIL).opacity }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); + DGL_SetModulationColor(color); return SetMatrixDTexture0 | SetMatrixDTexture1; } case DM_SHADOW: @@ -606,13 +600,13 @@ if (!spec.unit(TU_PRIMARY).hasTexture()) { // Apply a modelview shift. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // Scale towards the viewpoint to avoid Z-fighting. - LIBGUI_GL.glTranslatef(vOrigin.x, vOrigin.y, vOrigin.z); - LIBGUI_GL.glScalef(.99f, .99f, .99f); - LIBGUI_GL.glTranslatef(-vOrigin.x, -vOrigin.y, -vOrigin.z); + DGL_Translatef(vOrigin.x, vOrigin.y, vOrigin.z); + DGL_Scalef(.99f, .99f, .99f); + DGL_Translatef(-vOrigin.x, -vOrigin.y, -vOrigin.z); } return 0; @@ -625,7 +619,7 @@ // The intertex holds the info for the mask texture. GL_BindTo(spec.unit(TU_INTER), 1); dfloat color[4] = { 0, 0, 0, 1 }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color); + DGL_SetModulationColor(color); } // Intentional fall-through. @@ -671,7 +665,7 @@ if (spec.unit(TU_INTER).hasTexture()) { GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } break; @@ -679,7 +673,7 @@ if (spec.unit(TU_INTER).hasTexture()) { GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } break; @@ -689,11 +683,11 @@ if (spec.unit(TU_INTER).hasTexture()) { GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } else if (mode != DM_BLENDED_MOD_TEXTURE) { - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } break; @@ -703,11 +697,11 @@ if (spec.unit(TU_PRIMARY_DETAIL).hasTexture()) { GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } else { - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } } break; @@ -717,7 +711,7 @@ spec.unit(TU_PRIMARY_DETAIL).hasTexture()) { GL_SelectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } break; @@ -725,8 +719,8 @@ if (!spec.unit(TU_PRIMARY).hasTexture()) { // Restore original modelview matrix. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } break; @@ -821,7 +815,7 @@ { using Parm = PrimitiveParams; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Setup GL state for this list. @@ -911,7 +905,7 @@ d->last = nullptr; } -void DrawList::reserveSpace(DrawList::Indices &indices, uint count) // static +void DrawList::reserveSpace(DrawList::Indices &indices, uint count) // static { if (indices.size() < int(count)) indices.resize(int(count)); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/bloom.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/bloom.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/bloom.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/bloom.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -138,8 +138,7 @@ break; } - - GLState::pop().apply(); + GLState::pop(); } /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/colorfilter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/colorfilter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/colorfilter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/colorfilter.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -20,6 +20,7 @@ #include "render/fx/colorfilter.h" #include "gl/gl_draw.h" +#include "api_gl.h" #include #include @@ -63,13 +64,13 @@ { Rectanglei const rect = viewRect(); - LIBGUI_GL.glColor4f(filterColor.x, filterColor.y, filterColor.z, filterColor.w); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glVertex2f(rect.topLeft.x, rect.topLeft.y); - LIBGUI_GL.glVertex2f(rect.topRight().x, rect.topRight().y); - LIBGUI_GL.glVertex2f(rect.bottomRight.x, rect.bottomRight.y); - LIBGUI_GL.glVertex2f(rect.bottomLeft().x, rect.bottomLeft().y); - LIBGUI_GL.glEnd(); + DGL_Color4f(filterColor.x, filterColor.y, filterColor.z, filterColor.w); + DGL_Begin(DGL_QUADS); + DGL_Vertex2f(rect.topLeft.x, rect.topLeft.y); + DGL_Vertex2f(rect.topRight().x, rect.topRight().y); + DGL_Vertex2f(rect.bottomRight.x, rect.bottomRight.y); + DGL_Vertex2f(rect.bottomLeft().x, rect.bottomLeft().y); + DGL_End(); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/lensflares.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/lensflares.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/lensflares.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/lensflares.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -72,7 +72,7 @@ { try { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); images.addFromInfo(App::rootFolder().locate("/packs/feature.lensflares/images.dei")); @@ -517,7 +517,7 @@ d->uViewUnit = Vector2f(aspect, 1.f); d->uPixelAsUv = Vector2f(1.f / window.pixelWidth(), 1.f / window.pixelHeight()); - d->uMvpMatrix = Viewer_Matrix(); //GL_GetProjectionMatrix() * Rend_GetModelViewMatrix(console()); + d->uMvpMatrix = Viewer_Matrix(); //Rend_GetProjectionMatrix() * Rend_GetModelViewMatrix(console()); DENG2_ASSERT(console() == displayPlayer); //DENG2_ASSERT(viewPlayer - ddPlayers == displayPlayer); @@ -550,7 +550,7 @@ d->drawable.draw(); - GLState::pop().apply(); + GLState::pop(); } void LensFlares::consoleRegister() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/vignette.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/vignette.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/fx/vignette.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/fx/vignette.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -77,26 +77,26 @@ GL_BindTextureUnmanaged(GL_PrepareLSTexture(LST_CAMERA_VIGNETTE), gl::Repeat, gl::ClampToEdge); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); - LIBGUI_GL.glBegin(GL_TRIANGLE_STRIP); + DGL_Begin(DGL_TRIANGLE_STRIP); for (i = 0; i <= DIVS; ++i) { float ang = (float)(2 * de::PI * i) / (float)DIVS; float dx = cos(ang); float dy = sin(ang); - LIBGUI_GL.glColor4f(0, 0, 0, alpha); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex2f(cx + outer * dx, cy + outer * dy); - - LIBGUI_GL.glColor4f(0, 0, 0, 0); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex2f(cx + inner * dx, cy + inner * dy); + DGL_Color4f(0, 0, 0, alpha); + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex2f(cx + outer * dx, cy + outer * dy); + + DGL_Color4f(0, 0, 0, 0); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex2f(cx + inner * dx, cy + inner * dy); } - LIBGUI_GL.glEnd(); + DGL_End(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } Vignette::Vignette(int console) : ConsoleEffect(console) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/model.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/model.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/model.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/model.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -31,7 +31,7 @@ // Parse timeline events. if (def.hasSubrecord(DEF_TIMELINE)) { - timeline = new Scheduler; + timeline = new Timeline; timeline->addFromInfo(def.subrecord(DEF_TIMELINE)); } else if (def.hasMember(DEF_TIMELINE)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/modelloader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/modelloader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/modelloader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/modelloader.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -33,36 +33,38 @@ using namespace de; -String const ModelLoader::DEF_ANIMATION("animation"); -String const ModelLoader::DEF_MATERIAL ("material"); -String const ModelLoader::DEF_PASS ("pass"); -String const ModelLoader::DEF_RENDER ("render"); - -static String const DEF_ALIGNMENT_PITCH("alignment.pitch"); -static String const DEF_ALIGNMENT_YAW ("alignment.yaw"); -static String const DEF_AUTOSCALE ("autoscale"); -static String const DEF_BLENDFUNC ("blendFunc"); -static String const DEF_BLENDOP ("blendOp"); -static String const DEF_DEPTHFUNC ("depthFunc"); -static String const DEF_DEPTHWRITE ("depthWrite"); -static String const DEF_FRONT_VECTOR ("front"); -static String const DEF_MESHES ("meshes"); -static String const DEF_MIRROR ("mirror"); -static String const DEF_OFFSET ("offset"); -static String const DEF_SEQUENCE ("sequence"); -static String const DEF_SHADER ("shader"); -static String const DEF_STATE ("state"); -static String const DEF_TEXTURE_MAPPING("textureMapping"); -static String const DEF_TIMELINE ("timeline"); -static String const DEF_UP_VECTOR ("up"); -static String const DEF_VARIANT ("variant"); +String const ModelLoader::DEF_ANIMATION ("animation"); +String const ModelLoader::DEF_MATERIAL ("material"); +String const ModelLoader::DEF_PASS ("pass"); +String const ModelLoader::DEF_RENDER ("render"); + +static String const DEF_ALIGNMENT_PITCH ("alignment.pitch"); +static String const DEF_ALIGNMENT_YAW ("alignment.yaw"); +static String const DEF_AUTOSCALE ("autoscale"); +static String const DEF_BLENDFUNC ("blendFunc"); +static String const DEF_BLENDOP ("blendOp"); +static String const DEF_DEPTHFUNC ("depthFunc"); +static String const DEF_DEPTHWRITE ("depthWrite"); +static String const DEF_FRONT_VECTOR ("front"); +static String const DEF_MESHES ("meshes"); +static String const DEF_MIRROR ("mirror"); +static String const DEF_OFFSET ("offset"); +static String const DEF_SEQUENCE ("sequence"); +static String const DEF_SHADER ("shader"); +static String const DEF_STATE ("state"); +static String const DEF_TEXTURE_MAPPING ("textureMapping"); +static String const DEF_TIMELINE ("timeline"); +static String const DEF_UP_VECTOR ("up"); +static String const DEF_VARIANT ("variant"); + +static String const SHADER_DEFAULT ("model.skeletal.generic"); +static String const MATERIAL_DEFAULT ("default"); + +static String const VAR_U_MAP_TIME ("uMapTime"); +static String const VAR_U_PROJECTION_MATRIX ("uProjectionMatrix"); +static String const VAR_U_VIEW_MATRIX ("uViewMatrix"); -static String const SHADER_DEFAULT ("model.skeletal.generic"); -static String const MATERIAL_DEFAULT ("default"); - -static String const VAR_U_MAP_TIME ("uMapTime"); - -static Atlas::Size const MAX_ATLAS_SIZE(8192, 8192); +static Atlas::Size const MAX_ATLAS_SIZE (8192, 8192); DENG2_PIMPL(ModelLoader) , DENG2_OBSERVES(filesys::AssetObserver, Availability) @@ -123,12 +125,16 @@ // request another one. loadProgram(SHADER_DEFAULT); +#if defined (DENG_HAVE_BUSYRUNNER) ClientApp::busyRunner().audienceForDeferredGLTask() += this; +#endif } void deinit() { +#if defined (DENG_HAVE_BUSYRUNNER) ClientApp::busyRunner().audienceForDeferredGLTask() -= this; +#endif // GL resources must be accessed from the main thread only. bank.unloadAll(Bank::ImmediatelyInCurrentThread); @@ -200,7 +206,7 @@ } /** - * Initializes one or more uninitializes models for rendering. + * Initializes one or more uninitialized models for rendering. * Must be called from the main thread. * * @param maxCount Maximum number of models to initialize. @@ -267,10 +273,20 @@ i->newProgramCreated(*prog); } + auto &render = ClientApp::renderSystem(); + // Built-in special uniforms. if (prog->def->hasMember(VAR_U_MAP_TIME)) { - *prog << ClientApp::renderSystem().uMapTime(); + *prog << render.uMapTime(); + } + if (prog->def->hasMember(VAR_U_PROJECTION_MATRIX)) + { + *prog << render.uProjectionMatrix(); + } + if (prog->def->hasMember(VAR_U_VIEW_MATRIX)) + { + *prog << render.uViewMatrix(); } programs[name] = prog.get(); @@ -445,31 +461,41 @@ model.materialIndexForName.insert(MATERIAL_DEFAULT, 0); if (asset.has(DEF_MATERIAL)) { - asset.subrecord(DEF_MATERIAL).forSubrecords( - [this, &model] (String const &blockName, Record const &block) - { - if (ScriptedInfo::blockType(block) == DEF_VARIANT) - { - String const materialName = blockName; - if (!model.materialIndexForName.contains(materialName)) + asset.subrecord(DEF_MATERIAL) + .forSubrecords([this, &model](String const &blockName, Record const &block) { + try { - // Add a new material. - model.materialIndexForName.insert(materialName, model.addMaterial()); + if (ScriptedInfo::blockType(block) == DEF_VARIANT) + { + String const materialName = blockName; + if (!model.materialIndexForName.contains(materialName)) + { + // Add a new material. + model.materialIndexForName.insert(materialName, + model.addMaterial()); + } + block.forSubrecords([this, &model, &materialName]( + String const &matName, Record const &matDef) { + setupMaterial(model, + matName, + model.materialIndexForName[materialName], + matDef); + return LoopContinue; + }); + } + else + { + // The default material. + setupMaterial(model, blockName, 0, block); + } } - block.forSubrecords([this, &model, &materialName] - (String const &matName, Record const &matDef) + catch (const Error &er) { - setupMaterial(model, matName, model.materialIndexForName[materialName], matDef); - return LoopContinue; - }); - } - else - { - // The default material. - setupMaterial(model, blockName, 0, block); - } - return LoopContinue; - }); + LOG_GL_ERROR("Material variant \"%s\" is invalid: %s") + << blockName << er.asText(); + } + return LoopContinue; + }); } // Set up the animation sequences for states. @@ -504,7 +530,7 @@ auto timelines = ScriptedInfo::subrecordsOfType(DEF_TIMELINE, asset.subrecord(DEF_ANIMATION)); DENG2_FOR_EACH_CONST(Record::Subrecords, timeline, timelines) { - Scheduler *scheduler = new Scheduler; + Timeline *scheduler = new Timeline; scheduler->addFromInfo(*timeline.value()); model.timelines[timeline.key()] = scheduler; } @@ -535,6 +561,12 @@ int meshId = identifierFromText(value->asText(), [&model] (String const &text) { return model.meshId(text); }); + if (meshId < 0 || meshId >= model.meshCount()) + { + throw DefinitionError("ModelLoader::bankLoaded", + "Unknown mesh \"" + value->asText() + "\" in " + + ScriptedInfo::sourceLocation(def)); + } pass.meshes.setBit(meshId, true); } @@ -635,11 +667,16 @@ duint materialIndex, Record const &matDef) { - ModelDrawable::MeshId const mesh { - duint(identifierFromText(meshName, [&model] (String const &text) { - return model.meshId(text); })), - materialIndex - }; + int mid = identifierFromText(meshName, + [&model](const String &text) { return model.meshId(text); }); + if (mid < 0 || mid >= model.meshCount()) + { + throw DefinitionError("ModelLoader::setupMaterial", + "Mesh \"" + meshName + "\" not found in " + + ScriptedInfo::sourceLocation(matDef)); + } + + const ModelDrawable::MeshId mesh{duint(mid), materialIndex}; setupMaterialTexture(model, mesh, matDef, QStringLiteral("diffuseMap"), ModelDrawable::Diffuse); setupMaterialTexture(model, mesh, matDef, QStringLiteral("normalMap"), ModelDrawable::Normals); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/modelrenderer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/modelrenderer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/modelrenderer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/modelrenderer.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -30,10 +30,12 @@ #include "world/clientmobjthinkerdata.h" #include "world/convexsubspace.h" #include "clientapp.h" +#include "world/clientserverworld.h" #include #include #include +#include using namespace de; @@ -45,6 +47,7 @@ render::ModelLoader loader; GLUniform uMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; + GLUniform uWorldMatrix { "uWorldMatrix", GLUniform::Mat4 }; // included in uMvpMatrix GLUniform uReflectionMatrix { "uReflectionMatrix", GLUniform::Mat4 }; GLUniform uTex { "uTex", GLUniform::Sampler2D }; GLUniform uReflectionTex { "uReflectionTex", GLUniform::SamplerCube }; @@ -80,6 +83,7 @@ { program << uMvpMatrix << uReflectionMatrix + << uWorldMatrix << uTex << uReflectionTex << uEyePos @@ -138,28 +142,6 @@ lightCount++; } - void setupFog() - { - if (fogParams.usingFog) - { - uFogColor = Vector4f(fogParams.fogColor[0], - fogParams.fogColor[1], - fogParams.fogColor[2], - 1.f); - - Rangef const depthPlanes = GL_DepthClipRange(); - float const fogDepth = fogParams.fogEnd - fogParams.fogStart; - uFogRange = Vector4f(fogParams.fogStart, - fogDepth, - depthPlanes.start, - depthPlanes.end); - } - else - { - uFogColor = Vector4f(); - } - } - void setupPose(Vector3d const &modelWorldOrigin, Vector3f const &modelOffset, float yawAngle, @@ -169,6 +151,8 @@ Vector3f const aspectCorrect(1.0f, 1.0f/1.2f, 1.0f); Vector3d origin = modelWorldOrigin + modelOffset * aspectCorrect; + // "local" == world space but with origin at model origin + Matrix4f modelToLocal = Matrix4f::rotate(-90 + yawAngle, Vector3f(0, 1, 0) /* vertical axis for yaw */) * Matrix4f::rotate(pitchAngle, Vector3f(1, 0, 0)); @@ -183,28 +167,33 @@ modelToLocal = modelToLocal * (*preModelToLocal); } - Matrix4f localToView = - Viewer_Matrix() * + Matrix4f const localToWorld = Matrix4f::translate(origin) * Matrix4f::scale(aspectCorrect); // Inverse aspect correction. + Matrix4f const localToScreen = Viewer_Matrix() * localToWorld; + + uWorldMatrix = localToWorld * modelToLocal; // Set up a suitable matrix for the pose. - setTransformation(relativePos, modelToLocal, localToView); + setTransformation(relativePos, modelToLocal, localToScreen); } /** * Sets up the transformation matrices. * + * "Local space" is the same as world space but relative to the object's origin. + * That is, (0,0,0) being the object's origin. + * * @param relativeEyePos Position of the eye in relation to object (in world space). * @param modelToLocal Transformation from model space to the object's local space * (object's local frame in world space). - * @param localToView Transformation from local space to projected view space. + * @param localToScreen Transformation from local space to screen (projected 2D) space. */ void setTransformation(Vector3f const &relativeEyePos, Matrix4f const &modelToLocal, - Matrix4f const &localToView) + Matrix4f const &localToScreen) { - uMvpMatrix = localToView * modelToLocal; + uMvpMatrix = localToScreen * modelToLocal; inverseLocal = modelToLocal.inverse(); uEyePos = inverseLocal * relativeEyePos; } @@ -231,7 +220,7 @@ template // generic to accommodate psprites and vispsprites void draw(Params const &p) { - setupFog(); + DGL_FogParams(uFogRange, uFogColor); uTex = static_cast(p.model->textures->atlas()); p.model->draw(&p.animator->appearance(), p.animator); @@ -307,7 +296,7 @@ // Draw the model using the current animation state. GLState::push().setCull(p.model->cull); d->draw(p); - GLState::pop().apply(); + GLState::pop(); } void ModelRenderer::render(vispsprite_t const &pspr, mobj_t const *playerMobj) @@ -334,7 +323,7 @@ GLState::push().setCull(p.model->cull); d->draw(p); - GLState::pop().apply(); + GLState::pop(); } //--------------------------------------------------------------------------------------- @@ -373,6 +362,54 @@ return playing.release(); } +static Value *Function_StateAnimator_StartSequence(Context &ctx, Function::ArgumentValues const &args) +{ + render::StateAnimator &anim = animatorInstance(ctx); + int animId = anim.animationId(args.at(0)->asText()); + if (animId >= 0) + { + int priority = args.at(1)->asInt(); + bool looping = args.at(2)->isTrue(); + String node = args.at(3)->asText(); + + anim.startAnimation(animId, priority, looping, node); + } + else + { + LOG_SCR_ERROR("%s has no animation \"%s\"") + << anim.objectNamespace().gets("ID") + << args.at(0)->asText(); + } + return nullptr; +} + +static Value *Function_StateAnimator_StartTimeline(Context &ctx, Function::ArgumentValues const &args) +{ + render::StateAnimator &anim = animatorInstance(ctx); + render::Model const &model = anim.model(); + String const timelineName = args.first()->asText(); + if (model.timelines.contains(timelineName)) + { + anim.scheduler().start(*model.timelines[timelineName], + &anim.objectNamespace(), + timelineName); + return new TextValue(timelineName); + } + else + { + LOG_SCR_ERROR("%s has no timeline \"%s\"") + << anim.objectNamespace().gets("ID") << timelineName; + } + return nullptr; +} + +static Value *Function_StateAnimator_StopTimeline(Context &ctx, Function::ArgumentValues const &args) +{ + render::StateAnimator &anim = animatorInstance(ctx); + anim.scheduler().stop(args.first()->asText()); + return nullptr; +} + void ModelRenderer::initBindings(Binder &binder, Record &module) // static { // StateAnimator @@ -380,6 +417,13 @@ Record &anim = module.addSubrecord("StateAnimator"); binder.init(anim) << DENG2_FUNC_NOARG(StateAnimator_Thing, "thing") - << DENG2_FUNC_NOARG(StateAnimator_PlayingSequences, "playingSequences"); + << DENG2_FUNC_NOARG(StateAnimator_PlayingSequences, "playingSequences") + << DENG2_FUNC_DEFS (StateAnimator_StartSequence, "startSequence", + "sequence" << "priority" << "looping" << "node", + Function::Defaults({ std::make_pair("priority", new NumberValue(0)), + std::make_pair("looping", new NumberValue(0)), + std::make_pair("node", new TextValue) })) + << DENG2_FUNC (StateAnimator_StartTimeline, "startTimeline", "name") + << DENG2_FUNC (StateAnimator_StopTimeline, "stopTimeline", "name"); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/playerweaponanimator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/playerweaponanimator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/playerweaponanimator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/playerweaponanimator.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -63,7 +63,7 @@ auto &model = modelBank().model(identifier); model.audienceForDeletion() += this; animator.reset(new StateAnimator(identifier, model)); - animator->setOwnerNamespace(player->info(), QStringLiteral("PLAYER")); + animator->setOwnerNamespace(player->info(), QStringLiteral("__player__")); } else { @@ -120,21 +120,21 @@ spr.data.model2.animator = d->animator.get(); // Use the plain bob values. - float bob[2] = { *(float *) gx.GetVariable(DD_PSPRITE_BOB_X), - *(float *) gx.GetVariable(DD_PSPRITE_BOB_Y) }; + float bob[2] = { *(float *) gx.GetPointer(DD_PSPRITE_BOB_X), + *(float *) gx.GetPointer(DD_PSPRITE_BOB_Y) }; Vector2f angles( /* yaw: */ bob[0] * weaponOffsetScale, /* pitch: */ (32 - bob[1]) * weaponOffsetScale * weaponOffsetScaleY / 1000.0f); - TimeDelta const span = 1.0 / Timer_TicksPerSecond(); + TimeSpan const span = 1.0 / Timer_TicksPerSecond(); d->angleOffset.setValueIfDifferentTarget(angles, span); spr.data.model2.yawAngleOffset = d->angleOffset.x; spr.data.model2.pitchAngleOffset = d->angleOffset.y; } -void PlayerWeaponAnimator::advanceTime(TimeDelta const &elapsed) +void PlayerWeaponAnimator::advanceTime(TimeSpan const &elapsed) { if (clientPaused) return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_draw.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_draw.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_draw.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_draw.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -223,30 +223,30 @@ Vector2i const origin = port->geometry.topLeft; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); // Scale from viewport space to fixed 320x200 space. int border; if(port->geometry.width() >= port->geometry.height()) { - LIBGUI_GL.glScalef(float(SCREENHEIGHT) / port->geometry.height(), - float(SCREENHEIGHT) / port->geometry.height(), 1); + DGL_Scalef(float(SCREENHEIGHT) / port->geometry.height(), + float(SCREENHEIGHT) / port->geometry.height(), 1); border = float(borderSize) / SCREENHEIGHT * port->geometry.height(); } else { - LIBGUI_GL.glScalef(float(SCREENWIDTH) / port->geometry.width(), - float(SCREENWIDTH) / port->geometry.width(), 1); + DGL_Scalef(float(SCREENWIDTH) / port->geometry.width(), + float(SCREENWIDTH) / port->geometry.width(), 1); border = float(borderSize) / SCREENWIDTH * port->geometry.width(); } - LIBGUI_GL.glColor4f(1, 1, 1, 1); + DGL_Color4f(1, 1, 1, 1); // View background. try @@ -277,8 +277,8 @@ R_DrawPatchTiled(borderTexture(BG_RIGHT), origin.x + vd->window.topRight().x, origin.y + vd->window.topRight().y, border, vd->window.height(), gl::ClampToEdge, gl::Repeat); } - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); if(border) { @@ -288,5 +288,5 @@ R_DrawPatch(borderTexture(BG_BOTTOMLEFT), origin.x + vd->window.bottomLeft().x - border, origin.y + vd->window.bottomRight.y, border, border, false); } - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rendersystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rendersystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rendersystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rendersystem.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -27,6 +27,7 @@ #include #include #include +#include #include "clientapp.h" #include "render/environ.h" #include "render/rend_main.h" @@ -68,7 +69,9 @@ Store buffer; DrawLists drawLists; - GLUniform uMapTime { "uMapTime", GLUniform::Float }; + GLUniform uMapTime { "uMapTime", GLUniform::Float }; + GLUniform uViewMatrix { "uViewMatrix", GLUniform::Mat4 }; + GLUniform uProjectionMatrix { "uProjectionMatrix", GLUniform::Mat4 }; // Texture => world surface projection lists. struct ProjectionLists @@ -238,9 +241,6 @@ .define(SReg::IntCVar, "rend-model-mirror-hud", 0) .define(SReg::IntCVar, "rend-model-precache", 1) .define(SReg::IntCVar, "rend-sprite-precache", 1) - .define(SReg::IntCVar, "rend-light-multitex", 1) - .define(SReg::IntCVar, "rend-model-shiny-multitex", 1) - .define(SReg::IntCVar, "rend-tex-detail-multitex", 1) .define(SReg::IntCVar, "rend-tex", 1) .define(SReg::IntCVar, "rend-dev-wireframe", 0) .define(SReg::IntCVar, "rend-dev-thinker-ids", 0) @@ -361,23 +361,23 @@ ClientApp::shaders().removeAllFromPackage(packageId); } - /** + /* * Reads all shader definitions and sets up a Bank where the actual * compiled shaders are stored once they're needed. * * @todo This should be reworked to support unloading packages, and * loading of new shaders from any newly loaded packages. -jk */ - void loadAllShaders() - { - // Load all the shader program definitions. - FS::FoundFiles found; - App::findInPackages("shaders.dei", found); - DENG2_FOR_EACH(FS::FoundFiles, i, found) - { - loadShaders(**i); - } - } +// void loadAllShaders() +// { +// // Load all the shader program definitions. +// FS::FoundFiles found; +// App::findInPackages("shaders.dei", found); +// DENG2_FOR_EACH(FS::FoundFiles, i, found) +// { +// loadShaders(**i); +// } +// } void loadShaders(File const &defs) { @@ -401,6 +401,14 @@ void RenderSystem::glInit() { + // Shader defines. + { + DictionaryValue defines; + defines.add(new TextValue("DGL_BATCH_MAX"), + new NumberValue(DGL_BatchMaxSize())); + shaders().setPreprocessorDefines(defines); + } + d->models.glInit(); } @@ -425,6 +433,16 @@ return d->uMapTime; } +GLUniform &RenderSystem::uProjectionMatrix() const +{ + return d->uProjectionMatrix; +} + +GLUniform &RenderSystem::uViewMatrix() const +{ + return d->uViewMatrix; +} + render::Environment &RenderSystem::environment() { return d->environment; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_fakeradio.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_fakeradio.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_fakeradio.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_fakeradio.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -253,7 +253,7 @@ Plane const &visFloor = subsec.visFloor (); Plane const &visCeiling = subsec.visCeiling(); - de::zap(projected); + projected = {}; projected.texDimensions = Vector2f(0, shadowSize); projected.texOrigin = Vector2f(0, calcTexCoordY(leftEdge.top().z(), subsec.visFloor().heightSmoothed() , subsec.visCeiling().heightSmoothed(), shadowSize)); @@ -410,7 +410,7 @@ Plane const &visFloor = subsec.visFloor (); Plane const &visCeiling = subsec.visCeiling(); - de::zap(projected); + projected = {}; projected.texDimensions.y = -shadowSize; projected.texOrigin.y = calcTexCoordY(leftEdge.top().z(), visFloor.heightSmoothed(), visCeiling.heightSmoothed(), -shadowSize); projected.texture = LST_RADIO_OO; @@ -568,7 +568,7 @@ Plane const &visCeiling = subsec.visCeiling(); DENG2_ASSERT(visFloor.castsShadow() || visCeiling.castsShadow()); // sanity check. - de::zap(projected); + projected = {}; projected.texOrigin = Vector2f(0, leftEdge.bottom().z() - visFloor.heightSmoothed()); projected.texDimensions = Vector2f(0, visCeiling.heightSmoothed() - visFloor.heightSmoothed()); @@ -988,7 +988,11 @@ verts.posCoords[indices[order[2]]] = edges[1].inner(); verts.posCoords[indices[order[3]]] = edges[0].inner(); // Set uniform color. +#if defined (DENG_OPENGL) Vector4ub const &uniformColor = (::renderWireframe? white : black); // White to assist visual debugging. +#else + Vector4ub const &uniformColor = black; +#endif for(duint i = 0; i < 4; ++i) { verts.colorCoords[indices[i]] = uniformColor; @@ -1024,7 +1028,13 @@ auto const eyeToSubspace = Vector2f(Rend_EyeOrigin().xz() - subspace.poly().center()); // All shadow geometry uses the same texture (i.e., none) - use the same list. - DrawList &shadowList = ClientApp::renderSystem().drawLists().find(DrawListSpec(::renderWireframe? UnlitGeom : ShadowGeom)); + DrawList &shadowList = ClientApp::renderSystem().drawLists().find( +#if defined (DENG_OPENGL) + DrawListSpec(renderWireframe? UnlitGeom : ShadowGeom) +#else + DrawListSpec(ShadowGeom) +#endif + ); // Process all LineSides linked to this subspace as potential shadow casters. subspace.forAllShadowLines([&subsec, &shadowDark, &eyeToSubspace, &shadowList] (LineSide &side) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_font.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_font.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_font.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_font.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -1,7 +1,7 @@ /** @file rend_font.cpp Font Renderer. * - * @authors Copyright © 2003-2017 Jaakko Keränen * @authors Copyright © 2006-2015 Daniel Swanson + * @authors Copyright © 2003-2017 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html @@ -21,6 +21,7 @@ #include "de_base.h" #include "render/rend_font.h" +#include "sys_system.h" // novideo #include #include @@ -97,7 +98,7 @@ } caseMod[2]; // 1=upper, 0=lower } drawtextstate_t; -static void drawChar(uchar ch, float posX, float posY, AbstractFont *font, int alignFlags, short textFlags); +static void drawChar(uchar ch, float posX, float posY, const AbstractFont &font, int alignFlags); //, short textFlags); static void drawFlash(Point2Raw const *origin, Size2Raw const *size, bool bright); static int initedFont = false; @@ -110,18 +111,18 @@ static void errorIfNotInited(const char* callerName) { - if(initedFont) return; + if (initedFont) return; App_Error("%s: font renderer module is not presently initialized.", callerName); // Unreachable. Prevents static analysers from getting rather confused, poor things. exit(1); } -static int topToAscent(AbstractFont *font) +static int topToAscent(const AbstractFont &font) { - int lineHeight = font->lineSpacing(); - if(lineHeight == 0) + int lineHeight = font.lineSpacing(); + if (lineHeight == 0) return 0; - return lineHeight - font->ascent(); + return lineHeight - font.ascent(); } static inline fr_state_attributes_t *currentAttribs(void) @@ -131,7 +132,7 @@ void FR_Shutdown(void) { - if(!initedFont) return; + if (!initedFont) return; initedFont = false; } @@ -142,13 +143,13 @@ void FR_Ticker(timespan_t /*ticLength*/) { - if(!initedFont) + if (!initedFont) return; // Restricted to fixed 35 Hz ticks. /// @todo We should not be synced to the games' fixed "sharp" timing. /// This font renderer is used by the engine's UI also. - if(!DD_IsSharpTick()) + if (!DD_IsSharpTick()) return; // It's too soon. ++typeInTime; @@ -165,7 +166,7 @@ void FR_SetFont(fontid_t num) { errorIfNotInited("FR_SetFont"); - if(num != NOFONTID) + if (num != NOFONTID) { try { @@ -173,7 +174,7 @@ fr.fontNum = num; return; } - catch(ClientResources::UnknownFontIdError const &) + catch (ClientResources::UnknownFontIdError const &) {} } else @@ -206,7 +207,7 @@ void FR_PushAttrib(void) { errorIfNotInited("FR_PushAttrib"); - if(fr.attribStackDepth+1 == FR_MAX_ATTRIB_STACK_DEPTH) + if (fr.attribStackDepth+1 == FR_MAX_ATTRIB_STACK_DEPTH) { App_Error("FR_PushAttrib: STACK_OVERFLOW."); exit(1); // Unreachable. @@ -219,7 +220,7 @@ void FR_PopAttrib(void) { errorIfNotInited("FR_PopAttrib"); - if(fr.attribStackDepth == 0) + if (fr.attribStackDepth == 0) { App_Error("FR_PopAttrib: STACK_UNDERFLOW."); exit(1); // Unreachable. @@ -365,8 +366,8 @@ { fr_state_attributes_t* sat = currentAttribs(); errorIfNotInited("FR_ShadowOffset"); - if(NULL != offsetX) *offsetX = sat->shadowOffsetX; - if(NULL != offsetY) *offsetY = sat->shadowOffsetY; + if (NULL != offsetX) *offsetX = sat->shadowOffsetX; + if (NULL != offsetY) *offsetY = sat->shadowOffsetY; } #undef FR_SetShadowOffset @@ -424,7 +425,7 @@ void FR_CharSize(Size2Raw *size, uchar ch) { errorIfNotInited("FR_CharSize"); - if(size) + if (size) { Vector2ui dimensions = App_Resources().font(fr.fontNum).glyphPosCoords(ch).size(); size->width = dimensions.x; @@ -436,7 +437,7 @@ int FR_CharWidth(uchar ch) { errorIfNotInited("FR_CharWidth"); - if(fr.fontNum != 0) + if (fr.fontNum != 0) return App_Resources().font(fr.fontNum).glyphPosCoords(ch).width(); return 0; } @@ -445,7 +446,7 @@ int FR_CharHeight(uchar ch) { errorIfNotInited("FR_CharHeight"); - if(fr.fontNum != 0) + if (fr.fontNum != 0) return App_Resources().font(fr.fontNum).glyphPosCoords(ch).height(); return 0; } @@ -453,11 +454,11 @@ int FR_SingleLineHeight(char const *text) { errorIfNotInited("FR_SingleLineHeight"); - if(fr.fontNum == 0 || !text) + if (fr.fontNum == 0 || !text) return 0; AbstractFont &font = App_Resources().font(fr.fontNum); int ascent = font.ascent(); - if(ascent != 0) + if (ascent != 0) return ascent; return font.glyphPosCoords((uchar)text[0]).height(); } @@ -465,216 +466,248 @@ int FR_GlyphTopToAscent(char const *text) { errorIfNotInited("FR_GlyphTopToAscent"); - if(fr.fontNum == 0 || !text) + if (fr.fontNum == 0 || !text) return 0; AbstractFont &font = App_Resources().font(fr.fontNum); int lineHeight = font.lineSpacing(); - if(lineHeight == 0) + if (lineHeight == 0) return 0; return lineHeight - font.ascent(); } -static int textFragmentWidth(char const *fragment) +enum class TextFragmentPass { - DENG2_ASSERT(fragment != 0); - - if(fr.fontNum == 0) - { - App_Error("textFragmentHeight: Cannot determine height without a current font."); - exit(1); - } + Shadow, + Character, + Glitter, +}; - int width = 0; +struct TextFragment +{ + TextFragmentPass pass; + const AbstractFont &font; + const char *text; + int x; + int y; + int alignFlags; + uint16_t textFlags; + int initialCount; + + int length; + int width; + int height; + + void updateDimensions() + { + length = int(strlen(text)); + + // Width. + { + width = 0; + + // Just add them together. + int i = 0; + char const *ch = text; + uchar c; + while (i++ < length && (c = *ch++) != 0 && c != '\n') + { + width += FR_CharWidth(c); + } - // Just add them together. - size_t len = strlen(fragment); - size_t i = 0; - char const *ch = fragment; - uchar c; - while(i++ < len && (c = *ch++) != 0 && c != '\n') - { - width += FR_CharWidth(c); - } + if (length > 0) + { + width += currentAttribs()->tracking * (length - 1); + } + } - return int( width + currentAttribs()->tracking * (len-1) ); -} + // Height. + { + height = 0; -static int textFragmentHeight(char const *fragment) -{ - DENG2_ASSERT(fragment != 0); + // Find the greatest height. + int i = 0; + char const *ch = text; + uchar c; + while (i++ < length && (c = *ch++) != 0 && c != '\n') + { + height = de::max(height, FR_CharHeight(c)); + } - if(fr.fontNum == 0) - { - App_Error("textFragmentHeight: Cannot determine height without a current font."); - exit(1); + height += topToAscent(font); + } } - int height = 0; - - // Find the greatest height. - uint i = 0; - size_t len = strlen(fragment); - char const *ch = fragment; - uchar c; - while(i++ < len && (c = *ch++) != 0 && c != '\n') + void applyBlendMode() const { - height = de::max(height, FR_CharHeight(c)); - } + switch (pass) + { + case TextFragmentPass::Shadow: + DGL_BlendFunc(DGL_ZERO, DGL_ONE_MINUS_SRC_ALPHA); + break; - return topToAscent(&App_Resources().font(fr.fontNum)) + height; -} + case TextFragmentPass::Character: + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); + break; -/* -static void textFragmentSize(int* width, int* height, const char* fragment) -{ - if(width) *width = textFragmentWidth(fragment); - if(height) *height = textFragmentHeight(fragment); -} -*/ + case TextFragmentPass::Glitter: + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE); + break; + } + } +}; -static void textFragmentDrawer(const char* fragment, int x, int y, int alignFlags, - short textFlags, int initialCount) +static void drawTextFragment(const TextFragment &fragment) { - DENG2_ASSERT(fragment != 0 && fragment[0]); - - AbstractFont *font = &App_Resources().font(fr.fontNum); fr_state_attributes_t* sat = currentAttribs(); - dd_bool noTypein = (textFlags & DTF_NO_TYPEIN) != 0; - dd_bool noGlitter = (sat->glitterStrength <= 0 || (textFlags & DTF_NO_GLITTER) != 0); - dd_bool noShadow = (sat->shadowStrength <= 0 || (textFlags & DTF_NO_SHADOW) != 0 || - font->flags().testFlag(AbstractFont::Shadowed)); - dd_bool noCharacter = (textFlags & DTF_NO_CHARACTER) != 0; - float glitter = (noGlitter? 0 : sat->glitterStrength), glitterMul; - float shadow = (noShadow ? 0 : sat->shadowStrength), shadowMul; + bool noTypein = (fragment.textFlags & DTF_NO_TYPEIN) != 0; + + float glitterMul; + float shadowMul; float flashColor[3] = { 0, 0, 0 }; + int x = fragment.x; + int y = fragment.y; int w, h, cx, cy, count, yoff; unsigned char c; const char* ch; - if(alignFlags & ALIGN_RIGHT) - x -= textFragmentWidth(fragment); - else if(!(alignFlags & ALIGN_LEFT)) - x -= textFragmentWidth(fragment)/2; - - if(alignFlags & ALIGN_BOTTOM) - y -= textFragmentHeight(fragment); - else if(!(alignFlags & ALIGN_TOP)) - y -= textFragmentHeight(fragment)/2; + // We may be able to skip a fragment completely. + { + if (fragment.pass == TextFragmentPass::Shadow && + (sat->shadowStrength <= 0 || fragment.font.flags().testFlag(AbstractFont::Shadowed))) + { + return; + } + + if (fragment.pass == TextFragmentPass::Glitter && sat->glitterStrength <= 0) + { + return; + } + } - if(!(noTypein && noGlitter)) + if (fragment.pass == TextFragmentPass::Glitter) { flashColor[CR] = (1 + 2 * sat->rgba[CR]) / 3; flashColor[CG] = (1 + 2 * sat->rgba[CG]) / 3; flashColor[CB] = (1 + 2 * sat->rgba[CB]) / 3; } - if(renderWireframe > 1) + if (fragment.alignFlags & ALIGN_RIGHT) { - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + x -= fragment.width; + } + else if (!(fragment.alignFlags & ALIGN_LEFT)) + { + x -= fragment.width / 2; + } - LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + if (fragment.alignFlags & ALIGN_BOTTOM) + { + y -= fragment.height; } - if (BitmapFont *bmapFont = maybeAs(font)) + else if (!(fragment.alignFlags & ALIGN_TOP)) { - if(bmapFont->textureGLName()) + y -= fragment.height / 2; + } + + if (const BitmapFont *bmapFont = maybeAs(fragment.font)) + { + if (bmapFont->textureGLName()) { GL_BindTextureUnmanaged(bmapFont->textureGLName(), gl::ClampToEdge, - gl::ClampToEdge, filterUI? gl::Linear : gl::Nearest); + gl::ClampToEdge, filterUI ? gl::Linear : gl::Nearest); - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glScalef(1.f / bmapFont->textureDimensions().x, - 1.f / bmapFont->textureDimensions().y, 1.f); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Scalef(1.f / bmapFont->textureDimensions().x, + 1.f / bmapFont->textureDimensions().y, 1.f); } } - for(int pass = (noShadow? 1 : 0); pass < (noCharacter && noGlitter? 1 : 2); ++pass) + bool isBlendModeSet = false; + + //for (int pass = (noShadow? 1 : 0); pass < (noCharacter && noGlitter? 1 : 2); ++pass) { - count = initialCount; - ch = fragment; - cx = x + (pass == 0? sat->shadowOffsetX : 0); - cy = y + (pass == 0? sat->shadowOffsetY : 0); + count = fragment.initialCount; + ch = fragment.text; + cx = x + (fragment.pass == TextFragmentPass::Shadow? sat->shadowOffsetX : 0); + cy = y + (fragment.pass == TextFragmentPass::Shadow? sat->shadowOffsetY : 0); - for(;;) + for (;;) { c = *ch++; yoff = 0; - glitter = (noGlitter? 0 : sat->glitterStrength); glitterMul = 0; - - shadow = (noShadow? 0 : sat->shadowStrength); - shadowMul = (noShadow? 0 : sat->rgba[CA]); + shadowMul = sat->rgba[CA]; // Do the type-in effect? - if(!noTypein && (pass || (!noShadow && !pass))) + if (!noTypein) // && (pass || (!noShadow && !pass))) { int maxCount = (typeInTime > 0? typeInTime * 2 : 0); - if(pass) + if (fragment.pass == TextFragmentPass::Shadow) + { + if (count == maxCount) + { + shadowMul = 0; + } + else if (count + 1 == maxCount) + { + shadowMul *= .25f; + } + else if (count + 2 == maxCount) + { + shadowMul *= .5f; + } + else if (count + 3 == maxCount) + { + shadowMul *= .75f; + } + else if (count > maxCount) + { + break; + } + } + else { - if(!noGlitter) + //if (!noGlitter) + if (fragment.pass == TextFragmentPass::Glitter) { - if(count == maxCount) + if (count == maxCount) { glitterMul = 1; flashColor[CR] = sat->rgba[CR]; flashColor[CG] = sat->rgba[CG]; flashColor[CB] = sat->rgba[CB]; } - else if(count + 1 == maxCount) + else if (count + 1 == maxCount) { glitterMul = 0.88f; flashColor[CR] = (1 + sat->rgba[CR]) / 2; flashColor[CG] = (1 + sat->rgba[CG]) / 2; flashColor[CB] = (1 + sat->rgba[CB]) / 2; } - else if(count + 2 == maxCount) + else if (count + 2 == maxCount) { glitterMul = 0.75f; flashColor[CR] = sat->rgba[CR]; flashColor[CG] = sat->rgba[CG]; flashColor[CB] = sat->rgba[CB]; } - else if(count + 3 == maxCount) + else if (count + 3 == maxCount) { glitterMul = 0.5f; flashColor[CR] = sat->rgba[CR]; flashColor[CG] = sat->rgba[CG]; flashColor[CB] = sat->rgba[CB]; } - else if(count > maxCount) + else if (count > maxCount) { break; } } - else if(count > maxCount) - { - break; - } - } - else - { - if(count == maxCount) - { - shadowMul = 0; - } - else if(count + 1 == maxCount) - { - shadowMul *= .25f; - } - else if(count + 2 == maxCount) - { - shadowMul *= .5f; - } - else if(count + 3 == maxCount) - { - shadowMul *= .75f; - } - else if(count > maxCount) + else if (count > maxCount) { break; } @@ -682,48 +715,77 @@ } count++; - if(!c || c == '\n') + if (!c || c == '\n') break; w = FR_CharWidth(c); h = FR_CharHeight(c); - if(' ' != c) + if (c != ' ') { // A non-white-space character we have a glyph for. - if(pass) + switch (fragment.pass) { - if(!noCharacter) - { + case TextFragmentPass::Character: // The character itself. - LIBGUI_GL.glColor4fv(sat->rgba); - drawChar(c, cx, cy + yoff, font, ALIGN_TOPLEFT, DTF_NO_EFFECTS); - } + if (sat->rgba[CA] > 0.001f) + { + DGL_Color4fv(sat->rgba); + if (!isBlendModeSet) + { + fragment.applyBlendMode(); + isBlendModeSet = true; + } + drawChar(c, cx, cy + yoff, fragment.font, ALIGN_TOPLEFT); + } + break; - if(!noGlitter && glitter > 0) + case TextFragmentPass::Glitter: + if (/*!noGlitter &&*/ sat->glitterStrength > 0) + { + // Do something flashy. + Point2Raw origin; + Size2Raw size; + origin.x = cx; + origin.y = cy + yoff; + size.width = w; + size.height = h; + const float alpha = sat->glitterStrength * glitterMul; + if (alpha > 0) + { + if (!isBlendModeSet) + { + fragment.applyBlendMode(); + isBlendModeSet = true; + } + DGL_Color4f(flashColor[CR], flashColor[CG], flashColor[CB], alpha); + drawFlash(&origin, &size, true); + } + } + break; + + case TextFragmentPass::Shadow: { - // Do something flashy. Point2Raw origin; - Size2Raw size; - origin.x = cx; - origin.y = cy + yoff; + Size2Raw size; + origin.x = cx; + origin.y = cy + yoff; size.width = w; size.height = h; - LIBGUI_GL.glColor4f(flashColor[CR], flashColor[CG], flashColor[CB], glitter * glitterMul); - drawFlash(&origin, &size, true); + const float alpha = sat->shadowStrength * shadowMul; + if (alpha > 0) + { + if (!isBlendModeSet) + { + fragment.applyBlendMode(); + isBlendModeSet = true; + } + DGL_Color4f(1, 1, 1, alpha); + drawFlash(&origin, &size, false); + } + break; } } - else if(!noShadow) - { - Point2Raw origin; - Size2Raw size; - origin.x = cx; - origin.y = cy + yoff; - size.width = w; - size.height = h; - LIBGUI_GL.glColor4f(1, 1, 1, shadow * shadowMul); - drawFlash(&origin, &size, false); - } } cx += w + sat->tracking; @@ -731,51 +793,44 @@ } // Restore previous GL-state. - if (BitmapFont *bmapFont = maybeAs(font)) + if (const BitmapFont *bmapFont = maybeAs(fragment.font)) { - if(bmapFont->textureGLName()) + if (bmapFont->textureGLName()) { - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } } - if(renderWireframe > 1) - { - /// @todo do not assume previous state. - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - } } -static void drawChar(uchar ch, float x, float y, AbstractFont *font, - int alignFlags, short /*textFlags*/) +static void drawChar(uchar ch, float x, float y, const AbstractFont &font, int alignFlags) { - if(alignFlags & ALIGN_RIGHT) + if (alignFlags & ALIGN_RIGHT) { - x -= font->glyphPosCoords(ch).width(); + x -= font.glyphPosCoords(ch).width(); } - else if(!(alignFlags & ALIGN_LEFT)) + else if (!(alignFlags & ALIGN_LEFT)) { - x -= font->glyphPosCoords(ch).width() / 2; + x -= font.glyphPosCoords(ch).width() / 2; } - int const ascent = font->ascent(); - int const lineHeight = ascent? ascent : font->glyphPosCoords(ch).height(); - if(alignFlags & ALIGN_BOTTOM) + int const ascent = font.ascent(); + int const lineHeight = ascent ? ascent : font.glyphPosCoords(ch).height(); + if (alignFlags & ALIGN_BOTTOM) { y -= topToAscent(font) + lineHeight; } - else if(!(alignFlags & ALIGN_TOP)) + else if (!(alignFlags & ALIGN_TOP)) { y -= (topToAscent(font) + lineHeight) / 2; } - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glTranslatef(x, y, 0); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_Translatef(x, y, 0); - Rectanglei geometry = font->glyphPosCoords(ch); + Rectanglei geometry = font.glyphPosCoords(ch); - if (BitmapFont *bmapFont = maybeAs(font)) + if (const BitmapFont *bmapFont = maybeAs(font)) { /// @todo Filtering should be determined at a higher level. /// @todo We should not need to re-bind this texture here. @@ -784,16 +839,16 @@ geometry = geometry.expanded(bmapFont->textureMargin().toVector2i()); } - else if (CompositeBitmapFont *compFont = maybeAs(font)) + else if (const CompositeBitmapFont *compFont = maybeAs(font)) { GL_BindTexture(compFont->glyphTexture(ch)); geometry = geometry.expanded(compFont->glyphTextureBorder(ch)); } - Vector2i coords[4] = { font->glyphTexCoords(ch).topLeft, - font->glyphTexCoords(ch).topRight(), - font->glyphTexCoords(ch).bottomRight, - font->glyphTexCoords(ch).bottomLeft() }; + Vector2i coords[4] = { font.glyphTexCoords(ch).topLeft, + font.glyphTexCoords(ch).topRight(), + font.glyphTexCoords(ch).bottomRight, + font.glyphTexCoords(ch).bottomLeft() }; GL_DrawRectWithCoords(geometry, coords); @@ -802,8 +857,8 @@ GL_SetNoTexture(); } - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glTranslatef(-x, -y, 0); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_Translatef(-x, -y, 0); } static void drawFlash(Point2Raw const *origin, Size2Raw const *size, bool bright) @@ -814,7 +869,7 @@ int x, y, w, h; // Don't draw anything for very small letters. - if(size->height <= 4) return; + if (size->height <= 4) return; x = origin->x + (int) (size->width / 2.0f - fw / 2); y = origin->y + (int) (size->height / 2.0f - fh / 2); @@ -824,23 +879,16 @@ GL_BindTextureUnmanaged(GL_PrepareLSTexture(LST_DYNAMIC), gl::ClampToEdge, gl::ClampToEdge); - GLState::current().setBlendFunc(bright? gl::SrcAlpha : gl::Zero, - bright? gl::One : gl::OneMinusSrcAlpha) - .apply(); - - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex2f(x, y); - LIBGUI_GL.glTexCoord2f(1, 0); - LIBGUI_GL.glVertex2f(x + w, y); - LIBGUI_GL.glTexCoord2f(1, 1); - LIBGUI_GL.glVertex2f(x + w, y + h); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex2f(x, y + h); - LIBGUI_GL.glEnd(); - - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha) - .apply(); + DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex2f(x, y); + DGL_TexCoord2f(0, 1, 0); + DGL_Vertex2f(x + w, y); + DGL_TexCoord2f(0, 1, 1); + DGL_Vertex2f(x + w, y + h); + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex2f(x, y + h); + DGL_End(); } /** @@ -849,13 +897,13 @@ * " = " * */ -static float parseFloat(char** str) +static float parseFloat(const char **str) { float value; - char* end; + char *end; *str = M_SkipWhite(*str); - if(**str != '=') return 0; // Now I'm confused! + if (**str != '=') return 0; // Now I'm confused! *str = M_SkipWhite(*str + 1); value = (float) strtod(*str, &end); @@ -869,156 +917,156 @@ * " = [|"][|"]" * */ - static dd_bool parseString(char** str, char* buf, size_t bufLen) + static dd_bool parseString(const char **str, char* buf, size_t bufLen) { size_t len; - char* end; + const char* end; - if(!buf || bufLen == 0) return false; + if (!buf || bufLen == 0) return false; *str = M_SkipWhite(*str); - if(**str != '=') return false; // Now I'm confused! + if (**str != '=') return false; // Now I'm confused! // Skip over any leading whitespace. *str = M_SkipWhite(*str + 1); // Skip over any opening '"' character. - if(**str == '"') (*str)++; + if (**str == '"') (*str)++; // Find the end of the string. end = *str; - while(*end && *end != '}' && *end != ',' && *end !='"') { end++; } + while (*end && *end != '}' && *end != ',' && *end !='"') { end++; } len = end - *str; - if(len != 0) + if (len != 0) { dd_snprintf(buf, MIN_OF(len+1, bufLen), "%s", *str); *str = end; } // Skip over any closing '"' character. - if(**str == '"') + if (**str == '"') (*str)++; return true; } -static void parseParamaterBlock(char** strPtr, drawtextstate_t* state, int* numBreaks) +static void parseParamaterBlock(const char **strPtr, drawtextstate_t* state, int *numBreaks) { LOG_AS("parseParamaterBlock"); (*strPtr)++; - while(*(*strPtr) && *(*strPtr) != '}') + while (*(*strPtr) && *(*strPtr) != '}') { (*strPtr) = M_SkipWhite((*strPtr)); // What do we have here? - if(!strnicmp((*strPtr), "flash", 5)) + if (!strnicmp((*strPtr), "flash", 5)) { (*strPtr) += 5; state->typeIn = true; } - else if(!strnicmp((*strPtr), "noflash", 7)) + else if (!strnicmp((*strPtr), "noflash", 7)) { (*strPtr) += 7; state->typeIn = false; } - else if(!strnicmp((*strPtr), "case", 4)) + else if (!strnicmp((*strPtr), "case", 4)) { (*strPtr) += 4; state->caseScale = true; } - else if(!strnicmp((*strPtr), "nocase", 6)) + else if (!strnicmp((*strPtr), "nocase", 6)) { (*strPtr) += 6; state->caseScale = false; } - else if(!strnicmp((*strPtr), "ups", 3)) + else if (!strnicmp((*strPtr), "ups", 3)) { (*strPtr) += 3; state->caseMod[1].scale = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "upo", 3)) + else if (!strnicmp((*strPtr), "upo", 3)) { (*strPtr) += 3; state->caseMod[1].offset = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "los", 3)) + else if (!strnicmp((*strPtr), "los", 3)) { (*strPtr) += 3; state->caseMod[0].scale = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "loo", 3)) + else if (!strnicmp((*strPtr), "loo", 3)) { (*strPtr) += 3; state->caseMod[0].offset = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "break", 5)) + else if (!strnicmp((*strPtr), "break", 5)) { (*strPtr) += 5; ++(*numBreaks); } - else if(!strnicmp((*strPtr), "r", 1)) + else if (!strnicmp((*strPtr), "r", 1)) { (*strPtr)++; state->rgba[CR] = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "g", 1)) + else if (!strnicmp((*strPtr), "g", 1)) { (*strPtr)++; state->rgba[CG] = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "b", 1)) + else if (!strnicmp((*strPtr), "b", 1)) { (*strPtr)++; state->rgba[CB] = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "a", 1)) + else if (!strnicmp((*strPtr), "a", 1)) { (*strPtr)++; state->rgba[CA] = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "x", 1)) + else if (!strnicmp((*strPtr), "x", 1)) { (*strPtr)++; state->offX = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "y", 1)) + else if (!strnicmp((*strPtr), "y", 1)) { (*strPtr)++; state->offY = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "scalex", 6)) + else if (!strnicmp((*strPtr), "scalex", 6)) { (*strPtr) += 6; state->scaleX = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "scaley", 6)) + else if (!strnicmp((*strPtr), "scaley", 6)) { (*strPtr) += 6; state->scaleY = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "scale", 5)) + else if (!strnicmp((*strPtr), "scale", 5)) { (*strPtr) += 5; state->scaleX = state->scaleY = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "angle", 5)) + else if (!strnicmp((*strPtr), "angle", 5)) { (*strPtr) += 5; state->angle = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "glitter", 7)) + else if (!strnicmp((*strPtr), "glitter", 7)) { (*strPtr) += 7; state->glitterStrength = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "shadow", 6)) + else if (!strnicmp((*strPtr), "shadow", 6)) { (*strPtr) += 6; state->shadowStrength = parseFloat(&(*strPtr)); } - else if(!strnicmp((*strPtr), "tracking", 8)) + else if (!strnicmp((*strPtr), "tracking", 8)) { (*strPtr) += 8; state->tracking = parseFloat(&(*strPtr)); @@ -1026,19 +1074,19 @@ else { // Perhaps a font name? - if(!strnicmp((*strPtr), "font", 4)) + if (!strnicmp((*strPtr), "font", 4)) { char buf[80]; (*strPtr) += 4; - if(parseString(&(*strPtr), buf, 80)) + if (parseString(&(*strPtr), buf, 80)) { try { - state->fontNum = App_Resources().fontManifest(de::Uri(buf, RC_NULL)).uniqueId(); + state->fontNum = App_Resources().fontManifest(de::makeUri(buf)).uniqueId(); continue; } - catch(Resources::MissingResourceManifestError const &) + catch (Resources::MissingResourceManifestError const &) {} } @@ -1047,7 +1095,7 @@ } // Unknown, skip it. - if(*(*strPtr) != '}') + if (*(*strPtr) != '}') { (*strPtr)++; } @@ -1055,11 +1103,11 @@ } // Skip over the closing brace. - if(*(*strPtr)) + if (*(*strPtr)) (*strPtr)++; } -static void initDrawTextState(drawtextstate_t* state, short textFlags) +static void initDrawTextState(drawtextstate_t* state, uint16_t textFlags) { fr_state_attributes_t* sat = currentAttribs(); @@ -1089,15 +1137,15 @@ static char* enlargeTextBuffer(size_t lengthMinusTerminator) { - if(lengthMinusTerminator <= FR_SMALL_TEXT_BUFFER_SIZE) + if (lengthMinusTerminator <= FR_SMALL_TEXT_BUFFER_SIZE) { return smallTextBuffer; } - if(largeTextBuffer == NULL || lengthMinusTerminator > largeTextBufferSize) + if (largeTextBuffer == NULL || lengthMinusTerminator > largeTextBufferSize) { largeTextBufferSize = lengthMinusTerminator; largeTextBuffer = (char*)realloc(largeTextBuffer, largeTextBufferSize+1); - if(largeTextBuffer == NULL) + if (largeTextBuffer == NULL) App_Error("FR_EnlargeTextBuffer: Failed on reallocation of %lu bytes.", (unsigned long)(lengthMinusTerminator+1)); } @@ -1106,7 +1154,7 @@ static void freeTextBuffer(void) { - if(largeTextBuffer == NULL) + if (largeTextBuffer == NULL) return; free(largeTextBuffer); largeTextBuffer = 0; largeTextBufferSize = 0; @@ -1122,7 +1170,7 @@ errorIfNotInited("FR_TextWidth"); - if(!string || !string[0]) + if (!string || !string[0]) return 0; /// @todo All visual format parsing should be done in one place. @@ -1130,33 +1178,33 @@ w = 0; len = strlen(string); ch = string; - for(i = 0; i < len; ++i, ch++) + for (i = 0; i < len; ++i, ch++) { unsigned char c = *ch; - if(c == FR_FORMAT_ESCAPE_CHAR) + if (c == FR_FORMAT_ESCAPE_CHAR) { escaped = true; continue; } - if(!escaped && c == '{') + if (!escaped && c == '{') { skipping = true; } - else if(skipping && c == '}') + else if (skipping && c == '}') { skipping = false; continue; } - if(skipping) + if (skipping) continue; escaped = false; - if(c == '\n') + if (c == '\n') { - if(w > maxWidth) + if (w > maxWidth) maxWidth = w; w = 0; continue; @@ -1164,11 +1212,11 @@ w += FR_CharWidth(c); - if(i != len - 1) + if (i != len - 1) { w += FR_Tracking(); } - else if(maxWidth == -1) + else if (maxWidth == -1) { maxWidth = w; } @@ -1185,7 +1233,7 @@ const char* ch; size_t i, len; - if(!string || !string[0]) + if (!string || !string[0]) return 0; errorIfNotInited("FR_TextHeight"); @@ -1194,25 +1242,25 @@ len = strlen(string); h = 0; ch = string; - for(i = 0; i < len; ++i, ch++) + for (i = 0; i < len; ++i, ch++) { unsigned char c = *ch; int charHeight; - if(c == '{') + if (c == '{') { skip = true; } - else if(c == '}') + else if (c == '}') { skip = false; continue; } - if(skip) + if (skip) continue; - if(c == '\n') + if (c == '\n') { h += currentLineHeight == 0? (FR_CharHeight('A') * (1+FR_Leading())) : currentLineHeight; currentLineHeight = 0; @@ -1220,7 +1268,7 @@ } charHeight = FR_CharHeight(c) * (1+FR_Leading()); - if(charHeight > currentLineHeight) + if (charHeight > currentLineHeight) currentLineHeight = charHeight; } h += currentLineHeight; @@ -1231,77 +1279,84 @@ #undef FR_TextSize void FR_TextSize(Size2Raw* size, const char* text) { - if(!size) return; + if (!size) return; size->width = FR_TextWidth(text); size->height = FR_TextHeight(text); } #undef FR_DrawText3 -void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, short _textFlags) +void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, uint16_t textFlags) { fontid_t origFont = FR_Font(); float cx, cy, extraScale; drawtextstate_t state; const char* fragment; - int pass, curCase; + int curCase; Point2Raw origin; Size2Raw textSize; - size_t charCount; + int charCount; float origColor[4]; - char* str, *end; + const char *str, *end; dd_bool escaped = false; errorIfNotInited("FR_DrawText"); - if(!text || !text[0]) return; + if (!text || !text[0]) return; origin.x = _origin? _origin->x : 0; origin.y = _origin? _origin->y : 0; - _textFlags &= ~(DTF_INTERNAL_MASK); + textFlags &= ~(DTF_INTERNAL_MASK); // If we aren't aligning to top-left we need to know the dimensions. - if(alignFlags & ALIGN_RIGHT) + if (alignFlags & ALIGN_RIGHT) + { FR_TextSize(&textSize, text); + } - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - auto &GL = LIBGUI_GL; - // We need to change the current color, so remember for restore. - GL.glGetFloatv(GL_CURRENT_COLOR, origColor); + DGL_CurrentColor(origColor); - for(pass = ((_textFlags & DTF_NO_SHADOW) != 0? 1 : 0); - pass < ((_textFlags & DTF_NO_GLITTER) != 0? 2 : 3); ++pass) + for (TextFragmentPass pass : + {TextFragmentPass::Shadow, TextFragmentPass::Character, TextFragmentPass::Glitter}) { - short textFlags = 0; + switch (pass) + { + case TextFragmentPass::Shadow: + if (textFlags & DTF_NO_SHADOW) continue; + break; + + case TextFragmentPass::Character: + if (textFlags & DTF_NO_CHARACTER) continue; + break; + + case TextFragmentPass::Glitter: + if (textFlags & DTF_NO_GLITTER) continue; + break; + } // Configure the next pass. cx = (float) origin.x; cy = (float) origin.y; curCase = -1; charCount = 0; - switch(pass) - { - case 0: textFlags = _textFlags | (DTF_NO_GLITTER|DTF_NO_CHARACTER); break; - case 1: textFlags = _textFlags | (DTF_NO_SHADOW |DTF_NO_GLITTER); break; - case 2: textFlags = _textFlags | (DTF_NO_SHADOW |DTF_NO_CHARACTER); break; - } // Apply defaults. initDrawTextState(&state, textFlags); - str = (char*)text; - while(*str) + str = text; + while (*str) { - if(*str == FR_FORMAT_ESCAPE_CHAR) + if (*str == FR_FORMAT_ESCAPE_CHAR) { escaped = true; ++str; continue; } - if(!escaped && *str == '{') // Paramaters included? + if (!escaped && *str == '{') // Paramaters included? { fontid_t lastFont = state.fontNum; int lastTracking = state.tracking; @@ -1319,60 +1374,60 @@ parseParamaterBlock(&str, &state, &numBreaks); - if(numBreaks != 0) + if (numBreaks != 0) { do { cx = (float) origin.x; cy += state.lastLineHeight * (1+lastLeading); - } while(--numBreaks > 0); + } while (--numBreaks > 0); } - if(state.fontNum != lastFont) + if (state.fontNum != lastFont) FR_SetFont(state.fontNum); - if(state.tracking != lastTracking) + if (state.tracking != lastTracking) FR_SetTracking(state.tracking); - if(state.leading != lastLeading) + if (state.leading != lastLeading) FR_SetLeading(state.leading); - if(state.rgba[CR] != lastRGBA[CR] || state.rgba[CG] != lastRGBA[CG] || state.rgba[CB] != lastRGBA[CB] || state.rgba[CA] != lastRGBA[CA]) + if (state.rgba[CR] != lastRGBA[CR] || state.rgba[CG] != lastRGBA[CG] || state.rgba[CB] != lastRGBA[CB] || state.rgba[CA] != lastRGBA[CA]) FR_SetColorAndAlphav(state.rgba); - if(state.shadowStrength != lastShadowStrength) + if (state.shadowStrength != lastShadowStrength) FR_SetShadowStrength(state.shadowStrength); - if(state.glitterStrength != lastGlitterStrength) + if (state.glitterStrength != lastGlitterStrength) FR_SetGlitterStrength(state.glitterStrength); - if(state.caseScale != lastCaseScale) + if (state.caseScale != lastCaseScale) FR_SetCaseScale(state.caseScale); } - for(end = str; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{');) + for (end = str; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{');) { int newlines = 0, fragmentAlignFlags; float alignx = 0; // Find the end of the next fragment. - if(FR_CaseScale()) + if (FR_CaseScale()) { curCase = -1; // Select a substring with characters of the same case (or whitespace). - for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') && + for (; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') && *end != '\n'; end++) { escaped = false; // We can skip whitespace. - if(isspace(*end)) + if (isspace(*end)) continue; - if(curCase < 0) + if (curCase < 0) curCase = (isupper(*end) != 0); - else if(curCase != (isupper(*end) != 0)) + else if (curCase != (isupper(*end) != 0)) break; } } else { curCase = 0; - for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') && + for (; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') && *end != '\n'; end++) { escaped = false; } } @@ -1385,7 +1440,7 @@ fragment = buffer; } - while(*end == '\n') + while (*end == '\n') { newlines++; end++; @@ -1394,7 +1449,7 @@ // Continue from here. str = end; - if(!(alignFlags & (ALIGN_LEFT|ALIGN_RIGHT))) + if (!(alignFlags & (ALIGN_LEFT|ALIGN_RIGHT))) { fragmentAlignFlags = alignFlags; } @@ -1402,55 +1457,70 @@ { // We'll take care of horizontal positioning of the fragment so align left. fragmentAlignFlags = (alignFlags & ~(ALIGN_RIGHT)) | ALIGN_LEFT; - if(alignFlags & ALIGN_RIGHT) + if (alignFlags & ALIGN_RIGHT) alignx = -textSize.width * state.scaleX; } // Setup the scaling. - GL.glMatrixMode(GL_MODELVIEW); - GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // Rotate. - if(state.angle != 0) + if (!fequal(state.angle, 0)) { // The origin is the specified (x,y) for the patch. // We'll undo the aspect ratio (otherwise the result would be skewed). /// @todo Do not assume the aspect ratio and therefore whether // correction is even needed. - GL.glTranslatef((float)origin.x, (float)origin.y, 0); - GL.glScalef(1, 200.0f / 240.0f, 1); - GL.glRotatef(state.angle, 0, 0, 1); - GL.glScalef(1, 240.0f / 200.0f, 1); - GL.glTranslatef(-(float)origin.x, -(float)origin.y, 0); + DGL_Translatef((float)origin.x, (float)origin.y, 0); + DGL_Scalef(1, 200.0f / 240.0f, 1); + DGL_Rotatef(state.angle, 0, 0, 1); + DGL_Scalef(1, 240.0f / 200.0f, 1); + DGL_Translatef(-(float)origin.x, -(float)origin.y, 0); } - GL.glTranslatef(cx + state.offX + alignx, cy + state.offY + (FR_CaseScale() ? state.caseMod[curCase].offset : 0), 0); + DGL_Translatef(cx + state.offX + alignx, cy + state.offY + (FR_CaseScale() ? state.caseMod[curCase].offset : 0), 0); extraScale = (FR_CaseScale() ? state.caseMod[curCase].scale : 1); - GL.glScalef(state.scaleX, state.scaleY * extraScale, 1); + DGL_Scalef(state.scaleX, state.scaleY * extraScale, 1); // Draw it. - if(fr.fontNum) - { - textFragmentDrawer(fragment, 0, 0, fragmentAlignFlags, textFlags, state.typeIn ? (int) charCount : DEFAULT_INITIALCOUNT); - } - charCount += strlen(fragment); + DENG2_ASSERT(fr.fontNum); + + TextFragment frag{pass, + App_Resources().font(fr.fontNum), + fragment, + 0, + 0, + fragmentAlignFlags, + textFlags, + state.typeIn ? charCount : DEFAULT_INITIALCOUNT, + 0, + 0, + 0}; + frag.updateDimensions(); + + drawTextFragment(frag); + + charCount += frag.length; // Advance the current position? - if(newlines == 0) + if (newlines == 0) { - cx += ((float) textFragmentWidth(fragment) + currentAttribs()->tracking) * state.scaleX; + cx += (float(frag.width) + currentAttribs()->tracking) * state.scaleX; } else { - if(strlen(fragment) > 0) - state.lastLineHeight = textFragmentHeight(fragment); + if (frag.length > 0) + { + state.lastLineHeight = frag.height; + } cx = (float) origin.x; - cy += newlines * (float) state.lastLineHeight * (1+FR_Leading()); + cy += newlines * state.lastLineHeight * (1.f + FR_Leading()); } - GL.glMatrixMode(GL_MODELVIEW); - GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } } @@ -1460,7 +1530,8 @@ freeTextBuffer(); FR_SetFont(origFont); - GL.glColor4fv(origColor); + DGL_Color4fv(origColor); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); } #undef FR_DrawText2 @@ -1541,8 +1612,7 @@ void FR_Init(void) { // No reinitializations... - if(initedFont) return; - if(isDedicated) return; + if (initedFont || novideo) return; initedFont = true; fr.fontNum = 0; @@ -1553,12 +1623,12 @@ #undef Fonts_ResolveUri DENG_EXTERN_C fontid_t Fonts_ResolveUri(uri_s const *uri) { - if(!uri) return NOFONTID; + if (!uri) return NOFONTID; try { return App_Resources().fontManifest(*reinterpret_cast(uri)).uniqueId(); } - catch(Resources::MissingResourceManifestError const &) + catch (Resources::MissingResourceManifestError const &) {} return NOFONTID; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_halo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_halo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_halo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_halo.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -95,24 +95,20 @@ void H_SetupState(bool dosetup) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); if(dosetup) { - GLState::current() - .setDepthWrite(false) - .setDepthTest(false) - .apply(); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Disable(DGL_DEPTH_TEST); GL_BlendMode(BM_ADD); } else { + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); GL_BlendMode(BM_NORMAL); - GLState::current() - .setDepthWrite(true) - .setDepthTest(true) - .apply(); } } @@ -208,17 +204,17 @@ if(doPrimary) H_SetupState(true); - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Prepare the texture rotation matrix. - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); // Rotate around the center of the texture. - LIBGUI_GL.glTranslatef(0.5f, 0.5f, 0); - LIBGUI_GL.glRotatef(turnAngle / float(de::PI) * 180, 0, 0, 1); - LIBGUI_GL.glTranslatef(-0.5f, -0.5f, 0); + DGL_Translatef(0.5f, 0.5f, 0); + DGL_Rotatef(turnAngle / float(de::PI) * 180, 0, 0, 1); + DGL_Translatef(-0.5f, -0.5f, 0); flare_t *fl = flares; for(int i = 0; i < haloMode && i < NUM_FLARES; ++i, fl++) @@ -320,36 +316,36 @@ } GL_BindTextureUnmanaged(renderTextures? tex : 0, gl::ClampToEdge, gl::ClampToEdge); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); float const radX = radius * fl->size; float const radY = radX / 1.2f; // Aspect correction. - LIBGUI_GL.glColor4f(color.x, color.y, color.z, alpha); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex3f(pos.x + radX * leftOff.x, + DGL_Color4f(color.x, color.y, color.z, alpha); + DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex3f(pos.x + radX * leftOff.x, pos.y + radY * leftOff.y, pos.z + radX * leftOff.z); - LIBGUI_GL.glTexCoord2f(1, 0); - LIBGUI_GL.glVertex3f(pos.x + radX * rightOff.x, + DGL_TexCoord2f(0, 1, 0); + DGL_Vertex3f(pos.x + radX * rightOff.x, pos.y + radY * rightOff.y, pos.z + radX * rightOff.z); - LIBGUI_GL.glTexCoord2f(1, 1); - LIBGUI_GL.glVertex3f(pos.x - radX * leftOff.x, + DGL_TexCoord2f(0, 1, 1); + DGL_Vertex3f(pos.x - radX * leftOff.x, pos.y - radY * leftOff.y, pos.z - radX * leftOff.z); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex3f(pos.x - radX * rightOff.x, + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex3f(pos.x - radX * rightOff.x, pos.y - radY * rightOff.y, pos.z - radX * rightOff.z); - LIBGUI_GL.glEnd(); + DGL_End(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); } - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); // Restore previous GL state. if(doPrimary) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -157,6 +157,7 @@ D_CMD(LowRes); D_CMD(MipMap); D_CMD(TexReset); +D_CMD(CubeShot); #if 0 dint useBias; ///< Shadow Bias enabled? cvar @@ -167,14 +168,13 @@ dbyte smoothTexAnim = true; dint renderTextures = true; +#if defined (DENG_OPENGL) dint renderWireframe; -dint useMultiTexLights = true; -dint useMultiTexDetails = true; +#endif dint dynlightBlend; Vector3f torchColor(1, 1, 1); -//dint torchAdditive = true; dint useShinySurfaces = true; @@ -229,6 +229,17 @@ dfloat vang, vpitch; dfloat viewsidex, viewsidey; +// Helper for overriding the normal view matrices. +struct FixedView +{ + Matrix4f projectionMatrix; + Matrix4f modelViewMatrix; + float yaw; + float pitch; + float horizontalFov; +}; +static std::unique_ptr fixedView; + dbyte freezeRLs; dint devNoCulling; ///< @c 1= disabled (cvar). dint devRendSkyMode; @@ -272,7 +283,7 @@ dint extraLight; ///< Bumped light from gun blasts. dfloat extraLightDelta; -DGLuint dlBBox; ///< Display list id for the active-textured bbox model. +//DGLuint dlBBox; ///< Display list id for the active-textured bbox model. /* * Debug/Development cvars: @@ -394,11 +405,11 @@ { App_World().map().removeAllLumobjs(); } - if (dlBBox) - { - GL_DeleteLists(dlBBox, 1); - dlBBox = 0; - } +// if (dlBBox) +// { +// GL_DeleteLists(dlBBox, 1); +// dlBBox = 0; +// } } bool Rend_IsMTexLights() @@ -413,6 +424,11 @@ dfloat Rend_FieldOfView() { + if (fixedView) + { + return fixedView->horizontalFov; + } + if (vrCfg().mode() == VRConfig::OculusRift) { // OVR tells us which FOV to use. @@ -420,20 +436,6 @@ } else { - auto const viewRect = R_Console3DViewRect(displayPlayer); - - // Correction is applied for wide screens so that when the FOV is kept - // at a certain value (e.g., the default FOV), a 16:9 view has a wider angle - // than a 4:3, but not just scaled linearly since that would go too far - // into the fish eye territory. - dfloat widescreenCorrection = dfloat(viewRect.width()) / dfloat(viewRect.height()) / (4.f / 3.f); - if (widescreenCorrection < 1.5f) // up to ~16:9 - { - widescreenCorrection = (1 + 2 * widescreenCorrection) / 3; - return de::clamp(1.f, widescreenCorrection * fieldOfView, 179.f); - } - // This is an unusually wide (perhaps multimonitor) setup, so just use the - // configured FOV as is. return de::clamp(1.f, fieldOfView, 179.f); } } @@ -445,20 +447,53 @@ return vEyeOrigin; } -Matrix4f Rend_GetModelViewMatrix(dint consoleNum, bool inWorldSpace) +void Rend_SetFixedView(int consoleNum, float yaw, float pitch, float fov, Vector2f viewportSize) { viewdata_t const *viewData = &DD_Player(consoleNum)->viewport(); - dfloat bodyAngle = viewData->current.angleWithoutHeadTracking() / (dfloat) ANGLE_MAX * 360 - 90; + fixedView.reset(new FixedView); + + fixedView->yaw = yaw; + fixedView->pitch = pitch; + fixedView->horizontalFov = fov; + fixedView->modelViewMatrix = + Matrix4f::rotate(pitch, Vector3f(1, 0, 0)) * + Matrix4f::rotate(yaw, Vector3f(0, 1, 0)) * + Matrix4f::scale(Vector3f(1.0f, 1.2f, 1.0f)) * // This is the aspect correction. + Matrix4f::translate(-viewData->current.origin.xzy()); + + Rangef const clip = GL_DepthClipRange(); + fixedView->projectionMatrix = BaseGuiApp::app().vr() + .projectionMatrix(fov, viewportSize, clip.start, clip.end) * + Matrix4f::scale(Vector3f(1, 1, -1)); +} + +void Rend_UnsetFixedView() +{ + fixedView.reset(); +} + +Matrix4f Rend_GetModelViewMatrix(dint consoleNum, bool inWorldSpace) +{ + viewdata_t const *viewData = &DD_Player(consoleNum)->viewport(); /// @todo vOrigin et al. shouldn't be changed in a getter function. -jk vOrigin = viewData->current.origin.xzy(); - vang = viewData->current.angle() / (dfloat) ANGLE_MAX * 360 - 90; // head tracking included - vpitch = viewData->current.pitch * 85.0 / 110.0; - vEyeOrigin = vOrigin; + if (fixedView) + { + vang = fixedView->yaw; + vpitch = fixedView->pitch; + return fixedView->modelViewMatrix; + } + + vang = viewData->current.angle() / (dfloat) ANGLE_MAX * 360 - 90; // head tracking included + vpitch = viewData->current.pitch * 85.0 / 110.0; + + dfloat bodyAngle = viewData->current.angleWithoutHeadTracking() / (dfloat) ANGLE_MAX * 360 - 90; + OculusRift &ovr = vrCfg().oculusRift(); bool const applyHead = (vrCfg().mode() == VRConfig::OculusRift && ovr.isReady()); @@ -516,11 +551,27 @@ void Rend_ModelViewMatrix(bool inWorldSpace) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glLoadMatrixf(Rend_GetModelViewMatrix(DoomsdayApp::players().indexOf(viewPlayer), inWorldSpace).values()); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_LoadMatrix( + Rend_GetModelViewMatrix(DoomsdayApp::players().indexOf(viewPlayer), inWorldSpace).values()); +} + +Matrix4f Rend_GetProjectionMatrix() +{ + if (fixedView) + { + return fixedView->projectionMatrix; + } + + const dfloat fov = Rend_FieldOfView(); + const Vector2f size = R_Console3DViewRect(displayPlayer).size(); + yfov = vrCfg().verticalFieldOfView(fov, size); + const Rangef clip = GL_DepthClipRange(); + return vrCfg().projectionMatrix(fov, size, clip.start, clip.end) * + Matrix4f::scale(Vector3f(1, 1, -1)); } static inline ddouble viewFacingDot(Vector2d const &v1, Vector2d const &v2) @@ -660,7 +711,7 @@ light = de::clamp(0.f, light, 1.f) * dynlightFactor; // In fog additive blending is used; the normal fog color is way too bright. - if(fogParams.usingFog) light *= dynlightFogBright; + if (fogParams.usingFog) light *= dynlightFogBright; // Multiply light with (ambient) color. return color * light; @@ -673,13 +724,13 @@ ClientMaterial *Rend_ChooseMapSurfaceMaterial(Surface const &surface) { - switch(renderTextures) + switch (renderTextures) { case 0: // No texture mode. case 1: // Normal mode. - if(!(devNoTexFix && surface.hasFixMaterial())) + if (!(devNoTexFix && surface.hasFixMaterial())) { - if(surface.hasMaterial() || surface.parent().type() != DMU_PLANE) + if (surface.hasMaterial() || surface.parent().type() != DMU_PLANE) return static_cast(surface.materialPtr()); } @@ -687,9 +738,9 @@ return &ClientMaterial::find(de::Uri("System", Path("missing"))); case 2: // Lighting debug mode. - if(surface.hasMaterial() && !(!devNoTexFix && surface.hasFixMaterial())) + if (surface.hasMaterial() && !(!devNoTexFix && surface.hasFixMaterial())) { - if(!surface.hasSkyMaskedMaterial() || devRendSkyMode) + if (!surface.hasSkyMaskedMaterial() || devRendSkyMode) { // Use the special "gray" material. return &ClientMaterial::find(de::Uri("System", Path("gray"))); @@ -728,7 +779,7 @@ // Most masked walls need wrapping, though. What we need to do is // look at the texture coordinates and see if they require texture // wrapping. - if(renderTextures) + if (renderTextures) { // Ensure we've up to date info about the material. matAnimator->prepare(); @@ -742,9 +793,9 @@ (rvertices[3].z - rvertices[0].z) / matDimensions.y; dint wrapS = GL_REPEAT, wrapT = GL_REPEAT; - if(!matAnimator->isOpaque()) + if (!matAnimator->isOpaque()) { - if(!(VS_WALL(vis)->texCoord[0][0] < 0 || VS_WALL(vis)->texCoord[0][0] > 1 || + if (!(VS_WALL(vis)->texCoord[0][0] < 0 || VS_WALL(vis)->texCoord[0][0] > 1 || VS_WALL(vis)->texCoord[1][0] < 0 || VS_WALL(vis)->texCoord[1][0] > 1)) { // Visible portion is within the actual [0..1] range. @@ -752,7 +803,7 @@ } // Clamp on the vertical axis if the coords are in the normal [0..1] range. - if(!(VS_WALL(vis)->texCoord[0][1] < 0 || VS_WALL(vis)->texCoord[0][1] > 1 || + if (!(VS_WALL(vis)->texCoord[0][1] < 0 || VS_WALL(vis)->texCoord[0][1] > 1 || VS_WALL(vis)->texCoord[1][1] < 0 || VS_WALL(vis)->texCoord[1][1] > 1)) { wrapT = GL_CLAMP_TO_EDGE; @@ -766,13 +817,13 @@ VS_WALL(vis)->animator = matAnimator; VS_WALL(vis)->blendMode = blendMode; - for(dint i = 0; i < 4; ++i) + for (dint i = 0; i < 4; ++i) { VS_WALL(vis)->vertices[i].pos[0] = rvertices[i].x; VS_WALL(vis)->vertices[i].pos[1] = rvertices[i].y; VS_WALL(vis)->vertices[i].pos[2] = rvertices[i].z; - for(dint c = 0; c < 4; ++c) + for (dint c = 0; c < 4; ++c) { /// @todo Do not clamp here. VS_WALL(vis)->vertices[i].color[c] = de::clamp(0.f, rcolors[i][c], 1.f); @@ -780,8 +831,7 @@ } /// @todo Semitransparent masked polys arn't lit atm - if(glow < 1 && lightListIdx && numTexUnits > 1 && envModAdd && - !(rcolors[0].w < 1)) + if (glow < 1 && lightListIdx && !(rcolors[0].w < 1)) { // The dynlights will have already been sorted so that the brightest // and largest of them is first in the list. So grab that one. @@ -792,7 +842,7 @@ VS_WALL(vis)->modTexCoord[0][1] = tp.topLeft.y; VS_WALL(vis)->modTexCoord[1][0] = tp.bottomRight.x; VS_WALL(vis)->modTexCoord[1][1] = tp.bottomRight.y; - for(dint c = 0; c < 4; ++c) + for (dint c = 0; c < 4; ++c) { VS_WALL(vis)->modColor[c] = tp.color[c]; } @@ -859,11 +909,11 @@ //auto &subsec = ::curSubspace->subsector().as(); // Uniform color? - if(::levelFullBright || !(glowing < 1)) + if (::levelFullBright || !(glowing < 1)) { dfloat const lum = de::clamp(0.f, ::curSectorLightLevel + (::levelFullBright? 1 : glowing), 1.f); Vector4f const uniformColor(lum, lum, lum, 0); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = uniformColor; } @@ -871,15 +921,15 @@ } #if 0 - if(::useBias) // Bias lighting model. + if (::useBias) // Bias lighting model. { Map &map = subsec.sector().map(); Shard &shard = subsec.shard(mapElement, geomGroup); // Apply the ambient light term from the grid (if available). - if(map.hasLightGrid()) + if (map.hasLightGrid()) { - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = map.lightGrid().evaluate(posCoords[i]); } @@ -889,20 +939,20 @@ shard.lightWithBiasSources(posCoords, verts.color, surfaceTangents, map.biasCurrentTime()); // Apply surface glow. - if(glowing > 0) + if (glowing > 0) { Vector4f const glow(glowing, glowing, glowing, 0); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] += glow; } } // Apply light range compression and clamp. - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { Vector4f &color = verts.color[i]; - for(dint k = 0; k < 3; ++k) + for (dint k = 0; k < 3; ++k) { color[k] = de::clamp(0.f, color[k] + Rend_LightAdaptationDelta(color[k]), 1.f); } @@ -916,7 +966,7 @@ dfloat const lumLeft = de::clamp(0.f, ::curSectorLightLevel + luminosityDeltas[0] + glowing, 1.f); dfloat const lumRight = de::clamp(0.f, ::curSectorLightLevel + luminosityDeltas[1] + glowing, 1.f); - if(haveWall && !de::fequal(lumLeft, lumRight)) + if (haveWall && !de::fequal(lumLeft, lumRight)) { lightVertex(verts.color[0], posCoords[0], lumLeft, colorBlended); lightVertex(verts.color[1], posCoords[1], lumLeft, colorBlended); @@ -925,14 +975,14 @@ } else { - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { lightVertex(verts.color[i], posCoords[i], lumLeft, colorBlended); } } // Secondary color? - if(haveWall && color2) + if (haveWall && color2) { // Blend the secondary surface color tint with the sector light color. Vector3f const color2Blended = ::curSectorLightColor * (*color2); @@ -943,9 +993,9 @@ // Apply torch light? DENG2_ASSERT(::viewPlayer); - if(::viewPlayer->publicData().fixedColorMap) + if (::viewPlayer->publicData().fixedColorMap) { - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { Rend_ApplyTorchLight(verts.color[i], Rend_PointDist2D(posCoords[i])); } @@ -959,29 +1009,29 @@ { DENG2_ASSERT(posCoords); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.pos[i] = posCoords[i]; Vector3f const delta(posCoords[i] - topLeft); - if(verts.tex) // Primary. + if (verts.tex) // Primary. { verts.tex[i] = Vector2f(delta.x, -delta.y); } - if(verts.tex2) // Inter. + if (verts.tex2) // Inter. { verts.tex2[i] = Vector2f(delta.x, -delta.y); } } // Light the geometry? - if(useVertexLighting) + if (useVertexLighting) { lightWallOrFlatGeometry(verts, numVertices, posCoords, mapElement, geomGroup, surfaceTangents, color, color2, glowing, luminosityDeltas); // Apply uniform opacity (overwritting luminance factors). - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i].w = uniformOpacity; } @@ -996,27 +1046,27 @@ { DENG2_ASSERT(posCoords); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.pos[i] = posCoords[i]; } - if(verts.tex) // Primary. + if (verts.tex) // Primary. { quadTexCoords(verts.tex, posCoords, sectionWidth, topLeft); } - if(verts.tex2) // Inter. + if (verts.tex2) // Inter. { quadTexCoords(verts.tex2, posCoords, sectionWidth, topLeft); } // Light the geometry? - if(useVertexLighting) + if (useVertexLighting) { lightWallOrFlatGeometry(verts, numVertices, posCoords, mapElement, geomGroup, surfaceTangents, color, color2, glowing, luminosityDeltas); // Apply uniform opacity (overwritting luminance factors). - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i].w = uniformOpacity; } @@ -1033,14 +1083,14 @@ { DENG2_ASSERT(posCoords); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { Vector3f const eye = Rend_EyeOrigin(); // Determine distance to viewer. dfloat distToEye = (eye.xz() - Vector2f(posCoords[i])).normalize().length(); // Short distances produce an ugly 'crunch' below and above the viewpoint. - if(distToEye < 10) distToEye = 10; + if (distToEye < 10) distToEye = 10; // Offset from the normal view plane. dfloat offset = ((eye.y - posCoords[i].y) * sin(.4f)/*viewFrontVec[0]*/ - @@ -1050,7 +1100,7 @@ shineVertical(eye.y - posCoords[i].z, distToEye)); } - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = Vector4f(Vector3f(mainVerts.color[i]).max(shineColor), shineOpacity); } @@ -1071,7 +1121,7 @@ // Calculate coordinates based on viewpoint and surface normal. Vector3f const eye = Rend_EyeOrigin(); dfloat prevAngle = 0; - for(duint i = 0; i < 2; ++i) + for (duint i = 0; i < 2; ++i) { Vector2f const eyeToVert = eye.xz() - (i == 0? Vector2f(topLeft) : Vector2f(bottomRight)); dfloat const distToEye = eyeToVert.length(); @@ -1079,23 +1129,23 @@ Vector2f projected; dfloat const div = normal.lengthSquared(); - if(div != 0) + if (div != 0) { projected = normal * view.dot(normal) / div; } Vector2f const reflected = view + (projected - view) * 2; dfloat angle = std::acos(reflected.y) / PI; - if(reflected.x < 0) + if (reflected.x < 0) { angle = 1 - angle; } - if(i == 0) + if (i == 0) { prevAngle = angle; } - else if(angle > prevAngle) + else if (angle > prevAngle) { angle -= 1; } @@ -1109,7 +1159,7 @@ verts.tex[ (i == 0 ? 1 : 3) ].y = shineVertical(eye.y - topLeft.z, distToEye); } - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = Vector4f(Vector3f(mainVerts.color[i]).max(shineColor), shineOpactiy); } @@ -1122,7 +1172,7 @@ DENG2_ASSERT(posCoords); Vector4f const colorClamped = tp.color.min(Vector4f(1, 1, 1, 1)).max(Vector4f(0, 0, 0, 0)); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = colorClamped; } @@ -1130,7 +1180,7 @@ dfloat const width = bottomRight.x - topLeft.x; dfloat const height = bottomRight.y - topLeft.y; - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.tex[i].x = ((bottomRight.x - posCoords[i].x) / width * tp.topLeft.x) + ((posCoords[i].x - topLeft.x) / width * tp.bottomRight.x); @@ -1149,7 +1199,7 @@ DENG2_ASSERT(posCoords); Vector4f const colorClamped = tp.color.min(Vector4f(1, 1, 1, 1)).max(Vector4f(0, 0, 0, 0)); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = colorClamped; } @@ -1160,7 +1210,7 @@ verts.tex[2].y = verts.tex[0].y = tp.bottomRight.y; // If either edge has divisions - make two trifans. - if(leftEdge.divisionCount() || rightEdge.divisionCount()) + if (leftEdge.divisionCount() || rightEdge.divisionCount()) { // Need to swap indices around into fans set the position of the // division vertices, interpolate texcoords and color. @@ -1186,14 +1236,14 @@ DENG2_ASSERT(posCoords); Vector4f const colorClamped = tp.color.min(Vector4f(1, 1, 1, 1)).max(Vector4f(0, 0, 0, 0)); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = colorClamped; } dfloat const width = bottomRight.x - topLeft.x; dfloat const height = bottomRight.y - topLeft.y; - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.tex[i].x = ((bottomRight.x - posCoords[i].x) / width * tp.topLeft.x) + ((posCoords[i].x - topLeft.x) / width * tp.bottomRight.x); @@ -1212,7 +1262,7 @@ DENG2_ASSERT(posCoords); Vector4f const colorClamped = tp.color.min(Vector4f(1, 1, 1, 1)).max(Vector4f(0, 0, 0, 0)); - for(duint i = 0; i < numVertices; ++i) + for (duint i = 0; i < numVertices; ++i) { verts.color[i] = colorClamped; } @@ -1223,7 +1273,7 @@ verts.tex[2].y = verts.tex[0].y = tp.bottomRight.y; // If either edge has divisions - make two trifans. - if(leftEdge.divisionCount() || rightEdge.divisionCount()) + if (leftEdge.divisionCount() || rightEdge.divisionCount()) { // Need to swap indices around into fans set the position // of the division vertices, interpolate texcoords and color. @@ -1246,7 +1296,7 @@ { DENG2_ASSERT(rgbaValues); dfloat avg = 0; - for(duint i = 0; i < count; ++i) + for (duint i = 0; i < count; ++i) { Vector4f const &color = rgbaValues[i]; avg += color.x + color.y + color.z; @@ -1919,7 +1969,7 @@ } } - if(shineRTU) + if (shineRTU) { // Make shine geometry. // Surface shine geometry (primary texture and color coords). @@ -2085,23 +2135,23 @@ Lumobj const &lum, Surface const &surface, dfloat blendFactor, ProjectedTextureData &projected) { - if(blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) + if (blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) return false; // Has this already been occluded? - if(R_ViewerLumobjIsHidden(lum.indexInMap())) + if (R_ViewerLumobjIsHidden(lum.indexInMap())) return false; // No lightmap texture? DGLuint tex = prepareLightmap(lum.lightmap(lightmapForSurface(surface))); - if(!tex) return false; + if (!tex) return false; Vector3d lumCenter = lum.origin(); lumCenter.z += lum.zOffset(); // On the right side? Vector3d topLeftToLum = topLeft - lumCenter; - if(topLeftToLum.dot(surface.tangentMatrix().column(2)) > 0.f) + if (topLeftToLum.dot(surface.tangentMatrix().column(2)) > 0.f) return false; // Calculate 3D distance between surface and lumobj. @@ -2109,7 +2159,7 @@ topLeft, lumCenter); coord_t distToLum = (lumCenter - pointOnPlane).length(); - if(distToLum <= 0 || distToLum > lum.radius()) + if (distToLum <= 0 || distToLum > lum.radius()) return false; // Calculate the final surface light attribution factor. @@ -2119,17 +2169,17 @@ luma *= lum.attenuation(R_ViewerLumobjDistance(lum.indexInMap())); // Would this be seen? - if(luma * blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) + if (luma * blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) return false; // Project, counteracting aspect correction slightly. Vector2f s, t; dfloat const scale = 1.0f / ((2.f * lum.radius()) - distToLum); - if(!R_GenerateTexCoords(s, t, pointOnPlane, scale, scale * 1.08f, + if (!R_GenerateTexCoords(s, t, pointOnPlane, scale, scale * 1.08f, topLeft, bottomRight, surface.tangentMatrix())) return false; - de::zap(projected); + projected = {}; projected.texture = tex; projected.topLeft = Vector2f(s[0], t[0]); projected.bottomRight = Vector2f(s[1], t[1]); @@ -2142,22 +2192,22 @@ Plane const &plane, Vector3d const &pointOnPlane, dfloat blendFactor, ProjectedTextureData &projected) { - if(blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) + if (blendFactor < OMNILIGHT_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) return false; Vector3f color; dfloat intensity = plane.surface().glow(color); // Is the material glowing at this moment? - if(intensity < .05f) + if (intensity < .05f) return false; coord_t glowHeight = Rend_PlaneGlowHeight(intensity); - if(glowHeight < 2) return false; // Not too small! + if (glowHeight < 2) return false; // Not too small! // Calculate coords. dfloat bottom, top; - if(plane.surface().normal().z < 0) + if (plane.surface().normal().z < 0) { // Cast downward. bottom = (pointOnPlane.z - topLeft.z) / glowHeight; @@ -2171,7 +2221,7 @@ } // Within range on the Z axis? - if(!(bottom <= 1 || top >= 0)) return false; + if (!(bottom <= 1 || top >= 0)) return false; de::zap(projected); projected.texture = GL_PrepareLSTexture(LST_GRADIENT); @@ -2192,28 +2242,28 @@ // Is this too far? coord_t distanceFromViewer = 0; - if(shadowMaxDistance > 0) + if (shadowMaxDistance > 0) { distanceFromViewer = Rend_PointDist2D(mobOrigin); - if(distanceFromViewer > shadowMaxDistance) + if (distanceFromViewer > shadowMaxDistance) return false; } dfloat shadowStrength = Mobj_ShadowStrength(mob) * ::shadowFactor; - if(fogParams.usingFog) shadowStrength /= 2; - if(shadowStrength <= 0) return false; + if (fogParams.usingFog) shadowStrength /= 2; + if (shadowStrength <= 0) return false; coord_t shadowRadius = Mobj_ShadowRadius(mob); - if(shadowRadius > ::shadowMaxRadius) + if (shadowRadius > ::shadowMaxRadius) shadowRadius = ::shadowMaxRadius; - if(shadowRadius <= 0) return false; + if (shadowRadius <= 0) return false; mobOrigin[2] -= mob.floorClip; - if(mob.ddFlags & DDMF_BOB) + if (mob.ddFlags & DDMF_BOB) mobOrigin[2] -= Mobj_BobOffset(mob); coord_t mobHeight = mob.height; - if(!mobHeight) mobHeight = 1; + if (!mobHeight) mobHeight = 1; // If this were a light this is where we would check whether the origin is on // the right side of the surface. However this is a shadow and light is moving @@ -2226,11 +2276,11 @@ coord_t distFromSurface = (Vector3d(mobOrigin) - Vector3d(point)).length(); // Too far above or below the shadowed surface? - if(distFromSurface > mob.height) + if (distFromSurface > mob.height) return false; - if(mobOrigin[2] + mob.height < point.z) + if (mobOrigin[2] + mob.height < point.z) return false; - if(distFromSurface > shadowRadius) + if (distFromSurface > shadowRadius) return false; // Calculate the final strength of the shadow's attribution to the surface. @@ -2238,7 +2288,7 @@ // Fade at half mobj height for smooth fade out when embedded in the surface. coord_t halfMobjHeight = mobHeight / 2; - if(distFromSurface > halfMobjHeight) + if (distFromSurface > halfMobjHeight) { shadowStrength *= 1 - (distFromSurface - halfMobjHeight) / (mobHeight - halfMobjHeight); } @@ -2248,13 +2298,13 @@ shadowStrength *= blendFactor; // Would this shadow be seen? - if(shadowStrength < SHADOW_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) + if (shadowStrength < SHADOW_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) return false; // Project, counteracting aspect correction slightly. Vector2f s, t; dfloat const scale = 1.0f / ((2.f * shadowRadius) - distFromSurface); - if(!R_GenerateTexCoords(s, t, point, scale, scale * 1.08f, + if (!R_GenerateTexCoords(s, t, point, scale, scale * 1.08f, topLeft, bottomRight, surface.tangentMatrix())) return false; @@ -2278,15 +2328,15 @@ { DENG2_ASSERT(curSubspace); - if(levelFullBright) return; - if(glowStrength >= 1) return; + if (levelFullBright) return; + if (glowStrength >= 1) return; // lights? - if(!noLights) + if (!noLights) { dfloat const blendFactor = 1; - if(::useDynLights) + if (::useDynLights) { // Project all lumobjs affecting the given quad (world space), calculate // coordinates (in texture space) then store into a new list of projections. @@ -2295,7 +2345,7 @@ , &lightListIdx] (Lumobj &lum) { ProjectedTextureData projected; - if(projectDynlight(topLeft, bottomRight, lum, surface, blendFactor, + if (projectDynlight(topLeft, bottomRight, lum, surface, blendFactor, projected)) { ClientApp::renderSystem().findSurfaceProjectionList(&lightListIdx, sortLights) @@ -2305,18 +2355,18 @@ }); } - if(::useGlowOnWalls && surface.parent().type() == DMU_SIDE && bottomRight.z < topLeft.z) + if (::useGlowOnWalls && surface.parent().type() == DMU_SIDE && bottomRight.z < topLeft.z) { // Project all plane glows affecting the given quad (world space), calculate // coordinates (in texture space) then store into a new list of projections. auto const &subsec = curSubspace->subsector().as(); - for(dint i = 0; i < subsec.visPlaneCount(); ++i) + for (dint i = 0; i < subsec.visPlaneCount(); ++i) { Plane const &plane = subsec.visPlane(i); Vector3d const pointOnPlane(subsec.center(), plane.heightSmoothed()); ProjectedTextureData projected; - if(projectPlaneGlow(topLeft, bottomRight, plane, pointOnPlane, blendFactor, + if (projectPlaneGlow(topLeft, bottomRight, plane, pointOnPlane, blendFactor, projected)) { ClientApp::renderSystem().findSurfaceProjectionList(&lightListIdx, sortLights) @@ -2327,11 +2377,11 @@ } // Shadows? - if(!noShadows && ::useShadows) + if (!noShadows && ::useShadows) { // Glow inversely diminishes shadow strength. dfloat blendFactor = 1 - glowStrength; - if(blendFactor >= SHADOW_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) + if (blendFactor >= SHADOW_SURFACE_LUMINOSITY_ATTRIBUTION_MIN) { blendFactor = de::clamp(0.f, blendFactor, 1.f); @@ -2341,7 +2391,7 @@ , &blendFactor, &shadowListIdx] (mobj_t &mob) { ProjectedTextureData projected; - if(projectShadow(topLeft, bottomRight, mob, surface, blendFactor, + if (projectShadow(topLeft, bottomRight, mob, surface, blendFactor, projected)) { ClientApp::renderSystem().findSurfaceProjectionList(&shadowListIdx) @@ -2362,12 +2412,12 @@ { static Vector3f const worldLight(-.400891f, -.200445f, .601336f); - de::zap(vlight); + vlight = {}; vlight.direction = worldLight; vlight.color = ambientColor; vlight.affectedByAmbient = false; vlight.approxDist = 0; - if(starkLight) + if (starkLight) { vlight.lightSide = .35f; vlight.darkSide = .5f; @@ -2392,13 +2442,13 @@ lumCenter.y - point.y), point.z - lumCenter.z); dfloat intensity = 0; - if(dist < Lumobj::radiusMax()) + if (dist < Lumobj::radiusMax()) { intensity = de::clamp(0.f, dfloat(1 - dist / lum.radius()) * 2, 1.f); } - if(intensity < .05f) return false; + if (intensity < .05f) return false; - de::zap(vlight); + vlight = {}; vlight.direction = (lumCenter - point) / dist; vlight.color = lum.color() * intensity; vlight.affectedByAmbient = true; @@ -2419,23 +2469,23 @@ // Glowing at this moment? Vector3f glowColor; dfloat intensity = surface.glow(glowColor); - if(intensity < .05f) return false; + if (intensity < .05f) return false; coord_t const glowHeight = Rend_PlaneGlowHeight(intensity); - if(glowHeight < 2) return false; // Not too small! + if (glowHeight < 2) return false; // Not too small! // In front of the plane? Vector3d const pointOnPlane(subsec.center(), plane.heightSmoothed()); ddouble const dist = (point - pointOnPlane).dot(surface.normal()); - if(dist < 0) return false; + if (dist < 0) return false; intensity *= 1 - dist / glowHeight; - if(intensity < .05f) return false; + if (intensity < .05f) return false; Vector3f const color = Rend_LuminousColor(glowColor, intensity); - if(color == Vector3f()) return false; + if (color == Vector3f()) return false; - de::zap(vlight); + vlight = {}; vlight.direction = Vector3f(surface.normal().x, surface.normal().y, -surface.normal().z); vlight.color = color; vlight.affectedByAmbient = true; @@ -2455,7 +2505,7 @@ // Always apply an ambient world light. { VectorLightData vlight; - if(lightWithWorldLight(point, ambientColor, starkLight, vlight)) + if (lightWithWorldLight(point, ambientColor, starkLight, vlight)) { ClientApp::renderSystem().findVectorLightList(&lightListIdx) << vlight; // a copy is made. @@ -2463,14 +2513,14 @@ } // Add extra light by interpreting nearby sources. - if(subspace) + if (subspace) { // Interpret lighting from luminous-objects near the origin and which // are in contact the specified subspace and add them to the identified list. R_ForAllSubspaceLumContacts(*subspace, [&point, &lightListIdx] (Lumobj &lum) { VectorLightData vlight; - if(lightWithLumobj(point, lum, vlight)) + if (lightWithLumobj(point, lum, vlight)) { ClientApp::renderSystem().findVectorLightList(&lightListIdx) << vlight; // a copy is made. @@ -2481,10 +2531,10 @@ // Interpret vlights from glowing planes at the origin in the specfified // subspace and add them to the identified list. auto const &subsec = subspace->subsector().as(); - for(dint i = 0; i < subsec.sector().planeCount(); ++i) + for (dint i = 0; i < subsec.sector().planeCount(); ++i) { VectorLightData vlight; - if(lightWithPlaneGlow(point, subsec, i, vlight)) + if (lightWithPlaneGlow(point, subsec, i, vlight)) { ClientApp::renderSystem().findVectorLightList(&lightListIdx) << vlight; // a copy is made. @@ -2508,10 +2558,10 @@ static bool applyNearFadeOpacity(WallEdge const &leftEdge, WallEdge const &rightEdge, dfloat &opacity) { - if(!leftEdge.spec().flags.testFlag(WallSpec::NearFade)) + if (!leftEdge.spec().flags.testFlag(WallSpec::NearFade)) return false; - if(Rend_EyeOrigin().y < leftEdge.bottom().z() || Rend_EyeOrigin().y > rightEdge.top().z()) + if (Rend_EyeOrigin().y < leftEdge.bottom().z() || Rend_EyeOrigin().y > rightEdge.top().z()) return false; mobj_t const *mo = viewPlayer->publicData().mo; @@ -2522,7 +2572,7 @@ vec2d_t result; ddouble pos = V2d_ProjectOnLine(result, mo->origin, linePoint, lineDirection); - if(!(pos > 0 && pos < 1)) + if (!(pos > 0 && pos < 1)) return false; coord_t const maxDistance = Mobj_Radius(*mo) * .8f; @@ -2530,10 +2580,10 @@ auto delta = Vector2d(result) - Vector2d(mo->origin); coord_t distance = delta.length(); - if(de::abs(distance) > maxDistance) + if (de::abs(distance) > maxDistance) return false; - if(distance > 0) + if (distance > 0) { opacity = (opacity / maxDistance) * distance; opacity = de::clamp(0.f, opacity, 1.f); @@ -2559,7 +2609,7 @@ dfloat &leftDelta = luminosityDeltas[0]; dfloat &rightDelta = luminosityDeltas[1]; - if(leftEdge.spec().flags.testFlag(WallSpec::NoLightDeltas)) + if (leftEdge.spec().flags.testFlag(WallSpec::NoLightDeltas)) { leftDelta = rightDelta = 0; return; @@ -2567,7 +2617,7 @@ leftDelta = wallLuminosityDeltaFromNormal(leftEdge.normal()); - if(leftEdge.normal() == rightEdge.normal()) + if (leftEdge.normal() == rightEdge.normal()) { rightDelta = leftDelta; } @@ -2686,7 +2736,7 @@ // Geometry write/drawing begins. // - if(twoSidedMiddle && side.sectorPtr() != &subsec.sector()) + if (twoSidedMiddle && side.sectorPtr() != &subsec.sector()) { // Temporarily modify the draw state. curSectorLightColor = Rend_AmbientLightColor(side.sector()); @@ -2704,12 +2754,12 @@ bool const wroteOpaque = renderWorldPoly(posCoords, 4, parm, matAnimator); // Draw FakeRadio for this wall? - if(wroteOpaque && !skyMasked && !(parm.glowing > 0)) + if (wroteOpaque && !skyMasked && !(parm.glowing > 0)) { Rend_DrawWallRadio(leftEdge, rightEdge, ::curSectorLightLevel); } - if(twoSidedMiddle && side.sectorPtr() != &subsec.sector()) + if (twoSidedMiddle && side.sectorPtr() != &subsec.sector()) { // Undo temporary draw state changes. Vector4f const color = subsec.lightSourceColorfIntensity(); @@ -2717,9 +2767,9 @@ curSectorLightLevel = color.w; } - if(retWroteOpaque) *retWroteOpaque = wroteOpaque && !didNearFade; - if(retBottomZ) *retBottomZ = leftEdge .bottom().z(); - if(retTopZ) *retTopZ = rightEdge.top ().z(); + if (retWroteOpaque) *retWroteOpaque = wroteOpaque && !didNearFade; + if (retBottomZ) *retBottomZ = leftEdge .bottom().z(); + if (retTopZ) *retTopZ = rightEdge.top ().z(); } /** @@ -2747,7 +2797,7 @@ *verts = R_AllocRendVertices(totalVerts); duint n = 0; - if(!fanBase) + if (!fanBase) { (*verts)[n] = Vector3f(poly.center(), height); n++; @@ -2760,10 +2810,10 @@ { (*verts)[n] = Vector3f(node->origin(), height); n++; - } while((node = &node->neighbor(direction)) != baseNode); + } while ((node = &node->neighbor(direction)) != baseNode); // The last vertex is always equal to the first. - if(!fanBase) + if (!fanBase) { (*verts)[n] = Vector3f(poly.hedge()->origin(), height); } @@ -2778,15 +2828,15 @@ // Skip nearly transparent surfaces. dfloat const opacity = surface.opacity(); - if(opacity < .001f) return; + if (opacity < .001f) return; // Determine which Material to use (a drawable material is required). ClientMaterial *material = Rend_ChooseMapSurfaceMaterial(surface); - if(!material || !material->isDrawable()) + if (!material || !material->isDrawable()) return; // Skip planes with a sky-masked material (drawn with the mask geometry)? - if(!::devRendSkyMode && surface.hasSkyMaskedMaterial() && plane.indexInSector() <= Sector::Ceiling) + if (!::devRendSkyMode && surface.hasSkyMaskedMaterial() && plane.indexInSector() <= Sector::Ceiling) return; MaterialAnimator &matAnimator = material->getAnimator(Rend_MapSurfaceMaterialSpec()); @@ -2795,7 +2845,7 @@ + surface.originSmoothed(); // Add the Y offset to orient the Y flipped material. /// @todo fixme: What is this meant to do? -ds - if(plane.isSectorCeiling()) + if (plane.isSectorCeiling()) { materialOrigin.y -= poly.bounds().maxY - poly.bounds().minY; } @@ -2821,11 +2871,11 @@ parm.surfaceColor = &surface.color(); parm.surfaceTangentMatrix = &surface.tangentMatrix(); - if(material->isSkyMasked()) + if (material->isSkyMasked()) { // In devRendSkyMode mode we render all polys destined for the // skymask as regular world polys (with a few obvious properties). - if(devRendSkyMode) + if (devRendSkyMode) { parm.blendMode = BM_NORMAL; parm.forceOpaque = true; @@ -2836,7 +2886,7 @@ parm.skyMasked = true; } } - else if(plane.indexInSector() <= Sector::Ceiling) + else if (plane.indexInSector() <= Sector::Ceiling) { parm.blendMode = BM_NORMAL; parm.forceOpaque = true; @@ -2844,7 +2894,7 @@ else { parm.blendMode = surface.blendMode(); - if(parm.blendMode == BM_NORMAL && noSpriteTrans) + if (parm.blendMode == BM_NORMAL && noSpriteTrans) { parm.blendMode = BM_ZEROALPHA; // "no translucency" mode } @@ -2852,11 +2902,11 @@ parm.alpha = surface.opacity(); } - if(!parm.skyMasked) + if (!parm.skyMasked) { - if(glowFactor > .0001f) + if (glowFactor > .0001f) { - if(material == surface.materialPtr()) + if (material == surface.materialPtr()) { parm.glowing = matAnimator.glowStrength(); } @@ -2881,7 +2931,7 @@ // Geometry write/drawing begins. // - if(&plane.sector() != &curSubspace->subsector().sector()) + if (&plane.sector() != &curSubspace->subsector().sector()) { // Temporarily modify the draw state. curSectorLightColor = Rend_AmbientLightColor(plane.sector()); @@ -2896,7 +2946,7 @@ // Draw this section. renderWorldPoly(posCoords, vertCount, parm, matAnimator); - if(&plane.sector() != &curSubspace->subsector().sector()) + if (&plane.sector() != &curSubspace->subsector().sector()) { // Undo temporary draw state changes. Vector4f const color = curSubspace->subsector().as().lightSourceColorfIntensity(); @@ -2914,12 +2964,12 @@ static DrawList::Indices indices; - if(!devRendSkyMode) + if (!devRendSkyMode) { Store &buffer = ClientApp::renderSystem().buffer(); duint base = buffer.allocateVertices(vertCount); DrawList::reserveSpace(indices, vertCount); - for(dint i = 0; i < vertCount; ++i) + for (dint i = 0; i < vertCount; ++i) { indices[i] = base + i; buffer.posCoords[indices[i]] = posCoords[i]; @@ -2933,7 +2983,7 @@ DrawListSpec listSpec; listSpec.group = UnlitGeom; - if(renderTextures != 2) + if (renderTextures != 2) { DENG2_ASSERT(material); MaterialAnimator &matAnimator = material->as().getAnimator(Rend_MapSurfaceMaterialSpec()); @@ -2951,7 +3001,7 @@ Store &buffer = ClientApp::renderSystem().buffer(); duint base = buffer.allocateVertices(vertCount); DrawList::reserveSpace(indices, vertCount); - for(dint i = 0; i < vertCount; ++i) + for (dint i = 0; i < vertCount; ++i) { indices[i] = base + i; buffer.posCoords [indices[i]] = posCoords[i]; @@ -2996,7 +3046,7 @@ { // Are we monitoring material changes? Material *skyMaterial = nullptr; - if(splitOnMaterialChange) + if (splitOnMaterialChange) { skyMaterial = hedge->face().mapElementAs() .subsector().as() @@ -3004,7 +3054,7 @@ } // Add a first (left) edge to the current strip? - if(!scanNode && hedge->hasMapElement()) + if (!scanNode && hedge->hasMapElement()) { scanMaterialOffset = hedge->mapElementAs().lineSideOffset(); @@ -3012,7 +3062,7 @@ SkyFixEdge skyEdge(*hedge, fixType, (direction == Anticlockwise ? Line::To : Line::From), scanMaterialOffset); - if(skyEdge.isValid() && skyEdge.bottom().z() < skyEdge.top().z()) + if (skyEdge.isValid() && skyEdge.bottom().z() < skyEdge.top().z()) { // A new strip begins. stripBuilder.begin(direction); @@ -3029,11 +3079,11 @@ bool beginNewStrip = false; // Add the i'th (right) edge to the current strip? - if(scanNode) + if (scanNode) { // Stop if we've reached a "null" edge. bool endStrip = false; - if(hedge->hasMapElement()) + if (hedge->hasMapElement()) { scanMaterialOffset += hedge->mapElementAs().length() * (direction == Anticlockwise? -1 : 1); @@ -3042,12 +3092,12 @@ SkyFixEdge skyEdge(*hedge, fixType, (direction == Anticlockwise)? Line::From : Line::To, scanMaterialOffset); - if(!(skyEdge.isValid() && skyEdge.bottom().z() < skyEdge.top().z())) + if (!(skyEdge.isValid() && skyEdge.bottom().z() < skyEdge.top().z())) { endStrip = true; } // Must we split the strip here? - else if(hedge != scanNode && + else if (hedge != scanNode && ( !de::fequal(skyEdge.bottom().z(), scanZBottom) || !de::fequal(skyEdge.top ().z(), scanZTop) || (splitOnMaterialChange && skyMaterial != scanMaterial))) @@ -3066,7 +3116,7 @@ endStrip = true; } - if(endStrip || &hedge->neighbor(direction) == base) + if (endStrip || &hedge->neighbor(direction) == base) { // End the current strip. scanNode = nullptr; @@ -3087,13 +3137,13 @@ } // Start a new strip from the current node? - if(beginNewStrip) continue; + if (beginNewStrip) continue; // On to the next node. hedge = &hedge->neighbor(direction); // Are we done? - if(hedge == base) break; + if (hedge == base) break; } } @@ -3116,7 +3166,7 @@ duint const vertCount = poly.hedgeCount() + (!fanBase? 2 : 0); duint const base = verts.allocateVertices(vertCount); DrawList::reserveSpace(indices, vertCount); - for(duint i = 0; i < vertCount; ++i) + for (duint i = 0; i < vertCount; ++i) { indices[i] = base + i; } @@ -3126,7 +3176,7 @@ // primitive = gl::TriangleFan; duint n = 0; - if(!fanBase) + if (!fanBase) { verts.posCoords[indices[n++]] = Vector3f(poly.center(), worldZPosition); } @@ -3135,8 +3185,8 @@ do { verts.posCoords[indices[n++]] = Vector3f(node->origin(), worldZPosition); - } while((node = &node->neighbor(direction)) != baseNode); - if(!fanBase) + } while ((node = &node->neighbor(direction)) != baseNode); + if (!fanBase) { verts.posCoords[indices[n ]] = Vector3f(node->origin(), worldZPosition); } @@ -3247,7 +3297,7 @@ if (wroteOpaqueMiddle && middleCoversOpening) return true; - if( (bceil <= ffloor && (front.top ().hasMaterial() || front.middle().hasMaterial())) + if ( (bceil <= ffloor && (front.top ().hasMaterial() || front.middle().hasMaterial())) || (bfloor >= fceil && (front.bottom().hasMaterial() || front.middle().hasMaterial()))) { Surface const &ffloorSurface = subsec.visFloor ().surface(); @@ -3329,11 +3379,11 @@ do { writeAllWalls(*hedge); - } while((hedge = &hedge->next()) != base); + } while ((hedge = &hedge->next()) != base); ::curSubspace->forAllExtraMeshes([] (Mesh &mesh) { - for(HEdge *hedge : mesh.hedges()) + for (HEdge *hedge : mesh.hedges()) { writeAllWalls(*hedge); } @@ -3342,7 +3392,7 @@ ::curSubspace->forAllPolyobjs([] (Polyobj &pob) { - for(HEdge *hedge : pob.mesh().hedges()) + for (HEdge *hedge : pob.mesh().hedges()) { writeAllWalls(*hedge); } @@ -3368,7 +3418,7 @@ static void markFrontFacingWalls(HEdge &hedge) { - if(!hedge.hasMapElement()) return; + if (!hedge.hasMapElement()) return; // Which way is the line segment facing? hedge.mapElementAs() .setFrontFacing(viewFacingDot(hedge.origin(), hedge.twin().origin()) >= 0); @@ -3384,11 +3434,11 @@ do { markFrontFacingWalls(*hedge); - } while((hedge = &hedge->next()) != base); + } while ((hedge = &hedge->next()) != base); ::curSubspace->forAllExtraMeshes([] (Mesh &mesh) { - for(HEdge *hedge : mesh.hedges()) + for (HEdge *hedge : mesh.hedges()) { markFrontFacingWalls(*hedge); } @@ -3397,7 +3447,7 @@ ::curSubspace->forAllPolyobjs([] (Polyobj &pob) { - for(HEdge *hedge : pob.mesh().hedges()) + for (HEdge *hedge : pob.mesh().hedges()) { markFrontFacingWalls(*hedge); } @@ -3513,7 +3563,7 @@ DENG2_ASSERT(::curSubspace); // Any work to do? - if(!::curSubspace->polyobjCount()) + if (!::curSubspace->polyobjCount()) return; ::curSubspace->forAllLumobjs([] (Lumobj &lob) @@ -3526,13 +3576,13 @@ /// If not front facing this is no-op. static void clipFrontFacingWalls(HEdge &hedge) { - if(!hedge.hasMapElement()) + if (!hedge.hasMapElement()) return; auto &seg = hedge.mapElementAs(); - if(seg.isFrontFacing()) + if (seg.isFrontFacing()) { - if(!ClientApp::renderSystem().angleClipper().checkRangeFromViewRelPoints(hedge.origin(), hedge.twin().origin())) + if (!ClientApp::renderSystem().angleClipper().checkRangeFromViewRelPoints(hedge.origin(), hedge.twin().origin())) { seg.setFrontFacing(false); } @@ -3549,11 +3599,11 @@ do { clipFrontFacingWalls(*hedge); - } while((hedge = &hedge->next()) != base); + } while ((hedge = &hedge->next()) != base); ::curSubspace->forAllExtraMeshes([] (Mesh &mesh) { - for(HEdge *hedge : mesh.hedges()) + for (HEdge *hedge : mesh.hedges()) { clipFrontFacingWalls(*hedge); } @@ -3562,7 +3612,7 @@ ::curSubspace->forAllPolyobjs([] (Polyobj &pob) { - for(HEdge *hedge : pob.mesh().hedges()) + for (HEdge *hedge : pob.mesh().hedges()) { clipFrontFacingWalls(*hedge); } @@ -3575,13 +3625,13 @@ DENG2_ASSERT(::curSubspace); // Do not use validCount because other parts of the renderer may change it. - if(::curSubspace->lastSpriteProjectFrame() == R_FrameCount()) + if (::curSubspace->lastSpriteProjectFrame() == R_FrameCount()) return; // Already added. R_ForAllSubspaceMobContacts(*::curSubspace, [] (mobj_t &mob) { auto const &subsec = ::curSubspace->subsector().as(); - if(mob.addFrameCount != R_FrameCount()) + if (mob.addFrameCount != R_FrameCount()) { mob.addFrameCount = R_FrameCount(); @@ -3590,24 +3640,24 @@ // Kludge: Map-objects have a tendency to extend into the ceiling in // sky sectors. Here we will raise the skyfix dynamically, to make // sure they don't get clipped by the sky. - if(subsec.visCeiling().surface().hasSkyMaskedMaterial()) + if (subsec.visCeiling().surface().hasSkyMaskedMaterial()) { /// @todo fixme: Consider 3D models, also. -ds - if(Record const *spriteRec = Mobj_SpritePtr(mob)) + if (Record const *spriteRec = Mobj_SpritePtr(mob)) { defn::Sprite const sprite(*spriteRec); de::Uri const &viewMaterial = sprite.viewMaterial(0); - if(!viewMaterial.isEmpty()) + if (!viewMaterial.isEmpty()) { - if(world::Material *material = world::Materials::get().materialPtr(viewMaterial)) + if (world::Material *material = world::Materials::get().materialPtr(viewMaterial)) { - if(!(mob.dPlayer && (mob.dPlayer->flags & DDPF_CAMERA)) + if (!(mob.dPlayer && (mob.dPlayer->flags & DDPF_CAMERA)) && mob.origin[2] <= subsec.visCeiling().heightSmoothed() && mob.origin[2] >= subsec.visFloor ().heightSmoothed()) { world::ClSkyPlane &skyCeiling = subsec.sector().map().skyCeiling(); ddouble visibleTop = mob.origin[2] + material->height(); - if(visibleTop > skyCeiling.height()) + if (visibleTop > skyCeiling.height()) { // Raise the ceiling! skyCeiling.setHeight(visibleTop + 16/*leeway*/); @@ -3655,7 +3705,7 @@ clipSubspaceLumobjsBySight(); // Mark generators in the sector visible. - if(::useParticles) + if (::useParticles) { sector.map().forAllGeneratorsInSector(sector, [] (Generator &gen) { @@ -3692,7 +3742,7 @@ ::curSubspace = &subspace; // Update draw state. - if(subsecChanged) + if (subsecChanged) { Vector4f const color = subspace.subsector().as().lightSourceColorfIntensity(); ::curSectorLightColor = color.toVector3f(); @@ -3705,7 +3755,7 @@ DENG2_ASSERT(bspTree); AngleClipper const &clipper = ClientApp::renderSystem().angleClipper(); - while(!bspTree->isLeaf()) + while (!bspTree->isLeaf()) { // Descend deeper into the nodes. auto const &bspNode = bspTree->userData()->as(); @@ -3718,7 +3768,7 @@ // If the clipper is full we're pretty much done. This means no geometry // will be visible in the distance because every direction has already // been fully covered by geometry. - if(!::firstSubspace && clipper.isFull()) + if (!::firstSubspace && clipper.isFull()) return; // ...and back space. @@ -3727,17 +3777,17 @@ // We've arrived at a leaf. // Only leafs with a convex subspace geometry contain surfaces to draw. - if(ConvexSubspace *subspace = bspTree->userData()->as().subspacePtr()) + if (ConvexSubspace *subspace = bspTree->userData()->as().subspacePtr()) { DENG2_ASSERT(subspace->hasSubsector()); // Skip zero-volume subspaces. // (Neighbors handle the angle clipper ranges.) - if(!subspace->subsector().as().hasWorldVolume()) + if (!subspace->subsector().as().hasWorldVolume()) return; // Is this subspace visible? - if(!::firstSubspace && !clipper.isPolyVisible(subspace->poly())) + if (!::firstSubspace && !clipper.isPolyVisible(subspace->poly())) return; // This is now the current subspace. @@ -3782,7 +3832,7 @@ de::Uri const &viewMaterial = sprite.viewMaterial(0); if (!viewMaterial.isEmpty()) { - if(world::Material *mat = world::Materials::get().materialPtr(viewMaterial)) + if (world::Material *mat = world::Materials::get().materialPtr(viewMaterial)) { matAnimator = &mat->as().getAnimator(Rend_SpriteMaterialSpec()); } @@ -3811,10 +3861,10 @@ // Always use the front view. /// @todo We could do better here... - //if(viewMaterial.isEmpty()) return nullptr; + //if (viewMaterial.isEmpty()) return nullptr; //world::Material *mat = world::Materials::get().materialPtr(viewMaterial); - //if(!mat) return nullptr; + //if (!mat) return nullptr; MaterialAnimator *matAnimator = Rend_SpriteMaterialAnimator(spriteDef); //mat->as().getAnimator(Rend_SpriteMaterialSpec()); if (!matAnimator) return nullptr; @@ -3847,14 +3897,14 @@ texUnitMap.fill(-1); - switch(mode) + switch (mode) { case DM_SKYMASK: GL_SelectTexUnits(0); - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); break; case DM_BLENDED: @@ -3866,106 +3916,106 @@ // The first texture unit is used for the main texture. texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord1; - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); // Fog is allowed during this pass. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); } - // All of the surfaces are opaque. - GLState::current().setBlend(false).apply(); + // All of the surfaces are opaque. + DGL_Disable(DGL_BLEND); break; case DM_LIGHT_MOD_TEXTURE: case DM_TEXTURE_PLUS_LIGHT: // Modulate sector light, dynamic light and regular texture. GL_SelectTexUnits(2); - if(mode == DM_LIGHT_MOD_TEXTURE) + if (mode == DM_LIGHT_MOD_TEXTURE) { texUnitMap[0] = AttributeSpec::ModTexCoord; texUnitMap[1] = AttributeSpec::TexCoord0; - GL_ModulateTexture(4); // Light * texture. + DGL_ModulateTexture(4); // Light * texture. } else { texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::ModTexCoord; - GL_ModulateTexture(5); // Texture + light. + DGL_ModulateTexture(5); // Texture + light. } - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); // Fog is allowed during this pass. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); } // All of the surfaces are opaque. - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); break; case DM_FIRST_LIGHT: // One light, no texture. GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::ModTexCoord; - GL_ModulateTexture(6); - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_ModulateTexture(6); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); // All of the surfaces are opaque. - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); break; case DM_BLENDED_FIRST_LIGHT: // One additive light, no texture. GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::ModTexCoord; - GL_ModulateTexture(7); // Add light, no color. - GLState::current().setAlphaTest(true).apply(); - GLState::current().setAlphaLimit(1 / 255.0f).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(7); // Add light, no color. + DGL_Enable(DGL_ALPHA_TEST); + DGL_SetFloat(DGL_ALPHA_LIMIT, 1 / 255.0f); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // All of the surfaces are opaque. - GLState::current().setBlend(true).apply(); - GLState::current().setBlendFunc(gl::One, gl::One).apply(); + DGL_Enable(DGL_BLEND); + DGL_BlendFunc(DGL_ONE, DGL_ONE); break; case DM_WITHOUT_TEXTURE: GL_SelectTexUnits(0); - GL_ModulateTexture(1); - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_ModulateTexture(1); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); // All of the surfaces are opaque. - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); break; case DM_LIGHTS: GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::TexCoord0; - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setAlphaLimit(1 / 255.0f).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_SetFloat(DGL_ALPHA_LIMIT, 1 / 255.0f); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); - LIBGUI_GL.glFogfv(GL_FOG_COLOR, black); + DGL_Enable(DGL_FOG); + DGL_Fogfv(DGL_FOG_COLOR, black); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); GL_BlendMode(BM_ADD); break; @@ -3975,67 +4025,64 @@ // The first texture unit is used for the main texture. texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord1; - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // All of the surfaces are opaque. - GLState::current().setBlend(true).apply(); - //glBlendFunc(GL_DST_COLOR, GL_ZERO); - GLState::current().setBlendFunc(gl::DestColor, gl::Zero).apply(); + DGL_Enable(DGL_BLEND); + DGL_BlendFunc(DGL_DST_COLOR, DGL_ZERO); break; case DM_UNBLENDED_TEXTURE_AND_DETAIL: texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord0; - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); // All of the surfaces are opaque. - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); // Fog is allowed. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); } break; case DM_UNBLENDED_MOD_TEXTURE_AND_DETAIL: texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord0; - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // All of the surfaces are opaque. - GLState::current().setBlend(true).apply(); - //glBlendFunc(GL_DST_COLOR, GL_ZERO); - GLState::current().setBlendFunc(gl::DestColor, gl::Zero).apply(); + DGL_Enable(DGL_BLEND); + DGL_BlendFunc(DGL_DST_COLOR, DGL_ZERO); break; case DM_ALL_DETAILS: GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::TexCoord0; - GL_ModulateTexture(0); - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(0); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // All of the surfaces are opaque. - GLState::current().setBlend(true).apply(); - //glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - GLState::current().setBlendFunc(gl::DestColor, gl::SrcColor).apply(); + DGL_Enable(DGL_BLEND); + DGL_BlendFunc(DGL_DST_COLOR, DGL_SRC_COLOR); // Use fog to fade the details, if fog is enabled. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); dfloat const midGray[] = { .5f, .5f, .5f, fogParams.fogColor[3] }; // The alpha is probably meaningless? - LIBGUI_GL.glFogfv(GL_FOG_COLOR, midGray); + DGL_Fogfv(DGL_FOG_COLOR, midGray); } break; @@ -4043,22 +4090,21 @@ GL_SelectTexUnits(2); texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord1; - GL_ModulateTexture(3); - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(3); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // All of the surfaces are opaque. - GLState::current().setBlend(true).apply(); - //glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); - GLState::current().setBlendFunc(gl::DestColor, gl::SrcColor).apply(); + DGL_Enable(DGL_BLEND); + DGL_BlendFunc(DGL_DST_COLOR, DGL_SRC_COLOR); // Use fog to fade the details, if fog is enabled. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); dfloat const midGray[] = { .5f, .5f, .5f, fogParams.fogColor[3] }; // The alpha is probably meaningless? - LIBGUI_GL.glFogfv(GL_FOG_COLOR, midGray); + DGL_Fogfv(DGL_FOG_COLOR, midGray); } break; @@ -4066,38 +4112,38 @@ // A bit like 'negative lights'. GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::TexCoord0; - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setAlphaLimit(1 / 255.0f).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_SetFloat(DGL_ALPHA_LIMIT, 1 / 255.0f); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); // Set normal fog, if it's enabled. - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); - LIBGUI_GL.glFogfv(GL_FOG_COLOR, fogParams.fogColor); + DGL_Enable(DGL_FOG); + DGL_Fogfv(DGL_FOG_COLOR, fogParams.fogColor); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); GL_BlendMode(BM_NORMAL); break; case DM_SHINY: GL_SelectTexUnits(1); texUnitMap[0] = AttributeSpec::TexCoord0; - GL_ModulateTexture(1); // 8 for multitexture - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(1); // 8 for multitexture + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); - if(fogParams.usingFog) + if (fogParams.usingFog) { // Fog makes the shininess diminish in the distance. - LIBGUI_GL.glEnable(GL_FOG); - LIBGUI_GL.glFogfv(GL_FOG_COLOR, black); + DGL_Enable(DGL_FOG); + DGL_Fogfv(DGL_FOG_COLOR, black); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); GL_BlendMode(BM_ADD); // Purely additive. break; @@ -4105,19 +4151,19 @@ GL_SelectTexUnits(2); texUnitMap[0] = AttributeSpec::TexCoord0; texUnitMap[1] = AttributeSpec::TexCoord1; // the mask - GL_ModulateTexture(8); // same as with details - GLState::current().setAlphaTest(false).apply(); - GLState::current().setDepthWrite(false).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_ModulateTexture(8); // same as with details + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LEQUAL); - if(fogParams.usingFog) + if (fogParams.usingFog) { // Fog makes the shininess diminish in the distance. - LIBGUI_GL.glEnable(GL_FOG); - LIBGUI_GL.glFogfv(GL_FOG_COLOR, black); + DGL_Enable(DGL_FOG); + DGL_Fogfv(DGL_FOG_COLOR, black); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); GL_BlendMode(BM_ADD); // Purely additive. break; @@ -4127,14 +4173,14 @@ static void popGLStateForPass(DrawMode mode) { - switch(mode) + switch (mode) { default: break; case DM_SKYMASK: GL_SelectTexUnits(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); break; case DM_BLENDED: @@ -4142,54 +4188,54 @@ // Intentional fall-through. case DM_ALL: - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); break; case DM_LIGHT_MOD_TEXTURE: case DM_TEXTURE_PLUS_LIGHT: GL_SelectTexUnits(1); - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); break; case DM_FIRST_LIGHT: - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlend(true).apply(); + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_BLEND); break; case DM_BLENDED_FIRST_LIGHT: - GL_ModulateTexture(1); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha).apply(); + DGL_ModulateTexture(1); + DGL_Disable(DGL_DEPTH_TEST); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); break; case DM_WITHOUT_TEXTURE: GL_SelectTexUnits(1); - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlend(true).apply(); + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_BLEND); break; case DM_LIGHTS: - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } GL_BlendMode(BM_NORMAL); break; @@ -4197,76 +4243,76 @@ case DM_MOD_TEXTURE: case DM_MOD_TEXTURE_MANY_LIGHTS: case DM_BLENDED_MOD_TEXTURE: - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha).apply(); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); break; case DM_UNBLENDED_TEXTURE_AND_DETAIL: - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlend(true).apply(); - if(fogParams.usingFog) + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_BLEND); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } break; case DM_UNBLENDED_MOD_TEXTURE_AND_DETAIL: - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha).apply(); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); break; case DM_ALL_DETAILS: - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha).apply(); - if(fogParams.usingFog) + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } break; case DM_BLENDED_DETAILS: GL_SelectTexUnits(1); - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - GLState::current().setBlendFunc(gl::SrcAlpha, gl::OneMinusSrcAlpha).apply(); - if(fogParams.usingFog) + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + DGL_BlendFunc(DGL_SRC_ALPHA, DGL_ONE_MINUS_SRC_ALPHA); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } break; case DM_SHADOW: - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } break; case DM_SHINY: - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } GL_BlendMode(BM_NORMAL); break; case DM_MASKED_SHINY: GL_SelectTexUnits(1); - GL_ModulateTexture(1); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setDepthTest(false).apply(); - if(fogParams.usingFog) + DGL_ModulateTexture(1); + DGL_Enable(DGL_ALPHA_TEST); + DGL_Disable(DGL_DEPTH_TEST); + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } GL_BlendMode(BM_NORMAL); break; @@ -4275,16 +4321,16 @@ static void drawLists(DrawLists::FoundLists const &lists, DrawMode mode) { - if(lists.isEmpty()) return; + if (lists.isEmpty()) return; // If the first list is empty -- do nothing. - if(lists.at(0)->isEmpty()) return; + if (lists.at(0)->isEmpty()) return; // Setup GL state that's common to all the lists in this mode. TexUnitMap texUnitMap; pushGLStateForPass(mode, texUnitMap); // Draw each given list. - for(dint i = 0; i < lists.count(); ++i) + for (dint i = 0; i < lists.count(); ++i) { lists.at(i)->draw(mode, texUnitMap); } @@ -4296,24 +4342,24 @@ { DrawLists::FoundLists lists; ClientApp::renderSystem().drawLists().findAll(SkyMaskGeom, lists); - if(!devRendSkyAlways && lists.isEmpty()) + if (!devRendSkyAlways && lists.isEmpty()) { return; } // We do not want to update color and/or depth. - GLState::push() - .setDepthTest(false) - .setDepthWrite(false) - .setColorMask(gl::WriteNone) - .apply(); + DGL_PushState(); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Disable(DGL_DEPTH_WRITE); + + GLState::current().setColorMask(gl::WriteNone); // Mask out stencil buffer, setting the drawn areas to 1. LIBGUI_GL.glEnable(GL_STENCIL_TEST); LIBGUI_GL.glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE); LIBGUI_GL.glStencilFunc(GL_ALWAYS, 1, 0xffffffff); - if(!devRendSkyAlways) + if (!devRendSkyAlways) { drawLists(lists, DM_SKYMASK); } @@ -4324,7 +4370,7 @@ } // Restore previous GL state. - GLState::pop().apply(); + DGL_PopState(); LIBGUI_GL.glDisable(GL_STENCIL_TEST); // Now, only render where the stencil is set to 1. @@ -4334,7 +4380,7 @@ ClientApp::renderSystem().sky().draw(&ClientApp::world().map().skyAnimator()); - if(!devRendSkyAlways) + if (!devRendSkyAlways) { LIBGUI_GL.glClearStencil(0); } @@ -4347,13 +4393,13 @@ { DENG2_ASSERT(spr); - if(primary && (spr->data.flare.flags & RFF_NO_PRIMARY)) + if (primary && (spr->data.flare.flags & RFF_NO_PRIMARY)) { return false; } dfloat occlusionFactor; - if(spr->data.flare.isDecoration) + if (spr->data.flare.isDecoration) { // Surface decorations do not yet persist over frames, so we do // not smoothly occlude their flares. Instead, we will have to @@ -4387,19 +4433,19 @@ */ static void drawMasked() { - if(::devNoSprites) return; + if (::devNoSprites) return; R_SortVisSprites(); - if(::visSpriteP && ::visSpriteP > ::visSprites) + if (::visSpriteP && ::visSpriteP > ::visSprites) { bool primaryHaloDrawn = false; // Draw all vissprites back to front. // Sprites look better with Z buffer writes turned off. - for(vissprite_t *spr = ::visSprSortedHead.next; spr != &::visSprSortedHead; spr = spr->next) + for (vissprite_t *spr = ::visSprSortedHead.next; spr != &::visSprSortedHead; spr = spr->next) { - switch(spr->type) + switch (spr->type) { default: break; @@ -4422,7 +4468,7 @@ break; case VSPR_FLARE: - if(generateHaloForVisSprite(spr, true)) + if (generateHaloForVisSprite(spr, true)) { primaryHaloDrawn = true; } @@ -4431,14 +4477,14 @@ } // Draw secondary halos? - if(primaryHaloDrawn && ::haloMode > 1) + if (primaryHaloDrawn && ::haloMode > 1) { // Now we can setup the state only once. H_SetupState(true); - for(vissprite_t *spr = ::visSprSortedHead.next; spr != &::visSprSortedHead; spr = spr->next) + for (vissprite_t *spr = ::visSprSortedHead.next; spr != &::visSprSortedHead; spr = spr->next) { - if(spr->type == VSPR_FLARE) + if (spr->type == VSPR_FLARE) { generateHaloForVisSprite(spr); } @@ -4458,7 +4504,7 @@ static void drawAllLists(Map &map) { DENG2_ASSERT(!Sys_GLCheckError()); - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); drawSky(); @@ -4470,7 +4516,7 @@ // DrawLists::FoundLists lists; ClientApp::renderSystem().drawLists().findAll(UnlitGeom, lists); - if(IS_MTEX_DETAILS) + if (IS_MTEX_DETAILS) { // Draw details for unblended surfaces in this pass. drawLists(lists, DM_UNBLENDED_TEXTURE_AND_DETAIL); @@ -4491,9 +4537,9 @@ // If multitexturing is available, we'll use it to our advantage when // rendering lights. - if(IS_MTEX_LIGHTS && dynlightBlend != 2) + if (IS_MTEX_LIGHTS && dynlightBlend != 2) { - if(IS_MUL) + if (IS_MUL) { // All (unblended) surfaces with exactly one light can be // rendered in a single pass. @@ -4518,14 +4564,14 @@ } else // Multitexturing is not available for lights. { - if(IS_MUL) + if (IS_MUL) { // Render all lit surfaces without a texture. drawLists(lists, DM_WITHOUT_TEXTURE); } else { - if(IS_MTEX_DETAILS) // Draw detail textures using multitexturing. + if (IS_MTEX_DETAILS) // Draw detail textures using multitexturing. { // Unblended surfaces with a detail. drawLists(lists, DM_UNBLENDED_TEXTURE_AND_DETAIL); @@ -4546,7 +4592,7 @@ // // Pass: All light geometries (always additive). // - if(dynlightBlend != 2) + if (dynlightBlend != 2) { ClientApp::renderSystem().drawLists().findAll(LightGeom, lists); drawLists(lists, DM_LIGHTS); @@ -4555,11 +4601,11 @@ // // Pass: Geometries with texture modulation. // - if(IS_MUL) + if (IS_MUL) { // Finish the lit surfaces that didn't yet get a texture. ClientApp::renderSystem().drawLists().findAll(LitGeom, lists); - if(IS_MTEX_DETAILS) + if (IS_MTEX_DETAILS) { drawLists(lists, DM_UNBLENDED_MOD_TEXTURE_AND_DETAIL); drawLists(lists, DM_BLENDED_MOD_TEXTURE); @@ -4567,7 +4613,7 @@ } else { - if(IS_MTEX_LIGHTS && dynlightBlend != 2) + if (IS_MTEX_LIGHTS && dynlightBlend != 2) { drawLists(lists, DM_MOD_TEXTURE_MANY_LIGHTS); } @@ -4584,11 +4630,11 @@ // If multitexturing is not available for details, we need to apply them as // an extra pass over all the detailed surfaces. // - if(r_detail) + if (r_detail) { // Render detail textures for all surfaces that need them. ClientApp::renderSystem().drawLists().findAll(UnlitGeom, lists); - if(IS_MTEX_DETAILS) + if (IS_MTEX_DETAILS) { // Blended detail textures. drawLists(lists, DM_BLENDED_DETAILS); @@ -4612,16 +4658,10 @@ // ClientApp::renderSystem().drawLists().findAll(ShineGeom, lists); - if(numTexUnits > 1) - { - // Render masked shiny surfaces in a separate pass. - drawLists(lists, DM_SHINY); - drawLists(lists, DM_MASKED_SHINY); - } - else - { - drawLists(lists, DM_ALL_SHINY); - } + + // Render masked shiny surfaces in a separate pass. + drawLists(lists, DM_SHINY); + drawLists(lists, DM_MASKED_SHINY); // // Pass: Shadow geometries (objects and Fake Radio). @@ -4635,19 +4675,19 @@ renderTextures = oldRenderTextures; - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); // The draw lists do not modify these states -ds - GLState::current().setBlend(true).apply(); - GLState::current().setDepthWrite(true).apply(); - GLState::current().setDepthTest(true).apply(); - GLState::current().setDepthFunc(gl::Less).apply(); - GLState::current().setAlphaTest(true).apply(); - GLState::current().setAlphaLimit(0).apply(); - if(fogParams.usingFog) + DGL_Enable(DGL_BLEND); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); + DGL_DepthFunc(DGL_LESS); + DGL_Enable(DGL_ALPHA_TEST); + DGL_SetFloat(DGL_ALPHA_LIMIT, 0); + if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); - LIBGUI_GL.glFogfv(GL_FOG_COLOR, fogParams.fogColor); + DGL_Enable(DGL_FOG); + DGL_Fogfv(DGL_FOG_COLOR, fogParams.fogColor); } // Draw masked walls, sprites and models. @@ -4656,9 +4696,9 @@ // Draw particles. Rend_RenderParticles(map); - if(fogParams.usingFog) + if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } DENG2_ASSERT(!Sys_GLCheckError()); @@ -4671,7 +4711,7 @@ // Setup the modelview matrix. Rend_ModelViewMatrix(); - if(!freezeRLs) + if (!freezeRLs) { // Prepare for rendering. ClientApp::renderSystem().beginFrame(); @@ -4683,7 +4723,7 @@ eyeOrigin = viewData->current.origin; // Add the backside clipping range (if vpitch allows). - if(vpitch <= 90 - yfov / 2 && vpitch >= -90 + yfov / 2) + if (vpitch <= 90 - yfov / 2 && vpitch >= -90 + yfov / 2) { AngleClipper &clipper = ClientApp::renderSystem().angleClipper(); @@ -4724,6 +4764,8 @@ //drawBiasEditingVisuals(map); //GL_SetMultisample(false); + + DGL_Flush(); } #if 0 @@ -4731,262 +4773,73 @@ { static dfloat const black[] = { 0, 0, 0, 0 }; - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x - size, origin.z, origin.y); - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x + size, origin.z, origin.y); - - LIBGUI_GL.glVertex3f(origin.x, origin.z - size, origin.y); - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x, origin.z + size, origin.y); - - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y - size); - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y + size); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x - size, origin.z, origin.y); + DGL_Color4f(color.x, color.y, color.z, color.w); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x + size, origin.z, origin.y); + + DGL_Vertex3f(origin.x, origin.z - size, origin.y); + DGL_Color4f(color.x, color.y, color.z, color.w); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x, origin.z + size, origin.y); + + DGL_Vertex3f(origin.x, origin.z, origin.y - size); + DGL_Color4f(color.x, color.y, color.z, color.w); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x, origin.z, origin.y + size); + DGL_End(); } #endif static void drawLabel(String const &label, Vector3d const &origin, dfloat scale, dfloat opacity) { - if(label.isEmpty()) return; + if (label.isEmpty()) return; - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glTranslatef(origin.x, origin.z, origin.y); - LIBGUI_GL.glRotatef(-vang + 180, 0, 1, 0); - LIBGUI_GL.glRotatef(vpitch, 1, 0, 0); - LIBGUI_GL.glScalef(-scale, -scale, 1); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Translatef(origin.x, origin.z, origin.y); + DGL_Rotatef(-vang + 180, 0, 1, 0); + DGL_Rotatef(vpitch, 1, 0, 0); + DGL_Scalef(-scale, -scale, 1); - Point2Raw offset(2, 2); + Point2Raw offset = {{{2, 2}}}; UI_TextOutEx(label.toUtf8().constData(), &offset, UI_Color(UIC_TITLE), opacity); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } static void drawLabel(String const &label, Vector3d const &origin, ddouble maxDistance = 2000) { ddouble const distToEye = (Rend_EyeOrigin().xzy() - origin).length(); - if(distToEye < maxDistance) + if (distToEye < maxDistance) { drawLabel(label, origin, distToEye / (DENG_GAMEVIEW_WIDTH / 2), 1 - distToEye / maxDistance); } } -/* - * Visuals for Shadow Bias editing: - */ - -#if 0 -static String labelForSource(BiasSource *s) -{ - if(!s || !editShowIndices) return String(); - /// @todo Don't assume the current map. - return String::number(App_World().map().indexOf(*s)); -} - -static void drawSource(BiasSource *s) -{ - if(!s) return; - - ddouble distToEye = (s->origin() - eyeOrigin).length(); - - drawStar(s->origin(), 25 + s->evaluateIntensity() / 20, - Vector4f(s->color(), 1.0f / de::max(float((distToEye - 100) / 1000), 1.f))); - - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - - drawLabel(labelForSource(s), s->origin()); - - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); -} - -static void drawLock(Vector3d const &origin, ddouble unit, ddouble t) -{ - LIBGUI_GL.glColor4f(1, 1, 1, 1); - - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - - LIBGUI_GL.glTranslatef(origin.x, origin.z, origin.y); - - LIBGUI_GL.glRotatef(t / 2, 0, 0, 1); - LIBGUI_GL.glRotatef(t, 1, 0, 0); - LIBGUI_GL.glRotatef(t * 15, 0, 1, 0); - - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex3f(-unit, 0, -unit); - LIBGUI_GL.glVertex3f(+unit, 0, -unit); - - LIBGUI_GL.glVertex3f(+unit, 0, -unit); - LIBGUI_GL.glVertex3f(+unit, 0, +unit); - - LIBGUI_GL.glVertex3f(+unit, 0, +unit); - LIBGUI_GL.glVertex3f(-unit, 0, +unit); - - LIBGUI_GL.glVertex3f(-unit, 0, +unit); - LIBGUI_GL.glVertex3f(-unit, 0, -unit); - LIBGUI_GL.glEnd(); - - LIBGUI_GL.glPopMatrix(); -} - -static void drawBiasEditingVisuals(Map &map) -{ - if(freezeRLs) return; - if(!SBE_Active() || editHidden) return; - - if(!map.biasSourceCount()) - return; - - ddouble const t = Timer_RealMilliseconds() / 100.0f; - - if(HueCircle *hueCircle = SBE_HueCircle()) - { - viewdata_t const *viewData = &viewPlayer->viewport(); - - GLState::current().setDepthTest(false).apply(); - //glDisable(GL_CULL_FACE); - GLState::push().setCull(gl::None).apply(); - - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - - LIBGUI_GL.glTranslatef(Rend_EyeOrigin().x, Rend_EyeOrigin().y, Rend_EyeOrigin().z); - LIBGUI_GL.glScalef(1, 1.0f/1.2f, 1); - LIBGUI_GL.glTranslatef(-Rend_EyeOrigin().x, -Rend_EyeOrigin().y, -Rend_EyeOrigin().z); - - HueCircleVisual::draw(*hueCircle, Rend_EyeOrigin(), viewData->frontVec); - - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); - - GLState::current().setDepthTest(true).apply(); - //glEnable(GL_CULL_FACE); - GLState::pop().apply(); - } - - coord_t handDistance; - Hand &hand = App_World().hand(&handDistance); - - // Grabbed sources blink yellow. - Vector4f grabbedColor; - if(!editBlink || map.biasCurrentTime() & 0x80) - grabbedColor = Vector4f(1, 1, .8f, .5f); - else - grabbedColor = Vector4f(.7f, .7f, .5f, .4f); - - BiasSource *nearSource = map.biasSourceNear(hand.origin()); - DENG2_ASSERT(nearSource); - - if((hand.origin() - nearSource->origin()).length() > 2 * handDistance) - { - // Show where it is. - GLState::current().setDepthTest(false).apply(); - } - - // The nearest cursor phases blue. - drawStar(nearSource->origin(), 10000, - nearSource->isGrabbed()? grabbedColor : - Vector4f(.0f + sin(t) * .2f, - .2f + sin(t) * .15f, - .9f + sin(t) * .3f, - .8f - sin(t) * .2f)); - - FR_SetFont(fontFixed); - FR_LoadDefaultAttrib(); - FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); - FR_SetShadowStrength(UI_SHADOW_STRENGTH); - - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - - drawLabel(labelForSource(nearSource), nearSource->origin()); - - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - - if(nearSource->isLocked()) - drawLock(nearSource->origin(), 2 + (nearSource->origin() - eyeOrigin).length() / 100, t); - - for(Grabbable *grabbable : hand.grabbed()) - { - if(world::internal::cannotCastGrabbableTo(grabbable)) continue; - BiasSource *s = &grabbable->as(); - - if(s == nearSource) - continue; - - drawStar(s->origin(), 10000, grabbedColor); - - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - - drawLabel(labelForSource(s), s->origin()); - - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - - if(s->isLocked()) - drawLock(s->origin(), 2 + (s->origin() - eyeOrigin).length() / 100, t); - } - - /*BiasSource *s = hand.nearestBiasSource(); - if(s && !hand.hasGrabbed(*s)) - { - GLState::current().setDepthTest(false).apply(); - glEnable(GL_TEXTURE_2D); - - drawLabel(labelForSource(s), s->origin()); - - GLState::current().setDepthTest(true).apply(); - glDisable(GL_TEXTURE_2D); - }*/ - - // Show all sources? - if(editShowAll) - { - map.forAllBiasSources([&nearSource] (BiasSource &source) - { - if(&source != nearSource && !source.isGrabbed()) - { - drawSource(&source); - } - return LoopContinue; - }); - } - - GLState::current().setDepthTest(true).apply(); -} -#endif - void Rend_UpdateLightModMatrix() { - if(novideo) return; + if (novideo) return; de::zap(lightModRange); - if(!App_World().hasMap()) + if (!App_World().hasMap()) { rAmbient = 0; return; } dint mapAmbient = App_World().map().ambientLightLevel(); - if(mapAmbient > ambientLight) + if (mapAmbient > ambientLight) { rAmbient = mapAmbient; } @@ -4995,13 +4848,13 @@ rAmbient = ambientLight; } - for(dint i = 0; i < 255; ++i) + for (dint i = 0; i < 255; ++i) { // Adjust the white point/dark point? dfloat lightlevel = 0; - if(lightRangeCompression != 0) + if (lightRangeCompression != 0) { - if(lightRangeCompression >= 0) + if (lightRangeCompression >= 0) { // Brighten dark areas. lightlevel = dfloat(255 - i) * lightRangeCompression; @@ -5014,17 +4867,17 @@ } // Lower than the ambient limit? - if(rAmbient != 0 && i+lightlevel <= rAmbient) + if (rAmbient != 0 && i+lightlevel <= rAmbient) { lightlevel = rAmbient - i; } // Clamp the result as a modifier to the light value (j). - if((i + lightlevel) >= 255) + if ((i + lightlevel) >= 255) { lightlevel = 255 - i; } - else if((i + lightlevel) <= 0) + else if ((i + lightlevel) <= 0) { lightlevel = -i; } @@ -5055,92 +4908,92 @@ #define BORDER ( 20 ) // Disabled? - if(!devLightModRange) return; + if (!devLightModRange) return; - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); - LIBGUI_GL.glTranslatef(BORDER, BORDER, 0); + DGL_Translatef(BORDER, BORDER, 0); // Draw an outside border. - LIBGUI_GL.glColor4f(1, 1, 0, 1); - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex2f(-1, -1); - LIBGUI_GL.glVertex2f(255 + 1, -1); - LIBGUI_GL.glVertex2f(255 + 1, -1); - LIBGUI_GL.glVertex2f(255 + 1, BLOCK_HEIGHT + 1); - LIBGUI_GL.glVertex2f(255 + 1, BLOCK_HEIGHT + 1); - LIBGUI_GL.glVertex2f(-1, BLOCK_HEIGHT + 1); - LIBGUI_GL.glVertex2f(-1, BLOCK_HEIGHT + 1); - LIBGUI_GL.glVertex2f(-1, -1); - LIBGUI_GL.glEnd(); + DGL_Color4f(1, 1, 0, 1); + DGL_Begin(DGL_LINES); + DGL_Vertex2f(-1, -1); + DGL_Vertex2f(255 + 1, -1); + DGL_Vertex2f(255 + 1, -1); + DGL_Vertex2f(255 + 1, BLOCK_HEIGHT + 1); + DGL_Vertex2f(255 + 1, BLOCK_HEIGHT + 1); + DGL_Vertex2f(-1, BLOCK_HEIGHT + 1); + DGL_Vertex2f(-1, BLOCK_HEIGHT + 1); + DGL_Vertex2f(-1, -1); + DGL_End(); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Begin(DGL_QUADS); dfloat c = 0; - for(dint i = 0; i < 255; ++i, c += (1.0f/255.0f)) + for (dint i = 0; i < 255; ++i, c += (1.0f/255.0f)) { // Get the result of the source light level + offset. dfloat off = lightModRange[i]; - LIBGUI_GL.glColor4f(c + off, c + off, c + off, 1); - LIBGUI_GL.glVertex2f(i * BLOCK_WIDTH, 0); - LIBGUI_GL.glVertex2f(i * BLOCK_WIDTH + BLOCK_WIDTH, 0); - LIBGUI_GL.glVertex2f(i * BLOCK_WIDTH + BLOCK_WIDTH, BLOCK_HEIGHT); - LIBGUI_GL.glVertex2f(i * BLOCK_WIDTH, BLOCK_HEIGHT); + DGL_Color4f(c + off, c + off, c + off, 1); + DGL_Vertex2f(i * BLOCK_WIDTH, 0); + DGL_Vertex2f(i * BLOCK_WIDTH + BLOCK_WIDTH, 0); + DGL_Vertex2f(i * BLOCK_WIDTH + BLOCK_WIDTH, BLOCK_HEIGHT); + DGL_Vertex2f(i * BLOCK_WIDTH, BLOCK_HEIGHT); } - LIBGUI_GL.glEnd(); + DGL_End(); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); #undef BORDER #undef BLOCK_HEIGHT #undef BLOCK_WIDTH } -static DGLuint constructBBox(DGLuint name, dfloat br) +static void drawBBox(dfloat br) { - if(GL_NewList(name, GL_COMPILE)) - { - LIBGUI_GL.glBegin(GL_QUADS); - { - // Top - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f+br, 1.0f,-1.0f-br); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f-br, 1.0f,-1.0f-br); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f-br, 1.0f, 1.0f+br); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f+br, 1.0f, 1.0f+br); // BR - // Bottom - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f+br,-1.0f, 1.0f+br); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f-br,-1.0f, 1.0f+br); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f-br,-1.0f,-1.0f-br); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f+br,-1.0f,-1.0f-br); // BR - // Front - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f+br, 1.0f+br, 1.0f); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f-br, 1.0f+br, 1.0f); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f-br,-1.0f-br, 1.0f); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f+br,-1.0f-br, 1.0f); // BR - // Back - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f+br,-1.0f-br,-1.0f); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f-br,-1.0f-br,-1.0f); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f-br, 1.0f+br,-1.0f); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f+br, 1.0f+br,-1.0f); // BR - // Left - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f, 1.0f+br, 1.0f+br); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f(-1.0f, 1.0f+br,-1.0f-br); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f,-1.0f-br,-1.0f-br); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f(-1.0f,-1.0f-br, 1.0f+br); // BR - // Right - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f, 1.0f+br,-1.0f-br); // TR - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); LIBGUI_GL.glVertex3f( 1.0f, 1.0f+br, 1.0f+br); // TL - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f,-1.0f-br, 1.0f+br); // BL - LIBGUI_GL.glTexCoord2f(1.0f, 0.0f); LIBGUI_GL.glVertex3f( 1.0f,-1.0f-br,-1.0f-br); // BR - } - LIBGUI_GL.glEnd(); - return GL_EndList(); - } - return 0; +// if (GL_NewList(name, GL_COMPILE)) +// { + DGL_Begin(DGL_QUADS); + { + // Top + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f( 1.0f+br, 1.0f,-1.0f-br); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f(-1.0f-br, 1.0f,-1.0f-br); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f(-1.0f-br, 1.0f, 1.0f+br); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f( 1.0f+br, 1.0f, 1.0f+br); // BR + // Bottom + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f( 1.0f+br,-1.0f, 1.0f+br); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f(-1.0f-br,-1.0f, 1.0f+br); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f(-1.0f-br,-1.0f,-1.0f-br); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f( 1.0f+br,-1.0f,-1.0f-br); // BR + // Front + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f( 1.0f+br, 1.0f+br, 1.0f); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f(-1.0f-br, 1.0f+br, 1.0f); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f(-1.0f-br,-1.0f-br, 1.0f); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f( 1.0f+br,-1.0f-br, 1.0f); // BR + // Back + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f( 1.0f+br,-1.0f-br,-1.0f); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f(-1.0f-br,-1.0f-br,-1.0f); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f(-1.0f-br, 1.0f+br,-1.0f); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f( 1.0f+br, 1.0f+br,-1.0f); // BR + // Left + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f(-1.0f, 1.0f+br, 1.0f+br); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f(-1.0f, 1.0f+br,-1.0f-br); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f(-1.0f,-1.0f-br,-1.0f-br); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f(-1.0f,-1.0f-br, 1.0f+br); // BR + // Right + DGL_TexCoord2f(0, 1.0f, 1.0f); DGL_Vertex3f( 1.0f, 1.0f+br,-1.0f-br); // TR + DGL_TexCoord2f(0, 0.0f, 1.0f); DGL_Vertex3f( 1.0f, 1.0f+br, 1.0f+br); // TL + DGL_TexCoord2f(0, 0.0f, 0.0f); DGL_Vertex3f( 1.0f,-1.0f-br, 1.0f+br); // BL + DGL_TexCoord2f(0, 1.0f, 0.0f); DGL_Vertex3f( 1.0f,-1.0f-br,-1.0f-br); // BR + } + DGL_End(); + // return GL_EndList(); + //} + //return 0; } /** @@ -5160,26 +5013,27 @@ void Rend_DrawBBox(Vector3d const &pos, coord_t w, coord_t l, coord_t h, dfloat a, dfloat const color[3], dfloat alpha, dfloat br, bool alignToBase) { - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - if(alignToBase) + if (alignToBase) // The Z coordinate is to the bottom of the object. - LIBGUI_GL.glTranslated(pos.x, pos.z + h, pos.y); + DGL_Translatef(pos.x, pos.z + h, pos.y); else - LIBGUI_GL.glTranslated(pos.x, pos.z, pos.y); + DGL_Translatef(pos.x, pos.z, pos.y); - LIBGUI_GL.glRotatef(0, 0, 0, 1); - LIBGUI_GL.glRotatef(0, 1, 0, 0); - LIBGUI_GL.glRotatef(a, 0, 1, 0); + DGL_Rotatef(0, 0, 0, 1); + DGL_Rotatef(0, 1, 0, 0); + DGL_Rotatef(a, 0, 1, 0); - LIBGUI_GL.glScaled(w - br - br, h - br - br, l - br - br); - LIBGUI_GL.glColor4f(color[0], color[1], color[2], alpha); + DGL_Scalef(w - br - br, h - br - br, l - br - br); + DGL_Color4f(color[0], color[1], color[2], alpha); - GL_CallList(dlBBox); + //GL_CallList(dlBBox); + drawBBox(.08f); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } /** @@ -5193,37 +5047,37 @@ * @param alpha Alpha to make the box (uniform vertex color). */ void Rend_DrawArrow(Vector3d const &pos, dfloat a, dfloat s, dfloat const color[3], - dfloat alpha) + dfloat alpha) { - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - LIBGUI_GL.glTranslated(pos.x, pos.z, pos.y); + DGL_Translatef(pos.x, pos.z, pos.y); - LIBGUI_GL.glRotatef(0, 0, 0, 1); - LIBGUI_GL.glRotatef(0, 1, 0, 0); - LIBGUI_GL.glRotatef(a, 0, 1, 0); + DGL_Rotatef(0, 0, 0, 1); + DGL_Rotatef(0, 1, 0, 0); + DGL_Rotatef(a, 0, 1, 0); - LIBGUI_GL.glScalef(s, 0, s); + DGL_Scalef(s, 0, s); - LIBGUI_GL.glBegin(GL_TRIANGLES); + DGL_Begin(DGL_TRIANGLES); { - LIBGUI_GL.glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - LIBGUI_GL.glTexCoord2f(1.0f, 1.0f); - LIBGUI_GL.glVertex3f( 1.0f, 1.0f,-1.0f); // L + DGL_Color4f(0.0f, 0.0f, 0.0f, 0.5f); + DGL_TexCoord2f(0, 1.0f, 1.0f); + DGL_Vertex3f( 1.0f, 1.0f,-1.0f); // L - LIBGUI_GL.glColor4f(color[0], color[1], color[2], alpha); - LIBGUI_GL.glTexCoord2f(0.0f, 1.0f); - LIBGUI_GL.glVertex3f(-1.0f, 1.0f,-1.0f); // Point + DGL_Color4f(color[0], color[1], color[2], alpha); + DGL_TexCoord2f(0, 0.0f, 1.0f); + DGL_Vertex3f(-1.0f, 1.0f,-1.0f); // Point - LIBGUI_GL.glColor4f(0.0f, 0.0f, 0.0f, 0.5f); - LIBGUI_GL.glTexCoord2f(0.0f, 0.0f); - LIBGUI_GL.glVertex3f(-1.0f, 1.0f, 1.0f); // R + DGL_Color4f(0.0f, 0.0f, 0.0f, 0.5f); + DGL_TexCoord2f(0, 0.0f, 0.0f); + DGL_Vertex3f(-1.0f, 1.0f, 1.0f); // R } - LIBGUI_GL.glEnd(); + DGL_End(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } static void drawMobjBBox(mobj_t &mob) @@ -5233,19 +5087,19 @@ static dfloat const yellow[] = { 0.7f, 0.7f, 0.2f }; // missiles // We don't want the console player. - if(&mob == DD_Player(consolePlayer)->publicData().mo) + if (&mob == DD_Player(consolePlayer)->publicData().mo) return; // Is it vissible? - if(!Mobj_IsLinked(mob)) return; + if (!Mobj_IsLinked(mob)) return; BspLeaf const &bspLeaf = Mobj_BspLeafAtOrigin(mob); - if(!bspLeaf.hasSubspace() || !R_ViewerSubspaceIsVisible(bspLeaf.subspace())) + if (!bspLeaf.hasSubspace() || !R_ViewerSubspaceIsVisible(bspLeaf.subspace())) return; ddouble const distToEye = (eyeOrigin - Mobj_Origin(mob)).length(); dfloat alpha = 1 - ((distToEye / (DENG_GAMEVIEW_WIDTH/2)) / 4); - if(alpha < .25f) + if (alpha < .25f) alpha = .25f; // Don't make them totally invisible. // Draw a bounding box in an appropriate color. @@ -5273,20 +5127,20 @@ static dfloat const green [] = { 0.2f, 1, 0.2f }; // solid objects static dfloat const yellow[] = { 0.7f, 0.7f, 0.2f }; // missiles - if(!devMobjBBox && !devPolyobjBBox) return; + if (!devMobjBBox && !devPolyobjBBox) return; #ifndef _DEBUG // Bounding boxes are not allowed in non-debug netgames. - if(netGame) return; + if (netGame) return; #endif - if(!dlBBox) - dlBBox = constructBBox(0, .08f); +// if (!dlBBox) +// dlBBox = constructBBox(0, .08f); - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); //glDisable(GL_CULL_FACE); - GLState::push().setCull(gl::None).apply(); + DGL_CullFace(DGL_NONE); MaterialAnimator &matAnimator = ClientMaterial::find(de::Uri("System", Path("bbox"))) .getAnimator(Rend_SpriteMaterialSpec()); @@ -5297,7 +5151,7 @@ GL_BindTexture(matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture); GL_BlendMode(BM_ADD); - if(devMobjBBox) + if (devMobjBBox) { map.thinkers().forAll(reinterpret_cast(gx.MobjThinker), 0x1, [] (thinker_t *th) { @@ -5306,7 +5160,7 @@ }); } - if(devPolyobjBBox) + if (devPolyobjBBox) { map.forAllPolyobjs([] (Polyobj &pob) { @@ -5322,12 +5176,12 @@ ddouble const distToEye = (eyeOrigin - pos).length(); dfloat alpha = 1 - ((distToEye / (DENG_GAMEVIEW_WIDTH/2)) / 4); - if(alpha < .25f) + if (alpha < .25f) alpha = .25f; // Don't make them totally invisible. Rend_DrawBBox(pos, width, length, height, 0, yellow, alpha, .08f); - for(Line *line : pob.lines()) + for (Line *line : pob.lines()) { Vector3d pos(line->center(), sec.floor().height()); @@ -5342,29 +5196,29 @@ GL_BlendMode(BM_NORMAL); - GLState::pop().apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - GLState::current().setDepthTest(true).apply(); + DGL_PopState(); + DGL_Disable(DGL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); } static void drawPoint(Vector3d const &origin, Vector4f const &color = Vector4f(1, 1, 1, 1)) { - LIBGUI_GL.glBegin(GL_POINTS); - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_POINTS); + DGL_Color4f(color.x, color.y, color.z, color.w); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_End(); } static void drawVector(Vector3f const &vector, dfloat scalar, Vector4f const &color = Vector4f(1, 1, 1, 1)) { static dfloat const black[] = { 0, 0, 0, 0 }; - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(scalar * vector.x, scalar * vector.z, scalar * vector.y); - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Color4fv(black); + DGL_Vertex3f(scalar * vector.x, scalar * vector.z, scalar * vector.y); + DGL_Color4f(color.x, color.y, color.z, color.w); + DGL_Vertex3f(0, 0, 0); + DGL_End(); } static void drawTangentVectorsForSurface(Surface const &suf, Vector3d const &origin) @@ -5374,16 +5228,16 @@ static Vector4f const green( 0, 1, 0, 1); static Vector4f const blue ( 0, 0, 1, 1); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glTranslatef(origin.x, origin.z, origin.y); - - if(::devSurfaceVectors & SVF_TANGENT) drawVector(suf.tangent(), VISUAL_LENGTH, red); - if(::devSurfaceVectors & SVF_BITANGENT) drawVector(suf.bitangent(), VISUAL_LENGTH, green); - if(::devSurfaceVectors & SVF_NORMAL) drawVector(suf.normal(), VISUAL_LENGTH, blue); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Translatef(origin.x, origin.z, origin.y); + + if (::devSurfaceVectors & SVF_TANGENT) drawVector(suf.tangent(), VISUAL_LENGTH, red); + if (::devSurfaceVectors & SVF_BITANGENT) drawVector(suf.bitangent(), VISUAL_LENGTH, green); + if (::devSurfaceVectors & SVF_NORMAL) drawVector(suf.normal(), VISUAL_LENGTH, blue); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } /** @@ -5391,7 +5245,7 @@ */ static void drawTangentVectorsForWalls(HEdge const *hedge) { - if(!hedge || !hedge->hasMapElement()) + if (!hedge || !hedge->hasMapElement()) return; LineSideSegment const &seg = hedge->mapElementAs(); @@ -5399,7 +5253,7 @@ Line const &line = lineSide.line(); Vector2d const center = (hedge->twin().origin() + hedge->origin()) / 2; - if(lineSide.considerOneSided()) + if (lineSide.considerOneSided()) { auto &subsec = (line.definesPolyobj() ? line.polyobj().bspLeaf().subspace() @@ -5424,7 +5278,7 @@ : hedge->twin().face().mapElementAs()) .subsector().as(); - if(lineSide.middle().hasMaterial()) + if (lineSide.middle().hasMaterial()) { ddouble const bottom = subsec. visFloor().heightSmoothed(); ddouble const top = subsec.visCeiling().heightSmoothed(); @@ -5433,7 +5287,7 @@ Vector3d(center, bottom + (top - bottom) / 2)); } - if(backSubsec.visCeiling().heightSmoothed() < subsec.visCeiling().heightSmoothed() && + if (backSubsec.visCeiling().heightSmoothed() < subsec.visCeiling().heightSmoothed() && !(subsec. visCeiling().surface().hasSkyMaskedMaterial() && backSubsec.visCeiling().surface().hasSkyMaskedMaterial())) { @@ -5444,7 +5298,7 @@ Vector3d(center, bottom + (top - bottom) / 2)); } - if(backSubsec.visFloor().heightSmoothed() > subsec.visFloor().heightSmoothed() && + if (backSubsec.visFloor().heightSmoothed() > subsec.visFloor().heightSmoothed() && !(subsec. visFloor().surface().hasSkyMaskedMaterial() && backSubsec.visFloor().surface().hasSkyMaskedMaterial())) { @@ -5519,7 +5373,7 @@ if (!::devSurfaceVectors) return; //glDisable(GL_CULL_FACE); - GLState::push().setCull(gl::None).apply(); + DGL_CullFace(DGL_NONE); map.forAllSectors([] (Sector &sec) { @@ -5531,7 +5385,7 @@ }); //glEnable(GL_CULL_FACE); - GLState::pop().apply(); + DGL_PopState(); } static void drawLumobjs(Map &map) @@ -5540,54 +5394,54 @@ if (!devDrawLums) return; - GLState::current().setDepthTest(false).apply(); + DGL_Disable(DGL_DEPTH_TEST); //glDisable(GL_CULL_FACE); - GLState::push().setCull(gl::None).apply(); + DGL_CullFace(DGL_NONE); map.forAllLumobjs([] (Lumobj &lob) { if (rendMaxLumobjs > 0 && R_ViewerLumobjIsHidden(lob.indexInMap())) return LoopContinue; - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - LIBGUI_GL.glTranslated(lob.origin().x, lob.origin().z + lob.zOffset(), lob.origin().y); + DGL_Translatef(lob.origin().x, lob.origin().z + lob.zOffset(), lob.origin().y); - LIBGUI_GL.glBegin(GL_LINES); + DGL_Begin(DGL_LINES); { - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(-lob.radius(), 0, 0); - LIBGUI_GL.glColor4f(lob.color().x, lob.color().y, lob.color().z, 1); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(lob.radius(), 0, 0); - - LIBGUI_GL.glVertex3f(0, -lob.radius(), 0); - LIBGUI_GL.glColor4f(lob.color().x, lob.color().y, lob.color().z, 1); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(0, lob.radius(), 0); - - LIBGUI_GL.glVertex3f(0, 0, -lob.radius()); - LIBGUI_GL.glColor4f(lob.color().x, lob.color().y, lob.color().z, 1); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(0, 0, lob.radius()); + DGL_Color4fv(black); + DGL_Vertex3f(-lob.radius(), 0, 0); + DGL_Color4f(lob.color().x, lob.color().y, lob.color().z, 1); + DGL_Vertex3f(0, 0, 0); + DGL_Vertex3f(0, 0, 0); + DGL_Color4fv(black); + DGL_Vertex3f(lob.radius(), 0, 0); + + DGL_Vertex3f(0, -lob.radius(), 0); + DGL_Color4f(lob.color().x, lob.color().y, lob.color().z, 1); + DGL_Vertex3f(0, 0, 0); + DGL_Vertex3f(0, 0, 0); + DGL_Color4fv(black); + DGL_Vertex3f(0, lob.radius(), 0); + + DGL_Vertex3f(0, 0, -lob.radius()); + DGL_Color4f(lob.color().x, lob.color().y, lob.color().z, 1); + DGL_Vertex3f(0, 0, 0); + DGL_Vertex3f(0, 0, 0); + DGL_Color4fv(black); + DGL_Vertex3f(0, 0, lob.radius()); } - LIBGUI_GL.glEnd(); + DGL_End(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); return LoopContinue; }); //glEnable(GL_CULL_FACE); - GLState::pop().apply(); - GLState::current().setDepthTest(true).apply(); + DGL_PopState(); + DGL_Enable(DGL_DEPTH_TEST); } static String labelForLineSideSection(LineSide &side, dint sectionId) @@ -5617,24 +5471,24 @@ { static ddouble const MAX_DISTANCE = 384; - if(!devSoundEmitters) return; + if (!devSoundEmitters) return; FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); FR_SetShadowStrength(UI_SHADOW_STRENGTH); - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); - if(devSoundEmitters & SOF_SIDE) + if (devSoundEmitters & SOF_SIDE) { map.forAllLines([] (Line &line) { - for(dint i = 0; i < 2; ++i) + for (dint i = 0; i < 2; ++i) { LineSide &side = line.side(i); - if(!side.hasSections()) continue; + if (!side.hasSections()) continue; drawLabel(labelForLineSideSection(side, LineSide::Middle) , Vector3d(side.middleSoundEmitter().origin), MAX_DISTANCE); @@ -5649,11 +5503,11 @@ }); } - if(devSoundEmitters & (SOF_SECTOR | SOF_PLANE)) + if (devSoundEmitters & (SOF_SECTOR | SOF_PLANE)) { map.forAllSectors([] (Sector §or) { - if(devSoundEmitters & SOF_PLANE) + if (devSoundEmitters & SOF_PLANE) { sector.forAllPlanes([] (Plane &plane) { @@ -5663,7 +5517,7 @@ }); } - if(devSoundEmitters & SOF_SECTOR) + if (devSoundEmitters & SOF_SECTOR) { drawLabel(labelForSector(sector) , Vector3d(sector.soundEmitter().origin), MAX_DISTANCE); @@ -5672,22 +5526,22 @@ }); } - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); } void Rend_DrawVectorLight(VectorLightData const &vlight, dfloat alpha) { - if(alpha < .0001f) return; + if (alpha < .0001f) return; dfloat const unitLength = 100; - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glColor4f(vlight.color.x, vlight.color.y, vlight.color.z, alpha); - LIBGUI_GL.glVertex3f(unitLength * vlight.direction.x, unitLength * vlight.direction.z, unitLength * vlight.direction.y); - LIBGUI_GL.glColor4f(vlight.color.x, vlight.color.y, vlight.color.z, 0); - LIBGUI_GL.glVertex3f(0, 0, 0); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Color4f(vlight.color.x, vlight.color.y, vlight.color.z, alpha); + DGL_Vertex3f(unitLength * vlight.direction.x, unitLength * vlight.direction.z, unitLength * vlight.direction.y); + DGL_Color4f(vlight.color.x, vlight.color.y, vlight.color.z, 0); + DGL_Vertex3f(0, 0, 0); + DGL_End(); } static String labelForGenerator(Generator const &gen) @@ -5699,11 +5553,11 @@ { static dint const MAX_GENERATOR_DIST = 2048; - if(gen.source || gen.isUntriggered()) + if (gen.source || gen.isUntriggered()) { Vector3d const origin = gen.origin(); ddouble const distToEye = (eyeOrigin - origin).length(); - if(distToEye < MAX_GENERATOR_DIST) + if (distToEye < MAX_GENERATOR_DIST) { drawLabel(labelForGenerator(gen), origin, distToEye / (DENG_GAMEVIEW_WIDTH / 2) , 1 - distToEye / MAX_GENERATOR_DIST); @@ -5716,15 +5570,15 @@ */ static void drawGenerators(Map &map) { - if(!devDrawGenerators) return; + if (!devDrawGenerators) return; FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); FR_SetShadowStrength(UI_SHADOW_STRENGTH); - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); map.forAllGenerators([] (Generator &gen) { @@ -5732,8 +5586,8 @@ return LoopContinue; }); - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); } static void drawBar(Vector3d const &origin, coord_t height, dfloat opacity) @@ -5741,17 +5595,17 @@ static dint const EXTEND_DIST = 64; static dfloat const black[] = { 0, 0, 0, 0 }; - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x, origin.z - EXTEND_DIST, origin.y); - LIBGUI_GL.glColor4f(1, 1, 1, opacity); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z + height, origin.y); - LIBGUI_GL.glVertex3f(origin.x, origin.z + height, origin.y); - LIBGUI_GL.glColor4fv(black); - LIBGUI_GL.glVertex3f(origin.x, origin.z + height + EXTEND_DIST, origin.y); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINES); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x, origin.z - EXTEND_DIST, origin.y); + DGL_Color4f(1, 1, 1, opacity); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Vertex3f(origin.x, origin.z, origin.y); + DGL_Vertex3f(origin.x, origin.z + height, origin.y); + DGL_Vertex3f(origin.x, origin.z + height, origin.y); + DGL_Color4fv(black); + DGL_Vertex3f(origin.x, origin.z + height + EXTEND_DIST, origin.y); + DGL_End(); } static String labelForVertex(Vertex const *vtx) @@ -5772,46 +5626,46 @@ static void drawVertexVisual(Vertex const &vertex, ddouble minHeight, ddouble maxHeight, drawvertexvisual_parameters_t &parms) { - if(!parms.drawOrigin && !parms.drawBar && !parms.drawLabel) + if (!parms.drawOrigin && !parms.drawBar && !parms.drawLabel) return; // Skip vertexes produced by the space partitioner. - if(vertex.indexInArchive() == MapElement::NoIndex) + if (vertex.indexInArchive() == MapElement::NoIndex) return; // Skip already processed verts? - if(parms.drawnVerts) + if (parms.drawnVerts) { - if(parms.drawnVerts->testBit(vertex.indexInArchive())) + if (parms.drawnVerts->testBit(vertex.indexInArchive())) return; parms.drawnVerts->setBit(vertex.indexInArchive()); } // Distance in 2D determines visibility/opacity. ddouble distToEye = (Vector2d(eyeOrigin.x, eyeOrigin.y) - vertex.origin()).length(); - if(distToEye >= parms.maxDistance) + if (distToEye >= parms.maxDistance) return; Vector3d const origin(vertex.origin(), minHeight); dfloat const opacity = 1 - distToEye / parms.maxDistance; - if(parms.drawBar) + if (parms.drawBar) { drawBar(origin, maxHeight - minHeight, opacity); } - if(parms.drawOrigin) + if (parms.drawOrigin) { drawPoint(origin, Vector4f(.7f, .7f, .2f, opacity * 4)); } - if(parms.drawLabel) + if (parms.drawLabel) { - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); drawLabel(labelForVertex(&vertex), origin, distToEye / (DENG_GAMEVIEW_WIDTH / 2), opacity); - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); } } @@ -5881,11 +5735,11 @@ drawVertexVisual(hedge->vertex(), min, max, parms); - } while((hedge = &hedge->next()) != base); + } while ((hedge = &hedge->next()) != base); sub.forAllExtraMeshes([&min, &max, &parms] (Mesh &mesh) { - for(HEdge *hedge : mesh.hedges()) + for (HEdge *hedge : mesh.hedges()) { drawVertexVisual(hedge->vertex(), min, max, parms); drawVertexVisual(hedge->twin().vertex(), min, max, parms); @@ -5895,7 +5749,7 @@ sub.forAllPolyobjs([&min, &max, &parms] (Polyobj &pob) { - for(Line *line : pob.lines()) + for (Line *line : pob.lines()) { drawVertexVisual(line->from(), min, max, parms); drawVertexVisual(line->to(), min, max, parms); @@ -5913,7 +5767,7 @@ dfloat oldLineWidth = -1; - if(!devVertexBars && !devVertexIndices) + if (!devVertexBars && !devVertexIndices) return; AABoxd box(eyeOrigin.x - MAX_DISTANCE, eyeOrigin.y - MAX_DISTANCE, @@ -5931,9 +5785,11 @@ if (devVertexBars) { - GLState::current().setDepthTest(false).apply(); + DGL_Disable(DGL_DEPTH_TEST); +#if defined (DENG_OPENGL) LIBGUI_GL.glEnable(GL_LINE_SMOOTH); +#endif oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); DGL_SetFloat(DGL_LINE_WIDTH, 2); @@ -5945,7 +5801,7 @@ // Check the bounds. auto &subspace = *(ConvexSubspace *)object; AABoxd const &polyBounds = subspace.poly().bounds(); - if(!( polyBounds.maxX < box.minX + if (!( polyBounds.maxX < box.minX || polyBounds.minX > box.maxX || polyBounds.minY > box.maxY || polyBounds.maxY < box.minY)) @@ -5955,16 +5811,18 @@ return LoopContinue; }); - GLState::current().setDepthTest(true).apply(); + DGL_Enable(DGL_DEPTH_TEST); } // Draw the vertex origins. dfloat const oldPointSize = DGL_GetFloat(DGL_POINT_SIZE); +#if defined (DENG_OPENGL) LIBGUI_GL.glEnable(GL_POINT_SMOOTH); +#endif DGL_SetFloat(DGL_POINT_SIZE, 6); - GLState::current().setDepthTest(false).apply(); + DGL_Disable(DGL_DEPTH_TEST); parms.drawnVerts->fill(false); // Process all again. parms.drawOrigin = true; @@ -5985,7 +5843,7 @@ return LoopContinue; }); - GLState::current().setDepthTest(true).apply(); + DGL_Enable(DGL_DEPTH_TEST); if (devVertexIndices) { @@ -6013,10 +5871,14 @@ if (devVertexBars) { DGL_SetFloat(DGL_LINE_WIDTH, oldLineWidth); +#if defined (DENG_OPENGL) LIBGUI_GL.glDisable(GL_LINE_SMOOTH); +#endif } DGL_SetFloat(DGL_POINT_SIZE, oldPointSize); +#if defined (DENG_OPENGL) LIBGUI_GL.glDisable(GL_POINT_SMOOTH); +#endif #undef MAX_VERTEX_POINT_DIST } @@ -6040,8 +5902,8 @@ FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); FR_SetShadowStrength(UI_SHADOW_STRENGTH); - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); // Draw a sector label at the center of each subsector: map.forAllSectors([] (Sector &sec) @@ -6059,8 +5921,8 @@ }); }); - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); } static String labelForThinker(thinker_t *thinker) @@ -6076,24 +5938,24 @@ { static ddouble const MAX_THINKER_DIST = 2048; - if(!devThinkerIds) return; + if (!devThinkerIds) return; FR_SetFont(fontFixed); FR_LoadDefaultAttrib(); FR_SetShadowOffset(UI_SHADOW_OFFSET, UI_SHADOW_OFFSET); FR_SetShadowStrength(UI_SHADOW_STRENGTH); - GLState::current().setDepthTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Enable(DGL_TEXTURE_2D); map.thinkers().forAll(0x1 | 0x2, [] (thinker_t *th) { // Ignore non-mobjs. - if(Thinker_HasMobjFunc(th->function)) + if (Thinker_IsMobj(th)) { Vector3d const origin = Mobj_Center(*(mobj_t *)th); ddouble const distToEye = (eyeOrigin - origin).length(); - if(distToEye < MAX_THINKER_DIST) + if (distToEye < MAX_THINKER_DIST) { drawLabel(labelForThinker(th), origin, distToEye / (DENG_GAMEVIEW_WIDTH / 2) , 1 - distToEye / MAX_THINKER_DIST); @@ -6102,8 +5964,8 @@ return LoopContinue; }); - GLState::current().setDepthTest(true).apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Disable(DGL_TEXTURE_2D); } #if 0 @@ -6113,58 +5975,58 @@ static dint blink = 0; // Disabled? - if(!devLightGrid) return; + if (!devLightGrid) return; DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Determine the grid reference of the view player. LightGrid::Index viewerGridIndex = 0; - if(viewPlayer) + if (viewPlayer) { blink++; viewerGridIndex = lg.toIndex(lg.toRef(viewPlayer->publicData().mo->origin)); } // Go into screen projection mode. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); - for(dint y = 0; y < lg.dimensions().y; ++y) + for (dint y = 0; y < lg.dimensions().y; ++y) { - LIBGUI_GL.glBegin(GL_QUADS); - for(dint x = 0; x < lg.dimensions().x; ++x) + DGL_Begin(DGL_QUADS); + for (dint x = 0; x < lg.dimensions().x; ++x) { LightGrid::Index gridIndex = lg.toIndex(x, lg.dimensions().y - 1 - y); bool const isViewerIndex = (viewPlayer && viewerGridIndex == gridIndex); Vector3f const *color = 0; - if(isViewerIndex && (blink & 16)) + if (isViewerIndex && (blink & 16)) { color = &red; } - else if(lg.primarySource(gridIndex)) + else if (lg.primarySource(gridIndex)) { color = &lg.rawColorRef(gridIndex); } - if(!color) continue; + if (!color) continue; LIBGUI_GL.glColor3f(color->x, color->y, color->z); - LIBGUI_GL.glVertex2f(x * devLightGridSize, y * devLightGridSize); - LIBGUI_GL.glVertex2f(x * devLightGridSize + devLightGridSize, y * devLightGridSize); - LIBGUI_GL.glVertex2f(x * devLightGridSize + devLightGridSize, + DGL_Vertex2f(x * devLightGridSize, y * devLightGridSize); + DGL_Vertex2f(x * devLightGridSize + devLightGridSize, y * devLightGridSize); + DGL_Vertex2f(x * devLightGridSize + devLightGridSize, y * devLightGridSize + devLightGridSize); - LIBGUI_GL.glVertex2f(x * devLightGridSize, y * devLightGridSize + devLightGridSize); + DGL_Vertex2f(x * devLightGridSize, y * devLightGridSize + devLightGridSize); } - LIBGUI_GL.glEnd(); + DGL_End(); } - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } #endif @@ -6186,7 +6048,7 @@ /// Returns the texture variant specification for lightmaps. TextureVariantSpec const &Rend_MapSurfaceLightmapTextureSpec() { - return ClientApp::resources().textureSpec(TC_MAPSURFACE_LIGHTMAP, 0, 0, 0, 0, GL_CLAMP, GL_CLAMP, + return ClientApp::resources().textureSpec(TC_MAPSURFACE_LIGHTMAP, 0, 0, 0, 0, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, 1, -1, -1, false, false, false, true); } @@ -6206,13 +6068,13 @@ { DENG2_UNUSED3(src, argc, argv); - if(!App_GameLoaded()) + if (!App_GameLoaded()) { LOG_ERROR("A game must be loaded before the Renderer Appearance editor can be opened"); return false; } - if(!ClientWindow::main().hasSidebar()) + if (!ClientWindow::main().hasSidebar()) { // The editor sidebar will give its ownership automatically // to the window. @@ -6226,13 +6088,13 @@ { DENG2_UNUSED3(src, argc, argv); - if(!App_GameLoaded()) + if (!App_GameLoaded()) { LOG_ERROR("A game must be loaded before the Model Asset editor can be opened"); return false; } - if(!ClientWindow::main().hasSidebar()) + if (!ClientWindow::main().hasSidebar()) { ModelAssetEditor *editor = new ModelAssetEditor; editor->open(); @@ -6262,7 +6124,7 @@ DENG2_UNUSED2(src, argc); dint newMipMode = String(argv[1]).toInt(); - if(newMipMode < 0 || newMipMode > 5) + if (newMipMode < 0 || newMipMode > 5) { LOG_SCR_ERROR("Invalid mipmapping mode %i; the valid range is 0...5") << newMipMode; return false; @@ -6277,7 +6139,7 @@ { DENG2_UNUSED(src); - if(argc == 2 && !String(argv[1]).compareWithoutCase("raw")) + if (argc == 2 && !String(argv[1]).compareWithoutCase("raw")) { // Reset just raw images. GL_ReleaseTexturesForRawImages(); @@ -6298,14 +6160,14 @@ /* static void fieldOfViewChanged() { - if(vrCfg().mode() == VRConfig::OculusRift) + if (vrCfg().mode() == VRConfig::OculusRift) { - if(Con_GetFloat("rend-vr-rift-fovx") != fieldOfView) + if (Con_GetFloat("rend-vr-rift-fovx") != fieldOfView) Con_SetFloat("rend-vr-rift-fovx", fieldOfView); } else { - if(Con_GetFloat("rend-vr-nonrift-fovx") != fieldOfView) + if (Con_GetFloat("rend-vr-nonrift-fovx") != fieldOfView) Con_SetFloat("rend-vr-nonrift-fovx", fieldOfView); } }*/ @@ -6334,7 +6196,7 @@ static void useDynlightsChanged() { - if(!ClientApp::world().hasMap()) return; + if (!ClientApp::world().hasMap()) return; // Unlink luminous objects. ClientApp::world().map().thinkers() @@ -6377,7 +6239,7 @@ C_VAR_FLOAT2("rend-light-compression", &lightRangeCompression, 0, -1, 1, Rend_UpdateLightModMatrix); C_VAR_BYTE("rend-light-decor", &useLightDecorations, 0, 0, 1); C_VAR_FLOAT("rend-light-fog-bright", &dynlightFogBright, 0, 0, 1); - C_VAR_INT("rend-light-multitex", &useMultiTexLights, 0, 0, 1); + //C_VAR_INT("rend-light-multitex", &useMultiTexLights, 0, 0, 1); C_VAR_INT("rend-light-num", &rendMaxLumobjs, CVF_NO_MAX, 0, 0); C_VAR_FLOAT("rend-light-sky", &rendSkyLight, 0, 0, 1/*, useSkylightChanged*/); C_VAR_BYTE("rend-light-sky-auto", &rendSkyLightAuto, 0, 0, 1/*, useSkylightChanged*/); @@ -6394,7 +6256,7 @@ C_VAR_INT("rend-tex", &renderTextures, CVF_NO_ARCHIVE, 0, 2); C_VAR_BYTE("rend-tex-anim-smooth", &smoothTexAnim, 0, 0, 1); C_VAR_INT("rend-tex-detail", &r_detail, 0, 0, 1); - C_VAR_INT("rend-tex-detail-multitex", &useMultiTexDetails, 0, 0, 1); + //C_VAR_INT("rend-tex-detail-multitex", &useMultiTexDetails, 0, 0, 1); C_VAR_FLOAT("rend-tex-detail-scale", &detailScale, CVF_NO_MIN | CVF_NO_MAX, 0, 0); C_VAR_FLOAT2("rend-tex-detail-strength", &detailFactor, 0, 0, 5, detailFactorChanged); C_VAR_BYTE2("rend-tex-external-always", &loadExtAlways, 0, 0, 1, loadExtAlwaysChanged); @@ -6432,6 +6294,7 @@ C_CMD("rendedit", "", OpenRendererAppearanceEditor); C_CMD("modeledit", "", OpenModelAssetEditor); + C_CMD("cubeshot", "i", CubeShot); C_CMD_FLAGS("lowres", "", LowRes, CMDF_NO_DEDICATED); C_CMD_FLAGS("mipmap", "i", MipMap, CMDF_NO_DEDICATED); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_model.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_model.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_model.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_model.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -62,7 +62,7 @@ static inline float qatan2(float y, float x) { float ang = BANG2RAD(bamsAtan2(y * 512, x * 512)); - if(ang > PI) ang -= 2 * (float) PI; + if (ang > PI) ang -= 2 * (float) PI; return ang; } @@ -78,7 +78,7 @@ int frameInter = true; float modelAspectMod = 1 / 1.2f; //.833334f; int mirrorHudModels; -int modelShinyMultitex = true; +//int modelShinyMultitex = true; float modelShinyFactor = 1.0f; float modelSpinSpeed = 1; int maxModelDistance = 1500; @@ -127,13 +127,13 @@ C_VAR_FLOAT("rend-model-lod", &rend_model_lod, CVF_NO_MAX, 0, 0); C_VAR_INT ("rend-model-mirror-hud", &mirrorHudModels, 0, 0, 1); C_VAR_FLOAT("rend-model-spin-speed", &modelSpinSpeed, CVF_NO_MAX | CVF_NO_MIN, 0, 0); - C_VAR_INT ("rend-model-shiny-multitex", &modelShinyMultitex, 0, 0, 1); + //C_VAR_INT ("rend-model-shiny-multitex", &modelShinyMultitex, 0, 0, 1); C_VAR_FLOAT("rend-model-shiny-strength", &modelShinyFactor, 0, 0, 10); } void Rend_ModelInit() { - if(inited) return; // Already been here. + if (inited) return; // Already been here. modelPosCoords = 0; modelNormCoords = 0; @@ -150,7 +150,7 @@ void Rend_ModelShutdown() { - if(!inited) return; + if (!inited) return; M_Free(modelPosCoords); modelPosCoords = 0; M_Free(modelNormCoords); modelNormCoords = 0; @@ -171,13 +171,13 @@ LOG_AS("Rend_ModelExpandVertexBuffers"); - if(numVertices <= vertexBufferMax) return true; + if (numVertices <= vertexBufferMax) return true; // Sanity check a sane maximum... - if(numVertices >= RENDER_MAX_MODEL_VERTS) + if (numVertices >= RENDER_MAX_MODEL_VERTS) { #ifdef DENG_DEBUG - if(!announcedVertexBufferMaxBreach) + if (!announcedVertexBufferMaxBreach) { LOGDEV_GL_WARNING("Attempted to expand to %u vertices (max %u)") << numVertices << RENDER_MAX_MODEL_VERTS; @@ -199,7 +199,7 @@ Rend_ModelExpandVertexBuffers(numVertices); // Do we need to resize the buffers? - if(vertexBufferMax != vertexBufferSize) + if (vertexBufferMax != vertexBufferSize) { /// @todo Align access to this memory along a 4-byte boundary? modelPosCoords = (Vector3f *) M_Realloc(modelPosCoords, sizeof(*modelPosCoords) * vertexBufferMax); @@ -219,19 +219,19 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - if(vertices) + if (vertices) { arrays[AR_VERTEX].enabled = false; } - if(colors) + if (colors) { arrays[AR_COLOR].enabled = false; } - for(int i = 0; i < numTexUnits; ++i) + for (int i = 0; i < MAX_TEX_UNITS; ++i) { - if(coords & (1 << i)) + if (coords & (1 << i)) { arrays[AR_TEXCOORD0 + i].enabled = false; } @@ -245,8 +245,7 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + id); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE0 + id); } static inline void disableTexUnit(int id) @@ -254,8 +253,7 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glActiveTexture(GL_TEXTURE0 + id); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE0 + id); // Implicit disabling of texcoord array. disableArrays(0, 0, 1 << id); @@ -266,18 +264,18 @@ */ static void selectTexUnits(int count) { - if (count < numTexUnits) + if (count < MAX_TEX_UNITS) { - for (int i = numTexUnits - 1; i >= count; i--) + for (int i = MAX_TEX_UNITS - 1; i >= count; i--) { disableTexUnit(i); } } // Enable the selected units. - for(int i = count - 1; i >= 0; i--) + for (int i = count - 1; i >= 0; i--) { - if(i >= numTexUnits) continue; + if (i >= MAX_TEX_UNITS) continue; enableTexUnit(i); } } @@ -286,26 +284,26 @@ * Enable, set and optionally lock all enabled arrays. */ static void configureArrays(void *vertices, void *colors, int numCoords = 0, - void **coords = 0) + void **coords = 0) { DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - if(vertices) + if (vertices) { arrays[AR_VERTEX].enabled = true; arrays[AR_VERTEX].data = vertices; } - if(colors) + if (colors) { arrays[AR_COLOR].enabled = true; arrays[AR_COLOR].data = colors; } - for(int i = 0; i < numCoords && i < MAX_TEX_UNITS; ++i) + for (int i = 0; i < numCoords && i < MAX_TEX_UNITS; ++i) { - if(coords[i]) + if (coords[i]) { arrays[AR_TEXCOORD0 + i].enabled = true; arrays[AR_TEXCOORD0 + i].data = coords[i]; @@ -320,24 +318,25 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - for(int i = 0; i < numTexUnits; ++i) + for (int i = 0; i < MAX_TEX_UNITS; ++i) { - if(!arrays[AR_TEXCOORD0 + i].enabled) continue; - - Vector2f const &texCoord = ((Vector2f const *)arrays[AR_TEXCOORD0 + i].data)[index]; - LIBGUI_GL.glMultiTexCoord2f(GL_TEXTURE0 + i, texCoord.x, texCoord.y); + if (arrays[AR_TEXCOORD0 + i].enabled) + { + Vector2f const &texCoord = reinterpret_cast(arrays[AR_TEXCOORD0 + i].data)[index]; + DGL_TexCoord2fv(byte(i), texCoord.constPtr()); + } } - if(arrays[AR_COLOR].enabled) + if (arrays[AR_COLOR].enabled) { - Vector4ub const &colorCoord = ((Vector4ub const *) arrays[AR_COLOR].data)[index]; - LIBGUI_GL.glColor4ub(colorCoord.x, colorCoord.y, colorCoord.z, colorCoord.w); + Vector4ub const &colorCoord = reinterpret_cast(arrays[AR_COLOR].data)[index]; + DGL_Color4ubv(colorCoord.constPtr()); } - if(arrays[AR_VERTEX].enabled) + if (arrays[AR_VERTEX].enabled) { - Vector3f const &posCoord = ((Vector3f const *) arrays[AR_VERTEX].data)[index]; - LIBGUI_GL.glVertex3f(posCoord.x, posCoord.y, posCoord.z); + Vector3f const &posCoord = reinterpret_cast(arrays[AR_VERTEX].data)[index]; + DGL_Vertex3fv(posCoord.constPtr()); } } @@ -346,7 +345,7 @@ */ static FrameModelFrame &visibleModelFrame(FrameModelDef &modef, int subnumber, int mobjId) { - if(subnumber >= int(modef.subCount())) + if (subnumber >= int(modef.subCount())) { throw Error("Rend_DrawModel.visibleFrame", QString("Model has %1 submodels, but submodel #%2 was requested") @@ -355,7 +354,7 @@ SubmodelDef const &sub = modef.subModelDef(subnumber); int curFrame = sub.frame; - if(modef.flags & MFF_IDFRAME) + if (modef.flags & MFF_IDFRAME) { curFrame += mobjId % sub.frameRange; } @@ -366,8 +365,11 @@ /** * Render a set of 3D model primitives using the given data. */ -static void drawPrimitives(rendcmd_t mode, FrameModel::Primitives const &primitives, - Vector3f *posCoords, Vector4ub *colorCoords, Vector2f *texCoords = 0) +static void drawPrimitives(rendcmd_t mode, + FrameModel::Primitives const &primitives, + Vector3f *posCoords, + Vector4ub *colorCoords, + Vector2f *texCoords = 0) { DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); @@ -377,7 +379,7 @@ // Load the vertex array. void *coords[2]; - switch(mode) + switch (mode) { case RC_OTHER_COORDS: coords[0] = texCoords; @@ -395,24 +397,72 @@ break; } - foreach(FrameModel::Primitive const &prim, primitives) + FrameModel::Primitive::Element const *firstElem = nullptr; + bool joining = false; + + auto submitElement = [mode, &firstElem] (FrameModel::Primitive::Element const &elem) + { + if (!firstElem) + { + firstElem = &elem; + } + if (mode != RC_OTHER_COORDS) + { + DGL_TexCoord2fv(0, elem.texCoord.constPtr()); + } + drawArrayElement(elem.index); + }; + + int lastLength = 0; + + // Combine all triangle strips and fans into one big strip. Fans are converted + // to strips. When joining strips, winding is retained so that each sub-strip + // begins with the same winding. + + DGL_Begin(DGL_TRIANGLE_STRIP); + foreach (FrameModel::Primitive const &prim, primitives) { - // The type of primitive depends on the sign. - LIBGUI_GL.glBegin(prim.triFan? GL_TRIANGLE_FAN : GL_TRIANGLE_STRIP); + DGLenum const primType = (prim.triFan? DGL_TRIANGLE_FAN : DGL_TRIANGLE_STRIP); - foreach(FrameModel::Primitive::Element const &elem, prim.elements) + joining = false; + if (lastLength > 0) { - if(mode != RC_OTHER_COORDS) + // Disconnect strip. + DGL_Vertex3fv(nullptr); + if (lastLength & 1) DGL_Vertex3fv(nullptr); // Retain the winding. + joining = true; + } + firstElem = nullptr; + + if (primType == DGL_TRIANGLE_STRIP) + { + lastLength = prim.elements.size(); + foreach (FrameModel::Primitive::Element const &elem, prim.elements) { - LIBGUI_GL.glTexCoord2f(elem.texCoord.x, elem.texCoord.y); + submitElement(elem); + if (joining) + { + DGL_Vertex3fv(nullptr); + joining = false; + } + } + } + else + { + lastLength = 2; // just make it even, so it doesn't affect winding (see above) + for (int i = 1; i < prim.elements.size(); ++i) + { + submitElement(prim.elements.at(0)); + if (joining) + { + DGL_Vertex3fv(nullptr); + joining = false; + } + submitElement(prim.elements.at(i)); } - - drawArrayElement(elem.index); } - - // The primitive is complete. - LIBGUI_GL.glEnd(); } + DGL_End(); } /** @@ -428,11 +478,11 @@ FrameModelFrame::VertexBuf::const_iterator startIt = from.vertices.begin(); FrameModelFrame::VertexBuf::const_iterator endIt = to.vertices.begin(); - if(&from == &to || de::fequal(inter, 0)) + if (&from == &to || de::fequal(inter, 0)) { - for(int i = 0; i < count; ++i, startIt++, posOut++, normOut++) + for (int i = 0; i < count; ++i, startIt++, posOut++, normOut++) { - if(!activeLod || activeLod->hasVertex(i)) + if (!activeLod || activeLod->hasVertex(i)) { *posOut = startIt->pos; *normOut = startIt->norm; @@ -441,9 +491,9 @@ } else { - for(int i = 0; i < count; ++i, startIt++, endIt++, posOut++, normOut++) + for (int i = 0; i < count; ++i, startIt++, endIt++, posOut++, normOut++) { - if(!activeLod || activeLod->hasVertex(i)) + if (!activeLod || activeLod->hasVertex(i)) { *posOut = de::lerp(startIt->pos, endIt->pos, inter); *normOut = de::lerp(startIt->norm, endIt->norm, inter); @@ -455,7 +505,7 @@ static void Mod_MirrorCoords(dint count, Vector3f *coords, dint axis) { DENG2_ASSERT(coords); - for(; count-- > 0; coords++) + for (; count-- > 0; coords++) { (*coords)[axis] = -(*coords)[axis]; } @@ -478,7 +528,7 @@ M_RotateVector(rotated, yaw, pitch); // Quick hack: Flip light normal if model inverted. - if(invert) + if (invert) { rotated[0] = -rotated[0]; rotated[1] = -rotated[1]; @@ -496,9 +546,9 @@ { Vector4f const saturated(1, 1, 1, 1); - for(dint i = 0; i < count; ++i, out++, normCoords++) + for (dint i = 0; i < count; ++i, out++, normCoords++) { - if(activeLod && !activeLod->hasVertex(i)) + if (activeLod && !activeLod->hasVertex(i)) continue; Vector3f const &normal = *normCoords; @@ -520,7 +570,7 @@ + vlight.offset; // Shift a bit towards the light. // Ability to both light and shade. - if(strength > 0) strength *= vlight.lightSide; + if (strength > 0) strength *= vlight.lightSide; else strength *= vlight.darkSide; accum[vlight.affectedByAmbient? 0 : 1] @@ -543,7 +593,7 @@ static void Mod_FullBrightVertexColors(dint count, Vector4ub *colorCoords, dfloat alpha) { DENG2_ASSERT(colorCoords); - for(; count-- > 0; colorCoords++) + for (; count-- > 0; colorCoords++) { *colorCoords = Vector4ub(255, 255, 255, 255 * alpha); } @@ -555,7 +605,7 @@ static void Mod_FixedVertexColors(dint count, Vector4ub *colorCoords, Vector4ub const &color) { DENG2_ASSERT(colorCoords); - for(; count-- > 0; colorCoords++) + for (; count-- > 0; colorCoords++) { *colorCoords = color; } @@ -567,9 +617,9 @@ static void Mod_ShinyCoords(Vector2f *out, int count, Vector3f const *normCoords, float normYaw, float normPitch, float shinyAng, float shinyPnt, float reactSpeed) { - for(int i = 0; i < count; ++i, out++, normCoords++) + for (int i = 0; i < count; ++i, out++, normCoords++) { - if(activeLod && !activeLod->hasVertex(i)) + if (activeLod && !activeLod->hasVertex(i)) continue; float rotatedNormal[3] = { normCoords->x, normCoords->y, normCoords->z }; @@ -586,18 +636,18 @@ static int chooseSelSkin(FrameModelDef &mf, int submodel, int selector) { - if(mf.def.hasSub(submodel)) + if (mf.def.hasSub(submodel)) { Record &subDef = mf.def.sub(submodel); int i = (selector >> DDMOBJ_SELECTOR_SHIFT) & subDef.geti("selSkinMask"); int c = subDef.geti("selSkinShift"); - if(c > 0) i >>= c; - else i <<= -c; + if (c > 0) i >>= c; + else i <<= -c; - if(i > 7) i = 7; // Maximum number of skins for selskin. - if(i < 0) i = 0; // Improbable (impossible?), but doesn't hurt. + if (i > 7) i = 7; // Maximum number of skins for selskin. + if (i < 0) i = 0; // Improbable (impossible?), but doesn't hurt. return subDef.geta("selSkins")[i].asInt(); } @@ -606,7 +656,7 @@ static int chooseSkin(FrameModelDef &mf, int submodel, int id, int selector, int tmap) { - if(submodel >= int(mf.subCount())) + if (submodel >= int(mf.subCount())) { return 0; } @@ -616,18 +666,18 @@ int skin = smf.skin; // Selskin overrides the skin range. - if(smf.testFlag(MFF_SELSKIN)) + if (smf.testFlag(MFF_SELSKIN)) { skin = chooseSelSkin(mf, submodel, selector); } // Is there a skin range for this frame? // (During model setup skintics and skinrange are set to >0.) - if(smf.skinRange > 1) + if (smf.skinRange > 1) { // What rule to use for determining the skin? int offset; - if(smf.testFlag(MFF_IDSKIN)) + if (smf.testFlag(MFF_IDSKIN)) { offset = id; } @@ -640,12 +690,12 @@ } // Need translation? - if(smf.testFlag(MFF_SKINTRANS)) + if (smf.testFlag(MFF_SKINTRANS)) { skin = tmap; } - if(skin < 0 || skin >= mdl.skinCount()) + if (skin < 0 || skin >= mdl.skinCount()) { skin = 0; } @@ -669,25 +719,25 @@ FrameModel &mdl = App_Resources().model(smf.modelId); // Do not bother with infinitely small models... - if(mf->scale == Vector3f(0, 0, 0)) + if (mf->scale == Vector3f(0, 0, 0)) return; float alpha = spr.light.ambientColor[CA]; // Is the submodel-defined alpha multiplier in effect? // With df_brightshadow2, the alpha multiplier will be applied anyway. - if(smf.testFlag(MFF_BRIGHTSHADOW2) || + if (smf.testFlag(MFF_BRIGHTSHADOW2) || !(parm.flags & (DDMF_BRIGHTSHADOW|DDMF_SHADOW|DDMF_ALTSHADOW))) { alpha *= smf.alpha / 255.f; } // Would this be visible? - if(alpha <= 0) return; + if (alpha <= 0) return; blendmode_t blending = smf.blendMode; // Is the submodel-defined blend mode in effect? - if(parm.flags & DDMF_BRIGHTSHADOW) + if (parm.flags & DDMF_BRIGHTSHADOW) { blending = BM_ADD; } @@ -699,7 +749,7 @@ // interrange. If a custom one is defined, don't touch interpos. float endPos = 0; float inter = parm.inter; - if((mf->interRange[0] == 0 && mf->interRange[1] == 1) || smf.testFlag(MFF_WORLD_TIME_ANIM)) + if ((mf->interRange[0] == 0 && mf->interRange[1] == 1) || smf.testFlag(MFF_WORLD_TIME_ANIM)) { endPos = (mf->interNext ? mf->interNext->interMark : 1); inter = (parm.inter - mf->interMark) / (endPos - mf->interMark); @@ -708,7 +758,7 @@ FrameModelFrame *frame = &visibleModelFrame(*mf, number, parm.id); FrameModelFrame *nextFrame = 0; // Do we have a sky/particle model here? - if(parm.alwaysInterpolate) + if (parm.alwaysInterpolate) { // Always interpolate, if there's animation. // Used with sky and particle models. @@ -718,9 +768,9 @@ else { // Check for possible interpolation. - if(frameInter && mfNext && !smf.testFlag(MFF_DONT_INTERPOLATE)) + if (frameInter && mfNext && !smf.testFlag(MFF_DONT_INTERPOLATE)) { - if(mfNext->hasSub(number) && mfNext->subModelId(number) == smf.modelId) + if (mfNext->hasSub(number) && mfNext->subModelId(number) == smf.modelId) { nextFrame = &visibleModelFrame(*mfNext, number, parm.id); } @@ -730,7 +780,7 @@ // Clamp interpolation. inter = de::clamp(0.f, inter, 1.f); - if(!nextFrame) + if (!nextFrame) { // If not interpolating, use the same frame as interpolation target. // The lerp routines will recognize this special case. @@ -742,53 +792,53 @@ int numVerts = mdl.vertexCount(); // Ensure our vertex render buffers can accommodate this. - if(!resizeVertexBuffer(numVerts)) + if (!resizeVertexBuffer(numVerts)) { // No can do, we aint got the power! return; } // Setup transformation. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // Model space => World space - LIBGUI_GL.glTranslatef(spr.pose.origin[VX] + spr.pose.srvo[VX] + + DGL_Translatef(spr.pose.origin[VX] + spr.pose.srvo[VX] + de::lerp(mf->offset.x, mfNext->offset.x, inter), - spr.pose.origin[VZ] + spr.pose.srvo[VZ] + + spr.pose.origin[VZ] + spr.pose.srvo[VZ] + de::lerp(mf->offset.y, mfNext->offset.y, inter), - spr.pose.origin[VY] + spr.pose.srvo[VY] + zSign * + spr.pose.origin[VY] + spr.pose.srvo[VY] + zSign * de::lerp(mf->offset.z, mfNext->offset.z, inter)); - if(spr.pose.extraYawAngle || spr.pose.extraPitchAngle) + if (spr.pose.extraYawAngle || spr.pose.extraPitchAngle) { // Sky models have an extra rotation. - LIBGUI_GL.glScalef(1, 200 / 240.0f, 1); - LIBGUI_GL.glRotatef(spr.pose.extraYawAngle, 1, 0, 0); - LIBGUI_GL.glRotatef(spr.pose.extraPitchAngle, 0, 0, 1); - LIBGUI_GL.glScalef(1, 240 / 200.0f, 1); + DGL_Scalef(1, 200 / 240.0f, 1); + DGL_Rotatef(spr.pose.extraYawAngle, 1, 0, 0); + DGL_Rotatef(spr.pose.extraPitchAngle, 0, 0, 1); + DGL_Scalef(1, 240 / 200.0f, 1); } // Model rotation. - LIBGUI_GL.glRotatef(spr.pose.viewAligned? spr.pose.yawAngleOffset : spr.pose.yaw, 0, 1, 0); - LIBGUI_GL.glRotatef(spr.pose.viewAligned? spr.pose.pitchAngleOffset : spr.pose.pitch, 0, 0, 1); + DGL_Rotatef(spr.pose.viewAligned? spr.pose.yawAngleOffset : spr.pose.yaw, 0, 1, 0); + DGL_Rotatef(spr.pose.viewAligned? spr.pose.pitchAngleOffset : spr.pose.pitch, 0, 0, 1); // Scaling and model space offset. - LIBGUI_GL.glScalef(de::lerp(mf->scale.x, mfNext->scale.x, inter), + DGL_Scalef(de::lerp(mf->scale.x, mfNext->scale.x, inter), de::lerp(mf->scale.y, mfNext->scale.y, inter), de::lerp(mf->scale.z, mfNext->scale.z, inter)); - if(spr.pose.extraScale) + if (spr.pose.extraScale) { // Particle models have an extra scale. - LIBGUI_GL.glScalef(spr.pose.extraScale, spr.pose.extraScale, spr.pose.extraScale); + DGL_Scalef(spr.pose.extraScale, spr.pose.extraScale, spr.pose.extraScale); } - LIBGUI_GL.glTranslatef(smf.offset.x, smf.offset.y, smf.offset.z); + DGL_Translatef(smf.offset.x, smf.offset.y, smf.offset.z); // Determine the suitable LOD. - if(mdl.lodCount() > 1 && rend_model_lod != 0) + if (mdl.lodCount() > 1 && rend_model_lod != 0) { float lodFactor = rend_model_lod * DENG_GAMEVIEW_WIDTH / 640.0f / (Rend_FieldOfView() / 90.0f); - if(!de::fequal(lodFactor, 0)) + if (!de::fequal(lodFactor, 0)) { lodFactor = 1 / lodFactor; } @@ -805,7 +855,7 @@ Mod_LerpVertices(inter, numVerts, *frame, *nextFrame, modelPosCoords, modelNormCoords); - if(zSign < 0) + if (zSign < 0) { Mod_MirrorCoords(numVerts, modelPosCoords, 2); Mod_MirrorCoords(numVerts, modelNormCoords, 1); @@ -817,13 +867,13 @@ // Calculate lighting. Vector4f ambient; - if(smf.testFlag(MFF_FULLBRIGHT) && !smf.testFlag(MFF_DIM)) + if (smf.testFlag(MFF_FULLBRIGHT) && !smf.testFlag(MFF_DIM)) { // Submodel-specific lighting override. ambient = Vector4f(1, 1, 1, 1); Mod_FullBrightVertexColors(numVerts, modelColorCoords, alpha); } - else if(!spr.light.vLightListIdx) + else if (!spr.light.vLightListIdx) { // Lit uniformly. ambient = Vector4f(spr.light.ambientColor, alpha); @@ -842,13 +892,13 @@ TextureVariant *shinyTexture = 0; float shininess = 0; - if(mf->def.hasSub(number)) + if (mf->def.hasSub(number)) { shininess = float(de::clamp(0.0, mf->def.sub(number).getd("shiny") * modelShinyFactor, 1.0)); // Ensure we've prepared the shiny skin. - if(shininess > 0) + if (shininess > 0) { - if(ClientTexture *tex = static_cast(mf->subModelDef(number).shinySkin)) + if (ClientTexture *tex = static_cast(mf->subModelDef(number).shinySkin)) { shinyTexture = tex->prepareVariant(Rend_ModelShinyTextureSpec()); } @@ -860,7 +910,7 @@ } Vector4f color; - if(shininess > 0) + if (shininess > 0) { // Calculate shiny coordinates. Vector3f shinyColor = mf->def.sub(number).get("shinyColor"); @@ -879,7 +929,7 @@ float shinyAng = 0; float shinyPnt = 0; - if(parm.shinepspriteCoordSpace) + if (parm.shinepspriteCoordSpace) { // This is a hack to accommodate the psprite coordinate space. shinyPnt = 0.5; @@ -888,7 +938,7 @@ { Vector3f delta = modelCenter; - if(!parm.shineTranslateWithViewerPos) + if (!parm.shineTranslateWithViewerPos) { delta -= Rend_EyeOrigin().xzy(); } @@ -903,7 +953,7 @@ mf->def.sub(number).getf("shinyReact")); // Shiny color. - if(smf.testFlag(MFF_SHINY_LIT)) + if (smf.testFlag(MFF_SHINY_LIT)) { color = Vector4f(ambient * shinyColor, shininess); } @@ -914,7 +964,7 @@ } TextureVariant *skinTexture = 0; - if(renderTextures == 2) + if (renderTextures == 2) { // For lighting debug, render all surfaces using the gray texture. MaterialAnimator &matAnimator = ClientMaterial::find(de::Uri("System", Path("gray"))) @@ -928,36 +978,35 @@ else { skinTexture = 0; - if(ClientTexture *tex = static_cast(mdl.skin(useSkin).texture)) + if (ClientTexture *tex = static_cast(mdl.skin(useSkin).texture)) { skinTexture = tex->prepareVariant(Rend_ModelDiffuseTextureSpec(mdl.flags().testFlag(FrameModel::NoTextureCompression))); } } // If we mirror the model, triangles have a different orientation. - if(zSign < 0) + if (zSign < 0) { LIBGUI_GL.glFrontFace(GL_CCW); } // Twosided models won't use backface culling. - if(smf.testFlag(MFF_TWO_SIDED)) + if (smf.testFlag(MFF_TWO_SIDED)) { //glDisable(GL_CULL_FACE); - GLState::current().setCull(gl::None).apply(); + DGL_CullFace(DGL_NONE); } - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); FrameModel::Primitives const &primitives = activeLod? activeLod->primitives : mdl.primitives(); // Render using multiple passes? - if(!modelShinyMultitex || shininess <= 0 || alpha < 1 || - blending != BM_NORMAL || !smf.testFlag(MFF_SHINY_SPECULAR) || - numTexUnits < 2 || !envModAdd) + if (shininess <= 0 || alpha < 1 || + blending != BM_NORMAL || !smf.testFlag(MFF_SHINY_SPECULAR)) { // The first pass can be skipped if it won't be visible. - if(shininess < 1 || smf.testFlag(MFF_SHINY_SPECULAR)) + if (shininess < 1 || smf.testFlag(MFF_SHINY_SPECULAR)) { selectTexUnits(1); GL_BlendMode(blending); @@ -967,13 +1016,12 @@ modelPosCoords, modelColorCoords); } - if(shininess > 0) + if (shininess > 0) { - //glDepthFunc(GL_LEQUAL); - GLState::current().setDepthFunc(gl::LessOrEqual).apply(); + DGL_DepthFunc(DGL_LEQUAL); // Set blending mode, two choices: reflected and specular. - if(smf.testFlag(MFF_SHINY_SPECULAR)) + if (smf.testFlag(MFF_SHINY_SPECULAR)) GL_BlendMode(BM_ADD); else GL_BlendMode(BM_NORMAL); @@ -982,34 +1030,22 @@ Mod_FixedVertexColors(numVerts, modelColorCoords, (color * 255).toVector4ub()); - if(numTexUnits > 1 && modelShinyMultitex) - { - // We'll use multitexturing to clear out empty spots in - // the primary texture. - selectTexUnits(2); - GL_ModulateTexture(11); - - LIBGUI_GL.glActiveTexture(GL_TEXTURE1); - GL_BindTexture(renderTextures? shinyTexture : 0); + // We'll use multitexturing to clear out empty spots in + // the primary texture. + selectTexUnits(2); + DGL_ModulateTexture(11); - LIBGUI_GL.glActiveTexture(GL_TEXTURE0); - GL_BindTexture(renderTextures? skinTexture : 0); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); + GL_BindTexture(renderTextures? shinyTexture : 0); - drawPrimitives(RC_BOTH_COORDS, primitives, - modelPosCoords, modelColorCoords, modelTexCoords); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); + GL_BindTexture(renderTextures? skinTexture : 0); - selectTexUnits(1); - GL_ModulateTexture(1); - } - else - { - // Empty spots will get shine, too. - selectTexUnits(1); - GL_BindTexture(renderTextures? shinyTexture : 0); + drawPrimitives(RC_BOTH_COORDS, primitives, + modelPosCoords, modelColorCoords, modelTexCoords); - drawPrimitives(RC_OTHER_COORDS, primitives, - modelPosCoords, modelColorCoords, modelTexCoords); - } + selectTexUnits(1); + DGL_ModulateTexture(1); } } else @@ -1020,43 +1056,43 @@ selectTexUnits(2); // Tex1*Color + Tex2RGB*ConstRGB - GL_ModulateTexture(10); + DGL_ModulateTexture(10); - LIBGUI_GL.glActiveTexture(GL_TEXTURE1); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 1); GL_BindTexture(renderTextures? shinyTexture : 0); // Multiply by shininess. float colorv1[] = { color.x * color.w, color.y * color.w, color.z * color.w, color.w }; - LIBGUI_GL.glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, colorv1); + DGL_SetModulationColor(colorv1); - LIBGUI_GL.glActiveTexture(GL_TEXTURE0); + DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); GL_BindTexture(renderTextures? skinTexture : 0); drawPrimitives(RC_BOTH_COORDS, primitives, modelPosCoords, modelColorCoords, modelTexCoords); selectTexUnits(1); - GL_ModulateTexture(1); + DGL_ModulateTexture(1); } // We're done! - LIBGUI_GL.glDisable(GL_TEXTURE_2D); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_Disable(DGL_TEXTURE_2D); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); // Normally culling is always enabled. - if(smf.testFlag(MFF_TWO_SIDED)) + if (smf.testFlag(MFF_TWO_SIDED)) { //glEnable(GL_CULL_FACE); - GLState::current().setCull(gl::Back).apply(); + DGL_CullFace(DGL_BACK); } - if(zSign < 0) + if (zSign < 0) { LIBGUI_GL.glFrontFace(GL_CW); } //glDepthFunc(GL_LESS); - GLState::current().setDepthFunc(gl::Less).apply(); + DGL_DepthFunc(DGL_LESS); GL_BlendMode(BM_NORMAL); } @@ -1069,63 +1105,60 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - if(!parm.mf) return; + if (!parm.mf) return; + + DENG2_ASSERT(parm.mf->select == (parm.selector & DDMOBJ_SELECTOR_MASK)) // Render all the submodels of this model. - for(uint i = 0; i < parm.mf->subCount(); ++i) + for (uint i = 0; i < parm.mf->subCount(); ++i) { - if(parm.mf->subModelId(i)) + if (parm.mf->subModelId(i)) { bool disableZ = (parm.mf->flags & MFF_DISABLE_Z_WRITE || parm.mf->testSubFlag(i, MFF_DISABLE_Z_WRITE)); - if(disableZ) + if (disableZ) { - //glDepthMask(GL_FALSE); - GLState::current().setDepthWrite(false).apply(); + DGL_Disable(DGL_DEPTH_WRITE); } drawSubmodel(i, spr); - if(disableZ) + if (disableZ) { - //glDepthMask(GL_TRUE); - GLState::current().setDepthWrite(true).apply(); + DGL_Enable(DGL_DEPTH_WRITE); } } } - if(devMobjVLights && spr.light.vLightListIdx) + if (devMobjVLights && spr.light.vLightListIdx) { // Draw the vlight vectors, for debug. //glDisable(GL_DEPTH_TEST); //glDisable(GL_CULL_FACE); - GLState::push() - .setDepthTest(false) - .setCull(gl::None) - .apply(); + DGL_PushState(); + DGL_Disable(DGL_DEPTH_TEST); + DGL_CullFace(DGL_NONE); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - LIBGUI_GL.glTranslatef(spr.pose.origin[0], spr.pose.origin[2], spr.pose.origin[1]); + DGL_Translatef(spr.pose.origin[0], spr.pose.origin[2], spr.pose.origin[1]); coord_t const distFromViewer = de::abs(spr.pose.distance); ClientApp::renderSystem().forAllVectorLights(spr.light.vLightListIdx, [&distFromViewer] (VectorLightData const &vlight) { - if(distFromViewer < 1600 - 8) + if (distFromViewer < 1600 - 8) { Rend_DrawVectorLight(vlight, 1 - distFromViewer / 1600); } return LoopContinue; }); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); - //glEnable(GL_CULL_FACE); - //glEnable(GL_DEPTH_TEST); - GLState::pop().apply(); + DGL_PopState(); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_particle.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_particle.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/rend_particle.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/rend_particle.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -520,7 +520,7 @@ static void drawParticles(dint rtype, bool withBlend) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); viewdata_t const *viewData = &viewPlayer->viewport(); @@ -541,35 +541,26 @@ } } - ushort primType = GL_QUADS; + dglprimtype_t primType = DGL_QUADS; if (rtype == PTC_MODEL) { - //glDepthMask(GL_TRUE); - //glEnable(GL_DEPTH_TEST); - GLState::current() - .setDepthWrite(true) - .setDepthTest(true) - .apply(); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_Enable(DGL_DEPTH_TEST); } else if (tex != 0) { - //glDepthMask(GL_FALSE); - //glDisable(GL_CULL_FACE); - GLState::current() - .setDepthWrite(false) - .setDepthFunc(gl::LessOrEqual) - .setCull(gl::None) - .apply(); + DGL_Disable(DGL_DEPTH_WRITE); + DGL_DepthFunc(DGL_LEQUAL); + DGL_CullFace(DGL_NONE); GL_BindTextureUnmanaged(tex, gl::ClampToEdge, gl::ClampToEdge); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); - //glDepthFunc(GL_LEQUAL); - LIBGUI_GL.glBegin(primType = GL_QUADS); + DGL_Begin(primType = DGL_QUADS); } else { - LIBGUI_GL.glBegin(primType = GL_LINES); + DGL_Begin(primType = DGL_LINES); } // How many particles will be drawn? @@ -617,9 +608,9 @@ if(newMode != mode) { - LIBGUI_GL.glEnd(); + DGL_End(); GL_BlendMode(mode = newMode); - LIBGUI_GL.glBegin(primType); + DGL_Begin(primType); } } @@ -684,7 +675,7 @@ if(color.w <= 0) continue; - LIBGUI_GL.glColor4f(color.x, color.y, color.z, color.w); + DGL_Color4f(color.x, color.y, color.z, color.w); bool const nearWall = (pinfo.contact && !pinfo.mov[0] && !pinfo.mov[1]); @@ -720,7 +711,7 @@ // Model particles are rendered using the normal model rendering routine. if(rtype == PTC_MODEL && stDef->model >= 0) { - vissprite_t temp; de::zap(temp); + vissprite_t temp; setupModelParamsForParticle(temp, &pinfo, st, stDef, center, dist, size, inter, color.w); Rend_DrawModel(temp); continue; @@ -732,17 +723,17 @@ // Should the particle be flat against a plane? if(flatOnPlane) { - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex3f(center.x - size, center.y, center.z - size); + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex3f(center.x - size, center.y, center.z - size); - LIBGUI_GL.glTexCoord2f(1, 0); - LIBGUI_GL.glVertex3f(center.x + size, center.y, center.z - size); + DGL_TexCoord2f(0, 1, 0); + DGL_Vertex3f(center.x + size, center.y, center.z - size); - LIBGUI_GL.glTexCoord2f(1, 1); - LIBGUI_GL.glVertex3f(center.x + size, center.y, center.z + size); + DGL_TexCoord2f(0, 1, 1); + DGL_Vertex3f(center.x + size, center.y, center.z + size); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex3f(center.x - size, center.y, center.z + size); + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex3f(center.x - size, center.y, center.z + size); } // Flat against a wall, then? else if(flatOnWall) @@ -775,70 +766,64 @@ Vector2f unitVec = lineUnitVector(*pinfo.contact); - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex3d(projected[0] - size * unitVec.x, center.y - size, + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex3f(projected[0] - size * unitVec.x, center.y - size, projected[1] - size * unitVec.y); - LIBGUI_GL.glTexCoord2f(1, 0); - LIBGUI_GL.glVertex3d(projected[0] - size * unitVec.x, center.y + size, + DGL_TexCoord2f(0, 1, 0); + DGL_Vertex3f(projected[0] - size * unitVec.x, center.y + size, projected[1] - size * unitVec.y); - LIBGUI_GL.glTexCoord2f(1, 1); - LIBGUI_GL.glVertex3d(projected[0] + size * unitVec.x, center.y + size, + DGL_TexCoord2f(0, 1, 1); + DGL_Vertex3f(projected[0] + size * unitVec.x, center.y + size, projected[1] + size * unitVec.y); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex3d(projected[0] + size * unitVec.x, center.y - size, + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex3f(projected[0] + size * unitVec.x, center.y - size, projected[1] + size * unitVec.y); } else { - LIBGUI_GL.glTexCoord2f(0, 0); - LIBGUI_GL.glVertex3f(center.x + size * leftoff.x, + DGL_TexCoord2f(0, 0, 0); + DGL_Vertex3f(center.x + size * leftoff.x, center.y + size * leftoff.y / 1.2f, center.z + size * leftoff.z); - LIBGUI_GL.glTexCoord2f(1, 0); - LIBGUI_GL.glVertex3f(center.x + size * rightoff.x, + DGL_TexCoord2f(0, 1, 0); + DGL_Vertex3f(center.x + size * rightoff.x, center.y + size * rightoff.y / 1.2f, center.z + size * rightoff.z); - LIBGUI_GL.glTexCoord2f(1, 1); - LIBGUI_GL.glVertex3f(center.x - size * leftoff.x, + DGL_TexCoord2f(0, 1, 1); + DGL_Vertex3f(center.x - size * leftoff.x, center.y - size * leftoff.y / 1.2f, center.z - size * leftoff.z); - LIBGUI_GL.glTexCoord2f(0, 1); - LIBGUI_GL.glVertex3f(center.x - size * rightoff.x, + DGL_TexCoord2f(0, 0, 1); + DGL_Vertex3f(center.x - size * rightoff.x, center.y - size * rightoff.y / 1.2f, center.z - size * rightoff.z); } } else // It's a line. { - LIBGUI_GL.glVertex3f(center.x, center.y, center.z); - LIBGUI_GL.glVertex3f(center.x - FIX2FLT(pinfo.mov[0]), - center.y - FIX2FLT(pinfo.mov[2]), - center.z - FIX2FLT(pinfo.mov[1])); + DGL_Vertex3f(center.x, center.y, center.z); + DGL_Vertex3f(center.x - FIX2FLT(pinfo.mov[0]), + center.y - FIX2FLT(pinfo.mov[2]), + center.z - FIX2FLT(pinfo.mov[1])); } } if(rtype != PTC_MODEL) { - LIBGUI_GL.glEnd(); + DGL_End(); if(tex != 0) { - //glEnable(GL_CULL_FACE); - //glDepthMask(GL_TRUE); - //glDepthFunc(GL_LESS); - GLState::current() - .setCull(gl::Back) - .setDepthWrite(true) - .setDepthFunc(gl::Less) - .apply(); - - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_CullFace(DGL_BACK); + DGL_Enable(DGL_DEPTH_WRITE); + DGL_DepthFunc(DGL_LESS); + DGL_Disable(DGL_TEXTURE_2D); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_main.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -172,7 +172,7 @@ if (fogParams.usingFog) { - LIBGUI_GL.glEnable(GL_FOG); + DGL_Enable(DGL_FOG); } // Draw HUD vissprites. @@ -200,7 +200,7 @@ if (fogParams.usingFog) { - LIBGUI_GL.glDisable(GL_FOG); + DGL_Disable(DGL_FOG); } } @@ -308,7 +308,7 @@ if (spr.type == VPSPR_MODEL) { - vissprite_t vs; de::zap(vs); + vissprite_t vs; setupModelParamsForVisPSprite(vs, spr); Rend_DrawModel(vs); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_things.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_things.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/r_things.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/r_things.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -137,14 +137,12 @@ static void findMobjZOrigin(mobj_t &mob, bool floorAdjust, vissprite_t &vis) { validCount++; - Mobj_Map(mob).forAllSectorsTouchingMobj(mob, [&mob, &floorAdjust, &vis] (Sector §or) - { - if(floorAdjust && mob.origin[2] == sector.floor().height()) + Mobj_Map(mob).forAllSectorsTouchingMobj(mob, [&mob, &floorAdjust, &vis](Sector §or) { + if (floorAdjust && fequal(mob.origin[2], sector.floor().height())) { vis.pose.origin.z = sector.floor().heightSmoothed(); } - - if(mob.origin[2] + mob.height == sector.ceiling().height()) + if (fequal(mob.origin[2] + mob.height, sector.ceiling().height())) { vis.pose.origin.z = sector.ceiling().heightSmoothed() - mob.height; } @@ -193,6 +191,7 @@ mf = Mobj_ModelDef(mob, &nextmf, &interp); if(mf) { + DENG2_ASSERT(mf->select == (mob.selector & DDMOBJ_SELECTOR_MASK)) // Use a sprite if the object is beyond the maximum model distance. if(maxModelDistance && !(mf->flags & MFF_NO_DISTANCE_CHECK) && distFromEye > maxModelDistance) @@ -370,7 +369,13 @@ !INRANGE_OF(mob.mom[2], 0, NOMOMENTUM_THRESHOLD)) { // Use the object's speed to calculate a short-range offset. - visOff += Vector3d(mob.mom) * frameTimePos; + // Note that the object may have momentum but still be blocked from moving + // (e.g., Heretic gas pods). + + visOff += Vector3d(~mob.ddFlags & DDMF_MOVEBLOCKEDX ? mob.mom[VX] : 0.0, + ~mob.ddFlags & DDMF_MOVEBLOCKEDY ? mob.mom[VY] : 0.0, + ~mob.ddFlags & DDMF_MOVEBLOCKEDZ ? mob.mom[VZ] : 0.0) * + frameTimePos; } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/shadowedge.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/shadowedge.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/shadowedge.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/shadowedge.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -223,7 +223,7 @@ /// @todo fixme: Should use the visual plane heights of subsectors. dint const edge = lineSide.sideId() ^ d->edge; - LineOwner const *vo = &lineSide.line().vertexOwner(edge)->navigate(ClockDirection(d->edge ^ 1)); + LineOwner const *vo = lineSide.line().vertexOwner(edge)->navigate(ClockDirection(d->edge ^ 1)); Line const &neighborLine = vo->line(); if (&neighborLine == &lineSide.line()) @@ -278,7 +278,7 @@ if (d->openness < 1) { LineOwner *vo = lineSide.line().vertexOwner(lineSide.sideId() ^ d->edge); - if (d->edge) vo = &vo->prev(); + if (d->edge) vo = vo->prev(); d->inner = Vector3d(lineSide.vertex(d->edge).origin() + vo->innerShadowOffset(), plane.heightSmoothed()); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/skydrawable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/skydrawable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/skydrawable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/skydrawable.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -151,37 +151,37 @@ { GL_SetNoTexture(); - LIBGUI_GL.glColor3f(color.x, color.y, color.z); + DGL_Color3f(color.x, color.y, color.z); // Draw the cap. - LIBGUI_GL.glBegin(GL_TRIANGLE_FAN); + DGL_Begin(DGL_TRIANGLE_FAN); for(int c = 0; c < columns; ++c) { Vector3f const &vtx = vertex(0, c); - LIBGUI_GL.glVertex3f(vtx.x, vtx.y, vtx.z); + DGL_Vertex3f(vtx.x, vtx.y, vtx.z); } - LIBGUI_GL.glEnd(); + DGL_End(); // Are we doing a colored fadeout? if(!drawFadeOut) return; // We must fill the background for the top row since it'll be translucent. - LIBGUI_GL.glBegin(GL_TRIANGLE_STRIP); + DGL_Begin(DGL_TRIANGLE_STRIP); Vector3f const *vtx = &vertex(0, 0); - LIBGUI_GL.glVertex3f(vtx->x, vtx->y, vtx->z); + DGL_Vertex3f(vtx->x, vtx->y, vtx->z); int c = 0; for(; c < columns; ++c) { // One step down. vtx = &vertex(1, c); - LIBGUI_GL.glVertex3f(vtx->x, vtx->y, vtx->z); + DGL_Vertex3f(vtx->x, vtx->y, vtx->z); // And one step right. vtx = &vertex(0, c + 1); - LIBGUI_GL.glVertex3f(vtx->x, vtx->y, vtx->z); + DGL_Vertex3f(vtx->x, vtx->y, vtx->z); } vtx = &vertex(1, c); - LIBGUI_GL.glVertex3f(vtx->x, vtx->y, vtx->z); - LIBGUI_GL.glEnd(); + DGL_Vertex3f(vtx->x, vtx->y, vtx->z); + DGL_End(); } void draw(SphereComponent hemisphere, Sky const &sky, dint firstActiveLayer, @@ -196,9 +196,9 @@ if (yflip) { // The lower hemisphere must be flipped. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glScalef(1.0f, -1.0f, 1.0f); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Scalef(1.0f, -1.0f, 1.0f); } // First draw the cap and the background for fadeouts, if needed. @@ -224,20 +224,20 @@ layerTex = matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture; GL_BindTexture(layerTex); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); + DGL_Enable(DGL_TEXTURE_2D); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_LoadIdentity(); Vector2ui const &texSize = layerTex->base().dimensions(); if (texSize.x > 0) { - LIBGUI_GL.glTranslatef(ldata.offset / texSize.x, 0, 0); - LIBGUI_GL.glScalef(1024.f / texSize.x, 1, 1); + DGL_Translatef(ldata.offset / texSize.x, 0, 0); + DGL_Scalef(1024.f / texSize.x, 1, 1); } if (yflip) { - LIBGUI_GL.glScalef(1, -1, 1); - LIBGUI_GL.glTranslatef(0, -1, 0); + DGL_Scalef(1, -1, 1); + DGL_Translatef(0, -1, 0); } } else @@ -249,25 +249,25 @@ svtx = &vertex(r_, c_); \ if (layerTex) \ { \ - LIBGUI_GL.glTexCoord2f((c_) / float(columns), (r_) / float(rows)); \ + DGL_TexCoord2f(0, (c_) / float(columns), (r_) / float(rows)); \ } \ if (drawFadeOut) \ { \ - if ((r_) == 0) LIBGUI_GL.glColor4f(1, 1, 1, 0); \ - else LIBGUI_GL.glColor3f(1, 1, 1); \ + if ((r_) == 0) DGL_Color4f(1, 1, 1, 0); \ + else DGL_Color3f(1, 1, 1); \ } \ else \ { \ - if ((r_) == 0) LIBGUI_GL.glColor3f(0, 0, 0); \ - else LIBGUI_GL.glColor3f(1, 1, 1); \ + if ((r_) == 0) DGL_Color3f(0, 0, 0); \ + else DGL_Color3f(1, 1, 1); \ } \ - LIBGUI_GL.glVertex3f(svtx->x, svtx->y, svtx->z); \ + DGL_Vertex3f(svtx->x, svtx->y, svtx->z); \ } Vector3f const *svtx; for (dint r = 0; r < rows; ++r) { - LIBGUI_GL.glBegin(GL_TRIANGLE_STRIP); + DGL_Begin(DGL_TRIANGLE_STRIP); WRITESKYVERTEX(r, 0); WRITESKYVERTEX(r + 1, 0); for (dint c = 1; c <= columns; ++c) @@ -275,14 +275,14 @@ WRITESKYVERTEX(r, c); WRITESKYVERTEX(r + 1, c); } - LIBGUI_GL.glEnd(); + DGL_End(); } if (layerTex) { - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPopMatrix(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); + DGL_Disable(DGL_TEXTURE_2D); } #undef WRITESKYVERTEX @@ -290,8 +290,8 @@ if (yflip) { - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } } @@ -419,30 +419,26 @@ // Disable culling, all triangles face the viewer. //glDisable(GL_CULL_FACE); - GLState::push() - .setCull(gl::None) - .setDepthTest(false) - .setDepthWrite(false) - .apply(); + DGL_PushState(); + DGL_CullFace(DGL_NONE); + DGL_Disable(DGL_DEPTH_TEST); + DGL_Disable(DGL_DEPTH_WRITE); // Setup a proper matrix. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glTranslatef(vOrigin.x, vOrigin.y, vOrigin.z); - LIBGUI_GL.glScalef(sphereDistance, sphereDistance, sphereDistance); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Translatef(vOrigin.x, vOrigin.y, vOrigin.z); + DGL_Scalef(sphereDistance, sphereDistance, sphereDistance); // Always draw both hemispheres. hemisphere.draw(Hemisphere::LowerHemisphere, *sky, firstActiveLayer, layers); hemisphere.draw(Hemisphere::UpperHemisphere, *sky, firstActiveLayer, layers); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); // Restore assumed default GL state. - //glEnable(GL_CULL_FACE); - //glDepthMask(GL_TRUE); - //glEnable(GL_DEPTH_TEST); - GLState::pop().apply(); + DGL_PopState(); } void drawModels(Animator const *animator) const @@ -452,17 +448,15 @@ // Sky models use depth testing, but they won't interfere with world geometry. //glEnable(GL_DEPTH_TEST); //glDepthMask(GL_TRUE); - GLState::current() - .setDepthTest(true) - .setDepthWrite(true) - .apply(); + DGL_Enable(DGL_DEPTH_TEST); + DGL_Enable(DGL_DEPTH_WRITE); LIBGUI_GL.glClear(GL_DEPTH_BUFFER_BIT); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // Setup basic translation. - LIBGUI_GL.glTranslatef(vOrigin.x, vOrigin.y, vOrigin.z); + DGL_Translatef(vOrigin.x, vOrigin.y, vOrigin.z); for(int i = 0; i < MAX_MODELS; ++i) { @@ -484,7 +478,7 @@ Animator::ModelState const &mstate = animator->model(i); // Prepare a vissprite for ordered drawing. - vissprite_t vis; de::zap(vis); + vissprite_t vis; vis.pose.origin = vOrigin.xzy() * -Vector3f(skyModelDef.get("originOffset")).xzy(); vis.pose.topZ = vis.pose.origin.z; @@ -507,8 +501,8 @@ Rend_DrawModel(vis); } - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); // We don't want that anything in the world geometry interferes with what was // drawn in the sky. @@ -670,7 +664,7 @@ { DENG2_ASSERT(animator); DENG2_ASSERT(&animator->sky() == this && d->sky == animator->sky().sky()); - DENG2_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); d->prepare(animator); @@ -678,12 +672,12 @@ // Only drawn when at least one layer is active. if(d->firstActiveLayer < 0) return; - if(fogParams.usingFog) LIBGUI_GL.glEnable(GL_FOG); + if(fogParams.usingFog) DGL_Enable(DGL_FOG); d->drawSphere(); d->drawModels(animator); - if(fogParams.usingFog) LIBGUI_GL.glDisable(GL_FOG); + if(fogParams.usingFog) DGL_Disable(DGL_FOG); } MaterialVariantSpec const &SkyDrawable::layerMaterialSpec(bool masked) // static diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/stateanimator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/stateanimator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/stateanimator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/stateanimator.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -25,6 +25,7 @@ #include +#include #include #include #include @@ -32,11 +33,14 @@ #include #include +#include + using namespace de; namespace render { static String const DEF_ALWAYS_TRIGGER("alwaysTrigger"); +static String const DEF_MUST_FINISH ("mustFinish"); static String const DEF_ANGLE ("angle"); static String const DEF_AXIS ("axis"); static String const DEF_DURATION ("duration"); @@ -53,6 +57,8 @@ static String const VAR_ENABLED ("enabled"); static String const VAR_MATERIAL ("material"); +static String const VAR_NOTIFIED_STATES("notifiedStates"); + static String const PASS_GLOBAL (""); static String const DEFAULT_MATERIAL ("default"); @@ -74,16 +80,19 @@ }; LoopMode looping = NotLooping; + bool mustFinish = false; // Sequence will play to end unless higher priority started. int priority = ANIM_DEFAULT_PRIORITY; - Scheduler const *timeline = nullptr; // owned by ModelRenderer::AnimSequence - std::unique_ptr clock; - TimeDelta overrideDuration = -1.0; + Timeline const *timeline = nullptr; // owned by ModelRenderer::AnimSequence + std::unique_ptr clock; + TimeSpan overrideDuration = -1.0; + TimeSpan actualRuntime = 0.0; Sequence() {} - Sequence(int animationId, String const &rootNode, LoopMode looping, int priority, - Scheduler const *timeline = nullptr) + Sequence(int animationId, String const &rootNode, LoopMode looping, bool mustFinish, + int priority, Timeline const *timeline = nullptr) : looping(looping) + , mustFinish(mustFinish) , priority(priority) , timeline(timeline) { @@ -96,7 +105,7 @@ apply(other); } - Sequence &operator = (Sequence const &other) + Sequence &operator=(Sequence const &other) { apply(other); return *this; @@ -109,11 +118,12 @@ void apply(Sequence const &other) { - animId = other.animId; - node = other.node; - looping = other.looping; - priority = other.priority; - timeline = other.timeline; + animId = other.animId; + node = other.node; + looping = other.looping; + mustFinish = other.mustFinish; + priority = other.priority; + timeline = other.timeline; if (other.overrideDuration >= 0) { @@ -133,15 +143,24 @@ return !atEnd(); } - void operator >> (Writer &to) const override + int loopCount() const + { + if (duration > 0) + { + return int(actualRuntime / duration); + } + return 0; + } + + void operator>>(Writer &to) const override { - ModelDrawable::Animator::OngoingSequence::operator >> (to); + ModelDrawable::Animator::OngoingSequence::operator>>(to); to << duint8(looping) << priority; } - void operator << (Reader &from) override + void operator<<(Reader &from) override { - ModelDrawable::Animator::OngoingSequence::operator << (from); + ModelDrawable::Animator::OngoingSequence::operator<<(from); from.readAs(looping); from >> priority; } @@ -172,32 +191,52 @@ typedef QHash AnimVars; AnimVars animVars; - Impl(Public *i, DotPath const &id) : Base(i) + /// Optional script callback for chosen states. + struct StateCallback : public ConditionalTrigger { - names.add(Record::VAR_NATIVE_SELF).set(new NativePointerValue(thisPublic)).setReadOnly(); - names.addSuperRecord(ScriptSystem::builtInClass(QStringLiteral("Render"), - QStringLiteral("StateAnimator"))); - names.addText(VAR_ID, id).setReadOnly(); - names.add(VAR_ASSET).set(new RecordValue(App::asset(id).accessedRecord())).setReadOnly(); + Record &names; - initVariables(); - - // Set up the model drawing parameters. - if (!self().model().passes.isEmpty()) + StateCallback(Record &names) : names(names) { - appearance.drawPasses = &self().model().passes; + setCondition(names[VAR_NOTIFIED_STATES]); } - appearance.programCallback = [this] (GLProgram &program, ModelDrawable::ProgramBinding binding) + + void handleTriggered(String const &trigger) override { - bindUniforms(program, - binding == ModelDrawable::AboutToBind? Bind : Unbind); - }; - appearance.passCallback = [this] (ModelDrawable::Pass const &pass, ModelDrawable::PassState state) + Record ns; + ns.add(QStringLiteral("self")).set(new RecordValue(names)); + Process::scriptCall(Process::IgnoreResult, ns, + QStringLiteral("self.__asset__.onStateChange"), + "$self", // StateAnimator instance + trigger); // new state + } + }; + std::unique_ptr stateCallback; + std::unique_ptr scheduler; // only created if needed for additional timelines + + Impl(Public *i, DotPath const &assetId) : Base(i) + { + if (!assetId.isEmpty()) { - bindPassUniforms(*self().model().currentProgram(), - pass.name, - state == ModelDrawable::PassBegun? Bind : Unbind); - }; + initVariables(assetId); + + // Set up the model drawing parameters. + if (!self().model().passes.isEmpty()) + { + appearance.drawPasses = &self().model().passes; + } + appearance.programCallback = [this] (GLProgram &program, ModelDrawable::ProgramBinding binding) + { + bindUniforms(program, + binding == ModelDrawable::AboutToBind? Bind : Unbind); + }; + appearance.passCallback = [this] (ModelDrawable::Pass const &pass, ModelDrawable::PassState state) + { + bindPassUniforms(*self().model().currentProgram(), + pass.name, + state == ModelDrawable::PassBegun? Bind : Unbind); + }; + } } ~Impl() @@ -205,8 +244,30 @@ deinitVariables(); } - void initVariables() + void initVariables(DotPath const &assetId) { + // Initialize the StateAnimator script object. + names.add(Record::VAR_NATIVE_SELF).set(new NativePointerValue(thisPublic)).setReadOnly(); + names.addSuperRecord(ScriptSystem::builtInClass(QStringLiteral("Render"), + QStringLiteral("StateAnimator"))); + names.addText(VAR_ID, assetId).setReadOnly(); + Record const &assetDef = App::asset(assetId).accessedRecord(); + names.add(VAR_ASSET).set(new RecordValue(assetDef)).setReadOnly(); + if (assetDef.has(VAR_NOTIFIED_STATES)) + { + // Use the initial value for state callbacks. + names.add(VAR_NOTIFIED_STATES).set(assetDef.get(VAR_NOTIFIED_STATES)); + } + else + { + // The states to notify can be chosen later. + names.addArray(VAR_NOTIFIED_STATES); + } + if (assetDef.has(QStringLiteral("onStateChange"))) + { + stateCallback.reset(new StateCallback(names)); + } + int const passCount = self().model().passes.size(); // Clear lookups affected by the variables. @@ -519,11 +580,13 @@ Sequence &start(Sequence const &spec) { + //qDebug() << "[StateAnimator] start id" << spec.animId; + Sequence &anim = self().start(spec.animId, spec.node).as(); anim.apply(spec); if (anim.timeline) { - anim.clock.reset(new Scheduler::Clock(*anim.timeline, &names)); + anim.clock.reset(new Timeline::Clock(*anim.timeline, &names)); } applyFlagOperation(anim.flags, Sequence::ClampToDuration, anim.looping == Sequence::Looping? UnsetFlags : SetFlags); @@ -531,6 +594,11 @@ } }; +StateAnimator::StateAnimator() + : ModelDrawable::Animator(Impl::Sequence::make) + , d(new Impl(this, {})) +{} + StateAnimator::StateAnimator(DotPath const &id, Model const &model) : ModelDrawable::Animator(model, Impl::Sequence::make) , d(new Impl(this, id)) @@ -541,18 +609,27 @@ return static_cast(ModelDrawable::Animator::model()); } +Scheduler &StateAnimator::scheduler() +{ + if (!d->scheduler) + { + d->scheduler.reset(new Scheduler); + } + return *d->scheduler; +} + void StateAnimator::setOwnerNamespace(Record &names, String const &varName) { d->ownerNamespaceVarName = varName; d->names.add(d->ownerNamespaceVarName).set(new RecordValue(names)); // Call the onInit() function if there is one. - if (d->names.has(VAR_ASSET + QStringLiteral(".onInit"))) + if (d->names.has(QStringLiteral("__asset__.onInit"))) { Record ns; ns.add(QStringLiteral("self")).set(new RecordValue(d->names)); Process::scriptCall(Process::IgnoreResult, ns, - "self." + VAR_ASSET + ".onInit", + "self.__asset__.onInit", "$self"); } } @@ -566,6 +643,11 @@ { using Sequence = Impl::Sequence; + if (d->stateCallback) + { + d->stateCallback->tryTrigger(stateName); + } + // No animations can be triggered if none are available. auto const *stateAnims = &model().animations; if (!stateAnims) return; @@ -584,14 +666,23 @@ { // Test for the probability of this animation. float chance = seq.def->getf(DEF_PROBABILITY, 1.f); - if (frand() > chance) continue; + if (randf() > chance) continue; // Start the animation on the specified node (defaults to root), // unless it is already running. String const node = seq.def->gets(DEF_NODE, ""); int animId = d->animationId(seq.name); - bool const alwaysTrigger = ScriptedInfo::isTrue(*seq.def, DEF_ALWAYS_TRIGGER, false); + if (animId < 0) + { + LOG_GL_ERROR("%s: animation sequence \"%s\" not found") + << ScriptedInfo::sourceLocation(*seq.def) << seq.name; + break; + } + + const bool alwaysTrigger = ScriptedInfo::isTrue(*seq.def, DEF_ALWAYS_TRIGGER, false); + const bool mustFinish = ScriptedInfo::isTrue(*seq.def, DEF_MUST_FINISH, false); + if (!alwaysTrigger) { // Do not restart running sequences. @@ -603,7 +694,7 @@ int const priority = seq.def->geti(DEF_PRIORITY, ANIM_DEFAULT_PRIORITY); // Look up the timeline. - Scheduler *timeline = seq.timeline; + Timeline *timeline = seq.timeline; if (!seq.sharedTimeline.isEmpty()) { auto tl = model().timelines.constFind(seq.sharedTimeline); @@ -617,6 +708,7 @@ Sequence anim(animId, node, ScriptedInfo::isTrue(*seq.def, DEF_LOOPING)? Sequence::Looping : Sequence::NotLooping, + mustFinish, priority, timeline); @@ -629,7 +721,9 @@ // Do not override higher-priority animations. if (auto *existing = maybeAs(find(node))) { - if (priority < existing->priority) + if (priority < existing->priority || + (priority == existing->priority && existing->mustFinish && + !existing->atEnd() && existing->loopCount() == 0)) { // This will be started once the higher-priority animation // has finished. @@ -645,13 +739,10 @@ } catch (ModelDrawable::Animator::InvalidError const &er) { - LOGDEV_GL_WARNING("Failed to start animation \"%s\": %s") + LOG_GL_WARNING("Failed to start animation \"%s\": %s") << seq.name << er.asText(); continue; } - - //qDebug() << "Mobj starting animation: id" - // << d->names.geti(d->ownerNamespaceVarName + ".__id__") << seq.name; break; } } @@ -663,7 +754,7 @@ * variable holds a direct pointer to the asset definition, where the * function is defined. */ - if (d->names.has(VAR_ASSET + QStringLiteral(".onDamage"))) + if (d->names.has(QStringLiteral("__asset__.onDamage"))) { /* * We need to provide the StateAnimator instance to the script as an @@ -673,22 +764,37 @@ Record ns; ns.add(QStringLiteral("self")).set(new RecordValue(d->names)); Process::scriptCall(Process::IgnoreResult, ns, - "self." + VAR_ASSET + ".onDamage", + QStringLiteral("self.__asset__.onDamage"), "$self", points, inflictor? &THINKER_DATA(inflictor->thinker, ThinkerData) : nullptr); } } -void StateAnimator::startSequence(int animationId, int priority, bool looping, - String const &node) +void StateAnimator::startAnimation(int animationId, int priority, bool looping, String const &node) { - using Seq = Impl::Sequence; - d->start(Seq(animationId, node, looping? Seq::Looping : Seq::NotLooping, - priority)); + LOG_AS("StateAnimator::startAnimation"); + try + { + using Seq = Impl::Sequence; + d->start(Seq(animationId, + node, + looping ? Seq::Looping : Seq::NotLooping, + false, // same priority override allowed + priority)); + } + catch (const Error &er) + { + LOG_GL_ERROR("%s: %s") << d->names.gets(VAR_ID) << er.asText(); + } +} + +int StateAnimator::animationId(String const &name) const +{ + return d->animationId(name); } -void StateAnimator::advanceTime(TimeDelta const &elapsed) +void StateAnimator::advanceTime(TimeSpan const &elapsed) { ModelDrawable::Animator::advanceTime(elapsed); @@ -715,8 +821,9 @@ // TODO: Determine actual time factor. // Advance the sequence. - TimeDelta animElapsed = factor * elapsed; + TimeSpan animElapsed = factor * elapsed; anim.time += animElapsed; + anim.actualRuntime += animElapsed; if (anim.looping == Sequence::NotLooping) { @@ -769,6 +876,11 @@ } } + if (d->scheduler) + { + d->scheduler->advanceTime(elapsed); + } + if (retrigger && !d->currentStateName.isEmpty()) { triggerByState(d->currentStateName); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/viewports.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/viewports.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/viewports.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/viewports.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -675,7 +675,6 @@ player->extraLight = player->targetExtraLight; } - // Why? validCount++; extraLight = player->extraLight; @@ -696,7 +695,7 @@ void R_UseViewPort(viewport_t const *vp) { - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); if (!vp) @@ -757,7 +756,7 @@ void R_RenderBlankView() { - UI_DrawDDBackground(Point2Raw(0, 0), Size2Raw(320, 200), 1); + UI_DrawDDBackground(Point2Raw{0, 0}, Size2Raw{{{320, 200}}}, 1); } static void setupPlayerSprites() @@ -882,18 +881,22 @@ } } -static Matrix4f frameViewMatrix; +static Matrix4f frameViewerMatrix; static void setupViewMatrix() { - // This will be the view matrix for the current frame. - frameViewMatrix = GL_GetProjectionMatrix() * - Rend_GetModelViewMatrix(DoomsdayApp::players().indexOf(viewPlayer)); + auto &rend = ClientApp::renderSystem(); + + // These will be the matrices for the current frame. + rend.uProjectionMatrix() = Rend_GetProjectionMatrix(); + rend.uViewMatrix() = Rend_GetModelViewMatrix(DoomsdayApp::players().indexOf(viewPlayer)); + + frameViewerMatrix = rend.uProjectionMatrix().toMatrix4f() * rend.uViewMatrix().toMatrix4f(); } Matrix4f const &Viewer_Matrix() { - return frameViewMatrix; + return frameViewerMatrix; } enum ViewState { Default2D, PlayerView3D, PlayerSprite2D }; @@ -902,18 +905,15 @@ { //DENG2_ASSERT(port && viewData); - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); switch (viewState) { case PlayerView3D: - GLState::current() - .setCull(gl::Back) - .setDepthTest(true) - .apply(); - // The 3D projection matrix. - GL_ProjectionMatrix(); + DGL_CullFace(DGL_BACK); + DGL_Enable(DGL_DEPTH_TEST); + GL_ProjectionMatrix(); // The 3D projection matrix. break; case PlayerSprite2D: @@ -930,12 +930,12 @@ conRect.width(), conRect.height(), scalemode_t(weaponScaleMode)); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_LoadIdentity(); if(sm == SCALEMODE_STRETCH) { - LIBGUI_GL.glOrtho(0, SCREENWIDTH, height, 0, -1, 1); + DGL_Ortho(0, 0, SCREENWIDTH, height, -1, 1); } else { @@ -943,17 +943,17 @@ // translate and scale the projection to produce an aspect // corrected coordinate space at 4:3, aligned vertically to // the bottom and centered horizontally in the window. - LIBGUI_GL.glOrtho(0, conRect.width(), conRect.height(), 0, -1, 1); - LIBGUI_GL.glTranslatef(conRect.width()/2, conRect.height(), 0); + DGL_Ortho(0, 0, conRect.width(), conRect.height(), -1, 1); + DGL_Translatef(conRect.width()/2, conRect.height(), 0); if(conRect.width() >= conRect.height()) { - LIBGUI_GL.glScalef(dfloat( conRect.height() ) / SCREENHEIGHT, + DGL_Scalef(dfloat( conRect.height() ) / SCREENHEIGHT, dfloat( conRect.height() ) / SCREENHEIGHT, 1); } else { - LIBGUI_GL.glScalef(dfloat( conRect.width() ) / SCREENWIDTH, + DGL_Scalef(dfloat( conRect.width() ) / SCREENWIDTH, dfloat( conRect.width() ) / SCREENWIDTH, 1); } @@ -963,28 +963,26 @@ if(conRect.height() > conRect.width()) { dfloat extraScale = (dfloat(conRect.height() * 2) / conRect.width()) / 2; - LIBGUI_GL.glScalef(extraScale, extraScale, 1); + DGL_Scalef(extraScale, extraScale, 1); } - LIBGUI_GL.glTranslatef(-(SCREENWIDTH / 2), -SCREENHEIGHT, 0); - LIBGUI_GL.glScalef(1, dfloat( SCREENHEIGHT ) / height, 1); + DGL_Translatef(-(SCREENWIDTH / 2), -SCREENHEIGHT, 0); + DGL_Scalef(1, dfloat( SCREENHEIGHT ) / height, 1); } - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_LoadIdentity(); // Depth testing must be disabled so that psprite 1 will be drawn // on top of psprite 0 (Doom plasma rifle fire). - GLState::current().setDepthTest(false).apply(); + DGL_Disable(DGL_DEPTH_TEST); break; } case Default2D: - GLState::current() - .setCull(gl::None) - .setDepthTest(false) - .apply(); + DGL_CullFace(DGL_NONE); + DGL_Disable(DGL_DEPTH_TEST); break; } @@ -1056,15 +1054,17 @@ } // Go to wireframe mode? +#if defined (DENG_OPENGL) if (renderWireframe) { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } +#endif - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); // GL is in 3D transformation state only during the frame. //switchTo3DState(true); //, currentViewport, vd); @@ -1077,17 +1077,21 @@ changeViewState(PlayerSprite2D); // Don't render in wireframe mode with 2D psprites. +#if defined (DENG_OPENGL) if (renderWireframe) { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } +#endif Rend_Draw2DPlayerSprites(); // If the 2D versions are needed. +#if defined (DENG_OPENGL) if (renderWireframe) { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); } +#endif // Do we need to render any 3D psprites? if (psp3d) @@ -1101,16 +1105,20 @@ //restore2DState(2); //, currentViewport, vd); changeViewState(Default2D); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); + DGL_Flush(); + +#if defined (DENG_OPENGL) // Back from wireframe mode? if (renderWireframe) { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } +#endif // Now we can show the viewPlayer's mobj again. if (!(player->publicData().flags & DDPF_CHASECAM)) @@ -1138,54 +1146,6 @@ DGL_Enable(DGL_POINT_SMOOTH); } -#if 0 -static void clearViewPorts() -{ - GLbitfield bits = GL_DEPTH_BUFFER_BIT; - - if(fx::Bloom::isEnabled() || - (App_InFineSystem().finaleInProgess() && !GameUIWidget::finaleStretch()) || - ClientApp::vr().mode() == VRConfig::OculusRift) - { - // Parts of the previous frame might leak in the bloom unless we clear the color - // buffer. Not doing this would result in very bright HOMs in map holes and game - // UI elements glowing in the frame (UI elements are normally on a separate layer - // and should not affect bloom). - bits |= GL_COLOR_BUFFER_BIT; - } - - if(!devRendSkyMode) - bits |= GL_STENCIL_BUFFER_BIT; - - if(freezeRLs) - { - bits |= GL_COLOR_BUFFER_BIT; - } - else - { - for(dint i = 0; i < DDMAXPLAYERS; ++i) - { - player_t *plr = DD_Player(i); - - if(!plr->publicData().inGame || !(plr->publicData().flags & DDPF_LOCAL)) - continue; - - if(P_IsInVoid(plr) || !ClientApp::world().hasMap()) - { - bits |= GL_COLOR_BUFFER_BIT; - break; - } - } - } - - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); - - // This is all the clearing we'll do. - LIBGUI_GL.glClear(bits); -} -#endif - void R_RenderViewPort(int playerNum) { int localNum = P_ConsoleToLocal(playerNum); @@ -1207,157 +1167,44 @@ return; } - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); Rectanglei viewRect = R_Console3DViewRect(playerNum); // Use an orthographic projection in real pixel dimensions. - LIBGUI_GL.glOrtho(0, viewRect.width(), viewRect.height(), 0, -1, 1); + DGL_Ortho(0, 0, viewRect.width(), viewRect.height(), -1, 1); viewdata_t const *vd = &DD_Player(vp->console)->viewport(); - RectRaw vpGeometry(vp->geometry.topLeft.x, vp->geometry.topLeft.y, - vp->geometry.width(), vp->geometry.height()); - - RectRaw vdWindow(vd->window.topLeft.x, vd->window.topLeft.y, - vd->window.width(), vd->window.height()); + RectRaw vpGeometry = {{vp->geometry.topLeft.x, vp->geometry.topLeft.y}, + {int(vp->geometry.width()), int(vp->geometry.height())}}; - //switch(layer) - //{ - //case Player3DViewLayer: + RectRaw vdWindow = {{vd->window.topLeft.x, vd->window.topLeft.y}, + {int(vd->window.width()), int(vd->window.height())}}; R_UpdateViewer(vp->console); - //LensFx_BeginFrame(vp->console); - gx.DrawViewPort(localNum, &vpGeometry, &vdWindow, displayPlayer, /* layer: */ 0); - //LensFx_EndFrame(); - //break; - - LensFx_Draw(vp->console); - // Apply camera lens effects on the rendered view. - - -#if 0 - case ViewBorderLayer: - R_RenderPlayerViewBorder(); - break; - - case HUDLayer: - gx.DrawViewPort(p, &vpGeometry, &vdWindow, displayPlayer, /* layer: */ 1); - break; - } -#endif + LensFx_Draw(vp->console); restoreDefaultGLState(); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); -//} + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); -//if(layer == Player3DViewLayer) -//{ // Increment the internal frame count. This does not // affect the window's FPS counter. frameCount++; // Keep reseting until a new sharp world has arrived. if(resetNextViewer > 1) resetNextViewer = 0; -//} - - // Restore things back to normal. - displayPlayer = oldDisplay; - - //R_UseViewPort(nullptr); - //currentViewport = nullptr; -} - -#if 0 -void R_RenderViewPorts(ViewPortLayer layer) -{ - dint oldDisplay = displayPlayer; - - // First clear the viewport. - if(layer == Player3DViewLayer) - { - clearViewPorts(); - } - - // Draw a view for all players with a visible viewport. - for(dint p = 0, y = 0; y < gridRows; ++y) - for(dint x = 0; x < gridCols; x++, ++p) - { - viewport_t const *vp = &viewportOfLocalPlayer[p]; - - displayPlayer = vp->console; - R_UseViewPort(vp); - - if(displayPlayer < 0 || (DD_Player(displayPlayer)->publicData().flags & DDPF_UNDEFINED_ORIGIN)) - { - if(layer == Player3DViewLayer) - { - R_RenderBlankView(); - } - continue; - } - - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - - // Use an orthographic projection in real pixel dimensions. - LIBGUI_GL.glOrtho(0, vp->geometry.width(), vp->geometry.height(), 0, -1, 1); - - viewdata_t const *vd = &DD_Player(vp->console)->viewport(); - RectRaw vpGeometry(vp->geometry.topLeft.x, vp->geometry.topLeft.y, - vp->geometry.width(), vp->geometry.height()); - - RectRaw vdWindow(vd->window.topLeft.x, vd->window.topLeft.y, - vd->window.width(), vd->window.height()); - - switch(layer) - { - case Player3DViewLayer: - R_UpdateViewer(vp->console); - //LensFx_BeginFrame(vp->console); - gx.DrawViewPort(p, &vpGeometry, &vdWindow, displayPlayer, 0/*layer #0*/); - //LensFx_EndFrame(); - break; - - case ViewBorderLayer: - R_RenderPlayerViewBorder(); - break; - - case HUDLayer: - gx.DrawViewPort(p, &vpGeometry, &vdWindow, displayPlayer, 1/*layer #1*/); - break; - } - - restoreDefaultGLState(); - - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); - } - - if(layer == Player3DViewLayer) - { - // Increment the internal frame count. This does not - // affect the window's FPS counter. - frameCount++; - - // Keep reseting until a new sharp world has arrived. - if(resetNextViewer > 1) - resetNextViewer = 0; - } // Restore things back to normal. displayPlayer = oldDisplay; - R_UseViewPort(nullptr); } -#endif void R_ClearViewData() { @@ -1539,9 +1386,9 @@ /// @todo Determine the exact centerpoint of the light in addLuminous! Vector3d const origin(lum->x(), lum->y(), lum->z() + lum->zOffset()); - if(!(devNoCulling || P_IsInVoid(DD_Player(displayPlayer)))) + if (!P_IsInVoid(DD_Player(displayPlayer)) && !devNoCulling) { - if(!ClientApp::renderSystem().angleClipper().isPointVisible(origin)) + if (!ClientApp::renderSystem().angleClipper().isPointVisible(origin)) { markLumobjClipped(*lum); // Won't have a halo. } @@ -1551,7 +1398,7 @@ markLumobjClipped(*lum); Vector3d const eye = Rend_EyeOrigin().xzy(); - if(LineSightTest(eye, origin, -1, 1, LS_PASSLEFT | LS_PASSOVER | LS_PASSUNDER) + if (LineSightTest(eye, origin, -1, 1, LS_PASSLEFT | LS_PASSOVER | LS_PASSUNDER) .trace(lum->map().bspTree())) { markLumobjClipped(*lum, false); // Will have a halo. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/vissprite.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/vissprite.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/render/vissprite.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/render/vissprite.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -60,7 +60,7 @@ spr = visSpriteP - 1; } - de::zapPtr(spr); + *spr = {}; spr->type = type; return spr; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/abstractfont.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/abstractfont.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/abstractfont.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/abstractfont.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -32,10 +32,10 @@ DENG2_FOR_AUDIENCE(Deletion, i) i->fontBeingDeleted(*this); } -void AbstractFont::glInit() +void AbstractFont::glInit() const {} -void AbstractFont::glDeinit() +void AbstractFont::glDeinit() const {} FontManifest &AbstractFont::manifest() const @@ -48,17 +48,17 @@ return _flags; } -int AbstractFont::ascent() +int AbstractFont::ascent() const { return 0; } -int AbstractFont::descent() +int AbstractFont::descent() const { return 0; } -int AbstractFont::lineSpacing() +int AbstractFont::lineSpacing() const { return 0; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/base/api_material.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/base/api_material.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/base/api_material.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/base/api_material.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -81,7 +81,7 @@ { try { - return world::Materials::get().materialManifest(de::Uri(uriCString, RC_NULL)).id(); + return world::Materials::get().materialManifest(de::makeUri(uriCString)).id(); } catch (Resources::MissingResourceManifestError const &) {} // Ignore this error. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/base/api_resource.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/base/api_resource.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/base/api_resource.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/base/api_resource.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -352,7 +352,7 @@ info->flags.isCustom = tex.isFlagged(res::Texture::Custom); averagealpha_analysis_t *aa = reinterpret_cast(tex.analysisDataPointer(res::Texture::AverageAlphaAnalysis)); - info->flags.isEmpty = aa && FEQUAL(aa->alpha, 0); + info->flags.isEmpty = aa && IS_ZERO(aa->alpha); info->geometry.size.width = tex.width(); info->geometry.size.height = tex.height(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/bitmapfont.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/bitmapfont.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/bitmapfont.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/bitmapfont.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -256,42 +256,42 @@ return font; } -int BitmapFont::ascent() +int BitmapFont::ascent() const { glInit(); return d->ascent; } -int BitmapFont::descent() +int BitmapFont::descent() const { glInit(); return d->descent; } -int BitmapFont::lineSpacing() +int BitmapFont::lineSpacing() const { glInit(); return d->leading; } -Rectanglei const &BitmapFont::glyphPosCoords(uchar ch) +Rectanglei const &BitmapFont::glyphPosCoords(uchar ch) const { glInit(); return d->glyph(ch).posCoords; } -Rectanglei const &BitmapFont::glyphTexCoords(uchar ch) +Rectanglei const &BitmapFont::glyphTexCoords(uchar ch) const { glInit(); return d->glyph(ch).texCoords; } -void BitmapFont::glInit() +void BitmapFont::glInit() const { LOG_AS("BitmapFont"); if(!d->needGLInit) return; - if(novideo || isDedicated || BusyMode_Active()) return; + if(novideo || BusyMode_Active()) return; glDeinit(); @@ -314,7 +314,12 @@ default: DENG2_ASSERT(!"BitmapFont: Format not implemented"); } - if(!pixels) return; + if(!pixels) + { + App_FileSystem().releaseFile(hndl->file()); + delete hndl; + return; + } // Upload the texture. if(!novideo && !isDedicated) @@ -337,7 +342,7 @@ d->needGLInit = false; } -void BitmapFont::glDeinit() +void BitmapFont::glDeinit() const { LOG_AS("BitmapFont"); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/clientmaterial.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/clientmaterial.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/clientmaterial.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/clientmaterial.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -153,6 +153,22 @@ ClientMaterial::~ClientMaterial() {} +bool ClientMaterial::isAnimated() const +{ + if (Material::isAnimated()) + { + return true; + } + for (const auto &decor : d->decorations) + { + if (decor->isAnimated()) + { + return true; + } + } + return false; +} + AudioEnvironmentId ClientMaterial::audioEnvironment() const { return (isDrawable()? d->audioEnvironment : AE_NONE); @@ -168,7 +184,7 @@ return d->decorations.count(); } -LoopResult ClientMaterial::forAllDecorations(std::function func) const +LoopResult ClientMaterial::forAllDecorations(const std::function &func) const { for (Decoration *decor : d.getConst()->decorations) { @@ -214,7 +230,7 @@ return *d->findAnimator(spec, true/*create*/); } -LoopResult ClientMaterial::forAllAnimators(std::function func) const +LoopResult ClientMaterial::forAllAnimators(const std::function &func) const { for (MaterialAnimator *animator : d.getConst()->animators) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/clientresources.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/clientresources.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/clientresources.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/clientresources.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -1749,7 +1749,7 @@ if (select) { // Choose the correct selector, or selector zero if the given one not available. - dint const mosel = (select & DDMOBJ_SELECTOR_MASK); + dint const mosel = (select & DDMOBJ_SELECTOR_MASK); for (FrameModelDef *it = def; it; it = it->selectNext) { if (it->select == mosel) @@ -1831,8 +1831,9 @@ // Same state and a bigger order are the requirements. if (other->def.order() > me->def.order() && // Defined after me. - other->interMark > me->interMark && - other->interMark < minmark) + other->interMark > me->interMark && + other->interMark < minmark && + other->select == me->select) { minmark = other->interMark; closest = other; @@ -1858,9 +1859,9 @@ // Same state and a bigger order are the requirements. if (other->state == me->state && - other->def.order() > me->def.order() && // Defined after me. - other->select > me->select && other->select < minsel && - other->interMark >= me->interMark) + other->def.order() > me->def.order() && // Defined after me. + other->select > me->select && other->select < minsel && + other->interMark >= me->interMark) { minsel = other->select; closest = other; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/compositebitmapfont.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/compositebitmapfont.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/compositebitmapfont.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/compositebitmapfont.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -73,50 +73,50 @@ : AbstractFont(manifest), d(new Impl(this)) {} -int CompositeBitmapFont::ascent() +int CompositeBitmapFont::ascent() const { glInit(); return d->ascent; } -int CompositeBitmapFont::descent() +int CompositeBitmapFont::descent() const { glInit(); return d->descent; } -int CompositeBitmapFont::lineSpacing() +int CompositeBitmapFont::lineSpacing() const { glInit(); return d->leading; } -Rectanglei const &CompositeBitmapFont::glyphPosCoords(uchar ch) +Rectanglei const &CompositeBitmapFont::glyphPosCoords(uchar ch) const { glInit(); return d->glyph(ch).geometry; } -Rectanglei const &CompositeBitmapFont::glyphTexCoords(uchar /*ch*/) +Rectanglei const &CompositeBitmapFont::glyphTexCoords(uchar /*ch*/) const { static Rectanglei coords(Vector2i(0, 0), Vector2i(1, 1)); glInit(); return coords; } -uint CompositeBitmapFont::glyphTextureBorder(uchar ch) +uint CompositeBitmapFont::glyphTextureBorder(uchar ch) const { glInit(); return d->glyph(ch).border; } -TextureVariant *CompositeBitmapFont::glyphTexture(uchar ch) +TextureVariant *CompositeBitmapFont::glyphTexture(uchar ch) const { glInit(); return d->glyph(ch).tex; } -patchid_t CompositeBitmapFont::glyphPatch(uchar ch) +patchid_t CompositeBitmapFont::glyphPatch(uchar ch) const { glInit(); return d->glyph(ch).patch; @@ -139,10 +139,10 @@ GL_CLAMP_TO_EDGE, 0, -3, 0, false, false, false, false); } -void CompositeBitmapFont::glInit() +void CompositeBitmapFont::glInit() const { if(!d->needGLInit) return; - if(novideo || isDedicated || BusyMode_Active()) return; + if(novideo || BusyMode_Active()) return; LOG_AS("CompositeBitmapFont"); @@ -193,9 +193,9 @@ d->needGLInit = false; } -void CompositeBitmapFont::glDeinit() +void CompositeBitmapFont::glDeinit() const { - if(novideo || isDedicated) return; + if(novideo) return; d->needGLInit = true; if(BusyMode_Active()) return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/hq2x.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/hq2x.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/hq2x.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/hq2x.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -253,9 +253,9 @@ r = i << 3; g = j << 2; b = k << 3; - y = (uint32_t)( 0.299*r + 0.587*g + 0.114*b); - u = (uint32_t)(-0.169*r - 0.331*g + 0.5 *b) + 128; - v = (uint32_t)( 0.5 *r - 0.419*g - 0.081*b) + 128; + y = (uint32_t) de::clamp(0.0, ( 0.299*r + 0.587*g + 0.114*b), 255.0); + u = (uint32_t) de::clamp(0.0, (-0.169*r - 0.331*g + 0.5 *b) + 128, 255.0); + v = (uint32_t) de::clamp(0.0, ( 0.5 *r - 0.419*g - 0.081*b) + 128, 255.0); lutBGR888toYUV888[BGR565_PACK(k, j, i)] = YUV888_PACK(y, u, v); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/idtech1image.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/idtech1image.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/idtech1image.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/idtech1image.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -82,13 +82,14 @@ { try { - if (game.isPlayableWithDefaultPackages()) + if (flags.testFlag(AlwaysTryLoad) || game.isPlayableWithDefaultPackages()) { Block const playPal = catalog.read("PLAYPAL"); Block const title = catalog.read("TITLE"); Block const titlePic = catalog.read("TITLEPIC"); + Block const interPic = catalog.read("INTERPIC"); - IdTech1Image img(title.isEmpty()? titlePic : title, playPal); + IdTech1Image img(title? title : (titlePic? titlePic : interPic), playPal); float const scaleFactor = flags.testFlag(Downscale50Percent)? .5f : 1.f; Image::Size const finalSize(img.width() * scaleFactor, @@ -110,8 +111,9 @@ { if (flags & NullImageIfFails) return Image(); - LOG_RES_WARNING("Failed to load title picture for game \"%s\": %s") + LOG_RES_WARNING("Failed to load title picture for game \"%s\" using {%s}: %s") << game.title() + << String::join(catalog.packages(), " ") << er.asText(); } if (flags & NullImageIfFails) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/image.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/image.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/image.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/image.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -142,7 +142,7 @@ /// @return @c true if the file name in @a path ends with the "color key" suffix. static inline bool isColorKeyed(String path) { - return path.fileNameWithoutExtension().endsWith("-ck", Qt::CaseInsensitive); + return path.fileNameWithoutExtension().endsWith("-ck", String::CaseInsensitive); } void Image_Init(image_t &img) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/lightmaterialdecoration.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/lightmaterialdecoration.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/lightmaterialdecoration.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/lightmaterialdecoration.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -61,9 +61,9 @@ LightMaterialDecoration::AnimationStage * LightMaterialDecoration::AnimationStage::fromDef(Record const &stageDef) { - ClientTexture *lightmapUp = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::Uri(stageDef.gets("lightmapUp" ), RC_NULL))); - ClientTexture *lightmapDown = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::Uri(stageDef.gets("lightmapDown"), RC_NULL))); - ClientTexture *lightmapSide = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::Uri(stageDef.gets("lightmapSide"), RC_NULL))); + ClientTexture *lightmapUp = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::makeUri(stageDef.gets("lightmapUp" )))); + ClientTexture *lightmapDown = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::makeUri(stageDef.gets("lightmapDown")))); + ClientTexture *lightmapSide = static_cast(res::Textures::get().tryFindTextureByResourceUri("Lightmaps", de::makeUri(stageDef.gets("lightmapSide")))); int haloTextureIndex = stageDef.geti("haloTextureIndex"); ClientTexture *haloTexture = nullptr; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/materialanimator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/materialanimator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/materialanimator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/materialanimator.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -276,10 +276,10 @@ /// Current state of a layer animation. struct LayerState { - int stage; ///< Animation stage else @c -1 => layer not in use. - int nextStage; - short tics; ///< Remaining (sharp) tics in the current stage. - float inter; ///< Intermark from the current stage to the next [0..1]. + int stage = 0; ///< Animation stage else @c -1 => layer not in use. + int nextStage = 0; + short tics = 0; ///< Remaining (sharp) tics in the current stage. + float inter = 0.f; ///< Intermark from the current stage to the next [0..1]. QVector stageTextures; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/texturevariant.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/texturevariant.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/resource/texturevariant.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/resource/texturevariant.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -160,7 +160,9 @@ static String nameForGLTextureWrapMode(int mode) { if(mode == GL_REPEAT) return "repeat"; +#if defined (DENG_OPENGL) if(mode == GL_CLAMP) return "clamp"; +#endif if(mode == GL_CLAMP_TO_EDGE) return "clamp_edge"; return "(unknown)"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/sys_system.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/sys_system.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/sys_system.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/sys_system.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -156,7 +156,11 @@ // This is going to be the end, I'm afraid. de::Loop::get().stop(); +#if defined (__CLIENT__) Sys_MessageBox(MBT_WARNING, DOOMSDAY_NICENAME, msg, 0); +#else + qWarning() << msg; +#endif return 0; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/busyvisual.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/busyvisual.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/busyvisual.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/busyvisual.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -154,13 +154,13 @@ if (isDedicated) return; if (!Con_TransitionInProgress()) return; - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, SCREENWIDTH, SCREENHEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, SCREENWIDTH, SCREENHEIGHT, -1, 1); DENG2_ASSERT(ClientWindow::main().busy().transitionFrame() != 0); @@ -168,8 +168,9 @@ GL_BindTextureUnmanaged(texScreenshot, gl::ClampToEdge, gl::ClampToEdge); LIBGUI_GL.glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - GLState::push().setAlphaTest(false).apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_PushState(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Enable(DGL_TEXTURE_2D); switch (transition.style) { @@ -187,31 +188,31 @@ x = 0; s = 0; - LIBGUI_GL.glBegin(GL_QUAD_STRIP); + DGL_Begin(DGL_TRIANGLE_STRIP); for (i = 0; i <= SCREENWIDTH; ++i, x++, s += colWidth) { y = doomWipeSamples[i]; - LIBGUI_GL.glColor4f(1, 1, 1, topAlpha); - LIBGUI_GL.glTexCoord2f(s, 1); LIBGUI_GL.glVertex2i(x, y); - LIBGUI_GL.glColor4f(1, 1, 1, 1); - LIBGUI_GL.glTexCoord2f(s, div); LIBGUI_GL.glVertex2i(x, y + h); + DGL_Color4f(1, 1, 1, 1); + DGL_TexCoord2f(0, s, div); DGL_Vertex2f(x, y + h); + DGL_Color4f(1, 1, 1, topAlpha); + DGL_TexCoord2f(0, s, 1); DGL_Vertex2f(x, y); } - LIBGUI_GL.glEnd(); + DGL_End(); x = 0; s = 0; - LIBGUI_GL.glColor4f(1, 1, 1, 1); - LIBGUI_GL.glBegin(GL_QUAD_STRIP); + DGL_Color4f(1, 1, 1, 1); + DGL_Begin(DGL_TRIANGLE_STRIP); for (i = 0; i <= SCREENWIDTH; ++i, x++, s += colWidth) { y = doomWipeSamples[i] + h; - LIBGUI_GL.glTexCoord2f(s, div); LIBGUI_GL.glVertex2i(x, y); - LIBGUI_GL.glTexCoord2f(s, 0); LIBGUI_GL.glVertex2i(x, y + (SCREENHEIGHT - h)); + DGL_TexCoord2f(0, s, 0); DGL_Vertex2f(x, y + (SCREENHEIGHT - h)); + DGL_TexCoord2f(0, s, div); DGL_Vertex2f(x, y); } - LIBGUI_GL.glEnd(); + DGL_End(); break; } case TS_DOOM: { @@ -221,35 +222,35 @@ sampleDoomWipe(); - LIBGUI_GL.glColor4f(1, 1, 1, 1); - LIBGUI_GL.glBegin(GL_QUADS); + DGL_Color4f(1, 1, 1, 1); + DGL_Begin(DGL_QUADS); for (i = 0; i <= SCREENWIDTH; ++i, x++, s+= colWidth) { y = doomWipeSamples[i]; - LIBGUI_GL.glTexCoord2f(s, 1); LIBGUI_GL.glVertex2i(x, y); - LIBGUI_GL.glTexCoord2f(s+colWidth, 1); LIBGUI_GL.glVertex2i(x+1, y); - LIBGUI_GL.glTexCoord2f(s+colWidth, 0); LIBGUI_GL.glVertex2i(x+1, y+SCREENHEIGHT); - LIBGUI_GL.glTexCoord2f(s, 0); LIBGUI_GL.glVertex2i(x, y+SCREENHEIGHT); + DGL_TexCoord2f(0, s, 1); DGL_Vertex2f(x, y); + DGL_TexCoord2f(0, s+colWidth, 1); DGL_Vertex2f(x+1, y); + DGL_TexCoord2f(0, s+colWidth, 0); DGL_Vertex2f(x+1, y+SCREENHEIGHT); + DGL_TexCoord2f(0, s, 0); DGL_Vertex2f(x, y+SCREENHEIGHT); } - LIBGUI_GL.glEnd(); + DGL_End(); break; } case TS_CROSSFADE: - LIBGUI_GL.glColor4f(1, 1, 1, 1 - transition.position); + DGL_Color4f(1, 1, 1, 1 - transition.position); - LIBGUI_GL.glBegin(GL_QUADS); - LIBGUI_GL.glTexCoord2f(0, 1); LIBGUI_GL.glVertex2f(0, 0); - LIBGUI_GL.glTexCoord2f(0, 0); LIBGUI_GL.glVertex2f(0, SCREENHEIGHT); - LIBGUI_GL.glTexCoord2f(1, 0); LIBGUI_GL.glVertex2f(SCREENWIDTH, SCREENHEIGHT); - LIBGUI_GL.glTexCoord2f(1, 1); LIBGUI_GL.glVertex2f(SCREENWIDTH, 0); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, 1); DGL_Vertex2f(0, 0); + DGL_TexCoord2f(0, 0, 0); DGL_Vertex2f(0, SCREENHEIGHT); + DGL_TexCoord2f(0, 1, 0); DGL_Vertex2f(SCREENWIDTH, SCREENHEIGHT); + DGL_TexCoord2f(0, 1, 1); DGL_Vertex2f(SCREENWIDTH, 0); + DGL_End(); break; } GL_SetNoTexture(); - GLState::pop().apply(); + DGL_PopState(); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientrootwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientrootwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientrootwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientrootwidget.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -24,20 +24,38 @@ using namespace de; +DENG2_PIMPL_NOREF(ClientRootWidget) +{ + PackageIconBank packageIconBank; +}; + ClientRootWidget::ClientRootWidget(GLWindow *window) : GuiRootWidget(window) -{} + , d(new Impl) +{ + d->packageIconBank.setDisplaySize(GuiWidget::pointsToPixels(PackageIconBank::Size(32, 32))); +} ClientWindow &ClientRootWidget::window() { return GuiRootWidget::window().as(); } +PackageIconBank &ClientRootWidget::packageIconBank() +{ + return d->packageIconBank; +} + void ClientRootWidget::update() { if (!DoomsdayApp::app().isShuttingDown()) { GuiRootWidget::update(); + + if (window().isGLReady() && !d->packageIconBank.atlas()) + { + d->packageIconBank.setAtlas(&atlas()); + } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientstyle.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientstyle.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientstyle.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientstyle.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -19,6 +19,8 @@ #include "ui/clientstyle.h" #include "ui/clientwindow.h" +#include + using namespace de; DENG2_PIMPL_NOREF(ClientStyle) @@ -49,3 +51,17 @@ return d->emptyMenuLabelStylist; } +void ClientStyle::performUpdate() +{ + async([]() { + // Wait until all UI assets are finished, and thus we can sure that no background + // operations are accessing style assets. + LOG_MSG("Waiting for UI assets to be ready..."); + ClientWindow::main().root().waitForAssetsReady(); + return 0; + }, + [this](int) { + LOG_MSG("Updating the UI style"); + Style::performUpdate(); + }); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/clientwindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/clientwindow.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -71,8 +72,6 @@ using namespace de; -static ClientWindow *mainWindow = nullptr; // The main window, set after fully constructed. - DENG2_PIMPL(ClientWindow) , DENG2_OBSERVES(App, StartupComplete) , DENG2_OBSERVES(DoomsdayApp, GameChange) @@ -81,8 +80,11 @@ , DENG2_OBSERVES(GLWindow, Init) , DENG2_OBSERVES(GLWindow, Resize) , DENG2_OBSERVES(GLWindow, Swap) -, DENG2_OBSERVES(PersistentGLWindow, AttributeChange) , DENG2_OBSERVES(Variable, Change) +, DENG2_OBSERVES(FileSystem, Busy) +#if !defined (DENG_MOBILE) +, DENG2_OBSERVES(PersistentGLWindow, AttributeChange) +#endif { bool needMainInit = true; bool needRootSizeUpdate = false; @@ -118,6 +120,9 @@ UniqueWidgetPtr fpsCounter; float oldFps = 0; + // File system notification. + UniqueWidgetPtr fsBusy; + /// @todo Switch dynamically between VR and plain. VRWindowTransform contentXf; @@ -149,7 +154,7 @@ } } - ~Impl() + ~Impl() override { releaseRef(cursorX); releaseRef(cursorY); @@ -157,24 +162,27 @@ releaseRef(gameHeight); releaseRef(homeDelta); releaseRef(quitX); - - if (thisPublic == mainWindow) - { - mainWindow = nullptr; - } } StringList configVariableNames() const { +#if !defined (DENG_MOBILE) return StringList() << self().configName("fsaa") << self().configName("vsync"); +#else + return StringList(); +#endif } void setupUI() { Style &style = ClientApp::windowSystem().style(); + // This is a shared widget so it may be accessed during initialization of other widgets; + // create it first. + taskBarBlur = new LabelWidget("taskbar-blur"); + gameWidth ->set(root.viewWidth()); gameHeight->set(root.viewHeight()); @@ -195,7 +203,7 @@ auto *miniGameControls = new LabelWidget; { - miniGameControls->set(GuiWidget::Background(style.colors().colorf("inverted.background"))); + miniGameControls->set(GuiWidget::Background(style.colors().colorf("background"))); miniGameControls->rule() .setInput(Rule::Width, root.viewWidth()/2 - style.rules().rule(RuleBank::UNIT)) .setInput(Rule::Left, game->rule().right() + style.rules().rule(RuleBank::UNIT)) @@ -205,13 +213,14 @@ backToGame->setText("Back to Game"); backToGame->setSizePolicy(ui::Expand, ui::Expand); backToGame->setActionFn([this] () { home->moveOffscreen(1.0); }); + backToGame->setColorTheme(GuiWidget::Inverted); nowPlaying = new LabelWidget; nowPlaying->setSizePolicy(ui::Expand, ui::Expand); - nowPlaying->margins().setLeftRight("").setBottom("dialog.gap"); + nowPlaying->margins()/*.setLeftRight("")*/.setBottom("dialog.gap"); nowPlaying->setMaximumTextWidth(miniGameControls->rule().width()); nowPlaying->setTextLineAlignment(ui::AlignLeft); - nowPlaying->setTextColor("inverted.text"); + nowPlaying->setTextColor("text"); nowPlaying->setFont("heading"); AutoRef combined = nowPlaying->rule().height() + backToGame->rule().height(); @@ -242,10 +251,12 @@ .setInput(Rule::Bottom, root.viewBottom() + *homeDelta); root.add(home); +#if !defined (DENG_MOBILE) // Busy progress should be visible over the Home. busy->progress().orphan(); busy->progress().rule().setRect(game->rule()); root.add(&busy->progress()); +#endif // Common notification area. notifications = new NotificationAreaWidget; @@ -262,7 +273,7 @@ quitButton->setImageColor(style.colors().colorf("accent")); quitButton->setTextAlignment(ui::AlignLeft); quitButton->set(GuiWidget::Background(style.colors().colorf("background"))); - quitButton->setActionFn([this] () { Con_Execute(CMDS_DDAY, "quit!", false, false); }); + quitButton->setActionFn([]() { Con_Execute(CMDS_DDAY, "quit!", false, false); }); quitButton->rule() .setInput(Rule::Top, root.viewTop() + style.rules().rule("gap")) .setInput(Rule::Left, root.viewRight() + *quitX) @@ -280,9 +291,19 @@ fpsCounter->setSizePolicy(ui::Expand, ui::Expand); fpsCounter->setAlignment(ui::AlignRight); + // File system busy indicator. + fsBusy.reset(new ProgressWidget); + fsBusy->setSizePolicy(ui::Expand, ui::Expand); + fsBusy->setMode(ProgressWidget::Indefinite); + fsBusy->useMiniStyle(); + fsBusy->setText("Files"); + fsBusy->setTextAlignment(ui::AlignRight); + // Everything behind the task bar can be blurred with this widget. - taskBarBlur = new LabelWidget("taskbar-blur"); + if (style.isBlurringAllowed()) + { taskBarBlur->set(GuiWidget::Background(Vector4f(1, 1, 1, 1), GuiWidget::Background::Blurred)); + } taskBarBlur->rule().setRect(root.viewRule()); taskBarBlur->setAttribute(GuiWidget::DontDrawContent); root.add(taskBarBlur); @@ -349,10 +370,17 @@ #endif */ +#if !defined (DENG_MOBILE) self().audienceForAttributeChange() += this; +#endif + } + + void fileSystemBusyStatusChanged(FS::BusyStatus bs) override + { + notifications->showOrHide(*fsBusy, bs == FS::Busy); } - void appStartupCompleted() + void appStartupCompleted() override { taskBar->show(); @@ -368,10 +396,11 @@ taskBar->close(); } + FS::get().audienceForBusy() += this; Loop::get().timer(1.0, [this] () { showOrHideQuitButton(); }); } - void currentGameChanged(Game const &newGame) + void currentGameChanged(Game const &newGame) override { minimizeGame(false); showOrHideQuitButton(); @@ -433,8 +462,12 @@ break; case Normal: +#if defined (DENG_HAVE_BUSYRUNNER) // The busy widget will hide itself after a possible transition has finished. busy->disable(); +#else + busy->hide(); +#endif game->show(); game->enable(); @@ -446,7 +479,7 @@ mode = newMode; } - void windowInit(GLWindow &) + void windowInit(GLWindow &) override { Sys_GLConfigureDefaultState(); GL_Init2DState(); @@ -463,7 +496,7 @@ game->enable(); // Configure a viewport immediately. - GLState::current().setViewport(Rectangleui(0, 0, self().pixelWidth(), self().pixelHeight())).apply(); + GLState::current().setViewport(Rectangleui(0, 0, self().pixelWidth(), self().pixelHeight())); LOG_DEBUG("GameWidget enabled"); @@ -471,19 +504,12 @@ { needMainInit = false; +#if !defined (DENG_MOBILE) self().raise(); self().requestActivate(); - +#endif self().eventHandler().audienceForFocusChange() += this; -/*#ifdef WIN32 - if (self().isFullScreen()) - { - // It would seem we must manually give our canvas focus. Bug in Qt? - self().canvas().setFocus(); - } -#endif*/ - DD_FinishInitializationAfterWindowReady(); vrCfg().oculusRift().glPreInit(); @@ -491,7 +517,7 @@ } } - void windowResized(GLWindow &) + void windowResized(GLWindow &) override { LOG_AS("ClientWindow"); @@ -506,7 +532,7 @@ showOrHideQuitButton(); } - void windowSwapped(GLWindow &) + void windowSwapped(GLWindow &) override { if (DoomsdayApp::app().isShuttingDown()) return; @@ -517,14 +543,16 @@ completeFade(); } - void windowAttributesChanged(PersistentGLWindow &) +#if !defined (DENG_MOBILE) + void windowAttributesChanged(PersistentGLWindow &) override { showOrHideQuitButton(); } +#endif void showOrHideQuitButton() { - TimeDelta const SPAN = 0.6; + TimeSpan const SPAN = 0.6; if (self().isFullScreen() && !DoomsdayApp::isGameLoaded()) { quitX->set(-quitButton->rule().width() - Style::get().rules().rule("gap"), SPAN); @@ -535,7 +563,7 @@ } } - void mouseStateChanged(MouseEventSource::State state) + void mouseStateChanged(MouseEventSource::State state) override { Mouse_Trap(state == MouseEventSource::Trapped); } @@ -586,7 +614,7 @@ return false; } - void windowFocusChanged(GLWindow &, bool hasFocus) + void windowFocusChanged(GLWindow &, bool hasFocus) override { LOG_DEBUG("windowFocusChanged focus:%b fullscreen:%b hidden:%b minimized:%b") << hasFocus << self().isFullScreen() << self().isHidden() << self().isMinimized(); @@ -608,6 +636,11 @@ self().eventHandler().trapMouse(); } + if (Config::get().getb("audio.pauseOnFocus", true)) + { + AudioSystem::get().pauseMusic(!hasFocus); + } + // Generate an event about this. ddevent_t ev; de::zap(ev); ev.device = -1; @@ -628,7 +661,7 @@ } } - void variableValueChanged(Variable &variable, Value const &newValue) + void variableValueChanged(Variable &variable, Value const &newValue) override { if (variable.name() == "fsaa") { @@ -711,7 +744,7 @@ void minimizeGame(bool mini) { - TimeDelta const SPAN = 1.0; + TimeSpan const SPAN = 1.0; if (mini && !isGameMini) { @@ -736,6 +769,7 @@ void updateMouseCursor() { +#if !defined (DENG_MOBILE) // The cursor is only needed if the content is warped. cursor->show(!self().eventHandler().isMouseTrapped() && VRConfig::modeAppliesDisplacement(vrCfg().mode())); @@ -760,9 +794,10 @@ } cursorHasBeenHidden = false; } +#endif } - void setupFade(FadeDirection fadeDir, TimeDelta const &span) + void setupFade(FadeDirection fadeDir, TimeSpan const &span) { if (!fader) { @@ -795,23 +830,31 @@ : BaseWindow(id) , d(new Impl(this)) { +#if defined (DENG_MOBILE) + setMain(this); + WindowSystem::get().addWindow("main", this); +#endif + audienceForInit() += d; audienceForResize() += d; audienceForSwap() += d; -#ifdef WIN32 +#if defined (WIN32) // Set an icon for the window. setIcon(QIcon(":/doomsday.ico")); #endif d->setupUI(); - // The first window is the main window. - if (!mainWindow) - { - mainWindow = this; +#if defined (DENG_MOBILE) + // Stay out from under the virtual keyboard. + connect(this, &GLWindow::rootDimensionsChanged, [this] (QRect rect) + { + d->root.rootOffset().setValue(Vector2f(0, int(rect.height()) - int(pixelSize().y)), + 0.3); + }); +#endif } -} ClientRootWidget &ClientWindow::root() { @@ -898,8 +941,8 @@ ClientApp::app().preFrame(); /// @todo what about multiwindow? - DENG_ASSERT_IN_MAIN_THREAD(); - DENG_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT_IN_RENDER_THREAD(); + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); // Cursor position (if cursor is visible). d->updateMouseCursor(); @@ -919,13 +962,23 @@ void ClientWindow::drawWindowContent() { +#if defined (DENG_MOBILE) + { + + } +#endif + + DENG2_ASSERT_IN_RENDER_THREAD(); root().draw(); LIBGUI_ASSERT_GL_OK(); } void ClientWindow::postDraw() { - /// @note This method is called during the Canvas paintGL event. + /// @note This method is called during the GLWindow paintGL event. + DENG2_ASSERT_IN_RENDER_THREAD(); + + BaseWindow::postDraw(); // OVR will handle presentation in Oculus Rift mode. if (ClientApp::vr().mode() != VRConfig::OculusRift) @@ -934,8 +987,6 @@ // swapped. GL_FinishFrame(); } - - BaseWindow::postDraw(); } bool ClientWindow::setDefaultGLFormat() // static @@ -990,14 +1041,14 @@ DENG_ASSERT(img.pixelSize != 0); } -void ClientWindow::fadeInTaskBarBlur(TimeDelta span) +void ClientWindow::fadeInTaskBarBlur(TimeSpan span) { d->taskBarBlur->setAttribute(GuiWidget::DontDrawContent, UnsetFlags); d->taskBarBlur->setOpacity(0); d->taskBarBlur->setOpacity(1, span); } -void ClientWindow::fadeOutTaskBarBlur(TimeDelta span) +void ClientWindow::fadeOutTaskBarBlur(TimeSpan span) { d->taskBarBlur->setOpacity(0, span); QTimer::singleShot(span.asMilliSeconds(), this, SLOT(hideTaskBarBlur())); @@ -1029,7 +1080,7 @@ bool ClientWindow::mainExists() { - return mainWindow != nullptr; + return BaseWindow::mainExists(); } void ClientWindow::toggleFPSCounter() @@ -1079,7 +1130,7 @@ return d->handleFallbackEvent(event); } -void ClientWindow::fadeContent(FadeDirection fadeDirection, TimeDelta const &duration) +void ClientWindow::fadeContent(FadeDirection fadeDirection, TimeSpan const &duration) { d->setupFade(fadeDirection, duration); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/controllerpresets.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/controllerpresets.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/controllerpresets.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/controllerpresets.cpp 2018-12-11 07:08:19.000000000 +0000 @@ -44,7 +44,7 @@ int deviceId = 0; Impl() - : inputModule(App::scriptSystem().nativeModule("Input")) + : inputModule(App::scriptSystem()["Input"]) { inputModule.addDictionary(VAR_CONTROLLER_PRESETS); DoomsdayApp::app().audienceForGameChange() += this; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/aboutdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/aboutdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/aboutdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/aboutdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -75,13 +75,14 @@ title->setSizePolicy(ui::Fixed, ui::Expand); LabelWidget *info = new LabelWidget; - String txt = String(_E(b) "%4 %5 #%6" _E(.) "\n%7%9\n\n%1 (%2-%8)%3") + String txt = String(_E(b) "%4 build %5" _E(.) "\n%6%8\n\n%1 (%2-%7)%3") .arg(version.operatingSystem() == "windows"? tr("Windows") : - version.operatingSystem() == "macx"? tr("macOS") : tr("Unix")) + version.operatingSystem() == "macx"? tr("macOS") : + version.operatingSystem() == "ios"? tr("iOS") : tr("Unix")) .arg(version.cpuBits()) .arg(version.isDebugBuild()? tr(" Debug") : "") .arg(DOOMSDAY_RELEASE_TYPE) - .arg(version.compactNumber()) + //.arg(version.compactNumber()) .arg(version.build) .arg(Time::fromText(__DATE__ " " __TIME__, Time::CompilerDateTime) .asDateTime().toString(Qt::SystemLocaleShortDate)) @@ -101,7 +102,7 @@ layout << *logo << *title << *info; // Total size of the dialog's content. - area().setContentSize(layout.width(), layout.height()); + area().setContentSize(layout); buttons() << new DialogButtonItem(DialogWidget::Accept | DialogWidget::Default, tr("Close")) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/alertdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/alertdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/alertdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/alertdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -105,7 +105,7 @@ notification->setBehavior(Focusable, false); notification->setSizePolicy(ui::Expand, ui::Expand); notification->setImage(style().images().image("alert")); - notification->setOverrideImageSize(style().fonts().font("default").height().value()); + notification->setOverrideImageSize(style().fonts().font("default").height()); notification->setOpener([this] (PopupWidget *) { self().showListOfAlerts(); }); @@ -117,7 +117,7 @@ alerts->enableScrolling(false); alerts->setGridSize(1, ui::Expand, 0, ui::Expand); alerts->rule().setLeftTop(area.contentRule().left(), area.contentRule().top()); - area.setContentSize(alerts->rule().width(), alerts->rule().height()); + area.setContentSize(alerts->rule()); area.add(alerts); area.enableIndicatorDraw(true); @@ -208,7 +208,7 @@ label.setAppearanceAnimation(LabelWidget::AppearGrowVertically, 0.5); label.setAlignment(ui::AlignBottom); label.setImage(style().images().image("alert")); - label.setOverrideImageSize(style().fonts().font("default").height().value()); + label.setOverrideImageSize(style().fonts().font("default").height()); label.setImageAlignment(ui::AlignTop); label.setTextAlignment(ui::AlignRight); label.margins() @@ -291,6 +291,8 @@ AlertDialog::AlertDialog(String const &/*name*/) : d(new Impl(this)) { + setOutlineColor("transparent"); + // The dialog is connected to the notification icon. d->notification->setPopup(*this, ui::Down); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/audiosettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/audiosettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/audiosettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/audiosettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -29,9 +29,15 @@ #include "clientapp.h" #include "ConfigProfiles" -#include +#include #include +#include +#include +#include +#include #include +#include +#include using namespace de; using namespace de::ui; @@ -47,17 +53,25 @@ //CVarChoiceWidget *sampleRate; CVarChoiceWidget *musicSource; CVarNativePathWidget *musicSoundfont; + VariableToggleWidget *pauseOnFocus; CVarToggleWidget *soundInfo; GridPopupWidget *devPopup; - VariableChoiceWidget *fmodSpeakerMode; + FoldPanelWidget *backendFold; + GuiWidget *backendBase; + VariableSliderWidget *sfxChannels; + VariableChoiceWidget *audioOutput; +// VariableChoiceWidget *fmodSpeakerMode; VariableChoiceWidget *soundPlugin; VariableChoiceWidget *musicPlugin; +#if defined (WIN32) VariableChoiceWidget *cdPlugin; - bool audioPluginsChanged = false; +#endif + bool needAudioReinit = false; Impl(Public *i) : Base(i) { ScrollAreaWidget &area = self().area(); + area.enableIndicatorDraw(true); if (DoomsdayApp::isGameLoaded()) { @@ -71,12 +85,16 @@ area.add(musicSource = new CVarChoiceWidget ("music-source")); area.add(musicSoundfont = new CVarNativePathWidget("music-soundfont")); - musicSoundfont->setBlankText(tr("System default")); + musicSoundfont->setBlankText(tr("GeneralUser GS")); musicSoundfont->setFilters(StringList() << "SF2 soundfonts (*.sf2)" << "DLS soundfonts (*.dls)" << "All files (*)"); + area.add(pauseOnFocus = new VariableToggleWidget("Pause on Focus Lost", + App::config("audio.pauseOnFocus"), + "pause-on-focus")); + // Display volumes on a 0...100 scale. sfxVolume ->setDisplayFactor(100.0 / 255.0); musicVolume->setDisplayFactor(100.0 / 255.0); @@ -90,16 +108,50 @@ devPopup->commit(); } - area.add(soundPlugin = new VariableChoiceWidget(App::config("audio.soundPlugin"))); - area.add(musicPlugin = new VariableChoiceWidget(App::config("audio.musicPlugin"))); - area.add(cdPlugin = new VariableChoiceWidget(App::config("audio.cdPlugin"))); + backendFold = FoldPanelWidget::makeOptionsGroup("audio-backend", "Audio Backend", &area); + backendBase = new GuiWidget("fold-base"); + backendFold->setContent(backendBase); + + backendBase->add(audioOutput = new VariableChoiceWidget(App::config("audio.output"), VariableChoiceWidget::Number)); + backendBase->add(sfxChannels = new VariableSliderWidget(App::config("audio.channels"), Ranged(1, 64), 1.0)); + backendBase->add(soundPlugin = new VariableChoiceWidget(App::config("audio.soundPlugin"), VariableChoiceWidget::Text)); + backendBase->add(musicPlugin = new VariableChoiceWidget(App::config("audio.musicPlugin"), VariableChoiceWidget::Text)); +#if defined (WIN32) + backendBase->add(cdPlugin = new VariableChoiceWidget(App::config("audio.cdPlugin"), VariableChoiceWidget::Text)); +#endif +// backendBase->add(fmodSpeakerMode = new VariableChoiceWidget(App::config("audio.fmod.speakerMode"), VariableChoiceWidget::Text)); + + // Backend layout. + { + GridLayout layout(backendBase->rule().left(), backendBase->rule().top()); + layout.setGridSize(2, 0); + layout.setColumnAlignment(0, ui::AlignRight); + + layout << *LabelWidget::newWithText("SFX Plugin:", backendBase) << *soundPlugin + << *LabelWidget::newWithText("Music Plugin:", backendBase) << *musicPlugin +#if defined (WIN32) + << *LabelWidget::newWithText("CD Plugin:", backendBase) << *cdPlugin +#endif + << *LabelWidget::newWithText("Output:", backendBase) << *audioOutput +// << *LabelWidget::newWithText("Speaker Mode:", backendBase) << *fmodSpeakerMode + << *LabelWidget::newWithText("SFX Channels:", backendBase) << *sfxChannels; - area.add(fmodSpeakerMode = new VariableChoiceWidget(App::config("audio.fmod.speakerMode"))); + backendBase->rule().setSize(layout); + } + + // Check currently available outputs. + enumerateAudioOutputs(); + + /* fmodSpeakerMode->items() - << new ChoiceItem(tr("Stereo"), "") - << new ChoiceItem(tr("5.1"), "5.1") - << new ChoiceItem(tr("7.1"), "7.1") - << new ChoiceItem(tr("SRS 5.1/Prologic"), "prologic"); + << new ChoiceItem("Mono", "mono") + << new ChoiceItem("Stereo", "") + << new ChoiceItem("Quad", "quad") + << new ChoiceItem("Surround", "surround") + << new ChoiceItem("5.1", "5.1") + << new ChoiceItem("7.1", "7.1") + << new ChoiceItem("Raw", "raw"); + */ soundPlugin->items() << new ChoiceItem(tr("FMOD"), "fmod") @@ -113,9 +165,7 @@ << new ChoiceItem(tr("Disabled"), "dummy"); musicPlugin->items() - #if defined (UNIX) << new ChoiceItem(tr("Fluidsynth"), "fluidsynth") - #endif << new ChoiceItem(tr("FMOD"), "fmod") #if !defined (DENG_DISABLE_SDLMIXER) << new ChoiceItem(tr("SDL_mixer"), "sdlmixer") @@ -125,24 +175,49 @@ #endif << new ChoiceItem(tr("Disabled"), "dummy"); +#if defined (WIN32) cdPlugin->items() - << new ChoiceItem(tr("FMOD"), "fmod") - #if defined (WIN32) << new ChoiceItem(tr("Windows Multimedia"), "winmm") - #endif << new ChoiceItem(tr("Disabled"), "dummy"); + cdPlugin->updateFromVariable(); +#endif + soundPlugin ->updateFromVariable(); musicPlugin ->updateFromVariable(); - cdPlugin ->updateFromVariable(); - fmodSpeakerMode->updateFromVariable(); +// fmodSpeakerMode->updateFromVariable(); // The audio system needs reinitializing if the plugins are changed. - auto changeFunc = [this] (uint) { audioPluginsChanged = true; }; + auto changeFunc = [this](uint) { + needAudioReinit = true; + self().buttonWidget(Id2)->setText(_E(b) "Apply"); + }; QObject::connect(soundPlugin, &ChoiceWidget::selectionChangedByUser, changeFunc); QObject::connect(musicPlugin, &ChoiceWidget::selectionChangedByUser, changeFunc); +// QObject::connect(fmodSpeakerMode, &ChoiceWidget::selectionChangedByUser, changeFunc); +#if defined (WIN32) QObject::connect(cdPlugin, &ChoiceWidget::selectionChangedByUser, changeFunc); - QObject::connect(fmodSpeakerMode, &ChoiceWidget::selectionChangedByUser, changeFunc); +#endif + QObject::connect(sfxChannels, &SliderWidget::valueChangedByUser, changeFunc); + } + + void enumerateAudioOutputs() + { + audioOutput->items().clear(); + + const auto &outputs = + ScriptSystem::get()["Audio"]["outputs"].value(); + + /// @todo Currently only FMOD has outputs. + const TextValue key("fmod"); + if (outputs.contains(key)) + { + const auto &names = outputs.element(key).as(); + for (unsigned i = 0; i < names.size(); ++i) + { + audioOutput->items() << new ChoiceItem(names.at(i).asText(), i); + } + } } void fetch() @@ -160,7 +235,8 @@ }; AudioSettingsDialog::AudioSettingsDialog(String const &name) - : DialogWidget(name, WithHeading), d(new Impl(this)) + : DialogWidget(name, WithHeading) + , d(new Impl(this)) { bool const gameLoaded = DoomsdayApp::isGameLoaded(); @@ -198,48 +274,43 @@ auto *sfLabel = LabelWidget::newWithText(tr("MIDI Sound Font:"), &area()); // Layout. - layout << *sfxVolLabel << *d->sfxVolume - << *musicVolLabel << *d->musicVolume - << Const(0) << *d->sound3D - << *rvbVolLabel << *d->reverbVolume + LabelWidget::appendSeparatorWithText("Sound Effects", &area(), &layout); + layout << *sfxVolLabel << *d->sfxVolume << Const(0) << *d->overlapStop - //<< *rateLabel << *d->sampleRate - //<< Const(0) << *d->sound16bit + << Const(0) << *d->sound3D + << *rvbVolLabel << *d->reverbVolume; + + LabelWidget::appendSeparatorWithText("Music", &area(), &layout); + layout << *musicVolLabel << *d->musicVolume << *musSrcLabel << *d->musicSource - << *sfLabel << *d->musicSoundfont; + << *sfLabel << *d->musicSoundfont + << Const(0) << *d->pauseOnFocus; } + else + { + d->backendFold->open(); + } + + SequentialLayout layout2(area().contentRule().left(), + area().contentRule().top() + layout.height()); + layout2.setOverrideWidth(d->backendBase->rule().width()); + + layout2 << d->backendFold->title() + << *d->backendFold; + + area().setContentSize(OperatorRule::maximum(layout.width(), layout2.width()), + layout.height() + layout2.height()); - auto *soundPluginLabel = LabelWidget::newWithText(tr("SFX Plugin:" ), &area()); - auto *musicPluginLabel = LabelWidget::newWithText(tr("Music Plugin:"), &area()); - auto *cdPluginLabel = LabelWidget::newWithText(tr("CD Plugin:" ), &area()); - - LabelWidget *pluginLabel = LabelWidget::newWithText(_E(D) + tr("Audio Backend"), &area()); - pluginLabel->setFont("separator.label"); - pluginLabel->margins().setTop("gap"); - layout.setCellAlignment(Vector2i(0, layout.gridSize().y), ui::AlignLeft); - layout.append(*pluginLabel, 2); - - layout << *soundPluginLabel << *d->soundPlugin - << *musicPluginLabel << *d->musicPlugin - << *cdPluginLabel << *d->cdPlugin; - - auto *padding = new GuiWidget; - area().add(padding); - padding->rule().setInput(Rule::Height, rule("dialog.gap")); - layout.append(*padding, 2); - - auto *speakerLabel = LabelWidget::newWithText(tr("FMOD Speaker Mode:"), &area()); - layout << *speakerLabel << *d->fmodSpeakerMode; - - area().setContentSize(layout.width(), layout.height()); + // The subheading should extend all the way. + d->backendFold->title().rule().setInput(Rule::Width, area().contentRule().width()); buttons() - << new DialogButtonItem(DialogWidget::Default | DialogWidget::Accept, tr("Close")) - << new DialogButtonItem(DialogWidget::Action, tr("Reset to Defaults"), + << new DialogButtonItem(Default | Accept | Id2, tr("Close")) + << new DialogButtonItem(Action, tr("Reset to Defaults"), new SignalAction(this, SLOT(resetToDefaults()))); if (gameLoaded) { - buttons() << new DialogButtonItem(DialogWidget::ActionPopup | Id1, + buttons() << new DialogButtonItem(ActionPopup | Id1, style().images().image("gauge")); popupButtonWidget(Id1)->setPopup(*d->devPopup); } @@ -250,8 +321,8 @@ void AudioSettingsDialog::resetToDefaults() { ClientApp::audioSettings().resetToDefaults(); - d->fetch(); + d->needAudioReinit = true; } void AudioSettingsDialog::finish(int result) @@ -259,7 +330,7 @@ DialogWidget::finish(result); if (result) { - if (d->audioPluginsChanged) + if (d->needAudioReinit) { AudioSystem::get().reinitialize(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/coloradjustmentdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/coloradjustmentdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/coloradjustmentdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/coloradjustmentdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -54,7 +54,7 @@ layout << *gammaLabel << *gamma << *contrastLabel << *contrast << *brightnessLabel << *brightness; - area.setContentSize(layout.width(), layout.height()); + area.setContentSize(layout); } void fetch() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/createprofiledialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/createprofiledialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/createprofiledialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/createprofiledialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -18,28 +18,111 @@ #include "ui/dialogs/createprofiledialog.h" #include "ui/widgets/packagesbuttonwidget.h" +#include "ui/widgets/packageswidget.h" +#include "ui/dialogs/datafilesettingsdialog.h" #include #include #include +#include +#include +#include #include #include #include +#include +#include +#include +#include +#include +#include using namespace de; DENG_GUI_PIMPL(CreateProfileDialog) +, DENG2_OBSERVES(ToggleWidget, Toggle) +, DENG2_OBSERVES(SliderWidget, Change) { + GuiWidget *form; ChoiceWidget *gameChoice; PackagesButtonWidget *packages; + ChoiceWidget *autoStartMap; + ChoiceWidget *autoStartSkill; + AuxButtonWidget *customDataFileName; + ui::ListData customDataFileActions; + SafeWidgetPtr customPicker; + FoldPanelWidget *optionsFold; + GuiWidget *optionsBase; DialogContentStylist stylist; bool editing = false; String oldName; - std::unique_ptr tempProfile; + std::unique_ptr tempProfile; // Used only internally. Impl(Public *i) : Base(i) {} + void populateOptions() + { + optionsBase->clearTree(); + + GridLayout layout(optionsBase->rule().left(), optionsBase->rule().top()); + layout.setGridSize(2, 0); + layout.setColumnAlignment(0, ui::AlignRight); + const auto &opts = tempProfile->game()[Game::DEF_OPTIONS].valueAsRecord().members(); + if (opts.isEmpty()) + { + return; + } + StringList keys = opts.keys(); + // Alphabetic order based on the label. + std::sort(keys.begin(), keys.end(), [&opts](const String &k1, const String &k2) { + return opts[k1]->valueAsRecord().gets("label").compareWithoutCase( + opts[k2]->valueAsRecord().gets("label")) < 0; + }); + for (const auto &key : keys) + { + const Record &optDef = opts[key]->valueAsRecord(); + const String optType = optDef["type"]; + const String optLabel = optDef["label"]; + + if (optType == "boolean") + { + auto *tog = new ToggleWidget; + optionsBase->add(tog); + tog->setText(optLabel); + tog->setActive(ScriptedInfo::isTrue(tempProfile->optionValue(key))); + tog->objectNamespace().set("option", key); + tog->audienceForToggle() += this; + layout << Const(0) << *tog; + } + else if (optType == "number") + { + auto *slider = new SliderWidget; + optionsBase->add(slider); + slider->setRange(Ranged(optDef.getd("min"), optDef.getd("max"))); + const double step = optDef.getd("step", 1.0); + slider->setStep(step); + slider->setValue(tempProfile->optionValue(key).asNumber()); + slider->setPrecision(step < 1 ? 1 : 0); + slider->objectNamespace().set("option", key); + slider->audienceForChange() += this; + layout << *LabelWidget::newWithText(optLabel + ":", optionsBase) + << *slider; + } + } + optionsBase->rule().setSize(layout); + } + + void toggleStateChanged(ToggleWidget &widget) override + { + tempProfile->setOptionValue(widget["option"], NumberValue(widget.isActive())); + } + + void sliderValueChanged(SliderWidget &widget) override + { + tempProfile->setOptionValue(widget["option"], NumberValue(widget.value())); + } + void checkValidProfileName() { bool valid = false; @@ -54,7 +137,7 @@ else { // Must be a new, unique name. - valid = DoomsdayApp::gameProfiles().forAll([this, &entry] (GameProfile &prof) { + valid = DoomsdayApp::gameProfiles().forAll([&entry] (const GameProfile &prof) { if (!entry.compareWithoutCase(prof.name())) { return LoopAbort; } @@ -64,18 +147,103 @@ } // A game must be selected, too. - if (!gameChoice->isValidSelection()) valid = false; - + if (!gameChoice->isValidSelection()) + { + valid = false; + } if (gameChoice->isValidSelection() && - gameChoice->selectedItem().data().toString().isEmpty()) valid = false; - + gameChoice->selectedItem().data().toString().isEmpty()) + { + valid = false; + } self().buttonWidget(Id1)->enable(valid); } void gameChanged() { + if (gameChoice->isValidSelection()) + { + tempProfile->setGame(gameChoice->selectedItem().data().toString()); // Used with the PackagesButtonWidget. - tempProfile->setGame(gameChoice->selectedItem().data().toString()); + updateMapList(); + } + } + + void updateMapList() + { + auto &mapItems = autoStartMap->items(); + + String oldChoice; + if (!mapItems.isEmpty()) + { + oldChoice = autoStartMap->selectedItem().data().toString(); + } + + mapItems.clear(); + mapItems << new ChoiceItem(tr("Title screen"), ""); + + // Find out all the required and selected packages. + StringList packageIds; + if (gameChoice->isValidSelection()) + { + packageIds += tempProfile->allRequiredPackages(); + } + + // Create menu items for the Start Map choice. + for (int i = packageIds.size() - 1; i >= 0; --i) + { + String const pkgId = packageIds.at(i); + if (File const *pkgFile = PackageLoader::get().select(pkgId)) + { + DataBundle const *bundle = maybeAs(pkgFile->target()); + if (!bundle || !bundle->lumpDirectory()) + { + continue; + } + + auto const maps = bundle->lumpDirectory()->findMapLumpNames(); + if (!maps.isEmpty()) + { + mapItems << new ui::Item(ui::Item::Separator); + + String const wadName = Package::metadata(*pkgFile).gets(Package::VAR_TITLE); + foreach (String mapId, maps) + { + // Only show each map identifier once; only the last lump can + // be loaded. + if (mapItems.findData(mapId) == ui::Data::InvalidPos) + { + mapItems << new ChoiceItem(String("%1 " _E(s)_E(C) "%2").arg(mapId).arg(wadName), + mapId); + } + } + } + } + } + + auto const pos = mapItems.findData(oldChoice); + autoStartMap->setSelected(pos != ui::Data::InvalidPos ? pos : 0); + } + + void updateDataFile() + { + if (tempProfile->customDataFile().isEmpty()) + { + customDataFileName->setText(_E(l) "Default game data"); + } + else + { + if (const auto *pkgFile = PackageLoader::get().select(tempProfile->customDataFile())) + { + const auto path = pkgFile->correspondingNativePath(); + customDataFileName->setText(path.pretty()); + } + else + { + customDataFileName->setText(_E(b) "Not found"); + } + } + updateMapList(); } }; @@ -84,9 +252,13 @@ , d(new Impl(this)) { title() .setText(tr("New Profile")); - message().setText(tr("Enter a name for the new game profile. Only unique names are allowed.")); + message().setText(tr("Enter a name for the new game profile.")); + // MessageDialog applies a layout on its area contents, so we'll have our own parent widget + // for our widgets. + { auto *form = new GuiWidget; + d->form = form; d->stylist.setContainer(*form); area().add(form); @@ -94,9 +266,10 @@ form->add(d->gameChoice = new ChoiceWidget); DoomsdayApp::games().forAll([this, &gameFamily] (Game &game) { - if (game.isPlayable() && game.family() == gameFamily) + if (game.family() == gameFamily) { - d->gameChoice->items() << new ChoiceItem(game.title(), game.id()); + const char *labelColor = (!game.isPlayable() ? _E(F) : ""); + d->gameChoice->items() << new ChoiceItem(labelColor + game.title(), game.id()); } return LoopContinue; }); @@ -105,6 +278,57 @@ if (d->gameChoice->items().isEmpty()) { d->gameChoice->items() << new ChoiceItem(tr("No playable games"), ""); + } + + // Custom data file selection. + { + form->add(d->customDataFileName = new AuxButtonWidget); + d->customDataFileName->setMaximumTextWidth( + rule().right() - d->customDataFileName->rule().left() - + d->customDataFileName->margins().width()); + d->customDataFileName->setTextLineAlignment(ui::AlignLeft); + d->customDataFileName->auxiliary().setText("Reset"); + d->customDataFileActions + << new ui::ActionItem("Select", new CallbackAction([this]() { + if (d->customPicker) + { + d->tempProfile->setCustomDataFile(d->customPicker->actionPackage()); + d->customPicker->ancestorOfType()->accept(); + d->updateDataFile(); + } + })); + d->customDataFileName->setActionFn([this]() { + auto *dlg = new MessageDialog; + dlg->buttons() << new DialogButtonItem(Reject, "Cancel") + << new DialogButtonItem(Action | Id1, style().images().image("gear"), + "Data Files", new CallbackAction([dlg]() { + auto *dfsDlg = new DataFileSettingsDialog; + dfsDlg->setAnchorAndOpeningDirection(dlg->buttonWidget(Id1)->rule(), ui::Up); + dfsDlg->setDeleteAfterDismissed(true); + dlg->add(dfsDlg); + dfsDlg->open(); + })); + dlg->setDeleteAfterDismissed(true); + dlg->title().setText("Game Data File"); + dlg->message().setText( + "Select the main data file for this profile. When using a manually chosen main " + "data file, the default data files of the game will not be automatically loaded."); + dlg->area().enableIndicatorDraw(true); + d->customPicker.reset(new PackagesWidget); + dlg->area().add(d->customPicker); + d->customPicker->setHiddenTags({"hidden", "core"}); + d->customPicker->searchTermsEditor().setText("gamedata"); + d->customPicker->setAllowPackageInfoActions(false); + d->customPicker->setActionItems(d->customDataFileActions); + dlg->setAnchorAndOpeningDirection(d->customDataFileName->rule(), ui::Right); + dlg->updateLayout(); + root().addOnTop(dlg); + dlg->open(Modal); + }); + d->customDataFileName->auxiliary().setActionFn([this]() { + d->tempProfile->setCustomDataFile(""); + d->updateDataFile(); + }); } // Packages selection. @@ -118,10 +342,55 @@ layout.setColumnAlignment(0, ui::AlignRight); layout << *LabelWidget::newWithText(tr("Game:"), form) << *d->gameChoice - << *LabelWidget::newWithText(tr("Packages:"), form) + << *LabelWidget::newWithText("Data File:", form) + << *d->customDataFileName + << *LabelWidget::newWithText(tr("Mods:"), form) << *d->packages; + form->rule().setSize(layout); + } + + // Foldable panel for the Launch Options. + { + auto *launchOptions = + FoldPanelWidget::makeOptionsGroup("launch-options", "Launch Options", &area()); + + launchOptions->title().margins().setTop(rule("gap") + d->form->margins().bottom()); + + auto *form = new GuiWidget; + launchOptions->setContent(form); + + // Auto start map. + form->add(d->autoStartMap = new ChoiceWidget); + d->autoStartMap->popup().menu().enableIndicatorDraw(true); + d->autoStartMap->items() << new ChoiceItem(tr("Title screen"), ""); + + // Auto start skill. + form->add(d->autoStartSkill = new ChoiceWidget); + d->autoStartSkill->items() + << new ChoiceItem(tr("Novice"), 1) + << new ChoiceItem(tr("Easy"), 2) + << new ChoiceItem(tr("Normal"), 3) + << new ChoiceItem(tr("Hard"), 4) + << new ChoiceItem(tr("Nightmare"), 5); + d->autoStartSkill->disable(); + d->autoStartSkill->setSelected(2); + + GridLayout layout(form->rule().left(), form->rule().top()); + layout.setGridSize(2, 0); + layout.setColumnAlignment(0, ui::AlignRight); + layout << *LabelWidget::newWithText(tr("Starts in:"), form) << *d->autoStartMap + << *LabelWidget::newWithText(tr("Skill:"), form) << *d->autoStartSkill; + form->rule().setSize(layout); + } + + // Additional options defined by the game. + { + d->optionsFold = + FoldPanelWidget::makeOptionsGroup("gameplay-options", "Gameplay Options", &area()); - form->rule().setSize(layout.width(), layout.height()); + d->optionsBase = new GuiWidget; + d->optionsFold->setContent(d->optionsBase); + } buttons().clear() << new DialogButtonItem(Id1 | Default | Accept, tr("Create")) @@ -130,10 +399,19 @@ // The Create button is enabled when a valid name is entered. buttonWidget(Id1)->disable(); - updateLayout(); - + updateLayout(IncludeHidden); + d->updateDataFile(); d->gameChanged(); + d->populateOptions(); + connect(d->gameChoice, &ChoiceWidget::selectionChanged, [this] () { d->gameChanged(); }); + connect(d->packages, &PackagesButtonWidget::packageSelectionChanged, + [this] (QStringList) { d->updateMapList(); }); + connect(d->autoStartMap, &ChoiceWidget::selectionChanged, [this] () + { + d->autoStartSkill->disable(d->autoStartMap->items().isEmpty() || + d->autoStartMap->selectedItem().data().toString().isEmpty()); + }); connect(&editor(), &LineEditWidget::editorContentChanged, [this] () { d->checkValidProfileName(); }); } @@ -143,6 +421,10 @@ auto *prof = new GameProfile(profileName()); prof->setUserCreated(true); applyTo(*prof); + if (!prof->saveLocationId()) + { + prof->createSaveLocation(); + } return prof; } @@ -150,14 +432,30 @@ { editor().setText(profile.name()); d->gameChoice->setSelected(d->gameChoice->items().findData(profile.gameId())); + d->tempProfile->setCustomDataFile(profile.customDataFile()); d->packages->setPackages(profile.packages()); + d->updateDataFile(); + d->autoStartMap->setSelected(d->autoStartMap->items().findData(profile.autoStartMap())); + d->autoStartSkill->setSelected(d->autoStartSkill->items().findData(profile.autoStartSkill())); + d->tempProfile->setSaveLocationId(profile.saveLocationId()); + d->tempProfile->objectNamespace() = profile.objectNamespace(); + d->populateOptions(); } void CreateProfileDialog::applyTo(GameProfile &profile) const { profile.setName(profileName()); + if (d->gameChoice->isValidSelection()) + { profile.setGame(d->gameChoice->selectedItem().data().toString()); + } + profile.setCustomDataFile(d->tempProfile->customDataFile()); + profile.setUseGameRequirements(true); profile.setPackages(d->packages->packages()); + profile.setAutoStartMap(d->autoStartMap->selectedItem().data().toString()); + profile.setAutoStartSkill(d->autoStartSkill->selectedItem().data().toInt()); + profile.setSaveLocationId(profile.saveLocationId()); + profile.objectNamespace() = d->tempProfile->objectNamespace(); } String CreateProfileDialog::profileName() const @@ -165,6 +463,37 @@ return editor().text().strip(); } +void CreateProfileDialog::operator>>(PersistentState &toState) const +{ + auto &ps = toState.objectNamespace(); + auto &launch = find("launch-options")->as(); + ps.set(name().concatenateMember(launch.name()) + ".open", launch.isOpen()); + ps.set(name().concatenateMember(d->optionsFold->name()) + ".open", + d->optionsFold->isOpen()); +} + +void CreateProfileDialog::operator<<(const PersistentState &fromState) +{ + auto &ps = fromState.objectNamespace(); + auto &launch = find("launch-options")->as(); + if (ps.getb(name().concatenateMember(launch.name()) + ".open", true)) + { + launch.open(); + } + else + { + launch.close(0.0); + } + if (ps.getb(name().concatenateMember(d->optionsFold->name()) + ".open", false)) + { + d->optionsFold->open(); + } + else + { + d->optionsFold->close(0.0); + } +} + CreateProfileDialog *CreateProfileDialog::editProfile(String const &gameFamily, GameProfile &profile) { @@ -172,9 +501,9 @@ dlg->d->editing = true; dlg->d->oldName = profile.name(); dlg->title().setText(tr("Edit Profile")); - dlg->message().hide(); + delete &dlg->message(); dlg->buttonWidget(Id1)->setText(_E(b) + tr("OK")); dlg->fetchFrom(profile); - dlg->updateLayout(); + dlg->updateLayout(IncludeHidden); return dlg; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/datafilesettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/datafilesettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/datafilesettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/datafilesettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -20,6 +20,7 @@ #include "ui/clientwindow.h" #include "ui/widgets/consolewidget.h" #include "ui/widgets/packageswidget.h" +#include "ui/widgets/taskbarwidget.h" #include #include @@ -28,10 +29,8 @@ DENG2_PIMPL_NOREF(DataFileSettingsDialog) { - Variable &iwadFolders = Config::get("resource.iwadFolder"); Variable &pkgFolders = Config::get("resource.packageFolder"); - Id iwadGroup; - Id pkgGroup; + Id searchGroup; bool modified = false; }; @@ -39,8 +38,8 @@ : DirectoryListDialog(name) , d(new Impl) { - buttons().clear() - << new DialogButtonItem(Default | Accept, tr("Close")); + buttons().remove(1); // remove the Cancel + buttons().at(0).setLabel("Apply"); title().setFont("heading"); title().setText(tr("Data Files")); @@ -48,27 +47,19 @@ message().hide(); - //dlg->title().setFont("heading"); - //dlg->title().setStyleImage("package.icon"); - //dlg->title().setOverrideImageSize(Style::get().fonts().font("heading").ascent().value()); - //dlg->title().setTextGap("dialog.gap"); - //dlg->title().setText(QObject::tr("IWAD Folders")); - //dlg->message().setText(QObject::tr("The following folders are searched for game data files:")); - - d->iwadGroup = addGroup(tr("IWAD Folders"), - tr("The following folders are searched for game IWAD files. " - "Only these folders are checked, not their subfolders.")); - setValue(d->iwadGroup, d->iwadFolders.value()); - - d->pkgGroup = addGroup(tr("Add-on and Package Folders"), - tr("The following folders and all their subfolders are searched " - "for resource packs and other add-ons.")); - setValue(d->pkgGroup, d->pkgFolders.value()); + d->searchGroup = addGroup( + tr("Search Folders"), + tr("The following folders are searched for game IWAD files and mods like PWADs, PK3s, and " + "Doomsday packages. Toggle the " _E(b) "Subdirs" _E(.) + " option to include all subfolders as well.")); + setValue(d->searchGroup, d->pkgFolders.value()); connect(this, &DirectoryListDialog::arrayChanged, [this] () { d->modified = true; }); + + updateLayout(); } void DataFileSettingsDialog::finish(int result) @@ -77,14 +68,10 @@ if (d->modified) { - d->iwadFolders.set(value(d->iwadGroup)); - d->pkgFolders .set(value(d->pkgGroup)); + d->pkgFolders.set(value(d->searchGroup)); // Reload packages and recheck for game availability. - auto &win = ClientWindow::main(); - win.console().closeLogAndUnfocusCommandLine(); - win.root().find("home-packages")->as().showProgressIndicator(); - DoomsdayApp::app().initWadFolders(); + ClientWindow::main().taskBar().close(); DoomsdayApp::app().initPackageFolders(); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/downloaddialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/downloaddialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/downloaddialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/downloaddialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,75 @@ +/** + * @file downloaddialog.h + * Dialog for downloads. @ingroup ui + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "ui/dialogs/downloaddialog.h" + +#include + +using namespace de; + +DENG_GUI_PIMPL(DownloadDialog) +{ + ProgressWidget *progress; + + Impl(Public *i) : Base(i) + { + ScrollAreaWidget &area = self().area(); + + progress = new ProgressWidget; + area.add(progress); + progress->setAlignment(ui::AlignLeft); + progress->setSizePolicy(ui::Fixed, ui::Expand); + progress->setRange(Rangei(0, 100)); + progress->rule() + .setLeftTop(area.contentRule().left(), area.contentRule().top()) + .setInput(Rule::Width, rule("dialog.download.width")); + + area.setContentSize(progress->rule()); + + self().buttons() << new DialogButtonItem(DialogWidget::Reject, + "Cancel Download", + new CallbackAction([this] () { self().cancel(); })); + updateStyle(); + } + + void updateStyle() + { + progress->setImageScale(.4f); //pointsToPixels(.4f)); + } +}; + +DownloadDialog::DownloadDialog(String const &name) + : DialogWidget(name) + , d(new Impl(this)) +{} + +DownloadDialog::~DownloadDialog() +{} + +ProgressWidget &DownloadDialog::progressIndicator() +{ + return *d->progress; +} + +void DownloadDialog::updateStyle() +{ + DialogWidget::updateStyle(); + d->updateStyle(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/filedownloaddialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/filedownloaddialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/filedownloaddialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/filedownloaddialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,74 @@ +/** @file filedownloaddialog.cpp Dialog for monitoring file download progress. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "ui/dialogs/filedownloaddialog.h" +#include "network/serverlink.h" + +#include + +using namespace de; + +DENG_GUI_PIMPL(FileDownloadDialog) +, DENG2_OBSERVES(shell::PackageDownloader, Status) +{ + shell::PackageDownloader &downloader; + String message = tr("Downloading data files..."); + + Impl(Public *i, shell::PackageDownloader &downloader) + : Base(i) + , downloader(downloader) + { + downloader.audienceForStatus() += this; + + self().progressIndicator().setText(tr("%1\n" _E(l)_E(F) "%2" + DENG2_CHAR_MDASH " files / " + DENG2_CHAR_MDASH " MB") + .arg(message) + .arg(_E(l))); + } + + void downloadStatusUpdate(Rangei64 const &bytes, Rangei const &files) + { + if (!bytes.end) return; + + auto &indicator = self().progressIndicator(); + indicator.setProgress(round(100.0 * double(bytes.size())/double(bytes.end))); + + indicator.setText(tr("%1\n" _E(l)_E(F) "%2 file%3 / %4 MB") + .arg(message) + .arg(files.start) + .arg(DENG2_PLURAL_S(files.start)) + .arg(bytes.start/1.0e6, 0, 'f', 1)); + } +}; + +FileDownloadDialog::FileDownloadDialog(shell::PackageDownloader &downloader) + : d(new Impl(this, downloader)) +{} + +void FileDownloadDialog::cancel() +{ + d->downloader.cancel(); +} + +void FileDownloadDialog::finish(int result) +{ + if (!result) cancel(); + + DownloadDialog::finish(result); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/inputsettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/inputsettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/inputsettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/inputsettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -146,13 +146,13 @@ d->applyGamepad->setText(tr("Apply")); connect(d->applyGamepad, SIGNAL(pressed()), this, SLOT(applyControllerPreset())); - LabelWidget *mouseXLabel = LabelWidget::newWithText(_E(D) + tr("Mouse: Horizontal"), &area()); - LabelWidget *mouseYLabel = LabelWidget::newWithText(_E(D) + tr("Mouse: Vertical"), &area()); - mouseXLabel->setFont("separator.label"); - mouseYLabel->setFont("separator.label"); + LabelWidget *mouseXLabel = LabelWidget::appendSeparatorWithText("Mouse: Horizontal", &area()); + LabelWidget *mouseYLabel = LabelWidget::appendSeparatorWithText("Mouse: Vertical", &area()); + //mouseXLabel->setFont("separator.label"); +// mouseYLabel->setFont("separator.label"); - mouseXLabel->margins().setTop("gap"); - mouseYLabel->margins().setTop("gap"); +// mouseXLabel->margins().setTop("gap"); +// mouseYLabel->margins().setTop("gap"); LabelWidget *applyNote = LabelWidget::newWithText(tr("Clicking " _E(b) "Apply" _E(.) " will remove all " "existing game controller bindings and apply " diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/logsettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/logsettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/logsettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/logsettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -126,8 +126,9 @@ wgt.label = LabelWidget::newWithText(tr(dom.label) + ":", parent); // Minimum level for log entries. - parent->add(wgt.level = - new VariableChoiceWidget(Config::get(String("log.filter.%1.minLevel").arg(dom.name)))); + parent->add(wgt.level = new VariableChoiceWidget( + Config::get(String("log.filter.%1.minLevel").arg(dom.name)), + VariableChoiceWidget::Number)); wgt.level->setItems(levels); wgt.level->updateFromVariable(); QObject::connect(wgt.level, SIGNAL(selectionChangedByUser(uint)), @@ -242,7 +243,7 @@ d->fold->content().rule().setSize(d->foldLayout.width(), d->foldLayout.height()); // Dialog content size. - area().setContentSize(layout.width(), layout.height()); + area().setContentSize(layout); buttons() << new DialogButtonItem(DialogWidget::Default | DialogWidget::Accept, tr("Close")) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/manualconnectiondialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -145,12 +145,12 @@ d->autoJoin = joinWhenSelected; } -void ManualConnectionDialog::operator >> (PersistentState &toState) const +void ManualConnectionDialog::operator>>(PersistentState &toState) const { toState.objectNamespace().set(name() + ".address", d->usedAddress); } -void ManualConnectionDialog::operator << (PersistentState const &fromState) +void ManualConnectionDialog::operator<<(PersistentState const &fromState) { d->usedAddress = fromState[name() + ".address"]; editor().setText(d->usedAddress); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/networksettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/networksettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/networksettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/networksettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -44,7 +44,8 @@ { ScrollAreaWidget &area = self().area(); - area.add(localPackages = new VariableToggleWidget(tr("Local Multiplayer Packages"), App::config("resource.localPackages"))); + area.add(localPackages = new VariableToggleWidget(tr("Local Multiplayer Mods"), + App::config("resource.localPackages"))); // Developer options. self().add(devPopup = new GridPopupWidget); @@ -91,7 +92,7 @@ caution->setTextColor("altaccent"); layout << *caution; - area().setContentSize(layout.width(), layout.height()); + area().setContentSize(layout); buttons() << new DialogButtonItem(Default | Accept, tr("Close")) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packagecompatibilitydialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packagecompatibilitydialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packagecompatibilitydialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packagecompatibilitydialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "dd_main.h" @@ -34,18 +35,21 @@ DENG2_PIMPL(PackageCompatibilityDialog) { - String message; - StringList wanted; - bool conflicted = false; - PackagesWidget *list = nullptr; - ui::ListData actions; + String message; + StringList wanted; + bool conflicted = false; + PackagesWidget *list = nullptr; + ToggleWidget * ignoreToggle = nullptr; + LabelWidget * ignoreWarning = nullptr; + ui::ListData actions; ProgressWidget *updating; - bool ignoreCheck = false; - LoopCallback mainCall; + bool ignoreCheck = false; + LoopCallback mainCall; Impl(Public *i) : Base(i) { self().add(updating = new ProgressWidget); + self().area().enableIndicatorDraw(true); updating->setSizePolicy(ui::Expand, ui::Expand); updating->useMiniStyle("altaccent"); updating->setText(tr("Updating...")); @@ -67,9 +71,9 @@ } if (list->itemCount() > 0) { - return _E(b) + tr("Load Packages"); + return _E(b) + tr("Load Mods"); } - return _E(b) + tr("Unload Packages"); + return _E(b) + tr("Unload Mods"); } void enableIgnore(bool yes) @@ -79,6 +83,10 @@ { button->setText(defaultButtonLabel()); } + if (auto *button = self().buttonWidget(Id2)) + { + button->enable(ignoreCheck); + } } void update() @@ -88,43 +96,154 @@ delete list; list = nullptr; } + if (ignoreWarning) + { + delete ignoreWarning; + ignoreWarning = nullptr; + } + if (ignoreToggle) + { + delete ignoreToggle; + ignoreToggle = nullptr; + } self().buttons().clear(); try { // The only action on the packages is to view information. - actions << new ui::SubwidgetItem(tr("..."), ui::Up, [this] () -> PopupWidget * - { - return new PackageInfoDialog(list->actionPackage()); + actions << new ui::SubwidgetItem(tr("..."), ui::Up, [this]() -> PopupWidget * { + return new PackageInfoDialog(list->actionPackage(), + PackageInfoDialog::InformationOnly); + }); + + self().area().add(ignoreToggle = new ToggleWidget); + ignoreToggle->setText("Ignore incompatible/missing mods"); + ignoreToggle->setAlignment(ui::AlignLeft); + ignoreToggle->setActionFn([this]() { + enableIgnore(ignoreToggle->isActive()); }); - self().area().add(list = new PackagesWidget(wanted)); + self().area().add(ignoreWarning = new LabelWidget); + ignoreWarning->setText(_E(b) "Caution: " _E(.) "Playing without the right resources " + "may cause a crash."); + ignoreWarning->setFont("separator.annotation"); + ignoreWarning->setTextColor("altaccent"); + ignoreWarning->setAlignment(ui::AlignLeft); + ignoreWarning->setTextLineAlignment(ui::AlignLeft); + ignoreWarning->margins().setTop(ConstantRule::zero()); + + // Check which of the wanted packages are actually available. + StringList wantedUnavailable; + StringList wantedAvailable; + QList> wantedDifferentVersionAvailable; + { + auto &pkgLoader = PackageLoader::get(); + + for (const auto &id : wanted) + { + if (pkgLoader.isAvailable(id)) + { + wantedAvailable << id; + } + else + { + auto id_ver = Package::split(id); + if (const auto *p = pkgLoader.select(id_ver.first)) + { + wantedDifferentVersionAvailable.push_back( + {Package::versionedIdentifierForFile(*p), id_ver.second}); + } + else + { + wantedUnavailable << id; + } + } + } + } + + // Detail the problem to the user. + String unavailNote; + if (!wantedDifferentVersionAvailable.empty()) + { + unavailNote += + _E(b)_E(D) "Caution:" _E(.)_E(.) " There is a different version of " + "the following mods available:\n"; + for (const auto &avail_expected : wantedDifferentVersionAvailable) + { + unavailNote += + " - " _E(>) + Package::splitToHumanReadable(avail_expected.first) + + " " _E(l)_E(F) "\n(expected " + + avail_expected.second.fullNumber() + _E(<) ")\n" _E(w)_E(A); + } + unavailNote += "\n"; + } + if (!wantedUnavailable.empty()) + { + unavailNote += "The following mods are missing:\n"; + for (const auto &id : wantedUnavailable) + { + unavailNote += " - " + Package::splitToHumanReadable(id) + "\n"; + } + unavailNote += "\n"; + } + + StringList wantedDifferent = + map(wantedDifferentVersionAvailable, + [](const std::pair &sv) { return sv.first; }); + + self().area().add(list = new PackagesWidget(wantedAvailable + wantedDifferent)); + list->setAllowPackageInfoActions(false); + list->setHiddenTags({"core", "gamedata"}); list->setActionItems(actions); list->setActionsAlwaysShown(true); list->setFilterEditorMinimumY(self().area().rule().top()); - StringList const loaded = DoomsdayApp::loadedPackagesAffectingGameplay(); - //qDebug() << "Currently loaded:" << loaded; + const StringList loaded = DoomsdayApp::loadedPackagesAffectingGameplay(); if (!GameProfiles::arePackageListsCompatible(loaded, wanted)) { + // Packages needs loading and/or unloading. conflicted = true; - if (list->itemCount() > 0) + + if (list->itemCount() == 0) { - self().message().setText(message + "\n\n" + tr("The packages listed below " - "should be loaded.")); - self().buttons() - << new DialogButtonItem(Default | Accept | Id1, defaultButtonLabel(), - new CallbackAction([this] () { resolvePackages(); })); + list->hide(); + } + if (!wantedUnavailable.empty()) + { + self().message().setText(message + "\n\n" + unavailNote + + "Please locate the missing mods before continuing. " + "You may need to add more folders in your Data Files " + "settings so the mods can be found."); + if (list->itemCount() > 0) + { + self().message().setText( + self().message().text() + + "\n\nThe mods listed below are required and available, " + "and should be loaded now (the highlighted ones are already loaded)."); + } + self().buttons() << new DialogButtonItem(Default | Accept | Id2, + _E(b) _E(D) "Ignore and Continue"); + self().buttonWidget(Id2)->disable(); } else { - list->hide(); - self().message().setText(message + "\n\n" + tr("All additional packages " - "should be unloaded.")); - self().buttons() - << new DialogButtonItem(Default | Accept | Id1, defaultButtonLabel(), - new CallbackAction([this] () { resolvePackages(); })); + if (list->itemCount() > 0) + { + self().message().setText(message + "\n\n" + unavailNote + + tr("All the mods listed below should be loaded.")); + self().buttons() + << new DialogButtonItem(Default | Accept | Id1, defaultButtonLabel(), + new CallbackAction([this] () { resolvePackages(); })); + } + else + { + self().message().setText(message + "\n\n" + unavailNote + + tr("All additional mods should be unloaded.")); + self().buttons() + << new DialogButtonItem(Default | Accept | Id1, defaultButtonLabel(), + new CallbackAction([this] () { resolvePackages(); })); + } } self().buttons() << new DialogButtonItem(Reject, tr("Cancel")); @@ -153,12 +272,12 @@ { if (ignoreCheck) { - LOG_RES_NOTE("Ignoring package compatibility check due to user request"); + LOG_RES_NOTE("Ignoring package compatibility check due to user request!"); self().accept(); return; } - qDebug() << "resolving..."; + LOG_RES_MSG("Resolving packages..."); auto &pkgLoader = PackageLoader::get(); @@ -180,12 +299,12 @@ } } - qDebug() << "Good until:" << goodUntil; + LOG_RES_MSG("Good until %s") << goodUntil; // Unload excess. for (int i = loaded.size() - 1; i > goodUntil; --i) { - qDebug() << "unloading excess" << loaded.at(i); + LOG_RES_MSG("Unloading excess ") << loaded.at(i); pkgLoader.unload(loaded.at(i)); loaded.removeAt(i); @@ -194,12 +313,23 @@ // Load the remaining wanted packages. for (int i = goodUntil + 1; i < wanted.size(); ++i) { - qDebug() << "loading wanted" << wanted.at(i); + const auto &pkgId = wanted.at(i); - pkgLoader.load(wanted.at(i)); + if (pkgLoader.isAvailable(pkgId)) + { + LOG_RES_MSG("Loading wanted ") << wanted.at(i); + pkgLoader.load(wanted.at(i)); + } + else + { + auto id_ver = Package::split(pkgId); + LOG_RES_MSG("Loading latest version of wanted ") << id_ver.first; + pkgLoader.load(id_ver.first); + } } - qDebug() << DoomsdayApp::loadedPackagesAffectingGameplay(); + LOG_RES_MSG("Packages affecting gameplay:\n") + << String::join(DoomsdayApp::loadedPackagesAffectingGameplay(), "\n"); self().buttonsMenu().disable(); updating->setOpacity(1, 0.3); @@ -212,7 +342,7 @@ : MessageDialog(name) , d(new Impl(this)) { - title().setText(tr("Incompatible Add-ons")); + title().setText(tr("Incompatible Mods")); } void PackageCompatibilityDialog::setMessage(String const &msg) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packageinfodialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packageinfodialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packageinfodialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packageinfodialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -38,44 +38,50 @@ #include #include #include +#include #include #include #include #include +#include + using namespace de; DENG_GUI_PIMPL(PackageInfoDialog) { - LabelWidget *title; - LabelWidget *path; - DocumentWidget *description; - LabelWidget *icon; - LabelWidget *metaInfo; - IndirectRule *targetHeight; - IndirectRule *descriptionWidth; - IndirectRule *minContentHeight; - String packageId; - String compatibleGame; // guessed - NativePath nativePath; - SafeWidgetPtr configurePopup; + Mode mode; + LabelWidget * title; + LabelWidget * path; + DocumentWidget * description; + LabelWidget * icon; + LabelWidget * metaInfo; + IndirectRule * targetHeight; + IndirectRule * descriptionWidth; + IndirectRule * minContentHeight; + String packageId; + String compatibleGame; // guessed + NativePath nativePath; + const DataBundle * bundle = nullptr; + SafeWidgetPtr configurePopup; SafeWidgetPtr profileMenu; enum MenuMode { AddToProfile, PlayInProfile }; MenuMode menuMode; - Impl(Public *i) : Base(i) + Impl(Public * i, Mode mode) + : Base(i) + , mode(mode) { targetHeight = new IndirectRule; descriptionWidth = new IndirectRule; minContentHeight = new IndirectRule; - self().useInfoStyle(); + //self().useInfoStyle(); // The Close button is always available. Other actions are shown depending // on what kind of package is being displayed. - self().buttons() - << new DialogButtonItem(Default | Accept, tr("Close")); + self().buttons() << new DialogButtonItem(Default | Accept, tr("Close")); createWidgets(); } @@ -95,13 +101,13 @@ title = LabelWidget::newWithText("", &area); title->setFont("title"); title->setSizePolicy(ui::Filled, ui::Expand); - title->setTextColor("inverted.accent"); + title->setTextColor("accent"); title->setTextLineAlignment(ui::AlignLeft); title->margins().setBottom(""); path = LabelWidget::newWithText("", &area); path->setSizePolicy(ui::Filled, ui::Expand); - path->setTextColor("inverted.text"); + path->setTextColor("text"); path->setTextLineAlignment(ui::AlignLeft); path->margins().setTop("unit"); @@ -109,37 +115,42 @@ description = new DocumentWidget; description->setFont("small"); + + // Light-on-dark document. + description->setStyleColor(Font::RichFormat::NormalColor, "label.dimmed"); + description->setStyleColor(Font::RichFormat::HighlightColor, "label.highlight"); + description->setStyleColor(Font::RichFormat::DimmedColor, "label.dimmed"); + description->setStyleColor(Font::RichFormat::AccentColor, "label.accent"); + description->setStyleColor(Font::RichFormat::DimAccentColor, "label.dimaccent"); + description->progress().setColor("progress.light.wheel"); + description->progress().setShadowColor("progress.light.shadow"); + description->setWidthPolicy(ui::Fixed); - description->rule().setInput(Rule::Height, contentHeight - title->rule().height() - - path->rule().height()); + description->rule().setInput( + Rule::Height, contentHeight - title->rule().height() - path->rule().height()); area.add(description); - SequentialLayout layout(area.contentRule().left(), - area.contentRule().top(), - ui::Down); + SequentialLayout layout(area.contentRule().left(), area.contentRule().top(), ui::Down); layout.setOverrideWidth(*descriptionWidth); - layout << *title - << *path - << *description; + layout << *title << *path << *description; // Right column. icon = LabelWidget::newWithText("", &area); - icon->setSizePolicy(ui::Filled, ui::Filled); + icon->setSizePolicy(ui::Filled, ui::Expand); //icon->setImageFit(ui::FitToSize | ui::OriginalAspectRatio); //icon->setStyleImage("package.large"); //icon->setImageColor(style().colors().colorf("inverted.accent")); - icon->rule().setInput(Rule::Height, rule("dialog.packageinfo.icon.height")); + //icon->rule().setInput(Rule::Height, rule("dialog.packageinfo.icon.height")); metaInfo = LabelWidget::newWithText("", &area); metaInfo->setSizePolicy(ui::Filled, ui::Expand); metaInfo->setTextLineAlignment(ui::AlignLeft); metaInfo->setFont("small"); - metaInfo->setTextColor("inverted.altaccent"); + metaInfo->setTextColor("altaccent"); SequentialLayout rightLayout(title->rule().right(), title->rule().top(), ui::Down); rightLayout.setOverrideWidth(rule("dialog.packageinfo.metadata.width")); - rightLayout << *icon - << *metaInfo; + rightLayout << *icon << *metaInfo; targetHeight->setSource(rightLayout.height()); area.setContentSize(layout.width() + rightLayout.width(), contentHeight); @@ -154,9 +165,10 @@ icon->setBehavior(ContentClipping, true); } - bool useGameTitlePicture(DataBundle const &bundle) + bool useGameTitlePicture() { - auto *lumpDir = bundle.lumpDirectory(); + DENG_ASSERT(bundle != nullptr); + auto *lumpDir = bundle->lumpDirectory(); if (!lumpDir || (!lumpDir->has("TITLEPIC") && !lumpDir->has("TITLE"))) { return false; @@ -165,11 +177,9 @@ Game const &game = Games::get()[compatibleGame]; res::LumpCatalog catalog; - catalog.setPackages(game.requiredPackages() + StringList({ packageId })); - Image img = IdTech1Image::makeGameLogo(game, - catalog, - IdTech1Image::NullImageIfFails | - IdTech1Image::UnmodifiedAppearance); + catalog.setPackages(game.requiredPackages() + StringList({packageId})); + Image img = IdTech1Image::makeGameLogo( + game, catalog, IdTech1Image::NullImageIfFails | IdTech1Image::UnmodifiedAppearance); if (!img.isNull()) { setPackageIcon(img); @@ -181,19 +191,18 @@ void useDefaultIcon() { icon->setStyleImage("package.large"); - icon->setImageColor(style().colors().colorf("inverted.altaccent")); + icon->setImageColor(style().colors().colorf("altaccent")); icon->setImageFit(ui::FitToSize | ui::OriginalAspectRatio); //icon->setImageScale(.75f); icon->setOpacity(.5f); icon->setBehavior(ContentClipping, false); } - void useIconFile(String const &packagePath) + bool useIconFromPackage(const String &packagePath) { try { - static StringList const imageExts({ ".jpg", ".jpeg", ".png" }); - foreach (String ext, imageExts) + for (const auto *ext : {".jpg", ".jpeg", ".png"}) { String const imgPath = packagePath / "icon" + ext; if (ImageFile const *img = FS::tryLocate(imgPath)) @@ -202,10 +211,11 @@ if (iconImage.width() > 512 || iconImage.height() > 512) { throw Error("PackageInfoDialog::useIconFile", - "Icon file " + img->description() + " is too large (max 512x512)"); + "Icon file " + img->description() + + " is too large (max 512x512)"); } setPackageIcon(iconImage); - return; + return true; } } } @@ -213,11 +223,21 @@ { LOG_RES_WARNING("Failed to use package icon image: %s") << er.asText(); } - useDefaultIcon(); + return false; + } + + void useIconFile(String const &packagePath) + { + if (!useIconFromPackage(packagePath)) + { + useDefaultIcon(); + } } bool setup(File const *file) { + self().setOutlineColor("popup.outline"); + if (!file) return false; // Not a package? // Look up the package metadata. @@ -228,26 +248,34 @@ } Record const &meta = names.subrecord(Package::VAR_PACKAGE); - packageId = Package::versionedIdentifierForFile(*file); - nativePath = file->correspondingNativePath(); + packageId = Package::versionedIdentifierForFile(*file); + nativePath = file->correspondingNativePath(); String fileDesc = file->source()->description(); + String lumpDirCrc32; String format; - DataBundle const *bundle = maybeAs(file->target()); + bundle = maybeAs(file->target()); if (bundle) { format = bundle->formatAsText().upperFirstChar(); compatibleGame = bundle->guessCompatibleGame(); - if (!useGameTitlePicture(*bundle)) + if (!useIconFromPackage(file->path())) { - useDefaultIcon(); + if (!useGameTitlePicture()) + { + useDefaultIcon(); + } } if (bundle->format() == DataBundle::Collection) { fileDesc = file->target().description(); } + else if (bundle->format() == DataBundle::Iwad || bundle->format() == DataBundle::Pwad) + { + lumpDirCrc32 = String::format("%08x", bundle->lumpDirectory()->crc32()); + } } else { @@ -262,27 +290,24 @@ } title->setText(meta.gets(Package::VAR_TITLE)); - path->setText(String(_E(b) "%1" _E(.) "\n%2") - .arg(format) - .arg(fileDesc.upperFirstChar())); + path->setText(String(_E(b) "%1" _E(.) "\n%2").arg(format).arg(fileDesc.upperFirstChar())); // Metadata. - String metaMsg = String(_E(Ta)_E(l) "Version: " _E(.)_E(Tb) "%1\n" - _E(Ta)_E(l) "Tags: " _E(.)_E(Tb) "%2\n" - _E(Ta)_E(l) "License: " _E(.)_E(Tb) "%3") + String metaMsg = + String(_E(Ta) _E(l) "Version: " _E(.) _E(Tb) "%1\n" _E(Ta) _E(l) "Tags: " _E(.) + _E(Tb) "%2\n" _E(Ta) _E(l) "License: " _E(.) _E(Tb) "%3") .arg(meta.gets("version")) .arg(meta.gets("tags")) .arg(meta.gets("license")); if (meta.has("author")) { - metaMsg += String("\n" _E(Ta)_E(l) "Author: " - _E(.)_E(Tb) "%1").arg(meta.gets("author")); - + metaMsg += + String("\n" _E(Ta) _E(l) "Author: " _E(.) _E(Tb) "%1").arg(meta.gets("author")); } if (meta.has("contact")) { - metaMsg += String("\n" _E(Ta)_E(l) "Contact: " - _E(.)_E(Tb) "%1").arg(meta.gets("contact")); + metaMsg += + String("\n" _E(Ta) _E(l) "Contact: " _E(.) _E(Tb) "%1").arg(meta.gets("contact")); } metaInfo->setText(metaMsg); @@ -290,32 +315,41 @@ String msg; // Start with a generic description of the package format. - - if (compatibleGame.isEmpty()) { QRegularExpression reg(DataBundle::anyGameTagPattern()); if (!reg.match(meta.gets("tags")).hasMatch()) { - msg = "Not enough information to determine which game this package is for."; + msg += "Not enough information to determine which game this package is for."; } } else { - msg = String("This package is likely meant for " _E(b) "%1" _E(.) ".") + msg += String("This package is likely meant for " _E(b) "%1" _E(.) ".") .arg(compatibleGame); } + String moreMsg; + { if (bundle && bundle->lumpDirectory() && bundle->lumpDirectory()->mapType() != res::LumpDirectory::None) { int const mapCount = bundle->lumpDirectory()->findMaps().count(); - msg += QString("\n\nContains %1 map%2: ") - .arg(mapCount) - .arg(DENG2_PLURAL_S(mapCount)) + + moreMsg += + QString("Contains %1 map%2: ").arg(mapCount).arg(DENG2_PLURAL_S(mapCount)) + String::join(bundle->lumpDirectory()->mapsInContiguousRangesAsText(), ", "); + moreMsg += "\n"; + } + + if (lumpDirCrc32) + { + moreMsg += "WAD directory CRC32: " _E(m) + lumpDirCrc32 + _E(.) "\n"; + } + moreMsg += "Package ID: " _E(>) + meta.gets(Package::VAR_ID) + _E(<) "\n"; } + msg += "\n\n" + moreMsg.strip(); + if (meta.has("notes")) { msg += "\n\n" + meta.gets("notes") + _E(r); @@ -346,6 +380,8 @@ description->setText(msg.trimmed()); // Show applicable package actions. + if (mode == EnableActions) + { self().buttons() << new DialogButtonItem(Action | Id2, style().images().image("play"), @@ -355,18 +391,16 @@ style().images().image("create"), tr("Add to..."), new SignalAction(thisPublic, SLOT(addToProfile()))); - + } if (!nativePath.isEmpty()) { - self().buttons() - << new DialogButtonItem(Action, - tr("Show File"), - new SignalAction(thisPublic, SLOT(showFile()))); + self().buttons() << new DialogButtonItem( + Action, tr("Show File"), new SignalAction(thisPublic, SLOT(showFile()))); } - if (Package::hasOptionalContent(*file)) + if (mode == EnableActions && Package::hasOptionalContent(*file)) { - self().buttons() - << new DialogButtonItem(Action | Id1, + self().buttons() << new DialogButtonItem( + Action | Id1, style().images().image("gear"), tr("Options"), new SignalAction(thisPublic, SLOT(configure()))); @@ -397,7 +431,7 @@ QList profs = DoomsdayApp::gameProfiles().profilesSortedByFamily(); - auto &items = profileMenu->items(); + auto & items = profileMenu->items(); String lastFamily; for (GameProfile *prof : profs) { @@ -419,7 +453,7 @@ if (prof->packages().contains(packageId)) { color = _E(C); - label += " " _E(s)_E(b)_E(D) + tr("ADDED"); + label += " " _E(s) _E(b) _E(D) + tr("ADDED"); } if (!compatibleGame.isEmpty() && prof->gameId() == compatibleGame) { @@ -431,28 +465,63 @@ } label = color + label; - items << new ui::ActionItem(label, new CallbackAction([this, prof] () - { - profileSelectedFromMenu(*prof); - })); + items << new ui::ActionItem( + label, new CallbackAction([this, prof]() { profileSelectedFromMenu(*prof); })); } self().add(profileMenu); profileMenu->open(); } - void profileSelectedFromMenu(GameProfile &profile) + void profileSelectedFromMenu(GameProfile & profile) { switch (menuMode) { - case AddToProfile: - profile.appendPackage(packageId); - break; + case AddToProfile: profile.appendPackage(packageId); break; - case PlayInProfile: { + case PlayInProfile: + { auto &prof = DoomsdayApp::app().adhocProfile(); - prof = profile; + prof = profile; prof.appendPackage(packageId); + + // Generate an Episode definition if the package contains a single map. + if (bundle && bundle->format() == DataBundle::Pwad) + { + const auto mapIds = bundle->lumpDirectory()->findMapLumpNames(); + if (mapIds.size() == 1) + { + using namespace std; + + ostringstream os; + os << "# Episode definition for Ad-hoc profile (autogenerated)\n" + "Episode {\n" + " ID = \"adhoc_play_in\"\n" + " Title = \"" + << bundle->packageMetadata() + .gets(Package::VAR_TITLE) + .escaped() + .toStdString() + << "\"\n" + " Start Map = \"" + << mapIds.front().toStdString() + << "\"\n" + " Map {\n" + " ID = \"" + << mapIds.front().toStdString() + << "\"\n" + " Warp Number = 1\n" + " }\n" + "}\n"; + + File &f = App::homeFolder().replaceFile("AdhocPlayInEpisode_1.0.ded"); + f << Block(os.str().c_str()); + f.reinterpret(); + App::homeFolder().populate(); + prof.appendPackage("file.ded.adhocplayinepisode_1.0.0"); + } + } + Loop::timer(0.1, [] { // Switch the game. GLWindow::main().glActivate(); @@ -461,14 +530,15 @@ DD_ActivateGameWorker); }); self().accept(); - break; } + break; + } } } }; -PackageInfoDialog::PackageInfoDialog(String const &packageId) +PackageInfoDialog::PackageInfoDialog(String const &packageId, Mode mode) : DialogWidget("packagepopup") - , d(new Impl(this)) + , d(new Impl(this, mode)) { if (!d->setup(App::packageLoader().select(packageId))) { @@ -476,9 +546,9 @@ } } -PackageInfoDialog::PackageInfoDialog(File const *packageFile) +PackageInfoDialog::PackageInfoDialog(File const *packageFile, Mode mode) : DialogWidget("packagepopup") - , d(new Impl(this)) + , d(new Impl(this, mode)) { if (!d->setup(packageFile)) { @@ -497,13 +567,11 @@ // Update the width of the dialog. Don't let it get wider than the window. d->descriptionWidth->setSource(OperatorRule::minimum( - useWideLayout? - rule("dialog.packageinfo.description.wide") + useWideLayout ? rule("dialog.packageinfo.description.wide") : rule("dialog.packageinfo.description.normal"), - root().viewWidth() - margins().width() - - d->metaInfo->rule().width())); + root().viewWidth() - margins().width() - d->metaInfo->rule().width())); - d->minContentHeight->setSource(useWideLayout? rule("dialog.packageinfo.content.minheight") + d->minContentHeight->setSource(useWideLayout ? rule("dialog.packageinfo.content.minheight") : ConstantRule::zero()); } @@ -527,10 +595,7 @@ d->packageId, rule("dialog.packages.left.width"), root().viewHeight()); d->configurePopup.reset(pop); pop->setAnchorAndOpeningDirection(buttonWidget(Id1)->rule(), ui::Left); - pop->closeButton().setActionFn([pop] () - { - pop->close(); - }); + pop->closeButton().setActionFn([pop]() { pop->close(); }); add(pop); pop->open(); @@ -541,6 +606,6 @@ if (!d->nativePath.isEmpty()) { QDesktopServices::openUrl(QUrl::fromLocalFile( - d->nativePath.isDirectory()? d->nativePath : d->nativePath.fileNamePath())); + d->nativePath.isDirectory() ? d->nativePath : d->nativePath.fileNamePath())); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/packagesdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -21,6 +21,7 @@ #include "ui/widgets/homeitemwidget.h" #include "ui/widgets/homemenuwidget.h" #include "ui/dialogs/packageinfodialog.h" +#include "ui/dialogs/datafilesettingsdialog.h" #include "resource/idtech1image.h" #include "ui/clientwindow.h" #include "ui/clientstyle.h" @@ -28,9 +29,12 @@ #include #include +#include +#include #include #include +#include #include #include #include @@ -49,7 +53,6 @@ , public PackagesWidget::IPackageStatus , DENG2_OBSERVES(Widget, ChildAddition) { - StringList requiredPackages; // loaded first, cannot be changed StringList selectedPackages; LabelWidget *nothingSelected; ui::ListData actions; @@ -57,25 +60,35 @@ PackagesWidget *browser; LabelWidget *gameTitle; LabelWidget *gameDataFiles; - Game const *game = nullptr; + const GameProfile *gameProfile = nullptr; res::LumpCatalog catalog; /** * Information about a selected package. If the package file is not found, only * the ID is known. */ - class SelectedPackageItem : public ui::Item + class SelectedPackageItem + : public ui::Item + , DENG2_OBSERVES(res::Bundles, Identify) { public: SelectedPackageItem(String const &packageId) { setData(packageId); + updatePackageInfo(); + DoomsdayApp::bundles().audienceForIdentify() += this; + } - _file = App::packageLoader().select(packageId); - if (_file) + void updatePackageInfo() + { + if ((_file = App::packageLoader().select(packageId())) != nullptr) { _info = &_file->objectNamespace().subrecord(Package::VAR_PACKAGE); } + else + { + _info = nullptr; + } } String packageId() const @@ -93,6 +106,14 @@ return _file; } + void dataBundlesIdentified() override + { + Loop::mainCall([this]() { + updatePackageInfo(); + notifyChange(); + }); + } + private: File const *_file = nullptr; Record const *_info = nullptr; @@ -141,7 +162,8 @@ } else { - label().setText(_item->packageId()); + label().setText(Package::splitToHumanReadable(_item->packageId()) + + " " _E(D) DENG2_CHAR_MDASH " Missing"); } } @@ -152,7 +174,7 @@ PopupWidget *makeInfoPopup() const { - return new PackageInfoDialog(_item->packageFile()); + return new PackageInfoDialog(_item->packageFile(), PackageInfoDialog::EnableActions); } private: @@ -169,7 +191,7 @@ // Indicator that is only visible when no packages have been added to the profile. nothingSelected = new LabelWidget; - nothingSelected->setText(tr("No Packages Selected")); + nothingSelected->setText(tr("No Mods Selected")); style().as().emptyMenuLabelStylist().applyStyle(*nothingSelected); nothingSelected->rule() .setRect(self().leftArea().rule()) @@ -222,7 +244,7 @@ actions << new ui::SubwidgetItem(tr("..."), ui::Up, [this] () -> PopupWidget * { String const id = browser->actionPackage(); - return new PackageInfoDialog(id); + return new PackageInfoDialog(id, PackageInfoDialog::EnableActions); }); // Action for (de)selecting the package. @@ -277,29 +299,40 @@ void updateGameTitle() { - if (game && catalog.setPackages(requiredPackages + selectedPackages)) + if (gameProfile && catalog.setPackages(gameProfile->allRequiredPackages() + selectedPackages)) { - gameTitle->setImage(IdTech1Image::makeGameLogo(*game, catalog, - IdTech1Image::UnmodifiedAppearance)); + gameTitle->setImage(IdTech1Image::makeGameLogo(gameProfile->game(), catalog, + IdTech1Image::UnmodifiedAppearance | + IdTech1Image::AlwaysTryLoad)); // List of the native required files. StringList dataFiles; - for (String packageId : requiredPackages) - { - if (File const *file = App::packageLoader().select(packageId)) +// if (gameProfile->customDataFile()) +// { +// if (const auto *file = PackageLoader::get().select(gameProfile->customDataFile())) +// { +// dataFiles << file->source()->description(0); +// } +// } +// else +// { + for (String packageId : gameProfile->allRequiredPackages()) { - // Only list here the game data files; Doomsday's PK3s are always - // there so listing them is not very helpful. - if (Package::matchTags(*file, QStringLiteral("\\bgamedata\\b"))) + if (const File *file = PackageLoader::get().select(packageId)) { - // Resolve indirection (symbolic links and interpretations) to - // describe the actual source file of the package. - dataFiles << file->source()->description(0); + // Only list here the game data files; Doomsday's PK3s are always + // there so listing them is not very helpful. + if (Package::matchTags(*file, QStringLiteral("\\bgamedata\\b"))) + { + // Resolve indirection (symbolic links and interpretations) to + // describe the actual source file of the package. + dataFiles << file->source()->description(0); + } } } - } +// } if (!dataFiles.isEmpty()) { - gameDataFiles->setText(_E(l) + String::format("Data file%s: ", dataFiles.size() != 1? "s" : "") + + gameDataFiles->setText(_E(l) + String::format("Game data file%s: ", dataFiles.size() != 1? "s" : "") + _E(.) + String::join(dataFiles, _E(l) " and " _E(.))); } else @@ -309,12 +342,12 @@ } } - GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) + GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) override { return new SelectedPackageWidget(item.as(), self()); } - void updateItemWidget(GuiWidget &widget, ui::Item const &) + void updateItemWidget(GuiWidget &widget, ui::Item const &) override { widget.as().updateContents(); } @@ -334,7 +367,7 @@ updateGameTitle(); } - void widgetChildAdded(Widget &child) + void widgetChildAdded(Widget &child) override { ui::DataPos pos = menu->findItem(child.as()); // We use a delay here because ScrollAreaWidget does scrolling based on @@ -353,7 +386,7 @@ { if (titleText.isEmpty()) { - heading().setText(tr("Packages")); + heading().setText(tr("Mods")); } else { @@ -364,25 +397,37 @@ << new DialogButtonItem(Default | Accept, tr("OK")) << new DialogButtonItem(Reject, tr("Cancel")) << new DialogButtonItem(Action, style().images().image("refresh"), - new SignalAction(this, SLOT(refreshPackages()))); + new CallbackAction([]() { FS::get().refreshAsync(); })) + << new DialogButtonItem(Action | Id1, style().images().image("gear"), + "Data Files", + new CallbackAction([this]() { + // Open a Data Files dialog. + auto *dfsDlg = new DataFileSettingsDialog; + dfsDlg->setAnchorAndOpeningDirection(buttonWidget(Id1)->rule(), ui::Up); + dfsDlg->setDeleteAfterDismissed(true); + add(dfsDlg); + dfsDlg->open(); + })); // The individual menus will be scrolling independently. leftArea() .setContentSize(d->menu->rule().width(), OperatorRule::maximum(d->menu->rule().height(), - d->nothingSelected->rule().height()) + + d->nothingSelected->rule().height(), + rule("dialog.packages.left.minheight")) + d->gameTitle->rule().height()); - rightArea().setContentSize(d->browser->rule().width(), d->browser->rule().height()); + rightArea().setContentSize(d->browser->rule()); d->browser->progress().rule().setRect(rightArea().rule()); + setMaximumContentHeight(rule().width() * 0.9f); + // Setup has been completed, so contents can be updated. - //d->browser->setPopulationEnabled(true); - refreshPackages(); + d->browser->setPopulationEnabled(true); } -void PackagesDialog::setGame(String const &gameId) +void PackagesDialog::setProfile(const GameProfile &profile) { - d->game = &DoomsdayApp::games()[gameId]; - d->requiredPackages = d->game->requiredPackages(); + d->gameProfile = &profile; + //d->requiredPackages = d->game->requiredPackages(); d->updateGameTitle(); } @@ -398,10 +443,10 @@ return d->selectedPackages; } -void PackagesDialog::refreshPackages() -{ - d->browser->refreshPackages(); -} +//void PackagesDialog::refreshPackages() +//{ +// d->browser->refreshPackages(); +//} void PackagesDialog::preparePanelForOpening() { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/renderersettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/renderersettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/renderersettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/renderersettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -50,9 +50,6 @@ VariableToggleWidget *disableExtPatches; CVarToggleWidget *precacheModels; CVarToggleWidget *precacheSprites; - CVarToggleWidget *multiLight; - CVarToggleWidget *multiShiny; - CVarToggleWidget *multiDetail; // Developer settings. GridPopupWidget *devPopup; @@ -92,16 +89,10 @@ precacheModels = new CVarToggleWidget("rend-model-precache", tr("3D Models")); precacheSprites = new CVarToggleWidget("rend-sprite-precache", tr("Sprites")); - multiLight = new CVarToggleWidget("rend-light-multitex", tr("Dynamic Lights")); - multiShiny = new CVarToggleWidget("rend-model-shiny-multitex", tr("3D Model Shiny Surfaces")); - multiDetail = new CVarToggleWidget("rend-tex-detail-multitex", tr("Surface Details")); devPopup->addSeparatorLabel(tr("Behavior")); *devPopup << LabelWidget::newWithText(tr("Precaching:")) << precacheModels - << Const(0) << precacheSprites - << LabelWidget::newWithText(tr("Multitexturing:")) << multiLight - << Const(0) << multiShiny - << Const(0) << multiDetail; + << Const(0) << precacheSprites; devPopup->addSeparatorLabel(tr("Diagnosis")); *devPopup << LabelWidget::newWithText(tr("Surface Texturing:")) @@ -176,17 +167,18 @@ } // Textures options. - LabelWidget *texturesLabel = LabelWidget::newWithText(_E(D) + tr("Textures"), &area()); - texturesLabel->setFont("separator.label"); - texturesLabel->margins().setTop("gap"); - layout.setCellAlignment(Vector2i(0, layout.gridSize().y), ui::AlignLeft); - layout.append(*texturesLabel, 2); +// LabelWidget *texturesLabel = LabelWidget::newWithText(_E(D) + tr("Textures"), &area()); +// texturesLabel->setFont("separator.label"); +// texturesLabel->margins().setTop("gap"); +// layout.setCellAlignment(Vector2i(0, layout.gridSize().y), ui::AlignLeft); +// layout.append(*texturesLabel, 2); + LabelWidget::appendSeparatorWithText("Textures", &area(), &layout); layout << *LabelWidget::newWithText(tr("External Images:"), &area()) << *d->enableExtWithPWADs << Const(0) << *d->disableExtTextures << Const(0) << *d->disableExtPatches; - area().setContentSize(layout.width(), layout.height()); + area().setContentSize(layout); buttons() << new DialogButtonItem(DialogWidget::Default | DialogWidget::Accept, tr("Close")) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/repositorybrowserdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/repositorybrowserdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/repositorybrowserdialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/repositorybrowserdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,424 @@ +/** @file repositorybrowserdialog.cpp Remote package repository browser. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "ui/dialogs/repositorybrowserdialog.h" +#include "ui/widgets/homemenuwidget.h" +#include "ui/widgets/homeitemwidget.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace de; + +static String const VAR_RESOURCE_BROWSER_REPOSITORY("resource.browserRepository"); +static String const ALL_CATEGORIES(QObject::tr("All Categories")); + +DENG_GUI_PIMPL(RepositoryBrowserDialog) +, DENG2_OBSERVES(filesys::RemoteFeedRelay, Status) +, public ChildWidgetOrganizer::IWidgetFactory +, public AsyncScope +{ + using RFRelay = filesys::RemoteFeedRelay; + + ui::ListData categoryData; + std::shared_ptr data; + std::unique_ptr shownData; + std::unique_ptr populating; + Lockable linkBusy; + + ProgressWidget *refreshProgress; + ChoiceWidget *repo; + LineEditWidget *search; + MenuWidget *category; + LabelWidget *statusText; + HomeMenuWidget *nameList; + DocumentWidget *description; + String connectedRepository; + String mountPath; + QSet filterTerms; + + Impl(Public *i) : Base(i) + { + auto &area = self().area(); + + // The dialog contains scrollable widgets. + area.enableScrolling(false); + area.enableIndicatorDraw(false); + area.enablePageKeys(false); + + self().add(refreshProgress = new ProgressWidget); + + refreshProgress->useMiniStyle(); + refreshProgress->setOpacity(0); + refreshProgress->setColor("altaccent"); + refreshProgress->setTextColor("altaccent"); + refreshProgress->setText(tr("Loading...")); + refreshProgress->setTextAlignment(ui::AlignLeft); + refreshProgress->setSizePolicy(ui::Expand, ui::Expand); + + area.add(statusText = new LabelWidget); + area.add(repo = new ChoiceWidget); + area.add(search = new LineEditWidget); + area.add(category = new MenuWidget); + area.add(nameList = new HomeMenuWidget); + area.add(description = new DocumentWidget); + + //statusText->setFont("small"); + statusText->setTextColor("altaccent"); + + // Insert known repositories. + try + { + auto &repos = Config::get().getdt("resource.repositories"); + for (auto i = repos.elements().begin(); i != repos.elements().end(); ++i) + { + repo->items() + << new ChoiceItem(i->first.value->asText(), i->second->asText()); + } + repo->setSelected(repo->items().findLabel(App::config().gets(VAR_RESOURCE_BROWSER_REPOSITORY, ""))); + } + catch (Error const &er) + { + LOG_MSG("Remote repositories not listed in configuration; " + "set Config.resource.repositories: %s") + << er.asText(); + } + + category->setItems(categoryData); + category->setGridSize(0, ui::Expand, 1, ui::Expand, GridLayout::RowFirst); + category->organizer().setWidgetFactory(*this); + + nameList->setVirtualizationEnabled(true, style().fonts().font("default").height().valuei() + + rule("unit").valuei() * 2); + nameList->organizer().setWidgetFactory(*this); + nameList->enableScrolling(true); + nameList->enablePageKeys(true); + nameList->enableIndicatorDraw(true); + nameList->setGridSize(1, ui::Filled, 0, ui::Fixed); + nameList->layout().setRowPadding(Const(0)); + nameList->setBehavior(ChildVisibilityClipping); + + QObject::connect(repo, &ChoiceWidget::selectionChangedByUser, [this] (uint) + { + updateSelectedRepository(); + }); + QObject::connect(search, &LineEditWidget::editorContentChanged, [this] () + { + updateFilter(); + }); + RFRelay::get().audienceForStatus() += this; + + updateSelectedRepository(); + } + + ~Impl() + { + if (populating) populating->waitForFinished(); + disconnect(); + } + + bool filterItem(ui::Item const &item) const + { + if (filterTerms.isEmpty()) return true; + + DotPath const path(item.label()); + for (String const &term : filterTerms) + { + bool matched = false; + for (int i = 0; i < path.segmentCount(); ++i) + { + if (path.segment(i).toStringRef().contains(term)) + { + matched = true; + break; + } + } + if (!matched) return false; + } + return true; + } + + void updateFilter() + { + const auto oldTerms = filterTerms; + filterTerms.clear(); + foreach (String term, search->text().split(' ')) + { + if (auto cleaned = term.strip()) + { + filterTerms.insert(cleaned.toLower()); + } + } + if (oldTerms != filterTerms && shownData) + { + shownData->refilter(); + shownData->stableSort([] (ui::Item const &a, ui::Item const &b) + { + return a.label().compare(b.label()) < 0; + }); + updateStatusText(); + } + } + + GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *parent) override + { + if (parent == category) + { + auto *toggle = new ToggleWidget(ToggleWidget::WithoutIndicator); + QObject::connect(toggle, &ToggleWidget::stateChanged, + [toggle, &item] (ToggleWidget::ToggleState state) + { + toggle->setColorTheme(state == ToggleWidget::Active? Inverted : Normal); + }); + if (item.label() == ALL_CATEGORIES) + { + toggle->setToggleState(ToggleWidget::Active); + } + return toggle; + } + return new HomeItemWidget(HomeItemWidget::NonAnimatedHeight | + HomeItemWidget::WithoutIcon); + } + + void updateItemWidget(GuiWidget &widget, ui::Item const &item) override + { + if (widget.parentGuiWidget() == category) + { + auto &catButton = widget.as(); + catButton.setText(item.label()); + catButton.setSizePolicy(ui::Expand, ui::Expand); + catButton.margins().set("dialog.gap"); + } + else + { + auto &w = widget.as(); + w.useColorTheme(Normal, Inverted); + w.label().margins().set("unit"); + w.label().setText(item.label().fileName('.')); + //label.setSizePolicy(ui::Expand, ui::Expand); + //label.margins().set("unit"); + //label.set(Background()); + } + } + + void updateSelectedRepository() + { + if (repo->isValidSelection()) + { + auto const &selItem = repo->selectedItem(); + App::config().set(VAR_RESOURCE_BROWSER_REPOSITORY, selItem.label()); + connect(selItem.data().toString()); + } + } + + void connect(String address) + { + refreshProgress->setOpacity(1, 0.5); + repo->disable(); + + // Disconnecting may involve waiting for an operation to finish first, so + // we'll do it async. + *this += async([this] () + { + disconnect(); + return 0; + }, + [this, address] (int) + { + QUrl const url(address); + RFRelay::get().addRepository(address, "/remote" / url.host()); + connectedRepository = address; + }); + } + + void remoteRepositoryStatusChanged(String const &repository, RFRelay::Status status) override + { + if (repository == connectedRepository) + { + repo->enable(); + refreshProgress->setOpacity(0, 0.5); + + if (status == RFRelay::Connected) + { + populateAsync(); + } + else + { + disconnect(); + } + } + } + + void disconnect() + { + populating.reset(); + if (connectedRepository) + { + DENG2_GUARD(linkBusy); + mountPath.clear(); + connectedRepository.clear(); + RFRelay::get().removeRepository(connectedRepository); + } + } + + filesys::Link &link() + { + auto *link = RFRelay::get().repository(connectedRepository); + DENG2_ASSERT(link); + return *link; + } + + void populateAsync() + { + // If there is a previous task, it will finish but completion will not be called. + populating.reset(new AsyncScope); + + *populating += async([this] () + { + DENG2_GUARD(linkBusy); + // All packages from the remote repository are inserted to the data model. + std::shared_ptr pkgs(new ui::ListData); + link().forPackageIds([&pkgs] (String const &id) + { + pkgs->append(new ui::Item(ui::Item::DefaultSemantics, id)); + return LoopContinue; + }); + return pkgs; + }, + [this] (std::shared_ptr pkgs) + { + setData(pkgs); + }); + } + + void setData(std::shared_ptr newData) + { + DENG2_ASSERT_IN_MAIN_THREAD(); + //qDebug() << "got new data with" << newData->size() << "items"; + + nameList->useDefaultItems(); + shownData.reset(new ui::FilteredData(*newData)); + shownData->setFilter([this] (ui::Item const &i) { return filterItem(i); }); + data = newData; + shownData->sort(); + nameList->setItems(*shownData); + + categoryData.clear(); + categoryData.append(new ui::Item(ui::Item::ShownAsButton, ALL_CATEGORIES)); + StringList tags = link().categoryTags(); + qSort(tags); + foreach (String category, tags) + { + categoryData.append(new ui::Item(ui::Item::ShownAsButton, category)); + } + + updateStatusText(); + + repo->enable(); + refreshProgress->setOpacity(0, 0.5); + } + + void updateStatusText() + { + statusText->setText(tr("showing %1 out of %2 mods").arg(shownData->size()).arg(data->size())); + } +}; + +RepositoryBrowserDialog::RepositoryBrowserDialog() + : DialogWidget("repository-browser", WithHeading) + , d(new Impl(this)) +{ + heading().setText(tr("Install Mods")); + heading().setStyleImage("package.icon", heading().fontId()); + + AutoRef nameListWidth(new ConstantRule(2*175)); + AutoRef descriptionWidth(new ConstantRule(2*525)); + AutoRef listHeight(new ConstantRule(2*325)); + + auto &acRule = area().contentRule(); + + auto *searchLabel = LabelWidget::newWithText(tr("Search:"), &area()); + auto *repoLabel = LabelWidget::newWithText(tr("Repository:"), &area()); + + { + SequentialLayout layout(acRule.left(), + acRule.top(), + ui::Right); + layout << *searchLabel << *d->search << *repoLabel << *d->repo; + + d->search->rule().setInput(Rule::Width, + acRule.width() - + searchLabel->rule().width() - + repoLabel->rule().width() - + d->repo->rule().width()); + } + + d->category->rule() + .setInput(Rule::Left, acRule.left()) + .setInput(Rule::Top, d->search->rule().bottom()); + + d->statusText->rule() + .setInput(Rule::Right, acRule.right()) + .setInput(Rule::Top, d->category->rule().top()) + .setInput(Rule::Height, d->category->rule().height()); + + d->nameList->rule() + .setSize(nameListWidth, listHeight) + .setInput(Rule::Left, acRule.left()) + .setInput(Rule::Top, d->category->rule().bottom()); + + d->description->rule() + .setSize(descriptionWidth, listHeight) + .setInput(Rule::Left, d->nameList->rule().right()) + .setInput(Rule::Top, d->nameList->rule().top()); + + area().setContentSize(nameListWidth + descriptionWidth, + d->search->rule().height() + d->category->rule().height() + + listHeight); + + d->refreshProgress->rule() + .setInput(Rule::Right, rule().right() - area().margins().right()) + .setInput(Rule::Top, rule().top() + area().margins().top()); + + buttons() << new DialogButtonItem(Default | Accept, tr("Close")) + << new DialogButtonItem(Action | Id1, tr("Download & Install")) + << new DialogButtonItem(Action | Id2, tr("Try in...")); + + // Actions are unavaiable until something is selected. + buttonWidget(Id1)->disable(); + buttonWidget(Id2)->disable(); + + extraButtonsMenu().margins().setLeft(area().margins().left() + nameListWidth); +} + +void RepositoryBrowserDialog::finish(int result) +{ + DialogWidget::finish(result); + d->disconnect(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/serverinfodialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -54,7 +54,7 @@ String domainName; GameProfile profile; shell::ServerInfo serverInfo; - TimeDelta ping = -1; + TimeSpan ping = -1; // Network queries. ServerLink link; // querying details from the server @@ -166,10 +166,11 @@ bg->rule().setRect(mapOutline->rule()) .setInput(Rule::Bottom, gameState->rule().bottom()); - serverPackageActions << new ui::SubwidgetItem(tr("..."), ui::Right, [this] () -> PopupWidget * - { - return new PackageInfoDialog(serverPackages->actionPackage()); - }); + serverPackageActions << new ui::SubwidgetItem( + tr("..."), ui::Right, [this]() -> PopupWidget * { + return new PackageInfoDialog(serverPackages->actionPackage(), + PackageInfoDialog::EnableActions); + }); // Popups. @@ -177,11 +178,11 @@ self().add(serverPopup); serverPackages = new PackagesWidget(PackagesWidget::PopulationDisabled); serverPackages->margins().set("gap"); - serverPackages->setHiddenTags(StringList()); // show everything + serverPackages->setHiddenTags({"hidden"}); // show everything (top level) serverPackages->setActionItems(serverPackageActions); serverPackages->setActionsAlwaysShown(true); serverPackages->setPackageStatus(*this); - serverPackages->searchTermsEditor().setEmptyContentHint(tr("Filter Server Packages")); + serverPackages->searchTermsEditor().setEmptyContentHint(tr("Filter Server Mods")); serverPackages->rule().setInput(Rule::Width, rule("dialog.serverinfo.popup.width")); serverPopup->setContent(serverPackages); @@ -196,7 +197,7 @@ localPackages = new PackagesButtonWidget; localPackages->setColorTheme(Inverted); localPackages->setLabelPrefix(tr("Local: ")); - localPackages->setNoneLabel(tr("Local Packages...")); + localPackages->setNoneLabel(tr("Local Mods...")); localPackages->setGameProfile(profile); localPackages->disable(); localPackages->rule().setLeftTop(svBut->rule().right(), svBut->rule().top()); @@ -307,7 +308,7 @@ // Local packages. { - localPackages->setDialogTitle(tr("Local Packages for %1 Multiplayer").arg(gameTitle)); + localPackages->setDialogTitle(tr("Local Mods for %1 Multiplayer").arg(gameTitle)); localPackages->setGameProfile(profile); localPackages->setPackages(Game::localMultiplayerPackages(gameId)); } @@ -386,7 +387,7 @@ if (!domainName.isEmpty()) { // Begin a query for the latest details. - link.acquireServerProfile(domainName, [this] (Address resolvedAddress, + link.acquireServerProfileAsync(domainName, [this] (Address resolvedAddress, GameProfile const *svProfile) { host = resolvedAddress; @@ -395,7 +396,7 @@ } else { - link.acquireServerProfile(host, [this] (GameProfile const *svProfile) + link.acquireServerProfileAsync(host, [this] (GameProfile const *svProfile) { statusReceived(*svProfile); }); @@ -436,7 +437,7 @@ startQuery(QueryPing); } - void pingResponse(Address const &, TimeDelta pingTime) + void pingResponse(Address const &, TimeSpan pingTime) { ping = pingTime; updateContent(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/uisettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/uisettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/uisettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/uisettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -20,20 +20,19 @@ #include "clientapp.h" #include "ConfigProfiles" -#include #include +#include +#include #include #include -#include using namespace de; DENG2_PIMPL(UISettingsDialog) { VariableChoiceWidget *uiScale; + VariableToggleWidget *uiTranslucency; VariableToggleWidget *showAnnotations; - VariableToggleWidget *showColumnDescription; - VariableToggleWidget *showUnplayable; VariableToggleWidget *showDoom; VariableToggleWidget *showHeretic; VariableToggleWidget *showHexen; @@ -44,22 +43,20 @@ { auto &area = self().area(); - area.add(uiScale = new VariableChoiceWidget(App::config("ui.scaleFactor"))); - area.add(showAnnotations = new VariableToggleWidget(tr("Menu Annotations"), App::config("ui.showAnnotations"))); - area.add(showColumnDescription = new VariableToggleWidget(tr("Game Descriptions"), App::config("home.showColumnDescription"))); - area.add(showUnplayable = new VariableToggleWidget(tr("Unplayable Games"), App::config("home.showUnplayableGames"))); - area.add(showDoom = new VariableToggleWidget(tr("Doom"), App::config("home.columns.doom"))); - area.add(showHeretic = new VariableToggleWidget(tr("Heretic"), App::config("home.columns.heretic"))); - area.add(showHexen = new VariableToggleWidget(tr("Hexen"), App::config("home.columns.hexen"))); - area.add(showOther = new VariableToggleWidget(tr("Other Games"), App::config("home.columns.otherGames"))); - area.add(showMultiplayer = new VariableToggleWidget(tr("Multiplayer"), App::config("home.columns.multiplayer"))); - - uiScale->items() - << new ChoiceItem(tr("Huge (200%)"), 2.0) - << new ChoiceItem(tr("Large (150%)"), 1.5) - << new ChoiceItem(tr("Normal (100%)"), 1.0) - << new ChoiceItem(tr("Small (90%)"), 0.9) - << new ChoiceItem(tr("Tiny (80%)"), 0.8); + area.add(uiScale = new VariableChoiceWidget(Config::get("ui.scaleFactor"), VariableChoiceWidget::Number)); + area.add(uiTranslucency = new VariableToggleWidget("Background Translucency", Config::get("ui.translucency"))); + area.add(showAnnotations = new VariableToggleWidget("Menu Annotations", Config::get("ui.showAnnotations"))); + area.add(showDoom = new VariableToggleWidget("Doom", Config::get("home.columns.doom"))); + area.add(showHeretic = new VariableToggleWidget("Heretic", Config::get("home.columns.heretic"))); + area.add(showHexen = new VariableToggleWidget("Hexen", Config::get("home.columns.hexen"))); + area.add(showOther = new VariableToggleWidget("Other Games", Config::get("home.columns.otherGames"))); + area.add(showMultiplayer = new VariableToggleWidget("Multiplayer", Config::get("home.columns.multiplayer"))); + + uiScale->items() << new ChoiceItem("Double (200%)", 2.0) << new ChoiceItem("175%", 1.75) + << new ChoiceItem("150%", 1.5) << new ChoiceItem("125%", 1.25) + << new ChoiceItem("110%", 1.1) << new ChoiceItem("Normal (100%)", 1.0) + << new ChoiceItem("90%", 0.9) << new ChoiceItem("75%", 0.75) + << new ChoiceItem("Half (50%)", 0.5); uiScale->updateFromVariable(); } @@ -76,13 +73,13 @@ heading().setText(tr("UI Settings")); heading().setImage(style().images().image("home.icon")); - auto *library = LabelWidget::newWithText(_E(D) + tr("Game Library"), &area()); - library->setFont("separator.label"); +// auto *library = LabelWidget::appendSeparatorWithText(_E(D) + tr("Game Library"), &area()); +// library->setFont("separator.label"); - auto *restartNotice = LabelWidget::newWithText(tr("Takes effect only after restarting."), &area()); - restartNotice->margins().setTop(""); - restartNotice->setFont("separator.annotation"); - restartNotice->setTextColor("altaccent"); +// auto *restartNotice = LabelWidget::newWithText(tr("Changes take effect only after restarting."), &area()); +// restartNotice->margins().setTop(""); +// restartNotice->setFont("separator.annotation"); +// restartNotice->setTextColor("altaccent"); d->showAnnotations->margins().setBottom(RuleBank::UNIT); @@ -96,25 +93,27 @@ layout.setGridSize(2, 0); layout.setColumnAlignment(0, ui::AlignRight); layout << *LabelWidget::newWithText(tr("Scale:"), &area()) << *d->uiScale - << Const(0) << *restartNotice + << Const(0) << *d->uiTranslucency +// << Const(0) << *restartNotice << Const(0) << *d->showAnnotations << Const(0) << *annots; - layout.setCellAlignment(Vector2i(0, layout.gridSize().y), ui::AlignLeft); - layout.append(*library, 2); +// layout.setCellAlignment(Vector2i(0, layout.gridSize().y), ui::AlignLeft); +// layout.append(*library, 2); + auto *library = LabelWidget::appendSeparatorWithText("Game Library", &area(), &layout); - auto *showLabel = LabelWidget::newWithText(tr("Show:"), &area()); + auto *showLabel = LabelWidget::newWithText(tr("Enabled Tabs:"), &area()); showLabel->rule().setLeftTop(library->rule().left(), library->rule().bottom()); GridLayout showLayout(showLabel->rule().right(), showLabel->rule().top(), GridLayout::RowFirst); - showLayout.setGridSize(2, 4); + showLayout.setGridSize(2, 3); showLayout << *d->showDoom << *d->showHeretic << *d->showHexen << *d->showOther - << *d->showMultiplayer - << *d->showColumnDescription - << *d->showUnplayable; + << *d->showMultiplayer; +// << *d->showColumnDescription +// << *d->showUnplayable; area().setContentSize(OperatorRule::maximum(layout.width(), showLabel->rule().width() + showLayout.width()), diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/videosettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/videosettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/videosettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/videosettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -39,12 +39,15 @@ using namespace de; using namespace de::ui; -#ifndef MACOSX +#if !defined (MACOSX) +# define USE_REFRESH_RATE_CHOICE # define USE_COLOR_DEPTH_CHOICE #endif -DENG2_PIMPL(VideoSettingsDialog), -DENG2_OBSERVES(PersistentGLWindow, AttributeChange) +DENG2_PIMPL(VideoSettingsDialog) +#if !defined (DENG_MOBILE) +, DENG2_OBSERVES(PersistentGLWindow, AttributeChange) +#endif { ClientWindow &win; VariableToggleWidget *showFps; @@ -55,8 +58,11 @@ VariableToggleWidget *vsync; ToggleWidget *fpsLimiter = nullptr; SliderWidget *fpsMax = nullptr; - ChoiceWidget *modes; - ButtonWidget *windowButton; + ChoiceWidget *modes = nullptr; + ButtonWidget *windowButton = nullptr; +#ifdef USE_REFRESH_RATE_CHOICE + ChoiceWidget *refreshRates; +#endif #ifdef USE_COLOR_DEPTH_CHOICE ChoiceWidget *depths; #endif @@ -78,12 +84,20 @@ area.add(centered = new ToggleWidget); area.add(fsaa = new VariableToggleWidget(App::config("window.main.fsaa"))); area.add(vsync = new VariableToggleWidget(App::config("window.main.vsync"))); - area.add(modes = new ChoiceWidget); - area.add(windowButton = new ButtonWidget); + if (gotDisplayMode()) + { + area.add(modes = new ChoiceWidget("modes")); + area.add(windowButton = new ButtonWidget); + } +#ifdef USE_REFRESH_RATE_CHOICE + area.add(refreshRates = new ChoiceWidget("refresh-rate")); +#endif #ifdef USE_COLOR_DEPTH_CHOICE - area.add(depths = new ChoiceWidget); + area.add(depths = new ChoiceWidget("depths")); #endif +#if !defined (DENG_MOBILE) win.audienceForAttributeChange() += this; +#endif if (App_GameLoaded()) { @@ -138,37 +152,50 @@ */ void fetch() { +#if !defined (DENG_MOBILE) fullscreen->setActive(win.isFullScreen()); maximized->setActive(win.isMaximized()); centered->setActive(win.isCentered()); - windowButton->enable(!win.isFullScreen() && !win.isMaximized()); + if (windowButton) + { + windowButton->enable(!win.isFullScreen() && !win.isMaximized()); + } - // Select the current resolution/size in the mode list. - GLWindow::Size current = win.fullscreenSize(); + if (gotDisplayMode()) + { + // Select the current resolution/size in the mode list. + GLWindow::Size current = win.fullscreenSize(); - // Update selected display mode. - ui::Data::Pos closest = ui::Data::InvalidPos; - int delta = 0; - for (ui::Data::Pos i = 0; i < modes->items().size(); ++i) - { - QPoint const res = modes->items().at(i).data().toPoint(); - int dx = res.x() - current.x; - int dy = res.y() - current.y; - int d = dx*dx + dy*dy; - if (closest == ui::Data::InvalidPos || d < delta) + // Update selected display mode. + ui::Data::Pos closest = ui::Data::InvalidPos; + int delta = 0; + for (ui::Data::Pos i = 0; i < modes->items().size(); ++i) { - closest = i; - delta = d; + QPoint const res = modes->items().at(i).data().toPoint(); + int dx = res.x() - current.x; + int dy = res.y() - current.y; + int d = dx*dx + dy*dy; + if (closest == ui::Data::InvalidPos || d < delta) + { + closest = i; + delta = d; + } } + modes->setSelected(closest); } - modes->setSelected(closest); + +#ifdef USE_REFRESH_RATE_CHOICE + refreshRates->setSelected(refreshRates->items().findData(int(win.refreshRate() * 10))); +#endif #ifdef USE_COLOR_DEPTH_CHOICE // Select the current color depth in the depth list. depths->setSelected(depths->items().findData(win.colorDepthBits())); #endif +#endif // !DENG_MOBILE + // FPS limit. if (fpsMax) { @@ -185,11 +212,13 @@ } } +#if !defined (DENG_MOBILE) void windowAttributesChanged(PersistentGLWindow &) { fetch(); } - +#endif + void applyFpsMax() { if (fpsMax) @@ -198,13 +227,16 @@ fpsLimiter->isActive()? int(fpsMax->value()) : 0); } } + + bool gotDisplayMode() const + { + return DisplayMode_Count() > 0; + } }; VideoSettingsDialog::VideoSettingsDialog(String const &name) : DialogWidget(name, WithHeading), d(new Impl(this)) { - bool const gotDisplayMode = DisplayMode_Count() > 0; - heading().setText(tr("Video Settings")); heading().setImage(style().images().image("display")); @@ -224,10 +256,13 @@ d->vsync->setText(tr("VSync")); +#ifdef USE_REFRESH_RATE_CHOICE + LabelWidget *refreshLabel = nullptr; +#endif #ifdef USE_COLOR_DEPTH_CHOICE - LabelWidget *colorLabel = 0; + LabelWidget *colorLabel = nullptr; #endif - if (gotDisplayMode) + if (d->gotDisplayMode()) { // Choice of display modes + 16/32-bit color depth. d->modes->setOpeningDirection(ui::Up); @@ -253,15 +288,46 @@ d->modes->items() << new ChoiceItem(desc, res); } -#ifdef USE_COLOR_DEPTH_CHOICE - colorLabel = new LabelWidget; - colorLabel->setText(tr("Colors:")); - area().add(colorLabel); +#ifdef USE_REFRESH_RATE_CHOICE + { + refreshLabel = LabelWidget::newWithText(tr("Monitor Refresh:"), &area()); + + QSet rates; + rates.insert(0); + for (int i = 0; i < DisplayMode_Count(); ++i) + { + rates.insert(int(DisplayMode_ByIndex(i)->refreshRate * 10)); + } + foreach (int rate, rates) + { + if (rate == 0) + { + d->refreshRates->items() << new ChoiceItem(tr("Default"), 0); + } + else + { + d->refreshRates->items() + << new ChoiceItem(tr("%1 Hz").arg(float(rate) / 10.f, 0, 'f', 1), rate); + } + } + d->refreshRates->items().sort([] (ui::Item const &a, ui::Item const &b) { + int const i = a.data().toInt(); + int const j = b.data().toInt(); + if (!i) return true; + if (!j) return false; + return i < j; + }); + } +#endif - d->depths->items() +#ifdef USE_COLOR_DEPTH_CHOICE + { + colorLabel = LabelWidget::newWithText(tr("Colors:"), &area()); + d->depths->items() << new ChoiceItem(tr("32-bit"), 32) << new ChoiceItem(tr("24-bit"), 24) << new ChoiceItem(tr("16-bit"), 16); + } #endif } @@ -270,9 +336,12 @@ << new DialogButtonItem(DialogWidget::Action, tr("Reset to Defaults"), new SignalAction(this, SLOT(resetToDefaults()))); - d->windowButton->setImage(style().images().image("window.icon")); - d->windowButton->setOverrideImageSize(style().fonts().font("default").height().valuei()); - d->windowButton->setAction(new SignalAction(this, SLOT(showWindowMenu()))); + if (d->windowButton) + { + d->windowButton->setImage(style().images().image("window.icon")); + d->windowButton->setOverrideImageSize(style().fonts().font("default").height()); + d->windowButton->setAction(new SignalAction(this, SLOT(showWindowMenu()))); + } // Layout all widgets. Rule const &gap = rule("dialog.gap"); @@ -295,7 +364,7 @@ modeLayout.setGridSize(2, 0); modeLayout.setColumnAlignment(0, ui::AlignRight); - if (gotDisplayMode) + if (d->gotDisplayMode()) { modeLayout << *LabelWidget::newWithText(tr("Resolution:"), &area()); @@ -305,6 +374,9 @@ .setInput(Rule::Top, d->modes->rule().top()) .setInput(Rule::Left, d->modes->rule().right()); +#ifdef USE_REFRESH_RATE_CHOICE + modeLayout << *refreshLabel << *d->refreshRates; +#endif #ifdef USE_COLOR_DEPTH_CHOICE modeLayout << *colorLabel << *d->depths; #endif @@ -320,11 +392,13 @@ if (d->inludeAspect) { // Aspect ratio options. - auto *aspectLabel = LabelWidget::newWithText(_E(D) + tr("Aspect Ratios"), &area()); - aspectLabel->setFont("separator.label"); - aspectLabel->margins().setTop("gap"); - modeLayout.setCellAlignment(Vector2i(0, modeLayout.gridSize().y), ui::AlignLeft); - modeLayout.append(*aspectLabel, 2) +// auto *aspectLabel = LabelWidget::newWithText(_E(D) + tr("Aspect Ratios"), &area()); +// aspectLabel->setFont("separator.label"); +// aspectLabel->margins().setTop("gap"); +// modeLayout.setCellAlignment(Vector2i(0, modeLayout.gridSize().y), ui::AlignLeft); +// modeLayout.append(*aspectLabel, 2); + LabelWidget::appendSeparatorWithText("Aspect Ratios", &area(), &modeLayout); + modeLayout << *LabelWidget::newWithText(tr("Player Weapons:"), &area()) << *d->hudAspect << *LabelWidget::newWithText(tr("Intermissions:"), &area()) << *d->inludeAspect << *LabelWidget::newWithText(tr("Finales:"), &area()) << *d->finaleAspect @@ -336,8 +410,14 @@ d->fetch(); - connect(d->modes, SIGNAL(selectionChangedByUser(uint)), this, SLOT(changeMode(uint))); + if (d->gotDisplayMode()) + { + connect(d->modes, SIGNAL(selectionChangedByUser(uint)), this, SLOT(changeMode(uint))); + } +#ifdef USE_REFRESH_RATE_CHOICE + connect(d->refreshRates, SIGNAL(selectionChangedByUser(uint)), this, SLOT(changeRefreshRate(uint))); +#endif #ifdef USE_COLOR_DEPTH_CHOICE connect(d->depths, SIGNAL(selectionChangedByUser(uint)), this, SLOT(changeColorDepth(uint))); #endif @@ -350,11 +430,15 @@ d->fetch(); } +#if !defined (DENG_MOBILE) + void VideoSettingsDialog::changeMode(uint selected) { + DENG2_ASSERT(d->modes); + QPoint const res = d->modes->items().at(selected).data().toPoint(); - int attribs[] = { + int const attribs[] = { ClientWindow::FullscreenWidth, int(res.x()), ClientWindow::FullscreenHeight, int(res.y()), ClientWindow::End @@ -373,6 +457,20 @@ #endif } +void VideoSettingsDialog::changeRefreshRate(uint selected) +{ +#ifdef USE_REFRESH_RATE_CHOICE + float const rate = float(d->refreshRates->items().at(selected).data().toInt()) / 10.f; + int const attribs[] = { + ClientWindow::RefreshRate, int(rate * 1000), // milli-Hz + ClientWindow::End + }; + d->win.changeAttributes(attribs); +#else + DENG2_UNUSED(selected); +#endif +} + void VideoSettingsDialog::showColorAdjustments() { d->win.showColorAdjustments(); @@ -381,6 +479,8 @@ void VideoSettingsDialog::showWindowMenu() { + DENG2_ASSERT(d->windowButton); + PopupMenuWidget *menu = new PopupMenuWidget; menu->setDeleteAfterDismissed(true); add(menu); @@ -404,3 +504,5 @@ d->win.changeAttributes(attribs); } + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/vrsettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/vrsettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/dialogs/vrsettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/dialogs/vrsettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -163,7 +163,7 @@ } #endif - area().setContentSize(layout.width(), layout.height()); + area().setContentSize(layout); buttons() << new DialogButtonItem(DialogWidget::Default | DialogWidget::Accept, tr("Close")) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/editors/modelasseteditor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/editors/modelasseteditor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/editors/modelasseteditor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/editors/modelasseteditor.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -32,7 +32,7 @@ #include "render/playerweaponanimator.h" #include -#include +#include #include #include #include @@ -78,7 +78,7 @@ App::packageLoader().audienceForActivity() += this; // The contents of the editor will scroll. - GuiWidget *container = &self().containerWidget(); + ScrollAreaWidget *container = &self().containerWidget(); container->add(assetChoice = new ChoiceWidget); assetChoice->popup().useInfoStyle(); @@ -391,17 +391,17 @@ g->addSlider(var, range, step, precision); } } - else if (var.value().is()) + else if (is(var.value())) { g->addLabel(varLabel(label)); g->addLineEdit(var); } - else if (var.value().is()) + else if (is(var.value())) { g->addLabel(varLabel(label)); g->addSlider(var, range, step, precision); } - else if (descend && var.value().is()) + else if (descend && is(var.value())) { populateGroup(g, var.valueAsRecord(), descend, label); } @@ -462,15 +462,13 @@ { SequentialLayout &layout = self().layout(); layout.clear(); - layout << *info - << *instLabel; + layout << *assetLabel << *info << *instLabel; foreach (Group *g, groups) { layout << g->title() << *g; } - self().updateSidebarLayout(assetLabel->rule().width() + - assetChoice->rule().width(), - assetChoice->rule().height()); + assetChoice->rule().setLeftTop(assetLabel->rule().right(), assetLabel->rule().top()); + self().updateSidebarLayout(assetLabel->rule().width() + assetChoice->rule().width()); } void updateInstanceList() @@ -550,7 +548,7 @@ { assetChoice->items().clear(); - App::rootFolder().locate("/packs").forContents([this] (String name, File &) + FS::locate("/packs").forContents([this] (String name, File &) { QRegExp regex("asset\\.(model\\.((thing|weapon)\\..*))"); if (regex.exactMatch(name)) @@ -587,7 +585,7 @@ if (animator) { - animator->startSequence(data.animationId, 10, false); + animator->startAnimation(data.animationId, 10, false); } } @@ -608,24 +606,11 @@ { d->assetLabel = LabelWidget::newWithText(tr("Asset:"), &containerWidget()); - // Layout. - d->assetLabel->rule() - .setInput(Rule::Left, containerWidget().contentRule().left()) - .setInput(Rule::Top, title().rule().bottom()); - d->assetChoice->rule() - .setInput(Rule::Left, d->assetLabel->rule().right()) - .setInput(Rule::Top, d->assetLabel->rule().top()); - - // Update container size. - updateSidebarLayout(d->assetLabel->rule().width() + - d->assetChoice->rule().width(), - d->assetChoice->rule().height()); - layout().setStartY(d->assetChoice->rule().bottom()); - + d->redoLayout(); d->updateAssetsList(); connect(d->assetChoice, SIGNAL(selectionChangedByUser(uint)), this, SLOT(setSelectedAsset(uint))); - connect(d->instChoice, SIGNAL(selectionChangedByUser(uint)), this, SLOT(setSelectedInstance(uint))); + connect(d->instChoice, SIGNAL(selectionChangedByUser(uint)), this, SLOT(setSelectedInstance(uint))); } void ModelAssetEditor::setSelectedAsset(uint pos) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/editors/rendererappearanceeditor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/editors/rendererappearanceeditor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/editors/rendererappearanceeditor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/editors/rendererappearanceeditor.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -29,7 +29,6 @@ #include #include -#include #include #include #include @@ -486,7 +485,7 @@ updateSidebarLayout(profLabel->rule().width() + d->profile->rule().width() + - d->profile->button().rule().width(), Const(0)); + d->profile->button().rule().width()); d->fetch(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/columnwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/columnwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/columnwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/columnwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -52,10 +52,10 @@ bool update() override { StyleProceduralImage::update(); - Size const newSize = owner().rule().size(); - if (newSize != size()) + const Size newPtSize = GuiWidget::pixelsToPoints(owner().rule().size()); + if (newPtSize != pointSize()) { - setSize(newSize); + setPointSize(newPtSize); return true; } bool update = !colorAnim.done() || needUpdate; @@ -78,7 +78,7 @@ Rectanglef(uv.topLeft + norm.topLeft * uv.size(), uv.topLeft + norm.bottomRight * uv.size())); - int const edgeWidth = GuiWidget::toDevicePixels(1); + int const edgeWidth = GuiWidget::pointsToPixels(1); auto const edgeUv = owner().root().atlas().imageRectf(owner().root().solidWhitePixel()); verts.makeQuad(Rectanglef(rect.left(), rect.top(), edgeWidth, rect.height()), @@ -96,16 +96,11 @@ HeaderWidget *header; Rule const *maxContentWidth = nullptr; Vector4f backTintColor; - - //GLProgram bgProgram; - //GLUniform uSaturation { "uSaturation", GLUniform::Float }; // background saturation - //GLUniform uBgColor { "uColor", GLUniform::Vec4 }; Animation backSaturation { 0.f, Animation::Linear }; Impl(Public *i) : Base(i) { back = new LabelWidget; - //back->setCustomShader(&bgProgram); back->margins().setZero(); scrollArea = new ScrollAreaWidget; @@ -125,26 +120,13 @@ { releaseRef(maxContentWidth); } - - /*void glInit() - { - root().shaders().build(bgProgram, "generic.textured.hsv.color_ucolor") - << uSaturation - << uBgColor - << root().uAtlas(); - } - - void glDeinit() - { - bgProgram.clear(); - }*/ }; ColumnWidget::ColumnWidget(String const &name) : GuiWidget(name) , d(new Impl(this)) { - changeRef(d->maxContentWidth, Const(toDevicePixels(400))); + changeRef(d->maxContentWidth, rule("home.column.content.width")); AutoRef contentMargin = (rule().width() - *d->maxContentWidth) / 2; d->scrollArea->margins() @@ -225,20 +207,8 @@ GuiWidget::update(); d->back->setSaturation(d->backSaturation); - /*d->uSaturation = d->backSaturation; - d->uBgColor = Vector4f(1, 1, 1, visibleOpacity());*/ } -/*void ColumnWidget::glInit() -{ - d->glInit(); -} - -void ColumnWidget::glDeinit() -{ - d->bgProgram.clear(); -}*/ - void ColumnWidget::updateStyle() { GuiWidget::updateStyle(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/gamecolumnwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -30,19 +30,36 @@ #include #include #include +#include +#include #include #include #include #include #include +#include +#include + +#include using namespace de; +const String GameColumnWidget::SORT_GAME_ID("game"); +const String GameColumnWidget::SORT_MODS("mods"); +const String GameColumnWidget::SORT_RECENTLY_PLAYED("recent"); +const String GameColumnWidget::SORT_RELEASE_DATE("release"); +const String GameColumnWidget::SORT_TITLE("title"); + +static const String VAR_SORT_BY("home.sortBy"); +static const String VAR_SORT_ASCENDING("home.sortAscending"); +static const String VAR_SORT_CUSTOM_SEPARATELY("home.sortCustomSeparately"); + DENG_GUI_PIMPL(GameColumnWidget) , DENG2_OBSERVES(Games, Readiness) , DENG2_OBSERVES(Profiles, Addition) , DENG2_OBSERVES(Variable, Change) , DENG2_OBSERVES(ButtonWidget, StateChange) +, DENG2_OBSERVES(Profiles::AbstractProfile, Change) , public ChildWidgetOrganizer::IWidgetFactory { /** @@ -117,7 +134,7 @@ newProfileButton->audienceForStateChange() += this; newProfileButton->setText(tr("New Profile...")); newProfileButton->setStyleImage("create"); - newProfileButton->setOverrideImageSize(style().fonts().font("default").height().value() * 1.5f); + newProfileButton->setOverrideImageSize(style().fonts().font("default").height() * 1.5f); newProfileButton->set(Background()); newProfileButton->setSizePolicy(ui::Filled, ui::Expand); newProfileButton->setTextAlignment(ui::AlignRight); @@ -133,7 +150,7 @@ if (dlg->exec(root())) { // Adding the profile has the side effect that a widget is - // created for it. + // created for it in the menu. auto *added = dlg->makeProfile(); DoomsdayApp::gameProfiles().add(added); } @@ -146,6 +163,9 @@ DoomsdayApp::games().audienceForReadiness() += this; Config::get("home.showUnplayableGames").audienceForChange() += this; + Config::get(VAR_SORT_BY).audienceForChange() += this; + Config::get(VAR_SORT_ASCENDING).audienceForChange() += this; + Config::get(VAR_SORT_CUSTOM_SEPARATELY).audienceForChange() += this; } ui::Item *findProfileItem(GameProfile const &profile) const @@ -192,13 +212,14 @@ DENG2_ASSERT(!findProfileItem(profile)); menu->items() << new ProfileItem(this, profile); addOrRemoveSubheading(); + profile.audienceForChange() += this; return true; } } return false; } - void profileAdded(Profiles::AbstractProfile &prof) + void profileAdded(Profiles::AbstractProfile &prof) override { // This may be called from another thread. mainCall.enqueue([this, &prof] () @@ -215,16 +236,27 @@ }); } + void profileChanged(Profiles::AbstractProfile &) override + { + Loop::timer(0.1, [this]() { sortItems(); }); + } + + bool isSubheadingVisibleWithSortOptions() const + { + return Config::get().getb(VAR_SORT_CUSTOM_SEPARATELY, true); + } + void addOrRemoveSubheading() { - int const userCount = userProfileCount(); + const int userCount = userProfileCount(); + const bool subheadingVisible = isSubheadingVisibleWithSortOptions() && userCount > 0; - if (userCount > 0 && !gotSubheading) + if (subheadingVisible && !gotSubheading) { gotSubheading = true; menu->items() << new ui::Item(ui::Item::Separator, tr("Custom Profiles")); } - else if (!userCount && gotSubheading) + else if (!subheadingVisible && gotSubheading) { for (dsize pos = 0; pos < menu->items().size(); ++pos) { @@ -295,43 +327,94 @@ void sortItems() { - menu->items().sort([] (ui::Item const &a, ui::Item const &b) - { + const String sortBy = Config::get().gets(VAR_SORT_BY, SORT_RELEASE_DATE); + const bool sortAscending = Config::get().getb(VAR_SORT_ASCENDING, true); + const bool sortCustomSeparately = Config::get().getb(VAR_SORT_CUSTOM_SEPARATELY, true); + + const auto *oldSelectedItem = menu->selectedItem(); + + menu->items().sort([&sortBy, sortAscending, sortCustomSeparately](const ui::Item &a, + const ui::Item &b) { Section const section1 = itemSection(a); Section const section2 = itemSection(b); - if (section1 < section2) - { - return true; - } - if (section1 > section2) + if (sortCustomSeparately) { - return false; + if (section1 < section2) + { + return true; + } + if (section1 > section2) + { + return false; + } } - GameProfile const &prof1 = *a.as().profile; - GameProfile const &prof2 = *b.as().profile; + const GameProfile &prof1 = *a.as().profile; + const GameProfile &prof2 = *b.as().profile; + + // Sort built-in games by release date. + int cmp = 0; - if (section1 == Custom) + if (sortBy == SORT_RELEASE_DATE) + { + cmp = a.as().game().releaseDate().year() - + b.as().game().releaseDate().year(); + } + else if (sortBy == SORT_GAME_ID) + { + cmp = a.as().game().id().compare(b.as().game().id()); + } + else if (sortBy == SORT_TITLE) { - // Sorted alphabetically. - return prof1.name().compareWithoutCase(prof2.name()) < 0; + cmp = prof1.name().compareWithoutCase(prof2.name()); + } + else if (sortBy == SORT_MODS) + { + cmp = de::cmp(prof1.packages().size(), prof2.packages().size()); + } + else if (sortBy == SORT_RECENTLY_PLAYED) + { + if (prof1.lastPlayedAt().isValid() && prof2.lastPlayedAt().isValid()) + { + cmp = -de::cmp(prof1.lastPlayedAt(), prof2.lastPlayedAt()); + } + else if (prof1.lastPlayedAt().isValid()) + { + cmp = -1; + } + else if (prof2.lastPlayedAt().isValid()) + { + cmp = +1; + } } - // Sort built-in games by release date. - int year = a.as().game().releaseDate().year() - - b.as().game().releaseDate().year(); - if (!year) + if (cmp == 0) { + // Secondary sort order. + // Playable profiles first. - if (prof1.isPlayable() && !prof2.isPlayable()) return true; - if (!prof1.isPlayable() && prof2.isPlayable()) return false; + if (prof1.isPlayable() && !prof2.isPlayable()) return sortAscending; + if (!prof1.isPlayable() && prof2.isPlayable()) return !sortAscending; - // Finally, based on identifier. - return prof1.gameId().compareWithoutCase(prof2.gameId()) < 0; + cmp = prof1.name().compareWithoutCase(prof2.name()); + if (cmp == 0) + { + // Finally, based on identifier. + cmp = prof1.gameId().compareWithoutCase(prof2.gameId()); + } + } + if (!sortAscending) + { + cmp = -cmp; } - return year < 0; + return cmp < 0; }); + + if (oldSelectedItem) + { + menu->setSelectedIndex(menu->items().find(*oldSelectedItem)); + } } void updateItems() @@ -347,7 +430,7 @@ menu->updateLayout(); } - void gameReadinessUpdated() + void gameReadinessUpdated() override { populateItems(); @@ -362,14 +445,22 @@ DoomsdayApp::gameProfiles().audienceForAddition() += this; } - void variableValueChanged(Variable &, Value const &) + void variableValueChanged(Variable &var, Value const &) override { - updateItems(); + if (var.name().beginsWith("sort")) + { + addOrRemoveSubheading(); + sortItems(); + } + else + { + updateItems(); + } } //- ChildWidgetOrganizer::IWidgetFactory ------------------------------------------------ - GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) + GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) override { if (item.semantics().testFlag(ui::Item::Separator)) { @@ -412,36 +503,68 @@ } })); } - else - { - popup->items() << new ui::ActionItem(tr("Packages..."), new SignalAction(button, SLOT(selectPackages()))); - } // Items suitable for all types of profiles. popup->items() - << new ui::ActionItem(tr("Clear Packages"), new CallbackAction([this, button] () - { - button->clearPackages(); - })) - << new ui::ActionItem(tr("Duplicate"), new CallbackAction([this, profileItem] () - { - GameProfile *dup = new GameProfile(*profileItem->profile); - dup->setUserCreated(true); + << new ui::ActionItem(tr("Select Mods..."), + new SignalAction(button, SLOT(selectPackages()))) + << new ui::ActionItem(tr("Clear Mods"), new CallbackAction([this, button]() { + button->clearPackages(); + })) + << new ui::ActionItem( + tr("Duplicate"), new CallbackAction([profileItem]() { + GameProfile *dup = new GameProfile(*profileItem->profile); + dup->setUserCreated(true); + dup->createSaveLocation(); + + // Generate a unique name. + for (int attempt = 1;; ++attempt) + { + String newName; + if (attempt > 1) + newName = String("%1 (Copy %2)").arg(dup->name()).arg(attempt); + else + newName = String("%1 (Copy)").arg(dup->name()); + if (!DoomsdayApp::gameProfiles().tryFind(newName)) + { + dup->setName(newName); + DoomsdayApp::gameProfiles().add(dup); + break; + } + } + })); + + if (const auto *loc = FS::tryLocate(profileItem->profile->savePath())) + { + popup->items() << new ui::Item(ui::Item::Separator) + << new ui::ActionItem( + "Show Save Folder", new CallbackAction([loc]() { + QDesktopServices::openUrl( + QUrl::fromLocalFile(loc->correspondingNativePath())); + })); + } - // Generate a unique name. - for (int attempt = 1; ; ++attempt) - { - String newName; - if (attempt > 1) newName = String("%1 (Copy %2)").arg(dup->name()).arg(attempt); - else newName = String("%1 (Copy)").arg(dup->name()); - if (!DoomsdayApp::gameProfiles().tryFind(newName)) - { - dup->setName(newName); - DoomsdayApp::gameProfiles().add(dup); - break; - } - } - })); + if (isUserProfile && !profileItem->profile->saveLocationId()) + { + // Old profiles don't have their own save locations. Offer to create one here. + popup->items() + << new ui::ActionItem( + "Create New Save Folder", new CallbackAction([this, profileItem]() { + profileItem->profile->createSaveLocation(); + // Inform the user. + auto *msg = new MessageDialog; + msg->setDeleteAfterDismissed(true); + msg->title().setText("Save Folder Created"); + msg->message().setText( + "Save files of the profile " _E(b) + + profileItem->profile->name() + _E(.) " will be written to " + + FS::locate(profileItem->profile->savePath()) + .description() + "."); + msg->buttons() << new DialogButtonItem(DialogWidget::Accept | + DialogWidget::Default); + msg->exec(root()); + })); + } if (isUserProfile) { @@ -449,18 +572,60 @@ tr("Delete"), ui::Left); deleteSub->items() << new ui::Item(ui::Item::Separator, tr("Are you sure?")) - << new ui::ActionItem(tr("Delete Profile"), - new CallbackAction([this, button, profileItem, popup] () - { - popup->detachAnchor(); - // Animate the widget to fade it away. - TimeDelta const SPAN = 0.2; - button->setOpacity(0, SPAN); - Loop::get().timer(SPAN, [profileItem] () - { - delete profileItem->profile; - }); - })) + << new ui::ActionItem( + tr("Delete Profile"), + new CallbackAction([this, button, profileItem, popup]() { + if (profileItem->profile->saveLocationId()) + { + const Folder *saveFolder = + FS::tryLocate(profileItem->profile->savePath()); + + if (saveFolder && !profileItem->profile->isSaveLocationEmpty()) + { + // What to do with the savegames? + auto *question = new MessageDialog; + question->setDeleteAfterDismissed(true); + question->title().setText("Delete Saved Games?"); + question->title().setStyleImage("alert"); + question->message().setText( + "The profile " _E(b) + profileItem->profile->name() + + _E(.) " that is being deleted has saved games. " + "Do you wish to delete the save files as well?"); + const NativePath savePath = + saveFolder->correspondingNativePath(); + question->buttons() + << new DialogButtonItem(DialogWidget::Accept, + "Delete All") + << new DialogButtonItem(DialogWidget::Reject | + DialogWidget::Default, + "Cancel") + << new DialogButtonItem( + DialogWidget::Action, + "Show Folder", + new CallbackAction([savePath]() { + QDesktopServices::openUrl( + QUrl::fromLocalFile(savePath)); + })); + if (!question->exec(root())) + { + // Cancelled. + return; + } + } + if (saveFolder) + { + profileItem->profile->destroySaveLocation(); + } + } + + // Animate the widget to fade it away. + const TimeSpan SPAN = 0.2; + button->setOpacity(0, SPAN); + popup->detachAnchor(); + popup->close(); + Loop::get().timer(SPAN, + [profileItem]() { delete profileItem->profile; }); + })) << new ui::ActionItem(tr("Cancel"), new Action); popup->items() @@ -473,7 +638,7 @@ return button; } - void updateItemWidget(GuiWidget &widget, ui::Item const &item) + void updateItemWidget(GuiWidget &widget, ui::Item const &item) override { if (item.semantics().testFlag(ui::Item::Separator)) return; // Ignore. @@ -497,9 +662,9 @@ return self().isHighlighted()? .4f : 0.f; } - void buttonStateChanged(ButtonWidget &button, ButtonWidget::State state) + void buttonStateChanged(ButtonWidget &button, ButtonWidget::State state) override { - TimeDelta const SPAN = 0.25; + TimeSpan const SPAN = 0.25; switch (state) { case ButtonWidget::Up: @@ -550,8 +715,35 @@ setBackgroundImage("home.background.other"); } - header().menuButton().hide(); // no items for the menu atm - header().info().setTextColor("label.dimmed"); + // View options for the game columns. + { + header().menuButton().setPopup( + [](const PopupButtonWidget &) -> PopupWidget * { + auto *pop = new GridPopupWidget; + auto *sortBy = + new VariableChoiceWidget(Config::get(VAR_SORT_BY), VariableChoiceWidget::Text); + sortBy->items() << new ChoiceItem("Recently played", SORT_RECENTLY_PLAYED) + << new ChoiceItem("Release date", SORT_RELEASE_DATE) + << new ChoiceItem("Title", SORT_TITLE) + << new ChoiceItem("Mods", SORT_MODS) + << new ChoiceItem("Game ID", SORT_GAME_ID); + sortBy->updateFromVariable(); + *pop << LabelWidget::newWithText("Show:") + << new VariableToggleWidget("Descriptions", + Config::get("home.showColumnDescription")) + << Const(0) + << new VariableToggleWidget("Unplayable Games", + Config::get("home.showUnplayableGames")) + << LabelWidget::newWithText("Sort By:") << sortBy << Const(0) + << new VariableToggleWidget("Ascending", Config::get(VAR_SORT_ASCENDING)) + << Const(0) + << new VariableToggleWidget("Separate Custom", + Config::get(VAR_SORT_CUSTOM_SEPARATELY)); + pop->commit(); + return pop; + }, + ui::Down); + } /// @todo Get these description from the game family defs. { @@ -631,13 +823,13 @@ d->showActions(highlighted); } -void GameColumnWidget::operator >> (PersistentState &toState) const +void GameColumnWidget::operator>>(PersistentState &toState) const { Record &rec = toState.objectNamespace(); rec.set(name().concatenateMember("selected"), d->menu->selectedIndex()); } -void GameColumnWidget::operator << (PersistentState const &fromState) +void GameColumnWidget::operator<<(PersistentState const &fromState) { Record const &rec = fromState.objectNamespace(); d->restoredSelected = rec.geti(name().concatenateMember("selected"), -1); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/gamepanelbuttonwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/gamepanelbuttonwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/gamepanelbuttonwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/gamepanelbuttonwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -19,6 +19,7 @@ #include "ui/home/gamepanelbuttonwidget.h" #include "ui/widgets/homemenuwidget.h" #include "ui/home/savelistwidget.h" +#include "ui/home/gamecolumnwidget.h" #include "ui/savelistdata.h" #include "ui/dialogs/packagesdialog.h" #include "ui/widgets/packagesbuttonwidget.h" @@ -30,11 +31,15 @@ #include #include #include +#include #include +#include #include #include +#include #include +#include #include #include @@ -42,6 +47,10 @@ DENG_GUI_PIMPL(GamePanelButtonWidget) , DENG2_OBSERVES(Profiles::AbstractProfile, Change) +, DENG2_OBSERVES(res::Bundles, Identify) +, DENG2_OBSERVES(Variable, Change) +, DENG2_OBSERVES(ButtonWidget, StateChange) +, public AsyncScope { GameProfile &gameProfile; ui::FilteredDataT savedItems; @@ -52,6 +61,7 @@ LabelWidget *problemIcon; LabelWidget *packagesCounter; res::LumpCatalog catalog; + bool playHovering = false; Impl(Public *i, GameProfile &profile, SaveListData const &allSavedItems) : Base(i) @@ -70,6 +80,12 @@ if (!gameProfile.isPlayable()) return false; + // The file must be in the right save folder. + if (item.savePath().fileNamePath().compareWithoutCase(gameProfile.savePath())) + { + return false; + } + StringList const savePacks = item.loadedPackages(); // Fallback for older saves without package metadata. @@ -92,7 +108,7 @@ packagesButton = new PackagesButtonWidget; packagesButton->setGameProfile(gameProfile); - packagesButton->setDialogTitle(tr("Packages for %1").arg(profile.name())); + packagesButton->setDialogTitle(tr("Mods for %1").arg(profile.name())); packagesButton->setSetupCallback([this] (PackagesDialog &dialog) { // Add a button for starting the game. @@ -120,6 +136,7 @@ playButton->setStyleImage("play", "default"); playButton->setImageColor(style().colors().colorf("inverted.text")); playButton->setActionFn([this] () { playButtonPressed(); }); + playButton->audienceForStateChange() += this; self().addButton(playButton); // List of saved games. @@ -161,7 +178,11 @@ self().label().margins().height()); self().panel().setContent(saves); + saves->updateLayout(); self().panel().open(); + + DoomsdayApp::bundles().audienceForIdentify() += this; + Config::get("home.sortBy").audienceForChange() += this; } Game const &game() const @@ -172,7 +193,7 @@ void updatePackagesIndicator() { int const count = gameProfile.packages().size(); - bool const shown = count > 0 && !self().isSelected(); + bool const shown = !isMissingPackages() && count > 0 && !self().isSelected(); packagesCounter->setText(String::number(count)); packagesCounter->show(shown); @@ -187,6 +208,12 @@ } } + void buttonStateChanged(ButtonWidget &/*playButton*/, ButtonWidget::State state) override + { + playHovering = (state != ButtonWidget::Up); + self().updateContent(); + } + void playButtonPressed() { if (playButton->isEnabled()) @@ -195,6 +222,8 @@ //ClientWindow::main().taskBar().close(); // TODO: Emit a signal that hides the Home and closes the taskbar. + gameProfile.setLastPlayedAt(); + // Switch the game. DoomsdayApp::app().changeGame(gameProfile, DD_ActivateGameWorker); @@ -226,7 +255,7 @@ String const path = savedItems.at(saves->selectedPos()).savePath(); self().unselectSave(); App::rootFolder().destroyFile(path); - App::fileSystem().refresh(); + FS::get().refreshAsync(); })) << new ui::ActionItem(tr("Cancel"), new Action /* nop */); self().add(pop); @@ -235,13 +264,46 @@ void updateGameTitleImage() { - self().icon().setImage(IdTech1Image::makeGameLogo(game(), catalog)); + *this += async([this]() { return IdTech1Image::makeGameLogo(game(), catalog); }, + [this](const Image &gameLogo) { self().icon().setImage(gameLogo); }); } - void profileChanged(Profiles::AbstractProfile &) + void profileChanged(Profiles::AbstractProfile &) override { self().updateContent(); } + + void variableValueChanged(Variable &, Value const &) override + { + self().updateContent(); + } + + void dataBundlesIdentified() override + { + Loop::get().mainCall([this] () + { + catalog.clear(); + self().updateContent(); + }); + } + + bool isMissingPackages() const + { + return !gameProfile.isPlayable() && game().isPlayableWithDefaultPackages(); + } + + String defaultSubtitle() const + { + if (gameProfile.isUserCreated()) + { + return game().title(); + } + if (Config::get("home.sortBy") != GameColumnWidget::SORT_RECENTLY_PLAYED) + { + return String::number(game().releaseDate().year()); + } + return {}; + } }; GamePanelButtonWidget::GamePanelButtonWidget(GameProfile &game, SaveListData const &savedItems) @@ -256,16 +318,19 @@ void GamePanelButtonWidget::setSelected(bool selected) { - PanelButtonWidget::setSelected(selected); + if ((isSelected() && !selected) || (!isSelected() && selected)) + { + PanelButtonWidget::setSelected(selected); - d->playButton->enable(selected); + d->playButton->enable(selected); - if (!selected) - { - unselectSave(); - } + if (!selected) + { + unselectSave(); + } - updateContent(); + updateContent(); + } } void GamePanelButtonWidget::updateContent() @@ -279,8 +344,23 @@ d->problemIcon->show(!isGamePlayable); d->updatePackagesIndicator(); - String meta = !d->gameProfile.isUserCreated()? String::number(d->game().releaseDate().year()) - : d->game().title(); + const String sortBy = Config::get("home.sortBy"); + + String meta; + if (sortBy == GameColumnWidget::SORT_RECENTLY_PLAYED) + { + meta = d->gameProfile.lastPlayedAt().isValid() + ? "Last played " + d->gameProfile.lastPlayedAt().asText(Time::FriendlyFormat) + : ""; + } + else if (sortBy == GameColumnWidget::SORT_GAME_ID) + { + meta = d->game().id(); + } + if (meta.isEmpty()) + { + meta = d->defaultSubtitle(); + } if (isSelected()) { @@ -288,19 +368,30 @@ { meta = _E(D) + tr("Missing data files") + _E(.); } - else if (d->saves->selectedPos() != ui::Data::InvalidPos) + } + + if (d->playHovering) + { + if (d->saves->selectedPos() != ui::Data::InvalidPos) { meta = tr("Restore saved game"); } - else if (!d->gameProfile.isUserCreated()) + else { - meta = tr("Start new session"); + meta = tr("Start game"); } } - if (!isPlayable && isGamePlayable) + if (d->isMissingPackages()) + { + meta = _E(D) "Missing mods" _E(.); + d->packagesButton->setOverrideLabel("Fix..."); + setKeepButtonsVisible(true); + } + else { - meta = _E(D) + tr("Selected packages missing") + _E(.); + d->packagesButton->setOverrideLabel(""); + setKeepButtonsVisible(false); } label().setText(String(_E(b) "%1\n" _E(l) "%2") diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/headerwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/headerwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/headerwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/headerwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -75,7 +75,7 @@ HeaderWidget::HeaderWidget() : d(new Impl(this)) { - AutoRef logoHeight(new ConstantRule(toDevicePixels(120))); + const Rule &logoHeight = rule("home.header.logo.height"); margins().setTop("gap"); @@ -172,7 +172,7 @@ void HeaderWidget::setLogoImage(DotPath const &imageId) { d->logo->setStyleImage(imageId); - d->logo->rule().setInput(Rule::Width, Const(toDevicePixels(160))); + d->logo->rule().setInput(Rule::Width, rule("home.header.logo.width")); d->title->margins().setLeft("gap"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/homewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/homewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/homewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/homewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -44,8 +45,8 @@ using namespace de; -static TimeDelta const SCROLL_SPAN = .5; -static TimeDelta const DISMISS_SPAN = 1.5; +static TimeSpan const SCROLL_SPAN = .5; +static TimeSpan const DISMISS_SPAN = 1.5; DENG_GUI_PIMPL(HomeWidget) , DENG2_OBSERVES(App, StartupComplete) @@ -79,6 +80,7 @@ QTimer moveShowTimer; ButtonWidget *taskBarHintButton; bool dismissing = false; + bool havePackages = false; int restoredOffsetTab = -1; int restoredActiveTab = -1; @@ -97,7 +99,14 @@ tabs = new TabWidget; tabsBackground = new LabelWidget; - tabsBackground->set(Background(Vector4f(1, 1, 1, 1), Background::Blurred)); + if (style().isBlurringAllowed()) + { + tabsBackground->set(Background(Vector4f(1, 1, 1, 1), Background::Blurred)); + } + else + { + tabsBackground->set(Background(Vector4f(0, 0, 0, 1))); + } // Create the column navigation buttons. moveLeft = new ButtonWidget; @@ -115,7 +124,7 @@ taskBarHintButton->setSizePolicy(ui::Expand, ui::Expand); taskBarHintButton->margins().set("dialog.gap"); taskBarHintButton->setText(_E(b) "ESC" _E(.) + tr(" Task Bar")); - taskBarHintButton->setTextColor("altaccent"); +// taskBarHintButton->setTextColor("text"); taskBarHintButton->setFont("small"); taskBarHintButton->setOpacity(.66f); taskBarHintButton->rule() @@ -188,7 +197,7 @@ } } - void updateVisibleColumnsAndTabs() + void updateVisibleColumnsAndTabHeadings() { bool const gotGames = DoomsdayApp::games().numPlayable() > 0; @@ -201,6 +210,10 @@ { col.widget->show(gotGames && col.configVar->value().isTrue()); } + if (is(col.widget)) + { + col.widget->show(gotGames || havePackages); + } } // Tab headings for visible columns. @@ -247,6 +260,13 @@ } } + void updateVisibleTabsAndLayout() + { + updateVisibleColumnsAndTabHeadings(); + calculateColumnCount(); + updateLayout(); + } + void appStartupCompleted() { blanker->start(0.25); @@ -255,10 +275,8 @@ void gameReadinessUpdated() { self().root().window().glActivate(); - - updateVisibleColumnsAndTabs(); - calculateColumnCount(); - updateLayout(); + + updateVisibleTabsAndLayout(); // Restore previous state? if (restoredActiveTab >= 0) @@ -283,7 +301,7 @@ } else { - TimeDelta span = DISMISS_SPAN; + TimeSpan span = DISMISS_SPAN; auto &win = self().root().window().as(); if (win.isGameMinimized()) { @@ -306,12 +324,10 @@ void variableValueChanged(Variable &, Value const &) { - updateVisibleColumnsAndTabs(); - calculateColumnCount(); - updateLayout(); + updateVisibleTabsAndLayout(); } - void moveOffscreen(TimeDelta span = DISMISS_SPAN) + void moveOffscreen(TimeSpan span = DISMISS_SPAN) { self().disable(); self().setBehavior(DisableEventDispatchToChildren); @@ -328,7 +344,7 @@ } } - void moveOnscreen(TimeDelta span = DISMISS_SPAN) + void moveOnscreen(TimeSpan span = DISMISS_SPAN) { if (!fequal(dismissOffset->animation().target(), 0.f)) { @@ -439,7 +455,7 @@ * @param pos Column/tab index. * @param span Animation duration. */ - void scrollToTab(int pos, TimeDelta span) + void scrollToTab(int pos, TimeSpan span) { pos = de::clamp(0, pos, columns.size() - 1); @@ -465,7 +481,7 @@ setScrollOffset(currentOffsetTab, span); } - void setScrollOffset(int tab, TimeDelta const &span) + void setScrollOffset(int tab, TimeSpan const &span) { scrollOffset->set(*columnWidth * tab, span); } @@ -482,16 +498,16 @@ } // Remove the highlight. + const int newHighlightPos = tabs->currentItem().data().toInt(); for (int pos = 0; pos < columns.size(); ++pos) { - if (columns[pos]->isHighlighted()) + if (pos != newHighlightPos && columns[pos]->isHighlighted()) { columns[pos]->setHighlighted(false); } } - // Set new highlight. - columns[tabs->currentItem().data().toInt()]->setHighlighted(true); + columns[newHighlightPos]->setHighlighted(true); moveShowTimer.start(); } @@ -536,10 +552,19 @@ column = new MultiplayerColumnWidget(); d->addColumn(column); - column = new PackagesColumnWidget(); - d->addColumn(column); + { + auto *packagesColumn = new PackagesColumnWidget; + d->addColumn(packagesColumn); + connect(packagesColumn, + &PackagesColumnWidget::availablePackageCountChanged, + [this] (int count) + { + d->havePackages = count > 0; + d->updateVisibleTabsAndLayout(); + }); + } - d->updateVisibleColumnsAndTabs(); + d->updateVisibleColumnsAndTabHeadings(); d->tabs->setCurrent(0); // Tabs on top. @@ -614,12 +639,12 @@ return false; } -void HomeWidget::moveOnscreen(TimeDelta span) +void HomeWidget::moveOnscreen(TimeSpan span) { d->moveOnscreen(span); } -void HomeWidget::moveOffscreen(TimeDelta span) +void HomeWidget::moveOffscreen(TimeSpan span) { d->moveOffscreen(span); } @@ -690,6 +715,12 @@ } } +void HomeWidget::updateStyle() +{ + GuiWidget::updateStyle(); + viewResized(); +} + void HomeWidget::operator >> (PersistentState &toState) const { Record &rec = toState.objectNamespace(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/multiplayercolumnwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/multiplayercolumnwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/multiplayercolumnwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/multiplayercolumnwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -98,7 +98,7 @@ header().title().setText(_E(s)_E(C) "dengine.net\n" _E(.)_E(.)_E(w) + tr("Multiplayer Games")); header().info().setText(tr("Multiplayer servers are discovered via the dengine.net " - "master server and broadcasting on the local network.")); + "master server and by broadcasting on the local network.")); } String MultiplayerColumnWidget::tabHeading() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/multiplayerpanelbuttonwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/multiplayerpanelbuttonwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/multiplayerpanelbuttonwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/multiplayerpanelbuttonwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -30,6 +30,8 @@ #include #include #include + +#include #include #include #include @@ -42,6 +44,7 @@ DENG_GUI_PIMPL(MultiplayerPanelButtonWidget) , DENG2_OBSERVES(Games, Readiness) +, public AsyncScope { shell::ServerInfo serverInfo; ButtonWidget *joinButton; @@ -100,7 +103,7 @@ { i->aboutToJoinMultiplayerGame(serverInfo); } - ClientApp::serverLink().connectToServerAndChangeGame(serverInfo); + ClientApp::serverLink().connectToServerAndChangeGameAsync(serverInfo); } bool hasConfig(String const &token) const @@ -181,7 +184,9 @@ if (d->catalog.setPackages(game.requiredPackages())) { - icon().setImage(IdTech1Image::makeGameLogo(game, d->catalog)); + res::LumpCatalog catalog{d->catalog}; + *d += async([&game, catalog]() { return IdTech1Image::makeGameLogo(game, catalog); }, + [this](const Image &logo) { icon().setImage(logo); }); } } else diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/nogamescolumnwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/nogamescolumnwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/nogamescolumnwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/nogamescolumnwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include using namespace de; @@ -45,7 +46,7 @@ .setInput(Rule::Bottom, rule().midY()); ButtonWidget *chooseIwad = new ButtonWidget; - chooseIwad->setText(tr("Select IWAD Folder...")); + chooseIwad->setText(tr("Select WAD Folder...")); chooseIwad->setSizePolicy(ui::Expand, ui::Expand); chooseIwad->rule() .setMidAnchorX(rule().midX()) @@ -61,29 +62,51 @@ void NoGamesColumnWidget::browseForDataFiles() { + bool reload = false; + +#if !defined (DENG_MOBILE) // Use a native dialog to select the IWAD folder. ClientApp::app().beginNativeUIMode(); - QFileDialog dlg(nullptr, - tr("Select IWAD Folder"), - App::config().gets("resource.iwadFolder", "")); + const auto folders = Config::get().getStringList("resource.packageFolder"); + String lastDir; + if (!folders.isEmpty()) + { + lastDir = folders.back(); + } + QFileDialog dlg(nullptr, "Select IWAD Folder", lastDir); dlg.setFileMode(QFileDialog::Directory); dlg.setReadOnly(true); //dlg.setNameFilter("*.wad"); dlg.setLabelText(QFileDialog::Accept, tr("Select")); - bool reload = false; if (dlg.exec()) { - App::config().set("resource.iwadFolder", dlg.selectedFiles().at(0)); + Variable & var = Config::get("resource.packageFolder"); + const TextValue selDir{dlg.selectedFiles().at(0)}; + if (is(var.value())) + { + auto &array = var.value(); + int found = array.indexOf(TextValue(selDir)); + if (found >= 0) + { + array.remove(found); + } + array.add(selDir); + } + else + { + var.set(selDir); + } reload = true; } ClientApp::app().endNativeUIMode(); +#endif // Reload packages and recheck for game availability. if (reload) { ClientWindow::main().console().closeLogAndUnfocusCommandLine(); - DoomsdayApp::app().initWadFolders(); + DoomsdayApp::app().initPackageFolders(); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/packagescolumnwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/packagescolumnwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/packagescolumnwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/packagescolumnwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -20,6 +20,7 @@ #include "ui/widgets/packageswidget.h" #include "ui/dialogs/packageinfodialog.h" #include "ui/dialogs/datafilesettingsdialog.h" +#include "ui/dialogs/repositorybrowserdialog.h" #include "ui/widgets/homeitemwidget.h" #include "ui/widgets/homemenuwidget.h" @@ -47,14 +48,15 @@ ButtonWidget *folderOptionsButton; ui::ListData actions; LoopCallback mainCall; + int totalPackageCount = 0; Impl(Public *i) : Base(i) { DoomsdayApp::app().audienceForGameChange() += this; - actions << new ui::SubwidgetItem(tr("..."), ui::Left, [this] () -> PopupWidget * - { - return new PackageInfoDialog(packages->actionPackage()); + actions << new ui::SubwidgetItem(tr("..."), ui::Left, [this]() -> PopupWidget * { + return new PackageInfoDialog(packages->actionPackage(), + PackageInfoDialog::EnableActions); }); countLabel = new LabelWidget; @@ -80,6 +82,8 @@ { countLabel->setText(tr("%1 shown out of %2 available").arg(shown).arg(total)); } + totalPackageCount = total; + emit self().availablePackageCountChanged(total); }); area.add(folderOptionsButton = new ButtonWidget); @@ -104,8 +108,21 @@ self().header().menuButton().setPopup([this] (PopupButtonWidget const &) -> PopupWidget * { auto *menu = new PopupMenuWidget; menu->items() - << new ui::ActionItem(tr("Refresh"), - new CallbackAction([this] () { packages->refreshPackages(); })); + << new ui::SubwidgetItem(style().images().image("gear"), + ui::Item::ShownAsButton | ui::Item::ClosesParentPopup, + tr("Settings"), ui::Left, makePopup) +// << new ui::ActionItem(tr("Install Mods..." _E(l)_E(s)_E(D) " BETA"), +// new CallbackAction([this]() { openRepositoryBrowser(); })) + << new ui::Item(ui::Item::Separator) + << new ui::ActionItem("Show Recognized IWADs", + new CallbackAction([this]() { packages->searchTermsEditor().setText("gamedata"); })) + << new ui::ActionItem("Show Box Contents", + new CallbackAction([this]() { packages->searchTermsEditor().setText("hidden"); })) + << new ui::ActionItem("Show Core Packages", + new CallbackAction([this]() { packages->searchTermsEditor().setText("core"); })) + << new ui::Item(ui::Item::Separator) + << new ui::ActionItem(tr("Refresh List"), + new CallbackAction([]() { FS::get().refreshAsync(); })); return menu; }, ui::Down); } @@ -114,14 +131,21 @@ { folderOptionsButton->show(game.isNull()); } + + void openRepositoryBrowser() + { + auto *dlg = new RepositoryBrowserDialog; + dlg->setDeleteAfterDismissed(true); + dlg->exec(root()); + } }; PackagesColumnWidget::PackagesColumnWidget() : ColumnWidget("packages-column") , d(new Impl(this)) { - header().title().setText(_E(s) "\n" _E(.) + tr("Packages")); - header().info().setText(tr("Browse available packages and install new ones.")); + header().title().setText(_E(s) "\n" _E(.) + tr("Mods")); + header().info().setText(tr("Browse available mods/add-ons and install new ones.")); header().infoPanel().close(0); // Total number of packages listed. @@ -144,9 +168,19 @@ d->packages->progress().rule().setRect(scrollArea().rule()); } +int PackagesColumnWidget::availablePackageCount() const +{ + return d->totalPackageCount; +} + String PackagesColumnWidget::tabHeading() const { - return tr("Packages"); + return tr("Mods"); +} + +String PackagesColumnWidget::tabShortcut() const +{ + return QStringLiteral("s"); } void PackagesColumnWidget::setHighlighted(bool highlighted) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/savelistwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/savelistwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/home/savelistwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/home/savelistwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -122,7 +122,7 @@ auto const &saveItem = item.as(); button.setImage(style().images().image(Game::logoImageForId(saveItem.gameId()))); - button.setOverrideImageSize(style().fonts().font("default").height().value() * 1.4f); + button.setOverrideImageSize(style().fonts().font("default").height() * 1.4f); } void toggleSelectedItem(ButtonWidget &button) @@ -142,6 +142,9 @@ } emit self().selectionChanged(selected); + + // Keep focus on the clicked button. + self().root().setFocus(&self()); } void updateItemHighlights(ButtonWidget *selectedButton) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaleanimwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -126,11 +126,11 @@ { if (components == 3) { - LIBGUI_GL.glColor3f(color[0].value, color[1].value, color[2].value); + DGL_Color3f(color[0].value, color[1].value, color[2].value); } else if (components == 4) { - LIBGUI_GL.glColor4f(color[0].value, color[1].value, color[2].value, color[3].value); + DGL_Color4f(color[0].value, color[1].value, color[2].value, color[3].value); } } @@ -171,21 +171,21 @@ static void drawGeometry(int numVerts, Vector3f const *posCoords, Vector4f const *colorCoords, Vector2f const *texCoords) { - LIBGUI_GL.glBegin(GL_TRIANGLE_STRIP); + DGL_Begin(DGL_TRIANGLE_STRIP); Vector3f const *posIt = posCoords; Vector4f const *colorIt = colorCoords; Vector2f const *texIt = texCoords; for (int i = 0; i < numVerts; ++i, posIt++, colorIt++, texIt++) { if (texCoords) - LIBGUI_GL.glTexCoord2f(texIt->x, texIt->y); + DGL_TexCoord2f(0, texIt->x, texIt->y); if (colorCoords) - LIBGUI_GL.glColor4f(colorIt->x, colorIt->y, colorIt->z, colorIt->w); + DGL_Color4f(colorIt->x, colorIt->y, colorIt->z, colorIt->w); - LIBGUI_GL.glVertex3f(posIt->x, posIt->y, posIt->z); + DGL_Vertex3f(posIt->x, posIt->y, posIt->z); } - LIBGUI_GL.glEnd(); + DGL_End(); } static inline MaterialVariantSpec const &uiMaterialSpec_FinaleAnim() @@ -235,7 +235,7 @@ (filterUI ? gl::Linear : gl::Nearest)); if (glName) { - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); textureEnabled = true; } } @@ -249,7 +249,7 @@ (filterUI ? gl::Linear : gl::Nearest)); if (f->texRef.tex) { - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); textureEnabled = true; } break; @@ -268,7 +268,7 @@ int const texBorder = tex->spec().variant.border; GL_BindTexture(tex); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); textureEnabled = true; V3f_Set(dimensions, matDimensions.x + texBorder * 2, matDimensions.y + texBorder * 2, 0); @@ -298,7 +298,7 @@ Rend_PatchTextureSpec(0 | (tex.isFlagged(res::Texture::Monochrome) ? TSF_MONOCHROME : 0) | (tex.isFlagged(res::Texture::UpscaleAndSharpen) ? TSF_UPSCALE_AND_SHARPEN : 0)); GL_BindTexture(static_cast(tex).prepareVariant(texSpec)); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); textureEnabled = true; V3f_Set(offset, tex.origin().x, tex.origin().y, 0); @@ -334,41 +334,41 @@ numVerts = buildGeometry(dimensions, flipTextureS, rgba, rgba2, &posCoords, &colorCoords, &texCoords); // Setup the transformation. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); //glScalef(.1f/SCREENWIDTH, .1f/SCREENWIDTH, 1); // Move to the object origin. - LIBGUI_GL.glTranslatef(origin[VX], origin[VY], origin[VZ]); + DGL_Translatef(origin[VX], origin[VY], origin[VZ]); // Translate to the object center. /// @todo Remove this; just go to origin directly. Rotation origin is /// now separately in 'rotateCenter'. -jk - LIBGUI_GL.glTranslatef(originOffset[VX], originOffset[VY], originOffset[VZ]); + DGL_Translatef(originOffset[VX], originOffset[VY], originOffset[VZ]); - LIBGUI_GL.glScalef(scale[VX], scale[VY], scale[VZ]); + DGL_Scalef(scale[VX], scale[VY], scale[VZ]); if (angle != 0) { - LIBGUI_GL.glTranslatef(rotateCenter[VX], rotateCenter[VY], 0); + DGL_Translatef(rotateCenter[VX], rotateCenter[VY], 0); // With rotation we must counter the VGA aspect ratio. - LIBGUI_GL.glScalef(1, 200.0f / 240.0f, 1); - LIBGUI_GL.glRotatef(angle, 0, 0, 1); - LIBGUI_GL.glScalef(1, 240.0f / 200.0f, 1); + DGL_Scalef(1, 200.0f / 240.0f, 1); + DGL_Rotatef(angle, 0, 0, 1); + DGL_Scalef(1, 240.0f / 200.0f, 1); - LIBGUI_GL.glTranslatef(-rotateCenter[VX], -rotateCenter[VY], 0); + DGL_Translatef(-rotateCenter[VX], -rotateCenter[VY], 0); } - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); + DGL_MatrixMode(DGL_MODELVIEW); // Scale up our unit-geometry to the desired dimensions. - LIBGUI_GL.glScalef(dimensions[VX], dimensions[VY], dimensions[VZ]); + DGL_Scalef(dimensions[VX], dimensions[VY], dimensions[VZ]); if (texScale[0] != 1 || texScale[1] != 1) { - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glScalef(texScale[0], texScale[1], 1); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PushMatrix(); + DGL_Scalef(texScale[0], texScale[1], 1); mustPopTextureMatrix = true; } @@ -378,32 +378,32 @@ if (mustPopTextureMatrix) { - LIBGUI_GL.glMatrixMode(GL_TEXTURE); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_TEXTURE); + DGL_PopMatrix(); } if (showEdges) { - LIBGUI_GL.glBegin(GL_LINES); + DGL_Begin(DGL_LINES); useColor(p->edgeColor(), 4); - LIBGUI_GL.glVertex2f(0, 0); - LIBGUI_GL.glVertex2f(1, 0); - LIBGUI_GL.glVertex2f(1, 0); + DGL_Vertex2f(0, 0); + DGL_Vertex2f(1, 0); + DGL_Vertex2f(1, 0); useColor(p->otherEdgeColor(), 4); - LIBGUI_GL.glVertex2f(1, 1); - LIBGUI_GL.glVertex2f(1, 1); - LIBGUI_GL.glVertex2f(0, 1); - LIBGUI_GL.glVertex2f(0, 1); + DGL_Vertex2f(1, 1); + DGL_Vertex2f(1, 1); + DGL_Vertex2f(0, 1); + DGL_Vertex2f(0, 1); useColor(p->edgeColor(), 4); - LIBGUI_GL.glVertex2f(0, 0); - LIBGUI_GL.glEnd(); + DGL_Vertex2f(0, 0); + DGL_End(); } // Restore original transformation. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } void FinaleAnimWidget::draw(Vector3f const &offset) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaleinterpreter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaleinterpreter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaleinterpreter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaleinterpreter.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -1369,7 +1369,7 @@ { if (ded_value_t *value = DED_Definitions()->getValueByUri(*reinterpret_cast(OP_URI(0)))) { - material = &world::Materials::get().material(de::Uri(value->text, RC_NULL)); + material = &world::Materials::get().material(de::makeUri(value->text)); } else { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finalepagewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finalepagewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finalepagewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finalepagewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -126,7 +126,7 @@ matAnimator.prepare(); GL_BindTexture(matAnimator.texUnit(MaterialAnimator::TU_LAYER0).texture); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); } if (d->bg.material || topAlpha < 1.0 || bottomAlpha < 1.0) @@ -136,21 +136,20 @@ else { //glDisable(GL_BLEND); - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); } GL_DrawRectf2TextureColor(0, 0, SCREENWIDTH, SCREENHEIGHT, 64, 64, topColor, topAlpha, bottomColor, bottomAlpha); GL_SetNoTexture(); - //glEnable(GL_BLEND); - GLState::current().setBlend(true).apply(); + DGL_Enable(DGL_BLEND); } } // Now lets go into 3D mode for drawing the p objects. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); //glLoadIdentity(); //GL_SetMultisample(true); @@ -158,10 +157,15 @@ // Clear Z buffer (prevent the objects being clipped by nearby polygons). LIBGUI_GL.glClear(GL_DEPTH_BUFFER_BIT); +#if defined (DENG_OPENGL) if (renderWireframe > 1) + { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); - //glEnable(GL_ALPHA_TEST); - GLState::push().setAlphaTest(true).apply(); + } +#endif + + DGL_PushState(); + DGL_Enable(DGL_ALPHA_TEST); Vector3f worldOrigin(/*-SCREENWIDTH/2*/ - d->offset[VX].value, /*-SCREENHEIGHT/2*/ - d->offset[VY].value, @@ -173,11 +177,15 @@ } // Restore original matrices and state: back to normal 2D. - //glDisable(GL_ALPHA_TEST); - GLState::pop().apply(); + DGL_PopState(); + +#if defined (DENG_OPENGL) // Back from wireframe mode? if (renderWireframe > 1) + { LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } +#endif // Filter on top of everything. Only draw if necessary. if (d->filter[3].value > 0) @@ -187,8 +195,8 @@ //GL_SetMultisample(false); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaletextwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaletextwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/infine/finaletextwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/infine/finaletextwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -148,21 +148,21 @@ DENG_ASSERT_IN_MAIN_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); //glScalef(.1f/SCREENWIDTH, .1f/SCREENWIDTH, 1); - LIBGUI_GL.glTranslatef(origin()[0].value + offset.x, origin()[1].value + offset.y, origin()[2].value + offset.z); + DGL_Translatef(origin()[0].value + offset.x, origin()[1].value + offset.y, origin()[2].value + offset.z); if (angle().value != 0) { // Counter the VGA aspect ratio. - LIBGUI_GL.glScalef(1, 200.0f / 240.0f, 1); - LIBGUI_GL.glRotatef(angle().value, 0, 0, 1); - LIBGUI_GL.glScalef(1, 240.0f / 200.0f, 1); + DGL_Scalef(1, 200.0f / 240.0f, 1); + DGL_Rotatef(angle().value, 0, 0, 1); + DGL_Scalef(1, 240.0f / 200.0f, 1); } - LIBGUI_GL.glScalef(scale()[0].value, scale()[1].value, scale()[2].value); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Scalef(scale()[0].value, scale()[1].value, scale()[2].value); + DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(d->pageFont? page()->predefinedFont(d->pageFont - 1) : d->fontNum); @@ -241,10 +241,10 @@ ++cnt; } - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/inputdebug.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/inputdebug.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/inputdebug.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/inputdebug.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -99,9 +99,9 @@ // Ignore zero offsets. if (origin && !(origin->x == 0 && origin->y == 0)) { - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glTranslatef(origin->x, origin->y, 0); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_Translatef(origin->x, origin->y, 0); } } @@ -110,8 +110,8 @@ // Ignore zero offsets. if (origin && !(origin->x == 0 && origin->y == 0)) { - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } FR_PopAttrib(); @@ -224,26 +224,26 @@ textSize.height + BORDER * 2)); // Draw a background. - LIBGUI_GL.glColor4fv(button.isDown()? downColor : upColor); + DGL_Color4fv(button.isDown()? downColor : upColor); GL_DrawRect(textGeom); // Draw the text. - LIBGUI_GL.glEnable(GL_TEXTURE_2D); - Point2Raw const textOffset(BORDER, BORDER); + DGL_Enable(DGL_TEXTURE_2D); + Point2Raw const textOffset = {{{BORDER, BORDER}}}; FR_DrawText(label.toUtf8().constData(), &textOffset); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); // Mark expired? if (button.bindContextAssociation() & InputControl::Expired) { int const markSize = .5f + de::min(textGeom.width(), textGeom.height()) / 3.f; - LIBGUI_GL.glColor3fv(expiredMarkColor); - LIBGUI_GL.glBegin(GL_TRIANGLES); - LIBGUI_GL.glVertex2i(textGeom.width(), 0); - LIBGUI_GL.glVertex2i(textGeom.width(), markSize); - LIBGUI_GL.glVertex2i(textGeom.width() - markSize, 0); - LIBGUI_GL.glEnd(); + DGL_Color3fv(expiredMarkColor); + DGL_Begin(DGL_TRIANGLES); + DGL_Vertex2f(textGeom.width(), 0); + DGL_Vertex2f(textGeom.width(), markSize); + DGL_Vertex2f(textGeom.width() - markSize, 0); + DGL_End(); } // Mark triggered? @@ -251,12 +251,12 @@ { int const markSize = .5f + de::min(textGeom.width(), textGeom.height()) / 3.f; - LIBGUI_GL.glColor3fv(triggeredMarkColor); - LIBGUI_GL.glBegin(GL_TRIANGLES); - LIBGUI_GL.glVertex2i(0, 0); - LIBGUI_GL.glVertex2i(markSize, 0); - LIBGUI_GL.glVertex2i(0, markSize); - LIBGUI_GL.glEnd(); + DGL_Color3fv(triggeredMarkColor); + DGL_Begin(DGL_TRIANGLES); + DGL_Vertex2f(0, 0); + DGL_Vertex2f(markSize, 0); + DGL_Vertex2f(0, markSize); + DGL_End(); } endDrawStateForVisual(&origin); @@ -349,7 +349,7 @@ origin.y = _origin? _origin->y : 0; Rect *grpGeom = nullptr; - RectRaw ctrlGeom; + RectRaw ctrlGeom{}; for (uint i = 0; i < group->numControls; ++i) { inputdev_layout_control_t const *ctrl = group->controls + i; @@ -416,7 +416,7 @@ FR_SetColorAndAlpha(1, 1, 1, 1); initDrawStateForVisual(origin); - Point2Raw offset; + Point2Raw offset{}; Rect *visualGeom = nullptr; // Draw device name first. @@ -424,10 +424,10 @@ { Size2Raw size; - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + DGL_Enable(DGL_TEXTURE_2D); Block const fullName(device.title().toUtf8()); FR_DrawText(fullName.constData(), nullptr/*no offset*/); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE_2D); FR_TextSize(&size, fullName.constData()); visualGeom = Rect_NewWithOriginSize2(offset.x, offset.y, size.width, size.height); @@ -439,7 +439,7 @@ for (uint i = 0; i < layout->numGroups; ++i) { inputdev_layout_controlgroup_t const *grp = &layout->groups[i]; - RectRaw grpGeometry; + RectRaw grpGeometry{}; drawControlGroup(device, grp, &offset, &grpGeometry); @@ -759,21 +759,21 @@ }; static inputdev_layout_t joyLayout = { joyGroups, NUMITEMS(joyGroups) }; - Point2Raw origin(2, 2); - Size2Raw dimensions; + Point2Raw origin = {{{2, 2}}}; + Size2Raw dimensions{}; if (novideo || isDedicated) return; // Not for us. - DENG_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG_ASSERT_GL_CONTEXT_ACTIVE(); // Disabled? if (!devRendKeyState && !devRendMouseState && !devRendJoyState) return; - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); if (devRendKeyState) { @@ -792,8 +792,8 @@ Rend_RenderInputDeviceStateVisual(InputSystem::get().device(IDEV_JOY1), &joyLayout, &origin, &dimensions); } - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); #undef NUMITEMS #undef SPACING diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/inputsystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/inputsystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/inputsystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/inputsystem.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -530,16 +530,15 @@ */ void readKeyboard() { -#define QUEUESIZE 32 - if (novideo) return; ddevent_t ev; de::zap(ev); - ev.device = IDEV_KEYBOARD; - ev.type = E_TOGGLE; + ev.device = IDEV_KEYBOARD; + ev.type = E_TOGGLE; ev.toggle.state = ETOG_REPEAT; // Read the new keyboard events, convert to ddevents and post them. + int const QUEUESIZE = 32; keyevent_t keyevs[QUEUESIZE]; size_t const numkeyevs = Keyboard_GetEvents(keyevs, QUEUESIZE); for (size_t n = 0; n < numkeyevs; ++n) @@ -569,8 +568,6 @@ self().postEvent(&ev); } - -#undef QUEUESIZE } /** @@ -781,8 +778,8 @@ //vrCfg().oculusRift().update(); ddevent_t ev; de::zap(ev); - ev.device = IDEV_HEAD_TRACKER; - ev.type = E_AXIS; + ev.device = IDEV_HEAD_TRACKER; + ev.type = E_AXIS; ev.axis.type = EAXIS_ABSOLUTE; Vector3f const pry = vrCfg().oculusRift().headOrientation(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/mouse_qt.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/mouse_qt.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/mouse_qt.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/mouse_qt.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -68,6 +68,7 @@ { if (!mouseTrapped) return; +#if !defined (DENG_MOBILE) ClientWindow *win = ClientWindowSystem::mainPtr(); if (!win) return; // Hmm? @@ -89,6 +90,7 @@ { prevMousePos = curPos; } +#endif } static void Mouse_Qt_GetState(mousestate_t *state) @@ -120,10 +122,6 @@ static void Mouse_Qt_ShowCursor(bool yes) { -/*#ifndef MACOSX - de::Canvas &canvas = ClientWindowSystem::main().canvas(); -#endif*/ - LOG_INPUT_VERBOSE("%s cursor (presently visible? %b)") << (yes? "showing" : "hiding") << !cursorHidden; @@ -133,7 +131,6 @@ #ifdef MACOSX Cursor_Show(false); #else - //canvas.setCursor(QCursor(Qt::BlankCursor)); qApp->setOverrideCursor(QCursor(Qt::BlankCursor)); #endif } @@ -144,13 +141,13 @@ Cursor_Show(true); #else qApp->restoreOverrideCursor(); - //canvas.setCursor(QCursor(Qt::ArrowCursor)); // Default cursor. #endif } } static void Mouse_Qt_InitTrap() { +#if !defined (DENG_MOBILE) auto &window = ClientWindowSystem::main(); QCursor::setPos(window.mapToGlobal(window.geometry().center())); @@ -158,15 +155,18 @@ window.setKeyboardGrabEnabled(true); Mouse_Qt_ShowCursor(false); +#endif } static void Mouse_Qt_DeinitTrap() { +#if !defined (DENG_MOBILE) auto &window = ClientWindowSystem::main(); window.setMouseGrabEnabled(false); window.setKeyboardGrabEnabled(false); Mouse_Qt_ShowCursor(true); +#endif } static void Mouse_Qt_Trap(dd_bool enabled) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/postprocessing.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/postprocessing.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/postprocessing.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/postprocessing.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -49,9 +49,9 @@ struct QueueEntry { String shaderName; float fade; - TimeDelta span; + TimeSpan span; - QueueEntry(String const &name, float f, TimeDelta const &s) + QueueEntry(String const &name, float f, TimeSpan const &s) : shaderName(name), fade(f), span(s) {} }; typedef QList Queue; @@ -163,12 +163,12 @@ return d->isActive(); } -void PostProcessing::fadeInShader(String const &fxPostShader, TimeDelta const &span) +void PostProcessing::fadeInShader(String const &fxPostShader, TimeSpan const &span) { d->queue.append(Impl::QueueEntry(fxPostShader, 1, span)); } -void PostProcessing::fadeOut(TimeDelta const &span) +void PostProcessing::fadeOut(TimeSpan const &span) { d->queue.append(Impl::QueueEntry("", 0, span)); } @@ -224,7 +224,7 @@ int console = String(argv[1]).toInt(); String const shader = argv[2]; - TimeDelta const span = (argc == 4? String(argv[3]).toDouble() : 0); + TimeSpan const span = (argc == 4? String(argv[3]).toDouble() : 0); if (console < 0 || console >= DDMAXPLAYERS) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/progress.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/progress.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/progress.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/progress.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -27,7 +27,7 @@ using namespace de; // Time for the progress to reach the new target (seconds). -static de::TimeDelta const PROGRESS_DELTA_TIME = 0.5; +static de::TimeSpan const PROGRESS_DELTA_TIME = 0.5; static ProgressWidget &progress() { @@ -53,5 +53,5 @@ void Con_SetProgress(int progressValue) { progress().setProgress(progressValue, progressValue < progress().range().end? - PROGRESS_DELTA_TIME : TimeDelta(PROGRESS_DELTA_TIME / 2)); + PROGRESS_DELTA_TIME : TimeSpan(PROGRESS_DELTA_TIME / 2)); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/savelistdata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/savelistdata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/savelistdata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/savelistdata.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -75,10 +75,19 @@ { foreach (File *file, SaveGames::get().saveIndex().files()) { - GameStateFolder &save = file->as(); - if (shouldAddFolder(save)) + try { - self().append(new SaveItem(save)); + GameStateFolder &save = file->as(); + if (shouldAddFolder(save)) + { + self().append(new SaveItem(save)); + } + } + catch (Error const &er) + { + LOG_ERROR("Save file %s has corrupt metadata: %s") + << file->description() + << er.asText(); } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/ui_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/ui_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/ui_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/ui_main.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -20,6 +20,7 @@ #include "de_base.h" #include "ui/ui_main.h" #include "ui/clientwindow.h" +#include "sys_system.h" #include #include @@ -30,6 +31,7 @@ #include "api_fontrender.h" #include "gl/gl_main.h" +#include "gl/gl_draw.h" //#include "gl/texturecontent.h" //#include "resource/image.h" #include "render/rend_main.h" @@ -58,7 +60,7 @@ DENG2_ASSERT(name != 0 && name[0]); // Compose the resource name. - de::Uri uri = de::Uri("System:", RC_NULL).setPath(name); + de::Uri uri = de::makeUri("System:").setPath(name); // Compose the resource data path. ddstring_t resourcePath; Str_InitStd(&resourcePath); @@ -87,7 +89,7 @@ { try { - FontManifest &manifest = ClientResources::get().fontManifest(de::Uri(uri, RC_NULL)); + FontManifest &manifest = ClientResources::get().fontManifest(de::makeUri(uri)); if (manifest.hasResource()) { *fid = fontid_t(manifest.uniqueId()); @@ -105,7 +107,7 @@ void UI_LoadFonts() { - if (isDedicated) return; + if (novideo) return; loadFontIfNeeded(UI_ChooseFixedFont(), &fontFixed); } @@ -126,12 +128,12 @@ void UI_SetColorA(ui_color_t* color, float alpha) { - LIBGUI_GL.glColor4f(color->red, color->green, color->blue, alpha); + DGL_Color4f(color->red, color->green, color->blue, alpha); } void UI_SetColor(ui_color_t* color) { - LIBGUI_GL.glColor3f(color->red, color->green, color->blue); + DGL_Color3f(color->red, color->green, color->blue); } void UI_TextOutEx2(const char* text, const Point2Raw* origin, ui_color_t* color, float alpha, @@ -151,49 +153,20 @@ void UI_DrawDDBackground(Point2Raw const &origin, Size2Raw const &dimensions, float alpha) { - /* - ui_color_t const *dark = UI_Color(UIC_BG_DARK); - ui_color_t const *light = UI_Color(UIC_BG_LIGHT); - float const mul = 1.5f; - - // Background gradient picture. - MaterialSnapshot const &ms = - ClientResources::get().material(de::Uri("System", Path("ui/background"))) - .prepare(UI_MaterialSpec(TSF_MONOCHROME)); - GL_BindTexture(&ms.texture(MTU_PRIMARY)); - */ + //DGL_Disable(DGL_TEXTURE_2D); + DGL_PushState(); - GLState::push(); - - LIBGUI_GL.glDisable(GL_TEXTURE_2D); if (alpha < 1.0f) { GL_BlendMode(BM_NORMAL); } else { - //glDisable(GL_BLEND); - GLState::current().setBlend(false).apply(); + DGL_Disable(DGL_BLEND); } - LIBGUI_GL.glColor4f(0, 0, 0, alpha); - LIBGUI_GL.glBegin(GL_QUADS); - // Top color. - //glColor4f(dark->red * mul, dark->green * mul, dark->blue * mul, alpha); - //glTexCoord2f(0, 0); - LIBGUI_GL.glVertex2f(origin.x, origin.y); - //glTexCoord2f(1, 0); - LIBGUI_GL.glVertex2f(origin.x + dimensions.width, origin.y); - - // Bottom color. - //glColor4f(light->red * mul, light->green * mul, light->blue * mul, alpha); - //glTexCoord2f(1, 1); - LIBGUI_GL.glVertex2f(origin.x + dimensions.width, origin.y + dimensions.height); - //glTexCoord2f(0, 1); - LIBGUI_GL.glVertex2f(0, origin.y + dimensions.height); - LIBGUI_GL.glEnd(); - - //glEnable(GL_BLEND); - GLState::pop().apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + DGL_Color4f(0, 0, 0, alpha); + GL_DrawRect2(origin.x, origin.y, dimensions.width, dimensions.height); + + DGL_PopState(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/viewcompositor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/viewcompositor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/viewcompositor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/viewcompositor.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -31,6 +31,7 @@ #include "api_render.h" #include "clientapp.h" #include "dd_main.h" +#include "gl/gl_main.h" #include #include @@ -192,16 +193,14 @@ GLState::push() .setTarget(d->viewFramebuf) - .setViewport(Rectangleui::fromSize(d->viewFramebuf.size())) - .apply(); + .setViewport(Rectangleui::fromSize(d->viewFramebuf.size())); d->viewFramebuf.clear(GLFramebuffer::ColorDepthStencil); // Rendering is done by the caller-provided callback. renderFunc(d->playerNum); - GLState::pop() - .apply(); + GLState::pop(); } GLTextureFramebuffer &ViewCompositor::gameView() @@ -224,11 +223,11 @@ R_UseViewPort(d->playerNum); - GLState::push() - .setAlphaTest(false) - .setBlend (false) - .setDepthTest(false) - .setCull (gl::None); + DGL_PushState(); + DGL_Disable(DGL_ALPHA_TEST); + DGL_Disable(DGL_BLEND); + DGL_Disable(DGL_DEPTH_TEST); + DGL_CullFace(DGL_NONE); // 3D world view (using the previously rendered texture). d->postProcessing.update(); @@ -239,7 +238,7 @@ // Some of the layers use OpenGL 2 drawing code. DGL_MatrixMode(DGL_PROJECTION); DGL_PushMatrix(); - LIBGUI_GL.glLoadMatrixf(ClientWindow::main().root().projMatrix2D().values()); + DGL_LoadMatrix(ClientWindow::main().root().projMatrix2D().values()); // Fill around a scaled-down 3D view. The border is not visible if the 3D view // covers the entire area. @@ -251,18 +250,16 @@ /// @todo HUD rendering probably doesn't need the vdWindow (maybe for the automap?). - RectRaw vpGeometry(vp->geometry.topLeft.x, vp->geometry.topLeft.y, - vp->geometry.width(), vp->geometry.height()); + RectRaw vpGeometry = {{vp->geometry.topLeft.x, vp->geometry.topLeft.y}, + {int(vp->geometry.width()), int(vp->geometry.height())}}; viewdata_t const *vd = &DD_Player(d->playerNum)->viewport(); - RectRaw vdWindow(vd->window.topLeft.x, vd->window.topLeft.y, - vd->window.width(), vd->window.height()); + RectRaw vdWindow = {{vd->window.topLeft.x, vd->window.topLeft.y}, + {int(vd->window.width()), int(vd->window.height())}}; if (gx.DrawViewPort) { - GLState::current() - .setBlend(true) - .apply(); + DGL_Enable(DGL_BLEND); gx.DrawViewPort(P_ConsoleToLocal(d->playerNum), &vpGeometry, @@ -287,9 +284,8 @@ Rectanglef const vp { normRect.topLeft * targetSize, normRect.bottomRight * targetSize }; - GLState::push() - .setViewport(vp.toRectangleui()) - .apply(); + DGL_PushState(); + GLState::current().setViewport(vp.toRectangleui()); // Finale. { @@ -316,12 +312,12 @@ // Draw any full window game graphics. if (gx.DrawWindow) { - Size2Raw const dimensions(DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT); + Size2Raw const dimensions = {{{DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT}}}; gx.DrawWindow(&dimensions); } } - GLState::pop().apply(); + DGL_PopState(); // Legacy engine/debug UIs (stuff from the old Net_Drawer). { @@ -344,7 +340,7 @@ displayPlayer = oldDisplayPlayer; GLState::considerNativeStateUndefined(); - GLState::pop().apply(); + DGL_PopState(); } PostProcessing &ViewCompositor::postProcessing() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/busywidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/busywidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/busywidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/busywidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -124,10 +124,9 @@ { root().painter().flush(); GLState::push() - .setViewport(Rectangleui::fromSize(GLState::current().target().size())) - .apply(); + .setViewport(Rectangleui::fromSize(GLState::current().target().size())); Con_DrawTransition(); - GLState::pop().apply(); + GLState::pop(); } else { @@ -144,9 +143,8 @@ root().painter().flush(); GLState::push() .setAlphaTest(false) - .setBlend(false) - .apply(); - LIBGUI_GL.glEnable(GL_TEXTURE_2D); + .setBlend(false); + //DGL_Enable(DGL_TEXTURE_2D); // Draw the texture. Rectanglei pos = rule().recti(); @@ -155,8 +153,8 @@ Matrix4f::scaleThenTranslate(pos.size(), pos.topLeft); d->drawable.draw(); - GLState::pop().apply(); - LIBGUI_GL.glDisable(GL_TEXTURE_2D); + GLState::pop(); + //DGL_Disable(DGL_TEXTURE_2D); } } @@ -196,12 +194,11 @@ GLState::push() .setTarget(d->transitionFrame) - .setViewport(Rectangleui::fromSize(d->transitionFrame.size())) - .apply(); + .setViewport(Rectangleui::fromSize(d->transitionFrame.size())); d->gameWidget->drawComposited(); - GLState::pop().apply(); + GLState::pop(); d->transitionFrame.resolveSamples(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/consolewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/consolewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/consolewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/consolewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -43,13 +43,15 @@ #include #include -#include -#include -#include +#if !defined (DENG_MOBILE) +# include +# include +# include +#endif using namespace de; -static TimeDelta const LOG_OPEN_CLOSE_SPAN = 0.2; +static TimeSpan const LOG_OPEN_CLOSE_SPAN = 0.2; DENG_GUI_PIMPL(ConsoleWidget) , DENG2_OBSERVES(Variable, Change) @@ -158,7 +160,9 @@ if (grabHover != RightEdge) { grabHover = RightEdge; +#if !defined (DENG_MOBILE) self().root().window().setCursor(Qt::SizeHorCursor); +#endif } } else @@ -171,13 +175,17 @@ if (grabHover != TopEdge) { grabHover = TopEdge; +#if !defined (DENG_MOBILE) self().root().window().setCursor(Qt::SizeVerCursor); +#endif } } else if (grabHover != NotGrabbed) { grabHover = NotGrabbed; +#if !defined (DENG_MOBILE) self().root().window().setCursor(Qt::ArrowCursor); +#endif } } @@ -219,11 +227,6 @@ // Bottom of the console must follow the active command line height. self().rule().setInput(Rule::Bottom, next->rule().top() - rule(RuleBank::UNIT)); - if (scriptMode == yes) - { - return; // No need to change anything else. - } - scriptCmd->setAttribute(AnimateOpacityWhenEnabledOrDisabled, UnsetFlags); cmdLine ->setAttribute(AnimateOpacityWhenEnabledOrDisabled, UnsetFlags); @@ -238,9 +241,11 @@ root().setFocus(next); } - scriptMode = yes; - - emit self().commandModeChanged(); + if (scriptMode != yes) + { + scriptMode = yes; + emit self().commandModeChanged(); + } } struct RightClick : public GuiWidget::IEventHandler @@ -272,6 +277,7 @@ static PopupWidget *consoleShortcutPopup() { auto *pop = new PopupWidget; + pop->setOutlineColor("popup.outline"); // The 'padding' widget will provide empty margins around the content. // Popups normally do not provide any margins. auto *padding = new GuiWidget; @@ -299,7 +305,7 @@ d->button = new PopupButtonWidget; d->button->setSizePolicy(ui::Expand, ui::Expand); d->button->setImage(style().images().image("log")); - d->button->setOverrideImageSize(style().fonts().font("default").height().valuei()); + d->button->setOverrideImageSize(style().fonts().font("default").height()); d->buttons->add(d->button); d->button->rule() @@ -639,6 +645,7 @@ } } +#if !defined (DENG_MOBILE) void ConsoleWidget::copyLogPathToClipboard() { if (NativeFile *native = App::rootFolder().tryLocate(LogBuffer::get().outputFile())) @@ -646,3 +653,4 @@ qApp->clipboard()->setText(native->nativePath()); } } +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/cvarchoicewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/cvarchoicewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/cvarchoicewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/cvarchoicewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -34,7 +34,9 @@ } }; -CVarChoiceWidget::CVarChoiceWidget(char const *cvarPath) : d(new Impl) +CVarChoiceWidget::CVarChoiceWidget(char const *cvarPath) + : ChoiceWidget(String::format("cvar-%s", cvarPath)) + , d(new Impl) { d->cvar = cvarPath; updateFromCVar(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/cvarnativepathwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/cvarnativepathwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/cvarnativepathwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/cvarnativepathwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -27,13 +27,13 @@ using namespace de; -DENG2_PIMPL_NOREF(CVarNativePathWidget) +DENG2_PIMPL(CVarNativePathWidget) +, DENG2_OBSERVES(NativePathWidget, UserChange) { char const *cvar; - NativePath path; - QStringList filters; - PopupMenuWidget *menu; - String blankText = "(not set)"; + + Impl(Public *i) : Base(i) + {} cvar_t *var() const { @@ -42,48 +42,19 @@ return cv; } - String labelText() const + void pathChangedByUser(NativePathWidget &) { - if (path.isEmpty()) - { - return String(_E(l)) + blankText + _E(.); - } - return path.fileName(); + self().setCVarValueFromWidget(); } }; CVarNativePathWidget::CVarNativePathWidget(char const *cvarPath) - : d(new Impl) + : d(new Impl(this)) { - add(d->menu = new PopupMenuWidget); - d->menu->setAnchorAndOpeningDirection(rule(), ui::Up); - d->menu->items() - << new ui::ActionItem(tr("Browse..."), - new SignalAction(this, SLOT(chooseUsingNativeFileDialog()))) - << new ui::ActionItem(style().images().image("close.ring"), tr("Clear"), - new SignalAction(this, SLOT(clearPath()))); - d->cvar = cvarPath; updateFromCVar(); - - auxiliary().setText(tr("Browse")); - - connect(&auxiliary(), SIGNAL(pressed()), this, SLOT(chooseUsingNativeFileDialog())); - connect(this, SIGNAL(pressed()), this, SLOT(showActionsPopup())); -} - -void CVarNativePathWidget::setFilters(StringList const &filters) -{ - d->filters.clear(); - for (auto const &f : filters) - { - d->filters << f; - } -} - -void CVarNativePathWidget::setBlankText(String const &text) -{ - d->blankText = text; + setPrompt(QString("Select File for \"%1\"").arg(d->cvar)); + audienceForUserChange() += d; } char const *CVarNativePathWidget::cvarPath() const @@ -93,55 +64,10 @@ void CVarNativePathWidget::updateFromCVar() { - d->path = CVar_String(d->var()); - setText(d->labelText()); -} - -void CVarNativePathWidget::chooseUsingNativeFileDialog() -{ - ClientApp::app().beginNativeUIMode(); - - // Use a native dialog to pick the path. - QDir dir(d->path); - if (d->path.isEmpty()) dir = QDir::home(); - QFileDialog dlg(nullptr, tr("Select File for \"%1\"").arg(d->cvar), dir.absolutePath()); - if (!d->filters.isEmpty()) - { - dlg.setNameFilters(d->filters); - } - dlg.setFileMode(QFileDialog::ExistingFile); - dlg.setOption(QFileDialog::ReadOnly, true); - dlg.setLabelText(QFileDialog::Accept, tr("Select")); - if (dlg.exec()) - { - d->path = dlg.selectedFiles().at(0); - setCVarValueFromWidget(); - setText(d->labelText()); - } - - ClientApp::app().endNativeUIMode(); -} - -void CVarNativePathWidget::clearPath() -{ - d->path.clear(); - setCVarValueFromWidget(); - setText(d->labelText()); -} - -void CVarNativePathWidget::showActionsPopup() -{ - if (!d->menu->isOpen()) - { - d->menu->open(); - } - else - { - d->menu->close(0); - } + setPath(CVar_String(d->var())); } void CVarNativePathWidget::setCVarValueFromWidget() { - CVar_SetString(d->var(), d->path.toString().toUtf8()); + CVar_SetString(d->var(), path().toString().toUtf8()); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/gamewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/gamewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/gamewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/gamewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -48,11 +48,16 @@ #include "gl/gl_defer.h" #include +#include #include #include #include #include +#include +#include +#include + /** * Maximum number of milliseconds spent uploading textures at the beginning * of a frame. Note that non-uploaded textures will appear as pure white @@ -87,6 +92,20 @@ }); } + void renderPlayerViewToFramebuffer(int playerNum, GLFramebuffer &dest) + { + GLState::push() + .setTarget(dest) + .setViewport(Rectangleui::fromSize(dest.size())); + + dest.clear(GLFramebuffer::ColorDepthStencil); + + // Rendering is done by the caller-provided callback. + R_RenderViewPort(playerNum); + + GLState::pop(); + } + /** * Draw the game widget's contents by compositing the various layers: game view, * border, HUD, finale, intermission, and engine/debug overlays. This is generally @@ -129,6 +148,7 @@ // End any open DGL sequence. DGL_End(); + DGL_Flush(); // Notify the world that we've finished rendering the frame. App_World().endFrame(); @@ -161,15 +181,6 @@ requestGeometry(false); } -/* -void GameWidget::glApplyViewport(Rectanglei const &rect) -{ - GLState::current() - .setNormalizedViewport(normalizedRect(rect)) - .apply(); -} -*/ - void GameWidget::pause() { if (App_GameLoaded() && !clientPaused) @@ -183,6 +194,79 @@ d->drawComposited(); } +void GameWidget::renderCubeMap(uint size, String const &outputImagePath) +{ + int const player = consolePlayer; + Vector2ui fbSize(size, size); + + GLTextureFramebuffer destFb(Image::RGB_888, fbSize, 1); + destFb.glInit(); + + LOG_GL_MSG("Rendering %ix%i cube map...") << 6 * fbSize.x << fbSize.y; + + // Prevent the angleclipper from clipping anything. + int old_devNoCulling = devNoCulling; + devNoCulling = 1; + + // Make the player temporarily a plain camera to hide weapons etc. + ClientPlayer &plr = ClientApp::player(player); + auto const oldPlrFlags = plr.publicData().flags; + plr.publicData().flags |= DDPF_CAMERA; + + // Notify the world that a new render frame has begun. + App_World().beginFrame(CPP_BOOL(R_NextViewer())); + + QImage composited(QSize(6 * size, size), QImage::Format_RGB32); + QPainter painter(&composited); + + int const baseYaw = 180; + + for (int i = 0; i < 6; ++i) + { + if (i < 4) + { + Rend_SetFixedView(player, baseYaw + 90 + i * -90, 0, 90, fbSize); + } + else + { + Rend_SetFixedView(player, baseYaw, i == 4? -90 : 90, 90, fbSize); + } + d->renderPlayerViewToFramebuffer(player, destFb); + painter.drawImage(i * size, 0, destFb.toImage()); + } + + App_World().endFrame(); + + // Write the composited image to a file. + { + QBuffer buf; + buf.open(QBuffer::WriteOnly); + composited.save(&buf, outputImagePath.fileNameExtension().mid(1).toLatin1()); + + // Choose a unique name. + int counter = 0; + String uniquePath = outputImagePath; + while (FS::tryLocate(uniquePath)) + { + uniquePath = outputImagePath.fileNameAndPathWithoutExtension() + + String::format("-%03i", counter++) + + outputImagePath.fileNameExtension(); + } + + File &outFile = FS::get().root().replaceFile(uniquePath); + outFile << Block(buf.data()); + outFile.flush(); + + LOG_GL_MSG("Cube map saved to \"%s\"") << outFile.correspondingNativePath(); + } + + // Cleanup. + destFb.glDeinit(); + Rend_UnsetFixedView(); + devNoCulling = old_devNoCulling; + plr.publicData().flags = oldPlrFlags; +} + void GameWidget::viewResized() { GuiWidget::viewResized(); @@ -305,3 +389,13 @@ //d->glDeinit(); } + +D_CMD(CubeShot) +{ + DENG2_UNUSED2(src, argc); + + int size = String(argv[1]).toInt(); + if (size < 8) return false; + ClientWindow::main().game().renderCubeMap(size, "/home/cubeshot.png"); + return true; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/homeitemwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -91,9 +91,10 @@ } }; + Flags flags; AssetGroup assets; LabelWidget *background; - LabelWidget *icon; + LabelWidget *icon { nullptr }; LabelWidget *label; QList buttons; AnimationRule *labelRightMargin; @@ -108,23 +109,30 @@ DotPath selectedTextColor { "text" }; QTimer buttonHideTimer; - Impl(Public *i) : Base(i) + Impl(Public *i, Flags flags) : Base(i), flags(flags) { - labelRightMargin = new AnimationRule(0); + labelRightMargin = new AnimationRule(0); self().add(background = new LabelWidget); - self().add(icon = new LabelWidget); - self().add(label = new LabelWidget); + if (!(flags & WithoutIcon)) + { + self().add(icon = new LabelWidget); + } + self().add(label = new LabelWidget); // Observe state of the labels. assets += *background; - assets += *icon; assets += *label; - icon->setBehavior(ContentClipping); - icon->setImageFit(ui::CoverArea | ui::OriginalAspectRatio); - icon->setSizePolicy(ui::Filled, ui::Filled); - icon->margins().setZero(); + if (icon) + { + assets += *icon; + + icon->setBehavior(ContentClipping); + icon->setImageFit(ui::CoverArea | ui::OriginalAspectRatio); + icon->setSizePolicy(ui::Filled, ui::Filled); + icon->margins().setZero(); + } label->setSizePolicy(ui::Filled, ui::Expand); label->setTextLineAlignment(ui::AlignLeft); @@ -167,7 +175,7 @@ if (buttonsShown) { labelRightMargin->set(*buttonsWidth, - labelRightMargin->animation().done()? TimeDelta(0.4) : + labelRightMargin->animation().done()? TimeSpan(0.4) : labelRightMargin->animation().remainingTime()); } } @@ -194,7 +202,7 @@ } } - TimeDelta const SPAN = (self().hasBeenUpdated()? 0.4 : 0.0); + TimeSpan const SPAN = (self().hasBeenUpdated()? 0.4 : 0.0); if (show) { labelRightMargin->set(*buttonsWidth, SPAN/2); @@ -218,11 +226,14 @@ void updateColors() { auto bg = Background(style().colors().colorf(selected? selectedBgColor : bgColor)); - icon->set(bg); background->set(bg); label->setTextColor(selected? selectedTextColor : textColor); // Icon matches text color. - icon->setImageColor(label->textColorf()); + if (icon) + { + icon->setImageColor(label->textColorf()); + icon->set(bg); + } } /** @@ -241,16 +252,12 @@ HomeItemWidget::HomeItemWidget(Flags flags, String const &name) : GuiWidget(name) - , d(new Impl(this)) + , d(new Impl(this, flags)) { setBehavior(Focusable | ContentClipping); setAttribute(AutomaticOpacity); addEventHandler(new Impl::ClickHandler(*this)); - Rule const &iconSize = d->label->margins().height() + - style().fonts().font("default").height() + - style().fonts().font("default").lineSpacing(); - AutoRef height; if (flags.testFlag(AnimatedHeight)) { @@ -264,19 +271,25 @@ d->background->rule() .setInput(Rule::Top, rule().top()) .setInput(Rule::Height, height) - .setInput(Rule::Left, d->icon->rule().right()) + .setInput(Rule::Left, d->icon? d->icon->rule().right() : rule().left()) .setInput(Rule::Right, rule().right()); - d->icon->rule() - .setSize(iconSize, height) - .setInput(Rule::Left, rule().left()) - .setInput(Rule::Top, rule().top()); - d->icon->set(Background(Background::BorderGlow, - style().colors().colorf("home.icon.shadow"), 20)); + if (d->icon) + { + d->icon->rule() + .setSize(d->label->margins().height() + + style().fonts().font("default").height() + + style().fonts().font("default").lineSpacing(), + height) + .setInput(Rule::Left, rule().left()) + .setInput(Rule::Top, rule().top()); + d->icon->set(Background(Background::BorderGlow, + style().colors().colorf("home.icon.shadow"), 20)); + } d->label->rule() .setInput(Rule::Top, rule().top()) - .setInput(Rule::Left, d->icon->rule().right()) + .setInput(Rule::Left, d->icon? d->icon->rule().right() : rule().left()) .setInput(Rule::Right, rule().right()); d->label->margins().setRight(OperatorRule::maximum(*d->labelMinRightMargin, *d->labelRightMargin) + rule("gap")); @@ -292,6 +305,7 @@ LabelWidget &HomeItemWidget::icon() { + DENG2_ASSERT(d->icon); return *d->icon; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/homemenuwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/homemenuwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/homemenuwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/homemenuwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -20,6 +20,8 @@ #include "ui/widgets/homeitemwidget.h" #include "ui/home/columnwidget.h" +#include + using namespace de; DENG_GUI_PIMPL(HomeMenuWidget) @@ -111,21 +113,42 @@ return d->selectedIndex; } +const ui::Item *HomeMenuWidget::selectedItem() const +{ + if (selectedIndex() < items().size()) + { + return &items().at(selectedIndex()); + } + return nullptr; +} + void HomeMenuWidget::setSelectedIndex(ui::DataPos index) { + DENG2_ASSERT(hasRoot()); + if (auto *widget = itemWidget(index)) { - widget->acquireFocus(); - - // Check if we can scroll to the selected widget right away. - // If not, we are observing the asset and will scroll when it is ready. - if (assets().isReady()) + if (d->selectedIndex != index) { - d->scrollToSelected(); + root().setFocus(nullptr); + unselectAll(); + + widget->acquireFocus(); } - else + + // Focus-based scrolling is only enabled when keyboard focus is in use. + if (root().focusIndicator().isKeyboardFocusActive()) { - assets().audienceForStateChange() += d; + // Check if we can scroll to the selected widget right away. + // If not, we are observing the asset and will scroll when it is ready. + if (assets().isReady()) + { + d->scrollToSelected(); + } + else + { + assets().audienceForStateChange() += d; + } } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/mapoutlinewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/mapoutlinewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/mapoutlinewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/mapoutlinewidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -120,7 +120,7 @@ float const scale = de::min(rect.width() / mapBounds.width(), rect.height() / mapBounds.height()); return Matrix4f::translate(rect.middle()) * - Matrix4f::scale (scale) * + Matrix4f::scale (Vector3f(scale, -scale, 1)) * Matrix4f::translate(Vector2f(-mapBounds.middle())); } }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/multiplayerservermenuwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/multiplayerservermenuwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/multiplayerservermenuwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/multiplayerservermenuwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -36,9 +36,13 @@ , public ChildWidgetOrganizer::IWidgetFactory { static ServerLink &link() { return ClientApp::serverLink(); } - static String hostId(shell::ServerInfo const &sv) { - //auto const domain = sv.domainName(); - //return domain.isEmpty()? sv.address().asText() : domain; + + static String hostId(shell::ServerInfo const &sv) + { + if (sv.serverId()) + { + return String::format("%x", sv.serverId()); + } return sv.address().asText(); } @@ -60,6 +64,11 @@ return _lan; } + void setLocal(bool isLocal) + { + _lan = isLocal; + } + shell::ServerInfo const &info() const { return _info; @@ -86,8 +95,8 @@ bool _lan; }; - DiscoveryMode mode = NoDiscovery; - ServerLink::FoundMask mask = ServerLink::Any; + DiscoveryMode mode = NoDiscovery; + ServerLink::FoundMask mask = ServerLink::Any; Impl(Public *i) : Base(i) { @@ -128,17 +137,25 @@ shell::ServerInfo info; if (!link.foundServerInfo(host, info, mask)) continue; - ui::Data::Pos found = items.findData(hostId(info)); + ui::Data::Pos found = items.findData(hostId(info)); + const bool isLocal = link.isServerOnLocalNetwork(info.address()); + if (found == ui::Data::InvalidPos) { // Needs to be added. - items.append(new ServerListItem(info, - link.isServerOnLocalNetwork(info.address()))); + items.append(new ServerListItem(info, isLocal)); } else { - // Update the info. - items.at(found).as().setInfo(info); + // Update the info of an existing item. + auto &it = items.at(found).as(); + + // Prefer the info received via LAN, if the server is the same instance. + if (!it.isLocal() || isLocal) + { + it.setInfo(info); + it.setLocal(isLocal); + } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/multiplayerstatuswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/multiplayerstatuswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/multiplayerstatuswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/multiplayerstatuswidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -79,7 +79,7 @@ if (d->link().status() != ServerLink::Connected) return; - TimeDelta const elapsed = d->link().connectedAt().since(); + TimeSpan const elapsed = d->link().connectedAt().since(); items().at(POS_STATUS).setLabel( _E(s)_E(l) + tr("Server:") + _E(.) " " + d->link().address().asText() + "\n" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/nativepathwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/nativepathwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/nativepathwidget.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/nativepathwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,153 @@ +/** @file nativepathwidget.cpp Widget for selecting a native path. + * + * @authors Copyright (c) 2014-2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "ui/widgets/nativepathwidget.h" +#include "ui/clientwindow.h" +#include "clientapp.h" + +#include +#include +#include + +using namespace de; + +DENG2_PIMPL(NativePathWidget) +{ + NativePath path; + QStringList filters; + PopupMenuWidget *menu; + String blankText = "(not set)"; + String prompt = "Select File"; + + Impl(Public *i) + : Base(i) + {} + + String labelText() const + { + if (path.isEmpty()) + { + return String(_E(l)) + blankText + _E(.); + } + return path.fileName(); + } + + void notifyChange() + { + DENG2_FOR_PUBLIC_AUDIENCE2(UserChange, i) + { + i->pathChangedByUser(self()); + } + } + + DENG2_PIMPL_AUDIENCE(UserChange) +}; + +DENG2_AUDIENCE_METHOD(NativePathWidget, UserChange) + +NativePathWidget::NativePathWidget() + : d(new Impl(this)) +{ + add(d->menu = new PopupMenuWidget); + d->menu->setAnchorAndOpeningDirection(rule(), ui::Up); + d->menu->items() + << new ui::ActionItem(tr("Browse..."), + new SignalAction(this, SLOT(chooseUsingNativeFileDialog()))) + << new ui::ActionItem(style().images().image("close.ring"), tr("Reset"), + new SignalAction(this, SLOT(clearPath()))); + + auxiliary().setText(tr("Browse")); + + connect(&auxiliary(), SIGNAL(pressed()), this, SLOT(chooseUsingNativeFileDialog())); + connect(this, SIGNAL(pressed()), this, SLOT(showActionsPopup())); +} + +void NativePathWidget::setFilters(StringList const &filters) +{ + d->filters.clear(); + for (auto const &f : filters) + { + d->filters << f; + } +} + +void NativePathWidget::setBlankText(String const &text) +{ + d->blankText = text; + setText(d->labelText()); +} + +void NativePathWidget::setPrompt(const String &promptText) +{ + d->prompt = promptText; +} + +NativePath NativePathWidget::path() const +{ + return d->path; +} + +void NativePathWidget::setPath(const NativePath &path) +{ + if (d->path != path) + { + d->path = path; + setText(d->labelText()); + d->notifyChange(); + } +} + +void NativePathWidget::chooseUsingNativeFileDialog() +{ + ClientApp::app().beginNativeUIMode(); + + // Use a native dialog to pick the path. + QDir dir(d->path); + if (d->path.isEmpty()) dir = QDir::home(); + QFileDialog dlg(nullptr, d->prompt, dir.absolutePath()); + if (!d->filters.isEmpty()) + { + dlg.setNameFilters(d->filters); + } + dlg.setFileMode(QFileDialog::ExistingFile); + dlg.setOption(QFileDialog::ReadOnly, true); + dlg.setLabelText(QFileDialog::Accept, tr("Select")); + if (dlg.exec()) + { + setPath(dlg.selectedFiles().at(0)); + } + + ClientApp::app().endNativeUIMode(); +} + +void NativePathWidget::clearPath() +{ + setPath({}); +} + +void NativePathWidget::showActionsPopup() +{ + if (!d->menu->isOpen()) + { + d->menu->open(); + } + else + { + d->menu->close(0); + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagecontentoptionswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagecontentoptionswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagecontentoptionswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagecontentoptionswidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -343,6 +343,7 @@ Rule const &maxHeight) { PopupWidget *pop = new PopupWidget; + pop->setOutlineColor("popup.outline"); pop->setDeleteAfterDismissed(true); //pop->setAnchorAndOpeningDirection(rule(), ui::Left); /*pop->closeButton().setActionFn([this] () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagesbuttonwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagesbuttonwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagesbuttonwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagesbuttonwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -32,26 +32,36 @@ String noneLabel; GameProfile const *profile = nullptr; std::function setupFunc; + String overrideLabel; Impl(Public *i) : Base(i) {} void updateLabel() { - self().setStyleImage("package.icon"); - - if (packages.isEmpty()) + if (overrideLabel) { - self().setText(noneLabel); - self().setTextColor(self().colorTheme() == Normal? "text" : "inverted.text"); - if (!noneLabel.isEmpty()) self().setImage(nullptr); + self().setImage(nullptr); + self().setText(overrideLabel); + self().setTextColor(self().colorTheme() == Normal? "accent" : "inverted.accent"); } else { - self().setText(labelPrefix + String::format("%i", packages.count())); - self().setTextColor(self().colorTheme() == Normal? "accent" : "inverted.accent"); + self().setStyleImage("package.icon"); + + if (packages.isEmpty()) + { + self().setText(noneLabel); + self().setTextColor(self().colorTheme() == Normal? "text" : "inverted.text"); + if (!noneLabel.isEmpty()) self().setImage(nullptr); + } + else + { + self().setText(labelPrefix + String::format("%i", packages.count())); + self().setTextColor(self().colorTheme() == Normal? "accent" : "inverted.accent"); + } + self().setImageColor(self().textColorf()); } - self().setImageColor(self().textColorf()); } void pressed() @@ -62,7 +72,7 @@ dlg->heading().setStyleImage(dialogIcon); if (profile) { - dlg->setGame(profile->gameId()); + dlg->setProfile(*profile); } dlg->setDeleteAfterDismissed(true); dlg->setSelectedPackages(packages); @@ -85,7 +95,7 @@ PackagesButtonWidget::PackagesButtonWidget() : d(new Impl(this)) { - setOverrideImageSize(style().fonts().font("default").height().value()); + setOverrideImageSize(style().fonts().font("default").height()); setSizePolicy(ui::Expand, ui::Expand); setTextAlignment(ui::AlignLeft); connect(this, &ButtonWidget::pressed, [this] () { d->pressed(); }); @@ -115,6 +125,12 @@ d->updateLabel(); } +void PackagesButtonWidget::setOverrideLabel(const String &overrideLabel) +{ + d->overrideLabel = overrideLabel; + d->updateLabel(); +} + void PackagesButtonWidget::setDialogTitle(String const &title) { d->dialogTitle = title; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagessidebarwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagessidebarwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packagessidebarwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packagessidebarwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -22,6 +22,7 @@ #include "ui/widgets/homeitemwidget.h" #include +#include #include using namespace de; @@ -39,20 +40,24 @@ browser->rule().setInput(Rule::Width, rule("sidebar.width")); // Action for showing information about the package. - browser->actionItems().insert(0, new ui::ActionItem(tr("..."), new CallbackAction([this] () - { - auto *pop = new PackageInfoDialog(browser->actionPackage()); - root().addOnTop(pop); - pop->setDeleteAfterDismissed(true); - pop->setAnchorAndOpeningDirection(browser->actionWidget()->as() - .buttonWidget(0).rule(), ui::Up); - pop->open(); - }))); + browser->actionItems().insert( + 0, + new ui::ActionItem( + tr("..."), new CallbackAction([this]() { + auto *pop = new PackageInfoDialog(browser->actionPackage(), + PackageInfoDialog::EnableActions); + root().addOnTop(pop); + pop->setDeleteAfterDismissed(true); + pop->setAnchorAndOpeningDirection( + browser->actionWidget()->as().buttonWidget(0).rule(), + ui::Up); + pop->open(); + }))); } }; PackagesSidebarWidget::PackagesSidebarWidget() - : SidebarWidget("Packages", "packages-sidebar") + : SidebarWidget("Mods", "packages-sidebar") , d(new Impl(this)) { // Button for refreshing the available packages. @@ -64,10 +69,7 @@ .setInput(Rule::Top, closeButton().rule().top()) .setInput(Rule::Height, closeButton().rule().height()); refreshButton->setStyleImage("refresh", "default"); - refreshButton->setActionFn([this] () - { - d->browser->refreshPackages(); - }); + refreshButton->setActionFn([]() { FS::get().refreshAsync(); }); d->browser->setFilterEditorMinimumY(closeButton().rule().bottom()); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packageswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packageswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/packageswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/packageswidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -22,8 +22,10 @@ #include "ui/widgets/panelbuttonwidget.h" #include "ui/dialogs/packageinfodialog.h" #include "ui/widgets/packagecontentoptionswidget.h" +#include "ui/clientrootwidget.h" #include "clientapp.h" +#include #include #include #include @@ -32,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -45,19 +48,21 @@ #include #include +#include using namespace de; -static String const VAR_TITLE ("title"); -static String const VAR_TAGS ("tags"); - +static String const VAR_TITLE("title"); +static String const VAR_TAGS("tags"); static String const TAG_HIDDEN("hidden"); static String const TAG_LOADED("loaded"); +static String const TAG_CACHED("cached"); -static TimeDelta const REFILTER_DELAY(0.2); +static TimeSpan const REFILTER_DELAY(0.2); struct PackageLoadStatus : public PackagesWidget::IPackageStatus { - bool isPackageHighlighted(String const &packageId) const { + bool isPackageHighlighted(String const &packageId) const + { return App::packageLoader().isLoaded(packageId); } }; @@ -66,89 +71,73 @@ PackagesWidget::IPackageStatus::~IPackageStatus() {} DENG_GUI_PIMPL(PackagesWidget) -, DENG2_OBSERVES(res::Bundles, Identify) +//, DENG2_OBSERVES(res::Bundles, Identify) +, DENG2_OBSERVES(FileSystem, Busy) , public ChildWidgetOrganizer::IWidgetFactory { /** * Information about an available package. */ - struct PackageItem : public ui::Item, DENG2_OBSERVES(File, Deletion) - { - File const *file; - Record const *info; + struct PackageItem + : public ui::Item + , DENG2_OBSERVES(File, Deletion) { + SafePtr file; + const Record * info = nullptr; + NativePath nativePath; PackageItem(File const &packFile) - : file(&packFile) - , info(&file->objectNamespace().subrecord(Package::VAR_PACKAGE)) { - file->audienceForDeletion() += this; - setData(Package::versionedIdentifierForFile(packFile)); - setLabel(info->gets(Package::VAR_TITLE)); + setFile(packFile); } void setFile(File const &packFile) { + if (file) + { + file->audienceForDeletion() -= this; + } + DENG2_GUARD(packFile); packFile.audienceForDeletion() += this; - file = &packFile; + file.reset(&packFile); + if (const auto *nat = maybeAs(packFile.source())) + { + nativePath = nat->nativePath(); + } + else + { + nativePath.clear(); + } info = &file->objectNamespace().subrecord(Package::VAR_PACKAGE); + setData(Package::versionedIdentifierForFile(packFile)); setLabel(info->gets(Package::VAR_TITLE)); notifyChange(); } void fileBeingDeleted(File const &) { - file = nullptr; info = nullptr; + nativePath.clear(); } bool isLoaded() const { + DENG2_GUARD(file); if (!file) return false; return PackageLoader::get().isLoaded(*file); } }; - LoopCallback mainCall; - LoopCallback mainCallForIdentify; - - // Search filter: - LineEditWidget *search; - Rule const *searchMinY = nullptr; - ButtonWidget *clearSearch; - Animation searchBackgroundOpacity { 0.f, Animation::Linear }; - QStringList filterTerms; - QTimer refilterTimer; - - ProgressWidget *refreshProgress; - - // Packages list: - StringList hiddenTags; - StringList manualPackagePaths; // if empty, all available packages used - HomeMenuWidget *menu; - ui::ListDataT allPackages; - ui::FilteredData filteredPackages { allPackages }; - ui::ListData defaultActionItems; - ui::Data const *actionItems = &defaultActionItems; - bool populateEnabled = true; - bool showHidden = false; - bool showOnlyLoaded = false; - bool actionOnlyForSelection = true; - bool rightClickToOpenContextMenu = false; - - IPackageStatus const *packageStatus = &isPackageLoaded; - - GuiWidget::ColorTheme unselectedItem = GuiWidget::Normal; - GuiWidget::ColorTheme selectedItem = GuiWidget::Normal; - GuiWidget::ColorTheme unselectedItemHilit = GuiWidget::Inverted; - GuiWidget::ColorTheme selectedItemHilit = GuiWidget::Inverted; + //--------------------------------------------------------------------------------------- /** * Widget showing information about a package and containing buttons for manipulating * the package. */ - class PackageListItemWidget : public HomeItemWidget - , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation) // actions - , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate) // actions + class PackageListItemWidget + : public HomeItemWidget + , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation) // actions + , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate) // actions + , DENG2_OBSERVES(Bank, Load) // package icons { public: PackageListItemWidget(PackageItem const &item, PackagesWidget &owner) @@ -156,34 +145,37 @@ , _owner(owner) , _item(&item) { - icon().setImageFit(ui::FitToSize | ui::OriginalAspectRatio); - icon().margins().set("gap"); - Rule const &height = style().fonts().font("default").height(); - icon().rule().setInput(Rule::Width, height + rule("gap")*2); + icon().setImageFit(ui::FitToWidth | ui::OriginalAspectRatio); + icon().margins().set("gap").setRight(""); + icon().rule().setInput(Rule::Width, style().fonts().font("default").height() * 3); _actions = new MenuWidget; _actions->enablePageKeys(false); _actions->enableScrolling(false); _actions->margins().setZero(); _actions->organizer().audienceForWidgetCreation() += this; - _actions->organizer().audienceForWidgetUpdate() += this; + _actions->organizer().audienceForWidgetUpdate() += this; _actions->setGridSize(0, ui::Expand, 1, ui::Expand); _actions->setItems(*owner.d->actionItems); - connect(this, &HomeItemWidget::doubleClicked, [this] () { triggerAction(); }); + connect(this, &HomeItemWidget::doubleClicked, [this]() { triggerAction(); }); addButton(_actions); setKeepButtonsVisible(!_owner.d->actionOnlyForSelection); createTagButtons(); + fetchIcon(); } void setItem(PackageItem const &item) { if (_item != &item) { + iconBank().audienceForLoad() -= this; setSelected(false); + _packagePath.clear(); _item = &item; destroyTagButtons(); createTagButtons(); + fetchIcon(); } } @@ -191,7 +183,7 @@ { if (!_item->file) return; - SequentialLayout layout(label().rule().left() + label().margins().left(), + SequentialLayout layout(label().rule().left() + label().margins().left(), label().rule().bottom() - label().margins().bottom(), ui::Right); @@ -199,8 +191,7 @@ { auto *btn = new ButtonWidget; btn->setText(_E(l) + tag.toLower()); - btn->setActionFn([this, tag] () - { + btn->setActionFn([this, tag]() { String terms = _owner.d->search->text(); if (!terms.isEmpty() && !terms.last().isSpace()) terms += " "; terms += tag.toLower(); @@ -209,8 +200,10 @@ updateTagButtonStyle(btn, "accent"); btn->setSizePolicy(ui::Expand, ui::Expand); btn->margins() - .setTop(RuleBank::UNIT).setBottom(RuleBank::UNIT) - .setLeft("gap").setRight("gap"); + .setTop(RuleBank::UNIT) + .setBottom(RuleBank::UNIT) + .setLeft("gap") + .setRight("gap"); add(btn); layout << *btn; @@ -220,9 +213,8 @@ if (!_tags.isEmpty()) { //rule().setInput(Rule::Height, label().rule().height()); - label().margins().setBottom(rule(RuleBank::UNIT)*2 + - style().fonts().font("small").height() + - rule("gap")); + label().margins().setBottom(rule(RuleBank::UNIT) * 2 + + style().fonts().font("small").height() + rule("gap")); } else { @@ -246,21 +238,44 @@ tag->set(Background(Background::Rounded, style().colors().colorf(color), 6)); } - void widgetCreatedForItem(GuiWidget &widget, ui::Item const &) + PackageIconBank &iconBank() + { + return _owner.root().as().packageIconBank(); + } + + void fetchIcon() + { + _iconId = Id::None; + + if (_item && _item->file && iconBank().packageContainsIcon(*_item->file)) + { + _packagePath = _item->file->path(); + if (Id pkgIcon = iconBank().packageIcon(*_item->file)) + { + setPackageIcon(pkgIcon); + } + else + { + iconBank().audienceForLoad() += this; + } + } + } + + void widgetCreatedForItem(GuiWidget &widget, ui::Item const &) override { // An action button has been created. LabelWidget &label = widget.as(); label.setSizePolicy(ui::Expand, ui::Expand); } - void widgetUpdatedForItem(GuiWidget &widget, ui::Item const &item) + void widgetUpdatedForItem(GuiWidget &widget, ui::Item const &item) override { // An action button needs updating. LabelWidget &label = widget.as(); if (ui::VariantActionItem const *varItem = maybeAs(item)) { - label.setText (varItem->label (_actions->variantItemsEnabled())); + label.setText(varItem->label(_actions->variantItemsEnabled())); label.setStyleImage(varItem->styleImageId(_actions->variantItemsEnabled()), label.fontId()); } @@ -283,26 +298,33 @@ void updateContents() { - bool isFile = false; + bool isFile = false; auto pkgIdVer = Package::split(packageId()); + if (pkgIdVer.first.startsWith("file.")) { isFile = true; - icon().setStyleImage("file", "default"); + if (!_iconId) + { + icon().setStyleImage("file", "default"); + icon().setImageScale(.5f); + } // Local files should not be indicated to be packages. - if (NativeFile const *native = maybeAs(_item->file->source())) + if (!_item->nativePath.isEmpty()) { - pkgIdVer.first = native->nativePath().pretty(); + pkgIdVer.first = _item->nativePath.pretty(); } } - else + else if (!_iconId) { icon().setStyleImage("package.icon", "default"); + icon().setImageScale(.5f); } - String labelText = String(_E(b) "%1\n" _E(l)_E(s) "%2") - .arg(_item->label()) - .arg(pkgIdVer.first); + + String labelText = + String(_E(b) "%1\n" _E(l) _E(s) "%2").arg(_item->label()).arg(pkgIdVer.first); + if (!isFile && pkgIdVer.second.isValid()) { labelText += String(_E(C) " %1" _E(.)).arg(pkgIdVer.second.compactNumber()); @@ -316,9 +338,10 @@ { if (ButtonWidget *button = maybeAs(w)) { - button->setImageColor(style().colors().colorf(highlight? "text" : "inverted.text")); - button->setColorTheme(highlight? invertColorTheme(_owner.d->selectedItemHilit) - : invertColorTheme(_owner.d->selectedItem)); + button->setImageColor( + style().colors().colorf(highlight ? "text" : "inverted.text")); + button->setColorTheme(highlight ? invertColorTheme(_owner.d->selectedItemHilit) + : invertColorTheme(_owner.d->selectedItem)); } } @@ -337,22 +360,36 @@ { updateTagButtonStyle(b, auxColor); } + + checkIconColor(); } - String packageId() const + void setSelected(bool selected) override { - return _item->data().toString(); + HomeItemWidget::setSelected(selected); + checkIconColor(); + } + + void checkIconColor() + { + // Package icons should always use their original colors. + if (_iconId) + { + icon().setImageColor(Vector4f(1, 1, 1, 1)); + } } + String packageId() const { return _item->data().toString(); } + PopupWidget *makeInfoPopup() const { - return new PackageInfoDialog(_item->file); + return new PackageInfoDialog(_item->file, _owner.d->packageInfoMode); } float estimatedHeight() const override { float const fontHeight = style().fonts().font("default").height().value(); - float estimate = fontHeight * 2 + label().margins().height().value(); + float estimate = fontHeight * 2 + label().margins().height().value(); return estimate; } @@ -361,8 +398,8 @@ // Click the default action button (the last one). if (!_actions->items().isEmpty()) { - auto *w = (defaultAction? _actions->childWidgets().last() - : _actions->childWidgets().first()); + auto *w = (defaultAction ? _actions->childWidgets().last() + : _actions->childWidgets().first()); if (auto *button = maybeAs(w)) { button->trigger(); @@ -378,51 +415,119 @@ } } + void bankLoaded(DotPath const &path) override + { + if (_iconId) return; + + DENG2_ASSERT_IN_MAIN_THREAD(); + + auto &bank = iconBank(); + + if (_packagePath == path) + { + setPackageIcon(bank.texture(path)); + bank.audienceForLoad() -= this; + } + } + + void setPackageIcon(Id const &id) + { + _iconId = id; + + if (_iconId) + { + auto *img = new AtlasProceduralImage(_owner); + img->setPreallocatedImage(_iconId); + icon().setImage(img); + icon().setImageScale(1); + checkIconColor(); + } + } + private: - PackagesWidget &_owner; - PackageItem const *_item; + PackagesWidget & _owner; + PackageItem const * _item; + Path _packagePath; QList _tags; - MenuWidget *_actions = nullptr; + MenuWidget * _actions = nullptr; + Id _iconId; }; -//- PackagesWidget::Pimpl Methods ------------------------------------------------------- + //--------------------------------------------------------------------------------------- + + using Strings = std::set; + + LoopCallback mainCall; + LoopCallback mainCallForIdentify; + + // Search filter: + LineEditWidget *search; + Rule const * searchMinY = nullptr; + ButtonWidget * clearSearch; + Animation searchBackgroundOpacity{0.f, Animation::Linear}; + QStringList filterTerms; + Strings hiddenTagsInEffect; + QTimer refilterTimer; + + ProgressWidget *refreshProgress; + + // Packages list: + StringList hiddenTags; // Packages with these not shown unless filterTerms has the tag. + StringList manualPackagePaths; // if empty, all available packages used + HomeMenuWidget * menu; + ui::ListDataT allPackages; + ui::FilteredData filteredPackages{allPackages}; + ui::ListData defaultActionItems; + ui::Data const * actionItems = &defaultActionItems; + bool populateEnabled = true; + bool showOnlyLoaded = false; + bool actionOnlyForSelection = true; + bool rightClickToOpenContextMenu = false; + PackageInfoDialog::Mode packageInfoMode = PackageInfoDialog::EnableActions; + + IPackageStatus const *packageStatus = &isPackageLoaded; + + GuiWidget::ColorTheme unselectedItem = GuiWidget::Normal; + GuiWidget::ColorTheme selectedItem = GuiWidget::Normal; + GuiWidget::ColorTheme unselectedItemHilit = GuiWidget::Inverted; + GuiWidget::ColorTheme selectedItemHilit = GuiWidget::Inverted; + + //- PackagesWidget::Pimpl Methods ------------------------------------------------------- /** * Initializes the PackagesWidget private implementation. * @param i Public instance. */ - Impl(Public *i) + Impl(Public * i) : Base(i) - , hiddenTags({ "core", "gamedata" }) + , hiddenTags({"hidden", "core", "gamedata"}) { - defaultActionItems << new ui::VariantActionItem(tr("Load"), tr("Unload"), new CallbackAction([this] () - { - DENG2_ASSERT(menu->interactedItem()); + defaultActionItems << new ui::VariantActionItem( + tr("Load"), tr("Unload"), new CallbackAction([this]() { + DENG2_ASSERT(menu->interactedItem()); - String const packageId = menu->interactedItem()->as().data().toString(); + String const packageId = + menu->interactedItem()->as().data().toString(); - auto &loader = App::packageLoader(); - if (loader.isLoaded(packageId)) - { - loader.unload(packageId); - } - else - { - try + auto &loader = App::packageLoader(); + if (loader.isLoaded(packageId)) { - loader.load(packageId); + loader.unload(packageId); } - catch (Error const &er) + else { - LOG_RES_ERROR("Package \"" + packageId + "\" could not be loaded: " + - er.asText()); + try + { + loader.load(packageId); + } + catch (Error const &er) + { + LOG_RES_ERROR("Package \"" + packageId + + "\" could not be loaded: " + er.asText()); + } } - } - menu->interactedItem()->notifyChange(); - })); - - //maxPanelHeight = new IndirectRule; - //maxPanelHeight->setSource(self().rule().height()); + menu->interactedItem()->notifyChange(); + })); self().add(menu = new HomeMenuWidget); self().add(search = new LineEditWidget); @@ -430,10 +535,10 @@ // Search/filter terms. search->rule() - .setInput(Rule::Left, self().rule().left() + self().margins().left()) - .setInput(Rule::Right, self().rule().right() - self().margins().right()) - .setInput(Rule::Top, self().rule().top() + self().margins().top()); - search->setEmptyContentHint(tr("Search packages")); + .setInput(Rule::Left, self().rule().left() + self().margins().left()) + .setInput(Rule::Right, self().rule().right() - self().margins().right()) + .setInput(Rule::Top, self().rule().top() + self().margins().top()); + search->setEmptyContentHint("Enter search terms"); search->setSignalOnEnter(true); search->margins().setRight(style().fonts().font("default").height() + rule("gap")); @@ -442,18 +547,17 @@ clearSearch->setSizePolicy(ui::Filled, ui::Filled); clearSearch->margins().set(""); clearSearch->rule() - .setInput(Rule::Right, search->rule().right() - rule("gap")) - .setInput(Rule::Height, search->font().lineSpacing()) - .setInput(Rule::Width, search->font().lineSpacing()) - .setMidAnchorY(search->rule().midY()); - clearSearch->setActionFn([this] () { + .setInput(Rule::Right, search->rule().right() - rule("gap")) + .setInput(Rule::Height, search->font().lineSpacing()) + .setInput(Rule::Width, search->font().lineSpacing()) + .setMidAnchorY(search->rule().midY()); + clearSearch->setActionFn([this]() { search->setText(""); root().setFocus(search); }); // Filtered list of packages. - filteredPackages.setFilter([this] (ui::Item const &it) - { + filteredPackages.setFilter([this](ui::Item const &it) { auto &item = it.as(); // The terms are looked in: @@ -461,23 +565,34 @@ // - identifier // - tags - if (!item.info) return false; - - bool const isHidden = Package::matchTags(*item.file, QStringLiteral("\\bhidden\\b")); - if (showHidden ^ isHidden) + if (!item.info) { + // Don't know what this is (probably deleted), can't show it. return false; } if (showOnlyLoaded && !item.isLoaded()) { return false; } - - return filterTerms.isEmpty() || - checkTerms({ item.data().toString(), // ID - item.file->source()->name(), // file name - item.info->gets(VAR_TITLE), - item.info->gets(VAR_TAGS) }); + { + bool isHidden = false; + for (const auto &h : hiddenTagsInEffect) + { + if (Package::matchTags(*item.file, h)) + { + isHidden = true; + break; + } + } + if (isHidden) + { + return false; + } + } + return filterTerms.isEmpty() || checkTerms({item.data().toString(), // ID + item.file->source()->name(), // file name + item.info->gets(VAR_TITLE), + item.info->gets(VAR_TAGS)}); }); menu->setItems(filteredPackages); menu->setBehavior(ChildVisibilityClipping); @@ -487,20 +602,25 @@ } menu->layout().setRowPadding(Const(0)); menu->rule() - .setInput(Rule::Left, self().rule().left() + self().margins().left()) - .setInput(Rule::Right, self().rule().right() - self().margins().right()) - .setInput(Rule::Top, self().rule().top() + self().margins().top() + search->rule().height()); + .setInput(Rule::Left, self().rule().left() + self().margins().left()) + .setInput(Rule::Right, self().rule().right() - self().margins().right()) + .setInput(Rule::Top, + self().rule().top() + self().margins().top() + search->rule().height()); menu->organizer().setWidgetFactory(*this); - menu->setVirtualizationEnabled(true, rule("gap").valuei()*2 + rule(RuleBank::UNIT).valuei() + - int(style().fonts().font("default").height().value()*3)); + menu->setVirtualizationEnabled( + true, + rule("gap").valuei() * 2 + rule(RuleBank::UNIT).valuei() + + int(style().fonts().font("default").height().value() * 3)); menu->organizer().setRecyclingEnabled(true); // homogeneous widgets - QObject::connect(search, &LineEditWidget::editorContentChanged, [this] () { updateFilterTerms(); }); - QObject::connect(search, &LineEditWidget::enterPressed, [this] () { focusFirstListedPackage(); }); + QObject::connect( + search, &LineEditWidget::editorContentChanged, [this]() { updateFilterTerms(); }); + QObject::connect( + search, &LineEditWidget::enterPressed, [this]() { focusFirstListedPackage(); }); refilterTimer.setSingleShot(true); refilterTimer.setInterval(int(REFILTER_DELAY.asMilliSeconds())); - QObject::connect(&refilterTimer, &QTimer::timeout, [this] () { updateFilterTerms(true); }); + QObject::connect(&refilterTimer, &QTimer::timeout, [this]() { updateFilterTerms(true); }); // Refresh progress indicator. refreshProgress = new ProgressWidget; @@ -511,11 +631,12 @@ // By default, only the progress indicator is shown. showProgressIndicator(true); - self().rule().setInput(Rule::Height, search->rule().height() + menu->rule().height() + - self().margins().height()); + self().rule().setInput(Rule::Height, + search->rule().height() + menu->rule().height() + + self().margins().height()); } - ~Impl() + ~Impl() override { //releaseRef(maxPanelHeight); releaseRef(searchMinY); @@ -569,9 +690,8 @@ showProgressIndicator(false); - StringList packages = - (manualPackagePaths.isEmpty()? App::packageLoader().findAllPackages() - : manualPackagePaths); + StringList packages = (manualPackagePaths.isEmpty() ? App::packageLoader().findAllPackages() + : manualPackagePaths); // Remove from the list those packages that are no longer listed. for (ui::DataPos i = 0; i < allPackages.size(); ++i) @@ -586,25 +706,10 @@ // Add/update the listed packages. for (String const &path : packages) { - File const &pack = App::rootFolder().locate(path); - - // Check for tags that should never be shown. - auto const tags = Package::tags(pack); - { - bool disregard = false; - for (String const &hiddenTag : hiddenTags) - { - if (tags.contains(hiddenTag)) - { - disregard = true; - break; - } - } - if (disregard) continue; - } + const File &pack = App::rootFolder().locate(path); // Is this already in the list? - ui::DataPos pos = allPackages.findData(Package::versionedIdentifierForFile(pack)); + const ui::DataPos pos = allPackages.findData(Package::versionedIdentifierForFile(pack)); if (pos != ui::Data::InvalidPos) { allPackages.at(pos).setFile(pack); @@ -622,8 +727,7 @@ void updateItems() { - filteredPackages.forAll([this] (ui::Item &item) - { + filteredPackages.forAll([](ui::Item &item) { item.as().notifyChange(); return LoopContinue; }); @@ -643,10 +747,10 @@ { // Refiltering will potentially alter the widget tree, so doing it during // event handling is not a great idea. - mainCall.enqueue([this] () - { + mainCall.enqueue([this]() { /// @todo Parse quoted terms. -jk - setFilterTerms(search->text().strip().split(QRegExp("\\s"), QString::SkipEmptyParts)); + setFilterTerms( + search->text().strip().split(QRegExp("\\s"), QString::SkipEmptyParts)); menu->setOpacity(1.f, REFILTER_DELAY); }); @@ -656,15 +760,19 @@ void setFilterTerms(QStringList terms) { filterTerms = terms; + hiddenTagsInEffect.clear(); + for (const auto &t : hiddenTags) + { + if (!terms.contains(t)) + { + hiddenTagsInEffect.insert("\\b" + t + "\\b"); // tag regexp + } + } clearSearch->show(!terms.isEmpty()); if ((showOnlyLoaded = filterTerms.contains(TAG_LOADED)) != false) { filterTerms.removeAll(TAG_LOADED); } - if ((showHidden = filterTerms.contains(TAG_HIDDEN)) != false) - { - filterTerms.removeAll(TAG_HIDDEN); - } filteredPackages.refilter(); @@ -680,18 +788,23 @@ } } - void dataBundlesIdentified() override + void fileSystemBusyStatusChanged(FS::BusyStatus bs) override { - // After bundles have been refreshed, make sure the list items are up to date. - if (!mainCallForIdentify) + if (bs == FS::Busy) { - mainCallForIdentify.enqueue([this] () + showProgressIndicator(true); + } + else if (DoomsdayApp::bundles().isEverythingIdentified()) + { + // After bundles have been refreshed, make sure the list items are up to date. + if (!mainCallForIdentify) { - //qDebug() << "Bundles identified, re-populating" << &self; - root().window().glActivate(); - populateEnabled = true; - self().populate(); - }); + mainCallForIdentify.enqueue([this]() { + root().window().glActivate(); + populateEnabled = true; + self().populate(); + }); + } } } @@ -722,17 +835,18 @@ return true; } -//- ChildWidgetOrganizer::IWidgetFactory -------------------------------------- + //- ChildWidgetOrganizer::IWidgetFactory -------------------------------------- - GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) + GuiWidget *makeItemWidget(ui::Item const &item, GuiWidget const *) override { return new PackageListItemWidget(item.as(), self()); } - void updateItemWidget(GuiWidget &widget, ui::Item const &item) + void updateItemWidget(GuiWidget & widget, ui::Item const &item) override { auto &w = widget.as(); w.setItem(item.as()); + DENG2_ASSERT_IN_MAIN_THREAD(); w.updateContents(); } }; @@ -741,15 +855,9 @@ : GuiWidget(name) , d(new Impl(this)) { - auto &bundles = DoomsdayApp::bundles(); - bundles.audienceForIdentify() += d; - d->populateEnabled = (initBehavior == PopulationEnabled); - - if (bundles.isEverythingIdentified()) - { - populate(); - } + FS::get().audienceForBusy() += d; + populate(); } PackagesWidget::PackagesWidget(StringList manualPackageIds, String const &name) @@ -776,6 +884,12 @@ populate(); } +void PackagesWidget::setAllowPackageInfoActions(bool allowActions) +{ + d->packageInfoMode = + allowActions ? PackageInfoDialog::EnableActions : PackageInfoDialog::InformationOnly; +} + void PackagesWidget::setRightClickToOpenContextMenu(bool enable) { d->rightClickToOpenContextMenu = enable; @@ -794,15 +908,11 @@ void PackagesWidget::setFilterEditorMinimumY(Rule const &minY) { - d->search->rule().setInput(Rule::Top, OperatorRule::maximum(minY, rule().top() + margins().top())); + d->search->rule().setInput(Rule::Top, + OperatorRule::maximum(minY, rule().top() + margins().top())); changeRef(d->searchMinY, minY); } -/*void PackagesWidget::setMaximumPanelHeight(Rule const &maxHeight) -{ - //d->maxPanelHeight->setSource(maxHeight - d->search->rule().height() - rule("gap")); -}*/ - void PackagesWidget::setPackageStatus(IPackageStatus const &packageStatus) { d->packageStatus = &packageStatus; @@ -919,7 +1029,8 @@ // Estimate the position. scrollArea.scrollY(pos * d->menu->organizer().averageChildHeight() - - scrollArea.rule().height().value() / 2, 0.3); + scrollArea.rule().height().value() / 2, + 0.3); } } } @@ -929,19 +1040,6 @@ return *d->search; } -/* -void PackagesWidget::openContentOptions(ui::Item const &item) -{ - if (auto *widget = d->menu->organizer().itemWidget(item)) - { - if (auto *itemWidget = widget->maybeAs()) - { - itemWidget->openContentOptions(); - } - } -} -*/ - void PackagesWidget::initialize() { GuiWidget::initialize(); @@ -954,7 +1052,7 @@ if (d->searchMinY) { - TimeDelta const SPAN = 0.3; + TimeSpan const SPAN = 0.3; // Time to show or hide the background? if (d->searchBackgroundOpacity.target() < .5f && @@ -971,14 +1069,9 @@ // Update search field background opacity. d->search->setUnfocusedBackgroundOpacity(d->searchBackgroundOpacity); } - -// if (d->menu->isHidden() && DoomsdayApp::bundles().isEverythingIdentified()) -// { -// d->populate(); -// } } -void PackagesWidget::operator >> (PersistentState &toState) const +void PackagesWidget::operator>>(PersistentState &toState) const { if (name().isEmpty()) return; @@ -986,7 +1079,7 @@ rec.set(name().concatenateMember("search"), d->search->text()); } -void PackagesWidget::operator << (PersistentState const &fromState) +void PackagesWidget::operator<<(PersistentState const &fromState) { if (name().isEmpty()) return; @@ -994,9 +1087,3 @@ d->search->setText(rec.gets(name().concatenateMember("search"), "")); d->updateFilterTerms(true); } - -void PackagesWidget::refreshPackages() -{ - d->showProgressIndicator(true); - App::fileSystem().refresh(); -} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/privilegedlogwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -38,10 +38,16 @@ closeButton = new ButtonWidget; closeButton->setSizePolicy(ui::Expand, ui::Expand); + self().add(closeButton); + + updateStyle(); + } + + void updateStyle() + { + closeButton->setImageScale(.25f); closeButton->setImage(style().images().image("close.ringless")); - closeButton->setImageScale(toDevicePixels(.25f)); closeButton->setImageColor(style().colors().colorf("altaccent")); - self().add(closeButton); } }; @@ -75,3 +81,9 @@ hide(); d->log->clear(); } + +void PrivilegedLogWidget::updateStyle() +{ + GuiWidget::updateStyle(); + d->updateStyle(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/profilepickerwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/profilepickerwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/profilepickerwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/profilepickerwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -53,7 +53,7 @@ { button->setSizePolicy(ui::Expand, ui::Expand); button->setImage(style().images().image("gear")); - button->setOverrideImageSize(style().fonts().font("default").height().valuei()); + button->setOverrideImageSize(style().fonts().font("default").height()); } void populate() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/sidebarwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/sidebarwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/sidebarwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/sidebarwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -68,7 +68,7 @@ close->margins().set(rule("dialog.gap")); close->setImage(style().images().image("close.ringless")); close->setImageColor(title->textColorf()); - close->setOverrideImageSize(title->font().height().valuei()); + close->setOverrideImageSize(title->font().height()); close->setAction(new SignalAction(thisPublic, SLOT(close()))); close->setSizePolicy(ui::Expand, ui::Expand); } @@ -95,6 +95,7 @@ setSizePolicy(Fixed); setWaitForContentReady(false); setOpeningDirection(Left); + setAnimationStyle(Smooth); set(Background(style().colors().colorf("background")).withSolidFillOpacity(1)); d->title->setText(titleText); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/taskbarwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/taskbarwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/taskbarwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/taskbarwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -30,7 +30,6 @@ #include "ui/dialogs/inputsettingsdialog.h" #include "ui/dialogs/manualconnectiondialog.h" #include "ui/dialogs/networksettingsdialog.h" -#include "ui/dialogs/packagesdialog.h" #include "ui/dialogs/renderersettingsdialog.h" #include "ui/dialogs/uisettingsdialog.h" #include "ui/dialogs/videosettingsdialog.h" @@ -68,7 +67,7 @@ using namespace de; using namespace de::ui; -static TimeDelta OPEN_CLOSE_SPAN = 0.2; +static TimeSpan OPEN_CLOSE_SPAN = 0.2; enum MenuItemPositions { @@ -78,6 +77,7 @@ POS_GAMES_SEPARATOR = 3, POS_UNLOAD = 4, POS_PACKAGES = 7, + POS_PACKAGES_NOTE = 8, // Config menu: POS_RENDERER_SETTINGS = 0, @@ -281,6 +281,7 @@ itemWidget(mainMenu, POS_UNLOAD) .show(!game.isNull()); itemWidget(mainMenu, POS_GAMES_SEPARATOR) .show(!game.isNull()); itemWidget(mainMenu, POS_PACKAGES) .show(!game.isNull()); + itemWidget(mainMenu, POS_PACKAGES_NOTE) .show(!game.isNull()); //itemWidget(mainMenu, POS_IWAD_FOLDER) .show(game.isNull()); itemWidget(mainMenu, POS_HOME) .show(!game.isNull()); //itemWidget(mainMenu, POS_CONNECT) .show(game.isNull()); @@ -347,21 +348,16 @@ } }; +#if defined (DENG_HAVE_UPDATER) static PopupWidget *makeUpdaterSettings() { return new UpdaterSettingsDialog(UpdaterSettingsDialog::WithApplyAndCheckButton); } +#endif TaskBarWidget::TaskBarWidget() : GuiWidget("taskbar"), d(new Impl(this)) { -#if 0 - // GameWidget is presently too inefficient with blurring. - BlurWidget *blur = new BlurWidget("taskbar_blur"); - add(blur); - Background bg(*blur, style().colors().colorf("background")); -#else Background bg(style().colors().colorf("background")); -#endif Rule const &gap = rule("gap"); @@ -371,7 +367,14 @@ .setInput(Rule::Bottom, rule().bottom()) .setInput(Rule::Right, rule().right()) .setInput(Rule::Top, rule().top()); - d->backBlur->set(Background(ClientWindow::main().taskBarBlur(), Vector4f(1, 1, 1, 1))); + if (style().isBlurringAllowed()) + { + d->backBlur->set(Background(ClientWindow::main().taskBarBlur(), Vector4f(1, 1, 1, 1))); + } + else + { + d->backBlur->set(Background(Vector4f(0, 0, 0, 1))); + } add(d->backBlur); d->console = new ConsoleWidget; @@ -464,8 +467,11 @@ << new ui::SubwidgetItem(style().images().image("network"), tr("Network"), ui::Left, makePopup) << new ui::Item(ui::Item::Separator) << new ui::SubwidgetItem(style().images().image("package.icon"), tr("Data Files"), ui::Left, makePopup) - << new ui::SubwidgetItem(style().images().image("home.icon"), tr("User Interface"), ui::Left, makePopup) + << new ui::SubwidgetItem(style().images().image("home.icon"), tr("User Interface"), ui::Left, makePopup); +#if defined (DENG_HAVE_UPDATER) + d->configMenu->items() << new ui::SubwidgetItem(style().images().image("updater"), tr("Updater"), ui::Left, makeUpdaterSettings); +#endif auto *helpMenu = new ui::SubmenuItem(tr("Help"), ui::Left); helpMenu->items() @@ -481,15 +487,24 @@ << unloadMenu // hidden with null-game << new ui::Item(ui::Item::Separator) << new ui::Item(ui::Item::Separator, tr("Resources")) - << new ui::ActionItem(tr("Browse Packages..."), new SignalAction(this, SLOT(openPackagesSidebar()))) + << new ui::ActionItem(tr("Browse Mods..."), new SignalAction(this, SLOT(openPackagesSidebar()))) + << new ui::Item(ui::Item::Annotation, + tr("Load/unload data files and view package information.")) << new ui::ActionItem(tr("Clear Cache"), new CallbackAction([] () { DoomsdayApp::app().clearCache(); })) + << new ui::Item(ui::Item::Annotation, + tr("Forces a refresh of resource file metadata.")) << new ui::Item(ui::Item::Separator) << new ui::Item(ui::Item::Separator, tr("Doomsday")) +#if defined (DENG_HAVE_UPDATER) << new ui::ActionItem(tr("Check for Updates"), new CommandAction("updateandnotify")) +#endif << new ui::ActionItem(tr("About Doomsday"), new SignalAction(this, SLOT(showAbout()))) << helpMenu +#if !defined (DENG_MOBILE) << new ui::Item(ui::Item::Separator) - << new ui::ActionItem(tr("Quit Doomsday"), new CommandAction("quit!")); + << new ui::ActionItem(tr("Quit Doomsday"), new CommandAction("quit!")) +#endif + ; d->showOrHideMenuItems(); @@ -772,6 +787,7 @@ root().window().glDone(); } +#if defined (DENG_HAVE_UPDATER) void TaskBarWidget::showUpdaterSettings() { /// @todo This has actually little to do with the taskbar. -jk @@ -780,6 +796,7 @@ root().addOnTop(dlg); dlg->open(); } +#endif void TaskBarWidget::showOrHideHome() { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/tutorialwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/tutorialwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/widgets/tutorialwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/widgets/tutorialwidget.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -37,7 +37,7 @@ using namespace de; -static TimeDelta const FLASH_SPAN = 0.6; +static TimeSpan const FLASH_SPAN = 0.6; DENG_GUI_PIMPL(TutorialWidget) { @@ -72,7 +72,7 @@ exampleAlert.reset(new LabelWidget); exampleAlert->setSizePolicy(ui::Expand, ui::Expand); exampleAlert->setImage(style().images().image("alert")); - exampleAlert->setOverrideImageSize(style().fonts().font("default").height().value()); + exampleAlert->setOverrideImageSize(style().fonts().font("default").height()); exampleAlert->setImageColor(style().colors().colorf("accent")); // Highlight rectangle. @@ -248,12 +248,12 @@ break; case HomeScreen: - dlg->title().setText(tr("Home Screen")); + dlg->title().setText(tr("Game Library")); dlg->message().setText(tr("Here you can browse the library of available games " "and configure engine settings. You can also join ongoing " - "multiplayer games and manage your resource packages. " + "multiplayer games and manage your mods and resource packages. " "You can unload the current game at " - "any time to get back to the Home Screen.")); + "any time to get back to the Game Library.")); startHighlight(*root().guiFind("home")); break; @@ -298,7 +298,7 @@ "the application menu. " "You can check for available updates, switch games, or look for " "ongoing multiplayer games. You can also unload the current game " - "and return to Doomsday's Home Screen.")); + "and return to Doomsday's Game Library.")); win.taskBar().openMainMenu(); dlg->setAnchorAndOpeningDirection(root().guiFind("de-menu")->rule(), ui::Left); startHighlight(*root().guiFind("de-button")); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/zonedebug.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/zonedebug.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/ui/zonedebug.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/ui/zonedebug.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -24,7 +24,7 @@ #include "de_base.h" -#ifdef DENG_DEBUG +#if defined (DENG_DEBUG) && defined (DENG_OPENGL) #include #include @@ -60,9 +60,9 @@ int const availPixels = edge - x; int const usedPixels = de::min(availPixels, pixels); - LIBGUI_GL.glColor4fv(color); - LIBGUI_GL.glVertex2i(x, y); - LIBGUI_GL.glVertex2i(x + usedPixels, y); + DGL_Color4fv(color); + DGL_Vertex2f(x, y); + DGL_Vertex2f(x + usedPixels, y); pixels -= usedPixels; @@ -85,17 +85,17 @@ char *base = ((char *)volume->zone) + sizeof(memzone_t); // Clear the background. - LIBGUI_GL.glColor4f(0, 0, 0, opacity); + DGL_Color4f(0, 0, 0, opacity); GL_DrawRect(rect); // Outline. - LIBGUI_GL.glLineWidth(1); - LIBGUI_GL.glColor4f(1, 1, 1, opacity/2); +// GLInfo::setLineWidth(1); + DGL_Color4f(1, 1, 1, opacity/2); LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); GL_DrawRect(rect); LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - LIBGUI_GL.glBegin(GL_LINES); + DGL_Begin(DGL_LINES); // Visualize each block. for (memblock_t *block = volume->zone->blockList.next; @@ -121,12 +121,12 @@ drawRegion(*volume, rect, (char *)block - base, block->size, color); } - LIBGUI_GL.glEnd(); + DGL_End(); if (pd->isVolumeTooFull(volume)) { - LIBGUI_GL.glLineWidth(2); - LIBGUI_GL.glColor4f(1, 0, 0, 1); +// GLInfo::setLineWidth(2); + DGL_Color4f(1, 0, 0, 1); LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); GL_DrawRect(rect); LIBGUI_GL.glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -146,20 +146,19 @@ //glDisable(GL_CULL_FACE); //glDisable(GL_DEPTH_TEST); - GLState::push() - .setCull(gl::None) - .setDepthTest(false) - .apply(); + DGL_PushState(); + DGL_CullFace(DGL_NONE); + DGL_Disable(DGL_DEPTH_TEST); // Go into screen projection mode. - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); - LIBGUI_GL.glOrtho(0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, 0, -1, 1); - - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPushMatrix(); - LIBGUI_GL.glLoadIdentity(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PushMatrix(); + DGL_LoadIdentity(); + DGL_Ortho(0, 0, DENG_GAMEVIEW_WIDTH, DENG_GAMEVIEW_HEIGHT, -1, 1); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + DGL_LoadIdentity(); Z_GetPrivateData(&pd); @@ -186,14 +185,14 @@ pd.unlock(); - GLState::pop().apply(); + DGL_PopState(); // Cleanup. - LIBGUI_GL.glMatrixMode(GL_MODELVIEW); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); - LIBGUI_GL.glMatrixMode(GL_PROJECTION); - LIBGUI_GL.glPopMatrix(); + DGL_MatrixMode(DGL_PROJECTION); + DGL_PopMatrix(); } #endif // _DEBUG diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/downloaddialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/downloaddialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/downloaddialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/downloaddialog.cpp 1970-01-01 00:00:00.000000000 +0000 @@ -1,361 +0,0 @@ -/** @file downloaddialog.cpp Dialog that downloads a distribution package. - * @ingroup updater - * - * @authors Copyright © 2012-2017 Jaakko Keränen - * @authors Copyright © 2013 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include -#include "de_platform.h" -#include "updater/downloaddialog.h" -#include "updater/updatersettings.h" -#include "ui/widgets/taskbarwidget.h" -#include "ui/clientwindow.h" -#include "dd_version.h" -#include "network/net_main.h" - -#include -#include -#include -#include -#include -#include -#include - -#ifdef WIN32 -# undef open -#endif - -using namespace de; - -static DownloadDialog *downloadInProgress; - -DENG2_PIMPL(DownloadDialog) -{ - enum State { - Connecting, - MaybeRedirected, - Downloading, - Finished, - Error - }; - State state; - - QNetworkAccessManager* network; - ProgressWidget *progress; - QUrl uri; - QUrl uri2; - NativePath savedFilePath; - QNetworkReply *reply; - String redirected; - dint64 receivedBytes; - dint64 totalBytes; - String location; - String errorMessage; - - Impl(Public *d, String downloadUri, String fallbackUri) - : Base(d), state(Connecting), uri(downloadUri), uri2(fallbackUri), reply(0), - receivedBytes(0), totalBytes(0) - { - ScrollAreaWidget &area = self().area(); - - progress = new ProgressWidget; - area.add(progress); - progress->setImageScale(toDevicePixels(.4f)); - progress->setAlignment(ui::AlignLeft); - progress->setSizePolicy(ui::Fixed, ui::Expand); - progress->setRange(Rangei(0, 100)); - progress->rule() - .setLeftTop(area.contentRule().left(), area.contentRule().top()) - .setInput(Rule::Width, self().rule("dialog.download.width")); - - area.setContentSize(progress->rule().width(), progress->rule().height()); - - self().buttons() << new DialogButtonItem(DialogWidget::Reject, - tr("Cancel Download"), - new SignalAction(thisPublic, SLOT(cancel()))); - - updateLocation(uri); - updateProgress(); - - network = new QNetworkAccessManager(thisPublic); - QObject::connect(network, SIGNAL(finished(QNetworkReply *)), thisPublic, SLOT(finished(QNetworkReply *))); - - startDownload(); - } - - void updateLocation(QUrl const &url) - { - location = url.host(); - updateProgress(); - } - - void startDownload() - { - state = Connecting; - redirected.clear(); - - String path = uri.path(); - QDir::current().mkpath(UpdaterSettings().downloadPath()); // may not exist - savedFilePath = UpdaterSettings().downloadPath() / path.fileName(); - - QNetworkRequest request(uri); - request.setRawHeader("User-Agent", Net_UserAgent().toLatin1()); - reply = network->get(request); - - QObject::connect(reply, SIGNAL(metaDataChanged()), thisPublic, SLOT(replyMetaDataChanged())); - QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), thisPublic, SLOT(progress(qint64,qint64))); - - LOG_NOTE("Downloading %s, saving as: %s") << uri.toString() << savedFilePath; - - // Global state "flag". - downloadInProgress = thisPublic; - } - - void updateProgress() - { - String fn = savedFilePath.fileName(); - String msg; - - const double MB = 1.0e6; // MiB would be 2^20 - - switch (state) - { - default: - msg = String(tr("Connecting to %1")).arg(_E(b) + location + _E(.)); - break; - - case Downloading: - msg = String(tr("Downloading %1 (%2 MB) from %3")) - .arg(_E(b) + fn + _E(.)).arg(totalBytes / MB, 0, 'f', 1).arg(location); - break; - - case Finished: - msg = String(tr("Ready to install\n%1")).arg(_E(b) + fn + _E(.)); - break; - - case Error: - msg = String(tr("Failed to download:\n%1")).arg(_E(b) + errorMessage); - break; - } - - progress->setText(msg); - } -}; - -DownloadDialog::DownloadDialog(String downloadUri, String fallbackUri) - : DialogWidget("download"), d(new Impl(this, downloadUri, fallbackUri)) -{} - -DownloadDialog::~DownloadDialog() -{ - downloadInProgress = 0; -} - -String DownloadDialog::downloadedFilePath() const -{ - if (!isReadyToInstall()) return ""; - return d->savedFilePath; -} - -bool DownloadDialog::isReadyToInstall() const -{ - return d->state == Impl::Finished; -} - -bool DownloadDialog::isFailed() const -{ - return d->state == Impl::Error; -} - -void DownloadDialog::finished(QNetworkReply *reply) -{ - LOG_AS("Download"); - - reply->deleteLater(); - d->reply = 0; - - if (reply->error() != QNetworkReply::NoError) - { - LOG_WARNING("Failed: ") << reply->errorString(); - - d->state = Impl::Error; - d->errorMessage = reply->errorString(); - d->updateProgress(); - downloadInProgress = 0; - return; - } - - /// @todo If/when we include WebKit, this can be done more intelligently using QWebPage. -jk - - if (!d->redirected.isEmpty()) - { - LOG_NOTE("Redirected to: %s") << d->redirected; - d->uri = QUrl(d->redirected); - d->redirected.clear(); - d->startDownload(); - return; - } - - if (d->state == Impl::MaybeRedirected) - { - // This does not look like a binary file... Let's see if we can parse the page. - QString html = QString::fromUtf8(reply->readAll()); - - /// @todo Use a regular expression for parsing the redirection. - - int start = html.indexOf("uri2.isEmpty() && d->uri2 != d->uri) - { - d->uri = d->uri2; - d->updateLocation(d->uri); - d->startDownload(); - return; - } - - emit downloadFailed(d->uri.toString()); - return; - } - start = html.indexOf("url=\"", start, Qt::CaseInsensitive); - if (start < 0) - { - emit downloadFailed(d->uri.toString()); - return; - } - start += 5; // skip: url=" - QString equivRefresh = html.mid(start, html.indexOf("\"", start) - start); - equivRefresh.replace("&", "&"); - - // This is what we should actually be downloading. - d->uri = QUrl::fromEncoded(equivRefresh.toLatin1()); - - LOG_NOTE("Redirected to: %s") << d->uri.toString(); - - d->startDownload(); - return; - } - - // Save the received data. - QFile file(d->savedFilePath); - if (file.open(QFile::WriteOnly | QFile::Truncate)) - { - file.write(reply->readAll()); - } - else - { - LOG_WARNING("Failed to write to: %s") << d->savedFilePath; - emit downloadFailed(d->uri.toString()); - } - - buttons().clear() - << new DialogButtonItem(DialogWidget::Reject, tr("Delete"), - new SignalAction(this, SLOT(cancel()))) - << new DialogButtonItem(DialogWidget::Accept | DialogWidget::Default, tr("Install Update")); - - d->state = Impl::Finished; - d->progress->setRotationSpeed(0); - d->updateProgress(); - - // Make sure the finished download is noticed by the user. - showCompletedDownload(); - - LOG_DEBUG("Request finished"); -} - -void DownloadDialog::cancel() -{ - LOG_NOTE("Download cancelled due to user request"); - - d->state = Impl::Error; - d->progress->setRotationSpeed(0); - - if (d->reply) - { - d->reply->abort(); - buttons().clear() - << new DialogButtonItem(DialogWidget::Reject, tr("Close")); - } - else - { - reject(); - } -} - -void DownloadDialog::progress(qint64 received, qint64 total) -{ - LOG_AS("Download"); - - if (d->state == Impl::Downloading && total > 0) - { - d->totalBytes = total; - d->receivedBytes = received; - d->updateProgress(); - - dint64 percent = received * 100 / total; - d->progress->setProgress(percent); - - emit downloadProgress(percent); - } -} - -void DownloadDialog::replyMetaDataChanged() -{ - LOG_AS("Download"); - - String contentType = d->reply->header(QNetworkRequest::ContentTypeHeader).toString(); - String redirection = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); - - if (!redirection.isEmpty()) - { - d->redirected = redirection; - } - else if (contentType.startsWith("text/html")) - { - // Looks like a redirection page. - d->state = Impl::MaybeRedirected; - } - else - { - LOG_DEBUG("Receiving content of type '%s'") << contentType; - d->state = Impl::Downloading; - } -} - -bool DownloadDialog::isDownloadInProgress() -{ - return downloadInProgress != 0; -} - -DownloadDialog &DownloadDialog::currentDownload() -{ - DENG2_ASSERT(isDownloadInProgress()); - return *downloadInProgress; -} - -void DownloadDialog::showCompletedDownload() -{ - if (downloadInProgress && downloadInProgress->isReadyToInstall()) - { - ClientWindow::main().taskBar().openAndPauseGame(); - downloadInProgress->open(); - } -} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updateavailabledialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updateavailabledialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updateavailabledialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updateavailabledialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -34,7 +34,7 @@ using namespace de; -static TimeDelta const SHOW_ANIM_SPAN = 0.3; +static TimeSpan const SHOW_ANIM_SPAN = 0.3; DENG_GUI_PIMPL(UpdateAvailableDialog), DENG2_OBSERVES(ToggleWidget, Toggle) @@ -67,7 +67,7 @@ updateResult(latest, 0); } - void showProgress(bool show, TimeDelta span) + void showProgress(bool show, TimeSpan span) { checking->setOpacity(show? 1 : 0, span); self().area().setOpacity(show? 0 : 1, span); @@ -99,16 +99,23 @@ self().updateLayout(); } - void updateResult(Version const &latest, TimeDelta showSpan) + static bool isMatchingChannel(String const &channel, String const &buildType) + { + if (channel == buildType) return true; + if (channel == "RC/stable" && buildType != "unstable") return true; + return false; + } + + void updateResult(Version const &latest, TimeSpan showSpan) { showProgress(false, showSpan); latestVersion = latest; - Version currentVersion = Version::currentBuild(); - - String channel = (UpdaterSettings().channel() == UpdaterSettings::Stable? "stable" : "unstable"); - String builtInType = (String(DOOMSDAY_RELEASE_TYPE) == "Stable"? "stable" : "unstable"); + Version const currentVersion = Version::currentBuild(); + String const channel = (UpdaterSettings().channel() == UpdaterSettings::Stable? "stable" : + UpdaterSettings().channel() == UpdaterSettings::Unstable? "unstable" : "RC/stable"); + String const builtInType = String(DOOMSDAY_RELEASE_TYPE).toLower(); bool askUpgrade = false; bool askDowngrade = false; @@ -123,7 +130,7 @@ .arg(_E(b) + latestVersion.asHumanReadableText() + _E(.)) .arg(currentVersion.asHumanReadableText())); } - else if (channel == builtInType) // same release type + else if (isMatchingChannel(channel, builtInType)) // same release type { self().title().setText(tr("Up to Date")); self().message().setText(tr("The installed %1 is the latest available %2 build.") diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatedownloaddialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatedownloaddialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatedownloaddialog.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatedownloaddialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,343 @@ +/** @file updatedownloaddialog.cpp Dialog that downloads a distribution package. + * @ingroup updater + * + * @authors Copyright © 2012-2017 Jaakko Keränen + * @authors Copyright © 2013 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include +#include "de_platform.h" +#include "updater/updatedownloaddialog.h" +#include "updater/updatersettings.h" +#include "ui/widgets/taskbarwidget.h" +#include "ui/clientwindow.h" +#include "dd_version.h" +#include "network/net_main.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef WIN32 +# undef open +#endif + +using namespace de; + +static UpdateDownloadDialog *downloadInProgress; + +DENG_GUI_PIMPL(UpdateDownloadDialog) +{ + enum State { + Connecting, + MaybeRedirected, + Downloading, + Finished, + Error + }; + State state; + + QNetworkAccessManager* network; + QUrl uri; + QUrl uri2; + NativePath savedFilePath; + QNetworkReply *reply; + String redirected; + dint64 receivedBytes; + dint64 totalBytes; + String location; + String errorMessage; + + Impl(Public *d, String downloadUri, String fallbackUri) + : Base(d), state(Connecting), uri(downloadUri), uri2(fallbackUri), reply(0), + receivedBytes(0), totalBytes(0) + { + updateLocation(uri); + updateProgress(); + + network = new QNetworkAccessManager(thisPublic); + QObject::connect(network, SIGNAL(finished(QNetworkReply *)), thisPublic, SLOT(finished(QNetworkReply *))); + + startDownload(); + } + + void updateLocation(QUrl const &url) + { + location = url.host(); + updateProgress(); + } + + void startDownload() + { + state = Connecting; + redirected.clear(); + + String path = uri.path(); + QDir::current().mkpath(UpdaterSettings().downloadPath()); // may not exist + savedFilePath = UpdaterSettings().downloadPath() / path.fileName(); + + QNetworkRequest request(uri); + request.setRawHeader("User-Agent", Version::currentBuild().userAgent().toLatin1()); + reply = network->get(request); + + QObject::connect(reply, SIGNAL(metaDataChanged()), thisPublic, SLOT(replyMetaDataChanged())); + QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), thisPublic, SLOT(progress(qint64,qint64))); + + LOG_NOTE("Downloading %s, saving as: %s") << uri.toString() << savedFilePath; + + // Global state "flag". + downloadInProgress = thisPublic; + } + + void updateProgress() + { + String fn = savedFilePath.fileName(); + String msg; + + const double MB = 1.0e6; // MiB would be 2^20 + + switch (state) + { + default: + msg = String(tr("Connecting to %1")).arg(_E(b) + location + _E(.)); + break; + + case Downloading: + msg = String(tr("Downloading %1 (%2 MB) from %3")) + .arg(_E(b) + fn + _E(.)).arg(totalBytes / MB, 0, 'f', 1).arg(location); + break; + + case Finished: + msg = String(tr("Ready to install\n%1")).arg(_E(b) + fn + _E(.)); + break; + + case Error: + msg = String(tr("Failed to download:\n%1")).arg(_E(b) + errorMessage); + break; + } + + self().progressIndicator().setText(msg); + } +}; + +UpdateDownloadDialog::UpdateDownloadDialog(String downloadUri, String fallbackUri) + : DownloadDialog("download") + , d(new Impl(this, downloadUri, fallbackUri)) +{} + +UpdateDownloadDialog::~UpdateDownloadDialog() +{ + downloadInProgress = 0; +} + +String UpdateDownloadDialog::downloadedFilePath() const +{ + if (!isReadyToInstall()) return ""; + return d->savedFilePath; +} + +bool UpdateDownloadDialog::isReadyToInstall() const +{ + return d->state == Impl::Finished; +} + +bool UpdateDownloadDialog::isFailed() const +{ + return d->state == Impl::Error; +} + +void UpdateDownloadDialog::finished(QNetworkReply *reply) +{ + LOG_AS("Download"); + + reply->deleteLater(); + d->reply = 0; + + if (reply->error() != QNetworkReply::NoError) + { + LOG_WARNING("Failed: ") << reply->errorString(); + + d->state = Impl::Error; + d->errorMessage = reply->errorString(); + d->updateProgress(); + downloadInProgress = 0; + return; + } + + /// @todo If/when we include WebKit, this can be done more intelligently using QWebPage. -jk + + if (!d->redirected.isEmpty()) + { + LOG_NOTE("Redirected to: %s") << d->redirected; + d->uri = QUrl(d->redirected); + d->redirected.clear(); + d->startDownload(); + return; + } + + if (d->state == Impl::MaybeRedirected) + { + // This does not look like a binary file... Let's see if we can parse the page. + QString html = QString::fromUtf8(reply->readAll()); + + /// @todo Use a regular expression for parsing the redirection. + + int start = html.indexOf("uri2.isEmpty() && d->uri2 != d->uri) + { + d->uri = d->uri2; + d->updateLocation(d->uri); + d->startDownload(); + return; + } + + emit downloadFailed(d->uri.toString()); + return; + } + start = html.indexOf("url=\"", start, Qt::CaseInsensitive); + if (start < 0) + { + emit downloadFailed(d->uri.toString()); + return; + } + start += 5; // skip: url=" + QString equivRefresh = html.mid(start, html.indexOf("\"", start) - start); + equivRefresh.replace("&", "&"); + + // This is what we should actually be downloading. + d->uri = QUrl::fromEncoded(equivRefresh.toLatin1()); + + LOG_NOTE("Redirected to: %s") << d->uri.toString(); + + d->startDownload(); + return; + } + + // Save the received data. + QFile file(d->savedFilePath); + if (file.open(QFile::WriteOnly | QFile::Truncate)) + { + file.write(reply->readAll()); + } + else + { + LOG_WARNING("Failed to write to: %s") << d->savedFilePath; + emit downloadFailed(d->uri.toString()); + } + + buttons().clear() + << new DialogButtonItem(DialogWidget::Reject, tr("Delete"), + new SignalAction(this, SLOT(cancel()))) + << new DialogButtonItem(DialogWidget::Accept | DialogWidget::Default, tr("Install Update")); + + d->state = Impl::Finished; + progressIndicator().setRotationSpeed(0); + d->updateProgress(); + + // Make sure the finished download is noticed by the user. + showCompletedDownload(); + + LOG_DEBUG("Request finished"); +} + +void UpdateDownloadDialog::cancel() +{ + LOG_NOTE("Download cancelled due to user request"); + + d->state = Impl::Error; + progressIndicator().setRotationSpeed(0); + + if (d->reply) + { + d->reply->abort(); + buttons().clear() + << new DialogButtonItem(DialogWidget::Reject, tr("Close")); + } + else + { + reject(); + } +} + +void UpdateDownloadDialog::progress(qint64 received, qint64 total) +{ + LOG_AS("Download"); + + if (d->state == Impl::Downloading && total > 0) + { + d->totalBytes = total; + d->receivedBytes = received; + d->updateProgress(); + + int const percent = int(received * 100 / total); + progressIndicator().setProgress(percent); + + emit downloadProgress(percent); + } +} + +void UpdateDownloadDialog::replyMetaDataChanged() +{ + LOG_AS("Download"); + + String contentType = d->reply->header(QNetworkRequest::ContentTypeHeader).toString(); + String redirection = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString(); + + if (!redirection.isEmpty()) + { + d->redirected = redirection; + } + else if (contentType.startsWith("text/html")) + { + // Looks like a redirection page. + d->state = Impl::MaybeRedirected; + } + else + { + LOG_DEBUG("Receiving content of type '%s'") << contentType; + d->state = Impl::Downloading; + } +} + +bool UpdateDownloadDialog::isDownloadInProgress() +{ + return downloadInProgress != 0; +} + +UpdateDownloadDialog &UpdateDownloadDialog::currentDownload() +{ + DENG2_ASSERT(isDownloadInProgress()); + return *downloadInProgress; +} + +void UpdateDownloadDialog::showCompletedDownload() +{ + if (downloadInProgress && downloadInProgress->isReadyToInstall()) + { + ClientWindow::main().taskBar().openAndPauseGame(); + downloadInProgress->open(); + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updater.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updater.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updater.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updater.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -52,9 +52,9 @@ #include "ui/clientwindow.h" #include "ui/widgets/taskbarwidget.h" #include "updater.h" -#include "updater/downloaddialog.h" #include "updater/processcheckdialog.h" #include "updater/updateavailabledialog.h" +#include "updater/updatedownloaddialog.h" #include "updater/updatersettings.h" #include "updater/updatersettingsdialog.h" @@ -74,30 +74,7 @@ # define INSTALL_SCRIPT_NAME "deng-upgrade.scpt" #endif -/// @todo The platform ID should come from the Builder. -#if defined(WIN32) -# if defined(__64BIT__) -# define PLATFORM_ID "win-x64" -# else -# define PLATFORM_ID "win-x86" -# endif - -#elif defined(MACOSX) -# if defined(MACOS_10_7) || defined(MACOSX_NATIVESDK) -# define PLATFORM_ID "mac10_8-x86_64" -# elif defined(__64BIT__) -# define PLATFORM_ID "mac10_6-x86-x86_64" -# else -# define PLATFORM_ID "mac10_4-x86-ppc" -# endif - -#else -# if defined(__64BIT__) -# define PLATFORM_ID "linux-x86_64" -# else -# define PLATFORM_ID "linux-x86" -# endif -#endif +#define PLATFORM_ID DENG_PLATFORM_ID static CommandLine* installerCommand; @@ -167,7 +144,7 @@ , DENG2_OBSERVES(App, StartupComplete) { QNetworkAccessManager *network = nullptr; - DownloadDialog *download = nullptr; // not owned (in the widget tree, if exists) + UpdateDownloadDialog *download = nullptr; // not owned (in the widget tree, if exists) UniqueWidgetPtr status; UpdateAvailableDialog *availableDlg = nullptr; ///< If currently open (not owned). bool alwaysShowNotification; @@ -208,12 +185,12 @@ QString composeCheckUri() { UpdaterSettings st; - QString uri = QString(DOOMSDAY_HOMEURL) + "/latestbuild?"; - uri += QString("platform=") + PLATFORM_ID; - uri += (st.channel() == UpdaterSettings::Stable? "&stable" : "&unstable"); - uri += "&graph"; - - LOG_XVERBOSE("Check URI: ", uri); + String uri = String("%1builds?latest_for=%2&type=%3") + .arg(App::apiUrl()) + .arg(DENG_PLATFORM_ID) + .arg(st.channel() == UpdaterSettings::Stable? "stable" : + st.channel() == UpdaterSettings::Unstable? "unstable" : "candidate"); + LOG_XVERBOSE("URI: ", uri); return uri; } @@ -328,6 +305,7 @@ if (!result.isValid()) return; QVariantMap const map = result.toMap(); + if (!map.contains("direct_download_uri")) return; latestPackageUri = map["direct_download_uri"].toString(); latestLogUri = map["release_changeloguri"].toString(); @@ -426,7 +404,7 @@ LOG_MSG("Download and install update"); - download = new DownloadDialog(latestPackageUri, latestPackageUri2); + download = new UpdateDownloadDialog(latestPackageUri, latestPackageUri2); status->popupButton().setPopup(*download, ui::Down); QObject::connect(download, SIGNAL(closed()), thisPublic, SLOT(downloadDialogClosed())); QObject::connect(download, SIGNAL(downloadProgress(int)),thisPublic, SLOT(downloadProgressed(int))); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatersettings.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatersettings.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatersettings.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatersettings.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -165,7 +165,7 @@ de::Time when = lastCheckTime(); if (!when.isValid()) return ""; // Never checked. - de::TimeDelta delta = when.since(); + de::TimeSpan delta = when.since(); if (delta < 0.0) return ""; int t; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatersettingsdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatersettingsdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/updater/updatersettingsdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/updater/updatersettingsdialog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -104,11 +104,11 @@ releaseLabel->setText("Release Type:"); channels->items() - << new ChoiceItem(tr("Stable"), UpdaterSettings::Stable) - << new ChoiceItem(tr("Unstable/Candidate"), UpdaterSettings::Unstable); + << new ChoiceItem(tr("Stable only"), UpdaterSettings::Stable) + << new ChoiceItem(tr("RC or stable"), UpdaterSettings::StableOrCandidate) + << new ChoiceItem(tr("Unstable/nightly"), UpdaterSettings::Unstable); /*pathLabel->setText(tr("Download location:")); - paths->items() << new ChoiceItem(defaultLocationName(), UpdaterSettings::defaultDownloadPath().toString());*/ @@ -132,7 +132,7 @@ << Const(0) << *deleteAfter; //<< *pathLabel << *paths; - area.setContentSize(layout.width(), layout.height()); + area.setContentSize(layout); self().buttons() << new DialogButtonItem(DialogWidget::Default | DialogWidget::Accept, tr("Close")); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/blockmap.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/blockmap.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/blockmap.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/blockmap.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -23,6 +23,8 @@ #ifdef __CLIENT__ # include +# include "api_gl.h" +# include "gl/gl_main.h" #endif #include @@ -727,12 +729,13 @@ #define UNIT_SIZE 1 // We'll be changing the color, so query the current and restore later. - GLfloat oldColor[4]; LIBGUI_GL.glGetFloatv(GL_CURRENT_COLOR, oldColor); + GLfloat oldColor[4]; + DGL_CurrentColor(oldColor); /* * Draw the Quadtree. */ - LIBGUI_GL.glColor4f(1.f, 1.f, 1.f, 1.f / d->nodes.first().size); + DGL_Color4f(1.f, 1.f, 1.f, 1.f / d->nodes.first().size); foreach(Impl::Node const &node, d->nodes) { // Only leafs with user data. @@ -742,12 +745,13 @@ Vector2f const topLeft = node.cell * UNIT_SIZE; Vector2f const bottomRight = topLeft + Vector2f(UNIT_SIZE, UNIT_SIZE); - LIBGUI_GL.glBegin(GL_LINE_LOOP); - LIBGUI_GL.glVertex2f(topLeft.x, topLeft.y); - LIBGUI_GL.glVertex2f(bottomRight.x, topLeft.y); - LIBGUI_GL.glVertex2f(bottomRight.x, bottomRight.y); - LIBGUI_GL.glVertex2f(topLeft.x, bottomRight.y); - LIBGUI_GL.glEnd(); + DGL_Begin(DGL_LINE_STRIP); + DGL_Vertex2f(topLeft.x, topLeft.y); + DGL_Vertex2f(bottomRight.x, topLeft.y); + DGL_Vertex2f(bottomRight.x, bottomRight.y); + DGL_Vertex2f(topLeft.x, bottomRight.y); + DGL_Vertex2f(topLeft.x, topLeft.y); + DGL_End(); } /* @@ -756,23 +760,23 @@ Vector2f start; Vector2f end = start + d->dimensions * UNIT_SIZE; - LIBGUI_GL.glColor3f(1, .5f, .5f); - LIBGUI_GL.glBegin(GL_LINES); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glVertex2f( end.x, start.y); - - LIBGUI_GL.glVertex2f( end.x, start.y); - LIBGUI_GL.glVertex2f( end.x, end.y); - - LIBGUI_GL.glVertex2f( end.x, end.y); - LIBGUI_GL.glVertex2f(start.x, end.y); - - LIBGUI_GL.glVertex2f(start.x, end.y); - LIBGUI_GL.glVertex2f(start.x, start.y); - LIBGUI_GL.glEnd(); + DGL_Color3f(1, .5f, .5f); + DGL_Begin(DGL_LINES); + DGL_Vertex2f(start.x, start.y); + DGL_Vertex2f( end.x, start.y); + + DGL_Vertex2f( end.x, start.y); + DGL_Vertex2f( end.x, end.y); + + DGL_Vertex2f( end.x, end.y); + DGL_Vertex2f(start.x, end.y); + + DGL_Vertex2f(start.x, end.y); + DGL_Vertex2f(start.x, start.y); + DGL_End(); // Restore GL state. - LIBGUI_GL.glColor4fv(oldColor); + DGL_Color4fv(oldColor); #undef UNIT_SIZE } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/clientserverworld.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/clientserverworld.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/clientserverworld.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/clientserverworld.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -26,11 +26,12 @@ #include #include #include +#include #include #include -#include -#include +#include #include +#include #include #include #include @@ -146,7 +147,7 @@ */ void setMap(Map *newMap) { - if(_map != newMap) + if (_map != newMap) { observeMap(false); _map = newMap; @@ -178,40 +179,40 @@ */ void writeLog() { - if(dint numToLog = maxWarnings(unclosedSectorCount())) + if (dint numToLog = maxWarnings(unclosedSectorCount())) { String str; UnclosedSectorMap::const_iterator it = _unclosedSectors.begin(); - for(dint i = 0; i < numToLog; ++i, ++it) + for (dint i = 0; i < numToLog; ++i, ++it) { - if(i != 0) str += "\n"; + if (i != 0) str += "\n"; str += String("Sector #%1 is unclosed near %2") .arg(it->first).arg(it->second.asText()); } - if(numToLog < unclosedSectorCount()) + if (numToLog < unclosedSectorCount()) str += String("\n(%1 more like this)").arg(unclosedSectorCount() - numToLog); - LOG_MAP_WARNING("%s") << str; + LOGDEV_MAP_WARNING("%s") << str; } - if(dint numToLog = maxWarnings(oneWayWindowCount())) + if (dint numToLog = maxWarnings(oneWayWindowCount())) { String str; OneWayWindowMap::const_iterator it = _oneWayWindows.begin(); - for(dint i = 0; i < numToLog; ++i, ++it) + for (dint i = 0; i < numToLog; ++i, ++it) { - if(i != 0) str += "\n"; + if (i != 0) str += "\n"; str += String("Line #%1 seems to be a One-Way Window (back faces sector #%2).") .arg(it->first).arg(it->second); } - if(numToLog < oneWayWindowCount()) + if (numToLog < oneWayWindowCount()) str += String("\n(%1 more like this)").arg(oneWayWindowCount() - numToLog); - LOG_MAP_VERBOSE("%s") << str; + LOGDEV_MAP_MSG("%s") << str; } } @@ -251,9 +252,9 @@ void observeMap(bool yes) { - if(!_map) return; + if (!_map) return; - if(yes) + if (yes) { _map->audienceForDeletion() += this; _map->audienceForOneWayWindowFound += this; @@ -287,7 +288,7 @@ DENG2_ASSERT(!sourcePath.isEmpty()); dushort id = 0; - for(dint i = 0; i < sourcePath.size(); ++i) + for (dint i = 0; i < sourcePath.size(); ++i) { id ^= sourcePath.at(i).unicode() << ((i * 3) % 11); } @@ -302,6 +303,7 @@ Record fallbackMapInfo; ///< Used when no effective MapInfo definition. timespan_t time = 0; ///< World-wide time. + Scheduler scheduler; #if 0 #ifdef __CLIENT__ std::unique_ptr hand; ///< For map editing/manipulation. @@ -347,7 +349,7 @@ */ static Path cachePath(String sourcePath) { - if(sourcePath.isEmpty()) return String(); + if (sourcePath.isEmpty()) return String(); // Compose the final path. return mapCacheDir + App_CurrentGame().id() @@ -367,12 +369,12 @@ Map *convertMap(res::MapManifest const &mapManifest, MapConversionReporter *reporter = nullptr) { // We require a map converter for this. - if(!Plug_CheckForHook(HOOK_MAP_CONVERT)) + if (!Plug_CheckForHook(HOOK_MAP_CONVERT)) return nullptr; LOG_DEBUG("Attempting \"%s\"...") << mapManifest.composeUri().path(); - if(!mapManifest.sourceFile()) return nullptr; + if (!mapManifest.sourceFile()) return nullptr; // Initiate the conversion process. MPE_Begin(nullptr/*dummy*/); @@ -382,7 +384,7 @@ // Associate the map with its corresponding manifest. newMap->setManifest(&const_cast(mapManifest)); - if(reporter) + if (reporter) { // Instruct the reporter to begin observing the conversion. reporter->setMap(newMap); @@ -391,7 +393,7 @@ // Ask each converter in turn whether the map format is recognizable // and if so to interpret and transfer it to us via the runtime map // editing interface. - if(!DoomsdayApp::plugins().callAllHooks(HOOK_MAP_CONVERT, 0, + if (!DoomsdayApp::plugins().callAllHooks(HOOK_MAP_CONVERT, 0, const_cast(&mapManifest.recognizer()))) return nullptr; @@ -411,7 +413,7 @@ bool haveCachedMap(res::MapManifest &mapManifest) { // Disabled? - if(!mapCache) return false; + if (!mapCache) return false; return DAM_MapIsValid(mapManifest.cachePath, mapManifest.id()); } @@ -426,7 +428,7 @@ { Uri const mapUri = mapManifest.composeUri(); Map *map = DAM_MapRead(mapManifest.cachePath); - if(!map) + if (!map) /// Failed to load the map specified from the data cache. throw Error("loadMapFromCache", "Failed loading map \"" + mapUri.asText() + "\" from cache"); @@ -444,18 +446,18 @@ { LOG_AS("ClientServerWorld::loadMap"); - /*if(mapManifest.lastLoadAttemptFailed && !forceRetry) + /*if (mapManifest.lastLoadAttemptFailed && !forceRetry) return nullptr; // Load from cache? - if(haveCachedMap(mapManifest)) + if (haveCachedMap(mapManifest)) { return loadMapFromCache(mapManifest); }*/ // Try a JIT conversion with the help of a plugin. Map *map = convertMap(mapManifest, reporter); - if(!map) + if (!map) { LOG_WARNING("Failed conversion of \"%s\".") << mapManifest.composeUri().path(); //mapManifest.lastLoadAttemptFailed = true; @@ -470,13 +472,13 @@ { // This is now the current map (if any). self().setMap(map); - if(!map) return; + if (!map) return; // We cannot make an editable map current. DENG2_ASSERT(!map->isEditable()); // Should we cache this map? - /*if(mapCache && !haveCachedMap(&map->def())) + /*if (mapCache && !haveCachedMap(&map->def())) { // Ensure the destination directory exists. F_MakePath(map->def().cachePath.toUtf8().constData()); @@ -508,7 +510,7 @@ #ifdef __CLIENT__ // Reconfigure the sky. defn::Sky skyDef; - if(Record const *def = DED_Definitions()->skies.tryFind("id", mapInfo.gets("skyId"))) + if (Record const *def = DED_Definitions()->skies.tryFind("id", mapInfo.gets("skyId"))) { skyDef = *def; } @@ -542,13 +544,13 @@ // The game may need to perform it's own finalization now that the // "current" map has changed. - de::Uri const mapUri = (map->hasManifest() ? map->manifest().composeUri() : de::Uri("Maps:", RC_NULL)); - if(gx.FinalizeMapChange) + de::Uri const mapUri = (map->hasManifest() ? map->manifest().composeUri() : de::makeUri("Maps:")); + if (gx.FinalizeMapChange) { gx.FinalizeMapChange(reinterpret_cast(&mapUri)); } - if(gameTime > 20000000 / TICSPERSEC) + if (gameTime > 20000000 / TICSPERSEC) { // In very long-running games, gameTime will become so large that // it cannot be accurately converted to 35 Hz integer tics. Thus it @@ -607,7 +609,7 @@ #endif #ifdef __SERVER__ - if(::isServer) + if (::isServer) { // Init server data. Sv_InitPools(); @@ -642,7 +644,8 @@ // Rewind/restart material animators. /// @todo Only rewind animators responsible for map-surface contexts. - world::Materials::get().forAllMaterials([] (world::Material &material) + world::Materials::get().updateLookup(); + world::Materials::get().forAnimatedMaterials([] (world::Material &material) { return material.as().forAllAnimators([] (MaterialAnimator &animator) { @@ -658,17 +661,17 @@ // Run any commands specified in MapInfo. String execute = mapInfo.gets("execute"); - if(!execute.isEmpty()) + if (!execute.isEmpty()) { Con_Execute(CMDS_SCRIPT, execute.toUtf8().constData(), true, false); } // Run the special map setup command, which the user may alias to do // something useful. - if(!mapUri.isEmpty()) + if (!mapUri.isEmpty()) { String cmd = String("init-") + mapUri.path(); - if(Con_IsValidCommand(cmd.toUtf8().constData())) + if (Con_IsValidCommand(cmd.toUtf8().constData())) { Con_Executef(CMDS_SCRIPT, false, "%s", cmd.toUtf8().constData()); } @@ -703,8 +706,10 @@ { Map *map = self().mapPtr(); + scheduler.clear(); + #ifdef __CLIENT__ - if(map) + if (map) { // Remove the current map from our audiences. /// @todo Map should handle this. @@ -727,7 +732,7 @@ Z_FreeTags(PU_MAP, PU_PURGELEVEL - 1); // Are we just unloading the current map? - if(!mapManifest) return true; + if (!mapManifest) return true; LOG_MSG("Loading map \"%s\"...") << mapManifest->composeUri().path(); @@ -737,7 +742,7 @@ // Attempt to load in the new map. MapConversionReporter reporter; Map *newMap = loadMap(*mapManifest, &reporter); - if(newMap) + if (newMap) { // The map may still be in an editable state -- switch to playable. bool const mapIsPlayable = newMap->endEditing(); @@ -745,7 +750,7 @@ // Cancel further reports about the map. reporter.setMap(nullptr); - if(!mapIsPlayable) + if (!mapIsPlayable) { // Darn. Discard the useless data. delete newMap; newMap = nullptr; @@ -792,7 +797,7 @@ Map &ClientServerWorld::map() const { - if(!hasMap()) + if (!hasMap()) { /// @throw MapError Attempted with no map loaded. throw MapError("ClientServerWorld::map", "No map is currently loaded"); @@ -804,13 +809,13 @@ { res::MapManifest *mapDef = nullptr; - if(!mapUri.path().isEmpty()) + if (!mapUri.path().isEmpty()) { mapDef = App_Resources().mapManifests().tryFindMapManifest(mapUri); } // Switch to busy mode (if we haven't already) except when simply unloading. - if(!mapUri.path().isEmpty() && !DoomsdayApp::app().busyMode().isActive()) + if (!mapUri.path().isEmpty() && !DoomsdayApp::app().busyMode().isActive()) { /// @todo Use progress bar mode and update progress during the setup. return DoomsdayApp::app().busyMode().runNewTaskWithName( @@ -831,7 +836,7 @@ World::reset(); #ifdef __CLIENT__ - if(isClient) + if (isClient) { Cl_ResetFrame(); Cl_InitPlayers(); @@ -847,7 +852,7 @@ DoomsdayApp::players().forAll([] (Player &plr) { // States have changed, the state pointers are unknown. - for(ddpsprite_t &pspr : plr.publicData().pSprites) + for (ddpsprite_t &pspr : plr.publicData().pSprites) { pspr.statePtr = nullptr; } @@ -855,21 +860,26 @@ }); // Update the current map, also. - if(hasMap()) + if (hasMap()) { map().update(); } } +Scheduler &ClientServerWorld::scheduler() +{ + return d->scheduler; +} + Record const &ClientServerWorld::mapInfoForMapUri(de::Uri const &mapUri) const { // Is there a MapInfo definition for the given URI? - if(Record const *def = DED_Definitions()->mapInfos.tryFind("id", mapUri.compose())) + if (Record const *def = DED_Definitions()->mapInfos.tryFind("id", mapUri.compose())) { return *def; } // Is there is a default definition (for all maps)? - if(Record const *def = DED_Definitions()->mapInfos.tryFind("id", de::Uri("Maps", Path("*")).compose())) + if (Record const *def = DED_Definitions()->mapInfos.tryFind("id", de::Uri("Maps", Path("*")).compose())) { return *def; } @@ -879,10 +889,13 @@ void ClientServerWorld::advanceTime(timespan_t delta) { -#ifdef __CLIENT__ - if(::clientPaused) return; +#if defined (__CLIENT__) + if (!::clientPaused) #endif - d->time += delta; + { + d->time += delta; + d->scheduler.advanceTime(TimeSpan(delta)); + } } timespan_t ClientServerWorld::time() const @@ -893,11 +906,11 @@ void ClientServerWorld::tick(timespan_t elapsed) { #ifdef __CLIENT__ - if(hasMap()) + if (hasMap()) { map().skyAnimator().advanceTime(elapsed); - if(DD_IsSharpTick()) + if (DD_IsSharpTick()) { map().thinkers().forAll(reinterpret_cast(gx.MobjThinker), 0x1, [] (thinker_t *th) { @@ -916,16 +929,16 @@ Hand &ClientServerWorld::hand(ddouble *distance) const { // Time to create the hand? - if(!d->hand) + if (!d->hand) { d->hand.reset(new Hand()); audienceForFrameEnd() += *d->hand; - if(hasMap()) + if (hasMap()) { d->updateHandOrigin(); } } - if(distance) + if (distance) { *distance = handDistance; } @@ -942,12 +955,12 @@ void ClientServerWorld::endFrame() { #if 0 - if(hasMap() && d->hand) + if (hasMap() && d->hand) { d->updateHandOrigin(); // If the HueCircle is active update the current edit color. - if(HueCircle *hueCircle = SBE_HueCircle()) + if (HueCircle *hueCircle = SBE_HueCircle()) { viewdata_t const *viewData = &viewPlayer->viewport(); d->hand->setEditColor(hueCircle->colorAt(viewData->frontVec)); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/line.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/line.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/line.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/line.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -788,15 +788,15 @@ forever { // Select the next line. - binangle_t diff = (direction == Clockwise ? own->angle() : own->prev().angle()); - Line const *iter = &own->navigate(direction).line(); + binangle_t diff = (direction == Clockwise ? own->angle() : own->prev()->angle()); + Line const *iter = &own->navigate(direction)->line(); dint scanSecSide = (iter->front().hasSector() && iter->front().sectorPtr() == startSector ? Line::Back : Line::Front); // Step selfreferencing lines. while ((!iter->front().hasSector() && !iter->back().hasSector()) || iter->isSelfReferencing()) { - own = &own->navigate(direction); - diff += (direction == Clockwise ? own->angle() : own->prev().angle()); - iter = &own->navigate(direction).line(); + own = own->navigate(direction); + diff += (direction == Clockwise ? own->angle() : own->prev()->angle()); + iter = &own->navigate(direction)->line(); scanSecSide = (iter->front().sectorPtr() == startSector); } @@ -890,11 +890,11 @@ } // Swap to the iter line's owner node (i.e., around the corner)? - if (&own->navigate(direction) == iter->v2Owner()) + if (own->navigate(direction) == iter->v2Owner()) { own = iter->v1Owner(); } - else if (&own->navigate(direction) == iter->v1Owner()) + else if (own->navigate(direction) == iter->v1Owner()) { own = iter->v2Owner(); } @@ -913,7 +913,7 @@ if (backNeighbor && backNeighbor != iter) { // Into the back neighbor sector. - own = &own->navigate(direction); + own = own->navigate(direction); startSector = scanSector; } } @@ -1420,7 +1420,7 @@ if (isSelfReferencing()) return false; // Lines with no other neighbor do not qualify as shadow casters. - if (&v1Owner()->next().line() == this || &v2Owner()->next().line() == this) + if (&v1Owner()->next()->line() == this || &v2Owner()->next()->line() == this) return false; return true; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/map.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/map.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/map.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/map.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -454,7 +454,7 @@ if (de::abs(line.direction().x) < bsp::DIST_EPSILON) return; - if( (line.bounds().maxX < p.testLineCenter.x - bsp::DIST_EPSILON) + if ( (line.bounds().maxX < p.testLineCenter.x - bsp::DIST_EPSILON) || (line.bounds().minX > p.testLineCenter.x + bsp::DIST_EPSILON)) return; @@ -638,7 +638,7 @@ auto &leaf = cur->userData()->as(); if (!leaf.sectorPtr()) { - LOG_MAP_WARNING("BSP leaf %p has degenerate geometry (%d half-edges).") + LOGDEV_MAP_WARNING("BSP leaf %p has degenerate geometry (%d half-edges).") << &leaf << (leaf.hasSubspace()? leaf.subspace().poly().hedgeCount() : 0); } @@ -660,10 +660,10 @@ } } while ((hedge = &hedge->next()) != subspace.poly().hedge()); - if(discontinuities) + if (discontinuities) { - LOG_MAP_WARNING("Face geometry for BSP leaf [%p] at %s in sector %i " - "is not contiguous (%i gaps/overlaps).\n%s") + LOGDEV_MAP_WARNING("Face geometry for BSP leaf [%p] at %s in sector %i " + "is not contiguous (%i gaps/overlaps).\n%s") << &leaf << subspace.poly().center().asText() << (leaf.sectorPtr()? leaf.sectorPtr()->indexInArchive() : -1) << discontinuities @@ -1534,7 +1534,7 @@ Record const &Map::mapInfo() const { - return App_World().mapInfoForMapUri(hasManifest() ? manifest().composeUri() : de::Uri("Maps:", RC_NULL)); + return App_World().mapInfoForMapUri(hasManifest() ? manifest().composeUri() : de::makeUri("Maps:")); } Mesh const &Map::mesh() const @@ -1569,14 +1569,14 @@ LightGrid &Map::lightGrid() { - if(bool(d->lightGrid)) return *d->lightGrid; + if (bool(d->lightGrid)) return *d->lightGrid; /// @throw MissingLightGrid Attempted with no LightGrid initialized. throw MissingLightGridError("Map::lightGrid", "No light grid is initialized"); } LightGrid const &Map::lightGrid() const { - if(bool(d->lightGrid)) return *d->lightGrid; + if (bool(d->lightGrid)) return *d->lightGrid; /// @throw MissingLightGrid Attempted with no LightGrid initialized. throw MissingLightGridError("Map::lightGrid", "No light grid is initialized"); } @@ -1879,16 +1879,16 @@ Vertex const &vtx0 = line->vertex(i); Vertex const &vtx1 = line->vertex(i ^ 1); - LineOwner const &vo0 = line->vertexOwner(i)->next(); - LineOwner const &vo1 = line->vertexOwner(i ^ 1)->prev(); + LineOwner const *vo0 = line->vertexOwner(i)->next(); + LineOwner const *vo1 = line->vertexOwner(i ^ 1)->prev(); AABoxd bounds = line->bounds(); // Use the extended points, they are wider than inoffsets. - Vector2d const sv0 = vtx0.origin() + vo0.extendedShadowOffset(); + Vector2d const sv0 = vtx0.origin() + vo0->extendedShadowOffset(); V2d_AddToBoxXY(bounds.arvec2, sv0.x, sv0.y); - Vector2d const sv1 = vtx1.origin() + vo1.extendedShadowOffset(); + Vector2d const sv1 = vtx1.origin() + vo1->extendedShadowOffset(); V2d_AddToBoxXY(bounds.arvec2, sv1.x, sv1.y); // Link the shadowing line to all the subspaces whose axis-aligned bounding box @@ -2048,7 +2048,7 @@ Thinkers &Map::thinkers() const { - if(bool( d->thinkers )) return *d->thinkers; + if (bool( d->thinkers )) return *d->thinkers; /// @throw MissingThinkersError The thinker lists are not yet initialized. throw MissingThinkersError("Map::thinkers", "Thinkers not initialized"); } @@ -2434,7 +2434,7 @@ if (ld->back().hasSector()) { Sector &backSec = ld->back().sector(); - if(backSec.validCount() != validCount) + if (backSec.validCount() != validCount) { backSec.setValidCount(validCount); linkStore.append(&backSec); @@ -3111,6 +3111,114 @@ #ifdef __CLIENT__ +String Map::objectsDescription() const +{ + String str; + QTextStream os(&str); + + if (gx.MobjStateAsInfo) + { + // Print out a state description for each thinker. + thinkers().forAll(0x3, [&os] (thinker_t *th) + { + if (Thinker_IsMobj(th)) + { + os << gx.MobjStateAsInfo(reinterpret_cast(th)); + } + return LoopContinue; + }); + } + + return str; +} + +void Map::restoreObjects(Info const &objState, IThinkerMapping const &thinkerMapping) const +{ + /// @todo Generalize from mobjs to all thinkers? + LOG_AS("Map::restoreObjects"); + + if (!gx.MobjStateAsInfo || !gx.MobjRestoreState) return; + + bool problemsDetected = false; + + // Look up all the mobjs. + QList mobjs; + thinkers().forAll(0x3, [&mobjs] (thinker_t *th) { + if (Thinker_IsMobj(th)) mobjs << th; + return LoopContinue; + }); + + // Check that all objects are found in the state description. + if (objState.root().contents().size() != mobjs.size()) + { + LOGDEV_MAP_WARNING("Different number of objects: %i in map, but got %i in restore data") + << mobjs.size() + << objState.root().contents().size(); + } + + // Check the cross-references. + for (auto i = objState.root().contentsInOrder().begin(); + i != objState.root().contentsInOrder().end(); + ++i) + { + Info::BlockElement const &state = (*i)->as(); + Id::Type const privateId = state.name().toUInt32(); + DENG2_ASSERT(privateId != 0); + + if (thinker_t *th = thinkerMapping.thinkerForPrivateId(privateId)) + { + if (ThinkerData *found = ThinkerData::find(privateId)) + { + DENG2_ASSERT(&found->thinker() == th); + + // Restore the state according to the serialized info. + gx.MobjRestoreState(found->as().mobj(), state); + + // Verify that the state is now correct. + { + Info const currentDesc(gx.MobjStateAsInfo(found->as().mobj())); + Info::BlockElement const ¤tState = currentDesc.root().contentsInOrder() + .first()->as(); + DENG2_ASSERT(currentState.name() == state.name()); + foreach (String const &key, state.contents().keys()) + { + if (state.keyValue(key).text != currentState.keyValue(key).text) + { + problemsDetected = true; + const String msg = String("Object %1 has mismatching '%2' (current:%3 != arch:%4)") + .arg(privateId) + .arg(key) + .arg(currentState.keyValue(key).text) + .arg(state.keyValue(key).text); + LOGDEV_MAP_WARNING("%s") << msg; + } + } + } + } + else + { + LOGDEV_MAP_ERROR("Map does not have a thinker matching ID 0x%x") + << privateId; + } + } + else + { + LOGDEV_MAP_ERROR("Thinker mapping does not have a thinker matching ID 0x%x") + << privateId; + } + } + + if (problemsDetected) + { + LOG_MAP_WARNING("Map objects were not fully restored " DENG2_CHAR_MDASH + " gameplay may be affected (enable Developer log entries for details)"); + } + else + { + LOGDEV_MAP_MSG("State of map objects has been restored"); + } +} + void Map::serializeInternalState(Writer &to) const { BaseMap::serializeInternalState(to); @@ -3136,7 +3244,7 @@ to << Id(Id::None); } -void Map::deserializeInternalState(Reader &from, world::IThinkerMapping const &thinkerMapping) +void Map::deserializeInternalState(Reader &from, IThinkerMapping const &thinkerMapping) { BaseMap::deserializeInternalState(from, thinkerMapping); @@ -3497,14 +3605,14 @@ np->_link[Clockwise] = left; np = left; - left = left->nextPtr(); + left = left->next(); } else { np->_link[Clockwise] = right; np = right; - right = right->nextPtr(); + right = right->next(); } } @@ -3522,7 +3630,7 @@ if (!tmp.hasNext()) return nullptr; - return tmp.nextPtr(); + return tmp.next(); } static LineOwner *splitLineOwners(LineOwner *list) @@ -3536,11 +3644,11 @@ do { listc = listb; - listb = listb->nextPtr(); - lista = lista->nextPtr(); + listb = listb->next(); + lista = lista->next(); if (lista) { - lista = lista->nextPtr(); + lista = lista->next(); } } while (lista); @@ -3554,7 +3662,7 @@ static LineOwner *sortLineOwners(LineOwner *list, dint (*compare) (void const *a, void const *b)) { - if (list && list->nextPtr()) + if (list && list->next()) { LineOwner *p = splitLineOwners(list); @@ -3576,7 +3684,7 @@ if (&own->line() == lineptr) return; // Yes, we can exit. - own = &own->next(); + own = own->next(); } // Add a new owner. @@ -3611,10 +3719,10 @@ LineOwner const *cur = base; do { - if (&cur->prev().next() != cur) return false; - if (&cur->next().prev() != cur) return false; + if (cur->prev()->next() != cur) return false; + if (cur->next()->prev() != cur) return false; - } while ((cur = &cur->next()) != base); + } while ((cur = cur->next()) != base); return true; } #endif @@ -3656,7 +3764,7 @@ // and circularly linked. binangle_t firstAngle = v->_lineOwners->angle(); LineOwner *last = v->_lineOwners; - LineOwner *p = last->nextPtr(); + LineOwner *p = last->next(); while (p) { p->_link[Anticlockwise] = last; @@ -3665,7 +3773,7 @@ last->_angle = last->angle() - p->angle(); last = p; - p = p->nextPtr(); + p = p->next(); } last->_link[Clockwise] = v->_lineOwners; v->_lineOwners->_link[Anticlockwise] = last; @@ -4016,7 +4124,7 @@ /// @throw EditError Attempted when not editing. throw EditError("Map::createPolyobj", "Editing is not enabled"); - void *region = M_Calloc(POLYOBJ_SIZE); + void *region = M_Calloc(gx.GetInteger(DD_POLYOBJ_SIZE)); auto *pob = new (region) Polyobj(origin); d->editable.polyobjs.append(pob); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/maputil.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/maputil.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/maputil.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/maputil.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -192,7 +192,7 @@ Line *R_FindLineNeighbor(Line const &line, LineOwner const &own, ClockDirection direction, Sector const *sector, binangle_t *diff) { - LineOwner const *cown = (direction == Anticlockwise ? &own.prev() : &own.next()); + LineOwner const *cown = (direction == Anticlockwise ? own.prev() : own.next()); Line *other = &cown->line(); if(other == &line) @@ -276,7 +276,7 @@ { DENG2_ASSERT(sector); - LineOwner const *cown = (direction == Anticlockwise ? &own.prev() : &own.next()); + LineOwner const *cown = (direction == Anticlockwise ? own.prev() : own.next()); Line *other = &cown->line(); if (other == &line) return nullptr; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/polyobj.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/polyobj.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/polyobj.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/polyobj.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -137,8 +137,9 @@ } polyobj_s::polyobj_s(Vector2d const &origin_) - : thinker(thinker_s::InitializeToZero) { + zap(thinker); + origin[0] = origin_.x; origin[1] = origin_.y; tag = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/p_ticker.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/p_ticker.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/p_ticker.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/p_ticker.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -34,7 +34,7 @@ /// @todo Each context animator should be driven by a more relevant ticker, rather /// than using the playsim's ticker for all contexts. (e.g., animators for the UI /// context should be driven separately). - world::Materials::get().forAllMaterials([&elapsed] (world::Material &material) + world::Materials::get().forAnimatedMaterials([&elapsed] (world::Material &material) { auto &mat = material.as(); for (int i = mat.animatorCount() - 1; i >= 0; --i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/sector.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/sector.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/sector.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/sector.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -349,7 +349,7 @@ return d->subsectors.count(); } -LoopResult Sector::forAllSubsectors(std::function callback) const +LoopResult Sector::forAllSubsectors(const std::function &callback) const { for (Subsector *subsec : d->subsectors) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/sky.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/sky.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/sky.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/sky.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -343,7 +343,7 @@ lyr.setOffset(lyrDef? lyrDef->getf("offset") : DEFAULT_SKY_SPHERE_XOFFSET); lyr.setFadeoutLimit(lyrDef? lyrDef->getf("colorLimit") : DEFAULT_SKY_SPHERE_FADEOUT_LIMIT); - de::Uri const matUri = lyrDef? de::Uri(lyrDef->gets("material")) : de::Uri(DEFAULT_SKY_SPHERE_MATERIAL, RC_NULL); + de::Uri const matUri = lyrDef? de::makeUri(lyrDef->gets("material")) : de::makeUri(DEFAULT_SKY_SPHERE_MATERIAL); world::Material *mat = 0; try { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/surface.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/surface.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/surface.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/surface.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -253,8 +253,8 @@ : this == &side.bottom() ? LineSide::Bottom : LineSide::Top); - LOG_MAP_WARNING( "%s of Line #%d is missing a material for the %s section." - "\n %s was chosen to complete the definition.") + LOGDEV_MAP_WARNING("%s of Line #%d is missing a material for the %s section." + "\n %s was chosen to complete the definition.") << Line::sideIdAsText(side.sideId()).upperFirstChar() << side.line().indexInMap() << LineSide::sectionIdAsText(section) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/thinkers.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/thinkers.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/thinkers.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/thinkers.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -42,11 +42,16 @@ using namespace de; -dd_bool Thinker_HasMobjFunc(thinkfunc_t func) +bool Thinker_IsMobjFunc(thinkfunc_t func) { return (func && func == reinterpret_cast(gx.MobjThinker)); } +bool Thinker_IsMobj(thinker_t const *th) +{ + return (th && Thinker_IsMobjFunc(th->function)); +} + world::Map &Thinker_Map(thinker_t const & /*th*/) { /// @todo Do not assume the current map. @@ -234,7 +239,7 @@ throw Error("Thinkers::add", "Invalid thinker function"); // Will it need an ID? - if (Thinker_HasMobjFunc(th.function)) + if (Thinker_IsMobj(&th)) { // It is a mobj, give it an ID (not for client mobjs, though, they // already have an id). @@ -439,7 +444,7 @@ { Id const privateId = knownId? Id(knownId) : Id(/* get a new ID */); - if (Thinker_HasMobjFunc(th->function)) + if (Thinker_IsMobj(th)) { #ifdef __CLIENT__ th->d = new ClientMobjThinkerData(privateId); @@ -493,34 +498,41 @@ App_World().map().thinkers().forAll(0x1 | 0x2, [] (thinker_t *th) { - if (Thinker_InStasis(th)) return LoopContinue; // Skip. - - // Time to remove it? - if (th->function == (thinkfunc_t) -1) + try { - unlinkThinkerFromList(th); + if (Thinker_InStasis(th)) return LoopContinue; // Skip. - if (th->id) + // Time to remove it? + if (th->function == (thinkfunc_t) -1) { - // Recycle for reduced allocation overhead. - P_MobjRecycle((mobj_t *) th); + unlinkThinkerFromList(th); + + if (th->id) + { + // Recycle for reduced allocation overhead. + P_MobjRecycle((mobj_t *) th); + } + else + { + // Non-mobjs are just deleted right away. + Thinker::destroy(th); + } } - else + else if (th->function) { - // Non-mobjs are just deleted right away. - Thinker::destroy(th); + // Create a private data instance of appropriate type. + if (!th->d) Thinker_InitPrivateData(th); + + // Public thinker callback. + th->function(th); + + // Private thinking. + if (th->d) THINKER_DATA(*th, Thinker::IData).think(); } } - else if (th->function) + catch (const Error &er) { - // Create a private data instance of appropriate type. - if (!th->d) Thinker_InitPrivateData(th); - - // Public thinker callback. - th->function(th); - - // Private thinking. - if (th->d) THINKER_DATA(*th, Thinker::IData).think(); + LOG_MAP_WARNING("Thinker %i: %s") << th->id << er.asText(); } return LoopContinue; }); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/vertex.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/vertex.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/base/vertex.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/base/vertex.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -99,7 +99,7 @@ { _twosOwnerCount += 1; } - } while((own = &own->next()) != firstOwn); + } while((own = own->next()) != firstOwn); } } @@ -198,7 +198,7 @@ do { Line const &lineB = own->line(); - Line const &lineA = own->next().line(); + Line const &lineA = own->next()->line(); Vector2d const rightDir = (&lineB.from() == this? lineB.direction() : -lineB.direction()); Vector2d const leftDir = (&lineA.from() == this? -lineA.direction() : lineA.direction()) * -1; // Always flipped. @@ -208,7 +208,7 @@ &own->_shadowOffsets.inner, &own->_shadowOffsets.extended); - own = &own->next(); + own = own->next(); } while(own != base); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/clientmobjthinkerdata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/clientmobjthinkerdata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/client/src/world/clientmobjthinkerdata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/client/src/world/clientmobjthinkerdata.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -186,7 +186,7 @@ } - void advanceAnimations(TimeDelta const &delta) + void advanceAnimations(TimeSpan const &delta) { if (animator) { @@ -333,7 +333,15 @@ if (flags & Impl::HasAnimator) // Animator { d->initOnce(); - from >> *d->animator; + if (d->animator) + { + from >> *d->animator; + } + else + { + render::StateAnimator temp; + from >> temp; // Not used. + } } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/apps/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/CMakeLists.txt 2018-12-11 07:08:17.000000000 +0000 @@ -6,7 +6,9 @@ add_subdirectory (libdoomsday) add_subdirectory (plugins) -add_subdirectory (server) +if (DENG_ENABLE_SERVER AND NOT IOS) + add_subdirectory (server) +endif () if (DENG_ENABLE_GUI) add_subdirectory (client) endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/api.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/api.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/api.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/api.doxy 2018-12-11 07:08:20.000000000 +0000 @@ -2,10 +2,11 @@ @INCLUDE = ../../doomsday.doxy PROJECT_NAME = "Doomsday Engine" -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 PROJECT_BRIEF = "Shared functionality for client, server and plugins" PROJECT_LOGO = ../../doc/apidoc-logo.png HTML_STYLESHEET = ../../doxygen.css +HTML_HEADER = ../../doxygen_header.html OUTPUT_DIRECTORY = ../../apidoc/api/ INPUT = ../api include src diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/abstractsession.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/abstractsession.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/abstractsession.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/abstractsession.h 2018-12-11 07:08:20.000000000 +0000 @@ -96,30 +96,27 @@ void setThinkerMapping(world::IThinkerMapping *mapping); public: - /** - * Configuration profile. - * @todo Remove this. Could just point to a GameProfile instead. -jk - */ - struct Profile - { - // Unique identifier of the game this profile is used with. - de::String gameId; - - // List of resource files (specified via the command line or in a cfg, or found using - // the default search algorithm (e.g., /auto and DOOMWADDIR)). - QStringList resourceFiles; - }; +// /** +// * Configuration profile. +// * @todo Remove this. Could just point to a GameProfile instead. -jk +// */ +// struct Profile +// { +// // Unique identifier of the game this profile is used with. +// de::String gameId; + +// // List of resource files (specified via the command line or in a cfg, or found using +// // the default search algorithm (e.g., /auto and DOOMWADDIR)). +// QStringList resourceFiles; +// }; - /** + /* * Returns the current configuration profile for the game session. */ - static Profile &profile(); - - /// Convenient method of looking up the game identity key from the game session profile. - static inline de::String gameId() { return profile().gameId; } +// static Profile &profile(); - /// Compose the absolute path of the @em user saved session folder for the game session. - static inline de::String savePath() { return de::String("/home/savegames") / profile().gameId; } + // Convenient method of looking up the game identity key from the game session profile. +// static de::String gameId() const; protected: void setMapUri(de::Uri const &uri); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/ded.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/ded.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/ded.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/ded.h 2018-12-11 07:08:20.000000000 +0000 @@ -39,7 +39,7 @@ * DED_Write() and DED_Read() routines. * * It is VERY important not to sort the data arrays in any way: the index numbers are - * important. The Game DLL must be recompiled with the new constants if the order of the + * important. The game plugins must be recompiled with the new constants if the order of the * array items changes. */ struct LIBDOOMSDAY_PUBLIC ded_s @@ -197,13 +197,18 @@ ded_value_t *getValueById(char const *id) const; ded_value_t *getValueById(de::String const &id) const; - ded_value_t *getValueByUri(de::Uri const &uri) const; ded_compositefont_t *findCompositeFontDef(de::Uri const &uri) const; - ded_compositefont_t *getCompositeFont(char const *uriCString) const; + /** + * Finds the episode that has a specific map in it. + * @param mapId Map identifier. + * @return Episode ID. + */ + de::String findEpisode(de::String const &mapId) const; + protected: void release(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/dedtypes.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/dedtypes.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/dedtypes.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/defs/dedtypes.h 2018-12-11 07:08:20.000000000 +0000 @@ -31,36 +31,32 @@ #include "api_gl.h" #include "dedarray.h" -#define DED_DUP_URI(u) u = (u? new de::Uri(*u) : 0) +#define DED_DUP_URI(u) u = (u ? new de::Uri(*u) : 0) -#define DED_SPRITEID_LEN 4 -#define DED_STRINGID_LEN 31 -#define DED_FUNC_LEN 255 +#define DED_SPRITEID_LEN 4 +#define DED_STRINGID_LEN 31 +#define DED_FUNC_LEN 255 -#define DED_MAX_MATERIAL_LAYERS 1 ///< Maximum number of material layers (map renderer limitations). -#define DED_MAX_MATERIAL_DECORATIONS 16 ///< Maximum number of material decorations (arbitrary). +#define DED_MAX_MATERIAL_LAYERS 1 ///< Maximum number of material layers (map renderer limitations). +#define DED_MAX_MATERIAL_DECORATIONS 16 ///< Maximum number of material decorations (arbitrary). -#define DED_PTCGEN_ANY_MOBJ_TYPE -2 ///< Particle generator applies to ANY mobj type. +#define DED_PTCGEN_ANY_MOBJ_TYPE -2 ///< Particle generator applies to ANY mobj type. -typedef char ded_stringid_t[DED_STRINGID_LEN + 1]; +typedef char ded_stringid_t[DED_STRINGID_LEN + 1]; typedef ded_stringid_t ded_string_t; typedef ded_stringid_t ded_mobjid_t; typedef ded_stringid_t ded_stateid_t; typedef ded_stringid_t ded_soundid_t; typedef ded_stringid_t ded_funcid_t; -typedef char ded_func_t[DED_FUNC_LEN + 1]; -typedef int ded_flags_t; -typedef char* ded_anystring_t; +typedef char ded_func_t[DED_FUNC_LEN + 1]; +typedef int ded_flags_t; +typedef char * ded_anystring_t; typedef struct LIBDOOMSDAY_PUBLIC ded_uri_s { de::Uri *uri; - void release() { - delete uri; - } - void reallocate() { - DED_DUP_URI(uri); - } + void release() { delete uri; } + void reallocate() { DED_DUP_URI(uri); } } ded_uri_t; #ifdef _MSC_VER @@ -70,30 +66,30 @@ // Embedded sound information. typedef struct ded_embsound_s { - ded_string_t name; - int id; // Figured out at runtime. - float volume; + ded_string_t name; + int id; // Figured out at runtime. + float volume; } ded_embsound_t; typedef struct LIBDOOMSDAY_PUBLIC ded_ptcstage_s { - ded_flags_t type; - int tics; - float variance; // Stage variance (time). - float color[4]; // RGBA - float radius; - float radiusVariance; - ded_flags_t flags; - float bounce; - float resistance; // Air resistance. - float gravity; - float vectorForce[3]; - float spin[2]; // Yaw and pitch. - float spinResistance[2]; // Yaw and pitch. - int model; - ded_string_t frameName; // For model particles. - ded_string_t endFrameName; - short frame, endFrame; - ded_embsound_t sound, hitSound; + ded_flags_t type; + int tics; + float variance; // Stage variance (time). + float color[4]; // RGBA + float radius; + float radiusVariance; + ded_flags_t flags; + float bounce; + float resistance; // Air resistance. + float gravity; + float vectorForce[3]; + float spin[2]; // Yaw and pitch. + float spinResistance[2]; // Yaw and pitch. + int model; + ded_string_t frameName; // For model particles. + ded_string_t endFrameName; + short frame, endFrame; + ded_embsound_t sound, hitSound; void release() {} void reallocate() {} @@ -107,35 +103,37 @@ } ded_ptcstage_t; typedef struct { - char id[DED_SPRITEID_LEN + 1]; + char id[DED_SPRITEID_LEN + 1]; void release() {} } ded_sprid_t; typedef struct { - char str[DED_STRINGID_LEN + 1]; + char str[DED_STRINGID_LEN + 1]; } ded_str_t; typedef struct LIBDOOMSDAY_PUBLIC ded_light_s { - ded_stateid_t state; - char uniqueMapID[64]; - float offset[3]; /* Origin offset in world coords + ded_stateid_t state; + char uniqueMapID[64]; + float offset[3]; /* Origin offset in world coords Zero means automatic */ - float size; // Zero: automatic - float color[3]; // Red Green Blue (0,1) - float lightLevel[2]; // Min/max lightlevel for bias - ded_flags_t flags; - de::Uri* up, *down, *sides; - de::Uri* flare; - float haloRadius; // Halo radius (zero = no halo). + float size; // Zero: automatic + float color[3]; // Red Green Blue (0,1) + float lightLevel[2]; // Min/max lightlevel for bias + ded_flags_t flags; + de::Uri * up, *down, *sides; + de::Uri * flare; + float haloRadius; // Halo radius (zero = no halo). - void release() { + void release() + { delete up; delete down; delete sides; delete flare; } - void reallocate() { + void reallocate() + { DED_DUP_URI(up); DED_DUP_URI(down); DED_DUP_URI(sides); @@ -144,172 +142,165 @@ } ded_light_t; typedef struct LIBDOOMSDAY_PUBLIC ded_sound_s { - ded_soundid_t id; // ID of this sound, refered to by others. - ded_string_t name; // A tag name for the sound. - ded_string_t lumpName; // Actual lump name of the sound ("DS" not included). - de::Uri* ext; // External sound file (WAV). - ded_soundid_t link; // Link to another sound. - int linkPitch; - int linkVolume; - int priority; // Priority classification. - int channels; // Max number of channels to occupy. - int group; // Exclusion group. - ded_flags_t flags; // Flags (like chg_pitch). + ded_soundid_t id; // ID of this sound, refered to by others. + ded_string_t name; // A tag name for the sound. + ded_string_t lumpName; // Actual lump name of the sound ("DS" not included). + de::Uri * ext; // External sound file (WAV). + ded_soundid_t link; // Link to another sound. + int linkPitch; + int linkVolume; + int priority; // Priority classification. + int channels; // Max number of channels to occupy. + int group; // Exclusion group. + ded_flags_t flags; // Flags (like chg_pitch). - void release() { - delete ext; - } - void reallocate() { - DED_DUP_URI(ext); - } + void release() { delete ext; } + void reallocate() { DED_DUP_URI(ext); } } ded_sound_t; -struct ded_text_t -{ +struct ded_text_t { ded_stringid_t id; - char *text; + char * text; - void release() { - M_Free(text); - } + void release() { M_Free(text); } - void setText(char const *newTextToCopy) { + void setText(char const *newTextToCopy) + { release(); text = M_StrDup(newTextToCopy); } }; typedef struct { - ded_stringid_t id; + ded_stringid_t id; DEDArray materials; - void release() { - materials.clear(); - } + void release() { materials.clear(); } } ded_tenviron_t; typedef struct { char *id; char *text; - void release() { + void release() + { M_Free(id); M_Free(text); } } ded_value_t; typedef struct LIBDOOMSDAY_PUBLIC ded_linetype_s { - int id; - char comment[64]; - ded_flags_t flags[3]; - ded_flags_t lineClass; - ded_flags_t actType; - int actCount; - float actTime; - int actTag; - int aparm[9]; - ded_stringid_t aparm9; - float tickerStart; - float tickerEnd; - int tickerInterval; - ded_soundid_t actSound; - ded_soundid_t deactSound; - int evChain; - int actChain; - int deactChain; - int actLineType; - int deactLineType; - ded_flags_t wallSection; - de::Uri* actMaterial; - de::Uri* deactMaterial; - char actMsg[128]; - char deactMsg[128]; - float materialMoveAngle; - float materialMoveSpeed; - int iparm[20]; - char iparmStr[20][64]; - float fparm[20]; - char sparm[5][128]; + int id; + char comment[64]; + ded_flags_t flags[3]; + ded_flags_t lineClass; + ded_flags_t actType; + int actCount; + float actTime; + int actTag; + int aparm[9]; + ded_stringid_t aparm9; + float tickerStart; + float tickerEnd; + int tickerInterval; + ded_soundid_t actSound; + ded_soundid_t deactSound; + int evChain; + int actChain; + int deactChain; + int actLineType; + int deactLineType; + ded_flags_t wallSection; + de::Uri * actMaterial; + de::Uri * deactMaterial; + char actMsg[128]; + char deactMsg[128]; + float materialMoveAngle; + float materialMoveSpeed; + int iparm[20]; + char iparmStr[20][64]; + float fparm[20]; + char sparm[5][128]; - void release() { + void release() + { delete actMaterial; delete deactMaterial; } - void reallocate() { + void reallocate() + { DED_DUP_URI(actMaterial); DED_DUP_URI(deactMaterial); } } ded_linetype_t; typedef struct LIBDOOMSDAY_PUBLIC ded_sectortype_s { - int id; - char comment[64]; - ded_flags_t flags; - int actTag; - int chain[5]; - ded_flags_t chainFlags[5]; - float start[5]; - float end[5]; - float interval[5][2]; - int count[5]; - ded_soundid_t ambientSound; - float soundInterval[2]; // min,max - float materialMoveAngle[2]; // floor, ceil - float materialMoveSpeed[2]; // floor, ceil - float windAngle; - float windSpeed; - float verticalWind; - float gravity; - float friction; - ded_func_t lightFunc; - int lightInterval[2]; - ded_func_t colFunc[3]; // RGB - int colInterval[3][2]; - ded_func_t floorFunc; - float floorMul, floorOff; - int floorInterval[2]; - ded_func_t ceilFunc; - float ceilMul, ceilOff; - int ceilInterval[2]; + int id; + char comment[64]; + ded_flags_t flags; + int actTag; + int chain[5]; + ded_flags_t chainFlags[5]; + float start[5]; + float end[5]; + float interval[5][2]; + int count[5]; + ded_soundid_t ambientSound; + float soundInterval[2]; // min,max + float materialMoveAngle[2]; // floor, ceil + float materialMoveSpeed[2]; // floor, ceil + float windAngle; + float windSpeed; + float verticalWind; + float gravity; + float friction; + ded_func_t lightFunc; + int lightInterval[2]; + ded_func_t colFunc[3]; // RGB + int colInterval[3][2]; + ded_func_t floorFunc; + float floorMul, floorOff; + int floorInterval[2]; + ded_func_t ceilFunc; + float ceilMul, ceilOff; + int ceilInterval[2]; void release() {} void reallocate() {} } ded_sectortype_t; typedef struct LIBDOOMSDAY_PUBLIC ded_detail_stage_s { - int tics; - float variance; - de::Uri * texture; // The file/lump with the detail texture. - float scale; - float strength; - float maxDistance; + int tics; + float variance; + de::Uri *texture; // The file/lump with the detail texture. + float scale; + float strength; + float maxDistance; - void release() { - delete texture; - } - void reallocate() { - DED_DUP_URI(texture); - } + void release() { delete texture; } + void reallocate() { DED_DUP_URI(texture); } } ded_detail_stage_t; // Flags for detail texture definitions. -#define DTLF_NO_IWAD 0x1 // Don't use if from IWAD. -#define DTLF_PWAD 0x2 // Can use if from PWAD. -#define DTLF_EXTERNAL 0x4 // Can use if from external resource. +#define DTLF_NO_IWAD 0x1 // Don't use if from IWAD. +#define DTLF_PWAD 0x2 // Can use if from PWAD. +#define DTLF_EXTERNAL 0x4 // Can use if from external resource. typedef struct LIBDOOMSDAY_PUBLIC ded_detailtexture_s { - de::Uri *material1; - de::Uri *material2; - ded_flags_t flags; + de::Uri * material1; + de::Uri * material2; + ded_flags_t flags; // There is only one stage. ded_detail_stage_t stage; - void release() { + void release() + { delete material1; delete material2; stage.release(); } - void reallocate() { + void reallocate() + { DED_DUP_URI(material1); DED_DUP_URI(material2); stage.reallocate(); @@ -317,48 +308,50 @@ } ded_detailtexture_t; typedef struct LIBDOOMSDAY_PUBLIC ded_ptcgen_s { - struct ded_ptcgen_s* stateNext; // List of generators for a state. - ded_stateid_t state; // Triggered by this state (if mobj-gen). - de::Uri* material; - ded_mobjid_t type; // Triggered by this type of mobjs. - ded_mobjid_t type2; // Also triggered by this type. - int typeNum; - int type2Num; - ded_mobjid_t damage; // Triggered by mobj damage of this type. - int damageNum; - de::Uri* map; // Triggered by this map. - ded_flags_t flags; - float speed; // Particle spawn velocity. - float speedVariance; // Spawn speed variance (0-1). - float vector[3]; // Particle launch vector. - float vectorVariance; // Launch vector variance (0-1). 1=totally random. - float initVectorVariance; // Initial launch vector variance (0-1). - float center[3]; // Offset to the mobj (relat. to source). - int subModel; // Model source: origin submodel #. - float spawnRadius; - float spawnRadiusMin; // Spawn uncertainty box. - float maxDist; // Max visibility for particles. - int spawnAge; // How long until spawning stops? - int maxAge; // How long until generator dies? - int particles; // Maximum number of particles. - float spawnRate; // Particles spawned per tic. - float spawnRateVariance; - int preSim; // Tics to pre-simulate when spawned. - int altStart; - float altStartVariance; // Probability for alt start. - float force; // Radial strength of the sphere force. - float forceRadius; // Radius of the sphere force. - float forceAxis[3]; /* Rotation axis of the sphere force + struct ded_ptcgen_s * stateNext; // List of generators for a state. + ded_stateid_t state; // Triggered by this state (if mobj-gen). + de::Uri * material; + ded_mobjid_t type; // Triggered by this type of mobjs. + ded_mobjid_t type2; // Also triggered by this type. + int typeNum; + int type2Num; + ded_mobjid_t damage; // Triggered by mobj damage of this type. + int damageNum; + de::Uri * map; // Triggered by this map. + ded_flags_t flags; + float speed; // Particle spawn velocity. + float speedVariance; // Spawn speed variance (0-1). + float vector[3]; // Particle launch vector. + float vectorVariance; // Launch vector variance (0-1). 1=totally random. + float initVectorVariance; // Initial launch vector variance (0-1). + float center[3]; // Offset to the mobj (relat. to source). + int subModel; // Model source: origin submodel #. + float spawnRadius; + float spawnRadiusMin; // Spawn uncertainty box. + float maxDist; // Max visibility for particles. + int spawnAge; // How long until spawning stops? + int maxAge; // How long until generator dies? + int particles; // Maximum number of particles. + float spawnRate; // Particles spawned per tic. + float spawnRateVariance; + int preSim; // Tics to pre-simulate when spawned. + int altStart; + float altStartVariance; // Probability for alt start. + float force; // Radial strength of the sphere force. + float forceRadius; // Radius of the sphere force. + float forceAxis[3]; /* Rotation axis of the sphere force (+ speed). */ - float forceOrigin[3]; // Offset for the force sphere. + float forceOrigin[3]; // Offset for the force sphere. DEDArray stages; - void release() { + void release() + { delete material; delete map; stages.clear(); } - void reallocate() { + void reallocate() + { DED_DUP_URI(map); DED_DUP_URI(material); stages.reallocate(); @@ -366,103 +359,101 @@ } ded_ptcgen_t; typedef struct LIBDOOMSDAY_PUBLIC ded_shine_stage_s { - int tics; - float variance; - de::Uri *texture; - de::Uri *maskTexture; - blendmode_t blendMode; // Blend mode flags (bm_*). - float shininess; - float minColor[3]; - float maskWidth; - float maskHeight; + int tics; + float variance; + de::Uri * texture; + de::Uri * maskTexture; + blendmode_t blendMode; // Blend mode flags (bm_*). + float shininess; + float minColor[3]; + float maskWidth; + float maskHeight; - void release() { + void release() + { delete texture; delete maskTexture; } - void reallocate() { + void reallocate() + { DED_DUP_URI(texture); DED_DUP_URI(maskTexture); } } ded_shine_stage_t; // Flags for reflection definitions. -#define REFF_NO_IWAD 0x1 // Don't use if from IWAD. -#define REFF_PWAD 0x2 // Can use if from PWAD. -#define REFF_EXTERNAL 0x4 // Can use if from external resource. +#define REFF_NO_IWAD 0x1 // Don't use if from IWAD. +#define REFF_PWAD 0x2 // Can use if from PWAD. +#define REFF_EXTERNAL 0x4 // Can use if from external resource. typedef struct LIBDOOMSDAY_PUBLIC ded_reflection_s { - de::Uri *material; - ded_flags_t flags; + de::Uri * material; + ded_flags_t flags; // There is only one stage. ded_shine_stage_t stage; - void release() { + void release() + { delete material; stage.release(); } - void reallocate() { + void reallocate() + { DED_DUP_URI(material); stage.reallocate(); } } ded_reflection_t; typedef struct LIBDOOMSDAY_PUBLIC ded_group_member_s { - de::Uri* material; - int tics; - int randomTics; + de::Uri *material; + int tics; + int randomTics; - void release() { - delete material; - } - void reallocate() { - DED_DUP_URI(material); - } + void release() { delete material; } + void reallocate() { DED_DUP_URI(material); } } ded_group_member_t; typedef struct LIBDOOMSDAY_PUBLIC ded_group_s { - ded_flags_t flags; + ded_flags_t flags; DEDArray members; - void release() { - members.clear(); - } + void release() { members.clear(); } - ded_group_member_t *tryFindFirstMemberWithMaterial(de::Uri const &materialUri) { - if (!materialUri.isEmpty()) { - for (int i = 0; i < members.size(); ++i) { - if (members[i].material && *members[i].material == materialUri) { + ded_group_member_t *tryFindFirstMemberWithMaterial(de::Uri const &materialUri) + { + if (!materialUri.isEmpty()) + { + for (int i = 0; i < members.size(); ++i) + { + if (members[i].material && *members[i].material == materialUri) + { return &members[i]; } - // Only animate if the first frame in the group? if (flags & AGF_FIRST_ONLY) break; } } - return nullptr; // Not found. + return nullptr; // Not found. } } ded_group_t; typedef struct LIBDOOMSDAY_PUBLIC ded_compositefont_mappedcharacter_s { - unsigned char ch; - de::Uri* path; + unsigned char ch; + de::Uri * path; - void release() { - delete path; - } - void reallocate() { - DED_DUP_URI(path); - } + void release() { delete path; } + void reallocate() { DED_DUP_URI(path); } } ded_compositefont_mappedcharacter_t; typedef struct LIBDOOMSDAY_PUBLIC ded_compositefont_s { - de::Uri* uri; + de::Uri * uri; DEDArray charMap; - void release() { + void release() + { delete uri; charMap.clear(); } } ded_compositefont_t; -#endif // LIBDOOMSDAY_DEFINITION_TYPES_H +#endif // LIBDOOMSDAY_DEFINITION_TYPES_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/doomsdayapp.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/doomsdayapp.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/doomsdayapp.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/doomsdayapp.h 2018-12-11 07:08:20.000000000 +0000 @@ -25,8 +25,10 @@ #include "players.h" #include "gameprofiles.h" +#include #include #include +#include #include #include @@ -59,8 +61,6 @@ /// Notified when console variables and commands should be registered. DENG2_DEFINE_AUDIENCE2(ConsoleRegistration, void consoleRegistration()) - DENG2_DEFINE_AUDIENCE2(FileRefresh, void aboutToRefreshFiles()) - DENG2_DEFINE_AUDIENCE2(PeriodicAutosave, void periodicAutosave()) struct GameChangeParameters @@ -187,6 +187,8 @@ public: static DoomsdayApp & app(); + static de::shell::PackageDownloader & + packageDownloader(); static res::Bundles & bundles(); static Plugins & plugins(); static Games & games(); @@ -225,6 +227,8 @@ static de::StringList loadedPackagesAffectingGameplay(); protected: + static void initBindings(de::Binder &binder); + /** * Called just before a game change is about to begin. The GameUnload * audience has already been notified. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/datafolder.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/datafolder.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/datafolder.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/datafolder.h 2018-12-11 07:08:20.000000000 +0000 @@ -36,7 +36,10 @@ DataFolder(Format format, de::File &sourceFile); ~DataFolder(); - de::String describe() const; + de::String describe() const override; + + // Stream access. + IIStream const &operator >> (IByteArray &bytes) const override; }; #endif // LIBDOOMSDAY_DATABUNDLE_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/file.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/file.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/file.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/file.h 2018-12-11 07:08:20.000000000 +0000 @@ -76,7 +76,7 @@ * @param _info Info descriptor for the file. A copy is made. * @param container Container of this file. Can be @c NULL. */ - File1(FileHandle &hndl, String _path, FileInfo const &_info, File1 *container = 0); + File1(FileHandle *hndl, String _path, FileInfo const &_info, File1 *container = 0); /** * Release all memory acquired for objects linked with this resource. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/filetype.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/filetype.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/filetype.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/filetype.h 2018-12-11 07:08:20.000000000 +0000 @@ -128,7 +128,7 @@ class LIBDOOMSDAY_PUBLIC NullFileType : public FileType { public: - NullFileType() : FileType("FT_NONE", RC_UNKNOWN) + NullFileType() : FileType("FT_NONE", RC_IMPLICIT) {} }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgameslink.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgameslink.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgameslink.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgameslink.h 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,49 @@ +/** @file + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDOOMSDAY_FILESYS_IDGAMESLINK_H +#define LIBDOOMSDAY_FILESYS_IDGAMESLINK_H + +#include + +class IdgamesLink : public de::filesys::WebHostedLink +{ +public: + static de::filesys::Link *construct(de::String const &address); + + de::File *populateRemotePath(de::String const &packageId, + de::filesys::RepositoryPath const &path) const override; + + void parseRepositoryIndex(QByteArray data) override; + + de::StringList categoryTags() const override; + + de::LoopResult forPackageIds(std::function func) const override; + + de::String findPackagePath(de::String const &packageId) const override; + +protected: + IdgamesLink(de::String const &address); + + void setFileTree(FileTree *tree) override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // LIBDOOMSDAY_FILESYS_IDGAMESLINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgamespackageinfofile.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgamespackageinfofile.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgamespackageinfofile.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/idgamespackageinfofile.h 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,51 @@ +/** @file + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#ifndef LIBDOOMSDAY_IDGAMESPACKAGEINFOFILE_H +#define LIBDOOMSDAY_IDGAMESPACKAGEINFOFILE_H + +#include +#include + +/** + * Generates a Doomsday 2 package metadata for mods downloaded from the idgames archive. + * @ingroup fs + */ +class IdgamesPackageInfoFile : public de::File, public de::IDownloadable +{ +public: + IdgamesPackageInfoFile(de::String const &name); + + void setSourceFiles(de::RemoteFile const &dataFile, de::RemoteFile const &descriptionFile); + + // Downloadable interface. + de::Asset &asset() override; + de::Asset const &asset() const override; + de::dsize downloadSize() const override; + void download() override; + void cancelDownload() override; + + // Stream access. + IIStream const &operator >> (de::IByteArray &bytes) const override; + +private: + DENG2_PRIVATE(d) +}; + +#endif // LIBDOOMSDAY_IDGAMESPACKAGEINFOFILE_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/wad.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/wad.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/wad.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/wad.h 2018-12-11 07:08:20.000000000 +0000 @@ -57,7 +57,7 @@ class LumpFile : public File1 { public: - LumpFile(Entry &entry, FileHandle &hndl, String path, FileInfo const &info, + LumpFile(Entry &entry, FileHandle *hndl, String path, FileInfo const &info, File1 *container); /// @return Name of this file. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/zip.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/zip.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/zip.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/filesys/zip.h 2018-12-11 07:08:20.000000000 +0000 @@ -59,7 +59,7 @@ class LumpFile : public File1 { public: - LumpFile(Entry &entry, FileHandle &hndl, String path, FileInfo const &info, + LumpFile(Entry &entry, FileHandle *hndl, String path, FileInfo const &info, File1 *container); /// @return Name of this file. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gameapi.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gameapi.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gameapi.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gameapi.h 2018-12-11 07:08:20.000000000 +0000 @@ -31,237 +31,49 @@ struct event_s; -/// General constants (not to be used with Get/Set). -/// @note Many of these have become unused as better APIs are introduced for -/// sharing information. +/// General constants. enum { - DD_DISABLE, - DD_ENABLE, - DD_UNUSED22, // DD_MASK - DD_YES, - DD_NO, - DD_UNUSED23, // DD_MATERIAL - DD_UNUSED24, // DD_OFFSET - DD_UNUSED25, // DD_HEIGHT - DD_UNUSED2, - DD_UNUSED3, - DD_UNUSED26, // DD_COLOR_LIMIT - DD_PRE, - DD_POST, + DD_DISABLE = 0, + DD_ENABLE = 1, + DD_YES = 2, + DD_NO = 3, + DD_PRE = 4, + DD_POST = 5, + + DD_GAME_CONFIG = 0x100, ///< String: dm/co-op, jumping, etc. + DD_GAME_RECOMMENDS_SAVING, ///< engine asks whether game should be saved (e.g., when upgrading) (game's GetInteger) + + DD_NOTIFY_GAME_SAVED = 0x200, ///< savegame was written + DD_NOTIFY_PLAYER_WEAPON_CHANGED, ///< a player's weapon changed (including powerups) + DD_NOTIFY_PSPRITE_STATE_CHANGED, ///< a player's psprite state has changed + + DD_PLUGIN_NAME = 0x300, ///< (e.g., jdoom, jheretic etc..., suitable for use with filepaths) + DD_PLUGIN_NICENAME, ///< (e.g., jDoom, MyGame:Episode2 etc..., fancy name) DD_PLUGIN_VERSION_SHORT, DD_PLUGIN_VERSION_LONG, - DD_UNUSED27, // DD_HORIZON - DD_OLD_GAME_ID, - DD_UNUSED32, // DD_DEF_MOBJ - DD_UNUSED33, // DD_DEF_MOBJ_BY_NAME - DD_UNUSED29, // DD_DEF_STATE - DD_UNUSED34, // DD_DEF_SPRITE - DD_DEF_SOUND, - DD_UNUSED14, // DD_DEF_MUSIC - DD_UNUSED13, // DD_DEF_MAP_INFO - DD_UNUSED28, // DD_DEF_TEXT - DD_UNUSED36, // DD_DEF_VALUE - DD_UNUSED37, // DD_DEF_VALUE_BY_INDEX + DD_PLUGIN_HOMEURL, + DD_PLUGIN_DOCSURL, + + DD_DEF_SOUND = 0x400, DD_DEF_LINE_TYPE, DD_DEF_SECTOR_TYPE, - DD_PSPRITE_BOB_X, - DD_PSPRITE_BOB_Y, - DD_UNUSED19, // DD_DEF_FINALE_AFTER - DD_UNUSED20, // DD_DEF_FINALE_BEFORE - DD_UNUSED21, // DD_DEF_FINALE - DD_RENDER_RESTART_PRE, - DD_RENDER_RESTART_POST, - DD_UNUSED35, // DD_DEF_SOUND_BY_NAME DD_DEF_SOUND_LUMPNAME, - DD_UNUSED16, // DD_ID - DD_LUMP, - DD_UNUSED17, // DD_CD_TRACK - DD_UNUSED30, // DD_SPRITE - DD_UNUSED31, // DD_FRAME - DD_GAME_CONFIG, ///< String: dm/co-op, jumping, etc. - DD_PLUGIN_NAME, ///< (e.g., jdoom, jheretic etc..., suitable for use with filepaths) - DD_PLUGIN_NICENAME, ///< (e.g., jDoom, MyGame:Episode2 etc..., fancy name) - DD_PLUGIN_HOMEURL, - DD_PLUGIN_DOCSURL, DD_DEF_ACTION, - DD_UNUSED15, // DD_DEF_MUSIC_CDTRACK + DD_LUMP, - // Non-integer/special values for Set/Get - DD_MAP_BOUNDING_BOX, - DD_UNUSED4, // DD_TRACE_ADDRESS - DD_SPRITE_REPLACEMENT, ///< Sprite <-> model replacement. - DD_ACTION_LINK, ///< State action routine addresses. - DD_UNUSED10, // DD_MAP_NAME - DD_UNUSED11, // DD_MAP_AUTHOR - DD_MAP_MUSIC, - DD_MAP_MIN_X, - DD_MAP_MIN_Y, - DD_MAP_MAX_X, - DD_MAP_MAX_Y, - DD_WINDOW_WIDTH, - DD_WINDOW_HEIGHT, - DD_WINDOW_HANDLE, - DD_DYNLIGHT_TEXTURE, - DD_GAME_EXPORTS, - DD_POLYOBJ_COUNT, - DD_XGFUNC_LINK, ///< XG line classes - DD_SHARED_FIXED_TRIGGER_OBSOLETE, ///< obsolete - DD_GAMETIC, - DD_NOTIFY_PLAYER_WEAPON_CHANGED, ///< a player's weapon changed (including powerups) - DD_NOTIFY_PSPRITE_STATE_CHANGED, ///< a player's psprite state has changed - DD_UNUSED7, // DD_OPENBOTTOM - DD_UNUSED8, // DD_LOWFLOOR - DD_CPLAYER_THRUST_MUL_OBSOLETE, ///< obsolete - DD_GRAVITY, - DD_PSPRITE_OFFSET_X, ///< 10x - DD_PSPRITE_OFFSET_Y, ///< 10x - DD_PSPRITE_LIGHTLEVEL_MULTIPLIER, - DD_TORCH_RED, - DD_TORCH_GREEN, - DD_TORCH_BLUE, - DD_TORCH_ADDITIVE_obsolete, - DD_TM_FLOOR_Z, ///< output from P_CheckPosition - DD_TM_CEILING_Z, ///< output from P_CheckPosition - DD_SHIFT_DOWN, - DD_GAME_RECOMMENDS_SAVING, ///< engine asks whether game should be saved (e.g., when upgrading) (game's GetInteger) - DD_NOTIFY_GAME_SAVED, ///< savegame was written - DD_DEFS ///< engine definition database (DED) -}; + DD_ACTION_LINK = 0x500, ///< State action routine addresses. + DD_XGFUNC_LINK, ///< XG line classes + DD_MOBJ_SIZE, + DD_POLYOBJ_SIZE, -/** - * The routines/data exported from the game plugin. @ingroup game - * - * @todo Get rid of this struct in favor of individually queried export points. - */ -typedef struct { - size_t apiSize; ///< sizeof(game_export_t) - - // Base-level. - void (*PreInit) (char const *gameId); - void (*PostInit) (void); - dd_bool (*TryShutdown) (void); - void (*Shutdown) (void); - void (*UpdateState) (int step); - int (*GetInteger) (int id); - void *(*GetVariable) (int id); - - // Networking. - int (*NetServerStart) (int before); - int (*NetServerStop) (int before); - int (*NetConnect) (int before); - int (*NetDisconnect) (int before); - long int (*NetPlayerEvent) (int playernum, int type, void *data); - int (*NetWorldEvent) (int type, int parm, void *data); - void (*HandlePacket) (int fromplayer, int type, void *data, - size_t length); - - // Tickers. - void (*Ticker) (timespan_t ticLength); - - // Responders. - int (*FinaleResponder) (void const *ddev); - int (*PrivilegedResponder) (struct event_s *ev); - int (*Responder) (struct event_s *ev); - int (*FallbackResponder) (struct event_s *ev); - - // Refresh. - void (*BeginFrame) (void); - - /** - * Called at the end of a refresh frame. This is the last chance the game - * will have at updating the engine state before rendering of the frame - * begins. Once rendering begins, the viewer can still be updated however - * any changes will not take effect until the subsequent frame. Therefore - * this is the place where games should strive to update the viewer to - * ensure latency-free world refresh. - */ - void (*EndFrame) (void); - - /** - * Draw the view port display of the identified console @a player. - * The engine will configure a orthographic GL projection in real pixel - * dimensions prior to calling this. - * - * Example subdivision of the game window into four view ports: - *
-     *     (0,0)-----------------------. X
-     *       | .--------. |            |
-     *       | | window | |            |
-     *       | '--------' |            |
-     *       |    port #0 |    port #1 |
-     *       |-------------------------|
-     *       |            |            |
-     *       |            |            |
-     *       |            |            |
-     *       |    port #2 |    port #3 |
-     *       '--------------------(xn-1, yn-1)
-     *       Y               Game Window
-     * 
- * - * @param port Logical number of this view port. - * @param portGeometry Geometry of the view port in real screen pixels. - * @param windowGeometry Geometry of the view window within the port, in - * real screen pixels. - * - * @param player Console player number associated with the view port. - * @param layer Logical layer identifier for the content to be drawn: - * - 0: The bottom-most layer and the one which generally contains the - * call to R_RenderPlayerView. - * - 1: Displays to be drawn on top of view window (after bordering), - * such as the player HUD. - */ - void (*DrawViewPort) (int port, RectRaw const *portGeometry, - RectRaw const *windowGeometry, int player, int layer); - - /** - * Draw over-viewport displays covering the whole game window. Typically - * graphical user interfaces such as game menus are done here. - * - * @param windowSize Dimensions of the game window in real screen pixels. - */ - void (*DrawWindow) (Size2Raw const *windowSize); - - // Miscellaneous. - void (*MobjThinker) (void *mobj); - coord_t (*MobjFriction) (struct mobj_s const *mobj); // Returns a friction factor. - dd_bool (*MobjCheckPositionXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z); - dd_bool (*MobjTryMoveXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z); - void (*SectorHeightChangeNotification)(int sectorIdx); // Applies necessary checks on objects. - - // Main structure sizes. - size_t mobjSize; ///< sizeof(mobj_t) - size_t polyobjSize; ///< sizeof(Polyobj) - - // Map setup - - /** - * Called once a map change (i.e., P_MapChange()) has completed to allow the - * game to do any post change finalization it needs to do at this time. - */ - void (*FinalizeMapChange) (void const *uri); - - /** - * Called when trying to assign a value read from the map data (to a - * property known to us) that we don't know what to do with. - * - * (eg the side->toptexture field contains a text string that - * we don't understand but the game might). - * - * @return The action code returned by the game depends on the context. - */ - int (*HandleMapDataPropertyValue) (uint id, int dtype, int prop, - valuetype_t type, void *data); - // Post map setup - /** - * The engine calls this to inform the game of any changes it is - * making to map data object to which the game might want to - * take further action. - */ - int (*HandleMapObjectStatusReport) (int code, uint id, int dtype, void *data); -} game_export_t; + DD_TM_FLOOR_Z = 0x600, ///< output from P_CheckPosition + DD_TM_CEILING_Z, ///< output from P_CheckPosition -/// Function pointer for @c GetGameAPI() (exported by game plugin). @ingroup game -typedef game_export_t *(*GETGAMEAPI) (void); + DD_PSPRITE_BOB_X = 0x700, + DD_PSPRITE_BOB_Y, + DD_RENDER_RESTART_PRE, + DD_RENDER_RESTART_POST +}; #ifdef __cplusplus } // extern "C" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/game.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/game.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/game.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/game.h 2018-12-11 07:08:20.000000000 +0000 @@ -74,6 +74,7 @@ static de::String const DEF_LEGACYSAVEGAME_NAME_EXP; ///< Regular expression used for matching legacy savegame names. static de::String const DEF_LEGACYSAVEGAME_SUBFOLDER; ///< Game-specific subdirectory of /home for legacy savegames. static de::String const DEF_MAPINFO_PATH; ///< Base relative path to the main MAPINFO definition data. + static de::String const DEF_OPTIONS; public: /** @@ -248,7 +249,7 @@ /** * Returns the built-in profile of the game. */ - GameProfile const &profile() const; + GameProfile &profile() const; // IObject. de::Record const &objectNamespace() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gameprofiles.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gameprofiles.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gameprofiles.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gameprofiles.h 2018-12-11 07:08:20.000000000 +0000 @@ -21,6 +21,7 @@ #include "libdoomsday.h" +#include #include class Game; @@ -35,8 +36,12 @@ /** * Game profile. Identifies a specific Game and a set of packages to be loaded. * Profiles are serialized as plain text in "/home/configs/game.dei". + * + * When a custom data file is set, any normally required packages with the "gamedata" + * tag are ignored. The assumption is that the custom data file provides everything + * that is provided by those default gamedata packages. */ - class LIBDOOMSDAY_PUBLIC Profile : public AbstractProfile + class LIBDOOMSDAY_PUBLIC Profile : public AbstractProfile, public de::IObject { public: Profile(de::String const &name = de::String()); @@ -45,17 +50,35 @@ Profile &operator = (Profile const &other); void setGame(de::String const &id); + void setCustomDataFile(const de::String &id); void setPackages(de::StringList packagesInOrder); void setUserCreated(bool userCreated); void setUseGameRequirements(bool useGameRequirements); + void setAutoStartMap(de::String const &map); + void setAutoStartSkill(int level); + void setLastPlayedAt(const de::Time &at = de::Time()); + void setSaveLocationId(de::duint32 saveLocationId); + void setOptionValue(const de::String &option, const de::Value &value); bool appendPackage(de::String const &id); de::String gameId() const; Game &game() const; + de::String customDataFile() const; de::StringList packages() const; bool isUserCreated() const; bool isUsingGameRequirements() const; + de::String autoStartMap() const; + int autoStartSkill() const; + de::Time lastPlayedAt() const; + de::duint32 saveLocationId() const; + de::String savePath() const; + const de::Value &optionValue(const de::String &option) const; + + void createSaveLocation(); + void destroySaveLocation(); + void checkSaveLocation() const; + bool isSaveLocationEmpty() const; /** * Returns a list of the game's packages in addition to the profile's @@ -75,9 +98,13 @@ void unloadPackages() const; - virtual bool resetToDefaults() override; + virtual bool resetToDefaults() override; virtual de::String toInfoSource() const override; + // Implements IObject. + de::Record & objectNamespace() override; + const de::Record &objectNamespace() const override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/games.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/games.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/games.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/games.h 2018-12-11 07:08:20.000000000 +0000 @@ -81,6 +81,9 @@ /// @return Number of games marked as currently playable. int numPlayable() const; + /// @return Number of games marked as currently playable in a game family. + int numPlayable(de::String const &family) const; + /** * @return Game associated with @a identityKey. * diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gamestatefolder.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gamestatefolder.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/gamestatefolder.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/gamestatefolder.h 2018-12-11 07:08:20.000000000 +0000 @@ -64,7 +64,7 @@ /** * Generates a textual representation of the session metadata with Info syntax. */ - de::String asTextWithInfoSyntax() const; + de::String asInfo() const; }; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/plugins.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/plugins.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/plugins.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/plugins.h 2018-12-11 07:08:20.000000000 +0000 @@ -22,6 +22,7 @@ #include #include +#include "world/valuetype.h" /** * Unique identifier assigned to each plugin during initial startup. @@ -107,11 +108,142 @@ #ifdef __cplusplus #include +#include #include "libdoomsday.h" #include "library.h" #include "gameapi.h" /** + * Routines exported from a game plugin. @ingroup game + * + * Note that this struct is not part of the game plugin ABI any longer (since 2.1). + */ +struct GameExports +{ + // Base-level. + void (*PreInit) (char const *gameId); + void (*PostInit) (void); + dd_bool (*TryShutdown) (void); + void (*Shutdown) (void); + void (*UpdateState) (int step); + int (*GetInteger) (int id); + void *(*GetPointer) (int id); + + // Networking. + int (*NetServerStart) (int before); + int (*NetServerStop) (int before); + int (*NetConnect) (int before); + int (*NetDisconnect) (int before); + long int (*NetPlayerEvent) (int playernum, int type, void *data); + int (*NetWorldEvent) (int type, int parm, void *data); + void (*HandlePacket) (int fromplayer, int type, void *data, + size_t length); + + // Tickers. + void (*Ticker) (timespan_t ticLength); + + // Responders. + int (*FinaleResponder) (void const *ddev); + int (*PrivilegedResponder) (struct event_s *ev); + int (*Responder) (struct event_s *ev); + int (*FallbackResponder) (struct event_s *ev); + + // Refresh. + void (*BeginFrame) (void); + + /** + * Called at the end of a refresh frame. This is the last chance the game + * will have at updating the engine state before rendering of the frame + * begins. Once rendering begins, the viewer can still be updated however + * any changes will not take effect until the subsequent frame. Therefore + * this is the place where games should strive to update the viewer to + * ensure latency-free world refresh. + */ + void (*EndFrame) (void); + + /** + * Draw the view port display of the identified console @a player. + * The engine will configure a orthographic GL projection in real pixel + * dimensions prior to calling this. + * + * Example subdivision of the game window into four view ports: + *
+     *     (0,0)-----------------------. X
+     *       | .--------. |            |
+     *       | | window | |            |
+     *       | '--------' |            |
+     *       |    port #0 |    port #1 |
+     *       |-------------------------|
+     *       |            |            |
+     *       |            |            |
+     *       |            |            |
+     *       |    port #2 |    port #3 |
+     *       '--------------------(xn-1, yn-1)
+     *       Y               Game Window
+     * 
+ * + * @param port Logical number of this view port. + * @param portGeometry Geometry of the view port in real screen pixels. + * @param windowGeometry Geometry of the view window within the port, in + * real screen pixels. + * + * @param player Console player number associated with the view port. + * @param layer Logical layer identifier for the content to be drawn: + * - 0: The bottom-most layer and the one which generally contains the + * call to R_RenderPlayerView. + * - 1: Displays to be drawn on top of view window (after bordering), + * such as the player HUD. + */ + void (*DrawViewPort) (int port, RectRaw const *portGeometry, + RectRaw const *windowGeometry, int player, int layer); + + /** + * Draw over-viewport displays covering the whole game window. Typically + * graphical user interfaces such as game menus are done here. + * + * @param windowSize Dimensions of the game window in real screen pixels. + */ + void (*DrawWindow) (Size2Raw const *windowSize); + + // Miscellaneous. + void (*MobjThinker) (void *mobj); + coord_t (*MobjFriction) (struct mobj_s const *mobj); // Returns a friction factor. + dd_bool (*MobjCheckPositionXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z); + dd_bool (*MobjTryMoveXYZ) (struct mobj_s *mobj, coord_t x, coord_t y, coord_t z); + de::String (*MobjStateAsInfo) (struct mobj_s const *); + void (*MobjRestoreState) (struct mobj_s *, de::Info::BlockElement const &stateInfoBlockElement); + + void (*SectorHeightChangeNotification)(int sectorIdx); // Applies necessary checks on objects. + + // Map setup + + /** + * Called once a map change (i.e., P_MapChange()) has completed to allow the + * game to do any post change finalization it needs to do at this time. + */ + void (*FinalizeMapChange) (void const *uri); + + /** + * Called when trying to assign a value read from the map data (to a + * property known to us) that we don't know what to do with. + * + * (eg the side->toptexture field contains a text string that + * we don't understand but the game might). + * + * @return The action code returned by the game depends on the context. + */ + int (*HandleMapDataPropertyValue) (uint id, int dtype, int prop, + valuetype_t type, void *data); + // Post map setup + /** + * The engine calls this to inform the game of any changes it is + * making to map data object to which the game might want to + * take further action. + */ + int (*HandleMapObjectStatusReport) (int code, uint id, int dtype, void *data); +}; + +/** * Plugin loader. */ class LIBDOOMSDAY_PUBLIC Plugins @@ -167,7 +299,7 @@ /** * Returns the current game plugin's entrypoints. */ - game_export_t &gameExports() const; + GameExports &gameExports() const; public: // Function hooks: ---------------------------------------------------------- diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundlelinkfeed.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundlelinkfeed.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundlelinkfeed.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundlelinkfeed.h 2018-12-11 07:08:20.000000000 +0000 @@ -24,7 +24,7 @@ namespace res { /** - * FS feed for maanging data bundle links. + * FS feed for managing data bundle links. * * The main responsibility of the feed is to prune broken links. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundles.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundles.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundles.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/bundles.h 2018-12-11 07:08:20.000000000 +0000 @@ -67,6 +67,18 @@ BlockElements formatEntries(DataBundle::Format format) const; /** + * Defines a known pacakge. When identifying the specified path, it will be + * recognized as @a packageId. This is used for overriding the normal data bundle + * registry programmatically. The known file is given a maximum match score. + * + * @param path Path of a data bundle. + * @param packageId Package identifier. + */ +// void defineKnownPackage(de::Path const &path, de::String const &packageId); + +// void undefineKnownPackage(de::Path const &path); + + /** * Tries to identify of the data files that have been indexed since the * previous call of this method. Recognized data files are linked as * packages under the /sys/bundles folder. @@ -81,7 +93,7 @@ bool isEverythingIdentified() const; - void waitForEverythingIdentified(); +// void waitForEverythingIdentified(); /** * Finds a matching entry in the registry for a given data bundle. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/databundle.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/databundle.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/databundle.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/databundle.h 2018-12-11 07:08:20.000000000 +0000 @@ -23,6 +23,8 @@ #include "lumpdirectory.h" #include #include +#include +#include /** * Abstract base class for classic data files: PK3, WAD, LMP, DED, DEH. @@ -66,11 +68,15 @@ de::File const &asFile() const; de::File const &sourceFile() const; + de::String rootPath() const; + /** * Identifier of the package representing this data bundle (after being identified). */ de::String packageId() const; + de::String versionedPackageId() const; + /** * Generates appropriate packages according to the contents of the data bundle. * @return @c true, if the bundle was identid and linked as a package. @@ -126,6 +132,8 @@ */ de::String guessCompatibleGame() const; + void checkAuxiliaryNotes(de::Record &packageMetadata); + // Implements IByteArray. Size size() const; void get(Offset at, Byte *values, Size count) const; @@ -146,6 +154,8 @@ static DataBundle const *bundleForPackage(de::String const &packageId); + static DataBundle const *tryLocateDataFile(de::Package const &package, de::String const &dataFilePath); + /** * Compiles a list of all data bundles that have been loaded via * PackageLoader. The order of the list reflects the order in which @@ -170,6 +180,10 @@ static de::StringList gameTags(); static de::String anyGameTagPattern(); + static de::String cleanIdentifier(de::String const &text); + static de::String stripVersion(de::String const &text, de::Version *version = nullptr); + static de::String stripRedundantParts(de::String const &id); + static de::String versionFromTimestamp(de::Time const ×tamp); protected: void setFormat(Format format); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/lumpcatalog.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/lumpcatalog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/lumpcatalog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/lumpcatalog.h 2018-12-11 07:08:20.000000000 +0000 @@ -37,6 +37,8 @@ public: LumpCatalog(); + LumpCatalog(const LumpCatalog &); + void clear(); /** @@ -49,6 +51,8 @@ * @return @c true, if the list of packages is different than the one set previously. */ bool setPackages(de::StringList packageIds); + + de::StringList packages() const; de::Block read(de::String const &lumpName) const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resourceclass.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resourceclass.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resourceclass.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resourceclass.h 2018-12-11 07:08:20.000000000 +0000 @@ -35,7 +35,7 @@ */ typedef enum resourceclassid_e { RC_NULL = -2, ///< Not a real class. - RC_UNKNOWN = -1, ///< Attempt to guess the class through evaluation of the path. + RC_IMPLICIT = -1, ///< Attempt to guess the class through evaluation of the path. RESOURCECLASS_FIRST = 0, RC_PACKAGE = RESOURCECLASS_FIRST, RC_DEFINITION, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/resource/resources.h 2018-12-11 07:08:20.000000000 +0000 @@ -138,7 +138,7 @@ { auto const *path = reinterpret_cast(context); /// @todo Use PathTree::Node::compare() - return manifest.path().toStringRef().beginsWith(*path, Qt::CaseInsensitive); + return manifest.path().toStringRef().beginsWith(*path, de::String::CaseInsensitive); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/savegames.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/savegames.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/savegames.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/savegames.h 2018-12-11 07:08:20.000000000 +0000 @@ -54,6 +54,7 @@ bool convertLegacySavegames(de::String const &gameId, de::String const &sourcePath = ""); static void consoleRegister(); + static de::String savePath(); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/uri.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/uri.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/uri.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/uri.h 2018-12-11 07:08:20.000000000 +0000 @@ -83,6 +83,8 @@ */ Uri(); + Uri(String const &percentEncoded); + /** * Construct a Uri instance from a text string. * @@ -91,13 +93,13 @@ * * @param defaultResClass Default scheme. Determines the scheme for the Uri * if one is not specified in @a percentEncoded. - * @c RC_UNKNOWN: resource locator guesses an + * @c RC_IMPLICIT: resource locator guesses an * appropriate scheme for this type of file. * * @param sep Character used to separate path segments * in @a path. */ - Uri(String const &percentEncoded, resourceclassid_t defaultResClass = RC_UNKNOWN, QChar sep = '/'); + Uri(String const &percentEncoded, resourceclassid_t defaultResClass, QChar sep = '/'); /** * Construct a Uri from a textual scheme and a path. @@ -111,7 +113,7 @@ * Construct a Uri instance from a path. Note that Path instances can * never contain a scheme as a prefix, so @a resClass is mandatory. * - * @param resClass Scheme for the URI. @c RC_UNKNOWN: resource locator + * @param resClass Scheme for the URI. @c RC_IMPLICIT: resource locator * guesses an appropriate scheme for this. * * @param path Path of the URI. @@ -126,7 +128,7 @@ Uri(Path const &path); /** - * Construct a Uri instance from a UTF-8 C-style text string, using RC_UNKNOWN + * Construct a Uri instance from a UTF-8 C-style text string, using RC_IMPLICIT * as the default resource class. * * @param nullTerminatedCStr String to be parsed. Assumed to be in @@ -297,7 +299,7 @@ * * @param sep Character used to separate path segments in @a path. */ - Uri &setUri(String newUri, resourceclassid_t defaultResourceClass = RC_UNKNOWN, QChar sep = '/'); + Uri &setUri(String newUri, resourceclassid_t defaultResourceClass = RC_IMPLICIT, QChar sep = '/'); /** * Compose from this URI a plain-text representation. Any symbolic identifiers @@ -344,6 +346,11 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(Uri::ComposeAsTextFlags) +inline Uri makeUri(String const &percentEncoded, QChar sep = '/') +{ + return Uri(percentEncoded, RC_NULL, sep); +} + } // namespace de namespace std { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/material.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/material.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/material.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/material.h 2018-12-11 07:08:20.000000000 +0000 @@ -111,6 +111,8 @@ return (_flags & Valid) != 0; } + virtual bool isAnimated() const; + /** * Change the do-not-draw property of the material according to @a yes. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/materials.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/materials.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/materials.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/materials.h 2018-12-11 07:08:20.000000000 +0000 @@ -193,7 +193,11 @@ * * @param func Callback to make for each Material. */ - de::LoopResult forAllMaterials(std::function func) const; + de::LoopResult forAllMaterials(const std::function &func) const; + + de::LoopResult forAnimatedMaterials(const std::function &func) const; + + void updateLookup(); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobj.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobj.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobj.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobj.h 2018-12-11 07:08:20.000000000 +0000 @@ -34,9 +34,6 @@ // We'll use the base mobj template directly as our mobj. typedef struct mobj_s { DD_BASE_MOBJ_ELEMENTS() -#ifdef __cplusplus - mobj_s(thinker_s::InitBehavior b) : thinker(b) {} -#endif } mobj_t; #endif // LIBDOOMSDAY_CUSTOM_MOBJ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobjthinkerdata.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobjthinkerdata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobjthinkerdata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/mobjthinkerdata.h 2018-12-11 07:08:20.000000000 +0000 @@ -35,6 +35,7 @@ MobjThinkerData(de::Id const &id = de::Id::none()); MobjThinkerData(MobjThinkerData const &other); + void think() override; IData *duplicate() const override; mobj_t *mobj(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinkerdata.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinkerdata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinkerdata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinkerdata.h 2018-12-11 07:08:20.000000000 +0000 @@ -89,7 +89,7 @@ * @param id Identifier. * @return Thinker or @c nullptr. */ - //static ThinkerData *find(de::Id const &id); + static ThinkerData *find(de::Id const &id); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinker.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinker.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinker.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/include/doomsday/world/thinker.h 2018-12-11 07:08:20.000000000 +0000 @@ -43,16 +43,10 @@ uint32_t _flags; thid_t id; ///< Only used for mobjs (zero is not an ID). void *d; ///< Private data (owned). -#ifdef __cplusplus - enum InitBehavior { InitializeToZero }; - thinker_s(InitBehavior) { de::zap(*this); } - DENG2_NO_ASSIGN(thinker_s) - DENG2_NO_COPY(thinker_s) -#endif } thinker_t; #define THINKER_DATA(thinker, T) (reinterpret_cast((thinker).d)->as()) -#define THINKER_DATA_MAYBE(thinker, T) (maybeAs(reinterpret_cast((thinker).d))) +#define THINKER_DATA_MAYBE(thinker, T) (de::maybeAs(reinterpret_cast((thinker).d))) #ifdef __cplusplus extern "C" { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/databundles.dei doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/databundles.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/databundles.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/databundles.dei 2018-12-11 07:08:20.000000000 +0000 @@ -107,6 +107,35 @@ } } +package "com.idsoftware.doom.bfg_2012.10.16" { + format: PWAD + fileName: doom.wad + fileSize: 12487824 + lumps + lumpDirCRC32: 8aed7bf2 + info { + title: Ultimate DOOM (BFG Edition) + author: id Software + license: All rights reserved + tags: gamedata doom bfg + } +} + +package "com.idsoftware.doom.bfg.decensor_1.0" { + format: IWAD + fileName + fileSize: 12487826 + lumps + lumpDirCRC32: e51d82df + info { + title: Ultimate DOOM (BFG Edition + decensor) + author: id Software + license: All rights reserved + tags: gamedata doom bfg mod uncensored + notes: Variant of Ultimate DOOM (BFG Edition) generated using the "bfgdecens" tool. + } +} + package "com.idsoftware.doom2_1.6.66" { format: IWAD fileName: doom2.wad @@ -120,6 +149,18 @@ } } +package "com.idsoftware.doom2.german_1.6.66" { + format: IWAD + fileName: doom2.wad + fileSize: 14824716 + info { + title: DOOM 2: Hell on Earth (German) + author: id Software + license: All rights reserved + tags: doom vanilla german + } +} + package "com.idsoftware.doom2.french_1.8" { format: IWAD fileName: doom2f.wad @@ -147,6 +188,50 @@ } } +package "com.idsoftware.doom2.bfg_2012.10.16" { + format: PWAD + fileName: doom2.wad + fileSize: 14691821 + lumps + lumpDirCRC32: 2f9a0a30 + info { + title: DOOM 2: Hell on Earth (BFG Edition) + author: id Software + license: All rights reserved + tags: gamedata doom bfg + } +} + +package "com.idsoftware.doom2.bfg.decensor_1.0" { + format: IWAD + fileName + fileSize: 14692182 + lumps + lumpDirCRC32: 376c997e + info { + title: DOOM 2: Hell on Earth (BFG Edition + decensor) + author: id Software + license: All rights reserved + tags: gamedata doom bfg mod uncensored + notes: Variant of DOOM II (BFG Edition) generated using the "bfgdecens" tool. + } +} + +package "com.nervesoftware.norestfortheliving_2012.10.16" { + format: PWAD + fileName: nerve.wad + fileSize: 3819855 + lumps + lumpDirCRC32: 29240a37 + info { + title: No Rest for the Living + author: Nerve Software + license: All rights reserved + tags: gamedata doom bfg expansion + requires + } +} + package "com.idsoftware.finaldoom.plutonia_1.9" { format: IWAD fileName: plutonia.wad @@ -352,6 +437,20 @@ } } +package "freedoom.phase2_0.11.3" { + format: IWAD + fileName + fileSize: 29102220 + lumps + lumpDirCRC32: a8eb8bcd + info { + title: Freedoom: Phase 2 + author: Freedoom Project + license: BSD + tags: gamedata doom2 mod + } +} + package "freedoom.phase1_0.9" { format: IWAD fileName: freedoom1.wad @@ -408,6 +507,20 @@ } } +package "freedoom.phase1_0.11.3" { + format: IWAD + fileName: freedoom1.wad + fileSize: 23578720 + lumps + lumpDirCRC32: c03f5092 + info { + title: Freedoom: Phase 1 + author: Freedoom Project + license: BSD + tags: gamedata doom mod + } +} + package "freedoom.freedm_0.10.1" { format: IWAD fileName: freedm.wad @@ -436,6 +549,20 @@ } } +package "freedoom.freedm_0.11.3" { + format: IWAD + fileName: freedm.wad + fileSize: 21112116 + lumps + lumpDirCRC32: 521c112b + info { + title: Freedoom Deathmatch + author: Freedoom Project + license: BSD + tags: gamedata doom2 mod multiplayer + } +} + package "com.ravensoftware.heretic_1.0" { format: IWAD fileName: heretic.wad @@ -513,7 +640,7 @@ author: Raven Software license: All rights reserved tags: gamedata hexen vanilla expansion - required + requires } } @@ -528,7 +655,7 @@ author: Raven Software license: All rights reserved tags: gamedata hexen vanilla expansion - required + requires } } @@ -560,6 +687,20 @@ } } +package "com.ravensoftware.hexen.mac_1.1" { + format: IWAD + fileName: hexen.wad + fileSize: 21078584 + lumps + lumpDirCRC32: 6340baf + info { + title: Hexen (Macintosh) + author: Raven Software + license: All rights reserved + tags: gamedata hexen vanilla mac + } +} + package "com.ravensoftware.hexen.beta" { format: IWAD fileName diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/defs/flags.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/defs/flags.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/defs/flags.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/defs/flags.ded 2018-12-11 07:08:20.000000000 +0000 @@ -70,6 +70,7 @@ Flag { ID = "mif_sphere"; Value = 0x2; } # Draw the sky sphere even when models are in use. Flag { ID = "mif_nointermission"; Value = 0x4; } Flag { ID = "mif_lightning"; Value = 0x8; } +Flag { ID = "mif_spawn_all_firemaces"; Value = 0x10; } # Sky Info Flag { ID = "sif_sphere"; Value = 0x1; } # Draw the sky sphere even when models are in use. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/Info 2018-12-11 07:08:20.000000000 +0000 @@ -1,7 +1,7 @@ # Shared resources for all Doomsday applications title: Doomsday Base -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.de doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,44 +0,0 @@ -# The Doomsday Engine Project -- Doomsday Base Library -# -# Copyright (c) 2013-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -def setDefaults(d) - # Resource settings. - record d.resource() - iwadFolder = '' - packageFolder = '' - end - - try - import clientconfig - clientconfig.setDefaults(d) - catch: pass - - # Game mode related information (one for each game plugin): - # TODO: plugins should have their own Config scripts (when libcore loads them) - record d.plugin() - record doom - record heretic - record hexen - record doom64 - - # Single-shot load hooks. - doom.onNextLoad = [] - heretic.onNextLoad = [] - hexen.onNextLoad = [] - doom64.onNextLoad = [] - end -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.ds doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/net.dengine.base.pack/modules/appconfig.ds 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,58 @@ +# The Doomsday Engine Project -- Doomsday Base Library +# +# Copyright (c) 2013-2018 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +def setDefaults(d) + # Resource settings. + record d.resource() + iwadFolder = '' + packageFolder = '' + + # Dictionary of folders that should be fully recursed. Affects the + # folders listed in resource.packageFolder (native path -> bool). + recursedFolders = {} + + # Online package repositories. + repositories = { + 'idgames archive (gamers.org)': 'http://www.gamers.org/pub/idgames/', + 'idgames mirror (Idaho, USA)': 'http://mirrors.syringanetworks.net/idgames/', + 'idgames mirror (New York, USA)': 'http://youfailit.net/pub/idgames/', + 'idgames mirror (Germany)': 'https://www.quaddicted.com/files/idgames/', + 'idgames mirror (Greece)': 'http://ftp.ntua.gr/pub/vendors/idgames/', + 'idgames mirror (Texas, USA)': 'http://ftp.mancubus.net/pub/idgames/' + } + end + + try + import clientconfig + clientconfig.setDefaults(d) + catch: pass + + # Game mode related information (one for each game plugin): + # TODO: plugins should have their own Config scripts (when libcore loads them) + record d.plugin() + record doom + record heretic + record hexen + record doom64 + + # Single-shot load hooks. + doom.onNextLoad = [] + heretic.onNextLoad = [] + hexen.onNextLoad = [] + doom64.onNextLoad = [] + end +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/abstractsession.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/abstractsession.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/abstractsession.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/abstractsession.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -24,10 +24,12 @@ #include #include #include +#include +#include using namespace de; -static AbstractSession::Profile currentProfile; +//static AbstractSession::Profile currentProfile; DENG2_PIMPL_NOREF(AbstractSession) { @@ -48,11 +50,11 @@ d->inProgress = inProgress; } -AbstractSession::Profile &AbstractSession::profile() //static -{ - /// @todo None current profiles should be stored persistently when the game changes. - return currentProfile; -} +//AbstractSession::Profile &AbstractSession::profile() //static +//{ +// /// @todo None current profiles should be stored persistently when the game changes. +// return currentProfile; +//} bool AbstractSession::hasBegun() const { @@ -61,7 +63,7 @@ de::Uri AbstractSession::mapUri() const { - return hasBegun()? d->mapUri : de::Uri("Maps:", RC_NULL); + return hasBegun()? d->mapUri : de::makeUri("Maps:"); } world::IThinkerMapping const *AbstractSession::thinkerMapping() const @@ -74,6 +76,13 @@ d->thinkerMapping = mapping; } +//String AbstractSession::gameId() const +//{ +// const auto *gameProfile = DoomsdayApp::currentGameProfile(); +// DENG_ASSERT(gameProfile != nullptr); +// return gameProfile->gameId(); +//} + void AbstractSession::setMapUri(de::Uri const &uri) { d->mapUri = uri; @@ -96,6 +105,6 @@ removeSaved(destPath); GameStateFolder const &original = App::rootFolder().locate(sourcePath); - GameStateFolder &copied = App::fileSystem().copySerialized(sourcePath, destPath).as(); + GameStateFolder &copied = FS::copySerialized(sourcePath, destPath).as(); copied.cacheMetadata(original.metadata()); // Avoid immediately opening the .save package. } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/console/exec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/console/exec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/console/exec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/console/exec.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include #include @@ -106,6 +108,7 @@ D_CMD(InspectMobj); D_CMD(DebugCrash); D_CMD(DebugError); +D_CMD(DoomsdayScript); void initVariableBindings(Binder &); @@ -142,6 +145,7 @@ #ifdef _DEBUG C_CMD("crash", NULL, DebugCrash); #endif + C_CMD("ds", "s*", DoomsdayScript); Con_DataRegister(); } @@ -393,7 +397,7 @@ storage[255] = 0; - TimeDelta const now = TimeDelta::sinceStartOfProcess(); + TimeSpan const now = TimeSpan::sinceStartOfProcess(); // Execute the commands whose time has come. for (i = 0; i < exBuffSize; ++i) @@ -413,7 +417,7 @@ ptr->source == CMDS_CMDLINE); if (isInteractive) { - Log::threadLog().beginInteractive(); + LOG().beginInteractive(); } if (!executeSubCmd(storage, ptr->source, ptr->isNetCmd)) @@ -423,7 +427,7 @@ if (isInteractive) { - Log::threadLog().endInteractive(); + LOG().endInteractive(); } } @@ -714,7 +718,7 @@ break; case CVT_URIPTR: /// @todo Sanitize and validate against known schemas. - CVar_SetUri(cvar, de::Uri(argptr, RC_NULL)); + CVar_SetUri(cvar, de::makeUri(argptr)); break; default: break; } @@ -841,7 +845,7 @@ } // Queue it. - Con_QueueCmd(subCmd, TimeDelta::sinceStartOfProcess() + markerOffset, src, isNetCmd); + Con_QueueCmd(subCmd, TimeSpan::sinceStartOfProcess() + markerOffset, src, isNetCmd); scPos = 0; } @@ -1168,7 +1172,7 @@ {"<=", IF_LEQUAL}, {NULL, 0} }; - uint i, oper; + uint i, oper = IF_EQUAL; cvar_t *var; dd_bool isTrue = false; @@ -1400,3 +1404,19 @@ LOG_SCR_MSG("Found %i aliases") << numPrinted; return true; } + +D_CMD(DoomsdayScript) +{ + DENG_UNUSED(src); + DENG_UNUSED(argc); + String source; + for (int i = 1; i < argc; ++i) + { + if (source) source += " "; + source += String(argv[i]); + } + Script script(source); + Process proc(script); + proc.execute(); + return true; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/console/knownword.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/console/knownword.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/console/knownword.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/console/knownword.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -64,8 +64,8 @@ case WT_GAME: textA = AutoStr_FromTextStd(reinterpret_cast(wA->data)->id().toUtf8().constData()); break; default: - App_FatalError("compareKnownWordByName: Invalid type %i for word A.", wA->type); - exit(1); // Unreachable + DENG_ASSERT(!"compareKnownWordByName: Invalid type for word A"); + return false; } switch (wB->type) @@ -76,8 +76,8 @@ case WT_GAME: textB = AutoStr_FromTextStd(reinterpret_cast(wB->data)->id().toUtf8().constData()); break; default: - App_FatalError("compareKnownWordByName: Invalid type %i for word B.", wB->type); - exit(1); // Unreachable + DENG_ASSERT(!"compareKnownWordByName: Invalid type for word B"); + return false; } return Str_CompareIgnoreCase(textA, Str_Text(textB)) < 0; @@ -98,8 +98,8 @@ case WT_GAME: text = AutoStr_FromTextStd(reinterpret_cast(word->data)->id().toUtf8().constData()); break; default: - App_FatalError("textForKnownWord: Invalid type %i for word.", word->type); - exit(1); // Unreachable + DENG_ASSERT(!"textForKnownWord: Invalid type for word"); + text = AutoStr_FromTextStd(""); } return text; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/decoration.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/decoration.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/decoration.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/decoration.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -27,27 +27,31 @@ namespace defn { +static String const VAR_TEXTURE = "texture"; +static String const VAR_FLAGS = "flags"; +static String const VAR_LIGHT = "light"; + void Decoration::resetToDefaults() { Definition::resetToDefaults(); // Add all expected fields with their default values. - def().addText ("texture", ""); // URI. Unknown. - def().addNumber("flags", 0); - def().addArray ("light", new ArrayValue); + def().addText (VAR_TEXTURE, ""); // URI. Unknown. + def().addNumber(VAR_FLAGS, 0); + def().addArray (VAR_LIGHT, new ArrayValue); } Record &Decoration::addLight() { auto *decor = new Record; MaterialDecoration(*decor).resetToDefaults(); - def()["light"].array().add(new RecordValue(decor, RecordValue::OwnsRecord)); + def()[VAR_LIGHT].array().add(new RecordValue(decor, RecordValue::OwnsRecord)); return *decor; } int Decoration::lightCount() const { - return int(geta("light").size()); + return int(geta(VAR_LIGHT).size()); } bool Decoration::hasLight(int index) const @@ -57,12 +61,12 @@ Record &Decoration::light(int index) { - return *def().geta("light")[index].as().record(); + return *def().geta(VAR_LIGHT)[index].as().record(); } Record const &Decoration::light(int index) const { - return *geta("light")[index].as().record(); + return *geta(VAR_LIGHT)[index].as().record(); } } // namespace defn diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/ded.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/ded.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/ded.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/ded.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -41,9 +41,11 @@ using namespace de; +static String const VAR_ID = "id"; + float ded_ptcstage_t::particleRadius(int ptcIDX) const { - if (radiusVariance) + if (radiusVariance != 0.f) { static float const rnd[16] = { .875f, .125f, .3125f, .75f, .5f, .375f, .5625f, .0625f, 1, .6875f, .625f, .4375f, .8125f, .1875f, @@ -68,20 +70,20 @@ , decorations(names.addSubrecord("decorations")) { decorations.addLookupKey("texture"); - episodes.addLookupKey("id"); - things.addLookupKey("id", DEDRegister::OnlyFirst); + episodes.addLookupKey(VAR_ID); + things.addLookupKey(VAR_ID, DEDRegister::OnlyFirst); things.addLookupKey("name"); - states.addLookupKey("id", DEDRegister::OnlyFirst); - finales.addLookupKey("id"); + states.addLookupKey(VAR_ID, DEDRegister::OnlyFirst); + finales.addLookupKey(VAR_ID); finales.addLookupKey("before"); finales.addLookupKey("after"); - flags.addLookupKey("id"); - mapInfos.addLookupKey("id"); - materials.addLookupKey("id"); - models.addLookupKey("id", DEDRegister::OnlyFirst); + flags.addLookupKey(VAR_ID); + mapInfos.addLookupKey(VAR_ID); + materials.addLookupKey(VAR_ID); + models.addLookupKey(VAR_ID, DEDRegister::OnlyFirst); models.addLookupKey("state"); - musics.addLookupKey("id", DEDRegister::OnlyFirst); - skies.addLookupKey("id"); + musics.addLookupKey(VAR_ID, DEDRegister::OnlyFirst); + skies.addLookupKey(VAR_ID); clear(); } @@ -99,7 +101,7 @@ int ded_s::addFlag(String const &id, int value) { Record &def = flags.append(); - def.addText("id", id); + def.addText(VAR_ID, id); def.addNumber("value", value); return def.geti(defn::Definition::VAR_ORDER); } @@ -115,7 +117,7 @@ { Record &def = things.append(); defn::Thing(def).resetToDefaults(); - def.set("id", id); + def.set(VAR_ID, id); return def.geti(defn::Definition::VAR_ORDER); } @@ -123,7 +125,7 @@ { Record &def = states.append(); defn::State(def).resetToDefaults(); - def.set("id", id); + def.set(VAR_ID, id); return def.geti(defn::Definition::VAR_ORDER); } @@ -257,7 +259,7 @@ return ded->textureEnv.indexOf(env); } -int DED_AddCompositeFont(ded_t* ded, char const* uri) +int DED_AddCompositeFont(ded_t* ded, char const *uri) { ded_compositefont_t* cfont = ded->compositeFonts.append(); if (uri) cfont->uri = new de::Uri(uri, RC_NULL); @@ -360,7 +362,7 @@ int ded_s::getMobjNum(String const &id) const { - if (Record const *def = things.tryFind("id", id)) + if (Record const *def = things.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -393,12 +395,12 @@ { if (num < 0) return "(<0)"; if (num >= things.size()) return "(>mobjtypes)"; - return things[num].gets("id"); + return things[num].gets(VAR_ID); } int ded_s::getStateNum(String const &id) const { - if (Record const *def = states.tryFind("id", id)) + if (Record const *def = states.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -424,7 +426,7 @@ String flagName(ptr, flagNameLength); ptr += flagNameLength; - if (Record const *flag = flags.tryFind("id", flagName.toLower())) + if (Record const *flag = flags.tryFind(VAR_ID, flagName.toLower())) { value |= flag->geti("value"); } @@ -438,7 +440,7 @@ int ded_s::getEpisodeNum(String const &id) const { - if (Record const *def = episodes.tryFind("id", id)) + if (Record const *def = episodes.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -447,7 +449,7 @@ int ded_s::getMapInfoNum(de::Uri const &uri) const { - if (Record const *def = mapInfos.tryFind("id", uri.compose())) + if (Record const *def = mapInfos.tryFind(VAR_ID, uri.compose())) { return def->geti(defn::Definition::VAR_ORDER); } @@ -476,7 +478,7 @@ /*if (idx >= 0)*/ return idx; } - if (Record const *def = materials.tryFind("id", uri.compose())) + if (Record const *def = materials.tryFind(VAR_ID, uri.compose())) { return def->geti(defn::Definition::VAR_ORDER); } @@ -485,7 +487,7 @@ int ded_s::getModelNum(const char *id) const { - if (Record const *def = models.tryFind("id", id)) + if (Record const *def = models.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -504,7 +506,7 @@ int ded_s::getSkyNum(char const *id) const { - if (Record const *def = skies.tryFind("id", id)) + if (Record const *def = skies.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -570,7 +572,7 @@ int ded_s::getMusicNum(char const *id) const { - if (Record const *def = musics.tryFind("id", id)) + if (Record const *def = musics.tryFind(VAR_ID, id)) { return def->geti(defn::Definition::VAR_ORDER); } @@ -674,6 +676,22 @@ return def; } +String ded_s::findEpisode(String const &mapId) const +{ + de::Uri mapUri(mapId, RC_NULL); + if (mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); + + for (int i = 0; i < episodes.size(); ++i) + { + defn::Episode episode(episodes[i]); + if (episode.tryFindMapGraphNode(mapUri.compose())) + { + return episode.gets(VAR_ID); + } + } + return String(); +} + int ded_s::getTextNum(char const *id) const { if (id && id[0]) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/dedregister.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/dedregister.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/dedregister.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/dedregister.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -156,7 +156,7 @@ bool isEmptyKeyValue(Value const &value) const { - return value.is() && value.asText().isEmpty(); + return is(value) && value.asText().isEmpty(); } bool isValidKeyValue(Value const &value) const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/episode.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/episode.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/episode.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/episode.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -86,7 +86,7 @@ foreach (Value *mapIt, hubRec.geta("map").elements()) { Record &mgNodeDef = mapIt->as().dereference(); - if (mapUri == de::Uri(mgNodeDef.gets("id"), RC_NULL)) + if (mapUri == de::makeUri(mgNodeDef.gets("id"))) { return &hubRec; } @@ -108,7 +108,7 @@ foreach (Value *mapIt, hubRec.geta("map").elements()) { Record &mgNodeDef = mapIt->as().dereference(); - if (mapUri == de::Uri(mgNodeDef.gets("id"), RC_NULL)) + if (mapUri == de::makeUri(mgNodeDef.gets("id"))) { return &mgNodeDef; } @@ -118,7 +118,7 @@ foreach (Value *mapIt, geta("map").elements()) { Record &mgNodeDef = mapIt->as().dereference(); - if (mapUri == de::Uri(mgNodeDef.gets("id"), RC_NULL)) + if (mapUri == de::makeUri(mgNodeDef.gets("id"))) { return &mgNodeDef; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/sprite.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/sprite.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/defs/sprite.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/defs/sprite.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -107,7 +107,7 @@ def().set(VAR_FRONT_ONLY, angle <= 0); auto *view = new Record; - view->add(VAR_MATERIAL).set(new UriValue(de::Uri(material, RC_NULL))); + view->add(VAR_MATERIAL).set(new UriValue(de::makeUri(material))); view->addBoolean(VAR_MIRROR_X, mirrorX); viewsDict().add(new NumberValue(de::max(0, angle - 1)), new RecordValue(view, RecordValue::OwnsRecord)); return *view; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/doomsdayapp_bindings.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,57 @@ +/** @file doomsdayapp_bindings.cpp Script bindings for libdoomsday. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "doomsday/DoomsdayApp" + +#include +#include + +using namespace de; + +static Value *Function_App_Download(Context &, Function::ArgumentValues const &args) +{ + String const packageId = args.first()->asText(); + DoomsdayApp::packageDownloader().download(StringList({ packageId }), [packageId] () + { + LOG().beginInteractive(); + + LOG_SCR_MSG("Package \"%s\" downloaded.") << packageId; + + LOG().endInteractive(); + }); + return nullptr; +} + +static Value *Function_FS_RefreshPackageFolders(Context &, const Function::ArgumentValues &) +{ + LOG_SCR_MSG("Initializing package folders..."); + Folder::afterPopulation([]() { + DoomsdayApp::app().initWadFolders(); + DoomsdayApp::app().initPackageFolders(); + }); + return nullptr; +} + +void DoomsdayApp::initBindings(Binder &binder) +{ + binder.init(ScriptSystem::get()["App"]) + << DENG2_FUNC(App_Download, "download", "packageId"); + + binder.init(ScriptSystem::get()["FS"]) + << DENG2_FUNC_NOARG(FS_RefreshPackageFolders, "refreshPackageFolders"); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/doomsdayapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/doomsdayapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/doomsdayapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/doomsdayapp.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -28,6 +28,7 @@ #include "doomsday/filesys/datafile.h" #include "doomsday/filesys/datafolder.h" #include "doomsday/filesys/virtualmappings.h" +#include "doomsday/filesys/idgameslink.h" #include "doomsday/busymode.h" #include "doomsday/world/world.h" #include "doomsday/world/entitydef.h" @@ -48,6 +49,7 @@ #include #include #include +#include #include #include #include @@ -81,6 +83,7 @@ { std::string ddBasePath; // Doomsday root directory is at...? + Binder binder; bool initialized = false; bool gameBeingChanged = false; bool shuttingDown = false; @@ -94,6 +97,7 @@ BusyMode busyMode; Players players; res::Bundles dataBundles; + shell::PackageDownloader packageDownloader; SaveGames saveGames; LoopCallback mainCall; QTimer configSaveTimer; @@ -112,7 +116,7 @@ { ArrayValue args; args << DictionaryValue() << TextValue(newGame.id()); - App::scriptSystem().nativeModule("App")["audienceForGameChange"] + App::scriptSystem()["App"]["audienceForGameChange"] .array().callElements(args); } }; @@ -123,10 +127,13 @@ : Base(i) , players(playerConstructor) { - Record &appModule = App::scriptSystem().nativeModule("App"); + // Script bindings. + Record &appModule = App::scriptSystem()["App"]; appModule.addArray("audienceForGameChange"); // game change observers audienceForGameChange += scriptAudienceForGameChange; + initBindings(binder); + gameProfiles.setGames(games); saveGames .setGames(games); @@ -150,42 +157,88 @@ } }); configSaveTimer.start(); + + // File system extensions. + filesys::RemoteFeedRelay::get().defineLink(IdgamesLink::construct); } - ~Impl() + ~Impl() override { if (initialized) { // Save any changes to the game profiles. gameProfiles.serialize(); } + // Delete the temporary folder from the system disk. + if (Folder *tmp = FS::tryLocate("/tmp")) + { + tmp->destroyAllFilesRecursively(); + tmp->correspondingNativePath().destroy(); + } theDoomsdayApp = nullptr; Garbage_Recycle(); } - void attachWadFeed(String const &description, NativePath const &path) + DirectoryFeed::Flags directoryPopulationMode(const NativePath &path) const + { + const TextValue dir{path.toString()}; + if (Config::get().has("resource.recursedFolders")) + { + const auto &elems = Config::get().getdt("resource.recursedFolders").elements(); + auto i = elems.find(&dir); + if (i != elems.end()) + { + return i->second->isTrue() ? DirectoryFeed::PopulateNativeSubfolders + : DirectoryFeed::OnlyThisFolder; + } + } + return DirectoryFeed::PopulateNativeSubfolders; + } + + /** + * Composes a path that currently does not exist. The returned path is a subfolder of + * @a base and uses segments from @a path. + */ + Path composeUniqueFolderPath(Path base, const NativePath &path) const + { + if (path.segmentCount() >= 2) + { + base = base / path.lastSegment(); + } + // Choose a unique folder name. + // First try adding another segment. + Path folderPath = base; + if (FS::tryLocate(folderPath) && path.segmentCount() >= 3) + { + folderPath = folderPath.subPath(Rangei(0, folderPath.segmentCount() - 1)) / + path.reverseSegment(1) / folderPath.lastSegment(); + } + // Add a number. + int counter = 0; + while (FS::tryLocate(folderPath)) + { + folderPath = Path(base.toString() + String::format("%03d", ++counter)); + } + return folderPath; + } + + void attachWadFeed(const String & description, + const NativePath & path, + DirectoryFeed::Flags populationMode = DirectoryFeed::OnlyThisFolder) { if (!path.isEmpty()) { if (path.exists()) { - LOG_RES_NOTE("Using %s WAD folder: %s") << description << path.pretty(); - Path folderPathBase = PATH_LOCAL_WADS; - if (path.segmentCount() >= 2) - { - folderPathBase = folderPathBase / path.lastSegment(); - } - // Choose a unique folder name. - Path folderPath = folderPathBase; - int counter = 0; - while (FS::get().tryLocate(folderPath)) - { - folderPath = Path(String("%1-%2") - .arg(folderPathBase.toString()) - .arg(++counter, 3, 10, QChar('0'))); - } + LOG_RES_NOTE("Using %s WAD folder%s: %s") + << description + << (populationMode == DirectoryFeed::OnlyThisFolder ? "" + : " (including subfolders)") + << path.pretty(); + + const Path folderPath = composeUniqueFolderPath(PATH_LOCAL_WADS, path); FS::get().makeFolder(folderPath) - .attach(new DirectoryFeed(path, DirectoryFeed::OnlyThisFolder)); + .attach(new DirectoryFeed(path, populationMode)); } else { @@ -195,15 +248,21 @@ } } - void attachPacksFeed(String const &description, NativePath const &path) + void attachPacksFeed(String const &description, NativePath const &path, + DirectoryFeed::Flags populationMode) { if (!path.isEmpty()) { if (path.exists()) { - LOG_RES_NOTE("Using %s package folder (including subfolders): %s") - << description << path.pretty(); - App::rootFolder().locate(PATH_LOCAL_PACKS).attach(new DirectoryFeed(path)); + LOG_RES_NOTE("Using %s package folder%s: %s") + << description + << (populationMode == DirectoryFeed::OnlyThisFolder ? "" + : " (including subfolders)") + << path.pretty(); + const Path folderPath = composeUniqueFolderPath(PATH_LOCAL_PACKS, path); + FS::get().makeFolder(folderPath) + .attach(new DirectoryFeed(path, populationMode)); } else { @@ -340,7 +399,7 @@ // Configured via GUI. for (String path : App::config().getStringList("resource.iwadFolder")) { - attachWadFeed("user-selected", path); + attachWadFeed("user-selected", path, directoryPopulationMode(path)); } wads.populate(Folder::PopulateAsyncFullTree); @@ -348,7 +407,7 @@ void initPackageFolders() { - Folder &packs = FileSystem::get().makeFolder(PATH_LOCAL_PACKS, FS::DontInheritFeeds); + Folder &packs = FS::get().makeFolder(PATH_LOCAL_PACKS, FS::DontInheritFeeds); packs.clear(); packs.clearFeeds(); @@ -359,7 +418,8 @@ if (char *fn = UnixInfo_GetConfigValue("paths", "packsdir")) { attachPacksFeed("UnixInfo " _E(i) "paths.packsdir" _E(.), - cmdLine.startupPath() / fn); + cmdLine.startupPath() / fn, + DirectoryFeed::DefaultFlags); free(fn); } #endif @@ -372,20 +432,37 @@ if (cmdLine.isOption(p)) break; cmdLine.makeAbsolutePath(p); - attachPacksFeed("command-line", cmdLine.at(p)); + attachPacksFeed("command-line", cmdLine.at(p), DirectoryFeed::DefaultFlags); } } // Configured via GUI. for (String path : App::config().getStringList("resource.packageFolder")) { - attachPacksFeed("user-selected", path); + attachPacksFeed("user-selected", path, directoryPopulationMode(path)); } packs.populate(Folder::PopulateAsyncFullTree); } - void folderPopulationFinished() + void initRemoteRepositories() + { +#if 0 + filesys::RemoteFeedRelay::get().addRepository("https://www.quaddicted.com/files/idgames/", + "/remote/www.quaddicted.com"); +#endif + } + +// void remoteRepositoryStatusChanged(String const &address, filesys::RemoteFeedRelay::Status status) override +// { +// foreach (auto p, filesys::RemoteFeedRelay::get().locatePackages( +// StringList({"idgames.levels.doom2.deadmen"}))) +// { +// qDebug() << p.link->address() << p.localPath << p.remotePath; +// } +// } + + void folderPopulationFinished() override { if (initialized) { @@ -426,7 +503,6 @@ DENG2_PIMPL_AUDIENCE(GameUnload) DENG2_PIMPL_AUDIENCE(GameChange) DENG2_PIMPL_AUDIENCE(ConsoleRegistration) - DENG2_PIMPL_AUDIENCE(FileRefresh) DENG2_PIMPL_AUDIENCE(PeriodicAutosave) }; @@ -434,7 +510,6 @@ DENG2_AUDIENCE_METHOD(DoomsdayApp, GameUnload) DENG2_AUDIENCE_METHOD(DoomsdayApp, GameChange) DENG2_AUDIENCE_METHOD(DoomsdayApp, ConsoleRegistration) -DENG2_AUDIENCE_METHOD(DoomsdayApp, FileRefresh) DENG2_AUDIENCE_METHOD(DoomsdayApp, PeriodicAutosave) DoomsdayApp::DoomsdayApp(Players::Constructor playerConstructor) @@ -480,22 +555,27 @@ d->initWadFolders(); d->initPackageFolders(); - Folder::waitForPopulation(); + // We need to access the local file system to complete initialization. + Folder::waitForPopulation(Folder::BlockingMainThread); d->dataBundles.identify(); d->gameProfiles.deserialize(); + // Register some remote repositories. + d->initRemoteRepositories(); + d->initialized = true; } void DoomsdayApp::initWadFolders() { + FS::waitForIdle(); d->initWadFolders(); } void DoomsdayApp::initPackageFolders() { - DENG2_FOR_AUDIENCE2(FileRefresh, i) i->aboutToRefreshFiles(); + FS::waitForIdle(); d->initPackageFolders(); } @@ -532,6 +612,11 @@ return *theDoomsdayApp; } +shell::PackageDownloader &DoomsdayApp::packageDownloader() +{ + return DoomsdayApp::app().d->packageDownloader; +} + res::Bundles &DoomsdayApp::bundles() { return DoomsdayApp::app().d->dataBundles; @@ -707,7 +792,7 @@ void *unloader = plugins().findEntryPoint(game().pluginId(), "DP_Unload"); LOGDEV_MSG("Calling DP_Unload %p") << unloader; plugins().setActivePluginId(game().pluginId()); - if (unloader) ((pluginfunc_t)unloader)(); + if (unloader) reinterpret_cast(unloader)(); plugins().setActivePluginId(0); } @@ -725,7 +810,7 @@ Resources::get().clear(); // We do not want to load session resources specified on the command line again. - AbstractSession::profile().resourceFiles.clear(); +// AbstractSession::profile().resourceFiles.clear(); // The current game is now the special "null-game". setGame(games().nullGame()); @@ -799,9 +884,9 @@ app().d->currentGame = const_cast(&game); } -void DoomsdayApp::makeGameCurrent(GameProfile const &profile) +void DoomsdayApp::makeGameCurrent(const GameProfile &profile) { - auto const &newGame = profile.game(); + const auto &newGame = profile.game(); if (!newGame.isNull()) { @@ -824,7 +909,8 @@ // This is now the current game. setGame(newGame); d->currentProfile = &profile; - AbstractSession::profile().gameId = newGame.id(); + + profile.checkSaveLocation(); // in case it's gone missing if (!newGame.isNull()) { @@ -856,9 +942,9 @@ std::function gameActivationFunc, Behaviors behaviors) { - auto const &newGame = profile.game(); + const auto &newGame = profile.game(); - bool const arePackagesDifferent = + const bool arePackagesDifferent = !GameProfiles::arePackageListsCompatible(DoomsdayApp::app().loadedPackagesAffectingGameplay(), profile.packagesAffectingGameplay()); @@ -924,7 +1010,7 @@ void *loader = plugins().findEntryPoint(game().pluginId(), "DP_Load"); LOGDEV_MSG("Calling DP_Load %p") << loader; plugins().setActivePluginId(game().pluginId()); - if (loader) ((pluginfunc_t)loader)(); + if (loader) reinterpret_cast(loader)(); plugins().setActivePluginId(0); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/datafolder.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/datafolder.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/datafolder.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/datafolder.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -65,3 +65,12 @@ return desc; } + +IIStream const &DataFolder::operator >> (IByteArray &bytes) const +{ + if (source()) + { + *source() >> bytes; + } + return *this; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/file.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/file.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/file.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/file.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -28,8 +28,8 @@ namespace de { -File1::File1(FileHandle &hndl, String _path, FileInfo const &_info, File1 *_container) - : handle_(&hndl) +File1::File1(FileHandle *hndl, String _path, FileInfo const &_info, File1 *_container) + : handle_(hndl) , info_(_info) , container_(_container) , flags(DefaultFlags) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/fs_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/fs_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/fs_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/fs_main.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -42,6 +42,7 @@ #include #include #include +#include using namespace de; @@ -423,7 +424,7 @@ if (FILE *found = findAndOpenNativeFile(path, mode, foundPath)) { // Do not read files twice. - if (!allowDuplicate && !self().checkFileId(de::Uri(foundPath, RC_NULL))) + if (!allowDuplicate && !self().checkFileId(de::makeUri(foundPath))) { fclose(found); return 0; @@ -939,7 +940,7 @@ { // Use a generic file. File1 *container = (hndl.hasFile() && hndl.file().isContained())? &hndl.file().container() : 0; - interpretedFile = new File1(hndl, filePath, info, container); + interpretedFile = new File1(&hndl, filePath, info, container); } DENG2_ASSERT(interpretedFile); @@ -1238,6 +1239,11 @@ LOG_RES_MSG(_E(b)"Total: " _E(.) "%i files in %i packages") << totalFiles << totalPackages; + if (auto *svFiles = FS::get().tryLocate("/sys/server/public")) + { + LOG_RES_MSG("Server files:\n" _E(m) "%s") << svFiles->contentsAsText(); + } + return true; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/fs_scheme.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/fs_scheme.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/fs_scheme.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/fs_scheme.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -500,7 +500,7 @@ FileRef &fileRef = hashNode->fileRef; PathTree::Node &node = fileRef.directoryNode(); - if (!name.isEmpty() && !node.name().beginsWith(name, Qt::CaseInsensitive)) continue; + if (!name.isEmpty() && !node.name().beginsWith(name, String::CaseInsensitive)) continue; found.push_back(&node); } @@ -519,7 +519,7 @@ // Does this path qualify for mapping? if (path.length() <= name().length()) return false; if (path.at(name().length()) != '/') return false; - if (!path.beginsWith(name(), Qt::CaseInsensitive)) return false; + if (!path.beginsWith(name(), String::CaseInsensitive)) return false; // Yes. path = String("$(App.DataPath)/$(GamePlugin.Name)") / path; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/idgameslink.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/idgameslink.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/idgameslink.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/idgameslink.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,317 @@ +/** @file idgameslink.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "doomsday/filesys/idgameslink.h" +#include "doomsday/filesys/idgamespackageinfofile.h" +#include "doomsday/DataBundle" + +#include +#include +#include +#include + +#include +#include + +using namespace de; + +static String const DOMAIN_IDGAMES("idgames"); +static String const CATEGORY_LEVELS("levels"); +static String const CATEGORY_MUSIC ("music"); +static String const CATEGORY_SOUNDS("sounds"); +static String const CATEGORY_THEMES("themes"); + +DENG2_PIMPL(IdgamesLink) +{ + struct PackageIndexEntry : public PathTree::Node + { + FileEntry const *file = nullptr; + Version version; + + PackageIndexEntry(PathTree::NodeArgs const &args) : Node(args) {} + + String descriptionPath() const + { + return file->path().toString().fileNameAndPathWithoutExtension() + ".txt"; + } + }; + PathTreeT packageIndex; + + String localRootPath; + + Impl(Public *i) : Base(i) + { + localRootPath = "/remote/" + QUrl(self().address()).host(); + } + + String packageIdentifierForFileEntry(FileEntry const &entry) const + { + if (entry.name().fileNameExtension() == QStringLiteral(".zip")) + { + Path const path = entry.path(); + String id = QString("%1_%2") + .arg(DataBundle::cleanIdentifier(path.fileName().fileNameWithoutExtension())) + .arg(DataBundle::versionFromTimestamp(entry.modTime)); + + // Remove the hour:minute part. + id.truncate(id.size() - 5); + + if (path.segment(1) == CATEGORY_MUSIC || + path.segment(1) == CATEGORY_SOUNDS || + path.segment(1) == CATEGORY_THEMES) + { + return String("%1.%2.%3") + .arg(DOMAIN_IDGAMES) + .arg(path.segment(1)) + .arg(id); + } + if (path.segment(1) == CATEGORY_LEVELS) + { + String subset; + if (path.segment(3) == QStringLiteral("deathmatch")) subset = QStringLiteral("deathmatch."); + else if (path.segment(3) == QStringLiteral("megawads")) subset = QStringLiteral("megawads."); + return String("%1.%2.%3.%4%5") + .arg(DOMAIN_IDGAMES) + .arg(CATEGORY_LEVELS) + .arg(path.segment(2)) + .arg(subset) + .arg(id); + } + return String("%1.%2").arg(DOMAIN_IDGAMES).arg(id); + } + else + { + return String(); + } + } + + void buildPackageIndex() + { + packageIndex.clear(); + + PathTreeIterator iter(self().fileTree().leafNodes()); + while (iter.hasNext()) + { + auto const &fileEntry = iter.next(); + if (String pkg = packageIdentifierForFileEntry(fileEntry)) + { + auto const id_ver = Package::split(pkg); + auto &pkgEntry = packageIndex.insert(DotPath(id_ver.first)); + pkgEntry.file = &fileEntry; + pkgEntry.version = id_ver.second; + } + } + + qDebug() << "idgames package index has" << packageIndex.size() << "entries"; + } + + PackageIndexEntry const *findPackage(String const &packageId) const + { + auto const id_ver = Package::split(packageId); + if (auto *found = packageIndex.tryFind(DotPath(id_ver.first), + PathTree::MatchFull | PathTree::NoBranch)) + { + if (!id_ver.second.isValid() || found->version == id_ver.second) + { + return found; + } + } + return nullptr; + } + + RemoteFile &makeRemoteFile(Folder &folder, String const &remotePath, Block const &remoteMetaId) + { + auto *file = new RemoteFile(remotePath.fileName(), + remotePath, + remoteMetaId, + self().address()); + folder.add(file); + FS::get().index(*file); + return *file; + } +}; + +IdgamesLink::IdgamesLink(String const &address) + : filesys::WebHostedLink(address, "ls-laR.gz") + , d(new Impl(this)) +{} + +void IdgamesLink::parseRepositoryIndex(QByteArray data) +{ + // This may be a long list, so let's do it in a background thread. + // The link will be marked connected only after the data has been parsed. + + scope() += async([this, data] () -> String + { + Block const listing = gDecompress(data); + QTextStream is(listing, QIODevice::ReadOnly); + is.setCodec("UTF-8"); + QRegularExpression const reDir("^\\.?(.*):$"); + QRegularExpression const reTotal("^total\\s+\\d+$"); + QRegularExpression const reFile("^(-|d)[-rwxs]+\\s+\\d+\\s+\\w+\\s+\\w+\\s+" + "(\\d+)\\s+(\\w+\\s+\\d+\\s+[0-9:]+)\\s+(.*)$", + QRegularExpression::CaseInsensitiveOption); + String currentPath; + bool ignore = false; + QRegularExpression const reIncludedPaths("^/(levels|music|sounds|themes)"); + + std::unique_ptr tree(new FileTree); + while (!is.atEnd()) + { + if (String const line = is.readLine().trimmed()) + { + if (!currentPath) + { + // This should be a directory path. + auto match = reDir.match(line); + if (match.hasMatch()) + { + currentPath = match.captured(1); + //qDebug() << "[WebRepositoryLink] Parsing path:" << currentPath; + + ignore = !reIncludedPaths.match(currentPath).hasMatch(); + } + } + else if (!ignore && reTotal.match(line).hasMatch()) + { + // Ignore directory sizes. + } + else if (!ignore) + { + auto match = reFile.match(line); + if (match.hasMatch()) + { + bool const isFolder = (match.captured(1) == QStringLiteral("d")); + if (!isFolder) + { + String const name = match.captured(4); + if (name.startsWith(QChar('.')) || name.contains(" -> ")) + continue; + + auto &entry = tree->insert((currentPath / name).toLower()); + entry.size = match.captured(2).toULongLong(nullptr, 10);; + entry.modTime = Time::fromText(match.captured(3), Time::UnixLsStyleDateTime); + } + } + } + } + else + { + currentPath.clear(); + } + } + qDebug() << "idgames file tree contains" << tree->size() << "entries"; + setFileTree(tree.release()); + return String(); + }, + [this] (String const &errorMessage) + { + if (!errorMessage) + { + wasConnected(); + } + else + { + handleError("Failed to parse directory listing: " + errorMessage); + wasDisconnected(); + } +}); +} + +StringList IdgamesLink::categoryTags() const +{ + return StringList({ CATEGORY_LEVELS, + CATEGORY_MUSIC, + CATEGORY_SOUNDS, + CATEGORY_THEMES }); +} + +LoopResult IdgamesLink::forPackageIds(std::function func) const +{ + PathTreeIterator iter(d->packageIndex.leafNodes()); + while (iter.hasNext()) + { + if (auto result = func(iter.next().path('.'))) + { + return result; + } + } + return LoopContinue; +} + +String IdgamesLink::findPackagePath(String const &packageId) const +{ + if (auto *found = d->findPackage(packageId)) + { + return found->file->path(); + } + return String(); +} + +filesys::Link *IdgamesLink::construct(String const &address) +{ + if ((address.startsWith("http:") || address.startsWith("https:")) && + !address.contains("dengine.net")) + { + return new IdgamesLink(address); + } + return nullptr; +} + +File *IdgamesLink::populateRemotePath(String const &packageId, + filesys::RepositoryPath const &path) const +{ + DENG2_ASSERT(path.link == this); + + auto *pkgEntry = d->findPackage(packageId); + if (!pkgEntry) + { + DENG2_ASSERT(pkgEntry); + return nullptr; + } + + auto &pkgFolder = FS::get().makeFolder(path.localPath, FS::DontInheritFeeds); + + // The main data file of the package. + auto &dataFile = d->makeRemoteFile(pkgFolder, + pkgEntry->file->path(), + pkgEntry->file->metaId(*this)); + dataFile.setStatus(File::Status(pkgEntry->file->size, pkgEntry->file->modTime)); + + // Additional description. + auto &txtFile = d->makeRemoteFile(pkgFolder, + pkgEntry->descriptionPath(), + md5Hash(address(), pkgEntry->descriptionPath(), pkgEntry->file->modTime)); + if (auto const *txtEntry = findFile(pkgEntry->descriptionPath())) + { + txtFile.setStatus(File::Status(txtEntry->size, txtEntry->modTime)); + } + + auto *infoFile = new IdgamesPackageInfoFile("info.dei"); + infoFile->setSourceFiles(dataFile, txtFile); + pkgFolder.add(infoFile); + FS::get().index(*infoFile); + + return &pkgFolder; +} + +void IdgamesLink::setFileTree(FileTree *tree) +{ + WebHostedLink::setFileTree(tree); + d->buildPackageIndex(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/idgamespackageinfofile.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/idgamespackageinfofile.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/idgamespackageinfofile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/idgamespackageinfofile.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -0,0 +1,247 @@ +/** @file idgamespackageinfofile.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "doomsday/filesys/idgamespackageinfofile.h" +#include "doomsday/res/Bundles" +#include "doomsday/DoomsdayApp" + +#include +#include +#include +#include +#include + +#include + +using namespace de; + +DENG2_PIMPL(IdgamesPackageInfoFile) +, DENG2_OBSERVES(Asset, StateChange) +{ + Asset packageAsset; + AssetGroup assets; + SafePtr dataFile; + SafePtr descriptionFile; + Block serializedContent; + + Impl(Public *i) : Base(i) + { + assets.audienceForStateChange() += this; + } + + String cacheFolderPath() const + { + String const hex = dataFile->metaId().asHexadecimalText(); + return RemoteFile::CACHE_PATH / hex.right(1) / hex; + } + + void assetStateChanged(Asset &) + { + if (!assets.isEmpty() && assets.isReady()) + { + // Looks like we can process the file contents. + qDebug() << "[IdgamesPackageInfoFile] Time to unzip and analyze!"; + + DENG2_ASSERT(dataFile->isReady()); + DENG2_ASSERT(descriptionFile->isReady()); + + // We need to extract data files (WAD, DEH) so that they can be loaded. + /// @todo No need for this after FS2 used for loading everything. + + auto &fs = FileSystem::get(); + + Folder &packFolder = *self().parent(); + DotPath const packageId { packFolder.name() }; + + /*Folder &cacheFolder = */fs.makeFolder(cacheFolderPath()); + + FS::copySerialized(descriptionFile->path(), + cacheFolderPath()/descriptionFile->name()); + + StringList dataFiles; + Record meta; + + // A ZIP from idgames can contain any number of data files to load. Even + // though some ZIPs only have one WAD file, the following doesn't make a + // special case for those. (Single-file packages could just as well be + // recognized directly as an idgames package.) + + // If the data file is a ZIP archive, let's see what it contains. We want to + // have the data file(s) and the description text in the same folder so + // DataBundle will analyze it fully. + +// qDebug() << dataFile->parent()->path() << "\n" << dataFile->parent()->contentsAsText().toUtf8().constData(); +// qDebug() << dataFile->target().size() << dataFile->target().status().modifiedAt.asText(); + + //qDebug() << "remote file timestamp:" << DataBundle::versionFromTimestamp(dataFile->target().status().modifiedAt); + meta.set("title", dataFile->name().fileNameWithoutExtension().toUpper() + " (idgames)"); + meta.set("version", DataBundle::versionFromTimestamp(dataFile->target().status().modifiedAt)); + + if (Folder *zip = const_cast(maybeAs(dataFile->target()))) + { + zip->populate(); + zip->forContents([this, &dataFiles] (String name, File &file) + { + String const ext = name.fileNameExtension().toLower(); + if (ext == ".wad" || ext == ".deh" || ext == ".lmp" || ext == ".pk3") + { + File &copied = FS::copySerialized + (file.path(), cacheFolderPath()/file.name()); + dataFiles << copied.path(); + } + return LoopContinue; + }); + FS::waitForIdle(); + + StringList components; + foreach (String path, dataFiles) + { + if (DataBundle const *bundle = FS::tryLocate(path)) + { + //components << bundle->versionedPackageId(); + components << bundle->asFile().path(); + + Record const &compMeta = bundle->packageMetadata(); + if (compMeta.has("notes")) + { + meta.set("notes", compMeta.gets("notes")); + if (compMeta.has("title")) + { + meta.set("title", compMeta.gets("title")); + } +// if (compMeta.has("version")) +// { +// meta.set("version", compMeta.gets("version")); +// } + if (compMeta.has("license")) + { + meta.set("license", compMeta.gets("license")); + } + if (compMeta.has("author")) + { + meta.set("author", compMeta.gets("author")); + } + if (compMeta.has("tags")) + { + meta.appendMultipleUniqueWords("tags", compMeta.gets("tags")); + } + } + } + } + std::unique_ptr comps { new ArrayValue }; + foreach (String comp, components) + { + comps->add(new TextValue(comp)); + } + meta.addArray("dataFiles", comps.release()); + + meta.set("tags", meta.gets("tags", "") + .removed(QRegularExpression("\\b(hidden|cached)\\b")) + .normalizeWhitespace()); + + // Version should match the idgames index version (or overridden from + // metadata with an actual version). + qDebug() << "idgames package will contain:" << components; + qDebug() << meta.asText().toUtf8().constData(); + + if (packageId.segment(1) == "levels") + { + // Tag with the right game. + meta.set("tags", meta.gets("tags", "") + .removed(QRegularExpression(DataBundle::anyGameTagPattern())) + .normalizeWhitespace()); + meta.appendUniqueWord("tags", packageId.segment(2).toString()); + } + + // Apply metadata to the folder representing the package. + auto &pkgMeta = Package::initializeMetadata(packFolder, packageId); + pkgMeta.copyMembersFrom(meta); + + // Prepare the required package info in case this is installed locally. + { + Record info { pkgMeta, Record::IgnoreDoubleUnderscoreMembers }; + delete info.remove("ID"); + delete info.remove("path"); + String const cachePath = cacheFolderPath(); + ArrayValue *pkgData = new ArrayValue; + foreach (String path, info.getStringList("dataFiles")) + { + if (path.startsWith(cachePath)) + { + path.remove(0, cachePath.size() + 1); + } + pkgData->add(new TextValue(path)); + } + info.set("dataFiles", pkgData); + serializedContent = info.asInfo().toUtf8(); + } + } + + // Everythis is complete. + DENG2_FOR_PUBLIC_AUDIENCE(Download, i) + { + i->downloadProgress(self(), 0); + } + packageAsset.setState(Asset::Ready); + } + } +}; + +IdgamesPackageInfoFile::IdgamesPackageInfoFile(String const &name) + : File(name) + , d(new Impl(this)) +{} + +void IdgamesPackageInfoFile::setSourceFiles(RemoteFile const &dataFile, + RemoteFile const &descriptionFile) +{ + d->dataFile .reset(&dataFile); + d->descriptionFile.reset(&descriptionFile); + + d->assets += dataFile.asset(); + d->assets += descriptionFile.asset(); +} + +Asset &IdgamesPackageInfoFile::asset() +{ + return d->packageAsset; +} + +Asset const &IdgamesPackageInfoFile::asset() const +{ + return d->packageAsset; +} + +dsize IdgamesPackageInfoFile::downloadSize() const +{ + // No additional download for the info file is required. + return 0; +} + +void IdgamesPackageInfoFile::download() +{} + +void IdgamesPackageInfoFile::cancelDownload() +{} + +IIStream const &IdgamesPackageInfoFile::operator >> (IByteArray &bytes) const +{ + bytes.set(0, d->serializedContent.dataConst(), d->serializedContent.size()); + return *this; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/wad.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/wad.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/wad.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/wad.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -126,7 +126,7 @@ using namespace internal; -Wad::LumpFile::LumpFile(Entry &entry, FileHandle &hndl, String path, +Wad::LumpFile::LumpFile(Entry &entry, FileHandle *hndl, String path, FileInfo const &info, File1 *container) : File1(hndl, path, info, container) , entry(entry) @@ -182,7 +182,7 @@ }; Wad::Wad(FileHandle &hndl, String path, FileInfo const &info, File1 *container) - : File1(hndl, path, info, container) + : File1(&hndl, path, info, container) , LumpIndex() , d(new Impl) { @@ -212,8 +212,7 @@ entry.offset = lump.offset; entry.size = lump.size; - FileHandle *dummy = 0; /// @todo Fixme! - LumpFile *lumpFile = new LumpFile(entry, *dummy, entry.path(), + LumpFile *lumpFile = new LumpFile(entry, nullptr, entry.path(), FileInfo(lastModified(), // Inherited from the container (note recursion). i, entry.offset, entry.size, entry.size), this); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/zip.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/zip.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/filesys/zip.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/filesys/zip.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -269,7 +269,7 @@ using namespace internal; -Zip::LumpFile::LumpFile(Entry &entry, FileHandle &hndl, String path, +Zip::LumpFile::LumpFile(Entry &entry, FileHandle *hndl, String path, FileInfo const &info, File1 *container) : File1(hndl, path, info, container) , entry(entry) @@ -361,7 +361,7 @@ }; Zip::Zip(FileHandle &hndl, String path, FileInfo const &info, File1 *container) - : File1(hndl, path, info, container) + : File1(&hndl, path, info, container) , LumpIndex(true/*paths are unique*/) , d(new Impl(this)) { @@ -510,8 +510,7 @@ entry.size = DD_ULONG(header->size); entry.compressedSize = compressedSize; - FileHandle *dummy = 0; /// @todo Fixme! - LumpFile *lumpFile = new LumpFile(entry, *dummy, entry.path(), + LumpFile *lumpFile = new LumpFile(entry, nullptr, entry.path(), FileInfo(lastModified(), // Inherited from the file (note recursion). lumpIdx, entry.offset, entry.size, entry.compressedSize), this); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/game.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/game.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/game.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/game.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -58,8 +58,9 @@ String const Game::DEF_LEGACYSAVEGAME_NAME_EXP("legacySavegame.nameExp"); String const Game::DEF_LEGACYSAVEGAME_SUBFOLDER("legacySavegame.subfolder"); String const Game::DEF_MAPINFO_PATH("mapInfoPath"); +String const Game::DEF_OPTIONS("options"); -DENG2_PIMPL(Game) +DENG2_PIMPL(Game), public Lockable { pluginid_t pluginId = 0; ///< Unique identifier of the registering plugin. Record params; @@ -80,27 +81,32 @@ { params.set(DEF_CONFIG_BINDINGS_PATH, "/home/configs"/params.gets(DEF_CONFIG_DIR)/"player/bindings.cfg"); } + if (!params.has(DEF_OPTIONS)) + { + params.set(DEF_OPTIONS, RecordValue::takeRecord(Record())); + } params.set(DEF_CONFIG_DIR, NativePath(params.gets(DEF_CONFIG_DIR)).expand().withSeparators('/')); } ~Impl() { + DENG2_GUARD(this); qDeleteAll(manifests); } - GameProfile const *profile() const + GameProfile *profile() const { return maybeAs(DoomsdayApp::gameProfiles().tryFind(self().title())); } StringList packagesFromProfile() const { - if (auto const *prof = profile()) + if (const auto *prof = profile()) { return prof->packages(); } - return StringList(); + return {}; } }; @@ -116,21 +122,25 @@ bool Game::isNull() const { + DENG2_GUARD(d); return id().isEmpty(); } String Game::id() const { + DENG2_GUARD(d); return d->params.gets(DEF_ID); } String Game::variantOf() const { + DENG2_GUARD(d); return d->params.gets(DEF_VARIANT_OF); } String Game::family() const { + DENG2_GUARD(d); if (d->params.has(DEF_FAMILY)) { return d->params.gets(DEF_FAMILY); @@ -144,21 +154,25 @@ void Game::setRequiredPackages(StringList packageIds) { + DENG2_GUARD(d); d->requiredPackages = packageIds; } void Game::addRequiredPackage(String const &packageId) { + DENG2_GUARD(d); d->requiredPackages.append(packageId); } StringList Game::requiredPackages() const { + DENG2_GUARD(d); return d->requiredPackages; } StringList Game::localMultiplayerPackages() const { + DENG2_GUARD(d); return localMultiplayerPackages(id()); } @@ -202,6 +216,7 @@ void Game::addManifest(ResourceManifest &manifest) { + DENG2_GUARD(d); // Ensure we don't add duplicates. Manifests::const_iterator found = d->manifests.find(manifest.resourceClass(), &manifest); if (found == d->manifests.end()) @@ -212,6 +227,8 @@ bool Game::allStartupFilesFound() const { + DENG2_GUARD(d); + for (String const &pkg : d->requiredPackages + d->packagesFromProfile()) { if (!App::packageLoader().isAvailable(pkg)) @@ -235,6 +252,7 @@ bool Game::isPlayableWithDefaultPackages() const { + DENG2_GUARD(d); for (String const &pkg : d->requiredPackages) { if (!App::packageLoader().isAvailable(pkg)) @@ -245,6 +263,7 @@ Game::Status Game::status() const { + DENG2_GUARD(d); if (App_GameLoaded() && &DoomsdayApp::game() == this) { return Loaded; @@ -258,6 +277,7 @@ String const &Game::statusAsText() const { + DENG2_GUARD(d); static String const statusTexts[] = { "Loaded", "Playable", @@ -268,6 +288,7 @@ String Game::description() const { + DENG2_GUARD(d); return String(_E(b) "%1 - %2\n" _E(.) _E(l) "ID: " _E(.) "%3 " _E(l) "PluginId: " _E(.) "%4\n" @@ -287,16 +308,19 @@ pluginid_t Game::pluginId() const { + DENG2_GUARD(d); return d->pluginId; } void Game::setPluginId(pluginid_t newId) { + DENG2_GUARD(d); d->pluginId = newId; } String Game::logoImageId() const { + DENG2_GUARD(d); return logoImageForId(id()); } @@ -322,11 +346,13 @@ String Game::legacySavegameNameExp() const { - return d->params[DEF_LEGACYSAVEGAME_NAME_EXP]; + DENG2_GUARD(d); + return d->params.gets(DEF_LEGACYSAVEGAME_NAME_EXP, ""); } String Game::legacySavegamePath() const { + DENG2_GUARD(d); NativePath nativeSavePath = Resources::get().nativeSavePath(); if (nativeSavePath.isEmpty()) return ""; if (isNull()) return ""; @@ -338,7 +364,7 @@ } // The default save path. The savegames are in a game-specific folder. - if (!d->params.gets(DEF_LEGACYSAVEGAME_SUBFOLDER, "").isEmpty()) + if (d->params.gets(DEF_LEGACYSAVEGAME_SUBFOLDER, "")) { return App::app().nativeHomePath() / d->params.gets(DEF_LEGACYSAVEGAME_SUBFOLDER) / id(); } @@ -348,41 +374,50 @@ Path Game::mainConfig() const { + DENG2_GUARD(d); return d->params.gets(DEF_CONFIG_MAIN_PATH); } Path Game::bindingConfig() const { + DENG2_GUARD(d); return d->params.gets(DEF_CONFIG_BINDINGS_PATH); } Path Game::mainMapInfo() const { + DENG2_GUARD(d); return d->params.gets(DEF_MAPINFO_PATH); } String Game::title() const { + DENG2_GUARD(d); return d->params.gets(DEF_TITLE); } String Game::author() const { + DENG2_GUARD(d); return d->params.gets(DEF_AUTHOR); } Date Game::releaseDate() const { + DENG2_GUARD(d); return Date::fromText(d->params.gets(DEF_RELEASE_DATE, "")); } Game::Manifests const &Game::manifests() const { + DENG2_GUARD(d); return d->manifests; } bool Game::isRequiredFile(File1 &file) const { + DENG2_GUARD(d); + // If this resource is from a container we must use the path of the // root file container instead. File1 &rootFile = file; @@ -411,6 +446,8 @@ void Game::addResource(resourceclassid_t classId, dint rflags, char const *names, void const *params) { + DENG2_GUARD(d); + if (!VALID_RESOURCECLASSID(classId)) { throw Error("Game::addResource", @@ -444,8 +481,9 @@ } } -GameProfile const &Game::profile() const +GameProfile &Game::profile() const { + DENG2_GUARD(d); DENG2_ASSERT(d->profile()); // all games have a matching built-in profile return *d->profile(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/game_init.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/game_init.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/game_init.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/game_init.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -104,11 +104,14 @@ Record const &meta = bundle.packageMetadata(); for (auto const *v : meta.geta("dataFiles").elements()) { - if (File const *dataFile = App::rootFolder().tryLocate(v->asText())) +// LOG_RES_MSG("bundle root: %s -> trying to load %s") << bundle.rootPath() +// << v->asText(); + String const dataFilePath = bundle.rootPath() / v->asText(); + if (File const *dataFile = FS::tryLocate(dataFilePath)) { if (is(dataFile->source())) { - func(v->asText()); + func(dataFilePath); } else { @@ -241,23 +244,22 @@ char *token = strtok(buffer, ATWSEPS); while (token) { - tryLoadFile(de::Uri(token, RC_NULL)); + tryLoadFile(de::makeUri(token)); token = strtok(nullptr, ATWSEPS); } M_Free(buffer); } -static dint addListFiles(QStringList list, FileType const &ftype) +static dint addListFiles(const StringList &list, FileType const &ftype) { dint numAdded = 0; - foreach (QString const &path, list) + for (const auto &path : list) { if (&ftype != &DD_GuessFileTypeFromFileName(path)) { continue; } - - if (tryLoadFile(de::Uri(path, RC_NULL))) + if (tryLoadFile(de::makeUri(path))) { numAdded += 1; } @@ -284,10 +286,10 @@ // Create default Auto mappings in the runtime directory. // Data class resources. - App_FileSystem().addPathMapping("auto/", de::Uri("$(App.DataPath)/$(GamePlugin.Name)/auto/", RC_NULL).resolved()); + App_FileSystem().addPathMapping("auto/", de::makeUri("$(App.DataPath)/$(GamePlugin.Name)/auto/").resolved()); // Definition class resources. - App_FileSystem().addPathMapping("auto/", de::Uri("$(App.DefsPath)/$(GamePlugin.Name)/auto/", RC_NULL).resolved()); + App_FileSystem().addPathMapping("auto/", de::makeUri("$(App.DefsPath)/$(GamePlugin.Name)/auto/").resolved()); } // Load data files. @@ -371,7 +373,7 @@ // Ignore directories. if (i->attrib & A_SUBDIR) continue; - if (tryLoadFile(de::Uri(i->path, RC_NULL))) + if (tryLoadFile(de::makeUri(i->path))) { numLoaded += 1; } @@ -420,7 +422,8 @@ /** * Phase 3: Add real files from the Auto directory. */ - auto &prof = AbstractSession::profile(); + //auto &prof = AbstractSession::profile(); + StringList resourceFiles; FS1::PathList found; findAllGameDataPaths(found); @@ -430,14 +433,14 @@ if (i->attrib & A_SUBDIR) continue; /// @todo Is expansion of symbolics still necessary here? - prof.resourceFiles << NativePath(i->path).expand().withSeparators('/'); + resourceFiles << NativePath(i->path).expand().withSeparators('/'); } - if (!prof.resourceFiles.isEmpty()) + if (!resourceFiles.isEmpty()) { // First ZIPs then WADs (they may contain WAD files). - addListFiles(prof.resourceFiles, DD_FileTypeByName("FT_ZIP")); - addListFiles(prof.resourceFiles, DD_FileTypeByName("FT_WAD")); + addListFiles(resourceFiles, DD_FileTypeByName("FT_ZIP")); + addListFiles(resourceFiles, DD_FileTypeByName("FT_WAD")); } // Final autoload round. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/gameprofiles.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/gameprofiles.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/gameprofiles.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/gameprofiles.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -22,6 +22,8 @@ #include "doomsday/GameStateFolder" #include +#include +#include #include #include @@ -29,10 +31,18 @@ using namespace de; -static String const VAR_GAME ("game"); -static String const VAR_PACKAGES ("packages"); -static String const VAR_USER_CREATED("userCreated"); +static String const VAR_GAME ("game"); +static String const VAR_PACKAGES ("packages"); +static String const VAR_CUSTOM_DATA_FILE("customDataFile"); +static String const VAR_USER_CREATED ("userCreated"); static String const VAR_USE_GAME_REQUIREMENTS("useGameRequirements"); +static String const VAR_AUTO_START_MAP ("autoStartMap"); +static String const VAR_AUTO_START_SKILL("autoStartSkill"); +static String const VAR_LAST_PLAYED ("lastPlayed"); +static String const VAR_SAVE_LOCATION_ID("saveLocationId"); +static String const VAR_VALUES ("values"); + +static int const DEFAULT_SKILL = 3; // Normal skill level (1-5) static GameProfile nullGameProfile; @@ -159,36 +169,75 @@ if (Info::ListElement const *pkgs = block.findAs(VAR_PACKAGES)) { StringList ids; - for (auto const &val : pkgs->values()) ids << val.text; + for (auto const &val : pkgs->values()) + { + ids << val.text; + } prof->setPackages(ids); } prof->setUserCreated(!block.keyValue(VAR_USER_CREATED).text.compareWithoutCase("True")); + if (block.contains(VAR_CUSTOM_DATA_FILE)) + { + prof->setCustomDataFile(block.keyValue(VAR_CUSTOM_DATA_FILE).text); + } if (block.contains(VAR_USE_GAME_REQUIREMENTS)) { prof->setUseGameRequirements(!block.keyValue(VAR_USE_GAME_REQUIREMENTS) .text.compareWithoutCase("True")); } + if (block.contains(VAR_AUTO_START_MAP)) + { + prof->setAutoStartMap(block.keyValue(VAR_AUTO_START_MAP).text); + } + if (block.contains(VAR_AUTO_START_SKILL)) + { + prof->setAutoStartSkill(block.keyValue(VAR_AUTO_START_SKILL).text.toInt()); + } + if (block.contains(VAR_SAVE_LOCATION_ID)) + { + prof->setSaveLocationId(block.keyValue(VAR_SAVE_LOCATION_ID).text.toUInt32(nullptr, 16)); + } + if (block.contains(VAR_LAST_PLAYED)) + { + prof->setLastPlayedAt(Time::fromText(block.keyValue(VAR_LAST_PLAYED).text)); + } + if (const auto *values = block.findAs(VAR_VALUES)) + { + prof->objectNamespace() = values->asRecord(); + } return prof.release(); } -//--------------------------------------------------------------------------------------- +//------------------------------------------------------------------------------------------------- DENG2_PIMPL_NOREF(GameProfiles::Profile) { - String gameId; + String gameId; + String customDataFile; StringList packages; - bool userCreated = false; - bool useGameRequirements = true; + bool userCreated = false; + bool useGameRequirements = true; + String autoStartMap; + int autoStartSkill = DEFAULT_SKILL; + Time lastPlayedAt = Time::invalidTime(); + duint32 saveLocationId = 0; + Record values; Impl() {} Impl(Impl const &other) : gameId (other.gameId) + , customDataFile (other.customDataFile) , packages (other.packages) , userCreated (other.userCreated) , useGameRequirements(other.useGameRequirements) + , autoStartMap (other.autoStartMap) + , autoStartSkill (other.autoStartSkill) + , lastPlayedAt (other.lastPlayedAt) + , saveLocationId (other.saveLocationId) + , values (other.values) {} }; @@ -203,13 +252,19 @@ , d(new Impl(*other.d)) {} -GameProfiles::Profile &GameProfiles::Profile::operator = (Profile const &other) +GameProfiles::Profile &GameProfiles::Profile::operator=(const Profile &other) { - AbstractProfile::operator = (other); - d->gameId = other.d->gameId; - d->packages = other.d->packages; - d->userCreated = other.d->userCreated; - d->useGameRequirements = other.d->useGameRequirements; + AbstractProfile::operator=(other); + d->gameId = other.d->gameId; + d->customDataFile = other.d->customDataFile; + d->packages = other.d->packages; + d->userCreated = other.d->userCreated; + d->useGameRequirements = other.d->useGameRequirements; + d->autoStartMap = other.d->autoStartMap; + d->autoStartSkill = other.d->autoStartSkill; + d->lastPlayedAt = other.d->lastPlayedAt; + d->saveLocationId = other.d->saveLocationId; + d->values = other.d->values; return *this; } @@ -222,6 +277,15 @@ } } +void GameProfiles::Profile::setCustomDataFile(const String &id) +{ + if (d->customDataFile != id) + { + d->customDataFile = id; + notifyChange(); + } +} + void GameProfiles::Profile::setPackages(StringList packagesInOrder) { if (d->packages != packagesInOrder) @@ -249,6 +313,54 @@ } } +void GameProfiles::Profile::setAutoStartMap(String const &map) +{ + if (d->autoStartMap != map) + { + d->autoStartMap = map; + notifyChange(); + } +} + +void GameProfiles::Profile::setAutoStartSkill(int level) +{ + if (level < 1 || level > 5) level = DEFAULT_SKILL; + + if (d->autoStartSkill != level) + { + d->autoStartSkill = level; + notifyChange(); + } +} + +void GameProfiles::Profile::setLastPlayedAt(const Time &at) +{ + if (d->lastPlayedAt != at) + { + d->lastPlayedAt = at; + notifyChange(); + } +} + +void GameProfiles::Profile::setSaveLocationId(const duint32 saveLocationId) +{ + if (d->saveLocationId != saveLocationId) + { + d->saveLocationId = saveLocationId; + notifyChange(); + } +} + +void GameProfiles::Profile::setOptionValue(const String &option, const Value &value) +{ + const String key = "option." + option; + if (!d->values.has(key) || d->values[key].value().compare(value)) + { + d->values.set(key, value.duplicate()); + notifyChange(); + } +} + bool GameProfiles::Profile::appendPackage(String const &id) { if (!d->packages.contains(id)) @@ -270,6 +382,11 @@ return Games::nullGame(); } +String GameProfiles::Profile::customDataFile() const +{ + return d->customDataFile; +} + String GameProfiles::Profile::gameId() const { return d->gameId; @@ -290,12 +407,118 @@ return d->useGameRequirements; } +String GameProfiles::Profile::autoStartMap() const +{ + return d->autoStartMap; +} + +int GameProfiles::Profile::autoStartSkill() const +{ + return d->autoStartSkill; +} + +Time GameProfiles::Profile::lastPlayedAt() const +{ + return d->lastPlayedAt; +} + +duint32 GameProfiles::Profile::saveLocationId() const +{ + return d->saveLocationId; +} + +static const String PATH_SAVEGAMES = "/home/savegames"; + +String GameProfiles::Profile::savePath() const +{ + /// If the profile has a custom save location, use that instead. + if (d->saveLocationId) + { + return PATH_SAVEGAMES / String::format("profile-%08x", d->saveLocationId); + } + return PATH_SAVEGAMES / gameId(); +} + +const Value &GameProfiles::Profile::optionValue(const String &option) const +{ + if (const auto *var = d->values.tryFind("option." + option)) + { + return var->value(); + } + return game()[Game::DEF_OPTIONS.concatenateMember(option + ".default")].value(); +} + +bool GameProfiles::Profile::isSaveLocationEmpty() const +{ + FS::waitForIdle(); + if (const auto *loc = FS::tryLocate(savePath())) + { + return loc->contents().size() == 0; + } + return true; +} + +void GameProfiles::Profile::createSaveLocation() +{ + FS::waitForIdle(); + do + { + d->saveLocationId = randui32(); + } while (FS::exists(savePath())); + Folder &loc = FS::get().makeFolder(savePath()); + LOG_MSG("Created save location %s") << loc.description(); +} + +void GameProfiles::Profile::destroySaveLocation() +{ + if (d->saveLocationId) + { + FS::waitForIdle(); + if (auto *loc = FS::tryLocate(savePath())) + { + LOG_NOTE("Destroying save location %s") << loc->description(); + loc->destroyAllFiles(); + loc->correspondingNativePath().destroy(); + loc->parent()->populate(); + } + d->saveLocationId = 0; + } +} + +void GameProfiles::Profile::checkSaveLocation() const +{ + if (d->saveLocationId && !FS::exists(savePath())) + { + Folder &loc = FS::get().makeFolder(savePath()); + LOG_MSG("Created missing save location %s") << loc.description(); + } +} + StringList GameProfiles::Profile::allRequiredPackages() const { StringList list; + if (d->customDataFile) + { + list += d->customDataFile; + } if (d->useGameRequirements) { - list = DoomsdayApp::games()[d->gameId].requiredPackages(); + StringList reqs = DoomsdayApp::games()[d->gameId].requiredPackages(); + if (d->customDataFile) + { + // Remove any normally required gamedata-tagged packages. + reqs = filter(reqs, [](const String &id) { + if (const auto *f = PackageLoader::get().select(id)) + { + if (Package::matchTags(*f, QStringLiteral("\\bgamedata\\b"))) + { + return false; + } + } + return true; + }); + } + list += reqs; } return list + d->packages; } @@ -367,13 +590,43 @@ QTextStream os(&info); os.setCodec("UTF-8"); - os << VAR_GAME << ": " << d->gameId << "\n" - << VAR_PACKAGES << " <" << String::join(de::map(d->packages, Info::quoteString), ", ") << ">\n" - << VAR_USER_CREATED << ": " << (d->userCreated? "True" : "False") << "\n" + os << VAR_GAME << ": " << d->gameId << "\n" + << VAR_PACKAGES << " <" << String::join(de::map(d->packages, Info::quoteString), ", ") << ">\n" + << VAR_USER_CREATED << ": " << (d->userCreated? "True" : "False") << "\n" + << VAR_CUSTOM_DATA_FILE << ": " << d->customDataFile << "\n" << VAR_USE_GAME_REQUIREMENTS << ": " << (d->useGameRequirements? "True" : "False"); - + if (d->autoStartMap) + { + os << "\n" << VAR_AUTO_START_MAP << ": " << d->autoStartMap; + } + os << "\n" << VAR_AUTO_START_SKILL << ": " << d->autoStartSkill; + if (d->lastPlayedAt.isValid()) + { + os << "\n" << VAR_LAST_PLAYED << ": " << d->lastPlayedAt.asText(); + } + if (d->saveLocationId) + { + os << "\n" << VAR_SAVE_LOCATION_ID << ": " << String::format("%08x", d->saveLocationId); + } + // Additional configuration values (e.g., config for the game to use). + if (!d->values.isEmpty()) + { + String indented = d->values.asInfo(); + indented.replace("\n", "\n "); + os << "\n" << VAR_VALUES << " {\n " << indented << "\n}"; + } return info; } +Record &GameProfiles::Profile::objectNamespace() + +{ + return d->values; +} + +const Record &GameProfiles::Profile::objectNamespace() const +{ + return d->values; +} bool GameProfiles::arePackageListsCompatible(StringList const &list1, StringList const &list2) // static { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/games.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/games.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/games.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/games.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -62,7 +62,7 @@ { ArrayValue args; args << DictionaryValue() << TextValue(game.id()); - App::scriptSystem().nativeModule("App")["audienceForGameAddition"] + App::scriptSystem()["App"]["audienceForGameAddition"] .array().callElements(args); } }; @@ -78,7 +78,7 @@ nullGame = new NullGame; // Extend the native App module with a script audience for observing game addition. - App::scriptSystem().nativeModule("App").addArray("audienceForGameAddition"); + App::scriptSystem()["App"].addArray("audienceForGameAddition"); audienceForAddition += scriptAudienceForGameAddition; } @@ -115,6 +115,12 @@ Game *findById(String id) const { + if (id.beginsWith("doom-")) + { + // Originally, Freedoom and BFG variants used an inconsistently named ID. + id = "doom1-" + id.substr(5); + } + auto found = idLookup.constFind(id.toLower()); if (found != idLookup.constEnd()) { @@ -166,6 +172,19 @@ return count; } +int Games::numPlayable(String const &family) const +{ + int count = 0; + foreach (Game *game, d->games) + { + if (game->isPlayableWithDefaultPackages() && game->family() == family) + { + count++; + } + } + return count; +} + GameProfile const *Games::firstPlayable() const { foreach (Game *game, d->games) @@ -175,7 +194,7 @@ return nullptr; } -Game &Games::operator [] (String const &id) const +Game &Games::operator[](String const &id) const { if (id.isEmpty()) return *d->nullGame; @@ -324,8 +343,7 @@ */ QSet playable; - forAll([this, &playable] (Game &game) - { + forAll([&playable](Game &game) { if (game.isPlayable()) playable.insert(&game); return LoopContinue; }); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/gamestatefolder.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/gamestatefolder.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/gamestatefolder.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/gamestatefolder.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -306,7 +306,7 @@ } // Ensure the map URI has the "Maps" scheme set. - if (!gets("mapUri").beginsWith("Maps:", Qt::CaseInsensitive)) + if (!gets("mapUri").beginsWith("Maps:", String::CaseInsensitive)) { set("mapUri", String("Maps:") + gets("mapUri")); } @@ -318,7 +318,7 @@ if (!has("episode")) { String const mapUriPath = gets("mapUri").substr(5); - if (mapUriPath.beginsWith("MAP", Qt::CaseInsensitive)) + if (mapUriPath.beginsWith("MAP", String::CaseInsensitive)) { set("episode", "1"); } @@ -411,7 +411,7 @@ * See the Doomsday Wiki for an example of the syntax: * http://dengine.net/dew/index.php?title=Info */ -String GameStateFolder::Metadata::asTextWithInfoSyntax() const +String GameStateFolder::Metadata::asInfo() const { /// @todo Use a more generic Record => Info conversion logic. @@ -422,7 +422,7 @@ if (has("gameIdentityKey")) os << "gameIdentityKey: " << gets("gameIdentityKey"); if (has("packages")) { - os << "\npackages " << geta("packages").asTextUsingInfoSyntax(); + os << "\npackages " << geta("packages").asInfo(); } if (has("episode")) os << "\nepisode: " << gets("episode"); if (has("mapTime")) os << "\nmapTime: " << String::number(geti("mapTime")); @@ -441,7 +441,7 @@ } if (has("visitedMaps")) { - os << "\nvisitedMaps " << geta("visitedMaps").asTextUsingInfoSyntax(); + os << "\nvisitedMaps " << geta("visitedMaps").asInfo(); } if (has("sessionId")) os << "\nsessionId: " << String::number(geti("sessionId")); if (has("userDescription")) os << "\nuserDescription: " << gets("userDescription"); @@ -455,7 +455,7 @@ { Value const &value = i.value()->value(); String valueAsText = value.asText(); - if (value.is()) + if (is(value)) { valueAsText = "\"" + valueAsText.replace("\"", "''") + "\""; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/plugins.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/plugins.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/plugins.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/plugins.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -74,8 +74,8 @@ DENG2_PIMPL_NOREF(Plugins) { - GETGAMEAPI getGameAPI = nullptr; - game_export_t gameExports; + void *(*getGameAPI)(char const *) = nullptr; + GameExports gameExports; typedef ::Library *PluginHandle; @@ -106,9 +106,11 @@ { typedef void (*PluginInitializer)(void); +#if !defined (DENG_STATIC_LINK) // We are only interested in native files. if (!is(lib.source())) return 0; // Continue iteration. +#endif DENG2_ASSERT(!lib.path().isEmpty()); if (strcasestr("/bin/audio_", lib.path().toUtf8().constData())) @@ -122,7 +124,7 @@ { #ifdef UNIX String const fn = Path(lib.path()).fileName(); - if (fn.contains("libfmodex") || fn.contains("libassimp")) + if (fn.contains("libfmod") || fn.contains("libassimp")) { // No need to warn about these shared libs. return 0; @@ -286,13 +288,59 @@ if (pluginId != 0) { // Do the API transfer. - if (!(d->getGameAPI = (GETGAMEAPI) findEntryPoint(pluginId, "GetGameAPI"))) + if (!functionAssign(d->getGameAPI, findEntryPoint(pluginId, "GetGameAPI"))) { return false; } - game_export_t *gameExPtr = d->getGameAPI(); - std::memcpy(&d->gameExports, gameExPtr, de::min(sizeof(d->gameExports), gameExPtr->apiSize)); + zap(d->gameExports); + + // Query all the known entrypoints. + #define GET_FUNC_OPTIONAL(Name) { functionAssign(d->gameExports.Name, d->getGameAPI(#Name)); } + #define GET_FUNC(Name) { GET_FUNC_OPTIONAL(Name); DENG2_ASSERT(d->gameExports.Name); } + + GET_FUNC(PreInit); + GET_FUNC(PostInit); + GET_FUNC(TryShutdown); + GET_FUNC(Shutdown); + GET_FUNC(UpdateState); + GET_FUNC(GetInteger); + GET_FUNC(GetPointer); + + GET_FUNC(NetServerStart); + GET_FUNC(NetServerStop); + GET_FUNC(NetConnect); + GET_FUNC(NetDisconnect); + GET_FUNC(NetPlayerEvent); + GET_FUNC(NetWorldEvent); + GET_FUNC(HandlePacket); + + GET_FUNC(Ticker); + + GET_FUNC(FinaleResponder); + GET_FUNC(PrivilegedResponder); + GET_FUNC(Responder); + GET_FUNC_OPTIONAL(FallbackResponder); + + GET_FUNC_OPTIONAL(BeginFrame); + GET_FUNC(EndFrame); + GET_FUNC(DrawViewPort); + GET_FUNC(DrawWindow); + + GET_FUNC(MobjThinker); + GET_FUNC(MobjFriction); + GET_FUNC(MobjCheckPositionXYZ); + GET_FUNC(MobjTryMoveXYZ); + GET_FUNC(MobjStateAsInfo); + GET_FUNC(MobjRestoreState); + + GET_FUNC(SectorHeightChangeNotification); + + GET_FUNC(FinalizeMapChange); + GET_FUNC(HandleMapDataPropertyValue); + GET_FUNC(HandleMapObjectStatusReport); + + #undef GET_FUNC } else { @@ -303,7 +351,7 @@ return true; } -game_export_t &Plugins::gameExports() const +GameExports &Plugins::gameExports() const { return d->gameExports; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/bundles.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/bundles.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/bundles.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/bundles.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -110,7 +110,7 @@ DENG2_ASSERT(App::rootFolder().has("/sys/bundles")); bool wasIdentified = false; - int count = 0; + int count = 0; Time startedAt; while (auto const *bundle = nextToIdentify()) @@ -130,7 +130,7 @@ void parseRegistry() { - using Info = de::Info; + DENG2_GUARD(this); if (!identityRegistry.isEmpty()) return; @@ -141,7 +141,13 @@ for (auto *elem : identityRegistry.root().contentsInOrder()) { - if (!elem->isBlock()) continue; + using Info = de::Info; + + if (!elem->isBlock()) + { + // Looking for "package" blocks. + continue; + } Info::BlockElement &block = elem->as(); if (block.blockType() != QStringLiteral("package")) @@ -202,10 +208,10 @@ void Bundles::identify() { + FS::get().changeBusyLevel(+1); d->tasks.start([this] () { d->identifyAddedDataBundles(); - if (isEverythingIdentified()) { DENG2_FOR_AUDIENCE2(Identify, i) @@ -213,6 +219,7 @@ i->dataBundlesIdentified(); } } + FS::get().changeBusyLevel(-1); }); } @@ -222,11 +229,11 @@ return d->bundlesToIdentify.isEmpty(); } -void Bundles::waitForEverythingIdentified() +/*void Bundles::waitForEverythingIdentified() { identify(); d->tasks.waitForDone(); -} +}*/ Bundles::MatchResult Bundles::match(DataBundle const &bundle) const { @@ -268,8 +275,8 @@ // Match the file type. String fileType = def->keyValue(QStringLiteral("fileType")); if (fileType.isEmpty()) fileType = "file"; // prefer files by default - if ((!fileType.compareWithoutCase(QStringLiteral("file")) && source.status().type() == File::Status::FILE) || - (!fileType.compareWithoutCase(QStringLiteral("folder")) && source.status().type() == File::Status::FOLDER)) + if ((!fileType.compareWithoutCase(QStringLiteral("file")) && source.status().type() == File::Type::File) || + (!fileType.compareWithoutCase(QStringLiteral("folder")) && source.status().type() == File::Type::Folder)) { ++score; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/databundle.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/databundle.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/databundle.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/databundle.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -48,6 +48,7 @@ static String const VAR_AUTHOR ("author"); static String const VAR_TITLE ("title"); static String const VAR_TAGS ("tags"); +static String const VAR_NOTES ("notes"); static String const VAR_DATA_FILES ("dataFiles"); static String const VAR_BUNDLE_SCORE("bundleScore"); static String const VAR_REQUIRES ("requires"); @@ -97,50 +98,6 @@ return App::rootFolder().locate(QStringLiteral("/sys/bundles")); } - static String cleanIdentifier(String const &text) - { - // Periods and underscores have special meaning in packages IDs. - // Whitespace is used as separator in package ID lists (see PackageLoader). - // Info syntax has ambiguous quote/double-quote escaping in strings, so - // we'll also get rid of single quotes. (For example, Info converts a string - // containing ['"] to ['''].) - String cleaned = text.toLower(); - cleaned.replace(QRegExp("[._'\\s]"), "-"); - return cleaned; - } - - static String stripVersion(String const &text, Version *version = nullptr) - { - QRegExp re(".*([-_. ][0-9._-]+)$"); - if (re.exactMatch(text)) - { - if (version) - { - String str = re.cap(1).mid(1); - str.replace("_", "."); - version->parseVersionString(str); - } - return text.mid(0, text.size() - re.cap(1).size()); - } - return text; - } - - static String stripRedundantParts(String const &id) - { - DotPath const path(id); - String stripped = path.segment(0); - for (int i = 1; i < path.segmentCount(); ++i) - { - String seg = path.segment(i); - if (seg.startsWith(path.segment(i - 1) + "-")) - { - seg = seg.mid(path.segment(i - 1).size() + 1); - } - stripped = stripped.concatenateMember(seg); - } - return stripped; - } - /** * Identifies the data bundle and sets up a package link under "/sys/bundles" with * the appropriate metadata. @@ -286,14 +243,13 @@ container->packageMetadata().insertToSortedArray(subset, new TextValue(versionedPackageId)); /* - qDebug() << container->d->versionedPackageId - << "[" << container->d->pkgLink->objectNamespace().gets("package.tags", "") << "]" - << "requires" + LOGDEV_RES_VERBOSE("%s ") << container->d->versionedPackageId + << "(" << container->d->pkgLink->objectNamespace().gets("package.tags", "") << ") " + << subset << " " << versionedPackageId - << "[" << metadata.gets("tags", "") << "]" - << "from" << dataFilePath; - */ - + << " (" << metadata.gets("tags", "") << ") from " + << self().asFile().path(); + */ //Package::addRequiredPackage(containerFile, versionedPackageId); } return true; @@ -353,8 +309,8 @@ Record buildMetadata() { - String const dataFilePath = self().asFile().path(); - auto const *container = self().containerBundle(); + const String dataFilePath = self().asFile().path(); + const auto * container = self().containerBundle(); // Search for known data files in the bundle registry. res::Bundles::MatchResult matched = DoomsdayApp::bundles().match(self()); @@ -368,7 +324,8 @@ { // Classic data files are loaded via the "dataFiles" array (in the listed order). // However, collections are represented directly as Doomsday packages. - meta.addArray(VAR_DATA_FILES, new ArrayValue({ new TextValue(dataFilePath) })); + // Paths in "dataFiles" are relative to the package root. + meta.addArray(VAR_DATA_FILES, new ArrayValue({ new TextValue(dataFilePath.fileName()) })); } else { @@ -420,10 +377,19 @@ }; // Containers become part of the identifier. - for (DataBundle const *i = container; i; i = i->containerBundle()) + for (const DataBundle *c = container; c; c = c->containerBundle()) { - packageId = cleanIdentifier(stripVersion(i->sourceFile().name().fileNameWithoutExtension())) - .concatenateMember(packageId); + String containedId = cleanIdentifier( + stripVersion(c->sourceFile().name().fileNameWithoutExtension())); + + // Additionally include the parent subfolder within the container into the ID. + if (c == container && dataFilePath.fileNamePath() != c->asFile().path()) + { + containedId = containedId.concatenateMember(cleanIdentifier( + stripVersion(dataFilePath.fileNamePath().fileNameWithoutExtension()))); + } + + packageId = containedId.concatenateMember(packageId); } // The file name may contain a version number. @@ -448,16 +414,7 @@ auto &root = App::rootFolder(); // WAD files sometimes come with a matching TXT file. - if (format == Pwad || format == Iwad) - { - if (File const *wadTxt = root.tryLocate( - dataFilePath.fileNamePath() / dataFilePath.fileNameWithoutExtension() + ".txt")) - { - Block txt; - *wadTxt >> txt; - meta.set("notes", _E(m) + String::fromCP437(txt)); - } - } + checkAuxiliaryNotes(meta); // There may be Snowberry metadata available: // - Info entry inside root folder @@ -499,6 +456,47 @@ meta.appendUniqueWord(VAR_TAGS, "hidden"); } + // Check for built-in tags. + { + // Cached copies of remote files. + if (dataFilePath.startsWith("/home/cache/remote/")) + { + meta.appendUniqueWord(VAR_TAGS, "hidden"); + meta.appendUniqueWord(VAR_TAGS, "cached"); + } + + // Master Levels of Doom. + { + static const struct { + uint32_t crc32; + const char *filename; + } masterLevels[] = {{0xaa78f088, "attack.wad"}, {0x56bf62c2, "blacktwr.wad"}, + {0xa54aee5b, "bloodsea.wad"}, {0x5a8fb0f5, "canyon.wad"}, + {0x20954e50, "catwalk.wad"}, {0xb237de09, "combine.wad"}, + {0x9f051374, "fistula.wad"}, {0x86491354, "garrison.wad"}, + {0x60cc2385, "geryon.wad"}, {0x9755324e, "manor.wad"}, + {0xcfe7d641, "mephisto.wad"}, {0xc400cf65, "minos.wad"}, + {0x89386748, "nessus.wad"}, {0xac8808e9, "paradox.wad"}, + {0x8a84cc17, "subspace.wad"}, {0x9ffd4024, "subterra.wad"}, + {0x96919f5e, "teeth.wad"}, {0xd8d46a55, "ttrap.wad"}, + {0x1726dbb7, "vesperas.wad"}, {0xd421fe9d, "virgil.wad"}}; + if (format == Pwad) + { + for (const auto &spec : masterLevels) + { + if (lumpDir->crc32() == spec.crc32 && + self().asFile().name().compareWithoutCase(spec.filename) == 0) + { + removeGameTags(meta); + meta.appendUniqueWord(VAR_TAGS, "doom2"); + meta.appendUniqueWord(VAR_TAGS, "masterlevels"); + break; + } + } + } + } + } + determineGameTags(meta); LOG_RES_VERBOSE("Identified \"%s\" %s %s score: %i") @@ -507,10 +505,24 @@ << ::internal::formatDescriptions[format] << meta.geti(VAR_BUNDLE_SCORE); // matched.bestScore; - return meta; } + void checkAuxiliaryNotes(Record &meta) + { + if (format == Pwad || format == Iwad) + { + String const dataFilePath = self().asFile().path(); + if (File const *wadTxt = FS::tryLocate( + dataFilePath.fileNameAndPathWithoutExtension() + ".txt")) + { + Block txt; + *wadTxt >> txt; + meta.set(VAR_NOTES, _E(m) + String::fromCP437(txt)); + } + } + } + /** * Determines if the data bundle is intended to be automatically loaded by Doomsday * according to the v1.x autoload rules. @@ -638,7 +650,7 @@ if (!notes.isEmpty()) { notes.replace(QRegExp("\\s+"), " "); // normalize whitespace - meta.set("notes", notes); + meta.set(VAR_NOTES, notes); } } } @@ -646,8 +658,8 @@ if (parseErrorMsg) { meta.appendUniqueWord(VAR_TAGS, "error"); - meta.set("notes", QObject::tr("There is an error in the metadata of this package: %1") - .arg(parseErrorMsg) + "\n\n" + meta.gets("notes", "")); + meta.set(VAR_NOTES, QObject::tr("There is an error in the metadata of this package: %1") + .arg(parseErrorMsg) + "\n\n" + meta.gets(VAR_NOTES, "")); } } @@ -657,30 +669,35 @@ void parseNotesForMetadata(Record &meta) { static QRegularExpression const reTitle - ("^\\s*Title\\s*:\\s*(.*)", QRegularExpression::CaseInsensitiveOption); + ("^[\\s\x1Bm]*Title\\s*:?\\s*(.*)", QRegularExpression::CaseInsensitiveOption); static QRegularExpression const reVersion ("^\\s*Version\\s*:\\s*(.*)", QRegularExpression::CaseInsensitiveOption); static QRegularExpression const reReleaseDate ("^\\s*Release( date)?\\s*:\\s*(.*)", QRegularExpression::CaseInsensitiveOption); static QRegularExpression const reAuthor - ("^\\s*Author(s)?\\s*:\\s*(.*)", QRegularExpression::CaseInsensitiveOption); + ("^\\s*Author(s)?\\s*:?\\s*(.*)", QRegularExpression::CaseInsensitiveOption); static QRegularExpression const reContact - ("^\\s*Email address\\s*:\\s*(.*)", QRegularExpression::CaseInsensitiveOption); + ("^\\s*Email address\\s*:?\\s*(.*)", QRegularExpression::CaseInsensitiveOption); bool foundVersion = false; + bool foundTitle = false; - foreach (String line, meta.gets("notes", "").split('\n')) + foreach (String line, meta.gets(VAR_NOTES, "").split('\n')) { - auto match = reTitle.match(line); - if (match.hasMatch()) + if (!foundTitle) { - meta.set(VAR_TITLE, match.captured(1)); - continue; + auto match = reTitle.match(line); + if (match.hasMatch()) + { + meta.set(VAR_TITLE, match.captured(1).trimmed()); + foundTitle = true; + continue; + } } if (!foundVersion) { - match = reReleaseDate.match(line); + auto match = reReleaseDate.match(line); if (match.hasMatch()) { Date const releaseDate = Date::fromText(match.captured(2).trimmed()); @@ -695,7 +712,7 @@ } } - match = reVersion.match(line); + auto match = reVersion.match(line); if (match.hasMatch()) { Version parsed(match.captured(1).trimmed()); @@ -710,14 +727,14 @@ match = reAuthor.match(line); if (match.hasMatch()) { - meta.set(VAR_AUTHOR, match.captured(2)); + meta.set(VAR_AUTHOR, match.captured(2).trimmed()); continue; } match = reContact.match(line); if (match.hasMatch()) { - meta.set("contact", match.captured(1)); + meta.set("contact", match.captured(1).trimmed()); continue; } } @@ -733,10 +750,10 @@ static QList> terms; if (terms.isEmpty()) { - terms << std::make_pair(String("doom2"), StringList({ "doom2|doom 2|DoomII|Doom II|final\\s*doom|plutonia|tnt" })); //, "\\bmap[0-3][0-9]\\b" })); - terms << std::make_pair(String("doom"), StringList({ "^doom$|\\bdoom[^ s2][^2d]|ultimate\\s*doom|udoom" })); //, "\\be[1-4]m[1-9]\\b" })); - terms << std::make_pair(String("heretic"), StringList({ "jheretic|heretic", "d'sparil|serpent rider" })); //, "\\be[1-5]m[1-9]\\b" })); - terms << std::make_pair(String("hexen"), StringList({ "jhexen|hexen", "korax|mage|warrior|cleric" })); //, "\\bmap[0-3][0-9]\\b" })); + terms << std::make_pair(String("doom2"), StringList({ "\\b(doom2|doom 2|DoomII|Doom II|final\\s*doom|plutonia|tnt)\\b" })); + terms << std::make_pair(String("doom"), StringList({ "^doom$|\\bdoom[^ s2][^2d]\\b|\\bultimate\\s*doom\\b|\\budoom\\b" })); + terms << std::make_pair(String("heretic"), StringList({ "\\b(jheretic|heretic)\\b", "\\b(d'sparil|serpent rider)\\b" })); + terms << std::make_pair(String("hexen"), StringList({ "\\b(jhexen|hexen)\\b", "\\b(korax|mage|warrior|cleric)\\b" })); } QHash scores; for (auto i : terms) //= terms.constBegin(); i != terms.constEnd(); ++i) @@ -799,15 +816,16 @@ static void removeGameTags(Record &meta) { - String newTags; - foreach (QString tag, Package::tags(meta.gets(VAR_TAGS))) - { - if (!gameTags().contains(tag)) - { - if (!newTags.isEmpty()) newTags += QStringLiteral(" "); - newTags += tag; - } - } + String newTags = meta.gets(VAR_TAGS); + newTags.remove(QRegularExpression(anyGameTagPattern())); +// foreach (QString tag, Package::tags(meta.gets(VAR_TAGS))) +// { +// if (!gameTags().contains(tag)) +// { +// if (!newTags.isEmpty()) newTags += QStringLiteral(" "); +// newTags += tag; +// } +// } meta.set(VAR_TAGS, newTags); } @@ -841,7 +859,7 @@ removeGameTags(meta); meta.appendUniqueWord(VAR_TAGS, tag); } - else if (identifyMostLikelyGame(meta.gets("notes", ""), tag)) + else if (identifyMostLikelyGame(meta.gets(VAR_NOTES, ""), tag)) { //qDebug() << meta.gets(VAR_TITLE)<< "- from notes:" << tag; removeGameTags(meta); @@ -1088,15 +1106,29 @@ return *asFile().source(); } +String DataBundle::rootPath() const +{ + return asFile().path().fileNamePath(); +} + String DataBundle::packageId() const { - if (d->packageId.isEmpty()) + if (!d->packageId) { identifyPackages(); } return d->packageId; } +String DataBundle::versionedPackageId() const +{ + if (!d->packageId) + { + identifyPackages(); + } + return d->versionedPackageId; +} + IByteArray::Size DataBundle::size() const { if (d->source) @@ -1154,6 +1186,20 @@ return nullptr; } +DataBundle const *DataBundle::tryLocateDataFile(Package const &package, String const &dataFilePath) +{ + if (DataBundle const *bundle = package.root().tryLocate(dataFilePath)) + { + return bundle; + } + // The package may itself be a link to a data bundle. + if (DataBundle const *bundle = maybeAs(package.sourceFile().target())) + { + return bundle; + } + return nullptr; +} + void DataBundle::setFormat(Format format) { d->format = format; @@ -1233,6 +1279,12 @@ File *DataBundle::Interpreter::interpretFile(File *sourceData) const { + // Broken links cannot be interpreted. + if (LinkFile *link = maybeAs(sourceData)) + { + if (link->isBroken()) return nullptr; + } + // Naive check using the file extension. static struct { String str; Format format; } formats[] = { { ".pk3.zip", Pk3 }, @@ -1246,7 +1298,7 @@ //String const ext = sourceData->extension(); for (auto const &fmt : formats) { - if (sourceData->name().endsWith(fmt.str, Qt::CaseInsensitive)) + if (sourceData->name().endsWith(fmt.str, String::CaseInsensitive)) { LOG_RES_XVERBOSE("Interpreted %s as %s", sourceData->description() << @@ -1293,7 +1345,7 @@ String const dataFilePath = v->asText(); // Look up the data bundle file. - if (DataBundle const *bundle = pkg->root().tryLocate(dataFilePath)) + if (DataBundle const *bundle = tryLocateDataFile(*pkg, dataFilePath)) { // Identify it now (if not already identified). Note that data // files inside packages usually aren't identified during @@ -1344,7 +1396,7 @@ if (bundlePath.isEmpty()) return false; //qDebug() << "bundle:" << path.asText() << "searchTerm:" << searchPath.fileNamePath(); if (bundlePath.toString().endsWith(searchPath.fileNamePath(), - Qt::CaseInsensitive)) + String::CaseInsensitive)) { return true; } @@ -1365,3 +1417,61 @@ { return String("\\b(%1)\\b").arg(String::join(gameTags(), "|")); } + +String DataBundle::cleanIdentifier(String const &text) +{ + // Periods and underscores have special meaning in packages IDs. + // Whitespace is used as separator in package ID lists (see PackageLoader). + // Info syntax has ambiguous quote/double-quote escaping in strings, so + // we'll also get rid of single quotes. (For example, Info converts a string + // containing ['"] to ['''].) + String cleaned = text.toLower(); + cleaned.replace(QRegExp("[._'\\s]"), "-"); + return cleaned; +} + +String DataBundle::stripVersion(String const &text, Version *version) +{ + QRegExp re(".*([-_. ]v?([0-9._-]+))$"); + if (re.exactMatch(text)) + { + if (version) + { + String str = re.cap(2); + str.replace("_", "."); + version->parseVersionString(str); + } + return text.mid(0, text.size() - re.cap(1).size()); + } + return text; +} + +String DataBundle::stripRedundantParts(String const &id) +{ + DotPath const path(id); + String stripped = path.segment(0); + for (int i = 1; i < path.segmentCount(); ++i) + { + String seg = path.segment(i); + for (int k = 1; k <= i; ++k) // Check all previous segments. + { + if (seg.startsWith(path.segment(i - k) + "-")) + { + seg = seg.mid(path.segment(i - k).size() + 1); + break; + } + } + stripped = stripped.concatenateMember(seg); + } + return stripped; +} + +de::String DataBundle::versionFromTimestamp(const Time ×tamp) +{ + return timestamp.asDateTime().toString(QStringLiteral("0.yyyy.MMdd.hhmm")); +} + +void DataBundle::checkAuxiliaryNotes(Record &packageMetadata) +{ + d->checkAuxiliaryNotes(packageMetadata); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/lumpcatalog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/lumpcatalog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/lumpcatalog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/lumpcatalog.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -34,9 +34,17 @@ using Found = std::pair; StringList packageIds; - QList bundles; /// @todo Should observe for deletion. -jk + QList bundles; - Impl(Public *i) : Base(i) {} + Impl(Public *i) + : Base(i) + {} + + Impl(Public *i, const Impl &other) + : Base(i) + , packageIds(other.packageIds) + , bundles(other.bundles) + {} void clear() { @@ -70,11 +78,18 @@ // The last bundle is checked first. for (int i = bundles.size() - 1; i >= 0; --i) { - auto const pos = bundles.at(i)->lumpDirectory()->find(lumpName); - if (pos != LumpDirectory::InvalidPos) + if (const auto *bundle = maybeAs(bundles.at(i))) { - found = Found(bundles.at(i), pos); - break; + auto const pos = bundle->lumpDirectory()->find(lumpName); + if (pos != LumpDirectory::InvalidPos) + { + found = Found(bundle, pos); + break; + } + } + else + { + qDebug() << "LumpCatalog is outdated: a bundle has been deleted"; } } return found; @@ -84,6 +99,10 @@ LumpCatalog::LumpCatalog() : d(new Impl(this)) {} + +LumpCatalog::LumpCatalog(const LumpCatalog &other) + : d(new Impl(this, *other.d)) +{} void LumpCatalog::clear() { @@ -101,6 +120,11 @@ return false; } +StringList LumpCatalog::packages() const +{ + return d->packageIds; +} + Block LumpCatalog::read(String const &lumpName) const { Block data; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/resources.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/resources.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/resources.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/resources.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -64,13 +64,13 @@ else if (!symbol.compare("GamePlugin.Name", Qt::CaseInsensitive)) { auto &gx = DoomsdayApp::plugins().gameExports(); - if (DoomsdayApp::game().isNull() || !gx.GetVariable) + if (DoomsdayApp::game().isNull() || !gx.GetPointer) { /// @throw de::Uri::ResolveSymbolError An unresolveable symbol was encountered. throw de::Uri::ResolveSymbolError("Resources::resolveUriSymbol", "Symbol 'GamePlugin' did not resolve (no game plugin loaded)"); } - return String(reinterpret_cast(gx.GetVariable(DD_PLUGIN_NAME))); + return String(reinterpret_cast(gx.GetPointer(DD_PLUGIN_NAME))); } else { @@ -186,9 +186,7 @@ }; Resources::Resources() : d(new Impl(this)) -{ - App::packageLoader().loadFromCommandLine(); -} +{} void Resources::timeChanged(Clock const &) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/textures.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/textures.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/resource/textures.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/resource/textures.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -607,16 +607,16 @@ File1 &file = index[i]; String fileName = file.name().fileNameWithoutExtension(); - if (fileName.beginsWith('S', Qt::CaseInsensitive) && fileName.length() >= 5) + if (fileName.beginsWith('S', String::CaseInsensitive) && fileName.length() >= 5) { - if (fileName.endsWith("_START", Qt::CaseInsensitive)) + if (fileName.endsWith("_START", String::CaseInsensitive)) { // We've arrived at *a* sprite block. Stack_Push(stack, NULL); continue; } - if (fileName.endsWith("_END", Qt::CaseInsensitive)) + if (Stack_Height(stack) > 0 && fileName.endsWith("_END", String::CaseInsensitive)) { // The sprite block ends. Stack_Pop(stack); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/savegames.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/savegames.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/savegames.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/savegames.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -268,19 +268,22 @@ D_CMD(InspectSavegame) { DENG2_UNUSED2(src, argc); + String savePath = argv[1]; + // Append a .save extension if none exists. if (savePath.fileNameExtension().isEmpty()) { savePath += ".save"; } + // If a game is loaded assume the user is referring to those savegames if not specified. - if (savePath.fileNamePath().isEmpty() && App_GameLoaded()) + if (savePath.fileNamePath().isEmpty() && DoomsdayApp::currentGameProfile()) { - savePath = AbstractSession::savePath() / savePath; + savePath = DoomsdayApp::currentGameProfile()->savePath() / savePath; } - if (GameStateFolder const *saved = FileSystem::tryLocate(savePath)) + if (const GameStateFolder *saved = FileSystem::tryLocate(savePath)) { LOG_SCR_MSG("%s") << saved->metadata().asStyledText(); LOG_SCR_MSG(_E(D) "Resource: " _E(.)_E(i) "\"%s\"") << saved->path(); @@ -296,3 +299,12 @@ C_CMD("inspectsavegame", "s", InspectSavegame) } +String SaveGames::savePath() +{ + if (auto *gp = DoomsdayApp::currentGameProfile()) + { + return gp->savePath(); + } + return {}; +} + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/uri.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/uri.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/uri.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/uri.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -119,7 +119,7 @@ } // Attempt to guess the scheme by interpreting the path? - if (defaultResourceClass == RC_UNKNOWN) + if (defaultResourceClass == RC_IMPLICIT) { defaultResourceClass = DD_GuessFileTypeFromFileName(strPath).defaultClass(); } @@ -204,6 +204,14 @@ Uri::Uri() : d(new Impl) {} +Uri::Uri(String const &percentEncoded) : d(new Impl) +{ + if (!percentEncoded.isEmpty()) + { + setUri(percentEncoded, RC_IMPLICIT, '/'); + } +} + Uri::Uri(String const &percentEncoded, resourceclassid_t defaultResourceClass, QChar sep) : d(new Impl) { @@ -506,6 +514,7 @@ } #ifdef _DEBUG +# if !defined (DENG_MOBILE) LIBDENG_DEFINE_UNITTEST(Uri) { @@ -607,6 +616,7 @@ LIBDENG_RUN_UNITTEST(Uri) +# endif // DENG_MOBILE #endif // _DEBUG } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/urivalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/urivalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/urivalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/urivalue.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -63,7 +63,7 @@ { // We are able to look for substrings within the text, without applying automatic // type conversions. - if (value.is()) + if (is(value)) { return _uri.asText().indexOf(value.asText(), Qt::CaseSensitive) >= 0; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/actions.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/actions.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/actions.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/actions.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -33,7 +33,7 @@ ::actions.clear(); // Action links are provided by the game (which owns the actual action functions). - if (auto getVar = DoomsdayApp::plugins().gameExports().GetVariable) + if (auto getVar = DoomsdayApp::plugins().gameExports().GetPointer) { auto const *links = (actionlink_t const *) getVar(DD_ACTION_LINK); for (actionlink_t const *link = links; link && link->name; link++) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/materialarchive.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/materialarchive.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/materialarchive.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/materialarchive.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -103,7 +103,7 @@ Material *material = nullptr; try { - material = &world::Materials::get().material(de::Uri(records.stringRef(id), RC_NULL)); + material = &world::Materials::get().material(de::makeUri(records.stringRef(id))); } catch (Resources::MissingResourceManifestError const &) {} // Ignore this error. @@ -202,7 +202,7 @@ if (recordSymbolicMaterials) { // The first material is the special "unknown material". - d->insertRecord(de::Uri(UNKNOWN_MATERIALNAME, RC_NULL)); + d->insertRecord(de::makeUri(UNKNOWN_MATERIALNAME)); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/material.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/material.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/material.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/material.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -222,6 +222,11 @@ setDimensions(Vector2ui(width(), newHeight)); } +bool Material::isAnimated() const +{ + return hasAnimatedTextureLayers(); +} + void Material::setWidth(int newWidth) { setDimensions(Vector2ui(newWidth, height())); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/materials.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/materials.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/materials.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/materials.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -23,6 +23,7 @@ #include "doomsday/resource/resources.h" #include +#include using namespace de; @@ -56,6 +57,8 @@ QList materials; ///< From all schemes. int materialManifestCount = 0; ///< Total number of material manifests (in all schemes). + std::unordered_set animatedMaterialsSubset; ///< Subset of materials (not owned) that need to animate. + MaterialManifestGroups materialGroups; uint materialManifestIdMapSize = 0; @@ -158,7 +161,9 @@ /// Observes Material Deletion. void materialBeingDeleted(Material const &material) { - materials.removeOne(const_cast(&material)); + Material *pMat = const_cast(&material); + materials.removeOne(pMat); + animatedMaterialsSubset.erase(pMat); } }; @@ -269,7 +274,7 @@ return d->materials.count(); } -LoopResult Materials::forAllMaterials(std::function func) const +LoopResult Materials::forAllMaterials(const std::function &func) const { for (Material *mat : d.getConst()->materials) { @@ -281,6 +286,30 @@ return LoopContinue; } +LoopResult Materials::forAnimatedMaterials(const std::function &func) const +{ + for (Material *mat : d.getConst()->animatedMaterialsSubset) + { + if (auto result = func(*mat)) + { + return result; + } + } + return LoopContinue; +} + +void Materials::updateLookup() +{ + d->animatedMaterialsSubset.clear(); + for (auto *mat : d->materials) + { + if (mat->isAnimated()) + { + d->animatedMaterialsSubset.insert(mat); + } + } +} + Materials::MaterialManifestGroup &Materials::newMaterialGroup() { // Allocating one by one is inefficient, but it doesn't really matter. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/mobjthinkerdata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/mobjthinkerdata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/mobjthinkerdata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/mobjthinkerdata.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -39,6 +39,26 @@ , d(new Impl) {} +void MobjThinkerData::think() +{ + auto &mo = *mobj(); + + coord_t lastOrigin[3]; + memcpy(lastOrigin, mo.origin, sizeof(lastOrigin)); + mo.ddFlags &= ~DDMF_MOVEBLOCKED; + + ThinkerData::think(); + + // Flag the mobj if it didn't change position (per axis). + for (int axis = 0; axis < 3; ++axis) + { + if (fequal(lastOrigin[axis], mo.origin[axis])) + { + mo.ddFlags |= DDMF_MOVEBLOCKEDX << axis; + } + } +} + Thinker::IData *MobjThinkerData::duplicate() const { return new MobjThinkerData(*this); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/texturemateriallayer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/texturemateriallayer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/texturemateriallayer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/texturemateriallayer.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -83,7 +83,7 @@ TextureMaterialLayer::AnimationStage * TextureMaterialLayer::AnimationStage::fromDef(Record const &stageDef) { - return new AnimationStage(de::Uri(stageDef.gets("texture"), RC_NULL), + return new AnimationStage(de::makeUri(stageDef.gets("texture")), stageDef.geti("tics"), stageDef.getf("variance"), stageDef.getf("glowStrength"), diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/thinkerdata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/thinkerdata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/thinkerdata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/thinkerdata.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -24,7 +24,7 @@ using namespace de; -//static QMultiHash thinkerLookup; +static QMultiHash thinkerLookup; DENG2_PIMPL(ThinkerData) { @@ -47,7 +47,7 @@ ~Impl() { - //thinkerLookup.remove(id, &self()); + thinkerLookup.remove(id, &self()); DENG2_FOR_PUBLIC_AUDIENCE2(Deletion, i) { @@ -63,14 +63,18 @@ ThinkerData::ThinkerData(Id const &id) : d(new Impl(this, id)) { - //DENG2_ASSERT(!d->id.isNone()); - //thinkerLookup.insert(d->id, this); + if (d->id) + { + thinkerLookup.insert(d->id, this); + } } ThinkerData::ThinkerData(ThinkerData const &other) : d(new Impl(this, *other.d)) { - //DENG2_ASSERT(!d->id.isNone()); - //thinkerLookup.insert(d->id, this); + if (d->id) + { + thinkerLookup.insert(d->id, this); + } } Id const &ThinkerData::id() const @@ -80,8 +84,8 @@ void ThinkerData::setId(Id const &id) { - //thinkerLookup.remove(d->id, this); - //thinkerLookup.insert(id, this); + thinkerLookup.remove(d->id, this); + thinkerLookup.insert(id, this); d->id = id; } @@ -135,7 +139,7 @@ void ThinkerData::operator << (Reader &from) { - //thinkerLookup.remove(d->id, this); + thinkerLookup.remove(d->id, this); world::InternalSerialId sid; from >> sid; @@ -153,10 +157,10 @@ } // The thinker has a new ID. - //thinkerLookup.insert(d->id, this); + thinkerLookup.insert(d->id, this); } -/*ThinkerData *ThinkerData::find(Id const &id) +ThinkerData *ThinkerData::find(Id const &id) { auto found = thinkerLookup.constFind(id); if (found != thinkerLookup.constEnd()) @@ -164,7 +168,7 @@ return found.value(); } return nullptr; -}*/ +} #ifdef DENG2_DEBUG duint32 ThinkerData::DebugCounter::total = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/xg.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/xg.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/libdoomsday/src/world/xg.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/libdoomsday/src/world/xg.cpp 2018-12-11 07:08:20.000000000 +0000 @@ -30,7 +30,7 @@ ::xgClassLinks = nullptr; // XG class links are provided by the game (which defines the class specific parameter names). - if (auto getVar = DoomsdayApp::plugins().gameExports().GetVariable) + if (auto getVar = DoomsdayApp::plugins().gameExports().GetPointer) { ::xgClassLinks = (xgclass_t *) getVar(DD_XGFUNC_LINK); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/CMakeLists.txt 2018-12-11 07:08:20.000000000 +0000 @@ -5,30 +5,42 @@ project (Plugins) include (../../cmake/Config.cmake) +# Libraries ----------------------------------------------------------------------------- + add_subdirectory (libgamefw) +# Importers ----------------------------------------------------------------------------- + add_subdirectory (importdeh) add_subdirectory (importidtech1) -add_subdirectory (importsave) add_subdirectory (importudmf) +if (NOT IOS) + add_subdirectory (importsave) +endif () + +# Games --------------------------------------------------------------------------------- add_subdirectory (doom) add_subdirectory (heretic) add_subdirectory (hexen) add_subdirectory (doom64) +# Audio --------------------------------------------------------------------------------- + add_subdirectory (fmod) -add_subdirectory (openal) -if (NOT WIN32) +if (NOT TARGET audio_fmod) + add_subdirectory (openal) +endif () +if (NOT IOS) add_subdirectory (fluidsynth) endif () - -# Platform-specific plugins. if (WIN32) add_subdirectory (directsound) add_subdirectory (winmm) endif () -if (DENG_DEVELOPER) +# Other --------------------------------------------------------------------------------- + +if (DENG_DEVELOPER AND NOT IOS) add_subdirectory (example) endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/common.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/common.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/common.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/common.h 2018-12-11 07:08:20.000000000 +0000 @@ -57,8 +57,9 @@ extern "C" { #endif -int Common_GetInteger(int id); -void Common_Register(); +void * Common_GetGameAPI(char const *name); +int Common_GetInteger(int id); +void Common_Register(); #ifdef __cplusplus } // extern "C" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/config.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/config.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/config.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/config.h 2018-12-11 07:08:21.000000000 +0000 @@ -54,6 +54,7 @@ // Gameplay: byte switchSoundOrigin; byte defaultRuleFastMonsters; + byte pushableMomentumLimitedToPusher; // Weapons: byte weaponCycleSequential; // if true multiple next/prev weapon impulses can be chained to allow the user to "count-click-switch". @@ -141,6 +142,7 @@ float automapL3[3]; float automapBack[3]; float automapOpacity; + byte automapNeverObscure; float automapLineAlpha; float automapLineWidth; ///< In fixed 320x200 pixels. byte automapRotate; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/dmu_lib.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/dmu_lib.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/dmu_lib.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/dmu_lib.h 2018-12-11 07:08:21.000000000 +0000 @@ -37,7 +37,7 @@ #define numsectors (P_Count(DMU_SECTOR)) #define numlines (P_Count(DMU_LINE)) #define numsides (P_Count(DMU_SIDE)) -#define numpolyobjs (*(int*) DD_GetVariable(DD_POLYOBJ_COUNT)) +#define numpolyobjs (*(int*) DD_GetVariable(DD_MAP_POLYOBJ_COUNT)) // DMU property aliases. For short-hand purposes: #define DMU_FRONT_SECTOR (DMU_FRONT_OF_LINE | DMU_SECTOR) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gamerules.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gamerules.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gamerules.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gamerules.h 2018-12-11 07:08:21.000000000 +0000 @@ -17,54 +17,96 @@ * 02110-1301 USA */ -#ifndef DENG_CLIENT_GAMERULES_H -#define DENG_CLIENT_GAMERULES_H +#ifndef LIBCOMMON_GAMERULES_H +#define LIBCOMMON_GAMERULES_H + +typedef enum gfw_gamerule_e { + GFW_RULE_skill, + GFW_RULE_fast, + GFW_RULE_deathmatch, + GFW_RULE_noMonsters, + GFW_RULE_respawnMonsters, + GFW_RULE_randomClasses +} gfw_gamerule_t; #ifdef __cplusplus -#include "doomsday.h" +#include "gamesession.h" #include #include /** * @todo Separate behaviors so that each rule is singular. */ -class GameRuleset +class GameRules { public: - int skill; -#if !__JHEXEN__ - byte fast; -#endif - byte deathmatch; - byte noMonsters; + // Cached values (read-only): + struct Values { + int skill; + bool fast; + byte deathmatch; + bool noMonsters; + bool respawnMonsters; #if __JHEXEN__ - byte randomClasses; -#else - byte respawnMonsters; + bool randomClasses; #endif + }; + Values const values{}; + + static de::String const VAR_skill; + static de::String const VAR_fast; + static de::String const VAR_deathmatch; + static de::String const VAR_noMonsters; + static de::String const VAR_respawnMonsters; + static de::String const VAR_randomClasses; public: - GameRuleset(); - GameRuleset(GameRuleset const &other); + GameRules(); + GameRules(GameRules const &other); - static GameRuleset *fromReader(Reader1 *reader); - static GameRuleset *fromRecord(de::Record const &rec, GameRuleset const *defaults = 0); + //static GameRules *fromReader(Reader1 *reader); + static GameRules *fromRecord(de::Record const &rec, GameRules const *defaults = 0); - GameRuleset &operator = (GameRuleset const &other); + GameRules &operator = (GameRules const &other); de::String description() const; - de::Record *toRecord() const; + de::Record & asRecord(); + de::Record const & asRecord() const; + + template + void set(de::String const &key, T const &value) { + asRecord().set(key, value); + } - void write(Writer1 *writer) const; - void read(Reader1 *reader); + // void write(Writer1 *writer) const; + // void read(Reader1 *reader); de::String asText() const; + + void update(); + +private: + DENG2_PRIVATE(d) }; +#define gfw_Rule(name) (gfw_Session()->rules().values.name) +#define GameRules_Set(d, name, value) { \ + (d).set(GameRules::VAR_##name, value); \ + (d).update(); \ +} +#define gfw_SetRule(name, value) \ + GameRules_Set(gfw_Session()->rules(), name, value) + #else -typedef void *GameRuleset; -#endif -#endif // DENG_CLIENT_GAMERULES_H +// C API + +typedef void *GameRules; +int gfw_SessionRule(gfw_gamerule_t rule); +#define gfw_Rule(name) gfw_SessionRule(GFW_RULE_##name) + +#endif // __cplusplus + +#endif // LIBCOMMON_GAMERULES_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gamesession.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gamesession.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gamesession.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gamesession.h 2018-12-11 07:08:21.000000000 +0000 @@ -22,10 +22,16 @@ #include #include +#include #include -#include "doomsday.h" -#include "acs/system.h" -#include "gamerules.h" + +//#include "doomsday.h" +//#include "acs/system.h" +//#include "gamerules.h" + +class GameRules; + +namespace acs { class System; } namespace common { @@ -105,7 +111,7 @@ /** * Returns the current ruleset for the game session. */ - GameRuleset const &rules() const; + GameRules const &rules() const; /** * To be called when a new game begins to effect the game rules. Note that some of the rules @@ -113,7 +119,7 @@ * * @todo Prevent this outright if the game session is already in progress! */ - void applyNewRules(GameRuleset const &rules); + void applyNewRules(GameRules const &rules); /** * Determines whether saved game progress will be restored when the current map is reloaded, @@ -144,7 +150,7 @@ * * @throws InProgressError if the session has already begun. */ - void begin(GameRuleset const &rules, de::String const &episodeId, de::Uri const &mapUri, + void begin(GameRules const &rules, de::String const &episodeId, de::Uri const &mapUri, uint mapEntryPoint = 0); /** @@ -233,6 +239,16 @@ /** * Macro for conveniently accessing the common::GameSession singleton instance. */ -#define COMMON_GAMESESSION (&common::GameSession::gameSession()) +#define gfw_Session() (&common::GameSession::gameSession()) + +/** + * Returns the currently loaded game's ID. + */ +de::String gfw_GameId(); + +/** + * Returns the current game profile, or nullptr. + */ +const GameProfile *gfw_GameProfile(); #endif // LIBCOMMON_GAMESESSION_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/g_common.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/g_common.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/g_common.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/g_common.h 2018-12-11 07:08:21.000000000 +0000 @@ -23,6 +23,7 @@ #include "dd_share.h" #include +#include "common.h" #include "fi_lib.h" #include "mobj.h" #include "player.h" @@ -30,10 +31,13 @@ #if __cplusplus class SaveSlots; -extern GameRuleset defaultGameRules; +GameRules &gfw_DefaultGameRules(); + +#define gfw_DefaultRule(name) (gfw_DefaultGameRules().values.name) +#define gfw_SetDefaultRule(name, value) GameRules_Set(gfw_DefaultGameRules(), name, value) extern de::Uri nextMapUri; -extern uint nextMapEntryPoint; +extern uint nextMapEntryPoint; /** * Schedule a new game session (deferred). @@ -43,7 +47,7 @@ * @param mapUri Map identifier. * @param mapEntrance Logical map entry point number. */ -void G_SetGameActionNewSession(GameRuleset const &rules, de::String episodeId, +void G_SetGameActionNewSession(GameRules const &rules, de::String episodeId, de::Uri const &mapUri, uint mapEntrance = 0); /** @@ -92,7 +96,7 @@ * * @todo: Should use WorldSystem::mapInfoForMapUri() instead. */ -de::Record const &G_MapInfoForMapUri(de::Uri const &mapUri); +de::Record &G_MapInfoForMapUri(de::Uri const &mapUri); /** * @param mapUri Identifier of the map to lookup the author of. @@ -163,7 +167,13 @@ SaveSlots &G_SaveSlots(); extern "C" { -#endif +#endif // __cplusplus + +/** + * Returns the Map Info flags of the current map in the current game session. + * @return MIF flags. + */ +unsigned int gfw_MapInfoFlags(void); /** * Returns @c true, if the game is currently quiting. @@ -210,22 +220,19 @@ AutoStr *G_CurrentMapUriPath(void); -int G_Ruleset_Skill(); -#if !__JHEXEN__ -byte G_Ruleset_Fast(); -#endif -byte G_Ruleset_Deathmatch(); -byte G_Ruleset_NoMonsters(); -#if __JHEXEN__ -byte G_Ruleset_RandomClasses(); -#else -byte G_Ruleset_RespawnMonsters(); -#endif -void G_Ruleset_UpdateDefaults(); +void GameRules_UpdateDefaultsFromCVars(); /// @todo remove me void G_SetGameActionMapCompletedAndSetNextMap(void); +/** + * Changes the automap rotation mode for all players. Also sets the cvar value so the mode + * will persist. + * + * @param enableRotate Enable or disable the rotation mode. + */ +void G_SetAutomapRotateMode(byte enableRotate); + D_CMD( CCmdMakeLocal ); D_CMD( CCmdSetCamera ); D_CMD( CCmdSetViewLock ); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gl_special.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gl_special.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/gl_special.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/gl_special.h 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,21 @@ +/** @file + * + * @authors Copyright (c) 2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ +#ifndef GL_SPECIAL_H +#define GL_SPECIAL_H + +#endif // GL_SPECIAL_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hud/automapstyle.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hud/automapstyle.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hud/automapstyle.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hud/automapstyle.h 2018-12-11 07:08:21.000000000 +0000 @@ -23,103 +23,104 @@ #include "doomsday.h" -#if __JDOOM__ || __JDOOM64__ -#define BLACK (0) -#define WHITE (256-47) -#define REDS (256-5*16) -#define GREENS (7*16) -#define YELLOWS (256-32+7) -#define GRAYS (6*16) -#define BROWNS (4*16) - -#define WALLCOLORS REDS -#define TSWALLCOLORS GRAYS -#define CDWALLCOLORS YELLOWS -#define FDWALLCOLORS BROWNS -#define THINGCOLORS GREENS -#define BACKGROUND BLACK +#if defined (__JDOOM__) || defined(__JDOOM64__) +# define BLACK (0) +# define WHITE (256-47) +# define REDS (256-5*16) +# define GREENS (7*16) +# define YELLOWS (256-32+7) +# define GRAYS (6*16) +# define BROWNS (4*16) + +# define WALLCOLORS REDS +# define TSWALLCOLORS GRAYS +# define UNWALLCOLORS (GRAYS + 3) +# define CDWALLCOLORS YELLOWS +# define FDWALLCOLORS BROWNS +# define THINGCOLORS GREENS +# define BACKGROUND BLACK // Keys for Baby Mode -#define KEY1_COLOR (197) // Blue Key -#define KEY2_COLOR (256-5*16) // Red Key -#define KEY3_COLOR (256-32+7) // Yellow Key -#define KEY4_COLOR (256-32+7) // Yellow Skull -#define KEY5_COLOR (256-5*16) // Red Skull -#define KEY6_COLOR (197) // Blue Skull - -#define AM_PLR1_COLOR GREENS -#define AM_PLR2_COLOR GRAYS -#define AM_PLR3_COLOR BROWNS -#define AM_PLR4_COLOR REDS +# define KEY1_COLOR (197) // Blue Key +# define KEY2_COLOR (256-5*16) // Red Key +# define KEY3_COLOR (256-32+7) // Yellow Key +# define KEY4_COLOR (256-32+7) // Yellow Skull +# define KEY5_COLOR (256-5*16) // Red Skull +# define KEY6_COLOR (197) // Blue Skull + +# define AM_PLR1_COLOR GREENS +# define AM_PLR2_COLOR GRAYS +# define AM_PLR3_COLOR BROWNS +# define AM_PLR4_COLOR REDS #endif -#ifdef __JHERETIC__ -#define BLACK (0) -#define WHITE (4*8) -#define REDS (12*8) -#define GREENS (33*8) -#define YELLOWS (10*8) -#define GRAYS (5*8) -#define BROWNS (14*8-2) -#define PARCH (13*8-1) - -#define WALLCOLORS REDS -#define TSWALLCOLORS GRAYS -#define CDWALLCOLORS YELLOWS -#define FDWALLCOLORS BROWNS -#define THINGCOLORS (4) -#define BACKGROUND PARCH +#if defined (__JHERETIC__) +# define BLACK (0) +# define WHITE (35) +# define REDS (145) +# define GREENS (209) +# define YELLOWS (111) +# define GRAYS (16) +# define BROWNS (66) +# define PARCH (103) + +# define WALLCOLORS (72) +# define TSWALLCOLORS (1) +# define UNWALLCOLORS (40) +# define CDWALLCOLORS (77) +# define FDWALLCOLORS (110) +# define THINGCOLORS (4) +# define BACKGROUND PARCH // Keys for Baby Mode -#define KEY1_COLOR (144) // Green Key -#define KEY2_COLOR (197) // Yellow Key -#define KEY3_COLOR (220) // Blue Key - -#define AM_PLR1_COLOR (220) -#define AM_PLR2_COLOR (197) -#define AM_PLR3_COLOR (150) -#define AM_PLR4_COLOR (144) +# define KEY1_COLOR (144) // Green Key +# define KEY2_COLOR (197) // Yellow Key +# define KEY3_COLOR (220) // Blue Key + +# define AM_PLR1_COLOR (220) +# define AM_PLR2_COLOR (197) +# define AM_PLR3_COLOR (150) +# define AM_PLR4_COLOR (144) #endif - -#ifdef __JHEXEN__ +#if defined (__JHEXEN__) // For use if I do walls with outsides/insides -#define REDS (12*8) -#define BLUES (256-4*16+8) -#define GREENS (33*8) -#define GRAYS (5*8) -#define BROWNS (14*8) -#define YELLOWS (10*8) -#define BLACK (0) -#define WHITE (4*8) -#define PARCH (13*8-1) -#define BLOODRED (177) +# define REDS (12*8) +# define BLUES (256-4*16+8) +# define GREENS (33*8) +# define GRAYS (5*8) +# define BROWNS (14*8) +# define YELLOWS (10*8) +# define BLACK (0) +# define WHITE (4*8) +# define PARCH (13*8-1) +# define BLOODRED (177) // Automap colors -#define BACKGROUND PARCH -#define WALLCOLORS (83) // REDS -#define TSWALLCOLORS GRAYS -#define FDWALLCOLORS (96) // BROWNS -#define CDWALLCOLORS (107) // YELLOWS -#define THINGCOLORS (255) -#define SECRETWALLCOLORS WALLCOLORS +# define BACKGROUND PARCH +# define WALLCOLORS (83) // REDS +# define TSWALLCOLORS GRAYS +# define UNWALLCOLORS (GRAYS + 3) +# define FDWALLCOLORS (96) // BROWNS +# define CDWALLCOLORS (107) // YELLOWS +# define THINGCOLORS (255) +# define SECRETWALLCOLORS WALLCOLORS -#define BORDEROFFSET (4) +# define BORDEROFFSET (4) // Automap colors -#define AM_PLR1_COLOR (157) // Blue -#define AM_PLR2_COLOR (177) // Red -#define AM_PLR3_COLOR (137) // Yellow -#define AM_PLR4_COLOR (198) // Green -#define AM_PLR5_COLOR (215) // Jade -#define AM_PLR6_COLOR (32) // White -#define AM_PLR7_COLOR (106) // Hazel -#define AM_PLR8_COLOR (234) // Purple - -#define KEY1 (197) // HEXEN - -#define KEY2 (144) // HEXEN - -#define KEY3 (220) // HEXEN - - +# define AM_PLR1_COLOR (157) // Blue +# define AM_PLR2_COLOR (177) // Red +# define AM_PLR3_COLOR (137) // Yellow +# define AM_PLR4_COLOR (198) // Green +# define AM_PLR5_COLOR (215) // Jade +# define AM_PLR6_COLOR (32) // White +# define AM_PLR7_COLOR (106) // Hazel +# define AM_PLR8_COLOR (234) // Purple + +# define KEY1 (197) // HEXEN - +# define KEY2 (144) // HEXEN - +# define KEY3 (220) // HEXEN - #endif enum automapcfg_objectname_t @@ -162,7 +163,7 @@ int reqNotFlagged; int reqAutomapFlags; float rgba[4]; - blendmode_t blendMode; + //blendmode_t blendMode; float glowStrength, glowSize; glowtype_t glow; dd_bool scaleWithView; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hud/widgets/automapwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hud/widgets/automapwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hud/widgets/automapwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hud/widgets/automapwidget.h 2018-12-11 07:08:21.000000000 +0000 @@ -122,7 +122,7 @@ /** * Returns the current view space scaling factor. */ - dfloat scale() const; + de::dfloat scale() const; void setScale(de::dfloat newScale); /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hu_menu.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hu_menu.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/hu_menu.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/hu_menu.h 2018-12-11 07:08:21.000000000 +0000 @@ -107,7 +107,7 @@ #define SFX_MENU_NAV_RIGHT (SFX_SWITCH) #define SFX_MENU_ACCEPT (SFX_DORCLS) #define SFX_MENU_CYCLE (SFX_DORCLS) // Cycle available options. -#define SFX_MENU_SLIDER_MOVE (SFX_STNMOV) +#define SFX_MENU_SLIDER_MOVE (SFX_KEYUP) #define SFX_QUICKSAVE_PROMPT (SFX_CHAT) #define SFX_QUICKLOAD_PROMPT (SFX_CHAT) #define SFX_DELETESAVEGAME_CONFIRM (SFX_CHAT) @@ -241,7 +241,7 @@ void Hu_MenuDefaultFocusAction(menu::Widget &wi, menu::Widget::Action action); -void Hu_MenuDrawFocusCursor(de::Vector2i const &origin, int focusObjectHeight, float alpha); +void Hu_MenuDrawFocusCursor(de::Vector2i const &origin, float scale, float alpha); void Hu_MenuDrawPageTitle(de::String titleText, de::Vector2i const &origin); void Hu_MenuDrawPageHelp(de::String helpText, de::Vector2i const &origin); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/page.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/page.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/page.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/page.h 2018-12-11 07:08:21.000000000 +0000 @@ -63,12 +63,11 @@ }; Q_DECLARE_FLAGS(Flags, Flag) - typedef WidgetList Children; + using Children = WidgetList; - typedef void (*OnActiveCallback) (Page &); - typedef void (*OnDrawCallback) (Page const &, de::Vector2i const &); - - typedef int (*CommandResponder) (Page &, menucommand_e); + using OnActiveCallback = std::function; + using OnDrawCallback = std::function; + using CommandResponder = std::function; public: /** @@ -77,14 +76,14 @@ * @param name Symbolic name/identifier for the page. * @param origin Origin of the page in fixed 320x200 space. * @param flags Page flags. - * --- * @param drawer * @param cmdResponder */ - explicit Page(de::String name, de::Vector2i const &origin = de::Vector2i(), - Flags const &flags = DefaultFlags, - OnDrawCallback drawer = 0, - CommandResponder cmdResponder = 0); + explicit Page(de::String name, + de::Vector2i const & origin = de::Vector2i(), + Flags const & flags = DefaultFlags, + const OnDrawCallback & drawer = {}, + const CommandResponder &cmdResponder = {}); virtual ~Page(); @@ -99,9 +98,14 @@ void setOrigin(de::Vector2i const &newOrigin); de::Vector2i origin() const; + Flags flags() const; + de::Rectanglei viewRegion() const; + void setX(int x); void setY(int y); + void setLeftColumnWidth(float columnWidthPercentage = 0.6f); + void setPreviousPage(Page *newPreviousPage); Page *previousPage() const; @@ -188,7 +192,7 @@ * * @param newCallback Function to callback on page activation. Use @c 0 to clear. */ - void setOnActiveCallback(OnActiveCallback newCallback); + void setOnActiveCallback(const OnActiveCallback &newCallback); /** * Retrieve a predefined color triplet associated with this page by it's logical diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/buttonwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/buttonwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/buttonwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/buttonwidget.h 2018-12-11 07:08:21.000000000 +0000 @@ -39,6 +39,8 @@ void updateGeometry(); int handleCommand(menucommand_e command); + void setSilent(bool silent); + ButtonWidget &setText(de::String const &newText); de::String text() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/cvartogglewidget.h 2018-12-11 07:08:21.000000000 +0000 @@ -22,6 +22,7 @@ #define LIBCOMMON_UI_CVARTOGGLEWIDGET #include "buttonwidget.h" +#include namespace common { namespace menu { @@ -41,9 +42,9 @@ CVarToggleWidget(char const *cvarPath, int cvarValueMask = 0, de::String const &downText = "Yes", de::String const &upText = "No"); - virtual ~CVarToggleWidget(); + virtual ~CVarToggleWidget() override; - int handleCommand(menucommand_e command); + int handleCommand(menucommand_e command) override; void setState(State newState); State state() const; @@ -60,6 +61,10 @@ void setUpText(de::String const &newUpText); de::String upText() const; + void setStateChangeCallback(const std::function &stateChanged); + + void pageActivated() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/inputbindingwidget.h 2018-12-11 07:08:21.000000000 +0000 @@ -40,15 +40,20 @@ public: InputBindingWidget(); - virtual ~InputBindingWidget(); + virtual ~InputBindingWidget() override; - void draw() const; - void updateGeometry(); - int handleEvent_Privileged(event_t const &event); - int handleCommand(menucommand_e command); + void draw() const override; + void updateGeometry() override; + int handleEvent_Privileged(event_t const &event) override; + int handleCommand(menucommand_e command) override; char const *controlName() const; de::String bindContext() const; + + void pageActivated() override; + +private: + DENG2_PRIVATE(d) }; } // namespace menu diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/listwidget.h 2018-12-11 07:08:21.000000000 +0000 @@ -108,6 +108,10 @@ */ bool selectItemByValue(int itemIndex, int flags = MNLIST_SIF_NO_ACTION); + bool reorder(int itemIndex, int indexOffset); + + ListWidget &setReorderingEnabled(bool reorderEnabled); + /// @return Index of the currently selected item else -1. int selection() const; @@ -119,6 +123,8 @@ void updateVisibleSelection(); + void pageActivated() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/widget.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/widget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/menu/widgets/widget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/menu/widgets/widget.h 2018-12-11 07:08:21.000000000 +0000 @@ -58,6 +58,9 @@ PositionFixed = 0x100, ///< XY position is fixed and predefined; automatic layout does not apply. LayoutOffset = 0x200, ///< Predefined XY position is applied to the dynamic layout origin. + LeftColumn = 0x400, ///< Widget is laid out to the page's left column. + RightColumn = 0x800, ///< Widget is laid out to the page's right column. + /// @todo We need a new dynamic id mechanism. Id7 = 0x1000000, Id6 = 0x2000000, @@ -83,7 +86,7 @@ Activated, ///< Becomes "active". Closed, ///< Normally means changed-state to be discarded. FocusLost, ///< Loses selection "focus". - FocusGained ///< Gains selection "focus". + FocusGained, ///< Gains selection "focus". }; typedef void (*ActionCallback) (Widget &, Action); @@ -162,6 +165,9 @@ Widget &setFlags(Flags flagsToChange, de::FlagOp operation = de::SetFlags); Flags flags() const; + Widget &setLeft() { return setFlags(LeftColumn); } + Widget &setRight() { return setFlags(RightColumn); } + inline bool isActive() const { return flags() & Active; } inline bool isFocused() const { return flags() & Focused; } inline bool isHidden() const { return flags() & Hidden; } @@ -225,6 +231,12 @@ Widget &setUserValue2(QVariant const &newValue); QVariant const &userValue2() const; + float scrollingFadeout() const; + float scrollingFadeout(int yTop, int yBottom) const; + de::Vector4f selectionFlashColor(const de::Vector4f &noFlashColor) const; + + virtual void pageActivated(); + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/mobj.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/mobj.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/mobj.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/mobj.h 2018-12-11 07:08:21.000000000 +0000 @@ -25,10 +25,22 @@ #include "common.h" #ifdef __cplusplus + +#include + extern "C" { #endif /** + * Returns the private internal ID of a map object. This is a unique 32-bit number + * that the engine chooses internally for identifying the object. + * + * @param mob Map object. + * @return Private ID. + */ +uint32_t Mobj_PrivateID(mobj_t const *mob); + +/** * Determines the current friction affecting @a mo, given the sector it is in and * whether it is on the floor. * @@ -218,6 +230,16 @@ #ifdef __cplusplus } // extern "C" + +/** + * Describe the object in plain text Info syntax. + * @param mob Map object. + * @return Description text. + */ +de::String Mobj_StateAsInfo(mobj_t const *mob); + +void Mobj_RestoreObjectState(mobj_t *mob, de::Info::BlockElement const &state); + #endif #endif // LIBCOMMON_MOBJ_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/player.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/player.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/player.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/player.h 2018-12-11 07:08:21.000000000 +0000 @@ -181,8 +181,8 @@ * @param msg The message to be sent. * @param flags @ref logMessageFlags */ -void P_SetMessageWithFlags(player_t *plr, char const *msg, int flags); -void P_SetMessage (player_t *plr, char const *msg/*, int flags = 0*/); +void P_SetMessageWithFlags(const player_t *plr, char const *msg, int flags); +void P_SetMessage(const player_t *plr, char const *msg/*, int flags = 0*/); /** * Send a yellow message to the given player and maybe echos it to the console. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/p_sound.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/p_sound.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/p_sound.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/p_sound.h 2018-12-11 07:08:21.000000000 +0000 @@ -30,8 +30,10 @@ /** * Start the song for the specified map. + * + * @c return Music was successfully started. */ -void S_MapMusic(de::Uri const &mapUri); +bool S_MapMusic(de::Uri const &mapUri); extern "C" { #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/p_user.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/p_user.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/p_user.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/p_user.h 2018-12-11 07:08:21.000000000 +0000 @@ -25,11 +25,11 @@ #include "dd_types.h" -#define PLAYER_REBORN_TICS (1*TICSPERSEC) +#define PLAYER_REBORN_TICS (1 * TICSPERSEC) DENG_EXTERN_C dd_bool onground; - -DENG_EXTERN_C int maxHealth; +DENG_EXTERN_C float turboMul; // Multiplier for running speed. +DENG_EXTERN_C int maxHealth; #if __JDOOM__ || __JDOOM64__ DENG_EXTERN_C int healthLimit; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/r_special.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/r_special.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/include/r_special.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/include/r_special.h 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,36 @@ +/** @file gl_special.h Special color effects for the game view. + * + * @authors Copyright (c) 2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBCOMMON_REFRESH_SPECIAL_H +#define LIBCOMMON_REFRESH_SPECIAL_H + +#include + +DENG2_EXTERN_C void R_SpecialFilterRegister(void); + +DENG2_EXTERN_C void R_InitSpecialFilter(void); + +/** + * Draws a special filter over the screen (e.g. the Doom inversing filter used + * when in god mode). + */ +DENG2_EXTERN_C void R_UpdateSpecialFilter(int player); + +DENG2_EXTERN_C void R_UpdateSpecialFilterWithTimeDelta(int player, float delta); + +#endif // LIBCOMMON_REFRESH_SPECIAL_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/acs/interpreter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/acs/interpreter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/acs/interpreter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/acs/interpreter.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -827,7 +827,7 @@ { gametype = 0; // singleplayer } - else if(COMMON_GAMESESSION->rules().deathmatch) + else if(gfw_Rule(deathmatch)) { gametype = 2; // deathmatch } @@ -842,7 +842,7 @@ ACS_COMMAND(GameSkill) { - interp.locals.push((int)COMMON_GAMESESSION->rules().skill); + interp.locals.push((int)gfw_Rule(skill)); return Continue; } @@ -1131,7 +1131,7 @@ System &Interpreter::scriptSys() const { - return COMMON_GAMESESSION->acsSystem(); + return gfw_Session()->acsSystem(); } Script &Interpreter::script() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/acs/system.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/acs/system.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/acs/system.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/acs/system.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -73,7 +73,7 @@ { String mapUriStr; from >> mapUriStr; - mapUri = de::Uri(mapUriStr, RC_NULL); + mapUri = de::makeUri(mapUriStr); if(mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); from >> scriptNumber; @@ -216,12 +216,12 @@ Script::Args const &scriptArgs) { DENG2_ASSERT(!IS_CLIENT); - DENG2_ASSERT(COMMON_GAMESESSION->mapUri() != mapUri); + DENG2_ASSERT(gfw_Session()->mapUri() != mapUri); LOG_AS("acs::System"); // Don't defer tasks in deathmatch. /// @todo Why the restriction? -ds - if(COMMON_GAMESESSION->rules().deathmatch) + if (gfw_Rule(deathmatch)) return true; // Don't allow duplicates. @@ -335,7 +335,7 @@ D_CMD(InspectACScript) { DENG2_UNUSED2(src, argc); - System &scriptSys = COMMON_GAMESESSION->acsSystem(); + System &scriptSys = gfw_Session()->acsSystem(); dint const scriptNumber = String(argv[1]).toInt(); if(!scriptSys.hasScript(scriptNumber)) @@ -359,7 +359,7 @@ D_CMD(ListACScripts) { DENG2_UNUSED3(src, argc, argv); - System &scriptSys = COMMON_GAMESESSION->acsSystem(); + System &scriptSys = gfw_Session()->acsSystem(); if(scriptSys.scriptCount()) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/common.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/common.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/common.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/common.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,59 +0,0 @@ -/** @file common.c Top-level libcommon routines. - * - * @authors Copyright © 2012-2017 Jaakko Keränen - * @authors Copyright © 2013-2014 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#include "common.h" -#include "g_common.h" - -int Common_GetInteger(int id) -{ - switch(id) - { - case DD_GAME_RECOMMENDS_SAVING: - // The engine will use this as a hint whether to remind the user to - // manually save the game before, e.g., upgrading to a new version. - return G_GameState() == GS_MAP; - - default: break; - } - - return 0; -} - -#ifdef __JDOOM__ -void fastMonstersChanged() -{ - G_Ruleset_UpdateDefaults(); -} -#endif - -void Common_Register() -{ - // Movement - C_VAR_FLOAT("player-move-speed", &cfg.common.playerMoveSpeed, 0, 0, 1); - C_VAR_INT ("player-jump", &cfg.common.jumpEnabled, 0, 0, 1); - C_VAR_FLOAT("player-jump-power", &cfg.common.jumpPower, 0, 0, 100); - C_VAR_BYTE ("player-air-movement", &cfg.common.airborneMovement, 0, 0, 32); - - // Gameplay - C_VAR_BYTE ("sound-switch-origin", &cfg.common.switchSoundOrigin, 0, 0, 1); -#ifdef __JDOOM__ - C_VAR_BYTE2("game-monsters-fast", &cfg.common.defaultRuleFastMonsters, 0, 0, 1, fastMonstersChanged); -#endif -} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/common.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/common.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/common.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/common.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,119 @@ +/** @file common.c Top-level libcommon routines. + * + * @authors Copyright © 2012-2017 Jaakko Keränen + * @authors Copyright © 2013-2014 Daniel Swanson + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include "common.h" +#include "g_common.h" +#include "g_update.h" +#include "p_map.h" +#include "polyobjs.h" +#include "r_common.h" + +int Common_GetInteger(int id) +{ + switch(id) + { + case DD_MOBJ_SIZE: + return sizeof(mobj_t); // game plugin specific + + case DD_POLYOBJ_SIZE: + return sizeof(Polyobj); + + case DD_GAME_RECOMMENDS_SAVING: + // The engine will use this as a hint whether to remind the user to + // manually save the game before, e.g., upgrading to a new version. + return G_GameState() == GS_MAP; + + default: + break; + } + return 0; +} + +void *Common_GetGameAPI(char const *name) +{ + #define HASH_ENTRY(Name, Func) std::make_pair(QByteArray(Name), de::function_cast(Func)) + static QHash const funcs( + { + HASH_ENTRY("DrawViewPort", G_DrawViewPort), + HASH_ENTRY("FinaleResponder", FI_PrivilegedResponder), + HASH_ENTRY("FinalizeMapChange", P_FinalizeMapChange), + HASH_ENTRY("HandleMapDataPropertyValue", P_HandleMapDataPropertyValue), + HASH_ENTRY("HandleMapObjectStatusReport", P_HandleMapObjectStatusReport), + HASH_ENTRY("HandlePacket", D_HandlePacket), + HASH_ENTRY("MobjCheckPositionXYZ", P_CheckPositionXYZ), + HASH_ENTRY("MobjFriction", Mobj_Friction), + HASH_ENTRY("MobjRestoreState", Mobj_RestoreObjectState), + HASH_ENTRY("MobjStateAsInfo", Mobj_StateAsInfo), + HASH_ENTRY("MobjThinker", P_MobjThinker), + HASH_ENTRY("MobjTryMoveXYZ", P_TryMoveXYZ), + HASH_ENTRY("NetConnect", D_NetConnect), + HASH_ENTRY("NetDisconnect", D_NetDisconnect), + HASH_ENTRY("NetPlayerEvent", D_NetPlayerEvent), + HASH_ENTRY("NetServerStart", D_NetServerStarted), + HASH_ENTRY("NetServerStop", D_NetServerClose), + HASH_ENTRY("NetWorldEvent", D_NetWorldEvent), + HASH_ENTRY("PrivilegedResponder", G_PrivilegedResponder), + HASH_ENTRY("Responder", G_Responder), + HASH_ENTRY("SectorHeightChangeNotification", P_HandleSectorHeightChange), + HASH_ENTRY("Ticker", G_Ticker), + HASH_ENTRY("UpdateState", G_UpdateState), + }); + #undef HASH_ENTRY + + auto found = funcs.find(name); + if (found != funcs.end()) return found.value(); + return nullptr; +} + +GameRules &gfw_DefaultGameRules() +{ + static GameRules defaultGameRules; + return defaultGameRules; +} + +void GameRules_UpdateDefaultsFromCVars() +{ +#if !__JHEXEN__ + gfw_SetDefaultRule(fast, cfg.common.defaultRuleFastMonsters); +#endif +} + +#ifdef __JDOOM__ +void fastMonstersChanged() +{ + GameRules_UpdateDefaultsFromCVars(); +} +#endif + +void Common_Register() +{ + // Movement + C_VAR_FLOAT("player-move-speed", &cfg.common.playerMoveSpeed, 0, 0, 1); + C_VAR_INT ("player-jump", &cfg.common.jumpEnabled, 0, 0, 1); + C_VAR_FLOAT("player-jump-power", &cfg.common.jumpPower, 0, 0, 100); + C_VAR_BYTE ("player-air-movement", &cfg.common.airborneMovement, 0, 0, 32); + + // Gameplay + C_VAR_BYTE ("sound-switch-origin", &cfg.common.switchSoundOrigin, 0, 0, 1); +#ifdef __JDOOM__ + C_VAR_BYTE2("game-monsters-fast", &cfg.common.defaultRuleFastMonsters, 0, 0, 1, fastMonstersChanged); +#endif + C_VAR_BYTE ("game-objects-pushable-limit", &cfg.common.pushableMomentumLimitedToPusher, 0, 0, 1); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/fi_lib.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/fi_lib.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/fi_lib.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/fi_lib.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -87,10 +87,10 @@ #if __JHEXEN__ // Leaving the current hub? - if(Record const *episodeDef = COMMON_GAMESESSION->episodeDef()) + if(Record const *episodeDef = gfw_Session()->episodeDef()) { defn::Episode epsd(*episodeDef); - Record const *currentHub = epsd.tryFindHubByMapId(COMMON_GAMESESSION->mapUri().compose()); + Record const *currentHub = epsd.tryFindHubByMapId(gfw_Session()->mapUri().compose()); s.conditions.leave_hub = (!currentHub || currentHub != epsd.tryFindHubByMapId(::nextMapUri.compose())); } LOGDEV_SCR_VERBOSE("Infine state condition: leave_hub=%i") << s.conditions.leave_hub; @@ -427,7 +427,7 @@ else if(mode == FIMODE_BEFORE) // A briefing has ended. { // Its time to start the map; cue music and begin! - S_MapMusic(COMMON_GAMESESSION->mapUri()); + S_MapMusic(gfw_Session()->mapUri()); HU_WakeWidgets(-1 /* all players */); G_BeginMap(); Pause_End(); // skip forced period @@ -499,7 +499,7 @@ if(!qstricmp(p->token, "deathmatch")) { - p->returnVal = (COMMON_GAMESESSION->rules().deathmatch != false); + p->returnVal = (gfw_Rule(deathmatch) != false); return true; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/gamerules.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/gamerules.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/gamerules.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/gamerules.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -1,6 +1,6 @@ /** @file gamerules.cpp Game rule set. * - * @authors Copyright © 2003-2017 Jaakko Keränen + * @authors Copyright © 2003-2018 Jaakko Keränen * @authors Copyright © 2005-2013 Daniel Swanson * * @par License @@ -20,121 +20,153 @@ #include "common.h" #include "gamerules.h" +#include "gamesession.h" using namespace de; -GameRuleset::GameRuleset() - : skill(0) -#if !__JHEXEN__ - , fast(0) -#endif - , deathmatch(0) - , noMonsters(0) -#if __JHEXEN__ - , randomClasses(0) -#else - , respawnMonsters(0) -#endif -{} +/* + * These keys are used for serialization, so if changed, the only keys still need to be changed + * when reading data. + */ +String const GameRules::VAR_skill = "skill"; +String const GameRules::VAR_fast = "fast"; +String const GameRules::VAR_deathmatch = "deathmatch"; +String const GameRules::VAR_noMonsters = "noMonsters"; +String const GameRules::VAR_respawnMonsters = "respawnMonsters"; +String const GameRules::VAR_randomClasses = "randomClasses"; -GameRuleset::GameRuleset(GameRuleset const &other) - : skill (other.skill) -#if !__JHEXEN__ - , fast (other.fast) -#endif - , deathmatch (other.deathmatch) - , noMonsters (other.noMonsters) -#if __JHEXEN__ - , randomClasses (other.randomClasses) -#else - , respawnMonsters(other.respawnMonsters) -#endif -{} +DENG2_PIMPL_NOREF(GameRules) +{ + Record rules { + Record::withMembers(GameRules::VAR_skill, 2, // medium + GameRules::VAR_fast, false, + GameRules::VAR_deathmatch, 0, + GameRules::VAR_noMonsters, false, + GameRules::VAR_randomClasses, false, + GameRules::VAR_respawnMonsters, false) }; -GameRuleset *GameRuleset::fromReader(reader_s *reader) // static + Impl() {} + + Impl(Impl const &other) + : rules(other.rules) + {} +}; + +GameRules::GameRules() + : d(new Impl) { - GameRuleset *rules = new GameRuleset; - rules->read(reader); - return rules; + update(); } -GameRuleset *GameRuleset::fromRecord(Record const &record, GameRuleset const *defaults) // static +GameRules::GameRules(GameRules const &other) + : d(new Impl(*other.d)) { - GameRuleset *rules = new GameRuleset; + update(); +} - Record const *rec = &record; - if(defaults) +//GameRules *GameRules::fromReader(reader_s *reader) // static +//{ +// GameRules *rules = new GameRules; +// rules->read(reader); +// return rules; +//} + +GameRules *GameRules::fromRecord(Record const &record, GameRules const *defaults) // static +{ + GameRules *gr = new GameRules; + + /*Record rec = &record; + if (defaults) { - Record *merged = defaults->toRecord(); - merged->copyMembersFrom(record); + Record merged = defaults->d->rules; // defaults->toRecord(); + merged.copyMembersFrom(record); rec = merged; + }*/ + + if (defaults) + { + gr->d->rules.copyMembersFrom(defaults->asRecord(), Record::IgnoreDoubleUnderscoreMembers); } - /// @todo Info keys are converted to lowercase when parsed. - if(!defaults || rec->has("skill")) rules->skill = rec->geti("skill"); -#if !__JHEXEN__ - if(!defaults || rec->has("fast")) rules->fast = byte( rec->getb("fast") ); -#endif - if(!defaults || rec->has("deathmatch")) rules->deathmatch = byte( rec->geti("deathmatch") ); - if(!defaults || rec->has("noMonsters")) rules->noMonsters = byte( rec->getb("noMonsters") ); -#if __JHEXEN__ - if(!defaults || rec->has("randomClasses")) rules->randomClasses = byte( rec->getb("randomClasses") ); -#else - if(!defaults || rec->has("respawnMonsters")) rules->respawnMonsters = byte( rec->getb("respawnMonsters") ); -#endif + gr->d->rules.copyMembersFrom(record, Record::IgnoreDoubleUnderscoreMembers); + +// if(!defaults || rec->has("skill")) rules->skill = rec->geti("skill"); +//#if !__JHEXEN__ +// if(!defaults || rec->has("fast")) rules->fast = byte( rec->getb("fast") ); +//#endif +// if(!defaults || rec->has("deathmatch")) rules->deathmatch = byte( rec->geti("deathmatch") ); +// if(!defaults || rec->has("noMonsters")) rules->noMonsters = byte( rec->getb("noMonsters") ); +//#if __JHEXEN__ +// if(!defaults || rec->has("randomClasses")) rules->randomClasses = byte( rec->getb("randomClasses") ); +//#else +// if(!defaults || rec->has("respawnMonsters")) rules->respawnMonsters = byte( rec->getb("respawnMonsters") ); +//#endif + + //if(rec != &record) delete rec; + + //qDebug() << "GameRules from Record:\n" << gr->d->rules.asText().toUtf8().constData(); + + return gr; +} - if(rec != &record) delete rec; - return rules; +Record &GameRules::asRecord() +{ + return d->rules; } -Record *GameRuleset::toRecord() const +Record const &GameRules::asRecord() const { - Record *rec = new Record; + return d->rules; - rec->addNumber ("skill", skill); -#if !__JHEXEN__ - rec->addBoolean("fast", CPP_BOOL(fast)); -#endif - rec->addNumber ("deathmatch", deathmatch); - rec->addBoolean("noMonsters", CPP_BOOL(noMonsters)); -#if __JHEXEN__ - rec->addBoolean("randomClasses", CPP_BOOL(randomClasses)); -#else - rec->addBoolean("respawnMonsters", CPP_BOOL(respawnMonsters)); -#endif +// Record *rec = new Record; + +// rec->addNumber ("skill", skill); +//#if !__JHEXEN__ +// rec->addBoolean("fast", CPP_BOOL(fast)); +//#endif +// rec->addNumber ("deathmatch", deathmatch); +// rec->addBoolean("noMonsters", CPP_BOOL(noMonsters)); +//#if __JHEXEN__ +// rec->addBoolean("randomClasses", CPP_BOOL(randomClasses)); +//#else +// rec->addBoolean("respawnMonsters", CPP_BOOL(respawnMonsters)); +//#endif - return rec; +// return rec; } -GameRuleset &GameRuleset::operator = (GameRuleset const &other) +GameRules &GameRules::operator = (GameRules const &other) { - skill = other.skill; -#if !__JHEXEN__ - fast = other.fast; -#endif - deathmatch = other.deathmatch; - noMonsters = other.noMonsters; -#if __JHEXEN__ - randomClasses = other.randomClasses; -#else - respawnMonsters = other.respawnMonsters; -#endif + d->rules = other.d->rules; + + update(); + +// skill = other.skill; +// fast = other.fast; +// deathmatch = other.deathmatch; +// noMonsters = other.noMonsters; +//#if __JHEXEN__ +// randomClasses = other.randomClasses; +//#else +// respawnMonsters = other.respawnMonsters; +//#endif return *this; } -String GameRuleset::description() const +String GameRules::description() const { /// @todo Separate co-op behavior to new rules, avoiding netgame test. - if(IS_NETGAME) + if (IS_NETGAME) { - if(deathmatch == 2) return "Deathmatch2"; - if(deathmatch) return "Deathmatch"; + if(values.deathmatch == 2) return "Deathmatch2"; + if(values.deathmatch) return "Deathmatch"; return "Co-op"; } return "Singleplayer"; } -void GameRuleset::write(writer_s *writer) const +#if 0 +void GameRules::write(writer_s *writer) const { DENG2_ASSERT(writer != 0); @@ -151,7 +183,7 @@ #endif } -void GameRuleset::read(reader_s *reader) +void GameRules::read(reader_s *reader) { DENG2_ASSERT(reader != 0); @@ -173,20 +205,51 @@ respawnMonsters = Reader_ReadByte(reader); #endif } +#endif -String GameRuleset::asText() const +String GameRules::asText() const { String str; QTextStream os(&str); - os << "skillmode: " << int(skill); + os << "skillmode: " << int(values.skill); //os << " jumping: " << (cfg.common.jumpEnabled ? "yes" : "no"); -#if __JHEXEN__ - os << " random player classes: " << (randomClasses ? "yes" : "no"); +#if defined(__JHEXEN__) + os << " random player classes: " << (values.randomClasses ? "yes" : "no"); #endif - os << " monsters: " << (!noMonsters ? "yes" : "no"); -#if !__JHEXEN__ - os << " (fast: " << (fast ? "yes" : "no"); - os << " respawn: " << (respawnMonsters ? "yes" : "no") << ")"; + os << " monsters: " << (!values.noMonsters ? "yes" : "no"); +#if !defined(__JHEXEN__) + os << " (fast: " << (values.fast ? "yes" : "no"); + os << " respawn: " << (values.respawnMonsters ? "yes" : "no") << ")"; #endif return str; } + +void GameRules::update() +{ + Values *vals = const_cast(&values); + + vals->skill = d->rules.geti(VAR_skill); + vals->fast = d->rules.getb(VAR_fast); + vals->deathmatch = byte(d->rules.geti(VAR_deathmatch)); + vals->noMonsters = d->rules.getb(VAR_noMonsters); + vals->respawnMonsters = d->rules.getb(VAR_respawnMonsters); +#if defined(__JHEXEN__) + vals->randomClasses = d->rules.getb(VAR_randomClasses); +#endif +} + +DENG_EXTERN_C int gfw_SessionRule(gfw_gamerule_t rule) +{ + switch (rule) + { + case GFW_RULE_skill: return gfw_Rule(skill); + case GFW_RULE_fast: return gfw_Rule(fast); + case GFW_RULE_deathmatch: return gfw_Rule(deathmatch); + case GFW_RULE_noMonsters: return gfw_Rule(noMonsters); + case GFW_RULE_respawnMonsters: return gfw_Rule(respawnMonsters); +#if defined(__JHEXEN__) + case GFW_RULE_randomClasses: return gfw_Rule(randomClasses); +#endif + default: return 0; + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/gamesession.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/gamesession.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/gamesession.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/gamesession.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -31,7 +31,9 @@ #include #include #include +#include #include +#include "acs/system.h" #include "api_gl.h" #include "d_netsv.h" #include "g_common.h" @@ -75,7 +77,7 @@ << "\n# Date: " + now.asDateTime().toString(Qt::SystemLocaleShortDate); // Write metadata. - os << "\n\n" + metadata.asTextWithInfoSyntax() + "\n"; + os << "\n\n" + metadata.asInfo() + "\n"; return info; } @@ -100,14 +102,13 @@ using namespace internal; -static GameSession *singleton; - static String const internalSavePath = "/home/cache/internal.save"; +static GameSession theSession; DENG2_PIMPL(GameSession), public GameStateFolder::IMapStateReaderFactory { String episodeId; - GameRuleset rules; + GameRules rules; duint mapEntryPoint = 0; ///< Player entry point, for reborn. bool rememberVisitedMaps = false; @@ -116,13 +117,12 @@ acs::System acscriptSys; ///< The One acs::System instance. Impl(Public *i) : Base(i) - { - DENG2_ASSERT(singleton == nullptr); - singleton = thisPublic; - } + {} - inline String userSavePath(String const &fileName) { - return AbstractSession::savePath() / fileName + ".save"; + inline String userSavePath(String const &fileName) + { + DENG_ASSERT(DoomsdayApp::currentGameProfile()); + return SaveGames::savePath() / fileName + ".save"; } void cleanupInternalSave() @@ -192,12 +192,12 @@ GameStateMetadata meta; meta.set("sessionId", duint(Timer_RealMilliseconds() + (mapTime << 24)) & DDMAXINT); - meta.set("gameIdentityKey", AbstractSession::gameId()); + meta.set("gameIdentityKey", gfw_GameId()); meta.set("episode", episodeId); meta.set("userDescription", "(Unsaved)"); meta.set("mapUri", self().mapUri().compose()); - meta.set("mapTime", ::mapTime); - meta.add("gameRules", self().rules().toRecord()); // Takes ownership. + meta.set("mapTime", mapTime); + meta.add("gameRules", new Record(self().rules().asRecord())); auto *loadedPackages = new ArrayValue; for (String id : PackageLoader::get().loadedPackageIdsInOrder()) @@ -388,45 +388,53 @@ void applyCurrentRules() { - if (rules.skill < SM_NOTHINGS) - rules.skill = SM_NOTHINGS; - if (rules.skill > NUM_SKILL_MODES - 1) - rules.skill = skillmode_t( NUM_SKILL_MODES - 1 ); - + if (rules.values.skill < SM_NOTHINGS) + { + GameRules_Set(rules, skill, SM_NOTHINGS); + } + if (rules.values.skill > NUM_SKILL_MODES - 1) + { + GameRules_Set(rules, skill, skillmode_t(NUM_SKILL_MODES - 1)); + } if (!IS_NETGAME) { #if !__JHEXEN__ - rules.deathmatch = false; - rules.respawnMonsters = dbyte( App::commandLine().has("-respawn") ); - - rules.noMonsters = dbyte( App::commandLine().has("-nomonsters") ); + GameRules_Set(rules, deathmatch, 0); + GameRules_Set(rules, + respawnMonsters, + CommandLine::get().has("-respawn") || + gfw_GameProfile()->optionValue("respawn").isTrue()); + GameRules_Set(rules, + noMonsters, + CommandLine::get().has("-nomonsters") || + gfw_GameProfile()->optionValue("noMonsters").isTrue()); #endif #if __JDOOM__ || __JHERETIC__ // Is respawning enabled at all in nightmare skill? - if (rules.skill == SM_NIGHTMARE) + if (rules.values.skill == SM_NIGHTMARE) { - rules.respawnMonsters = cfg.respawnMonstersNightmare; + GameRules_Set(rules, respawnMonsters, cfg.respawnMonstersNightmare); } #endif } else if (IS_DEDICATED) { #if !__JHEXEN__ - rules.deathmatch = cfg.common.netDeathmatch; - rules.respawnMonsters = cfg.netRespawn; + GameRules_Set(rules, deathmatch, cfg.common.netDeathmatch); + GameRules_Set(rules, respawnMonsters, cfg.netRespawn); - rules.noMonsters = cfg.common.netNoMonsters; + GameRules_Set(rules, noMonsters, cfg.common.netNoMonsters); /*rules.*/cfg.common.jumpEnabled = cfg.common.netJumping; #else - rules.randomClasses = cfg.netRandomClass; + GameRules_Set(rules, randomClasses, cfg.netRandomClass); #endif } // Fast monsters? #if __JDOOM__ || __JDOOM64__ - bool fastMonsters = CPP_BOOL(rules.fast); + bool fastMonsters = rules.values.fast; # if __JDOOM__ - if (rules.skill == SM_NIGHTMARE) + if (rules.values.skill == SM_NIGHTMARE) { fastMonsters = true; } @@ -436,9 +444,9 @@ // Fast missiles? #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - bool fastMissiles = CPP_BOOL(rules.fast); + bool fastMissiles = rules.values.fast; # if !__JDOOM64__ - if (rules.skill == SM_NIGHTMARE) + if (rules.values.skill == SM_NIGHTMARE) { fastMissiles = true; } @@ -449,7 +457,7 @@ NetSv_UpdateGameConfigDescription(); // Update game status cvars: - Con_SetInteger2("game-skill", rules.skill, SVF_WRITE_OVERRIDE); + Con_SetInteger2("game-skill", rules.values.skill, SVF_WRITE_OVERRIDE); } /** @@ -538,10 +546,10 @@ GameStateMetadata const &metadata = saved.metadata(); // Ensure a complete game ruleset is available. - std::unique_ptr newRules; + std::unique_ptr newRules; try { - newRules.reset(GameRuleset::fromRecord(metadata.subrecord("gameRules"))); + newRules.reset(GameRules::fromRecord(metadata.subrecord("gameRules"))); } catch (Record::NotFoundError const &) { @@ -553,7 +561,7 @@ << saved.path(); // Use the current rules as our basis. - newRules.reset(GameRuleset::fromRecord(metadata.subrecord("gameRules"), &rules)); + newRules.reset(GameRules::fromRecord(metadata.subrecord("gameRules"), &rules)); } rules = *newRules; // make a copy applyCurrentRules(); @@ -567,7 +575,7 @@ ArrayValue const &vistedMapsArray = metadata.geta("visitedMaps"); for (Value const *value : vistedMapsArray.elements()) { - visitedMaps << de::Uri(value->as(), RC_NULL); + visitedMaps << de::makeUri(value->as()); } } @@ -581,7 +589,7 @@ self().setInProgress(true); - setMap(de::Uri(metadata.gets("mapUri"), RC_NULL)); + setMap(de::makeUri(metadata.gets("mapUri"))); //mapEntryPoint = ??; // not saved?? reloadMap(); @@ -770,7 +778,7 @@ plr->attacker = nullptr; plr->poisoner = nullptr; - if (IS_NETGAME || rules.deathmatch) + if (IS_NETGAME || rules.values.deathmatch) { // In a network game, force all players to be alive if (plr->playerState == PST_DEAD) @@ -778,7 +786,7 @@ plr->playerState = PST_REBORN; } - if (!rules.deathmatch) + if (!rules.values.deathmatch) { // Cooperative net-play; retain keys and weapons. oldKeys = plr->keys; @@ -793,7 +801,7 @@ bool wasReborn = (plr->playerState == PST_REBORN); - if (rules.deathmatch) + if (rules.values.deathmatch) { de::zap(plr->frags); ddplr->mo = nullptr; @@ -815,7 +823,7 @@ } } - if (wasReborn && IS_NETGAME && !rules.deathmatch) + if (wasReborn && IS_NETGAME && !rules.values.deathmatch) { dint bestWeapon = 0; @@ -885,13 +893,11 @@ { LOG_AS("~GameSession"); d.reset(); - singleton = nullptr; } GameSession &GameSession::gameSession() { - DENG2_ASSERT(singleton); - return *singleton; + return theSession; } bool GameSession::isLoadingPossible() @@ -1001,18 +1007,18 @@ if (chosenExit) { - return de::Uri(chosenExit->gets("targetMap"), RC_NULL); + return de::makeUri(chosenExit->gets("targetMap")); } } return de::Uri(); } -GameRuleset const &GameSession::rules() const +GameRules const &GameSession::rules() const { return d->rules; } -void GameSession::applyNewRules(GameRuleset const &newRules) +void GameSession::applyNewRules(GameRules const &newRules) { LOG_AS("GameSession"); @@ -1026,7 +1032,7 @@ bool GameSession::progressRestoredOnReload() const { - if (d->rules.deathmatch) return false; // Never. + if (d->rules.values.deathmatch) return false; // Never. #if __JHEXEN__ return true; // Cannot be disabled. #else @@ -1066,7 +1072,7 @@ throw Error("GameSession::endAndBeginTitle", "An InFine 'title' script must be defined"); } -void GameSession::begin(GameRuleset const &newRules, String const &episodeId, +void GameSession::begin(GameRules const &newRules, String const &episodeId, de::Uri const &mapUri, uint mapEntryPoint) { if (hasBegun()) @@ -1187,13 +1193,13 @@ d->backupPlayersInHub(playerBackup); // Disable class randomization (all players must spawn as their existing class). - dbyte oldRandomClassesRule = d->rules.randomClasses; - d->rules.randomClasses = false; + dbyte oldRandomClassesRule = d->rules.values.randomClasses; + GameRules_Set(d->rules, randomClasses, false); #endif // Are we saving progress? GameStateFolder *saved = nullptr; - if (!d->rules.deathmatch) // Never save in deathmatch. + if (!d->rules.values.deathmatch) // Never save in deathmatch. { saved = &App::rootFolder().locate(internalSavePath); auto &mapsFolder = saved->locate("maps"); @@ -1278,7 +1284,7 @@ d->restorePlayersInHub(playerBackup); // Restore the random class rule. - d->rules.randomClasses = oldRandomClassesRule; + GameRules_Set(d->rules, randomClasses, oldRandomClassesRule); // Launch waiting scripts. d->acscriptSys.runDeferredTasks(mapUri()); @@ -1426,4 +1432,23 @@ #undef READONLYCVAR } -} // namespace common +} // namespace common + +DENG_EXTERN_C unsigned int gfw_MapInfoFlags(void) +{ + return gfw_Session()->mapInfo().getui(QStringLiteral("flags")); +} + +String gfw_GameId() +{ + if (auto *gp = DoomsdayApp::currentGameProfile()) + { + return gp->gameId(); + } + return {}; +} + +const GameProfile *gfw_GameProfile() +{ + return DoomsdayApp::currentGameProfile(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_defs.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_defs.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_defs.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_defs.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -69,8 +69,9 @@ defn::Episode episodeDef(*rec); if(Record const *mgNodeRec = episodeDef.tryFindMapGraphNodeByWarpNumber(warpNumber)) { - return de::Uri(mgNodeRec->gets("id"), RC_NULL); + return de::makeUri(mgNodeRec->gets("id")); } } - return de::Uri("Maps:", RC_NULL); // Not found. + return de::makeUri("Maps:"); // Not found. } + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_game.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_game.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_game.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_game.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -71,6 +71,7 @@ #include "p_user.h" #include "player.h" #include "r_common.h" +#include "r_special.h" #include "saveslots.h" #include "x_hair.h" @@ -82,8 +83,6 @@ void R_LoadVectorGraphics(); int Hook_DemoStop(int hookType, int val, void *parm); -GameRuleset defaultGameRules; - game_config_t cfg; // The global cfg. #if __JDOOM__ || __JDOOM64__ @@ -113,8 +112,6 @@ de::Uri nextMapUri; uint nextMapEntryPoint; -static GameSession session; - static bool quitInProgress; static gamestate_t gameState = GS_STARTUP; @@ -124,13 +121,17 @@ static gameaction_t gameAction; // Game action parameters: -static GameRuleset gaNewSessionRules; -static String gaNewSessionEpisodeId; +static GameRules &G_NewSessionRules() +{ + static GameRules gaNewSessionRules; + return gaNewSessionRules; +} +static String gaNewSessionEpisodeId; static de::Uri gaNewSessionMapUri; -static uint gaNewSessionMapEntrance; +static uint gaNewSessionMapEntrance; static String gaSaveSessionSlot; -static bool gaSaveSessionGenerateDescription = true; +static bool gaSaveSessionGenerateDescription = true; static String gaSaveSessionUserDescription; static String gaLoadSessionSlot; @@ -141,18 +142,18 @@ void G_SetGameAction(gameaction_t newAction) { - if(G_QuitInProgress()) return; + if (G_QuitInProgress()) return; - if(::gameAction != newAction) + if (::gameAction != newAction) { ::gameAction = newAction; } } -void G_SetGameActionNewSession(GameRuleset const &rules, String episodeId, - de::Uri const &mapUri, uint mapEntrance) +void G_SetGameActionNewSession(GameRules const &rules, String episodeId, de::Uri const &mapUri, + uint mapEntrance) { - ::gaNewSessionRules = rules; // make a copy. + G_NewSessionRules() = rules; ::gaNewSessionEpisodeId = episodeId; ::gaNewSessionMapUri = mapUri; ::gaNewSessionMapEntrance = mapEntrance; @@ -162,12 +163,12 @@ bool G_SetGameActionSaveSession(String slotId, String *userDescription) { - if(!COMMON_GAMESESSION->isSavingPossible()) return false; - if(!G_SaveSlots().has(slotId)) return false; + if (!gfw_Session()->isSavingPossible()) return false; + if (!G_SaveSlots().has(slotId)) return false; ::gaSaveSessionSlot = slotId; - if(userDescription && !userDescription->isEmpty()) + if (userDescription && !userDescription->isEmpty()) { // A new description. ::gaSaveSessionGenerateDescription = false; @@ -186,7 +187,7 @@ bool G_SetGameActionLoadSession(String slotId) { - if(!COMMON_GAMESESSION->isLoadingPossible()) return false; + if (!gfw_Session()->isLoadingPossible()) return false; // Check whether this slot is in use. We do this here also because we need to provide our // caller with instant feedback. Naturally this is no guarantee that the game-save will @@ -194,7 +195,7 @@ auto scheduleLoad = [slotId] () { - if(G_SaveSlots()[slotId].isLoadable()) + if (G_SaveSlots()[slotId].isLoadable()) { // Everything appears to be in order - schedule the game-save load! gaLoadSessionSlot = slotId; @@ -217,7 +218,7 @@ DoomsdayApp::app().checkPackageCompatibility( meta.getStringList("packages"), String::format("The savegame " _E(b) "%s" _E(.) " was created with " - "add-ons that are different than the ones currently in use.", + "mods that are different than the ones currently in use.", meta.gets("userDescription").toUtf8().constData()), scheduleLoad); } @@ -226,7 +227,7 @@ scheduleLoad(); } } - catch(SaveSlots::MissingSlotError const &er) + catch (SaveSlots::MissingSlotError const &er) { LOG_RES_WARNING("Save slot '%s' not found: %s") << slotId << er.asText(); return false; @@ -242,11 +243,11 @@ DENG2_UNUSED(nextMapEntryPoint); #endif - if(IS_CLIENT) return; - if(::cyclingMaps && ::mapCycleNoExit) return; + if (IS_CLIENT) return; + if (::cyclingMaps && ::mapCycleNoExit) return; #if __JHEXEN__ - if((::gameMode == hexen_betademo || ::gameMode == hexen_demo) && + if ((::gameMode == hexen_betademo || ::gameMode == hexen_demo) && !(nextMapUri.path() == "MAP01" || nextMapUri.path() == "MAP02" || nextMapUri.path() == "MAP03" || @@ -266,9 +267,9 @@ # if __JDOOM__ // If no Wolf3D maps, no secret exit! - if(::secretExit && (::gameModeBits & GM_ANY_DOOM2)) + if (::secretExit && (::gameModeBits & GM_ANY_DOOM2)) { - if(!P_MapExists(de::Uri("Maps:MAP31", RC_NULL).compose().toUtf8().constData())) + if (!P_MapExists(de::makeUri("Maps:MAP31").compose().toUtf8().constData())) { ::secretExit = false; } @@ -281,7 +282,7 @@ void G_SetGameActionMapCompletedAndSetNextMap() { - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); } static void initSaveSlots() @@ -297,7 +298,7 @@ menu::Widget::Id6, menu::Widget::Id7 #endif }; - for(int i = 0; i < NUMSAVESLOTS; ++i) + for (int i = 0; i < NUMSAVESLOTS; ++i) { sslots->add(String::number(i), true, String(SAVEGAMENAME"%1").arg(i), int(gameMenuSaveSlotWidgetIds[i])); @@ -313,13 +314,14 @@ ::quitInProgress = false; // Apply the default game rules. - COMMON_GAMESESSION->applyNewRules(defaultGameRules = GameRuleset()); + cfg.common.pushableMomentumLimitedToPusher = true; + gfw_Session()->applyNewRules(gfw_DefaultGameRules() = GameRules()); // Register hooks. Plug_AddHook(HOOK_DEMO_STOP, Hook_DemoStop); // Setup the players. - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { player_t *pl = &players[i]; @@ -328,7 +330,7 @@ /// @todo Only necessary because the engine does not yet unload game plugins when they /// are not in use; thus a game change may leave these pointers dangling. - for(int k = 0; k < NUMPSPRITES; ++k) + for (int k = 0; k < NUMPSPRITES; ++k) { pl->pSprites[k].state = nullptr; pl->plr->pSprites[k].statePtr = nullptr; @@ -358,6 +360,7 @@ IN_ConsoleRegister(); // For the interlude/intermission. X_Register(); // For the crosshair. FI_StackRegister(); // For the InFine lib. + R_SpecialFilterRegister(); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ XG_Register(); #endif @@ -375,14 +378,14 @@ { int mapped; - if(plrClass == PCLASS_PIG) + if (plrClass == PCLASS_PIG) { // A pig is never translated. *tclass = *tmap = 0; return; } - if(gameMode == hexen_v10) + if (gameMode == hexen_v10) { int const mapping[3][4] = { /* Fighter */ { 1, 2, 0, 3 }, @@ -412,12 +415,12 @@ void Mobj_UpdateTranslationClassAndMap(mobj_t *mo) { DENG2_ASSERT(mo); - if(mo->player) + if (mo->player) { int plrColor = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; R_GetTranslation(mo->player->class_, plrColor, &mo->tclass, &mo->tmap); } - else if(mo->flags & MF_TRANSLATION) + else if (mo->flags & MF_TRANSLATION) { mo->tclass = mo->special1; mo->tmap = (mo->flags & MF_TRANSLATION) >> MF_TRANSSHIFT; @@ -456,13 +459,13 @@ // per class. Thus we'll need to account for the difference. int xlatNum = 0; - for(int cl = 0; cl < 3; ++cl) - for(int i = 0; i < 7; ++i) + for (int cl = 0; cl < 3; ++cl) + for (int i = 0; i < 7; ++i) { - if(i == numPerClass) break; // Not present. + if (i == numPerClass) break; // Not present. String lumpName; - if(xlatNum < 10) + if (xlatNum < 10) { lumpName = String("TRANTBL%1").arg(xlatNum); } @@ -477,7 +480,7 @@ lumpName << cl << i); lumpName += ".lmp"; - if(CentralLumpIndex().contains(lumpName)) + if (CentralLumpIndex().contains(lumpName)) { File1 &lump = CentralLumpIndex()[CentralLumpIndex().findLast(lumpName)]; uint8_t const *mappings = lump.cache(); @@ -492,20 +495,20 @@ // brown, red. Could be read from a lump instead? { uint8_t xlat[PALENTRIES]; - for(int xlatNum = 0; xlatNum < 3; ++xlatNum) + for (int xlatNum = 0; xlatNum < 3; ++xlatNum) { // Translate just the 16 green colors. - for(int palIdx = 0; palIdx < 256; ++palIdx) + for (int palIdx = 0; palIdx < 256; ++palIdx) { # if __JHERETIC__ - if(palIdx >= 225 && palIdx <= 240) + if (palIdx >= 225 && palIdx <= 240) { xlat[palIdx] = xlatNum == 0? 114 + (palIdx - 225) /*yellow*/ : xlatNum == 1? 145 + (palIdx - 225) /*red*/ : 190 + (palIdx - 225) /*blue*/; } # else - if(palIdx >= 0x70 && palIdx <= 0x7f) + if (palIdx >= 0x70 && palIdx <= 0x7f) { // Map green ramp to gray, brown, red. xlat[palIdx] = xlatNum == 0? 0x60 + (palIdx & 0xf) : @@ -670,7 +673,7 @@ { 3, anglePoints } }; - if(IS_DEDICATED) return; + if (IS_DEDICATED) return; R_NewSvg(VG_KEY, key, NUMITEMS(key)); R_NewSvg(VG_TRIANGLE, thintriangle, NUMITEMS(thintriangle)); @@ -698,14 +701,14 @@ uri_s *uri = Uri_NewWithPath2(name, RC_NULL); fontid_t fontId = Fonts_ResolveUri(uri); Uri_Delete(uri); - if(fontId) return fontId; + if (fontId) return fontId; Con_Error("Failed loading font \"%s\".", name); exit(1); // Unreachable. } void R_InitRefresh() { - if(IS_DEDICATED) return; + if (IS_DEDICATED) return; LOG_RES_VERBOSE("Loading data for refresh..."); @@ -713,14 +716,14 @@ cfg.common.screenBlocks = cfg.common.setBlocks; { uri_s *paths[9]; - for(int i = 0; i < 9; ++i) + for (int i = 0; i < 9; ++i) { paths[i] = ((borderGraphics[i] && borderGraphics[i][0])? Uri_NewWithPath2(borderGraphics[i], RC_NULL) : 0); } R_SetBorderGfx((uri_s const **)paths); - for(int i = 0; i < 9; ++i) + for (int i = 0; i < 9; ++i) { - if(paths[i]) + if (paths[i]) { Uri_Delete(paths[i]); } @@ -799,6 +802,24 @@ G_RegisterCheats(); #endif + // Change the turbo multiplier. + { + auto &cmdLine = CommandLine::get(); + turboMul = float(gfw_GameProfile()->optionValue("turbo").asNumber()); + if (int arg = cmdLine.check("-turbo")) + { + int scale = 200; // Default to 2x without a numeric value. + + if (arg + 1 < cmdLine.count() && !cmdLine.isOption(arg + 1)) + { + scale = cmdLine.at(arg + 1).toInt(); + } + scale = de::clamp(10, scale, 400); + turboMul = scale / 100.f; + LOG_NOTE("Turbo speed: %i%%") << scale; + } + } + // From this point on, the shortcuts are always active. DD_Execute(true, "activatebcontext shortcut"); @@ -814,14 +835,14 @@ de::Uri startMapUri; // A specific episode? - if(int arg = cmdLine.check("-episode", 1)) + if (int arg = cmdLine.check("-episode", 1)) { String episodeId = cmdLine.at(arg + 1); - if(Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) + if (Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) { // Ensure this is a playable episode. de::Uri startMap(episodeDef->gets("startMap"), RC_NULL); - if(P_MapExists(startMap.compose().toUtf8().constData())) + if (P_MapExists(startMap.compose().toUtf8().constData())) { startEpisodeId = episodeId; } @@ -829,16 +850,16 @@ } // A specific map? - if(int arg = cmdLine.check("-warp", 1)) + if (int arg = cmdLine.check("-warp", 1)) { bool haveEpisode = (arg + 2 < cmdLine.count() && !cmdLine.isOption(arg + 2)); - if(haveEpisode) + if (haveEpisode) { - if(Record const *episodeDef = Defs().episodes.tryFind("id", cmdLine.at(arg + 1))) + if (Record const *episodeDef = Defs().episodes.tryFind("id", cmdLine.at(arg + 1))) { // Ensure this is a playable episode. de::Uri startMap(episodeDef->gets("startMap"), RC_NULL); - if(P_MapExists(startMap.compose().toUtf8().constData())) + if (P_MapExists(startMap.compose().toUtf8().constData())) { startEpisodeId = episodeDef->gets("id"); } @@ -849,17 +870,17 @@ bool isNumber; int mapWarpNumber = cmdLine.at(arg + (haveEpisode? 2 : 1)).toInt(&isNumber); - if(!isNumber) + if (!isNumber) { // It must be a URI, then. Block rawMapUri = cmdLine.at(arg + (haveEpisode? 2 : 1)).toUtf8(); char *args[1] = { const_cast(rawMapUri.constData()) }; startMapUri = de::Uri::fromUserInput(args, 1); - if(startMapUri.scheme().isEmpty()) startMapUri.setScheme("Maps"); + if (startMapUri.scheme().isEmpty()) startMapUri.setScheme("Maps"); } else { - if(startEpisodeId.isEmpty()) + if (startEpisodeId.isEmpty()) { // Pick the first playable episode. startEpisodeId = FirstPlayableEpisodeId(); @@ -871,24 +892,24 @@ // Are we attempting an auto-start? bool autoStart = (IS_NETGAME || !startEpisodeId.isEmpty() || !startMapUri.isEmpty()); - if(autoStart) + if (autoStart) { - if(startEpisodeId.isEmpty()) + if (startEpisodeId.isEmpty()) { // Pick the first playable episode. startEpisodeId = FirstPlayableEpisodeId(); } // Ensure that the map exists. - if(!P_MapExists(startMapUri.compose().toUtf8().constData())) + if (!P_MapExists(startMapUri.compose().toUtf8().constData())) { startMapUri.clear(); // Pick the start map from the episode, if specified and playable. - if(Record const *episodeDef = Defs().episodes.tryFind("id", startEpisodeId)) + if (Record const *episodeDef = Defs().episodes.tryFind("id", startEpisodeId)) { de::Uri startMap(episodeDef->gets("startMap"), RC_NULL); - if(P_MapExists(startMap.compose().toUtf8().constData())) + if (P_MapExists(startMap.compose().toUtf8().constData())) { startMapUri = startMap; } @@ -897,21 +918,21 @@ } // Are we auto-starting? - if(!startEpisodeId.isEmpty() && !startMapUri.isEmpty()) + if (!startEpisodeId.isEmpty() && !startMapUri.isEmpty()) { LOG_NOTE("Auto-starting episode '%s', map \"%s\", skill %i") << startEpisodeId << startMapUri - << ::defaultGameRules.skill; + << gfw_DefaultRule(skill); // Don't brief when autostarting. ::briefDisabled = true; - G_SetGameActionNewSession(::defaultGameRules, startEpisodeId, startMapUri); + G_SetGameActionNewSession(gfw_DefaultGameRules(), startEpisodeId, startMapUri); } else { - COMMON_GAMESESSION->endAndBeginTitle(); // Start up intro loop. + gfw_Session()->endAndBeginTitle(); // Start up intro loop. } } @@ -921,7 +942,7 @@ */ void G_CommonShutdown() { - COMMON_GAMESESSION->end(); + gfw_Session()->end(); Plug_RemoveHook(HOOK_DEMO_STOP, Hook_DemoStop); @@ -960,9 +981,9 @@ { GS_INFINE, "GS_INFINE" }, { gamestate_t(-1), 0 } }; - for(uint i = 0; stateNames[i].name; ++i) + for (uint i = 0; stateNames[i].name; ++i) { - if(stateNames[i].state == state) + if (stateNames[i].state == state) return stateNames[i].name; } return 0; @@ -974,18 +995,18 @@ int G_UIResponder(event_t *ev) { // Handle "Press any key to continue" messages. - if(Hu_MsgResponder(ev)) + if (Hu_MsgResponder(ev)) return true; - if(ev->state != EVS_DOWN) + if (ev->state != EVS_DOWN) return false; - if(!(ev->type == EV_KEY || ev->type == EV_MOUSE_BUTTON || ev->type == EV_JOY_BUTTON)) + if (!(ev->type == EV_KEY || ev->type == EV_MOUSE_BUTTON || ev->type == EV_JOY_BUTTON)) return false; - if(!Hu_MenuIsActive() && !DD_GetInteger(DD_SHIFT_DOWN)) + if (!Hu_MenuIsActive() && !DD_GetInteger(DD_SHIFT_DOWN)) { // Any key/button down pops up menu if in demos. - if((gameAction == GA_NONE && !singledemo && Get(DD_PLAYBACK)) || + if ((gameAction == GA_NONE && !singledemo && Get(DD_PLAYBACK)) || (G_GameState() == GS_INFINE && FI_IsMenuTrigger())) { Hu_MenuCommand(MCMD_OPEN); @@ -998,15 +1019,15 @@ void G_ChangeGameState(gamestate_t state) { - if(G_QuitInProgress()) return; + if (G_QuitInProgress()) return; - if(state < 0 || state >= NUM_GAME_STATES) + if (state < 0 || state >= NUM_GAME_STATES) { DENG2_ASSERT(!"G_ChangeGameState: Invalid state"); return; } - if(gameState != state) + if (gameState != state) { gameState = state; LOGDEV_NOTE("Game state changed to %s") << getGameStateStr(state); @@ -1015,7 +1036,7 @@ // Update the state of the gameui binding context. bool gameUIActive = false; bool gameActive = true; - switch(gameState) + switch (gameState) { case GS_FINALE: case GS_STARTUP: @@ -1031,9 +1052,9 @@ default: break; } - if(!IS_DEDICATED) + if (!IS_DEDICATED) { - if(gameUIActive) + if (gameUIActive) { DD_Execute(true, "activatebcontext gameui"); B_SetContextFallback("gameui", G_UIResponder); @@ -1044,10 +1065,10 @@ dd_bool G_StartFinale(char const *script, int flags, finale_mode_t mode, char const *defId) { - if(!script || !script[0]) + if (!script || !script[0]) return false; - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { ST_LogEmpty(i); // Clear the message queue for all local players. ST_CloseAll(i, true/*fast*/); // Close the HUDs left open for all local players. @@ -1061,15 +1082,15 @@ void G_StartHelp() { - if(G_QuitInProgress()) return; - if(IS_CLIENT) + if (G_QuitInProgress()) return; + if (IS_CLIENT) { /// @todo Fix this properly: http://sf.net/p/deng/bugs/1082/ return; } char const *scriptId = "help"; - if(Record const *finale = Defs().finales.tryFind("id", scriptId)) + if (Record const *finale = Defs().finales.tryFind("id", scriptId)) { Hu_MenuCommand(MCMD_CLOSEFAST); G_StartFinale(finale->gets("script").toUtf8().constData(), FF_LOCAL, FIMODE_NORMAL, scriptId); @@ -1082,7 +1103,7 @@ { G_ChangeGameState(GS_MAP); - if(!IS_DEDICATED) + if (!IS_DEDICATED) { R_SetViewPortPlayer(CONSOLEPLAYER, CONSOLEPLAYER); // View the guy you are playing. R_ResizeViewWindow(RWF_FORCE|RWF_NO_LERP); @@ -1099,8 +1120,8 @@ // Print a map banner to the log. LOG_MSG(DE2_ESC(R)); - LOG_NOTE("%s") << G_MapDescription(COMMON_GAMESESSION->episodeId(), - COMMON_GAMESESSION->mapUri()); + LOG_NOTE("%s") << G_MapDescription(gfw_Session()->episodeId(), + gfw_Session()->mapUri()); LOG_MSG(DE2_ESC(R)); } @@ -1109,19 +1130,19 @@ DENG2_ASSERT(ev); // Eat all events once shutdown has begun. - if(G_QuitInProgress()) return true; + if (G_QuitInProgress()) return true; - if(G_GameState() == GS_MAP) + if (G_GameState() == GS_MAP) { Pause_Responder(ev); // With the menu active, none of these should respond to input events. - if(!Hu_MenuIsActive() && !Hu_IsMessageActive()) + if (!Hu_MenuIsActive() && !Hu_IsMessageActive()) { - if(ST_Responder(ev)) + if (ST_Responder(ev)) return true; - if(G_EventSequenceResponder(ev)) + if (G_EventSequenceResponder(ev)) return true; } } @@ -1134,17 +1155,17 @@ DENG2_ASSERT(ev); // Ignore all events once shutdown has begun. - if(G_QuitInProgress()) return false; + if (G_QuitInProgress()) return false; - if(Hu_MenuPrivilegedResponder(ev)) + if (Hu_MenuPrivilegedResponder(ev)) return true; // Process the screen shot key right away? - if(ev->type == EV_KEY && ev->data1 == DDKEY_F1) + if (ev->type == EV_KEY && ev->data1 == DDKEY_F1) { - if(CommandLine_Check("-devparm")) + if (CommandLine_Check("-devparm")) { - if(ev->state == EVS_DOWN) + if (ev->state == EVS_DOWN) { G_SetGameAction(GA_SCREENSHOT); } @@ -1158,7 +1179,7 @@ static sfxenum_t randomQuitSound() { #if __JDOOM__ || __JDOOM64__ - if(cfg.menuQuitSound) + if (cfg.menuQuitSound) { # if __JDOOM64__ static sfxenum_t quitSounds[] = { @@ -1201,14 +1222,14 @@ int sndTableSize = numQuitSounds; # if !__JDOOM64__ - if(gameModeBits & GM_ANY_DOOM2) + if (gameModeBits & GM_ANY_DOOM2) { sndTable = quitSounds2; sndTableSize = numQuitSounds2; } # endif - if(sndTable && sndTableSize > 0) + if (sndTable && sndTableSize > 0) { return sndTable[P_Random() & (sndTableSize - 1)]; } @@ -1225,12 +1246,12 @@ static bool intermissionEnabled() { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - if(COMMON_GAMESESSION->mapInfo().geti("flags") & MIF_NO_INTERMISSION) + if (gfw_MapInfoFlags() & MIF_NO_INTERMISSION) { return false; } #elif __JHEXEN__ - if(!COMMON_GAMESESSION->rules().deathmatch) + if (!gfw_Rule(deathmatch)) { return false; } @@ -1262,11 +1283,11 @@ info->maxFrags = 0; // See if there is a par time definition. - float parTime = COMMON_GAMESESSION->mapInfo().getf("parTime"); + float parTime = gfw_Session()->mapInfo().getf("parTime"); info->parTime = (parTime > 0? TICRATE * int(parTime) : -1 /*N/A*/); info->pNum = CONSOLEPLAYER; - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { player_t const *p = &players[i]; wbplayerstruct_t *pStats = &info->plyr[i]; @@ -1288,7 +1309,7 @@ ::wmInfo.nextMapEntryPoint = ::nextMapEntryPoint; #endif #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ - ::wmInfo.currentMap = COMMON_GAMESESSION->mapUri(); + ::wmInfo.currentMap = gfw_Session()->mapUri(); ::wmInfo.didSecret = ::players[CONSOLEPLAYER].didSecret; # if __JDOOM__ || __JDOOM64__ ::wmInfo.maxKills = de::max(1, ::totalKills); @@ -1313,14 +1334,14 @@ static bool unloadTriggered = false; // Run the quit countdown? - if(::quitInProgress) + if (::quitInProgress) { - if(Timer_RealMilliseconds() > quitTime + QUITWAIT_MILLISECONDS) + if (Timer_RealMilliseconds() > quitTime + QUITWAIT_MILLISECONDS) { - if(!unloadTriggered) + if (!unloadTriggered) { unloadTriggered = true; - if(CommandLine_Exists("-game")) + if (CommandLine_Exists("-game")) { // Launched directly into game, so quit the engine altogether. // Sys_Quit unloads the game immediately, though, and we're deep @@ -1346,42 +1367,44 @@ // Do things to change the game state. gameaction_t currentAction; - while((currentAction = ::gameAction) != GA_NONE) + while ((currentAction = ::gameAction) != GA_NONE) { BusyMode_FreezeGameForBusyMode(); // The topmost action will now be processed. G_SetGameAction(GA_NONE); - switch(currentAction) + switch (currentAction) { case GA_NEWSESSION: - COMMON_GAMESESSION->end(); - COMMON_GAMESESSION->begin(::gaNewSessionRules, ::gaNewSessionEpisodeId, - ::gaNewSessionMapUri, ::gaNewSessionMapEntrance); + gfw_Session()->end(); + gfw_Session()->begin(G_NewSessionRules(), + ::gaNewSessionEpisodeId, + ::gaNewSessionMapUri, + ::gaNewSessionMapEntrance); break; case GA_LOADSESSION: - COMMON_GAMESESSION->end(); + gfw_Session()->end(); try { SaveSlot const &sslot = G_SaveSlots()[::gaLoadSessionSlot]; - COMMON_GAMESESSION->load(sslot.saveName()); + gfw_Session()->load(sslot.saveName()); // Make note of the last used save slot. Con_SetInteger2("game-save-last-slot", sslot.id().toInt(), SVF_WRITE_OVERRIDE); } - catch(Error const &er) + catch (Error const &er) { LOG_RES_WARNING("Error loading from save slot #%s:\n") << ::gaLoadSessionSlot << er.asText(); } // Return to the title loop if loading did not succeed. - if(!COMMON_GAMESESSION->hasBegun()) + if (!gfw_Session()->hasBegun()) { - COMMON_GAMESESSION->endAndBeginTitle(); + gfw_Session()->endAndBeginTitle(); } break; @@ -1389,12 +1412,12 @@ try { SaveSlot const &sslot = G_SaveSlots()[::gaSaveSessionSlot]; - COMMON_GAMESESSION->save(sslot.saveName(), ::gaSaveSessionUserDescription); + gfw_Session()->save(sslot.saveName(), ::gaSaveSessionUserDescription); // Make note of the last used save slot. Con_SetInteger2("game-save-last-slot", sslot.id().toInt(), SVF_WRITE_OVERRIDE); } - catch(Error const &er) + catch (Error const &er) { LOG_RES_WARNING("Error saving to save slot #%s:\n") << ::gaSaveSessionSlot << er.asText(); @@ -1408,7 +1431,7 @@ Hu_MenuCommand(MCMD_CLOSEFAST); - if(!IS_NETGAME) + if (!IS_NETGAME) { // Play an exit sound if it is enabled. S_LocalSound(randomQuitSound(), 0); @@ -1418,30 +1441,30 @@ case GA_LEAVEMAP: // Check that the map truly exists. - if(!P_MapExists(::nextMapUri.compose().toUtf8().constData())) + if (!P_MapExists(::nextMapUri.compose().toUtf8().constData())) { - ::nextMapUri = de::Uri(COMMON_GAMESESSION->episodeDef()->gets("startMap"), RC_NULL); + ::nextMapUri = de::makeUri(gfw_Session()->episodeDef()->gets("startMap")); } - COMMON_GAMESESSION->leaveMap(::nextMapUri, ::nextMapEntryPoint); + gfw_Session()->leaveMap(::nextMapUri, ::nextMapEntryPoint); break; case GA_RESTARTMAP: - COMMON_GAMESESSION->reloadMap(); + gfw_Session()->reloadMap(); break; case GA_MAPCOMPLETED: { // Leaving the current hub? dd_bool newHub = true; #if __JHEXEN__ - if(Record const *episodeDef = COMMON_GAMESESSION->episodeDef()) + if (Record const *episodeDef = gfw_Session()->episodeDef()) { defn::Episode epsd(*episodeDef); - Record const *currentHub = epsd.tryFindHubByMapId(COMMON_GAMESESSION->mapUri().compose()); + Record const *currentHub = epsd.tryFindHubByMapId(gfw_Session()->mapUri().compose()); newHub = (!currentHub || currentHub != epsd.tryFindHubByMapId(::nextMapUri.compose())); } #endif - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { ST_CloseAll(i, true/*fast*/); // hide any HUDs left open Player_LeaveMap(&players[i], newHub); // take away cards and stuff @@ -1451,13 +1474,13 @@ SN_StopAllSequences(); #endif - if(!IS_DEDICATED) + if (!IS_DEDICATED) { G_ResetViewEffects(); } // Go to an intermission? - if(intermissionEnabled()) + if (intermissionEnabled()) { S_StartMusic(intermissionMusic().toUtf8().constData(), true); S_PauseMusic(true); @@ -1483,7 +1506,7 @@ case GA_SCREENSHOT: { // Find an unused screenshot file name. - String fileName = COMMON_GAMESESSION->gameId() + "-"; + String fileName = gfw_GameId() + "-"; int const numPos = fileName.length(); for (int i = 0; i < 1e6; ++i) // Stop eventually... { @@ -1516,7 +1539,7 @@ static int rebornLoadConfirmed(msgresponse_t response, int, void *) { - if(response == MSG_YES) + if (response == MSG_YES) { G_SetGameAction(GA_RESTARTMAP); } @@ -1536,23 +1559,23 @@ static void rebornPlayers() { // Reborns are impossible if no game session is in progress. - if(!COMMON_GAMESESSION->hasBegun()) return; + if (!gfw_Session()->hasBegun()) return; // ...or if no map is currently loaded. - if(G_GameState() != GS_MAP) return; + if (G_GameState() != GS_MAP) return; - if(!IS_NETGAME && P_CountPlayersInGame(LocalOnly) == 1) + if (!IS_NETGAME && P_CountPlayersInGame(LocalOnly) == 1) { - if(Player_WaitingForReborn(&players[0])) + if (Player_WaitingForReborn(&players[0])) { // Are we still awaiting a response to a previous confirmation? - if(Hu_IsMessageActiveWithCallback(rebornLoadConfirmed)) + if (Hu_IsMessageActiveWithCallback(rebornLoadConfirmed)) return; // Do we need user confirmation? - if(COMMON_GAMESESSION->progressRestoredOnReload() && cfg.common.confirmRebornLoad) + if (gfw_Session()->progressRestoredOnReload() && cfg.common.confirmRebornLoad) { S_LocalSound(SFX_REBORNLOAD_CONFIRM, NULL); - AutoStr *msg = Str_Appendf(AutoStr_NewStd(), REBORNLOAD_CONFIRM, COMMON_GAMESESSION->userDescription().toUtf8().constData()); + AutoStr *msg = Str_Appendf(AutoStr_NewStd(), REBORNLOAD_CONFIRM, gfw_Session()->userDescription().toUtf8().constData()); Hu_MsgStart(MSG_YESNO, Str_Text(msg), rebornLoadConfirmed, 0, 0); return; } @@ -1562,23 +1585,23 @@ return; } - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { player_t *plr = &players[i]; - if(Player_WaitingForReborn(plr)) + if (Player_WaitingForReborn(plr)) { P_RebornPlayerInMultiplayer(i); } // Player has left? - if((int)plr->playerState == PST_GONE) + if ((int)plr->playerState == PST_GONE) { plr->playerState = PST_REBORN; ddplayer_t *ddplr = plr->plr; - if(mobj_t *plmo = ddplr->mo) + if (mobj_t *plmo = ddplr->mo) { - if(!IS_CLIENT) + if (!IS_CLIENT) { P_SpawnTeleFog(plmo->origin[VX], plmo->origin[VY], plmo->angle + ANG180); } @@ -1607,11 +1630,11 @@ Hu_MenuTicker(ticLength); Hu_MsgTicker(); - if(IS_CLIENT && !Get(DD_GAME_READY)) return; + if (IS_CLIENT && !Get(DD_GAME_READY)) return; runGameAction(); - if(!G_QuitInProgress()) + if (!G_QuitInProgress()) { // Do player reborns if needed. rebornPlayers(); @@ -1619,10 +1642,10 @@ // Update the viewer's look angle //G_LookAround(CONSOLEPLAYER); - if(!IS_CLIENT) + if (!IS_CLIENT) { // Enable/disable sending of frames (delta sets) to clients. - Set(DD_ALLOW_FRAMES, G_GameState() == GS_MAP); + Set(DD_SERVER_ALLOW_FRAMES, G_GameState() == GS_MAP); // Tell Doomsday when the game is paused (clients can't pause // the game.) @@ -1634,14 +1657,14 @@ } else { - if(!IS_CLIENT) + if (!IS_CLIENT) { // Disable sending of frames (delta sets) to clients. - Set(DD_ALLOW_FRAMES, false); + Set(DD_SERVER_ALLOW_FRAMES, false); } } - if(G_GameState() == GS_MAP && !IS_DEDICATED) + if (G_GameState() == GS_MAP && !IS_DEDICATED) { ST_Ticker(ticLength); } @@ -1650,14 +1673,14 @@ R_ResizeViewWindow(0); // The following is restricted to fixed 35 Hz ticks. - if(DD_IsSharpTick()) + if (DD_IsSharpTick()) { // Do main actions. - switch(G_GameState()) + switch (G_GameState()) { case GS_MAP: // Update in-map game status cvar. - if(oldGameState != GS_MAP) + if (oldGameState != GS_MAP) { Con_SetInteger2("game-state-map", 1, SVF_WRITE_OVERRIDE); } @@ -1668,7 +1691,7 @@ // Activate briefings once again (disabled for autostart or loading a saved game). briefDisabled = false; - if(IS_DEDICATED) + if (IS_DEDICATED) break; Hu_Ticker(); @@ -1679,7 +1702,7 @@ break; default: - if(oldGameState != G_GameState()) + if (oldGameState != G_GameState()) { // Update game status cvars. Con_SetInteger2("game-state-map", 0, SVF_WRITE_OVERRIDE); @@ -1691,13 +1714,13 @@ } // Players post-ticking. - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { Player_PostTick(&players[i]); } // Servers will have to update player information and do such stuff. - if(!IS_CLIENT) + if (!IS_CLIENT) { NetSv_Ticker(); } @@ -1759,7 +1782,7 @@ */ void G_PlayerReborn(int player) { - if(player < 0 || player >= MAXPLAYERS) + if (player < 0 || player >= MAXPLAYERS) return; // Wha? LOGDEV_MAP_NOTE("G_PlayerReborn: reseting player %i") << player; @@ -1799,7 +1822,7 @@ p->colorMap = cfg.playerColor[player]; p->class_ = P_ClassForPlayerWhenRespawning(player, false); #if __JHEXEN__ - if(p->class_ == PCLASS_FIGHTER && !IS_NETGAME) + if (p->class_ == PCLASS_FIGHTER && !IS_NETGAME) { // In Hexen single-player, the Fighter's default color is Yellow. p->colorMap = 2; @@ -1828,8 +1851,8 @@ p->weapons[WT_SECOND].owned = true; p->ammo[AT_CRYSTAL].owned = 50; - de::Uri const mapUri = COMMON_GAMESESSION->mapUri(); - if(secret || + de::Uri const mapUri = gfw_Session()->mapUri(); + if (secret || (mapUri.path() == "E1M9" || mapUri.path() == "E2M9" || mapUri.path() == "E3M9" || @@ -1840,7 +1863,7 @@ } #ifdef DENG2_DEBUG - for(int i = 0; i < NUM_WEAPON_TYPES; ++i) + for (int i = 0; i < NUM_WEAPON_TYPES; ++i) { LOGDEV_MAP_MSG("Player %i owns wpn %i: %i") << player << i << p->weapons[i].owned; } @@ -1854,7 +1877,7 @@ #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ // Reset maxammo. - for(int i = 0; i < NUM_AMMO_TYPES; ++i) + for (int i = 0; i < NUM_AMMO_TYPES; ++i) { p->ammo[i].max = maxAmmo[i]; } @@ -1880,10 +1903,10 @@ #if __JDOOM__ || __JDOOM64__ void G_QueueBody(mobj_t *mo) { - if(!mo) return; + if (!mo) return; // Flush an old corpse if needed. - if(bodyQueueSlot >= BODYQUEUESIZE) + if (bodyQueueSlot >= BODYQUEUESIZE) { P_MobjRemove(bodyQueue[bodyQueueSlot % BODYQUEUESIZE], false); } @@ -1893,62 +1916,19 @@ } #endif -int G_Ruleset_Skill() -{ - return COMMON_GAMESESSION->rules().skill; -} - -#if !__JHEXEN__ -byte G_Ruleset_Fast() -{ - return COMMON_GAMESESSION->rules().fast; -} -#endif - -byte G_Ruleset_Deathmatch() -{ - return COMMON_GAMESESSION->rules().deathmatch; -} - -byte G_Ruleset_NoMonsters() -{ - return COMMON_GAMESESSION->rules().noMonsters; -} - -#if __JHEXEN__ -byte G_Ruleset_RandomClasses() -{ - return COMMON_GAMESESSION->rules().randomClasses; -} -#endif - -#if !__JHEXEN__ -byte G_Ruleset_RespawnMonsters() -{ - return COMMON_GAMESESSION->rules().respawnMonsters; -} -#endif - -void G_Ruleset_UpdateDefaults() -{ -#if !__JHEXEN__ - defaultGameRules.fast = cfg.common.defaultRuleFastMonsters; -#endif -} - /** * Lookup the debriefing Finale for the current episode and map (if any). */ static Record const *finaleDebriefing() { - if(::briefDisabled) return 0; + if (::briefDisabled) return 0; #if __JHEXEN__ - if(::cfg.overrideHubMsg && G_GameState() == GS_MAP) + if (::cfg.overrideHubMsg && G_GameState() == GS_MAP) { - defn::Episode epsd(*COMMON_GAMESESSION->episodeDef()); - Record const *currentHub = epsd.tryFindHubByMapId(COMMON_GAMESESSION->mapUri().compose()); - if(!currentHub || currentHub != epsd.tryFindHubByMapId(::nextMapUri.compose())) + defn::Episode epsd(*gfw_Session()->episodeDef()); + Record const *currentHub = epsd.tryFindHubByMapId(gfw_Session()->mapUri().compose()); + if (!currentHub || currentHub != epsd.tryFindHubByMapId(::nextMapUri.compose())) { return 0; } @@ -1956,22 +1936,22 @@ #endif // In a networked game the server will schedule the debrief. - if(IS_CLIENT || Get(DD_PLAYBACK)) return 0; + if (IS_CLIENT || Get(DD_PLAYBACK)) return 0; // If we're already in the INFINE state, don't start a finale. - if(G_GameState() == GS_INFINE) return 0; + if (G_GameState() == GS_INFINE) return 0; // Is there such a finale definition? - return Defs().finales.tryFind("after", COMMON_GAMESESSION->mapUri().compose()); + return Defs().finales.tryFind("after", gfw_Session()->mapUri().compose()); } /// @todo common::GameSession should handle this -ds void G_IntermissionDone() { // We have left Intermission, however if there is an InFine for debriefing we should run it now. - if(Record const *finale = finaleDebriefing()) + if (Record const *finale = finaleDebriefing()) { - if(G_StartFinale(finale->gets("script").toUtf8().constData(), 0, FIMODE_AFTER, 0)) + if (G_StartFinale(finale->gets("script").toUtf8().constData(), 0, FIMODE_AFTER, 0)) { // The GA_ENDDEBRIEFING action is taken after the debriefing stops. return; @@ -1985,7 +1965,7 @@ FI_StackClear(); // Has the player completed the game? - if(::nextMapUri.isEmpty()) + if (::nextMapUri.isEmpty()) { // Victorious! G_SetGameAction(GA_VICTORY); @@ -1998,21 +1978,21 @@ String G_DefaultGameStateFolderUserDescription(String const &saveName, bool autogenerate) { // If the slot is already in use then choose existing description. - if(!saveName.isEmpty()) + if (!saveName.isEmpty()) { - String const existing = COMMON_GAMESESSION->savedUserDescription(saveName); - if(!existing.isEmpty()) return existing; + String const existing = gfw_Session()->savedUserDescription(saveName); + if (!existing.isEmpty()) return existing; } - if(!autogenerate) return ""; + if (!autogenerate) return ""; // Autogenerate a suitable description. String description; // Include the source file name, for custom maps. - de::Uri const mapUri = COMMON_GAMESESSION->mapUri(); + de::Uri const mapUri = gfw_Session()->mapUri(); String mapUriAsText = mapUri.compose(); - if(P_MapIsCustom(mapUriAsText.toUtf8().constData())) + if (P_MapIsCustom(mapUriAsText.toUtf8().constData())) { String const mapSourcePath(Str_Text(P_MapSourceFile(mapUriAsText.toUtf8().constData()))); description += mapSourcePath.fileNameWithoutExtension() + ":"; @@ -2022,7 +2002,7 @@ String mapTitle = G_MapTitle(mapUri); // No map title? Use the identifier. (Some tricksy modders provide us with an empty title). /// @todo Move this logic engine-side. - if(mapTitle.isEmpty() || mapTitle.at(0) == ' ') + if (mapTitle.isEmpty() || mapTitle.at(0) == ' ') { mapTitle = mapUri.path(); } @@ -2044,13 +2024,13 @@ String G_EpisodeTitle(String episodeId) { String title; - if(Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) + if (Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) { title = episodeDef->gets("title"); // Perhaps the title string is a reference to a Text definition? int textIdx = Defs().getTextNum(title.toUtf8().constData()); - if(textIdx >= 0) + if (textIdx >= 0) { title = Defs().text[textIdx].text; // Yes, use the resolved text string. } @@ -2061,20 +2041,20 @@ uint G_MapNumberFor(de::Uri const &mapUri) { String path = mapUri.path(); - if(!path.isEmpty()) + if (!path.isEmpty()) { #if __JDOOM__ || __JHERETIC__ # if __JDOOM__ - if(gameModeBits & (GM_ANY_DOOM | ~GM_DOOM_CHEX)) + if (gameModeBits & (GM_ANY_DOOM | ~GM_DOOM_CHEX)) # endif { - if(path.at(0).toLower() == 'e' && path.at(2).toLower() == 'm') + if (path.at(0).toLower() == 'e' && path.at(2).toLower() == 'm') { return path.substr(3).toInt() - 1; } } #endif - if(path.beginsWith("map", Qt::CaseInsensitive)) + if (path.beginsWith("map", String::CaseInsensitive)) { return path.substr(3).toInt() - 1; } @@ -2084,7 +2064,7 @@ AutoStr *G_CurrentMapUriPath() { - return AutoStr_FromTextStd(COMMON_GAMESESSION->mapUri().path().toStringRef().toUtf8().constData()); + return AutoStr_FromTextStd(gfw_Session()->mapUri().path().toStringRef().toUtf8().constData()); } @@ -2096,7 +2076,7 @@ mapId = String("map%1").arg(map+1, 2, 10, QChar('0')); DENG2_UNUSED(episode); #elif __JDOOM__ - if(gameModeBits & GM_ANY_DOOM2) + if (gameModeBits & GM_ANY_DOOM2) mapId = String("map%1").arg(map+1, 2, 10, QChar('0')); else mapId = String("e%1m%2").arg(episode+1).arg(map+1); @@ -2109,15 +2089,15 @@ return de::Uri("Maps", mapId); } -Record const &G_MapInfoForMapUri(de::Uri const &mapUri) +Record &G_MapInfoForMapUri(de::Uri const &mapUri) { // Is there a MapInfo definition for the given URI? - if(Record const *def = Defs().mapInfos.tryFind("id", mapUri.compose())) + if (Record *def = Defs().mapInfos.tryFind("id", mapUri.compose())) { return *def; } // Is there is a default definition (for all maps)? - if(Record const *def = Defs().mapInfos.tryFind("id", de::Uri("Maps", Path("*")).compose())) + if (Record *def = Defs().mapInfos.tryFind("id", de::Uri("Maps", Path("*")).compose())) { return *def; } @@ -2125,7 +2105,7 @@ { static Record fallbackDef; static bool needInitFallbackDef = true; - if(needInitFallbackDef) + if (needInitFallbackDef) { needInitFallbackDef = false; defn::MapInfo(fallbackDef).resetToDefaults(); @@ -2141,17 +2121,17 @@ // Perhaps the title string is a reference to a Text definition? int textIdx = Defs().getTextNum(title.toUtf8().constData()); - if(textIdx >= 0) + if (textIdx >= 0) { title = Defs().text[textIdx].text; // Yes, use the resolved text string. } // Skip the "ExMx" part, if present. int idSuffixAt = title.indexOf(':'); - if(idSuffixAt >= 0) + if (idSuffixAt >= 0) { int subStart = idSuffixAt + 1; - while(subStart < title.length() && title.at(subStart).isSpace()) { subStart++; } + while (subStart < title.length() && title.at(subStart).isSpace()) { subStart++; } return title.substr(subStart); } @@ -2164,15 +2144,15 @@ // Perhaps a MapInfo definition exists for the map? String author = G_MapInfoForMapUri(mapUri).gets("author"); - if(!author.isEmpty()) + if (!author.isEmpty()) { // Should we suppress the author? /// @todo Do not do this here. GameInfo gameInfo; DD_GameInfo(&gameInfo); - if(supressGameAuthor || P_MapIsCustom(mapUri.compose().toUtf8().constData())) + if (supressGameAuthor || P_MapIsCustom(mapUri.compose().toUtf8().constData())) { - if(!author.compareWithoutCase(Str_Text(gameInfo.author))) + if (!author.compareWithoutCase(Str_Text(gameInfo.author))) return ""; } } @@ -2182,13 +2162,13 @@ de::Uri G_MapTitleImage(de::Uri const &mapUri) { - return de::Uri(G_MapInfoForMapUri(mapUri).gets("titleImage"), RC_NULL); + return de::makeUri(G_MapInfoForMapUri(mapUri).gets("titleImage")); } String G_MapDescription(String episodeId, de::Uri const &mapUri) { Block mapUriUtf8 = mapUri.compose().toUtf8(); - if(!P_MapExists(mapUriUtf8.constData())) + if (!P_MapExists(mapUriUtf8.constData())) { return String("Unknown map (Episode: ") + episodeId + ", Uri: " + mapUri + ")"; } @@ -2197,14 +2177,14 @@ QTextStream os(&desc); String const title = G_MapTitle(mapUri); - if(!title.isEmpty()) + if (!title.isEmpty()) { os << "Map: " DE2_ESC(i) DE2_ESC(b) << title << DE2_ESC(.) << " (Uri: " << mapUri; - if(Record const *rec = Defs().episodes.tryFind("id", episodeId)) + if (Record const *rec = Defs().episodes.tryFind("id", episodeId)) { - if(Record const *mgNodeDef = defn::Episode(*rec).tryFindMapGraphNode(mapUri.compose())) + if (Record const *mgNodeDef = defn::Episode(*rec).tryFindMapGraphNode(mapUri.compose())) { os << ", warp: " << String::number(mgNodeDef->geti("warpNumber")); } @@ -2214,7 +2194,7 @@ } String const author = G_MapAuthor(mapUri, P_MapIsCustom(mapUriUtf8.constData())); - if(!author.isEmpty()) + if (!author.isEmpty()) { os << "\n - Author: " DE2_ESC(i) << author; } @@ -2240,7 +2220,7 @@ G_ChangeGameState(GS_WAITING); - if(!aborted && singledemo) + if (!aborted && singledemo) { // Playback ended normally. G_SetGameAction(GA_QUIT); @@ -2249,22 +2229,22 @@ G_SetGameAction(GA_NONE); - if(IS_NETGAME && IS_CLIENT) + if (IS_NETGAME && IS_CLIENT) { // Restore normal game state. - GameRuleset newRules(COMMON_GAMESESSION->rules()); - newRules.deathmatch = false; - newRules.noMonsters = false; + GameRules newRules(gfw_Session()->rules()); + GameRules_Set(newRules, deathmatch, 0); + GameRules_Set(newRules, noMonsters, false); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - newRules.respawnMonsters = false; + GameRules_Set(newRules, respawnMonsters, false); #endif #if __JHEXEN__ - newRules.randomClasses = false; + GameRules_Set(newRules, randomClasses, false); #endif - COMMON_GAMESESSION->applyNewRules(newRules); + gfw_Session()->applyNewRules(newRules); } - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { ST_CloseAll(i, true/*fast*/); } @@ -2274,7 +2254,7 @@ static int quitGameConfirmed(msgresponse_t response, int /*userValue*/, void * /*userPointer*/) { - if(response == MSG_YES) + if (response == MSG_YES) { G_SetGameAction(GA_QUIT); } @@ -2283,9 +2263,9 @@ void G_QuitGame() { - if(G_QuitInProgress()) return; + if (G_QuitInProgress()) return; - if(Hu_IsMessageActiveWithCallback(quitGameConfirmed)) + if (Hu_IsMessageActiveWithCallback(quitGameConfirmed)) { // User has re-tried to quit with "quit" when the question is already on // the screen. Apparently we should quit... @@ -2308,7 +2288,7 @@ { DENG2_UNUSED3(src, argc, argv); - if(!COMMON_GAMESESSION->isLoadingPossible()) return false; + if (!gfw_Session()->isLoadingPossible()) return false; DD_Execute(true, "menu loadgame"); return true; } @@ -2317,14 +2297,14 @@ { DENG2_UNUSED3(src, argc, argv); - if(!COMMON_GAMESESSION->isSavingPossible()) return false; + if (!gfw_Session()->isSavingPossible()) return false; DD_Execute(true, "menu savegame"); return true; } static int endSessionConfirmed(msgresponse_t response, int /*userValue*/, void * /*context*/) { - if(response == MSG_YES) + if (response == MSG_YES) { DD_Execute(true, "endgame confirm"); } @@ -2335,17 +2315,17 @@ { DENG2_UNUSED3(src, argc, argv); - if(G_QuitInProgress()) return true; + if (G_QuitInProgress()) return true; - if(IS_NETGAME && IS_SERVER) + if (IS_NETGAME && IS_SERVER) { LOG_NET_ERROR("Cannot end a networked game session. Stop the server instead"); return false; } - if(!COMMON_GAMESESSION->hasBegun()) + if (!gfw_Session()->hasBegun()) { - if(IS_NETGAME && IS_CLIENT) + if (IS_NETGAME && IS_CLIENT) { LOG_NET_ERROR("%s") << ENDNOGAME; } @@ -2358,15 +2338,15 @@ // Is user confirmation required? (Never if this is a network server). bool const confirmed = (argc >= 2 && !qstricmp(argv[argc-1], "confirm")); - if(confirmed || (IS_NETGAME && IS_SERVER)) + if (confirmed || (IS_NETGAME && IS_SERVER)) { - if(IS_NETGAME && IS_CLIENT) + if (IS_NETGAME && IS_CLIENT) { DD_Executef(false, "net disconnect"); } else { - COMMON_GAMESESSION->endAndBeginTitle(); + gfw_Session()->endAndBeginTitle(); } } else @@ -2381,7 +2361,7 @@ { String *slotId = static_cast(context); DENG2_ASSERT(slotId != 0); - if(response == MSG_YES) + if (response == MSG_YES) { DD_Executef(true, "loadgame %s confirm", slotId->toUtf8().constData()); } @@ -2395,22 +2375,22 @@ bool const confirmed = (argc == 3 && !qstricmp(argv[2], "confirm")); - if(G_QuitInProgress()) return false; - if(!COMMON_GAMESESSION->isLoadingPossible()) return false; + if (G_QuitInProgress()) return false; + if (!gfw_Session()->isLoadingPossible()) return false; - if(IS_NETGAME) + if (IS_NETGAME) { S_LocalSound(SFX_QUICKLOAD_PROMPT, nullptr); Hu_MsgStart(MSG_ANYKEY, QLOADNET, nullptr, 0, nullptr); return false; } - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) { - if(sslot->isLoadable()) + if (sslot->isLoadable()) { // A known used slot identifier. - if(confirmed || !cfg.common.confirmQuickGameSave) + if (confirmed || !cfg.common.confirmQuickGameSave) { // Try to schedule a GA_LOADSESSION action. S_LocalSound(SFX_MENU_ACCEPT, nullptr); @@ -2418,12 +2398,12 @@ } // Are we already awaiting a reponse of some kind? - if(Hu_IsMessageActive()) return false; + if (Hu_IsMessageActive()) return false; S_LocalSound(SFX_QUICKLOAD_PROMPT, nullptr); // Compose the confirmation message. - String const &existingDescription = COMMON_GAMESESSION->savedUserDescription(sslot->saveName()); + String const &existingDescription = gfw_Session()->savedUserDescription(sslot->saveName()); AutoStr *msg = Str_Appendf(AutoStr_NewStd(), QLPROMPT, sslot->id().toUtf8().constData(), existingDescription.toUtf8().constData()); @@ -2433,14 +2413,14 @@ } } - if(!qstricmp(argv[1], "quick") || !qstricmp(argv[1], "")) + if (!qstricmp(argv[1], "quick") || !qstricmp(argv[1], "")) { S_LocalSound(SFX_QUICKLOAD_PROMPT, nullptr); Hu_MsgStart(MSG_ANYKEY, QSAVESPOT, nullptr, 0, nullptr); return true; } - if(!G_SaveSlots().has(argv[1])) + if (!G_SaveSlots().has(argv[1])) { LOG_SCR_WARNING("Failed to determine save slot from \"%s\"") << argv[1]; } @@ -2450,7 +2430,7 @@ // Reasoning: User attempted to load a named game-save however the name // specified didn't match anything known. Opening the load menu allows // the user to see the names of the known game-saves. - if(src == CMDS_CONSOLE) + if (src == CMDS_CONSOLE) { LOG_SCR_MSG("Opening Load Game menu..."); DD_Execute(true, "menu loadgame"); @@ -2477,7 +2457,7 @@ { savesessionconfirmed_params_t *p = static_cast(context); DENG2_ASSERT(p != 0); - if(response == MSG_YES) + if (response == MSG_YES) { DD_Executef(true, "savegame %s \"%s\" confirm", p->slotId.toUtf8().constData(), p->userDescription.toUtf8().constData()); } @@ -2491,40 +2471,40 @@ bool const confirmed = (argc >= 3 && !qstricmp(argv[argc-1], "confirm")); - if(G_QuitInProgress()) return false; + if (G_QuitInProgress()) return false; - if(IS_CLIENT || IS_NETWORK_SERVER) + if (IS_CLIENT || IS_NETWORK_SERVER) { LOG_ERROR("Network savegames are not supported at the moment"); return false; } player_t *player = &players[CONSOLEPLAYER]; - if(player->playerState == PST_DEAD || Get(DD_PLAYBACK)) + if (player->playerState == PST_DEAD || Get(DD_PLAYBACK)) { S_LocalSound(SFX_QUICKSAVE_PROMPT, nullptr); Hu_MsgStart(MSG_ANYKEY, SAVEDEAD, nullptr, 0, nullptr); return true; } - if(G_GameState() != GS_MAP) + if (G_GameState() != GS_MAP) { S_LocalSound(SFX_QUICKSAVE_PROMPT, nullptr); Hu_MsgStart(MSG_ANYKEY, SAVEOUTMAP, nullptr, 0, nullptr); return true; } - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) { - if(sslot->isUserWritable()) + if (sslot->isUserWritable()) { String userDescription; - if(argc >= 3 && qstricmp(argv[2], "confirm")) + if (argc >= 3 && qstricmp(argv[2], "confirm")) { userDescription = argv[2]; } - if(sslot->isUnused() || confirmed || !cfg.common.confirmQuickGameSave) + if (sslot->isUnused() || confirmed || !cfg.common.confirmQuickGameSave) { // Try to schedule a GA_SAVESESSION action. S_LocalSound(SFX_MENU_ACCEPT, nullptr); @@ -2532,12 +2512,12 @@ } // Are we already awaiting a reponse of some kind? - if(Hu_IsMessageActive()) return false; + if (Hu_IsMessageActive()) return false; S_LocalSound(SFX_QUICKSAVE_PROMPT, nullptr); // Compose the confirmation message. - String const existingDescription = COMMON_GAMESESSION->savedUserDescription(sslot->saveName()); + String const existingDescription = gfw_Session()->savedUserDescription(sslot->saveName()); AutoStr *msg = Str_Appendf(AutoStr_NewStd(), QSPROMPT, sslot->id().toUtf8().constData(), existingDescription.toUtf8().constData()); @@ -2553,7 +2533,7 @@ LOG_SCR_ERROR("Save slot '%s' is non-user-writable") << sslot->id(); } - if(!qstricmp(argv[1], "quick") || !qstricmp(argv[1], "")) + if (!qstricmp(argv[1], "quick") || !qstricmp(argv[1], "")) { // No quick-save slot has been nominated - allow doing so now. Hu_MenuCommand(MCMD_OPEN); @@ -2562,7 +2542,7 @@ return true; } - if(!G_SaveSlots().has(argv[1])) + if (!G_SaveSlots().has(argv[1])) { LOG_SCR_WARNING("Failed to determine save slot from \"%s\"") << argv[1]; } @@ -2581,7 +2561,7 @@ { String const *saveName = static_cast(context); DENG2_ASSERT(saveName != 0); - if(response == MSG_YES) + if (response == MSG_YES) { DD_Executef(true, "deletegamesave %s confirm", saveName->toUtf8().constData()); } @@ -2593,29 +2573,29 @@ { DENG2_UNUSED(src); - if(G_QuitInProgress()) return false; + if (G_QuitInProgress()) return false; bool const confirmed = (argc >= 3 && !qstricmp(argv[argc-1], "confirm")); - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(argv[1])) { - if(sslot->isUserWritable()) + if (sslot->isUserWritable()) { // A known slot identifier. - if(sslot->isUnused()) return false; + if (sslot->isUnused()) return false; - if(confirmed) + if (confirmed) { - COMMON_GAMESESSION->removeSaved(sslot->saveName()); + gfw_Session()->removeSaved(sslot->saveName()); } else { // Are we already awaiting a reponse of some kind? - if(Hu_IsMessageActive()) return false; + if (Hu_IsMessageActive()) return false; S_LocalSound(SFX_DELETESAVEGAME_CONFIRM, nullptr); // Compose the confirmation message. - String const existingDescription = COMMON_GAMESESSION->savedUserDescription(sslot->saveName()); + String const existingDescription = gfw_Session()->savedUserDescription(sslot->saveName()); AutoStr *msg = Str_Appendf(AutoStr_NewStd(), DELETESAVEGAME_CONFIRM, existingDescription.toUtf8().constData()); Hu_MsgStart(MSG_YESNO, Str_Text(msg), deleteGameStateFolderConfirmed, 0, new String(sslot->saveName())); } @@ -2655,10 +2635,10 @@ String exitName(argc > 1? argv[1] : "next"); // Only the server operator can end the map this way. - if(IS_NETGAME && !IS_NETWORK_SERVER) + if (IS_NETGAME && !IS_NETWORK_SERVER) return false; - if(G_GameState() != GS_MAP) + if (G_GameState() != GS_MAP) { #if __JHERETIC__ || __JHEXEN__ S_LocalSound(SFX_CHAT, nullptr); @@ -2668,8 +2648,33 @@ LOG_MAP_ERROR("Can only exit a map when in a game!"); return false; } + + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit(exitName)); + return true; +} + +D_CMD(SetDefaultSkill) +{ + DENG_UNUSED(src); - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit(exitName)); + if (argc != 2) + { + LOG_SCR_NOTE("Usage: %s (skill)") << argv[0]; + return true; + } + gfw_SetDefaultRule(skill, String(argv[1]).toInt() - 1); + if (gfw_DefaultRule(skill) < SM_BABY || gfw_DefaultRule(skill) >= NUM_SKILL_MODES) + { + gfw_SetDefaultRule(skill, SM_MEDIUM); + } + char const *skillNames[] = { + "Novice", + "Easy", + "Normal", + "Hard", + "Nightmare!" + }; + LOG_SCR_MSG("Default skill level for new games: %s") << skillNames[gfw_DefaultRule(skill)]; return true; } @@ -2688,41 +2693,45 @@ * changes to take effect. In single player this behavior is not necessary. * * @note "setmap" is an alias of "warp" + * + * @todo Clean up the map/episode selection logic... -jk */ D_CMD(WarpMap) { // Only server operators can warp maps in network games. /// @todo Implement vote or similar mechanics. - if(IS_NETGAME && !IS_NETWORK_SERVER) + if (IS_NETGAME && !IS_NETWORK_SERVER) { return false; } - if(argc == 1) + if (argc == 1) { LOG_SCR_NOTE("Usage: %s (episode) (map)") << argv[0]; return true; } // If a session is already in progress, the default episode is the current. - String episodeId = COMMON_GAMESESSION->episodeId(); + String episodeId = gfw_Session()->episodeId(); // Otherwise if only one playable episode is defined - select it. - if(episodeId.isEmpty() && PlayableEpisodeCount() == 1) + if (episodeId.isEmpty() && PlayableEpisodeCount() == 1) { episodeId = FirstPlayableEpisodeId(); } // Has an episode been specified? bool const haveEpisode = (argc >= 3); - if(haveEpisode) episodeId = argv[1]; + if (haveEpisode) + { + episodeId = argv[1]; // Catch invalid episodes. - if(Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) + if (Record const *episodeDef = Defs().episodes.tryFind("id", episodeId)) { // Ensure that the episode is playable. de::Uri startMap(episodeDef->gets("startMap"), RC_NULL); - if(!P_MapExists(startMap.compose().toUtf8().constData())) + if (!P_MapExists(startMap.compose().toUtf8().constData())) { LOG_SCR_NOTE("Failed to locate the start map for episode '%s'." " This episode is not playable") << episodeId; @@ -2734,31 +2743,41 @@ LOG_SCR_NOTE("Unknown episode '%s'") << episodeId; return false; } + } // The map. de::Uri mapUri; bool isNumber; int mapWarpNumber = String(argv[haveEpisode? 2 : 1]).toInt(&isNumber); - if(!isNumber) + if (!isNumber) + { + if (!haveEpisode) + { + // Implicit episode ID based on the map. + if (String implicitEpisodeId = Defs().findEpisode(argv[1])) { + episodeId = implicitEpisodeId; + } + } + // It must be a URI, then. Block rawMapUri = String(argv[haveEpisode? 2 : 1]).toUtf8(); char *args[1] = { const_cast(rawMapUri.constData()) }; mapUri = de::Uri::fromUserInput(args, 1); - if(mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); + if (mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); } else { // Map warp numbers must be translated in the context of an Episode. mapUri = TranslateMapWarpNumber(episodeId, mapWarpNumber); - if(mapUri.isEmpty()) + if (mapUri.isEmpty()) { // It may be a map that is outside the defined progression. bool isNumber; int episodeNum = episodeId.toInt(&isNumber); - if(isNumber) + if (isNumber) { mapUri = G_ComposeMapUri(episodeNum, mapWarpNumber > 0? mapWarpNumber - 1 : 0); } @@ -2766,10 +2785,10 @@ } // Catch invalid maps. - if(!P_MapExists(mapUri.compose().toUtf8().constData())) + if (!P_MapExists(mapUri.compose().toUtf8().constData())) { String msg("Unknown map"); - if(argc >= 3) msg += String(" \"%1 %2\"").arg(argv[1]).arg(argv[2]); + if (argc >= 3) msg += String(" \"%1 %2\"").arg(argv[1]).arg(argv[2]); else msg += String(" \"%1\"").arg(argv[1]); P_SetMessageWithFlags(&players[CONSOLEPLAYER], msg.toUtf8().constData(), LMF_NO_HIDE); @@ -2777,9 +2796,9 @@ } bool forceNewSession = (IS_NETGAME != 0); - if(COMMON_GAMESESSION->hasBegun()) + if (gfw_Session()->hasBegun()) { - if(COMMON_GAMESESSION->episodeId().compareWithoutCase(episodeId)) + if (gfw_Session()->episodeId().compareWithoutCase(episodeId)) { forceNewSession = true; } @@ -2787,7 +2806,7 @@ #if __JHEXEN__ // Hexen does not allow warping to the current map. - if(!forceNewSession && COMMON_GAMESESSION->mapUri() == mapUri) + if (!forceNewSession && gfw_Session()->mapUri() == mapUri) { P_SetMessageWithFlags(&players[CONSOLEPLAYER], "Cannot warp to the current map.", LMF_NO_HIDE); return false; @@ -2796,7 +2815,7 @@ // Close any left open UIs. /// @todo Still necessary here? - for(int i = 0; i < MAXPLAYERS; ++i) + for (int i = 0; i < MAXPLAYERS; ++i) { ST_CloseAll(i, true/*fast*/); } @@ -2806,27 +2825,26 @@ ::briefDisabled = true; // So be it. - if(!forceNewSession && COMMON_GAMESESSION->hasBegun()) + if (!forceNewSession && gfw_Session()->hasBegun()) { #if __JHEXEN__ ::nextMapUri = mapUri; ::nextMapEntryPoint = 0; G_SetGameAction(GA_LEAVEMAP); #else - G_SetGameActionNewSession(COMMON_GAMESESSION->rules(), COMMON_GAMESESSION->episodeId(), mapUri); + G_SetGameActionNewSession(gfw_Session()->rules(), gfw_Session()->episodeId(), mapUri); #endif } else { // If a session is already in progress then copy the rules from it. - GameRuleset rules = (COMMON_GAMESESSION->hasBegun()? COMMON_GAMESESSION->rules() - : defaultGameRules); + GameRules rules = (gfw_Session()->hasBegun() ? gfw_Session()->rules() : gfw_DefaultGameRules()); if (IS_DEDICATED) { // Why is this necessary to set here? Changing the rules in P_SetupMap() // causes the skill change to be effective on the _next_ map load, not // the current one. -jk - rules.skill = cfg.common.netSkill; + GameRules_Set(rules, skill, cfg.common.netSkill); } G_SetGameActionNewSession(rules, episodeId, mapUri); } @@ -2834,7 +2852,7 @@ // If the command source was "us" the game library then it was probably in // response to the local player entering a cheat event sequence, so set the // "CHANGING MAP" message. Somewhat of a kludge... - if(src == CMDS_GAME && !(IS_NETGAME && IS_SERVER)) + if (src == CMDS_GAME && !(IS_NETGAME && IS_SERVER)) { #if __JHEXEN__ char const *msg = TXT_CHEATWARP; @@ -2922,6 +2940,9 @@ {"player-weapon-bfg", READONLYCVAR, CVT_INT, &gsvWeapons[WT_SEVENTH], 0, 0, 0}, {"player-weapon-chainsaw", READONLYCVAR, CVT_INT, &gsvWeapons[WT_EIGHTH], 0, 0, 0}, {"player-weapon-sshotgun", READONLYCVAR, CVT_INT, &gsvWeapons[WT_NINETH], 0, 0, 0}, + #if __JDOOM64__ + {"player-weapon-unmaker", READONLYCVAR, CVT_INT, &gsvWeapons[WT_TENTH], 0, 0, 0}, + #endif // Keys {"player-key-blue", READONLYCVAR, CVT_INT, &gsvKeys[KT_BLUECARD], 0, 0, 0}, {"player-key-yellow", READONLYCVAR, CVT_INT, &gsvKeys[KT_YELLOWCARD], 0, 0, 0}, @@ -3030,7 +3051,7 @@ #if __JHEXEN__ // Fourth-weapon pieces: - for(int i = 0; i < WEAPON_FOURTH_PIECE_COUNT; ++i) + for (int i = 0; i < WEAPON_FOURTH_PIECE_COUNT; ++i) { Block const cvarName = String("player-weapon-piece%1").arg(i + 1).toUtf8(); C_VAR_INT(cvarName.constData(), &gsvWPieces[i], READONLYCVAR, 0, 1); @@ -3069,6 +3090,7 @@ C_CMD("togglegamma", "", CycleTextureGamma); C_CMD("warp", nullptr, WarpMap); /* Alias */ C_CMD("setmap", nullptr, WarpMap); + C_CMD("setdefaultskill", "i", SetDefaultSkill); registerGameStatusCVars(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_update.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_update.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/g_update.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/g_update.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -126,7 +126,7 @@ #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - S_MapMusic(COMMON_GAMESESSION->mapUri()); + S_MapMusic(gfw_Session()->mapUri()); #endif break; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/saveslots.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/saveslots.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/game/saveslots.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/game/saveslots.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -67,7 +67,7 @@ { status = Incompatible; // Game identity key missmatch? - if (!session->metadata().gets("gameIdentityKey").compareWithoutCase(COMMON_GAMESESSION->gameId())) + if (!session->metadata().gets("gameIdentityKey", "").compareWithoutCase(gfw_GameId())) { /// @todo Validate loaded add-ons and checksum the definition database. status = Loadable; // It's good! @@ -129,7 +129,7 @@ d->id = id; d->userWritable = userWritable; d->menuWidgetId = menuWidgetId; - d->savePath = GameSession::savePath() / saveName; + d->savePath = SaveGames::savePath() / saveName; if (d->savePath.fileNameExtension().isEmpty()) { d->savePath += ".save"; @@ -161,7 +161,7 @@ void SaveSlots::Slot::bindSaveName(String newName) { - String newPath = GameSession::savePath() / newName; + String newPath = SaveGames::savePath() / newName; if (newPath.fileNameExtension().isEmpty()) { newPath += ".save"; @@ -340,7 +340,7 @@ SaveSlots::Slot *SaveSlots::slotBySaveName(String const &name) const { - return d->slotBySavePath(GameSession::savePath() / name); + return d->slotBySavePath(SaveGames::savePath() / name); } SaveSlots::Slot *SaveSlots::slotBySavedUserDescription(String const &description) const @@ -349,7 +349,7 @@ { DENG2_FOR_EACH_CONST(Impl::Slots, i, d->sslots) { - if (!COMMON_GAMESESSION->savedUserDescription(i->second->saveName()) + if (!gfw_Session()->savedUserDescription(i->second->saveName()) .compareWithoutCase(description)) { return i->second; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/gl_drawpatch.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/gl_drawpatch.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/gl_drawpatch.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/gl_drawpatch.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -26,7 +26,7 @@ void GL_DrawPatch(patchid_t id, Vector2i const &origin, int alignFlags, int patchFlags) { if(!id) return; - if(DD_GetInteger(DD_NOVIDEO) || DD_GetInteger(DD_DEDICATED)) return; + if(DD_GetInteger(DD_NOVIDEO)) return; patchinfo_t info; if(!R_GetPatchInfo(id, &info)) return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/gl_special.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/gl_special.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/gl_special.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/gl_special.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,17 @@ +/** @file + * + * @authors Copyright (c) 2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/automapstyle.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/automapstyle.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/automapstyle.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/automapstyle.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -74,7 +74,7 @@ } void newLineInfo(int reqAutomapFlags, int reqSpecial, int reqSided, int reqNotFlagged, - float r, float g, float b, float a, blendmode_t blendmode, glowtype_t glowType, + float r, float g, float b, float a, blendmode_t /*blendmode*/, glowtype_t glowType, float glowStrength, float glowSize, dd_bool scaleGlowWithView) { DENG2_ASSERT(reqSpecial >= 0) @@ -104,7 +104,7 @@ info->glowStrength = de::clamp(0.f, glowStrength, 1.f); info->glowSize = glowSize; info->scaleWithView = scaleGlowWithView; - info->blendMode = blendmode; + //info->blendMode = blendmode; } }; @@ -178,7 +178,7 @@ d->mapObjectInfo[MOL_LINEDEF_UNSEEN].glow = GLOW_NONE; d->mapObjectInfo[MOL_LINEDEF_UNSEEN].glowStrength = 1; d->mapObjectInfo[MOL_LINEDEF_UNSEEN].glowSize = 10; - d->mapObjectInfo[MOL_LINEDEF_UNSEEN].blendMode = BM_NORMAL; + //d->mapObjectInfo[MOL_LINEDEF_UNSEEN].blendMode = BM_NORMAL; d->mapObjectInfo[MOL_LINEDEF_UNSEEN].scaleWithView = false; d->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[0] = 1; d->mapObjectInfo[MOL_LINEDEF_UNSEEN].rgba[1] = 1; @@ -187,7 +187,7 @@ d->mapObjectInfo[MOL_LINEDEF].glow = GLOW_NONE; d->mapObjectInfo[MOL_LINEDEF].glowStrength = 1; d->mapObjectInfo[MOL_LINEDEF].glowSize = 10; - d->mapObjectInfo[MOL_LINEDEF].blendMode = BM_NORMAL; + //d->mapObjectInfo[MOL_LINEDEF].blendMode = BM_NORMAL; d->mapObjectInfo[MOL_LINEDEF].scaleWithView = false; d->mapObjectInfo[MOL_LINEDEF].rgba[0] = 1; d->mapObjectInfo[MOL_LINEDEF].rgba[1] = 1; @@ -196,7 +196,7 @@ d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glow = GLOW_NONE; d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glowStrength = 1; d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].glowSize = 10; - d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].blendMode = BM_NORMAL; + //d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].blendMode = BM_NORMAL; d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].scaleWithView = false; d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[0] = 1; d->mapObjectInfo[MOL_LINEDEF_TWOSIDED].rgba[1] = 1; @@ -205,7 +205,7 @@ d->mapObjectInfo[MOL_LINEDEF_FLOOR].glow = GLOW_NONE; d->mapObjectInfo[MOL_LINEDEF_FLOOR].glowStrength = 1; d->mapObjectInfo[MOL_LINEDEF_FLOOR].glowSize = 10; - d->mapObjectInfo[MOL_LINEDEF_FLOOR].blendMode = BM_NORMAL; + //d->mapObjectInfo[MOL_LINEDEF_FLOOR].blendMode = BM_NORMAL; d->mapObjectInfo[MOL_LINEDEF_FLOOR].scaleWithView = false; d->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[0] = 1; d->mapObjectInfo[MOL_LINEDEF_FLOOR].rgba[1] = 1; @@ -214,7 +214,7 @@ d->mapObjectInfo[MOL_LINEDEF_CEILING].glow = GLOW_NONE; d->mapObjectInfo[MOL_LINEDEF_CEILING].glowStrength = 1; d->mapObjectInfo[MOL_LINEDEF_CEILING].glowSize = 10; - d->mapObjectInfo[MOL_LINEDEF_CEILING].blendMode = BM_NORMAL; + //d->mapObjectInfo[MOL_LINEDEF_CEILING].blendMode = BM_NORMAL; d->mapObjectInfo[MOL_LINEDEF_CEILING].scaleWithView = false; d->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[0] = 1; d->mapObjectInfo[MOL_LINEDEF_CEILING].rgba[1] = 1; @@ -279,7 +279,7 @@ setObjectSvg(AMO_THINGPLAYER, VG_ARROW); float rgb[3]; - AM_GetMapColor(rgb, cfg.common.automapL0, GRAYS+3, customPal); + AM_GetMapColor(rgb, cfg.common.automapL0, UNWALLCOLORS, customPal); setObjectColorAndOpacity(AMO_UNSEENLINE, rgb[0], rgb[1], rgb[2], 1); AM_GetMapColor(rgb, cfg.common.automapL1, WALLCOLORS, customPal); @@ -437,8 +437,8 @@ void AM_GetMapColor(float *rgb, float const *uColor, int palidx, dd_bool customPal) { - if((!customPal && !cfg.common.automapCustomColors) || - (customPal && cfg.common.automapCustomColors != 2)) + if ((!customPal && !cfg.common.automapCustomColors) || + (customPal && cfg.common.automapCustomColors != 2)) { R_GetColorPaletteRGBf(0, palidx, rgb, false); return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/hudwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/hudwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/hudwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/hudwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -31,7 +31,7 @@ { uiwidgetid_t id = 0; ///< Unique identifier associated with this widget. dint alignFlags = ALIGN_TOPLEFT; ///< @ref alignmentFlags - Size2Raw maxSize; ///< Maximum size of this widget in pixels. + Size2Raw maxSize{}; ///< Maximum size of this widget in pixels. Rect *geometry = Rect_New(); ///< Geometry of this widget in pixels. dint player = 0; ///< Local player number associated with this widget. fontid_t font = 0; ///< Current font used for text child objects of this widget. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/automapwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/automapwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/automapwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/automapwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include "dmu_lib.h" @@ -58,10 +59,10 @@ { player_t *plr; dint obType; ///< The type of object to draw. @c -1= only line specials. - dd_bool addToLists; + dd_bool glowOnly; + dglprimtype_t primType; }; -uiautomap_rendstate_t rs; - +static uiautomap_rendstate_t rs; static dbyte freezeMapRLs; // if -1 no background image will be drawn. @@ -95,10 +96,10 @@ { DENG2_ASSERT(aabb); if (point.x < aabb[BOXLEFT ]) aabb[BOXLEFT ] = point.x; - else if(point.x > aabb[BOXRIGHT ]) aabb[BOXRIGHT ] = point.x; + else if (point.x > aabb[BOXRIGHT ]) aabb[BOXRIGHT ] = point.x; if (point.y < aabb[BOXBOTTOM]) aabb[BOXBOTTOM] = point.y; - else if(point.y > aabb[BOXTOP ]) aabb[BOXTOP ] = point.y; + else if (point.y > aabb[BOXTOP ]) aabb[BOXTOP ] = point.y; } static dd_bool interceptEdge(coord_t point[2], coord_t const startA[2], @@ -106,7 +107,7 @@ { coord_t directionA[2]; V2d_Subtract(directionA, endA, startA); - if(V2d_PointOnLineSide(point, startA, directionA) >= 0) + if (V2d_PointOnLineSide(point, startA, directionA) >= 0) { coord_t directionB[2]; V2d_Subtract(directionB, endB, startB); @@ -140,9 +141,9 @@ // Trace a vector from the view location to the marked point and intercept // vs the edges of the rotated view window. - if(!interceptEdge(pointV1, topLeftV1, bottomLeftV1, viewPointV1, pointV1)) + if (!interceptEdge(pointV1, topLeftV1, bottomLeftV1, viewPointV1, pointV1)) interceptEdge(pointV1, bottomRightV1, topRightV1, viewPointV1, pointV1); - if(!interceptEdge(pointV1, topRightV1, topLeftV1, viewPointV1, pointV1)) + if (!interceptEdge(pointV1, topRightV1, topLeftV1, viewPointV1, pointV1)) interceptEdge(pointV1, bottomLeftV1, bottomRightV1, viewPointV1, pointV1); return Vector2d(pointV1); @@ -176,7 +177,7 @@ #endif }; - if(!IS_NETGAME) return WHITE; + if (!IS_NETGAME) return WHITE; return playerColors[cfg.playerColor[de::max(0, consoleNum) % MAXPLAYERS]]; } @@ -185,10 +186,10 @@ { DENG2_ASSERT(consoleNum >= 0 && consoleNum < MAXPLAYERS); player_t *player = &players[consoleNum]; - if(!player->plr->inGame) return; + if (!player->plr->inGame) return; mobj_t *plrMob = player->plr->mo; - if(!plrMob) return; + if (!plrMob) return; coord_t origin[3]; Mobj_OriginSmoothed(plrMob, origin); dfloat const angle = Mobj_AngleSmoothed(plrMob) / (dfloat) ANGLE_MAX * 360; /* $unifiedangles */ @@ -197,7 +198,7 @@ dfloat opacity = cfg.common.automapLineAlpha * uiRendState->pageAlpha; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - if(player->powers[PT_INVISIBILITY]) + if (player->powers[PT_INVISIBILITY]) opacity *= .125f; #endif @@ -206,13 +207,15 @@ } } // namespace internal -using namespace internal; +using namespace ::internal; DENG2_PIMPL(AutomapWidget) { AutomapStyle *style = nullptr; - DGLuint lists[NUM_MAP_OBJECTLISTS]; ///< Each list contains one or more of given type of automap wi. + float pixelRatio = 1.f; // DisplayMode.PIXEL_RATIO + + //DGLuint lists[NUM_MAP_OBJECTLISTS]; ///< Each list contains one or more of given type of automap wi. bool needBuildLists = false; ///< @c true= force a rebuild of all lists. dint flags = 0; @@ -224,9 +227,9 @@ bool forceMaxScale = false; ///< If the map is currently in forced max zoom mode. dfloat priorToMaxScale = 0; ///< Viewer scale before entering maxScale mode. - dfloat minScale = 0; - dfloat scaleMTOF = 0; ///< Used by MTOF to scale from map-to-frame-buffer coords. - dfloat scaleFTOM = 0; ///< Used by FTOM to scale from frame-buffer-to-map coords (=1/scaleMTOF). + dfloat minScale = 1.f; + dfloat scaleMTOF = 1.f; ///< Used by MTOF to scale from map-to-frame-buffer coords. + dfloat scaleFTOM = 1.f; ///< Used by FTOM to scale from frame-buffer-to-map coords (=1/scaleMTOF). coord_t bounds[4]; ///< Map space bounds: @@ -239,10 +242,10 @@ dfloat viewTimer = 0; coord_t maxViewPositionDelta = 128; - Vector2d viewPL; // For the parallax layer. +// Vector2d viewPL; // For the parallax layer. // View frame scale: - dfloat viewScale = 0, targetViewScale = 0, oldViewScale = 1; + dfloat viewScale = 1, targetViewScale = 1, oldViewScale = 1; dfloat viewScaleTimer = 0; bool needViewScaleUpdate = false; @@ -266,9 +269,17 @@ Impl(Public *i) : Base(i) { - de::zap(lists); - de::zap(bounds); - de::zap(viewAABB); + using namespace de; + + zap(bounds); + zap(viewAABB); + + auto &ds = ScriptSystem::get(); + + if (ds.nativeModuleExists("DisplayMode")) + { + pixelRatio = ds["DisplayMode"].getf("PIXEL_RATIO"); + } } ~Impl() @@ -323,67 +334,71 @@ static void drawLine2(Vector2d const &from, Vector2d const &to, Vector3f const &color, dfloat opacity, glowtype_t glowType, dfloat glowStrength, dfloat glowSize, dd_bool glowOnly, dd_bool scaleGlowWithView, dd_bool caps, - blendmode_t blend, dd_bool drawNormal, dd_bool addToLists) + /*blendmode_t blend, */dd_bool drawNormal) { opacity *= uiRendState->pageAlpha; Vector2d const unit = (to - from).normalize(); Vector2d const normal(unit.y, -unit.x); - if(de::abs(unit.length()) <= 0) return; + if (de::abs(unit.length()) <= 0) return; + + //DGL_BlendMode(blend); // Is this a glowing line? - if(glowType != GLOW_NONE) + if (glowOnly && glowType != GLOW_NONE) { - dint const tex = Get(DD_DYNLIGHT_TEXTURE); + //dint const tex = Get(DD_DYNLIGHT_TEXTURE); // Scale line thickness relative to zoom level? dfloat thickness; - if(scaleGlowWithView) + if (scaleGlowWithView) thickness = cfg.common.automapDoorGlow * 2.5f + 3; else thickness = glowSize; + DENG_ASSERT(rs.primType == DGL_QUADS); + // Draw a "cap" at the start of the line? - if(caps) + if (caps) { Vector2f const v1 = from - unit * thickness + normal * thickness; Vector2f const v2 = from + normal * thickness; Vector2f const v3 = from - normal * thickness; Vector2f const v4 = from - unit * thickness - normal * thickness; - if(!addToLists) + //if (!addToLists) { - DGL_Bind(tex); + //DGL_Bind(tex); DGL_Color4f(color.x, color.y, color.z, glowStrength * opacity); - DGL_BlendMode(blend); + //DGL_BlendMode(blend); } - DGL_Begin(DGL_QUADS); - DGL_TexCoord2f(0, 0, 0); - DGL_TexCoord2f(1, v1.x, v1.y); - DGL_Vertex2f(v1.x, v1.y); - - DGL_TexCoord2f(0, .5f, 0); - DGL_TexCoord2f(1, v2.x, v2.y); - DGL_Vertex2f(v2.x, v2.y); - - DGL_TexCoord2f(0, .5f, 1); - DGL_TexCoord2f(1, v3.x, v3.y); - DGL_Vertex2f(v3.x, v3.y); - - DGL_TexCoord2f(0, 0, 1); - DGL_TexCoord2f(1, v4.x, v4.y); - DGL_Vertex2f(v4.x, v4.y); - DGL_End(); +// DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, 0); + DGL_TexCoord2f(1, v1.x, v1.y); + DGL_Vertex2f(v1.x, v1.y); + + DGL_TexCoord2f(0, .5f, 0); + DGL_TexCoord2f(1, v2.x, v2.y); + DGL_Vertex2f(v2.x, v2.y); + + DGL_TexCoord2f(0, .5f, 1); + DGL_TexCoord2f(1, v3.x, v3.y); + DGL_Vertex2f(v3.x, v3.y); + + DGL_TexCoord2f(0, 0, 1); + DGL_TexCoord2f(1, v4.x, v4.y); + DGL_Vertex2f(v4.x, v4.y); +// DGL_End(); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + //if (!addToLists) + //DGL_BlendMode(BM_NORMAL); } // The middle part of the line. - switch(glowType) + switch (glowType) { case GLOW_BOTH: { Vector2f const v1 = from + normal * thickness; @@ -391,190 +406,193 @@ Vector2f const v3 = to - normal * thickness; Vector2f const v4 = from - normal * thickness; - if(!addToLists) + //if (!addToLists) { - DGL_Bind(tex); + //DGL_Bind(tex); DGL_Color4f(color.x, color.y, color.z, glowStrength * opacity); - DGL_BlendMode(blend); + //DGL_BlendMode(blend); } - DGL_Begin(DGL_QUADS); - DGL_TexCoord2f(0, .5f, 0); - DGL_TexCoord2f(1, v1.x, v1.y); - DGL_Vertex2f(v1.x, v1.y); - - DGL_TexCoord2f(0, .5f, 0); - DGL_TexCoord2f(1, v2.x, v2.y); - DGL_Vertex2f(v2.x, v2.y); - - DGL_TexCoord2f(0, .5f, 1); - DGL_TexCoord2f(1, v3.x, v3.y); - DGL_Vertex2f(v3.x, v3.y); - - DGL_TexCoord2f(0, .5f, 1); - DGL_TexCoord2f(1, v4.x, v4.y); - DGL_Vertex2f(v4.x, v4.y); - DGL_End(); +// DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, .5f, 0); + DGL_TexCoord2f(1, v1.x, v1.y); + DGL_Vertex2f(v1.x, v1.y); + + DGL_TexCoord2f(0, .5f, 0); + DGL_TexCoord2f(1, v2.x, v2.y); + DGL_Vertex2f(v2.x, v2.y); + + DGL_TexCoord2f(0, .5f, 1); + DGL_TexCoord2f(1, v3.x, v3.y); + DGL_Vertex2f(v3.x, v3.y); + + DGL_TexCoord2f(0, .5f, 1); + DGL_TexCoord2f(1, v4.x, v4.y); + DGL_Vertex2f(v4.x, v4.y); +// DGL_End(); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + //if (!addToLists) + //DGL_BlendMode(BM_NORMAL); break; } case GLOW_BACK: { Vector2f const v1 = from + normal * thickness; Vector2f const v2 = to + normal * thickness; - if(!addToLists) + //if (!addToLists) { - DGL_Bind(tex); + //DGL_Bind(tex); DGL_Color4f(color.x, color.y, color.z, glowStrength * opacity); - DGL_BlendMode(blend); +// DGL_BlendMode(blend); } - DGL_Begin(DGL_QUADS); - DGL_TexCoord2f(0, 0, .25f); - DGL_TexCoord2f(1, v1.x, v1.y); - DGL_Vertex2f(v1.x, v1.y); - - DGL_TexCoord2f(0, 0, .25f); - DGL_TexCoord2f(1, v2.x, v2.y); - DGL_Vertex2f(v2.x, v2.y); - - DGL_TexCoord2f(0, .5f, .25f); - DGL_TexCoord2f(1, to.x, to.y); - DGL_Vertex2f(to.x, to.y); - - DGL_TexCoord2f(0, .5f, .25f); - DGL_TexCoord2f(1, from.x, from.y); - DGL_Vertex2f(from.x, from.y); - DGL_End(); +// DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, 0, .25f); + DGL_TexCoord2f(1, v1.x, v1.y); + DGL_Vertex2f(v1.x, v1.y); + + DGL_TexCoord2f(0, 0, .25f); + DGL_TexCoord2f(1, v2.x, v2.y); + DGL_Vertex2f(v2.x, v2.y); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + DGL_TexCoord2f(0, .5f, .25f); + DGL_TexCoord2f(1, to.x, to.y); + DGL_Vertex2f(to.x, to.y); + + DGL_TexCoord2f(0, .5f, .25f); + DGL_TexCoord2f(1, from.x, from.y); + DGL_Vertex2f(from.x, from.y); +// DGL_End(); + + //if (!addToLists) +// DGL_BlendMode(BM_NORMAL); break; } case GLOW_FRONT: { Vector2f const v3 = to - normal * thickness; Vector2f const v4 = from - normal * thickness; - if(!addToLists) + //if (!addToLists) { - DGL_Bind(tex); + //DGL_Bind(tex); DGL_Color4f(color.x, color.y, color.z, glowStrength * opacity); - DGL_BlendMode(blend); +// DGL_BlendMode(blend); } - DGL_Begin(DGL_QUADS); - DGL_TexCoord2f(0, .75f, .5f); - DGL_TexCoord2f(1, from.x, from.y); - DGL_Vertex2f(from.x, from.y); - - DGL_TexCoord2f(0, .75f, .5f); - DGL_TexCoord2f(1, to.x, to.y); - DGL_Vertex2f(to.x, to.y); - - DGL_TexCoord2f(0, .75f, 1); - DGL_TexCoord2f(1, v3.x, v3.y); - DGL_Vertex2f(v3.x, v3.y); - - DGL_TexCoord2f(0, .75f, 1); - DGL_TexCoord2f(1, v4.x, v4.y); - DGL_Vertex2f(v4.x, v4.y); - DGL_End(); +// DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, .75f, .5f); + DGL_TexCoord2f(1, from.x, from.y); + DGL_Vertex2f(from.x, from.y); + + DGL_TexCoord2f(0, .75f, .5f); + DGL_TexCoord2f(1, to.x, to.y); + DGL_Vertex2f(to.x, to.y); + + DGL_TexCoord2f(0, .75f, 1); + DGL_TexCoord2f(1, v3.x, v3.y); + DGL_Vertex2f(v3.x, v3.y); + + DGL_TexCoord2f(0, .75f, 1); + DGL_TexCoord2f(1, v4.x, v4.y); + DGL_Vertex2f(v4.x, v4.y); +// DGL_End(); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + //if (!addToLists) +// DGL_BlendMode(BM_NORMAL); break; } - default: DENG2_ASSERT(!"Unknown glowtype"); break; + default: + DENG2_ASSERT(!"Unknown glowtype"); + break; } - if(caps) + if (caps) { Vector2f const v1 = to + normal * thickness; Vector2f const v2 = to + unit * thickness + normal * thickness; Vector2f const v3 = to + unit * thickness - normal * thickness; Vector2f const v4 = to - normal * thickness; - if(!addToLists) + //if (!addToLists) { - DGL_Bind(tex); + //DGL_Bind(tex); DGL_Color4f(color.x, color.y, color.z, glowStrength * opacity); - DGL_BlendMode(blend); +// DGL_BlendMode(blend); } - DGL_Begin(DGL_QUADS); - DGL_TexCoord2f(0, .5f, 0); - DGL_TexCoord2f(1, v1.x, v1.y); - DGL_Vertex2f(v1.x, v1.y); - - DGL_TexCoord2f(0, 1, 0); - DGL_TexCoord2f(1, v2.x, v2.y); - DGL_Vertex2f(v2.x, v2.y); - - DGL_TexCoord2f(0, 1, 1); - DGL_TexCoord2f(1, v3.x, v3.y); - DGL_Vertex2f(v3.x, v3.y); - - DGL_TexCoord2f(0, .5, 1); - DGL_TexCoord2f(1, v4.x, v4.y); - DGL_Vertex2f(v4.x, v4.y); - DGL_End(); +// DGL_Begin(DGL_QUADS); + DGL_TexCoord2f(0, .5f, 0); + DGL_TexCoord2f(1, v1.x, v1.y); + DGL_Vertex2f(v1.x, v1.y); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + DGL_TexCoord2f(0, 1, 0); + DGL_TexCoord2f(1, v2.x, v2.y); + DGL_Vertex2f(v2.x, v2.y); + + DGL_TexCoord2f(0, 1, 1); + DGL_TexCoord2f(1, v3.x, v3.y); + DGL_Vertex2f(v3.x, v3.y); + + DGL_TexCoord2f(0, .5, 1); + DGL_TexCoord2f(1, v4.x, v4.y); + DGL_Vertex2f(v4.x, v4.y); +// DGL_End(); + + //if (!addToLists) +// DGL_BlendMode(BM_NORMAL); } } - - if(!glowOnly) + else if (!glowOnly) { - if(!addToLists) + DENG_ASSERT(rs.primType == DGL_LINES); + //if (!addToLists) { DGL_Color4f(color.x, color.y, color.z, opacity); - DGL_BlendMode(blend); +// DGL_BlendMode(blend); } - DGL_Begin(DGL_LINES); - DGL_TexCoord2f(0, from[0], from[1]); - DGL_Vertex2f(from[0], from[1]); - DGL_TexCoord2f(0, to[0], to[1]); - DGL_Vertex2f(to[0], to[1]); - DGL_End(); - - if(!addToLists) - DGL_BlendMode(BM_NORMAL); - } - - if(drawNormal) - { + //DGL_Begin(DGL_LINES); + DGL_TexCoord2f(0, from[0], from[1]); + DGL_Vertex2f(from[0], from[1]); + DGL_TexCoord2f(0, to[0], to[1]); + DGL_Vertex2f(to[0], to[1]); + //DGL_End(); + + //if (!addToLists) +// DGL_BlendMode(BM_NORMAL); + if (drawNormal) + { #define NORMTAIL_LENGTH 8 - Vector2f const v1 = (from + to) / 2; - Vector2d const v2 = v1 + normal * NORMTAIL_LENGTH; + Vector2f const v1 = (from + to) / 2; + Vector2d const v2 = v1 + normal * NORMTAIL_LENGTH; - if(!addToLists) - { - DGL_Color4f(color.x, color.y, color.z, opacity); - DGL_BlendMode(blend); - } + //if (!addToLists) + { + DGL_Color4f(color.x, color.y, color.z, opacity); + // DGL_BlendMode(blend); + } - DGL_Begin(DGL_LINES); +// DGL_Begin(DGL_LINES); DGL_TexCoord2f(0, v1.x, v1.y); DGL_Vertex2f(v1.x, v1.y); DGL_TexCoord2f(0, v2.x, v2.y); DGL_Vertex2f(v2.x, v2.y); - DGL_End(); +// DGL_End(); - if(!addToLists) - DGL_BlendMode(BM_NORMAL); + //if (!addToLists) + // DGL_BlendMode(BM_NORMAL); #undef NORMTAIL_LENGTH + } } + + //DGL_BlendMode(BM_NORMAL); } void drawLine(Line *line) const @@ -584,70 +602,70 @@ xline_t *xline = P_ToXLine(line); // Already drawn once? - if(xline->validCount == VALIDCOUNT) + if (xline->validCount == VALIDCOUNT) return; // Is this line being drawn? - if((xline->flags & ML_DONTDRAW) && !(flags & AWF_SHOW_ALLLINES)) + if ((xline->flags & ML_DONTDRAW) && !(flags & AWF_SHOW_ALLLINES)) return; // We only want to draw twosided lines once. auto *frontSector = (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR); - if(frontSector && frontSector != (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR)) + if (frontSector && frontSector != (Sector *)P_GetPtrp(line, DMU_FRONT_SECTOR)) { return; } automapcfg_lineinfo_t const *info = nullptr; - if((flags & AWF_SHOW_ALLLINES) || xline->mapped[rs.plr - players]) + if ((flags & AWF_SHOW_ALLLINES) || xline->mapped[rs.plr - players]) { - auto *backSector = (Sector *)P_GetPtrp(line, DMU_BACK_SECTOR); + auto *backSector = reinterpret_cast(P_GetPtrp(line, DMU_BACK_SECTOR)); // Perhaps this is a specially colored line? info = style->tryFindLineInfo_special(xline->special, xline->flags, frontSector, backSector, flags); - if(rs.obType != -1 && !info) + if (rs.obType != -1 && !info) { // Perhaps a default colored line? /// @todo Implement an option which changes the vanilla behavior of always /// coloring non-secret lines with the solid-wall color to instead /// use whichever color it would be if not flagged secret. - if(!backSector || !P_GetPtrp(line, DMU_BACK) || (xline->flags & ML_SECRET)) + if (!backSector || !P_GetPtrp(line, DMU_BACK) || (xline->flags & ML_SECRET)) { // solid wall (well probably anyway...) info = style->tryFindLineInfo(AMO_SINGLESIDEDLINE); } else { - if(!de::fequal(P_GetDoublep(backSector, DMU_FLOOR_HEIGHT), - P_GetDoublep(frontSector, DMU_FLOOR_HEIGHT))) + if (!de::fequal(P_GetDoublep(backSector, DMU_FLOOR_HEIGHT), + P_GetDoublep(frontSector, DMU_FLOOR_HEIGHT))) { // Floor level change. info = style->tryFindLineInfo(AMO_FLOORCHANGELINE); } - else if(!de::fequal(P_GetDoublep(backSector, DMU_CEILING_HEIGHT), - P_GetDoublep(frontSector, DMU_CEILING_HEIGHT))) + else if (!de::fequal(P_GetDoublep(backSector, DMU_CEILING_HEIGHT), + P_GetDoublep(frontSector, DMU_CEILING_HEIGHT))) { // Ceiling level change. info = style->tryFindLineInfo(AMO_CEILINGCHANGELINE); } - else if(flags & AWF_SHOW_ALLLINES) + else if (flags & AWF_SHOW_ALLLINES) { info = style->tryFindLineInfo(AMO_UNSEENLINE); } } } } - else if(rs.obType != -1 && revealed) + else if (rs.obType != -1 && revealed) { - if(!(xline->flags & ML_DONTDRAW)) + if (!(xline->flags & ML_DONTDRAW)) { // An as yet, unseen line. info = style->tryFindLineInfo(AMO_UNSEENLINE); } } - if(info && (rs.obType == -1 || info == &style->lineInfo(rs.obType))) + if (info && (rs.obType == -1 || info == &style->lineInfo(rs.obType))) { ddouble from[2]; P_GetDoublepv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, from); ddouble to [2]; P_GetDoublepv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, to); @@ -655,11 +673,10 @@ drawLine2(Vector2d(from), Vector2d(to), Vector3f(info->rgba), info->rgba[3], (xline->special && !cfg.common.automapShowDoors ? GLOW_NONE : info->glow), info->glowStrength, - info->glowSize, !rs.addToLists, info->scaleWithView, + info->glowSize, rs.glowOnly, info->scaleWithView, (info->glow && !(xline->special && !cfg.common.automapShowDoors)), - (xline->special && !cfg.common.automapShowDoors ? BM_NORMAL : info->blendMode), - (flags & AWF_SHOW_LINE_NORMALS), - rs.addToLists); + //(xline->special && !cfg.common.automapShowDoors ? BM_NORMAL : info->blendMode), + (flags & AWF_SHOW_LINE_NORMALS)); xline->validCount = VALIDCOUNT; // Mark as drawn this frame. } @@ -681,56 +698,79 @@ * * @params objType Type of map object being drawn. */ - void drawAllLines(dint obType, bool addToLists = true) const + void drawAllLines(dint obType, bool glowOnly = false) const { // VALIDCOUNT is used to track which lines have been drawn this frame. VALIDCOUNT++; // Configure render state: - rs.obType = obType; - rs.addToLists = addToLists; + rs.obType = obType; + rs.glowOnly = glowOnly; + + if (glowOnly) + { + rs.primType = DGL_QUADS; + DGL_Enable(DGL_TEXTURE0); + DGL_Bind(DGLuint(Get(DD_DYNLIGHT_TEXTURE))); + } + else + { + rs.primType = DGL_LINES; + if (amMaskTexture) + { + DGL_Enable(DGL_TEXTURE0); + DGL_Bind(amMaskTexture); + } + } + + DGL_Begin(rs.primType); // Can we use the automap's in-view bounding box to cull out of view objects? - if(!addToLists) + //if (!addToLists) { AABoxd aaBox; self().pvisibleBounds(&aaBox.minX, &aaBox.maxX, &aaBox.minY, &aaBox.maxY); Subspace_BoxIterator(&aaBox, drawLinesForSubspaceWorker, const_cast(this)); } - else + /*else { // No. As the map lists are considered static we want them to contain all // walls, not just those visible *now* (note rotation). dint const numSubspaces = P_Count(DMU_SUBSPACE); - for(dint i = 0; i < numSubspaces; ++i) + for (dint i = 0; i < numSubspaces; ++i) { P_Iteratep(P_ToPtr(DMU_SUBSPACE, i), DMU_LINE, drawLineWorker, const_cast(this)); } - } + }*/ + + DGL_End(); + DGL_Enable(DGL_TEXTURE0); } static void drawLine(Line *line, Vector3f const &color, dfloat opacity, - blendmode_t blendMode, bool showNormal) + /*blendmode_t blendMode, */bool showNormal) { dfloat length = P_GetFloatp(line, DMU_LENGTH); - if(length > 0) + if (length > 0) { dfloat v1[2]; P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX0), DMU_XY, v1); dfloat v2[2]; P_GetFloatpv(P_GetPtrp(line, DMU_VERTEX1), DMU_XY, v2); - DGL_BlendMode(blendMode); + //DGL_BlendMode(blendMode); DGL_Color4f(color.x, color.y, color.z, opacity); - DGL_Begin(DGL_LINES); - DGL_TexCoord2f(0, v1[0], v1[1]); - DGL_Vertex2f(v1[0], v1[1]); + DENG_ASSERT(rs.primType == DGL_LINES); - DGL_TexCoord2f(0, v2[0], v2[1]); - DGL_Vertex2f(v2[0], v2[1]); - DGL_End(); + //DGL_Begin(DGL_LINES); + DGL_TexCoord2f(0, v1[0], v1[1]); + DGL_Vertex2f(v1[0], v1[1]); - if(showNormal) + DGL_TexCoord2f(0, v2[0], v2[1]); + DGL_Vertex2f(v2[0], v2[1]); + //DGL_End(); + + if (showNormal) { #define NORMTAIL_LENGTH 8 @@ -747,18 +787,18 @@ v2[0] = v1[0] + normal[0] * NORMTAIL_LENGTH; v2[1] = v1[1] + normal[1] * NORMTAIL_LENGTH; - DGL_Begin(DGL_LINES); - DGL_TexCoord2f(0, v1[0], v1[1]); - DGL_Vertex2f(v1[0], v1[1]); - - DGL_TexCoord2f(0, v2[0], v2[1]); - DGL_Vertex2f(v2[0], v2[1]); - DGL_End(); + //DGL_Begin(DGL_LINES); + DGL_TexCoord2f(0, v1[0], v1[1]); + DGL_Vertex2f(v1[0], v1[1]); + + DGL_TexCoord2f(0, v2[0], v2[1]); + DGL_Vertex2f(v2[0], v2[1]); + //DGL_End(); #undef NORMTAIL_LENGTH } - DGL_BlendMode(BM_NORMAL); + //DGL_BlendMode(BM_NORMAL); } } @@ -770,34 +810,34 @@ dfloat const opacity = uiRendState->pageAlpha; xline_t *xline = P_ToXLine(line); - if(!xline) return false; + if (!xline) return false; // Already processed this frame? - if(xline->validCount == VALIDCOUNT) return false; + if (xline->validCount == VALIDCOUNT) return false; - if((xline->flags & ML_DONTDRAW) && !(inst->flags & AWF_SHOW_ALLLINES)) + if ((xline->flags & ML_DONTDRAW) && !(inst->flags & AWF_SHOW_ALLLINES)) { return false; } automapcfg_objectname_t amo = AMO_NONE; - if((inst->flags & AWF_SHOW_ALLLINES) || xline->mapped[rs.plr - players]) + if ((inst->flags & AWF_SHOW_ALLLINES) || xline->mapped[rs.plr - players]) { amo = AMO_SINGLESIDEDLINE; } - else if(rs.obType != -1 && inst->revealed) + else if (rs.obType != -1 && inst->revealed) { - if(!(xline->flags & ML_DONTDRAW)) + if (!(xline->flags & ML_DONTDRAW)) { // An as yet, unseen line. amo = AMO_UNSEENLINE; } } - if(automapcfg_lineinfo_t const *info = inst->style->tryFindLineInfo(amo)) + if (automapcfg_lineinfo_t const *info = inst->style->tryFindLineInfo(amo)) { drawLine(line, Vector3f(info->rgba), info->rgba[3] * cfg.common.automapLineAlpha * opacity, - info->blendMode, (inst->flags & AWF_SHOW_LINE_NORMALS)); + /*info->blendMode, */(inst->flags & AWF_SHOW_LINE_NORMALS)); } xline->validCount = VALIDCOUNT; // Mark as processed this frame. @@ -811,11 +851,16 @@ // Configure render state: rs.obType = MOL_LINEDEF; + rs.primType = DGL_LINES; - // Draw any polyobjects in view. - AABoxd aaBox; - self().pvisibleBounds(&aaBox.minX, &aaBox.maxX, &aaBox.minY, &aaBox.maxY); - Line_BoxIterator(&aaBox, LIF_POLYOBJ, drawLine_polyob, const_cast(this)); + DGL_Begin(rs.primType); + { + // Draw any polyobjects in view. + AABoxd aaBox; + self().pvisibleBounds(&aaBox.minX, &aaBox.maxX, &aaBox.minY, &aaBox.maxY); + Line_BoxIterator(&aaBox, LIF_POLYOBJ, drawLine_polyob, const_cast(this)); + } + DGL_End(); } #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ @@ -825,22 +870,22 @@ DENG2_ASSERT(line && inst); xline_t *xline = P_ToXLine(line); - if(!xline) return false; + if (!xline) return false; - if(xline->validCount == VALIDCOUNT) return false; + if (xline->validCount == VALIDCOUNT) return false; - if(!(inst->flags & AWF_SHOW_ALLLINES)) + if (!(inst->flags & AWF_SHOW_ALLLINES)) { - if(xline->flags & ML_DONTDRAW) return false; + if (xline->flags & ML_DONTDRAW) return false; } // Only active XG lines. - if(!xline->xg || !xline->xg->active) return false; + if (!xline->xg || !xline->xg->active) return false; // XG lines blink. - if(!(mapTime & 4)) return false; + if (!(mapTime & 4)) return false; - drawLine(line, Vector3f(.8f, 0, .8f), 1, BM_ADD, (inst->flags & AWF_SHOW_LINE_NORMALS)); + drawLine(line, Vector3f(.8f, 0, .8f), 1, (inst->flags & AWF_SHOW_LINE_NORMALS)); xline->validCount = VALIDCOUNT; // Mark as processed this frame. return false; // Continue iteration. @@ -850,19 +895,26 @@ void drawAllLines_xg() const { #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - if(!(flags & AWF_SHOW_SPECIALLINES)) + if (!(flags & AWF_SHOW_SPECIALLINES)) return; // VALIDCOUNT is used to track which lines have been drawn this frame. VALIDCOUNT++; // Configure render state: - rs.addToLists = false; - rs.obType = -1; + rs.glowOnly = true; + rs.obType = -1; + rs.primType = DGL_LINES; - AABoxd aaBox; - self().pvisibleBounds(&aaBox.minX, &aaBox.maxX, &aaBox.minY, &aaBox.maxY); - Line_BoxIterator(&aaBox, LIF_SECTOR, drawLine_xg, const_cast(this)); + DGL_BlendMode(BM_ADD); + DGL_Begin(rs.primType); + { + AABoxd aaBox; + self().pvisibleBounds(&aaBox.minX, &aaBox.maxX, &aaBox.minY, &aaBox.maxY); + Line_BoxIterator(&aaBox, LIF_SECTOR, drawLine_xg, const_cast(this)); + } + DGL_End(); + DGL_BlendMode(BM_NORMAL); #endif } @@ -871,10 +923,10 @@ */ void drawAllPlayerMarkers() const { - for(dint i = 0; i < MAXPLAYERS; ++i) + for (dint i = 0; i < MAXPLAYERS; ++i) { // Do not show markers for other players in deathmatch. - if(COMMON_GAMESESSION->rules().deathmatch && i != self().player()) + if (gfw_Rule(deathmatch) && i != self().player()) { continue; } @@ -903,9 +955,9 @@ { MT_AKYY, KEY3_COLOR }, # endif }; - for(auto const &thing : thingData) + for (auto const &thing : thingData) { - if(thing.type == type) return thing.palColor; + if (thing.type == type) return thing.palColor; } return -1; // None. #endif @@ -921,10 +973,10 @@ static int drawThingPoint(mobj_t *mob, void *context) { - auto *p = (drawthingpoint_params_t *) context; + auto *p = reinterpret_cast(context); // Only sector linked mobjs should be visible in the automap. - if(!(mob->flags & MF_NOSECTOR)) + if (!(mob->flags & MF_NOSECTOR)) { svgid_t vgId = p->vgId; bool isVisible = false; @@ -932,10 +984,10 @@ dfloat angle = 0; dfloat keyColorRGB[3]; - if(p->flags & AWF_SHOW_KEYS) + if (p->flags & AWF_SHOW_KEYS) { dint keyColor = thingColorForMobjType(mobjtype_t(mob->type)); - if(keyColor != -1) + if (keyColor != -1) { R_GetColorPaletteRGBf(0, keyColor, keyColorRGB, false); vgId = VG_KEY; @@ -945,13 +997,13 @@ } // Something else? - if(!isVisible) + if (!isVisible) { isVisible = !!(p->flags & AWF_SHOW_THINGS); - angle = Mobj_AngleSmoothed(mob) / (float) ANGLE_MAX * 360; // In degrees. + angle = Mobj_AngleSmoothed(mob) / float(ANGLE_MAX) * 360; // In degrees. } - if(isVisible) + if (isVisible) { /* $unifiedangles */ coord_t origin[3]; Mobj_OriginSmoothed(mob, origin); @@ -966,7 +1018,7 @@ void drawAllThings() const { - if(!(flags & (AWF_SHOW_THINGS | AWF_SHOW_KEYS))) + if (!(flags & (AWF_SHOW_THINGS | AWF_SHOW_KEYS))) return; dfloat const alpha = uiRendState->pageAlpha; @@ -988,7 +1040,7 @@ { dfloat const alpha = uiRendState->pageAlpha; - if(points.isEmpty()) return; + if (points.isEmpty()) return; // Calculate final scale factor. scale = self().frameToMap(1) * scale; @@ -998,8 +1050,8 @@ #endif dint idx = 0; - Point2Raw const labelOffset; - for(MarkedPoint const *point : points) + const Point2Raw labelOffset{}; + for (MarkedPoint const *point : points) { String const label = String::number(idx++); Vector2d const origin = fitPointInRectangle(point->origin(), topLeft, topRight, bottomRight, bottomLeft, view); @@ -1014,7 +1066,7 @@ FR_SetFont(FID(GF_MAPPOINT)); #if __JDOOM__ - if(gameMode == doom2_hacx) + if (gameMode == doom2_hacx) FR_SetColorAndAlpha(1, 1, 1, alpha); else FR_SetColorAndAlpha(.22f, .22f, .22f, alpha); @@ -1034,7 +1086,7 @@ */ void setupGLStateForMap() const { - dfloat const alpha = uiRendState->pageAlpha; + const dfloat alpha = uiRendState->pageAlpha; // Store the old scissor state (to clip the map lines and stuff). DGL_PushState(); @@ -1044,13 +1096,14 @@ dfloat bgColor[3]; #if __JHERETIC__ || __JHEXEN__ - if(!CentralLumpIndex().contains("AUTOPAGE.lmp")) + if (CentralLumpIndex().contains("AUTOPAGE.lmp")) { - bgColor[0] = .55f; bgColor[1] = .45f; bgColor[2] = .35f; + bgColor[0] = bgColor[1] = bgColor[2] = 1.f; // use lump colors as-is } else { - AM_GetMapColor(bgColor, cfg.common.automapBack, WHITE, customPal); + // Automap background lump is missing. + bgColor[0] = .55f; bgColor[1] = .45f; bgColor[2] = .35f; } #else AM_GetMapColor(bgColor, cfg.common.automapBack, BACKGROUND, customPal); @@ -1058,11 +1111,20 @@ RectRaw geom; Rect_Raw(&self().geometry(), &geom); - // Do we want a background texture? - if(autopageLumpNum != -1) + // Draw the AUTOPAGE background image (if available). + if (autopageLumpNum != -1) { - // Apply the background texture onto a parallaxing layer which - // follows the map view target (not player). + const float autopageWidth = 320; /// @todo Could be external with different size. + const float autopageHeight = 200; + const float autopageAspectRatio = autopageWidth / autopageHeight; + + const float texScale = 1.f / 3000.f; + const float bgScale = texScale / scaleMTOF; + const float offsetScale = texScale * autopageAspectRatio; + + // The autopage texture is transformed in texture coordinate space. It is drawn as + // a single quad covering the entire widget. + DGL_Enable(DGL_TEXTURE_2D); DGL_MatrixMode(DGL_TEXTURE); @@ -1072,6 +1134,7 @@ DGL_SetRawImage(autopageLumpNum, DGL_REPEAT, DGL_REPEAT); DGL_Color4f(bgColor[0], bgColor[1], bgColor[2], cfg.common.automapOpacity * alpha); +#if 0 DGL_Translatef(geom.origin.x, geom.origin.y, 0); // Apply the parallax scrolling, map rotation and counteract the @@ -1080,10 +1143,17 @@ self().mapToFrame(viewPL.y) + .5f, 0); DGL_Scalef(1, 1.2f/*aspect correct*/, 1); DGL_Rotatef(360 - self().cameraAngle(), 0, 0, 1); - DGL_Scalef(1, (dfloat)geom.size.height / geom.size.width, 1); DGL_Translatef(-(.5f), -(.5f), 0); +#endif - DGL_DrawRectf2(0, 0, geom.size.width, geom.size.height); + DENG_ASSERT(!std::isnan(view.x)); + + DGL_Translatef(offsetScale * view.x, -offsetScale * view.y, 1.f); + DGL_Scalef(autopageAspectRatio, autopageAspectRatio, 1.f); + DGL_Rotatef(360.f - self().cameraAngle(), 0, 0, 1); + DGL_Scalef(bgScale * float(geom.size.width), bgScale * float(geom.size.height), 1.f); + DGL_Translatef(-.5f, -.5f, 0); // center + DGL_DrawRectf2(geom.origin.x, geom.origin.y, geom.size.width, geom.size.height); DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); @@ -1101,7 +1171,7 @@ #if __JDOOM64__ // jd64 > Demon keys // If drawn in HUD we don't need them visible in the map too. - if(!cfg.hudShown[HUD_INVENTORY]) + if (!cfg.hudShown[HUD_INVENTORY]) { static inventoryitemtype_t const items[3] = { IIT_DEMONKEY1, IIT_DEMONKEY2, IIT_DEMONKEY3 @@ -1109,13 +1179,13 @@ dint player = self().player(); dint num = 0; - for(inventoryitemtype_t const &item : items) + for (inventoryitemtype_t const &item : items) { - if(P_InventoryCount(player, item) > 0) + if (P_InventoryCount(player, item) > 0) num += 1; } - if(num > 0) + if (num > 0) { static dint const invItemSprites[NUM_INVENTORYITEM_TYPES] = { SPR_ART1, SPR_ART2, SPR_ART3 @@ -1126,9 +1196,9 @@ spriteinfo_t sprInfo; dfloat y = 0; - for(dint i = 0; i < 3; ++i) + for (dint i = 0; i < 3; ++i) { - if(P_InventoryCount(player, items[i])) + if (P_InventoryCount(player, items[i])) { R_GetSpriteInfo(invItemSprites[i], 0, &sprInfo); DGL_SetPSprite(sprInfo.material); @@ -1186,7 +1256,7 @@ void drawAllVertexes() { - if(!(flags & AWF_SHOW_VERTEXES)) + if (!(flags & AWF_SHOW_VERTEXES)) return; DGL_Color4f(.2f, .5f, 1, uiRendState->pageAlpha); @@ -1197,7 +1267,7 @@ dfloat v[2]; DGL_Begin(DGL_POINTS); - for(dint i = 0; i < numvertexes; ++i) + for (dint i = 0; i < numvertexes; ++i) { P_GetFloatv(DMU_VERTEX, i, DMU_XY, v); DGL_TexCoord2f(0, v[0], v[1]); @@ -1208,41 +1278,6 @@ DGL_SetFloat(DGL_POINT_SIZE, oldPointSize); DGL_Disable(DGL_POINT_SMOOTH); } - - void deleteLists() - { - if(Get(DD_NOVIDEO) || IS_DEDICATED) return; - - for(dint i = 0; i < NUM_MAP_OBJECTLISTS; ++i) - { - if(lists[i]) - { - DGL_DeleteLists(lists[i], 1); lists[i] = 0; - } - } - } - - /** - * Compile OpenGL commands for drawing the map objects with display lists. - */ - void buildLists() - { - if(Get(DD_NOVIDEO) || IS_DEDICATED) return; - - deleteLists(); - - for(dint i = 0; i < NUM_MAP_OBJECTLISTS; ++i) - { - // Build commands and compile to a display list. - if(DGL_NewList(0, DGL_COMPILE)) - { - drawAllLines(i); - lists[i] = DGL_EndList(); - } - } - - needBuildLists = false; - } }; AutomapWidget::AutomapWidget(dint player) @@ -1271,13 +1306,14 @@ { LumpIndex const &lumpIndex = CentralLumpIndex(); - if(autopageLumpNum >= 0) + if (autopageLumpNum >= 0) + { autopageLumpNum = lumpIndex.findLast("autopage.lmp"); - - if(!amMaskTexture) + } + if (!amMaskTexture) { lumpnum_t lumpNum = lumpIndex.findLast("mapmask.lmp"); - if(lumpNum >= 0) + if (lumpNum >= 0) { File1 &file = lumpIndex[lumpNum]; uint8_t const *pixels = file.cache(); @@ -1293,15 +1329,15 @@ void AutomapWidget::releaseAssets() // static { - if(!amMaskTexture) return; + if (!amMaskTexture) return; DGL_DeleteTextures(1, &amMaskTexture); amMaskTexture = 0; } void AutomapWidget::reset() { - d->deleteLists(); d->needBuildLists = true; + d->rotate = cfg.common.automapRotate; } void AutomapWidget::lineAutomapVisibilityChanged(Line const &) @@ -1321,20 +1357,20 @@ float const alpha = uiRendState->pageAlpha; player_t *plr = &players[player()]; - if(!plr->plr->inGame) return; + if (!plr->plr->inGame) return; // Configure render state: rs.plr = plr; - Vector2d const viewPoint = cameraOrigin(); + const Vector2d viewPoint = cameraOrigin(); float angle = cameraAngle(); RectRaw geom; Rect_Raw(&geometry(), &geom); // Freeze the lists if the map is fading out from being open, or for debug. - if((++updateWait % 10) && d->needBuildLists && !freezeMapRLs && isOpen()) - { - // Its time to rebuild the automap object display lists. - d->buildLists(); - } +// if ((++updateWait % 10) && d->needBuildLists && !freezeMapRLs && isOpen()) +// { +// // Its time to rebuild the automap object display lists. +// d->buildLists(); +// } // Setup for frame. d->setupGLStateForMap(); @@ -1343,16 +1379,16 @@ // objects using their world-space coordinates directly. DGL_MatrixMode(DGL_MODELVIEW); DGL_Translatef(offset.x, offset.y, 0); - DGL_Translatef(geom.size.width / 2, geom.size.height / 2, 0); + DGL_Translatef(geom.size.width / 2, geom.size.height / 2, 0); DGL_Rotatef(angle, 0, 0, 1); DGL_Scalef(1, -1, 1); // In the world coordinate space Y+ is up. DGL_Scalef(d->scaleMTOF, d->scaleMTOF, 1); DGL_Translatef(-viewPoint.x, -viewPoint.y, 0); - float const oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); - DGL_SetFloat(DGL_LINE_WIDTH, de::clamp(.5f, cfg.common.automapLineWidth * aspectScale, 3.f)); + const float oldLineWidth = DGL_GetFloat(DGL_LINE_WIDTH); + DGL_SetFloat(DGL_LINE_WIDTH, d->pixelRatio * de::clamp(.5f, cfg.common.automapLineWidth, 8.f)); -/*#if _DEBUG + /*#if _DEBUG // Draw the rectangle described by the visible bounds. { coord_t topLeft[2], bottomRight[2], topRight[2], bottomLeft[2]; @@ -1371,15 +1407,11 @@ } #endif*/ - if(amMaskTexture) + if (amMaskTexture) { dint const border = .5f + UIAUTOMAP_BORDER * aspectScale; - DGL_Bind(amMaskTexture); - DGL_Enable(DGL_TEXTURE_2D); - DGL_SetInteger(DGL_ACTIVE_TEXTURE, 0); - DGL_MatrixMode(DGL_TEXTURE); DGL_LoadIdentity(); @@ -1394,16 +1426,11 @@ } // Draw static map geometry. - for(dint i = NUM_MAP_OBJECTLISTS-1; i >= 0; i--) + for (dint i = NUM_MAP_OBJECTLISTS-1; i >= 0; i--) { - if(d->lists[i]) - { - automapcfg_lineinfo_t const &info = d->style->lineInfo(i); - - DGL_Color4f(info.rgba[0], info.rgba[1], info.rgba[2], info.rgba[3] * cfg.common.automapLineAlpha * alpha); - DGL_BlendMode(info.blendMode); - DGL_CallList(d->lists[i]); - } + automapcfg_lineinfo_t const &info = d->style->lineInfo(i); + DGL_Color4f(info.rgba[0], info.rgba[1], info.rgba[2], info.rgba[3] * cfg.common.automapLineAlpha * alpha); + d->drawAllLines(i); } // Draw dynamic map geometry. @@ -1422,20 +1449,17 @@ d->drawAllPlayerMarkers(); DGL_SetFloat(DGL_LINE_WIDTH, oldLineWidth); - if(amMaskTexture) + if (amMaskTexture) { - DGL_Disable(DGL_TEXTURE_2D); + DGL_Disable(DGL_TEXTURE0); DGL_MatrixMode(DGL_TEXTURE); DGL_PopMatrix(); } // Draw glows? - if(cfg.common.automapShowDoors) + if (cfg.common.automapShowDoors) { - /// @todo Optimize: Hugely inefficent. Need a new approach. - DGL_Enable(DGL_TEXTURE_2D); - d->drawAllLines(-1, false /*don't use draw lists*/); - DGL_Disable(DGL_TEXTURE_2D); + d->drawAllLines(-1, true /*only glows*/); } d->restoreGLStateFromMap(); @@ -1449,12 +1473,12 @@ void AutomapWidget::open(bool yes, bool instantly) { - if(G_GameState() != GS_MAP && yes) return; + if (G_GameState() != GS_MAP && yes) return; - if(d->open == yes) return; // No change. + if (d->open == yes) return; // No change. d->targetOpacity = (yes? 1.f : 0.f); - if(instantly) + if (instantly) { d->opacity = d->oldOpacity = d->targetOpacity; } @@ -1466,18 +1490,18 @@ } d->open = yes; - if(d->open) + if (d->open) { - if(mobj_t *mob = followMobj()) + if (mobj_t *mob = followMobj()) { // The map's target player is available. - if(!(!d->follow && !cfg.common.automapPanResetOnOpen)) + if (d->follow || cfg.common.automapPanResetOnOpen) { coord_t origin[3]; Mobj_OriginSmoothed(mob, origin); setCameraOrigin(Vector2d(origin)); } - if(!d->follow && cfg.common.automapPanResetOnOpen) + if (!d->follow && cfg.common.automapPanResetOnOpen) { /* $unifiedangles */ setCameraAngle((d->rotate ? (mob->angle - ANGLE_90) / (float) ANGLE_MAX * 360 : 0)); @@ -1493,10 +1517,10 @@ } } - if(d->open) + if (d->open) { DD_Execute(true, "activatebcontext map"); - if(!d->follow) + if (!d->follow) DD_Execute(true, "activatebcontext map-freepan"); } else @@ -1516,63 +1540,81 @@ dfloat panX[2]; P_GetControlState(plrNum, CTL_MAP_PAN_X, &panX[0], &panX[1]); dfloat panY[2]; P_GetControlState(plrNum, CTL_MAP_PAN_Y, &panY[0], &panY[1]); - if(G_GameState() != GS_MAP) return; + if (G_GameState() != GS_MAP) return; // Move towards the target alpha level for the automap. - d->opacityTimer += (cfg.common.automapOpenSeconds == 0? 1 : 1 / cfg.common.automapOpenSeconds * elapsed); - if(d->opacityTimer >= 1) + if (cfg.common.automapOpenSeconds >= .001f) + { + d->opacityTimer += 1.f / cfg.common.automapOpenSeconds * elapsed; + } + else + { + d->opacityTimer = 1.f; // Instant. + } + + if (d->opacityTimer >= 1) + { d->opacity = d->targetOpacity; + } else + { d->opacity = de::lerp(d->oldOpacity, d->targetOpacity, d->opacityTimer); + } // Unless open we do nothing further. - if(!isOpen()) return; + if (!isOpen()) return; // Map view zoom contol. dfloat zoomSpeed = 1 + (2 * cfg.common.automapZoomSpeed) * elapsed * TICRATE; - if(players[plrNum].brain.speed) zoomSpeed *= 1.5f; + if (players[plrNum].brain.speed) + { + zoomSpeed *= 1.5f; + } dfloat zoomVel; P_GetControlState(plrNum, CTL_MAP_ZOOM, &zoomVel, nullptr); // ignores rel offset -jk - if(zoomVel > 0) // zoom in + if (zoomVel > 0) // zoom in { setScale(d->viewScale * zoomSpeed); } - else if(zoomVel < 0) // zoom out + else if (zoomVel < 0) // zoom out { setScale(d->viewScale / zoomSpeed); } - if(!d->follow || !followMob) + if (!d->follow || !followMob) { // Camera panning mode. dfloat panUnitsPerSecond; // DOOM.EXE pans the automap at 140 fixed pixels per second (VGA: 200 pixels tall). /// @todo This needs resolution-independent units. (The "frame" units are screen pixels.) - panUnitsPerSecond = frameToMap(140 * Rect_Height(&geometry()) / 200.f) * (2 * cfg.common.automapPanSpeed); - if(panUnitsPerSecond < 8) panUnitsPerSecond = 8; + panUnitsPerSecond = de::max(8.f, + frameToMap(140 * Rect_Height(&geometry()) / 200.f) * + (2 * cfg.common.automapPanSpeed)); /// @todo Fix sensitivity for relative axes. - Vector2d const delta = rotate(Vector2d(panX[0], panY[0]) * panUnitsPerSecond * elapsed + Vector2d(panX[1], panY[1]), + Vector2d const delta = rotate(Vector2d(panX[0], panY[0]) * panUnitsPerSecond * elapsed + + Vector2d(panX[1], panY[1]), degreeToRadian(d->angle)); moveCameraOrigin(delta, true /*instant move*/); } else { // Camera follow mode. - dfloat const angle = (d->rotate ? (followMob->angle - ANGLE_90) / (dfloat) ANGLE_MAX * 360 : 0); /* $unifiedangles */ + dfloat const angle = (d->rotate ? (followMob->angle - ANGLE_90) / (dfloat) ANGLE_MAX * 360 + : 0); /* $unifiedangles */ coord_t origin[3]; Mobj_OriginSmoothed(followMob, origin); setCameraOrigin(Vector2d(origin)); setCameraAngle(angle); } - if(d->needViewScaleUpdate) + if (d->needViewScaleUpdate) d->updateViewScale(); // Map viewer location. d->viewTimer += dfloat(.4 * elapsed * TICRATE); - if(d->viewTimer >= 1) + if (d->viewTimer >= 1) { d->view = d->targetView; } @@ -1580,12 +1622,13 @@ { d->view = de::lerp(d->oldView, d->targetView, d->viewTimer); } + // Move the parallax layer. - d->viewPL = d->view / 4000; +// d->viewPL = d->view / 4000; // Map view scale (zoom). d->viewScaleTimer += dfloat(.4 * elapsed * TICRATE); - if(d->viewScaleTimer >= 1) + if (d->viewScaleTimer >= 1) { d->viewScale = d->targetViewScale; } @@ -1596,7 +1639,7 @@ // Map view rotation. d->angleTimer += dfloat(.4 * elapsed * TICRATE); - if(d->angleTimer >= 1) + if (d->angleTimer >= 1) { d->angle = d->targetAngle; } @@ -1606,22 +1649,22 @@ dfloat endAngle = d->targetAngle; dfloat diff; - if(endAngle > startAngle) + if (endAngle > startAngle) { diff = endAngle - startAngle; - if(diff > 180) + if (diff > 180) endAngle = startAngle - (360 - diff); } else { diff = startAngle - endAngle; - if(diff > 180) + if (diff > 180) endAngle = startAngle + (360 - diff); } d->angle = de::lerp(startAngle, endAngle, d->angleTimer); - if(d->angle < 0) d->angle += 360; - else if(d->angle > 360) d->angle -= 360; + if (d->angle < 0) d->angle += 360; + else if (d->angle > 360) d->angle -= 360; } // @@ -1678,12 +1721,13 @@ { // Determine whether the available space has changed and thus whether // the position and/or size of the automap must therefore change too. - RectRaw newGeom; R_ViewWindowGeometry(player(), &newGeom); + RectRaw newGeom; + R_ViewWindowGeometry(player(), &newGeom); - if(newGeom.origin.x != Rect_X(&geometry()) || - newGeom.origin.y != Rect_Y(&geometry()) || - newGeom.size.width != Rect_Width(&geometry()) || - newGeom.size.height != Rect_Height(&geometry())) + if (newGeom.origin.x != Rect_X(&geometry()) || + newGeom.origin.y != Rect_Y(&geometry()) || + newGeom.size.width != Rect_Width(&geometry()) || + newGeom.size.height != Rect_Height(&geometry())) { Rect_SetXY(&geometry(), newGeom.origin.x, newGeom.origin.y); Rect_SetWidthHeight(&geometry(), newGeom.size.width, newGeom.size.height); @@ -1703,7 +1747,7 @@ { // Already at this target? newAngle = de::clamp(0.f, newAngle, 359.9999f); - if(newAngle == d->targetAngle) return; + if (newAngle == d->targetAngle) return; // Begin animating toward the new target. d->oldAngle = d->angle; @@ -1719,21 +1763,21 @@ void AutomapWidget::setCameraOrigin(Vector2d const &newOrigin, bool instantly) { // Already at this target? - if(newOrigin == d->targetView) + if (newOrigin == d->targetView) return; // If the delta is too great - perform the move instantly. - if(!instantly && d->maxViewPositionDelta > 0) + if (!instantly && d->maxViewPositionDelta > 0) { coord_t const dist = de::abs((cameraOrigin() - newOrigin).length()); - if(dist > d->maxViewPositionDelta) + if (dist > d->maxViewPositionDelta) { instantly = true; } } // Begin animating toward the new target. - if(instantly) + if (instantly) { d->view = d->oldView = d->targetView = newOrigin; } @@ -1752,13 +1796,13 @@ void AutomapWidget::setScale(dfloat newScale) { - if(d->needViewScaleUpdate) + if (d->needViewScaleUpdate) d->updateViewScale(); newScale = de::clamp(d->minScaleMTOF, newScale, d->maxScaleMTOF); // Already at this target? - if(newScale == d->targetViewScale) + if (newScale == d->targetViewScale) return; // Begin animating toward the new target. @@ -1779,7 +1823,7 @@ void AutomapWidget::reveal(bool yes) { - if(d->revealed != yes) + if (d->revealed != yes) { d->revealed = yes; d->needBuildLists = true; @@ -1788,10 +1832,10 @@ void AutomapWidget::pvisibleBounds(coord_t *lowX, coord_t *hiX, coord_t *lowY, coord_t *hiY) const { - if(lowX) *lowX = d->viewAABB[BOXLEFT]; - if(hiX) *hiX = d->viewAABB[BOXRIGHT]; - if(lowY) *lowY = d->viewAABB[BOXBOTTOM]; - if(hiY) *hiY = d->viewAABB[BOXTOP]; + if (lowX) *lowX = d->viewAABB[BOXLEFT]; + if (hiX) *hiX = d->viewAABB[BOXRIGHT]; + if (lowY) *lowY = d->viewAABB[BOXBOTTOM]; + if (hiY) *hiY = d->viewAABB[BOXTOP]; } dint AutomapWidget::pointCount() const @@ -1803,7 +1847,7 @@ { d->points << new MarkedPoint(origin); dint pointNum = d->points.count() - 1; // base 0. - if(player() >= 0) + if (player() >= 0) { String msg = String(AMSTR_MARKEDSPOT) + " " + String::number(pointNum); P_SetMessageWithFlags(&players[player()], msg.toUtf8().constData(), LMF_NO_HIDE); @@ -1818,16 +1862,16 @@ AutomapWidget::MarkedPoint &AutomapWidget::point(dint index) const { - if(hasPoint(index)) return *d->points.at(index); + if (hasPoint(index)) return *d->points.at(index); /// @throw MissingPointError Invalid point reference. throw MissingPointError("AutomapWidget::point", "Unknown point #" + String::number(index)); } LoopResult AutomapWidget::forAllPoints(std::function func) const { - for(MarkedPoint *point : d->points) + for (MarkedPoint *point : d->points) { - if(auto result = func(*point)) return result; + if (auto result = func(*point)) return result; } return LoopContinue; } @@ -1836,7 +1880,7 @@ { d->clearPoints(); - if(!silent && player() >= 0) + if (!silent && player() >= 0) { P_SetMessageWithFlags(&players[player()], AMSTR_MARKSCLEARED, LMF_NO_HIDE); } @@ -1852,20 +1896,20 @@ LOG_AS("AutomapWidget"); bool const oldZoomMax = d->forceMaxScale; - if(d->needViewScaleUpdate) + if (d->needViewScaleUpdate) { d->updateViewScale(); } // When switching to max scale mode, store the old scale. - if(!d->forceMaxScale) + if (!d->forceMaxScale) { d->priorToMaxScale = d->viewScale; } d->forceMaxScale = yes; setScale((d->forceMaxScale ? 0 : d->priorToMaxScale)); - if(oldZoomMax != d->forceMaxScale) + if (oldZoomMax != d->forceMaxScale) { LOGDEV_XVERBOSE("Maximum zoom: ", DENG2_BOOL_YESNO(cameraZoomMode())); } @@ -1878,10 +1922,10 @@ void AutomapWidget::setCameraFollowMode(bool yes) { - if(d->follow != yes) + if (d->follow != yes) { d->follow = yes; - if(d->open) + if (d->open) { DD_Executef(true, "%sactivatebcontext map-freepan", d->follow? "de" : ""); P_SetMessageWithFlags(&players[player()], (d->follow ? AMSTR_FOLLOWON : AMSTR_FOLLOWOFF), LMF_NO_HIDE); @@ -1891,7 +1935,7 @@ mobj_t *AutomapWidget::followMobj() const { - if(d->followPlayer >= 0) + if (d->followPlayer >= 0) { player_t *player = &players[d->followPlayer]; return player->plr->inGame ? player->plr->mo : nullptr; @@ -1917,7 +1961,7 @@ void AutomapWidget::setOpacityEX(dfloat newOpacity) { newOpacity = de::clamp(0.f, newOpacity, 1.f); - if(newOpacity != d->targetOpacity) + if (newOpacity != d->targetOpacity) { // Start animating toward the new target. d->oldOpacity = d->opacity; @@ -1933,7 +1977,7 @@ void AutomapWidget::setFlags(dint newFlags) { - if(d->flags != newFlags) + if (d->flags != newFlags) { d->flags = newFlags; // We will need to rebuild one or more display lists. @@ -1956,6 +2000,7 @@ void AutomapWidget::consoleRegister() // static { C_VAR_FLOAT("map-opacity", &cfg.common.automapOpacity, 0, 0, 1); + C_VAR_BYTE ("map-neverobscure", &cfg.common.automapNeverObscure, 0, 0, 1); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ C_VAR_BYTE ("map-babykeys", &cfg.common.automapBabyKeys, 0, 0, 1); #endif @@ -1964,7 +2009,7 @@ C_VAR_FLOAT("map-background-b", &cfg.common.automapBack[2], 0, 0, 1); C_VAR_INT ("map-customcolors", &cfg.common.automapCustomColors, 0, 0, 1); C_VAR_FLOAT( "map-line-opacity", &cfg.common.automapLineAlpha, 0, 0, 1); - C_VAR_FLOAT("map-line-width", &cfg.common.automapLineWidth, 0, .1f, 2); + C_VAR_FLOAT("map-line-width", &cfg.common.automapLineWidth, 0, .5f, 8); C_VAR_FLOAT("map-mobj-r", &cfg.common.automapMobj[0], 0, 0, 1); C_VAR_FLOAT("map-mobj-g", &cfg.common.automapMobj[1], 0, 0, 1); C_VAR_FLOAT("map-mobj-b", &cfg.common.automapMobj[2], 0, 0, 1); @@ -1994,3 +2039,19 @@ // Aliases for old names: C_VAR_FLOAT("map-alpha-lines", &cfg.common.automapLineAlpha, 0, 0, 1); } + +void G_SetAutomapRotateMode(byte enableRotate) +{ + cfg.common.automapRotate = enableRotate; // Note: this sets the global default. + + for (int i = 0; i < MAXPLAYERS; ++i) + { + ST_SetAutomapCameraRotation(i, cfg.common.automapRotate); + if (players[i].plr->inGame) + { + P_SetMessageWithFlags(&players[i], + (cfg.common.automapRotate ? AMSTR_ROTATEON : AMSTR_ROTATEOFF), + LMF_NO_HIDE); + } + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/fragswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/fragswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/fragswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/fragswidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -76,7 +76,7 @@ if(!::cfg.hudShown[HUD_FRAGS]) return; #endif - if(!G_Ruleset_Deathmatch()) return; + if(!gfw_Rule(deathmatch)) return; if(ST_AutomapIsOpen(frags->player()) && ::cfg.common.automapHudDisplay == 0) return; if(P_MobjIsCamera(::players[frags->player()].plr->mo) && Get(DD_PLAYBACK)) return; @@ -118,7 +118,7 @@ if(!::cfg.hudShown[HUD_FRAGS]) return; #endif - if(!G_Ruleset_Deathmatch()) return; + if(!gfw_Rule(deathmatch)) return; if(ST_AutomapIsOpen(frags->player()) && ::cfg.common.automapHudDisplay == 0) return; if(P_MobjIsCamera(::players[frags->player()].plr->mo) && Get(DD_PLAYBACK)) return; @@ -166,7 +166,7 @@ dfloat const textOpacity = (activeHud == 0? 1 : ::uiRendState->pageAlpha * ::cfg.common.statusbarCounterAlpha); //dfloat const iconOpacity = (activeHud == 0? 1 : ::uiRendState->pageAlpha * ::cfg.common.statusbarCounterAlpha); - if(!G_Ruleset_Deathmatch()) return; + if(!gfw_Rule(deathmatch)) return; #if __JHERETIC__ || __JHEXEN__ if(Hu_InventoryIsOpen(frags->player())) return; #endif @@ -227,7 +227,7 @@ Rect_SetWidthHeight(&frags->geometry(), 0, 0); - if(!G_Ruleset_Deathmatch()) return; + if(!gfw_Rule(deathmatch)) return; #if __JHERETIC__ || __JHEXEN__ if(Hu_InventoryIsOpen(frags->player())) return; #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/healthwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/healthwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/healthwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/healthwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -139,7 +139,7 @@ //dfloat const iconOpacity = (activeHud == 0? 1 : ::uiRendState->pageAlpha * ::cfg.common.statusbarCounterAlpha); #if __JHERETIC__ || __JHEXEN__ - if(G_Ruleset_Deathmatch()) return; + if(gfw_Rule(deathmatch)) return; if(Hu_InventoryIsOpen(hlth->player())) return; #endif @@ -232,7 +232,7 @@ if(hlth->_value == 1994) return; #if __JHERETIC__ || __JHEXEN__ - if(G_Ruleset_Deathmatch()) return; + if(gfw_Rule(deathmatch)) return; if(Hu_InventoryIsOpen(hlth->player())) return; #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/keyswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/keyswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/keyswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/keyswidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -247,7 +247,7 @@ if(ST_AutomapIsOpen(player()) && ::cfg.common.automapHudDisplay == 0) return; if(P_MobjIsCamera(::players[player()].plr->mo) && Get(DD_PLAYBACK)) return; - RectRaw iconGeometry; + RectRaw iconGeometry{}; for(int i = 0; i < NUM_KEY_TYPES; ++i) { if(!_keyBoxes[i]) continue; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/playerlogwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/playerlogwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hud/widgets/playerlogwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hud/widgets/playerlogwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -202,7 +202,6 @@ void PlayerLogWidget::draw(Vector2i const &offset) { - dint pvisEntryCount = de::min(d->pvisEntryCount, de::max(0, cfg.common.msgCount)); dint firstEntry = d->firstPVisEntryIdx(); @@ -423,7 +422,7 @@ dint n = firstEntry; dint drawnEntryCount = 0; - RectRaw lineGeometry; + RectRaw lineGeometry{}; for(dint i = 0; i < pvisEntryCount; ++i, n = d->nextEntryIdx(n)) { entry = &d->entries[n]; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_lib.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_lib.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_lib.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_lib.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -242,7 +242,7 @@ void GUI_DrawWidgetXY(HudWidget *wi, int x, int y) { - Point2Raw origin(x, y); + Point2Raw origin = {{{x, y}}}; GUI_DrawWidget(wi, &origin); } @@ -314,7 +314,7 @@ void GUI_LoadResources() { - if(Get(DD_DEDICATED) || Get(DD_NOVIDEO)) return; + if(Get(DD_NOVIDEO)) return; AutomapWidget::prepareAssets(); menu::LineEditWidget::loadResources(); @@ -323,7 +323,7 @@ void GUI_ReleaseResources() { - if(Get(DD_DEDICATED) || Get(DD_NOVIDEO)) return; + if(Get(DD_NOVIDEO)) return; AutomapWidget::prepareAssets(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_menu.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_menu.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_menu.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_menu.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -648,19 +648,20 @@ void Hu_MenuInitPlayerSetupPage() { #if __JHERETIC__ || __JHEXEN__ - Vector2i const origin(70, 44); + Vector2i const origin(70, 34); #else Vector2i const origin(70, 54); #endif - Page *page = Hu_MenuAddPage(new Page("PlayerSetup", origin, 0, Hu_MenuDrawPlayerSetupPage)); + Page *page = Hu_MenuAddPage(new Page("PlayerSetup", origin, Page::NoScroll, Hu_MenuDrawPlayerSetupPage)); + page->setLeftColumnWidth(.5f); page->setOnActiveCallback(Hu_MenuActivatePlayerSetup); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPredefinedFont(MENU_FONT2, FID(GF_FONTB)); page->setPreviousPage(Hu_MenuPagePtr("Options")); page->addWidget(new MobjPreviewWidget) - .setFixedOrigin(Vector2i(SCREENWIDTH / 2 - origin.x, 60)) + .setFixedOrigin(Vector2i(SCREENWIDTH / 2 - 40, 60)) .setFlags(Widget::Id0 | Widget::PositionFixed); page->addWidget(new CVarLineEditWidget("net-name")) @@ -670,6 +671,7 @@ #if __JHEXEN__ page->addWidget(new LabelWidget("Class")) + .setLeft() .setFlags(Widget::LayoutOffset) .setFixedY(5); @@ -679,12 +681,14 @@ << new ListWidgetItem(GET_TXT(TXT_PLAYERCLASS3), PCLASS_MAGE)) .setFlags(Widget::Id2) .setShortcut('c') + .setRight() .setColor(MENU_COLOR3) .setAction(Widget::Modified, Hu_MenuSelectPlayerSetupPlayerClass) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); #endif auto &label = page->addWidget(new LabelWidget("Color")); + label.setLeft(); #ifdef __JHERETIC__ label.setFlags(Widget::LayoutOffset); label.setFixedY(5); @@ -725,6 +729,7 @@ .addItems(items) .setFlags(Widget::Id3) .setColor(MENU_COLOR3) + .setRight() .setAction(Widget::Modified, Hu_MenuSelectPlayerColor) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); @@ -737,16 +742,20 @@ void Hu_MenuInitSaveOptionsPage() { Page *page = Hu_MenuAddPage(new Page("SaveOptions", Vector2i(60, 50))); - page->setTitle("Save Options"); + page->setTitle("Savegame Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("Confirm quick load/save")); + page->addWidget(new LabelWidget("Confirm quick load/save")) + .setLeft(); page->addWidget(new CVarToggleWidget("game-save-confirm")) + .setRight() .setShortcut('q'); - page->addWidget(new LabelWidget("Confirm reborn load")); + page->addWidget(new LabelWidget("Confirm reborn load")) + .setLeft(); page->addWidget(new CVarToggleWidget("game-save-confirm-loadonreborn")) + .setRight() .setShortcut('r'); page->addWidget(new LabelWidget("Reborn preferences")) @@ -754,8 +763,10 @@ .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Load last save")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-save-last-loadonreborn")) + .setRight() .setGroup(1) .setShortcut('a'); } @@ -888,31 +899,41 @@ void Hu_MenuInitOptionsPage() { #if __JHERETIC__ || __JHEXEN__ - Vector2i const origin(110, 63); + Vector2i const origin(110, 45); #else Vector2i const origin(110, 63); #endif - Page *page = Hu_MenuAddPage(new Page("Options", origin, 0, Hu_MenuDrawOptionsPage)); + Page *page = Hu_MenuAddPage(new Page("Options", origin, Page::NoScroll, Hu_MenuDrawOptionsPage)); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Main")); page->addWidget(new ButtonWidget("End Game")) .setShortcut('e') .setFont(MENU_FONT1) + .setGroup(1) .setAction(Widget::Deactivated, Hu_MenuSelectEndGame) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); + page->addWidget(new ButtonWidget("Player Setup")) + .setShortcut('p') + .setGroup(1) + .setFont(MENU_FONT1) + .setUserValue(String("PlayerSetup")) + .setAction(Widget::Deactivated, Hu_MenuActionSetActivePage) + .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); + page->addWidget(new ButtonWidget("Show Taskbar")) .setShortcut('t') .setFont(MENU_FONT1) + .setGroup(1) .setAction(Widget::Deactivated, Hu_MenuSelectControlPanelLink) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); - page->addWidget(new ButtonWidget("Multiplayer")) - .setShortcut('m') + page->addWidget(new ButtonWidget("Sound")) + .setShortcut('s') .setFont(MENU_FONT1) - .setUserValue(String("PlayerSetup")) + .setUserValue(String("SoundOptions")) .setAction(Widget::Deactivated, Hu_MenuActionSetActivePage) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); @@ -930,13 +951,6 @@ .setAction(Widget::Deactivated, Hu_MenuActionSetActivePage) .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); - page->addWidget(new ButtonWidget("Game saves")) - .setShortcut('s') - .setFont(MENU_FONT1) - .setUserValue(String("SaveOptions")) - .setAction(Widget::Deactivated, Hu_MenuActionSetActivePage) - .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); - page->addWidget(new ButtonWidget("HUD")) .setShortcut('h') .setFont(MENU_FONT1) @@ -967,12 +981,12 @@ .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); #endif - page->addWidget(new ButtonWidget("Sound")) + page->addWidget(new ButtonWidget("Savegame")) .setShortcut('s') .setFont(MENU_FONT1) - .setUserValue(String("SoundOptions")) + .setUserValue(String("SaveOptions")) .setAction(Widget::Deactivated, Hu_MenuActionSetActivePage) - .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); + .setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); } void Hu_MenuInitGameplayOptionsPage() @@ -986,164 +1000,190 @@ #endif Page *page = Hu_MenuAddPage(new Page("GameplayOptions", origin)); + page->setLeftColumnWidth(.75f); page->setTitle("Gameplay Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("Always Run")); - page->addWidget(new CVarToggleWidget("ctl-run")) + page->addWidget(new LabelWidget("Always Run")).setLeft(); + page->addWidget(new CVarToggleWidget("ctl-run")).setRight() .setShortcut('r'); - page->addWidget(new LabelWidget("Use LookSpring")); - page->addWidget(new CVarToggleWidget("ctl-look-spring")) + page->addWidget(new LabelWidget("Use LookSpring")).setLeft(); + page->addWidget(new CVarToggleWidget("ctl-look-spring")).setRight() .setShortcut('l'); - page->addWidget(new LabelWidget("Disable AutoAim")); - page->addWidget(new CVarToggleWidget("ctl-aim-noauto")) + page->addWidget(new LabelWidget("Disable AutoAim")).setLeft(); + page->addWidget(new CVarToggleWidget("ctl-aim-noauto")).setRight() .setShortcut('a'); #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - page->addWidget(new LabelWidget("Allow Jumping")); - page->addWidget(new CVarToggleWidget("player-jump")) + page->addWidget(new LabelWidget("Allow Jumping")).setLeft(); + page->addWidget(new CVarToggleWidget("player-jump")).setRight() .setShortcut('j'); #endif #if __JDOOM__ - page->addWidget(new LabelWidget("Fast Monsters")); - page->addWidget(new CVarToggleWidget("game-monsters-fast")) + page->addWidget(new LabelWidget("Fast Monsters")).setLeft(); + page->addWidget(new CVarToggleWidget("game-monsters-fast")).setRight() .setShortcut('f'); #endif #if __JDOOM64__ - page->addWidget(new LabelWidget("Weapon Recoil")); - page->addWidget(new CVarToggleWidget("player-weapon-recoil")); + page->addWidget(new LabelWidget("Weapon Recoil")).setLeft(); + page->addWidget(new CVarToggleWidget("player-weapon-recoil")).setRight(); #endif #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ page->addWidget(new LabelWidget("Compatibility")) + .setLeft() .setGroup(1) .setColor(MENU_COLOR2); # if __JDOOM__ || __JDOOM64__ - page->addWidget(new LabelWidget("Any Boss Trigger 666")) + page->addWidget(new LabelWidget("Any Boss Trigger 666")).setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-anybossdeath666")) + page->addWidget(new CVarToggleWidget("game-anybossdeath666")).setRight() .setGroup(1) .setShortcut('b'); # if !__JDOOM64__ page->addWidget(new LabelWidget("Av Resurrects Ghosts")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-raiseghosts")) + .setRight() .setGroup(1) .setShortcut('g'); # if __JDOOM__ page->addWidget(new LabelWidget("VileChase uses Av radius")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-vilechase-usevileradius")) + .setRight() .setGroup(1) .setShortcut('g'); # endif # endif // !__JDOOM64__ page->addWidget(new LabelWidget("PE Limited To 21 Lost Souls")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-maxskulls")) + .setRight() .setGroup(1) .setShortcut('p'); page->addWidget(new LabelWidget("LS Can Get Stuck Inside Walls")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-skullsinwalls")) + .setRight() .setGroup(1); # endif // __JDOOM__ || __JDOOM64__ page->addWidget(new LabelWidget("Monsters Fly Over Obstacles")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-monsters-floatoverblocking")) + .setRight() .setGroup(1); - page->addWidget(new LabelWidget("Monsters Can Get Stuck In Doors")) + page->addWidget(new LabelWidget("Monsters Can Get Stuck\n In Doors")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-monsters-stuckindoors")) + .setRight() .setGroup(1) .setShortcut('d'); - page->addWidget(new LabelWidget("Some Objects Never Hang Over Ledges")) + page->addWidget(new LabelWidget("Some Objects Never Hang\n Over Ledges")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-objects-neverhangoverledges")) + .setRight() .setGroup(1) .setShortcut('h'); page->addWidget(new LabelWidget("Objects Fall Under Own Weight")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-objects-falloff")) + .setRight() .setGroup(1) .setShortcut('f'); #if __JDOOM__ || __JDOOM64__ - page->addWidget(new LabelWidget("All Crushed Objects Become A Pile Of Gibs")) + page->addWidget(new LabelWidget("All Crushed Objects\n Become A Pile Of Gibs")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-objects-gibcrushednonbleeders")) + .setRight() .setGroup(1) .setShortcut('g'); #endif page->addWidget(new LabelWidget("Corpses Slide Down Stairs")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-corpse-sliding")) + .setRight() .setGroup(1) .setShortcut('s'); - page->addWidget(new LabelWidget("Use Exactly Doom's Clipping Code")) + page->addWidget(new LabelWidget("Use Doom's Clipping\n Code Exactly")) + .setLeft() .setGroup(1); page->addWidget(new CVarToggleWidget("game-objects-clipping")) + .setRight() .setGroup(1) .setShortcut('c'); page->addWidget(new LabelWidget(" ^If Not NorthOnly WallRunning")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("game-player-wallrun-northonly")) + .setRight() .setGroup(1) .setShortcut('w'); + page->addWidget(new LabelWidget("Pushable Speed Limit")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("game-objects-pushable-limit")) + .setRight() + .setGroup(1) + .setShortcut('p'); + # if __JDOOM__ || __JDOOM64__ - page->addWidget(new LabelWidget("Zombie Players Can Exit Maps")) + page->addWidget(new LabelWidget("Zombie Players Can\n Exit Maps")).setLeft() .setGroup(1); - - page->addWidget(new CVarToggleWidget("game-zombiescanexit")) + page->addWidget(new CVarToggleWidget("game-zombiescanexit")).setRight() .setGroup(1) .setShortcut('e'); - page->addWidget(new LabelWidget("Fix Ouch Face")) + page->addWidget(new LabelWidget("Fix Ouch Face")).setLeft() .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-face-ouchfix")) + page->addWidget(new CVarToggleWidget("hud-face-ouchfix")).setRight() .setGroup(1); - page->addWidget(new LabelWidget("Fix Weapon Slot Display")) + page->addWidget(new LabelWidget("Fix Weapon Slot Display")).setLeft() .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-status-weaponslots-ownedfix")) + page->addWidget(new CVarToggleWidget("hud-status-weaponslots-ownedfix")).setRight() .setGroup(1); # endif // __JDOOM__ || __JDOOM64__ #endif // __JDOOM__ || __JHERETIC__ || __JDOOM64__ - page->addWidget(new LabelWidget("Vanilla Switch Sound Positioning")) + page->addWidget(new LabelWidget("Vanilla Switch Sound\n Positioning")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("sound-switch-origin")) + .setRight() .setGroup(1) .setShortcut('v'); } @@ -1158,10 +1198,11 @@ Page *page = Hu_MenuAddPage(new Page("HudOptions", origin)); page->setTitle("HUD Options"); + page->setLeftColumnWidth(.45f); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("View Size")); + page->addWidget(new LabelWidget("View Size")).setLeft(); page->addWidget(new CVarSliderWidget("view-size")) #if __JDOOM64__ @@ -1169,108 +1210,43 @@ #else .setRange(3, 13, 1) #endif - .setFloatMode(false); - -#if __JDOOM__ - page->addWidget(new LabelWidget("Single Key Display")); - page->addWidget(new CVarToggleWidget("hud-keys-combine")); -#endif - - page->addWidget(new LabelWidget("AutoHide")); - page->addWidget(new CVarTextualSliderWidget("hud-timer", 0, 60, 1)) - .setEmptyText("Disabled") - .setOnethSuffix(" second") - .setNthSuffix(" seconds"); - - page->addWidget(new LabelWidget("UnHide Events")) - .setGroup(1) - .setColor(MENU_COLOR2); - - page->addWidget(new LabelWidget("Receive Damage")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-damage")) - .setGroup(1); - - page->addWidget(new LabelWidget("Pickup Health")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-health")) - .setGroup(1); - - page->addWidget(new LabelWidget("Pickup Armor")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-armor")) - .setGroup(1); - - page->addWidget(new LabelWidget("Pickup Powerup")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-powerup")) - .setGroup(1); - - page->addWidget(new LabelWidget("Pickup Weapon")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-weapon")) - .setGroup(1); - - page->addWidget(new LabelWidget) -#if __JHEXEN__ - .setText("Pickup Mana") -#else - .setText("Pickup Ammo") -#endif - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-ammo")) - .setGroup(1); - - page->addWidget(new LabelWidget("Pickup Key")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-key")) - .setGroup(1); - -#if __JHERETIC__ || __JHEXEN__ - page->addWidget(new LabelWidget("Pickup Item")) - .setGroup(1); - - page->addWidget(new CVarToggleWidget("hud-unhide-pickup-invitem")) - .setGroup(1); -#endif // __JHERETIC__ || __JHEXEN__ + .setFloatMode(false) + .setRight(); page->addWidget(new LabelWidget("Messages")) .setGroup(2) .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Shown")) + .setLeft() .setGroup(2); - page->addWidget(new CVarToggleWidget("msg-show")) + .setRight() .setGroup(2) .setShortcut('m'); page->addWidget(new LabelWidget("Uptime")) + .setLeft() .setGroup(2); - page->addWidget(new CVarTextualSliderWidget("msg-uptime", 0, 60, 1)) .setEmptyText("Disabled") .setOnethSuffix(" second") .setNthSuffix(" seconds") + .setRight() .setGroup(2); page->addWidget(new LabelWidget("Size")) + .setLeft() .setGroup(2); - page->addWidget(new CVarSliderWidget("msg-scale")) + .setRight() .setGroup(2); page->addWidget(new LabelWidget("Color")) + .setLeft() .setGroup(2); - page->addWidget(new CVarColorEditWidget("msg-color-r", "msg-color-g", "msg-color-b")) + .setRight() .setGroup(2) .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); @@ -1281,8 +1257,8 @@ page->addWidget(new LabelWidget("Symbol")) .setGroup(3) + .setLeft() .setShortcut('c'); - page->addWidget(new CVarInlineListWidget("view-cross-type")) .addItems(ListWidget::Items() << new ListWidgetItem("None", 0) << new ListWidgetItem("Cross", 1) @@ -1290,79 +1266,174 @@ << new ListWidgetItem("Square", 3) << new ListWidgetItem("Open Square", 4) << new ListWidgetItem("Angle", 5)) - .setGroup(3); + .setGroup(3) + .setRight(); page->addWidget(new LabelWidget("Size")) + .setLeft() .setGroup(3); - page->addWidget(new CVarSliderWidget("view-cross-size")) + .setRight() .setGroup(3); page->addWidget(new LabelWidget("Thickness")) + .setLeft() .setGroup(3); - - page->addWidget(new CVarSliderWidget("view-cross-weight")) + page->addWidget(new CVarSliderWidget("view-cross-width", .5f, 5, .25f)) + .setRight() .setGroup(3); page->addWidget(new LabelWidget("Angle")) + .setLeft() .setGroup(3); - page->addWidget(new CVarSliderWidget("view-cross-angle", 0.0f, 1.0f, 0.0625f)) + .setRight() .setGroup(3); page->addWidget(new LabelWidget("Opacity")) + .setLeft() .setGroup(3); - page->addWidget(new CVarSliderWidget("view-cross-a")) + .setRight() .setGroup(3); - page->addWidget(new LabelWidget("Vitality Color")) + page->addWidget(new LabelWidget("Color")) + .setLeft() .setGroup(3); + page->addWidget(new CVarColorEditWidget("view-cross-r", "view-cross-g", "view-cross-b")) + .setRight() + .setGroup(3) + .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) + .setAction(Widget::Activated, Hu_MenuActivateColorWidget); + page->addWidget(new LabelWidget("Vitality Color")) + .setLeft() + .setGroup(3); page->addWidget(new CVarToggleWidget("view-cross-vitality")) + .setRight() .setGroup(3); - page->addWidget(new LabelWidget("Vitality Colour (Dead)")) + page->addWidget(new LabelWidget(" When Dead")) + .setLeft() .setGroup(3); - page->addWidget(new CVarColorEditWidget("view-cross-dead-r", "view-cross-dead-g", "view-cross-dead-b")) + .setRight() .setGroup(3) .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Vitality Colour (Full Health)")) + page->addWidget(new LabelWidget(" Full Health")) + .setLeft() .setGroup(3); page->addWidget(new CVarColorEditWidget("view-cross-live-r", "view-cross-live-g", "view-cross-live-b")) + .setRight() .setGroup(3) .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Color")) - .setGroup(3); - - page->addWidget(new CVarColorEditWidget("view-cross-r", "view-cross-g", "view-cross-b")) - .setGroup(3) - .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) - .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - #if __JDOOM__ || __JHERETIC__ || __JHEXEN__ page->addWidget(new LabelWidget("Statusbar")) .setGroup(4) .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Size")) + .setLeft() .setGroup(4); - page->addWidget(new CVarSliderWidget("hud-status-size")) + .setRight() .setGroup(4); page->addWidget(new LabelWidget("Opacity")) + .setLeft() .setGroup(4); - page->addWidget(new CVarSliderWidget("hud-status-alpha")) + .setRight() + .setGroup(4); + +#if __JDOOM__ + page->addWidget(new LabelWidget("Single Key Display")).setLeft().setGroup(4); + page->addWidget(new CVarToggleWidget("hud-keys-combine")).setRight().setGroup(4); +#endif + + page->addWidget(new LabelWidget("AutoHide Status")) + .setLeft() + .setGroup(4); + page->addWidget(new CVarTextualSliderWidget("hud-timer", 0, 60, 1)) + .setEmptyText("Disabled") + .setOnethSuffix(" second") + .setNthSuffix(" seconds") + .setRight() .setGroup(4); + page->addWidget(new LabelWidget("Status UnHide Events")) + .setGroup(1) + .setColor(MENU_COLOR2); + + page->addWidget(new LabelWidget("Receive Damage")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-damage")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Pickup Health")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-health")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Pickup Armor")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-armor")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Pickup Powerup")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-powerup")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Pickup Weapon")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-weapon")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget) +#if __JHEXEN__ + .setText("Pickup Mana") +#else + .setText("Pickup Ammo") +#endif + .setGroup(1) + .setLeft(); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-ammo")) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Pickup Key")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-key")) + .setRight() + .setGroup(1); + +#if __JHERETIC__ || __JHEXEN__ + page->addWidget(new LabelWidget("Pickup Item")) + .setLeft() + .setGroup(1); + + page->addWidget(new CVarToggleWidget("hud-unhide-pickup-invitem")) + .setRight() + .setGroup(1); +#endif // __JHERETIC__ || __JHEXEN__ + #endif // __JDOOM__ || __JHERETIC__ || __JHEXEN__ #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ @@ -1371,17 +1442,19 @@ .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Items")) + .setLeft() .setGroup(5); - page->addWidget(new CVarInlineListWidget("hud-cheat-counter", CCH_ITEMS | CCH_ITEMS_PRCNT)) .addItems(ListWidget::Items() << new ListWidgetItem("Hidden", 0) << new ListWidgetItem("Count", CCH_ITEMS) << new ListWidgetItem("Percent", CCH_ITEMS_PRCNT) << new ListWidgetItem("Count+Percent", CCH_ITEMS | CCH_ITEMS_PRCNT)) + .setRight() .setGroup(5) .setShortcut('i'); page->addWidget(new LabelWidget("Kills")) + .setLeft() .setGroup(5); page->addWidget(new CVarInlineListWidget("hud-cheat-counter", CCH_KILLS | CCH_KILLS_PRCNT)) @@ -1389,30 +1462,34 @@ << new ListWidgetItem("Count", CCH_KILLS) << new ListWidgetItem("Percent", CCH_KILLS_PRCNT) << new ListWidgetItem("Count+Percent", CCH_KILLS | CCH_KILLS_PRCNT)) + .setRight() .setGroup(5) .setShortcut('k'); page->addWidget(new LabelWidget("Secrets")) + .setLeft() .setGroup(5); - page->addWidget(new CVarInlineListWidget("hud-cheat-counter", CCH_SECRETS | CCH_SECRETS_PRCNT)) .addItems(ListWidget::Items() << new ListWidgetItem("Hidden", 0) << new ListWidgetItem("Count", CCH_SECRETS) << new ListWidgetItem("Percent", CCH_SECRETS_PRCNT) << new ListWidgetItem("Count+Percent", CCH_SECRETS | CCH_SECRETS_PRCNT)) .setGroup(5) + .setRight() .setShortcut('s'); page->addWidget(new LabelWidget("Automap Only")) + .setLeft() .setGroup(5); - page->addWidget(new CVarToggleWidget("hud-cheat-counter-show-mapopen")) + .setRight() .setGroup(5); page->addWidget(new LabelWidget("Size")) + .setLeft() .setGroup(5); - page->addWidget(new CVarSliderWidget("hud-cheat-counter-scale")) + .setRight() .setGroup(5); #endif // __JDOOM__ || __JDOOM64__ || __JHERETIC__ @@ -1422,15 +1499,17 @@ .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Size")) + .setLeft() .setGroup(6); - page->addWidget(new CVarSliderWidget("hud-scale")) + .setRight() .setGroup(6); page->addWidget(new LabelWidget("Text Color")) + .setLeft() .setGroup(6); - page->addWidget(new CVarColorEditWidget("hud-color-r", "hud-color-g", "hud-color-b", "hud-color-a", Vector4f(), true)) + .setRight() .setGroup(6) .setAction(Widget::Deactivated, CVarColorEditWidget_UpdateCVar) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); @@ -1438,9 +1517,11 @@ #if __JHEXEN__ page->addWidget(new LabelWidget("Show Mana")) + .setLeft() .setGroup(6); page->addWidget(new CVarToggleWidget("hud-mana")) + .setRight() .setGroup(6); #endif // __JHEXEN__ @@ -1448,16 +1529,18 @@ #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ page->addWidget(new LabelWidget("Show Ammo")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-ammo")) + .setRight() .setGroup(6) .setShortcut('a'); page->addWidget(new LabelWidget("Show Armor")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-armor")) + .setRight() .setGroup(6) .setShortcut('r'); @@ -1466,9 +1549,10 @@ #if __JDOOM64__ page->addWidget(new LabelWidget("Show PowerKeys")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-power")) + .setRight() .setGroup(6) .setShortcut('p'); @@ -1477,27 +1561,30 @@ #if __JDOOM__ page->addWidget(new LabelWidget("Show Status")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-face")) + .setRight() .setGroup(6) .setShortcut('f'); #endif // __JDOOM__ page->addWidget(new LabelWidget("Show Health")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-health")) + .setRight() .setGroup(6) .setShortcut('h'); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ page->addWidget(new LabelWidget("Show Keys")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-keys")) + .setRight() .setGroup(6); #endif // __JDOOM__ || __JDOOM64__ || __JHERETIC__ @@ -1505,9 +1592,10 @@ #if __JHERETIC__ || __JHEXEN__ page->addWidget(new LabelWidget("Show Ready-Item")) + .setLeft() .setGroup(6); - page->addWidget(new CVarToggleWidget("hud-currentitem")) + .setRight() .setGroup(6); #endif // __JHERETIC__ || __JHEXEN__ @@ -1516,77 +1604,150 @@ void Hu_MenuInitAutomapOptionsPage() { #if __JHERETIC__ || __JHEXEN__ - Vector2i const origin(64, 28); + const Vector2i origin(32, 28); #else - Vector2i const origin(70, 40); + const Vector2i origin(70, 40); #endif Page *page = Hu_MenuAddPage(new Page("AutomapOptions", origin)); + page->setLeftColumnWidth(.55f); page->setTitle("Automap Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("Background Opacity")); - page->addWidget(new CVarSliderWidget("map-opacity")) - .setShortcut('o'); - - page->addWidget(new LabelWidget("Line Opacity")); - page->addWidget(new CVarSliderWidget("map-line-opacity")) - .setShortcut('l'); - - page->addWidget(new LabelWidget("Line Width")); - page->addWidget(new CVarSliderWidget("map-line-width", 0.1f, 2.f)); - - page->addWidget(new LabelWidget("HUD Display")); + page->addWidget(new LabelWidget("Rotation")) + .setLeft(); + { + auto *tgl = new CVarToggleWidget("map-rotate"); + tgl->setRight(); + tgl->setShortcut('r'); + tgl->setStateChangeCallback([](CVarToggleWidget::State state) { + G_SetAutomapRotateMode(state == CVarToggleWidget::Down); + }); + page->addWidget(tgl); + } + + page->addWidget(new LabelWidget("Always Update Map")) + .setLeft(); + page->addWidget(new CVarToggleWidget("map-neverobscure")) + .setRight() + .setShortcut('a') + .setHelpInfo("Update map even when background is opaque"); -#if !__JDOOM64__ +#if !defined (__JDOOM64__) + page->addWidget(new LabelWidget("HUD Display")) + .setLeft(); page->addWidget(new CVarInlineListWidget("map-huddisplay")) .addItems(ListWidget::Items() << new ListWidgetItem("None", 0) << new ListWidgetItem("Current", 1) << new ListWidgetItem("Statusbar", 2)) + .setRight() .setShortcut('h'); #endif - page->addWidget(new LabelWidget("Door Colors")); + page->addWidget(new LabelWidget("Appearance")) + .setGroup(1) + .setColor(MENU_COLOR2); + + page->addWidget(new LabelWidget("Background Opacity")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarSliderWidget("map-opacity")) + .setShortcut('o') + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Line Opacity")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarSliderWidget("map-line-opacity")) + .setShortcut('l') + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Line Width")) + .setLeft() + .setGroup(1); + page->addWidget(new CVarSliderWidget("map-line-width", 0.5f, 8.f)) + .setRight() + .setGroup(1); + + page->addWidget(new LabelWidget("Colored Doors")) + .setLeft() + .setGroup(1); page->addWidget(new CVarToggleWidget("map-door-colors")) - .setShortcut('d'); + .setRight() + .setShortcut('d') + .setGroup(1); - page->addWidget(new LabelWidget("Door Glow")); + page->addWidget(new LabelWidget("Door Glow")) + .setLeft() + .setGroup(1); page->addWidget(new CVarSliderWidget("map-door-glow", 0, 200, 5)) - .setShortcut('g'); + .setRight() + .setShortcut('g') + .setGroup(1); - page->addWidget(new LabelWidget("Use Custom Colors")); + page->addWidget(new LabelWidget("Use Custom Colors")) + .setLeft() + .setGroup(2); page->addWidget(new CVarInlineListWidget("map-customcolors")) .addItems(ListWidget::Items() << new ListWidgetItem("Never", 0) << new ListWidgetItem("Auto", 1) - << new ListWidgetItem("Always", 2)); + << new ListWidgetItem("Always", 2)) + .setRight() + .setGroup(2); - page->addWidget(new LabelWidget("Wall")); + page->addWidget(new LabelWidget("Wall")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-wall-r", "map-wall-g", "map-wall-b")) + .setRight() .setShortcut('w') + .setGroup(2) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Floor Height Change")); + page->addWidget(new LabelWidget("Floor Height Change")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-wall-floorchange-r", "map-wall-floorchange-g", "map-wall-floorchange-b")) + .setRight() .setShortcut('f') + .setGroup(2) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Ceiling Height Change")); + page->addWidget(new LabelWidget("Ceiling Height Change")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-wall-ceilingchange-r", "map-wall-ceilingchange-g", "map-wall-ceilingchange-b")) + .setRight() + .setGroup(2) .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Unseen")); + page->addWidget(new LabelWidget("Unseen")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-wall-unseen-r", "map-wall-unseen-g", "map-wall-unseen-b")) + .setRight() + .setGroup(2) .setShortcut('u') .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Thing")); + page->addWidget(new LabelWidget("Thing")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-mobj-r", "map-mobj-g", "map-mobj-b")) + .setRight() + .setGroup(2) .setShortcut('t') .setAction(Widget::Activated, Hu_MenuActivateColorWidget); - page->addWidget(new LabelWidget("Background")); + page->addWidget(new LabelWidget("Background")) + .setLeft() + .setGroup(2); page->addWidget(new CVarColorEditWidget("map-background-r", "map-background-g", "map-background-b")) + .setRight() + .setGroup(2) .setShortcut('b') .setAction(Widget::Activated, Hu_MenuActivateColorWidget); } @@ -1596,11 +1757,11 @@ int i = 0, aIndex = -1, bIndex = -1; do { - if(cfg.common.weaponOrder[i] == a->userValue()) + if (cfg.common.weaponOrder[i] == a->userValue()) { aIndex = i; } - if(cfg.common.weaponOrder[i] == b->userValue()) + if (cfg.common.weaponOrder[i] == b->userValue()) { bIndex = i; } @@ -1656,6 +1817,7 @@ }; Page *page = Hu_MenuAddPage(new Page("WeaponOptions", origin)); + page->setLeftColumnWidth(.5f); page->setTitle("Weapons Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); @@ -1664,7 +1826,7 @@ .setColor(MENU_COLOR2); ListWidget::Items weapItems; - for(int i = 0; weaponOrder[i].data < NUM_WEAPON_TYPES; ++i) + for (int i = 0; weaponOrder[i].data < NUM_WEAPON_TYPES; ++i) { char const *itemText = weaponOrder[i].text; if(itemText && (PTR2INT(itemText) > 0 && PTR2INT(itemText) < NUMTEXT)) @@ -1676,6 +1838,7 @@ qSort(weapItems.begin(), weapItems.end(), compareWeaponPriority); page->addWidget(new ListWidget) .addItems(weapItems) + .setReorderingEnabled(true) .setHelpInfo("Use left/right to move weapon up/down") .setShortcut('p') .setColor(MENU_COLOR3) @@ -1687,16 +1850,18 @@ .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Use Priority Order")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("player-weapon-nextmode")) + .setRight() .setGroup(1) .setShortcut('o'); page->addWidget(new LabelWidget("Sequential")) + .setLeft() .setGroup(1); - page->addWidget(new CVarToggleWidget("player-weapon-cycle-sequential")) + .setRight() .setGroup(1) .setShortcut('s'); @@ -1705,38 +1870,42 @@ .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Pickup Weapon")) + .setLeft() .setGroup(2); - page->addWidget(new CVarInlineListWidget("player-autoswitch")) .addItems(ListWidget::Items() << new ListWidgetItem("Never", 0) << new ListWidgetItem("If Better", 1) << new ListWidgetItem("Always", 2)) .setGroup(2) + .setRight() .setShortcut('w'); page->addWidget(new LabelWidget(" If Not Firing")) + .setLeft() .setGroup(2); - page->addWidget(new CVarToggleWidget("player-autoswitch-notfiring")) + .setRight() .setGroup(2) .setShortcut('f'); page->addWidget(new LabelWidget("Pickup Ammo")) + .setLeft() .setGroup(2); - page->addWidget(new CVarInlineListWidget("player-autoswitch-ammo")) .addItems(ListWidget::Items() << new ListWidgetItem("Never", 0) << new ListWidgetItem("If Better", 1) << new ListWidgetItem("Always", 2)) .setGroup(2) + .setRight() .setShortcut('a'); #if __JDOOM__ || __JDOOM64__ page->addWidget(new LabelWidget("Pickup Beserk")) + .setLeft() .setGroup(2); - page->addWidget(new CVarToggleWidget("player-autoswitch-berserk")) + .setRight() .setGroup(2) .setShortcut('b'); @@ -1747,75 +1916,95 @@ void Hu_MenuInitInventoryOptionsPage() { Page *page = Hu_MenuAddPage(new Page("InventoryOptions", Vector2i(78, 48))); + page->setLeftColumnWidth(.65f); page->setTitle("Inventory Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("Select Mode")); + page->addWidget(new LabelWidget("Select Mode")) + .setLeft(); page->addWidget(new CVarToggleWidget("ctl-inventory-mode", 0, "Scroll", "Cursor")) + .setRight() .setShortcut('s'); - page->addWidget(new LabelWidget("Wrap Around")); + page->addWidget(new LabelWidget("Wrap Around")) + .setLeft(); page->addWidget(new CVarToggleWidget("ctl-inventory-wrap")) + .setRight() .setShortcut('w'); - page->addWidget(new LabelWidget("Choose And Use")); + page->addWidget(new LabelWidget("Choose And Use")) + .setLeft(); page->addWidget(new CVarToggleWidget("ctl-inventory-use-immediate")) + .setRight() .setShortcut('c'); - page->addWidget(new LabelWidget("Select Next If Use Failed")); + page->addWidget(new LabelWidget("Select Next If Use Failed")) + .setLeft(); page->addWidget(new CVarToggleWidget("ctl-inventory-use-next")) + .setRight() .setShortcut('n'); - page->addWidget(new LabelWidget("AutoHide")); + page->addWidget(new LabelWidget("AutoHide")) + .setLeft(); page->addWidget(new CVarTextualSliderWidget("hud-inventory-timer", 0, 30, 1.f)) .setEmptyText("Disabled") .setOnethSuffix(" second") .setNthSuffix(" seconds") - .setShortcut('h'); + .setShortcut('h') + .setRight(); page->addWidget(new LabelWidget("Fullscreen HUD")) .setGroup(1) .setColor(MENU_COLOR2); page->addWidget(new LabelWidget("Max Visible Slots")) + .setLeft() .setGroup(1); page->addWidget(new CVarTextualSliderWidget("hud-inventory-slot-max", 0, 16, 1, false)) .setEmptyText("Automatic") + .setRight() .setGroup(1) .setShortcut('v'); page->addWidget(new LabelWidget("Show Empty Slots")) - .setGroup(1); + .setGroup(1) + .setLeft(); page->addWidget(new CVarToggleWidget("hud-inventory-slot-showempty")) .setGroup(1) + .setRight() .setShortcut('e'); } #endif void Hu_MenuInitSoundOptionsPage() { -#if __JHEXEN__ - Vector2i const origin(97, 25); -#elif __JHERETIC__ - Vector2i const origin(97, 30); -#elif __JDOOM__ || __JDOOM64__ +//#if __JHEXEN__ +// Vector2i const origin(97, 25); +//#elif __JHERETIC__ +// Vector2i const origin(97, 30); +//#elif __JDOOM__ || __JDOOM64__ Vector2i const origin(97, 40); -#endif +//#endif Page *page = Hu_MenuAddPage(new Page("SoundOptions", origin)); + page->setLeftColumnWidth(.4f); page->setTitle("Sound Options"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); - page->addWidget(new LabelWidget("SFX Volume")); - page->addWidget(new CVarSliderWidget("sound-volume", 0, 255, 5, false)) + page->addWidget(new LabelWidget("SFX Volume")) + .setLeft(); + page->addWidget(new CVarSliderWidget("sound-volume", 0, 255, 16, false)) + .setRight() .setShortcut('s'); - page->addWidget(new LabelWidget("Music Volume")); - page->addWidget(new CVarSliderWidget("music-volume", 0, 255, 5, false)) + page->addWidget(new LabelWidget("Music Volume")) + .setLeft(); + page->addWidget(new CVarSliderWidget("music-volume", 0, 255, 16, false)) + .setRight() .setShortcut('m'); } @@ -1832,33 +2021,54 @@ Vector2i const origin(48, 63); #endif - Page *page = Hu_MenuAddPage(new Page("Episode", origin, Page::FixedLayout, Hu_MenuDrawEpisodePage)); + Page *page = + Hu_MenuAddPage(new Page("Episode", origin, Page::FixedLayout, Hu_MenuDrawEpisodePage)); + page->setPredefinedFont(MENU_FONT1, FID(GF_FONTB)); page->setPreviousPage(Hu_MenuPagePtr("Main")); + page->setOnActiveCallback([](Page &page) { + const auto &items = page.children(); + if (items.size() == 1) + { + // If there is only one episode, select it automatically. + auto &ep = items.front()->as(); + ep.setSilent(true); + ep.handleCommand(MCMD_SELECT); + ep.setSilent(false); + } + }); - DictionaryValue::Elements const &episodesById = Defs().episodes.lookup("id").elements(); - if(!episodesById.size()) + const DictionaryValue::Elements &episodesById = Defs().episodes.lookup("id").elements(); + if (!episodesById.size()) { - LOG_WARNING("No episodes are defined. It will not be possible to start a new game from the menu"); + LOG_WARNING( + "No episodes are defined. It will not be possible to start a new game from the menu"); return; } int y = 0; int n = 0; - for(auto const &pair : episodesById) + for (auto const &pair : episodesById) + { + const Record &episodeDef = *pair.second->as().record(); + const String episodeId = episodeDef.gets("id"); + const String episodeTitle = G_EpisodeTitle(episodeId); + + if (episodeTitle.empty()) { - Record const &episodeDef = *pair.second->as().record(); - String const episodeId = episodeDef.gets("id"); + // Hidden/untitled episode. + continue; + } - auto *btn = new ButtonWidget(G_EpisodeTitle(episodeId)); + auto *btn = new ButtonWidget(episodeTitle); btn->setFixedY(y); // Has a menu image been specified? de::Uri image(episodeDef.gets("menuImage"), RC_NULL); - if(!image.path().isEmpty()) + if (!image.path().isEmpty()) { // Presently only patches are supported. - if(!image.scheme().compareWithoutCase("Patches")) + if (!image.scheme().compareWithoutCase("Patches")) { btn->setPatch(R_DeclarePatch(image.path().toUtf8().constData())); } @@ -1867,20 +2077,20 @@ // Has a menu shortcut/hotkey been specified? /// @todo Validate symbolic dday key names. String const shortcut = episodeDef.gets("menuShortcut"); - if(!shortcut.isEmpty() && shortcut.first().isLetterOrNumber()) + if (!shortcut.isEmpty() && shortcut.first().isLetterOrNumber()) { btn->setShortcut(shortcut.first().toLower().toLatin1()); } // Has a menu help/info text been specified? String const helpInfo = episodeDef.gets("menuHelpInfo"); - if(!helpInfo.isEmpty()) + if (!helpInfo.isEmpty()) { btn->setHelpInfo(helpInfo); } de::Uri startMap(episodeDef.gets("startMap"), RC_NULL); - if(P_MapExists(startMap.compose().toUtf8().constData())) + if (P_MapExists(startMap.compose().toUtf8().constData())) { btn->setAction(Widget::Deactivated, Hu_MenuSelectEpisode); btn->setUserValue(episodeId); @@ -1889,12 +2099,12 @@ { #if __JDOOM__ || __JHERETIC__ // In shareware display a prompt to buy the full game. - if( -#if __JHERETIC__ + if ( +# if __JHERETIC__ gameMode == heretic_shareware -#else // __JDOOM__ +# else // __JDOOM__ gameMode == doom_shareware -#endif +# endif && startMap.path() != "E1M1") { btn->setAction(Widget::Deactivated, Hu_MenuActivateNotSharewareEpisode); @@ -2113,7 +2323,7 @@ { cursor.angle += float( 5 * ticLength * TICRATE ); } - else if(cursor.angle != 0) + else if (!fequal(cursor.angle, 0)) { float rewind = float( MENU_CURSOR_REWIND_SPEED * ticLength * TICRATE ); if(cursor.angle <= rewind || cursor.angle >= 360 - rewind) @@ -2171,7 +2381,7 @@ if(!menuActive) return; if(!page) return; - if(!(Get(DD_DEDICATED) || Get(DD_NOVIDEO))) + if(!Get(DD_NOVIDEO)) { FR_ResetTypeinTimer(); } @@ -2206,14 +2416,14 @@ return ((~cfg.common.menuEffectFlags & DTF_NO_EFFECTS) | (f & ~DTF_NO_EFFECTS)); } -void Hu_MenuDrawFocusCursor(Vector2i const &origin, int focusObjectHeight, float alpha) +void Hu_MenuDrawFocusCursor(Vector2i const &origin, float scale, float alpha) { #if __JDOOM__ || __JDOOM64__ # define OFFSET_X (-22) -# define OFFSET_Y (-2) +# define OFFSET_Y (-1) #elif __JHERETIC__ || __JHEXEN__ # define OFFSET_X (-16) -# define OFFSET_Y (3) +# define OFFSET_Y (1) #endif float const angle = cursor.angle; @@ -2224,9 +2434,9 @@ if(!R_GetPatchInfo(pCursor, &info)) return; - float const scale = de::min((focusObjectHeight * 1.267f) / info.geometry.size.height, 1.f); +// float const scale = /*de::min((focusObjectHeight * 1.267f) /*/ 1; //info.geometry.size.height; //, 1.f); Vector2i pos = origin + Vector2i(OFFSET_X, OFFSET_Y) * scale; - pos.y += focusObjectHeight / 2; +// pos.y -= info.geometry.size.height / 2; DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); @@ -2267,6 +2477,13 @@ { if(helpText.isEmpty()) return; + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); + + DGL_Translatef(SCREENWIDTH / 2, SCREENHEIGHT, 0); + DGL_Scalef(.666666f, .666666f, 1.f); + DGL_Translatef(-SCREENWIDTH / 2, -SCREENHEIGHT, 0); + DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(FID(GF_FONTA)); FR_SetColorv(cfg.common.menuTextColors[1]); @@ -2275,6 +2492,9 @@ FR_DrawTextXY3(helpText.toUtf8().constData(), origin.x, origin.y, ALIGN_BOTTOM, Hu_MenuMergeEffectWithDrawTextFlags(0)); DGL_Disable(DGL_TEXTURE_2D); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); } static void drawOverlayBackground(float darken) @@ -2957,7 +3177,7 @@ void Hu_MenuDrawOptionsPage(Page const & /*page*/, Vector2i const &origin) { #if __JHERETIC__ || __JHEXEN__ - Hu_MenuDrawPageTitle("Options", Vector2i(origin.x + 42, origin.y - 38)); + Hu_MenuDrawPageTitle("Options", Vector2i(origin.x + 42, origin.y - 30)); #else DGL_Enable(DGL_TEXTURE_2D); DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); @@ -3007,30 +3227,16 @@ } } -void Hu_MenuChangeWeaponPriority(Widget & /*wi*/, Widget::Action action) +void Hu_MenuChangeWeaponPriority(Widget &wi, Widget::Action action) { - if(action != Widget::Modified) return; - - /*int choice = option >> NUM_WEAPON_TYPES; - - if(option & RIGHT_DIR) + if (action == Widget::Modified) { - if(choice < NUM_WEAPON_TYPES-1) + auto &list = wi.as(); + for (int i = 0; i < list.itemCount(); ++i) { - int temp = cfg.common.weaponOrder[choice+1]; - cfg.common.weaponOrder[choice+1] = cfg.common.weaponOrder[choice]; - cfg.common.weaponOrder[choice] = temp; - } + cfg.common.weaponOrder[i] = list.itemData(i); } - else - { - if(choice > 0) - { - int temp = cfg.common.weaponOrder[choice]; - cfg.common.weaponOrder[choice] = cfg.common.weaponOrder[choice-1]; - cfg.common.weaponOrder[choice-1] = temp; } - }*/ } void Hu_MenuSelectSingleplayer(Widget & /*wi*/, Widget::Action action) @@ -3207,7 +3413,7 @@ { if(action != Widget::Deactivated) return; - if(!Get(DD_DEDICATED)) + if(!Get(DD_NOVIDEO)) { if(IS_CLIENT && !Get(DD_PLAYBACK)) { @@ -3225,7 +3431,7 @@ if(action != Widget::Deactivated) return; - if(!Get(DD_DEDICATED)) + if(!Get(DD_NOVIDEO)) { if(IS_CLIENT) { @@ -3384,11 +3590,11 @@ cfg.playerClass[CONSOLEPLAYER] = playerclass_t(mnPlrClass); #endif - GameRuleset newRules(defaultGameRules); - newRules.skill = mnSkillmode; + GameRules newRules{gfw_DefaultGameRules()}; + GameRules_Set(newRules, skill, mnSkillmode); Record const &episodeDef = Defs().episodes.find("id", mnEpisode); - G_SetGameActionNewSession(newRules, mnEpisode, de::Uri(episodeDef.gets("startMap"), RC_NULL)); + G_SetGameActionNewSession(newRules, mnEpisode, de::makeUri(episodeDef.gets("startMap"))); } void Hu_MenuActionInitNewGame(Widget & /*wi*/, Widget::Action action) @@ -3543,10 +3749,6 @@ #endif C_VAR_BYTE ("menu-save-suggestname", &cfg.common.menuGameSaveSuggestDescription, 0, 0, 1); - // Aliases for obsolete cvars: - C_VAR_BYTE ("menu-turningskull", &cfg.common.menuCursorRotate, 0, 0, 1); - - C_CMD("menu", "s", MenuOpen); C_CMD("menu", "", MenuOpen); C_CMD("menuup", "", MenuCommand); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_msg.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_msg.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_msg.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_msg.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -133,7 +133,7 @@ #define LEADING (0) short textFlags = Hu_MenuMergeEffectWithDrawTextFlags(0); - Point2Raw origin( SCREENWIDTH/2, SCREENHEIGHT/2); + Point2Raw origin = {{{SCREENWIDTH/2, SCREENHEIGHT/2}}}; char const *questionString = ""; switch(msgType) @@ -252,7 +252,7 @@ composeYesNoMessage(); } - if(!(Get(DD_DEDICATED) || Get(DD_NOVIDEO))) + if(!Get(DD_NOVIDEO)) { FR_ResetTypeinTimer(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_stuff.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_stuff.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/hu_stuff.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/hu_stuff.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -210,7 +210,7 @@ static void prepareFogTexture() { - if(Get(DD_NOVIDEO) || Get(DD_DEDICATED)) return; + if(Get(DD_NOVIDEO)) return; // Already prepared? if(fogEffectData.texture) return; @@ -228,7 +228,7 @@ static void releaseFogTexture() { - if(Get(DD_NOVIDEO) || Get(DD_DEDICATED)) return; + if(Get(DD_NOVIDEO)) return; // Not prepared? if(!fogEffectData.texture) return; @@ -349,7 +349,7 @@ if(a->kills > b->kills) return -1; if(b->kills > a->kills) return 1; - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { // In deathmatch, suicides affect your place on the scoreboard. if(a->suicides < b->suicides) return -1; @@ -424,7 +424,7 @@ } #endif - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { for(int j = 0; j < maxPlayers; ++j) { @@ -682,11 +682,11 @@ { #define BORDER 2 - de::String title = G_MapTitle(COMMON_GAMESESSION->mapUri()); + de::String title = G_MapTitle(gfw_Session()->mapUri()); if(title.isEmpty()) title = "Unnamed"; char buf[256]; - dd_snprintf(buf, 256, "%s - %s", COMMON_GAMESESSION->rules().description().toLatin1().constData(), + dd_snprintf(buf, 256, "%s - %s", gfw_Session()->rules().description().toLatin1().constData(), title.toLatin1().constData()); FR_SetColorAndAlpha(1, 1, 1, alpha); @@ -738,7 +738,7 @@ int inCount = populateScoreInfo(scoreBoard, MAXPLAYERS, player); // Determine the dimensions of the scoreboard: - RectRaw geom = RectRaw(0, 0, SCREENWIDTH - 32, SCREENHEIGHT - 32); + RectRaw geom = {{0, 0}, {SCREENWIDTH - 32, SCREENHEIGHT - 32}}; DGL_MatrixMode(DGL_MODELVIEW); DGL_PushMatrix(); @@ -1111,7 +1111,7 @@ if(!replacement.isEmpty()) { // Use the replacement string. - Point2Raw const originAsPoint2Raw(origin.x, origin.y); + const Point2Raw originAsPoint2Raw = {{{origin.x, origin.y}}}; FR_DrawText3(replacement.toUtf8().constData(), &originAsPoint2Raw, alignFlags, textFlags); return; } @@ -1362,7 +1362,7 @@ int Hu_MapTitleFirstLineHeight() { int y = 0; - de::Uri titleImage = G_MapTitleImage(COMMON_GAMESESSION->mapUri()); + de::Uri titleImage = G_MapTitleImage(gfw_Session()->mapUri()); if(!titleImage.isEmpty()) { if(!titleImage.scheme().compareWithoutCase("Patches")) @@ -1381,7 +1381,7 @@ dd_bool Hu_IsMapTitleAuthorVisible() { - de::String const author = G_MapAuthor(COMMON_GAMESESSION->mapUri(), CPP_BOOL(cfg.common.hideIWADAuthor)); + de::String const author = G_MapAuthor(gfw_Session()->mapUri(), CPP_BOOL(cfg.common.hideIWADAuthor)); return !author.isEmpty() && (actualMapTime <= 6 * TICSPERSEC); } @@ -1400,7 +1400,7 @@ void Hu_DrawMapTitle(float alpha, dd_bool mapIdInsteadOfAuthor) { - de::Uri const mapUri = COMMON_GAMESESSION->mapUri(); + de::Uri const mapUri = gfw_Session()->mapUri(); de::String const title = G_MapTitle(mapUri); de::String const author = G_MapAuthor(mapUri, CPP_BOOL(cfg.common.hideIWADAuthor)); @@ -1493,8 +1493,8 @@ scalemode_t(cfg.common.menuScaleMode)); // Determine origin of the title. - Point2Raw origin(portGeometry->size.width / 2, - 6 * portGeometry->size.height / SCREENHEIGHT); + Point2Raw origin = {{{portGeometry->size.width / 2, + 6 * portGeometry->size.height / SCREENHEIGHT}}}; // Should the title be positioned in the bottom of the view? if(cfg.common.automapTitleAtBottom && @@ -1573,7 +1573,7 @@ void M_DrawShadowedPatch3(patchid_t id, int x, int y, int alignFlags, int patchFlags, float r, float g, float b, float a) { - if(id == 0 || DD_GetInteger(DD_NOVIDEO) || DD_GetInteger(DD_DEDICATED)) + if(id == 0 || DD_GetInteger(DD_NOVIDEO)) return; DGL_Color4f(0, 0, 0, a * .4f); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/m_ctrl.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/m_ctrl.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/m_ctrl.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/m_ctrl.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -104,13 +104,13 @@ #endif #ifdef __JHERETIC__ - { (char const *) TXT_TXT_INV_INVULNERABILITY, 0, 0, "impulse invulnerability", 0 }, + { /* (char const *) TXT_TXT_INV_INVULNERABILITY */ "Invincibility", 0, 0, "impulse invulnerability", 0 }, { (char const *) TXT_TXT_INV_INVISIBILITY, 0, 0, "impulse invisibility", 0 }, { (char const *) TXT_TXT_INV_HEALTH, 0, 0, "impulse health", 0 }, { (char const *) TXT_TXT_INV_SUPERHEALTH, 0, 0, "impulse superhealth", 0 }, { (char const *) TXT_TXT_INV_TOMEOFPOWER, 0, 0, "impulse tome", 0 }, { (char const *) TXT_TXT_INV_TORCH, 0, 0, "impulse torch", 0 }, - { (char const *) TXT_TXT_INV_FIREBOMB, 0, 0, "impulse firebomb", 0 }, + { /* (char const *) TXT_TXT_INV_FIREBOMB */ "Time Bomb", 0, 0, "impulse firebomb", 0 }, { (char const *) TXT_TXT_INV_EGG, 0, 0, "impulse egg", 0 }, { (char const *) TXT_TXT_INV_FLY, 0, 0, "impulse fly", 0 }, { (char const *) TXT_TXT_INV_TELEPORT, 0, 0, "impulse teleport", 0 }, @@ -182,7 +182,7 @@ { "Smaller View", 0, 0, "sub view-size 1", CCF_REPEAT }, { "Larger View", 0, 0, "add view-size 1", CCF_REPEAT }, - { "Message Refresh", 0, 0, "impulse msgrefresh", 0 }, + { "Msg Refresh", 0, 0, "impulse msgrefresh", 0 }, { "Shortcuts", 0, 0, 0, 0 }, { "Pause Game", 0, 0, "pause", 0 }, @@ -196,7 +196,7 @@ { "Quick Load", "shortcut", 0, "quickload", 0 }, { "Sound Options", "shortcut", 0, "menu soundoptions", 0 }, { "Toggle Messages", "shortcut", 0, "toggle msg-show", 0 }, - { "Gamma Correction", "shortcut", 0, "togglegamma", 0 }, + { "Gamma Adjust", "shortcut", 0, "togglegamma", 0 }, { "Screenshot", "shortcut", 0, "screenshot", 0 }, { "Quit", "shortcut", 0, "quit", 0 }, @@ -214,8 +214,8 @@ { "Answer No", "message", 0, "messageno", 0 }, { "Cancel", "message", 0, "messagecancel", 0 }, - { "Virtual Reality", 0, 0, 0, 0 }, - { "Reset Tracking", 0, 0, "resetriftpose", 0 } +// { "Virtual Reality", 0, 0, 0, 0 }, +// { "Reset Tracking", 0, 0, "resetriftpose", 0 } }; static void Hu_MenuDrawControlsPage(Page const &page, Vector2i const &offset); @@ -229,6 +229,7 @@ void Hu_MenuInitControlsPage() { Page *page = Hu_MenuAddPage(new Page("ControlOptions", Vector2i(32, 40), 0, Hu_MenuDrawControlsPage)); + page->setLeftColumnWidth(.4f); page->setTitle("Controls"); page->setPredefinedFont(MENU_FONT1, FID(GF_FONTA)); page->setPreviousPage(Hu_MenuPagePtr("Options")); @@ -240,12 +241,12 @@ controlconfig_t *binds = &controlConfig[i]; char const *labelText = binds->text; - if(labelText && (PTR2INT(labelText) > 0 && PTR2INT(labelText) < NUMTEXT)) + if (labelText && (PTR2INT(labelText) > 0 && PTR2INT(labelText) < NUMTEXT)) { labelText = GET_TXT(PTR2INT(labelText)); } - if(!binds->command && !binds->controlName) + if (!binds->command && !binds->controlName) { // Inert. page->addWidget(new LabelWidget(labelText)) @@ -255,10 +256,12 @@ else { page->addWidget(new LabelWidget(labelText)) + .setLeft() .setGroup(group); InputBindingWidget *binding = new InputBindingWidget; binding->binds = binds; + binding->setRight(); binding->setGroup(group); binding->setAction(Widget::Activated, Hu_MenuActivateBindingsGrab); binding->setAction(Widget::FocusGained, Hu_MenuDefaultFocusAction); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/page.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/page.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/page.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/page.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -36,6 +36,8 @@ #include "menu/widgets/labelwidget.h" #include "menu/widgets/mobjpreviewwidget.h" +#include + using namespace de; namespace common { @@ -47,24 +49,27 @@ DENG2_PIMPL(Page) { - String name; ///< Symbolic name/identifier. + String name; ///< Symbolic name/identifier. Children children; - Vector2i origin; - Rectanglei geometry; ///< "Physical" geometry, in fixed 320x200 screen coordinate space. - - String title; ///< Title of this page. - Page *previous = nullptr; ///< Previous page. - int focus = -1; ///< Index of the currently focused widget else @c -1 - Flags flags = DefaultFlags; - int timer = 0; + Vector2i origin; + Rectanglei geometry; ///< "Physical" geometry, in fixed 320x200 screen coordinate space. + Animation scrollOrigin; + Rectanglei viewRegion; + int leftColumnWidth = SCREENWIDTH * 6 / 10; + + String title; ///< Title of this page. + Page * previous = nullptr; ///< Previous page. + int focus = -1; ///< Index of the currently focused widget else @c -1 + Flags flags = DefaultFlags; + int timer = 0; fontid_t fonts[MENU_FONT_COUNT]; ///< Predefined. Used by all widgets. - uint colors[MENU_COLOR_COUNT]; ///< Predefined. Used by all widgets. + uint colors[MENU_COLOR_COUNT]; ///< Predefined. Used by all widgets. - OnActiveCallback onActiveCallback = nullptr; - OnDrawCallback drawer = nullptr; - CommandResponder cmdResponder = nullptr; + OnActiveCallback onActiveCallback; + OnDrawCallback drawer; + CommandResponder cmdResponder; // User data values. QVariant userValue; @@ -103,18 +108,16 @@ */ int lineHeight(int *lineOffset = 0) { - fontid_t oldFont = FR_Font(); - - /// @kludge We cannot yet query line height from the font... + /// @todo Kludge: We cannot yet query line height from the font... + const fontid_t oldFont = FR_Font(); FR_SetFont(self().predefinedFont(MENU_FONT1)); int lh = FR_TextHeight("{case}WyQ"); - if(lineOffset) + if (lineOffset) { *lineOffset = de::max(1.f, .5f + lh * .34f); } // Restore the old font. FR_SetFont(oldFont); - return lh; } @@ -123,101 +126,106 @@ geometry.topLeft = Vector2i(0, 0); geometry.setSize(Vector2ui(0, 0)); - if(flags & FixedLayout) + if (children.empty()) return; + + if (flags & FixedLayout) { - for(Widget *wi : children) + for (Widget *wi : children) { - if(wi->isHidden()) continue; - - wi->geometry().moveTopLeft(wi->fixedOrigin()); - geometry |= wi->geometry(); + if (!wi->isHidden()) + { + wi->geometry().moveTopLeft(wi->fixedOrigin()); + geometry |= wi->geometry(); + } } return; } // This page uses a dynamic layout. - int lineOffset; - int const lh = lineHeight(&lineOffset); - - Vector2i origin; + int lineOffset; + const int lh = lineHeight(&lineOffset); + int prevGroup = children.front()->group(); + Widget * prevWidget = nullptr; + int usedColumns = 0; // column flags for current row + Vector2i origin; + int rowHeight = 0; - for(int i = 0; i < children.count(); ) + for (auto *wi : children) { - Widget *wi = children[i]; - Widget *nextWi = i + 1 < children.count()? children[i + 1] : 0; - - if(wi->isHidden()) + if (wi->isHidden()) { - // Proceed to the next widget. - i += 1; continue; } // If the widget has a fixed position, we will ignore it while doing // dynamic layout. - if(wi->flags() & Widget::PositionFixed) + if (wi->flags() & Widget::PositionFixed) { wi->geometry().moveTopLeft(wi->fixedOrigin()); geometry |= wi->geometry(); - - // Proceed to the next widget. - i += 1; continue; } + // Extra spacing between object groups. + if (wi->group() != prevGroup) + { + origin.y += lh; + prevGroup = wi->group(); + } + // An additional offset requested? - if(wi->flags() & Widget::LayoutOffset) + if (wi->flags() & Widget::LayoutOffset) { origin += wi->fixedOrigin(); } - wi->geometry().moveTopLeft(origin); + int widgetColumns = (wi->flags() & (Widget::LeftColumn | Widget::RightColumn)); + if (widgetColumns == 0) + { + // Use both columns if neither specified. + widgetColumns = Widget::LeftColumn | Widget::RightColumn; + } - // Orient label plus button/inline-list/textual-slider pairs about a - // vertical dividing line, with the label on the left, other widget - // on the right. - // @todo Do not assume pairing, a widget should designate it's label. - if(is(wi) && nextWi) - { - if(!nextWi->isHidden() && - (is(nextWi) || - is(nextWi) || - is(nextWi) || - is(nextWi) || - is(nextWi))) - { - int const margin = lineOffset * 2; + // If this column is already used, move to the next row. + if ((usedColumns & widgetColumns) != 0) + { + origin.y += rowHeight; + usedColumns = 0; + rowHeight = 0; + } + usedColumns |= widgetColumns; - nextWi->geometry().moveTopLeft(Vector2i(margin + wi->geometry().width(), origin.y)); + wi->geometry().moveTopLeft(origin); + rowHeight = MAX_OF(rowHeight, wi->geometry().height() + lineOffset); - Rectanglei const united = wi->geometry() | nextWi->geometry(); - geometry |= united; - origin.y += united.height() + lineOffset; + if (wi->flags() & Widget::RightColumn) + { + // Move widget to the right side. + wi->geometry().move(Vector2i(leftColumnWidth, 0)); - // Extra spacing between object groups. - if(i + 2 < children.count() && nextWi->group() != children[i + 2]->group()) + if (prevWidget && prevWidget->flags() & Widget::LeftColumn) + { + // Align the shorter widget vertically. + if (prevWidget->geometry().height() < wi->geometry().height()) { - origin.y += lh; + prevWidget->geometry().move(Vector2i( + 0, (wi->geometry().height() - prevWidget->geometry().height()) / 2)); + } + else + { + wi->geometry().move(Vector2i( + 0, (prevWidget->geometry().height() - wi->geometry().height()) / 2)); } - - // Proceed to the next object! - i += 2; - continue; } } geometry |= wi->geometry(); - origin.y += wi->geometry().height() + lineOffset; - // Extra spacing between object groups. - if(nextWi && nextWi->group() != wi->group()) - { - origin.y += lh; - } - - // Proceed to the next object! - i += 1; + prevWidget = wi; } + + // Center horizontally. + this->origin.x = SCREENWIDTH / 2 - geometry.width() / 2; } /// @pre @a wi is a child of this page. @@ -331,6 +339,7 @@ } } +#if 0 /** * Determines the size of the menu cursor for a focused widget. If no widget is currently * focused the default cursor size (i.e., the effective line height for @c MENU_FONT1) @@ -340,6 +349,8 @@ */ int cursorSizeFor(Widget *focused, int lineHeight) { + return lineHeight; + /* int focusedHeight = focused? focused->geometry().height() : 0; // Ensure the cursor is at least as tall as the effective line height for @@ -348,11 +359,16 @@ /// @note Handling this correctly would mean separate physical/visual /// geometries for menu widgets. return de::max(focusedHeight, lineHeight); + */ } +#endif }; -Page::Page(String name, Vector2i const &origin, Flags const &flags, - OnDrawCallback drawer, CommandResponder cmdResponder) +Page::Page(String name, + Vector2i const & origin, + Flags const & flags, + const OnDrawCallback & drawer, + const CommandResponder &cmdResponder) : d(new Impl(this)) { d->origin = origin; @@ -386,7 +402,7 @@ return d->children; } -void Page::setOnActiveCallback(Page::OnActiveCallback newCallback) +void Page::setOnActiveCallback(const OnActiveCallback &newCallback) { d->onActiveCallback = newCallback; } @@ -489,31 +505,30 @@ } Vector2i cursorOrigin; - int focusedHeight = 0; - if(focused) + if (focused) { - focusedHeight = d->cursorSizeFor(focused, d->lineHeight()); - // Determine the origin and dimensions of the cursor. /// @todo Each object should define a focus origin... cursorOrigin.x = -1; - cursorOrigin.y = focused->geometry().topLeft.y; + cursorOrigin.y = focused->geometry().middle().y; + /* /// @kludge /// We cannot yet query the subobjects of the list for these values /// so we must calculate them ourselves, here. - if(ListWidget const *list = maybeAs(focused)) + if (ListWidget const *list = maybeAs(focused)) { - if(focused->isActive() && list->selectionIsVisible()) + if (focused->isActive() && list->selectionIsVisible()) { FR_PushAttrib(); FR_SetFont(predefinedFont(mn_page_fontid_t(focused->font()))); - focusedHeight = FR_CharHeight('A') * (1+MNDATA_LIST_LEADING); - cursorOrigin.y += (list->selection() - list->first()) * focusedHeight; + const int rowHeight = FR_CharHeight('A') * (1+MNDATA_LIST_LEADING); + //cursorOrigin.y += (list->selection() - list->first()) * rowHeight + rowHeight/2; FR_PopAttrib(); } } // kludge end + */ } DGL_MatrixMode(DGL_MODELVIEW); @@ -521,42 +536,48 @@ DGL_Translatef(d->origin.x, d->origin.y, 0); // Apply page scroll? - if(!(d->flags & NoScroll) && focused) + if (!(d->flags & NoScroll) && focused) { - Rectanglei viewRegion; - // Determine available screen region for the page. - viewRegion.topLeft = Vector2i(0, d->origin.y); - viewRegion.setSize(Vector2ui(SCREENWIDTH, SCREENHEIGHT - 40/*arbitrary but enough for the help message*/)); + d->viewRegion.topLeft = Vector2i(0, 0); //d->origin.y); + d->viewRegion.setSize(Vector2ui(SCREENWIDTH, SCREENHEIGHT - d->origin.y - 35 /*arbitrary but enough for the help message*/)); // Is scrolling in effect? - if(d->geometry.height() > viewRegion.height()) + if (d->geometry.height() > d->viewRegion.height()) { - int const minY = -viewRegion.topLeft.y / 2 + viewRegion.height() / 2; - if(cursorOrigin.y > minY) - { - int const scrollLimitY = d->geometry.height() - viewRegion.height() / 2; - int const scrollOriginY = de::min(cursorOrigin.y, scrollLimitY) - minY; - DGL_Translatef(0, -scrollOriginY, 0); - } + d->scrollOrigin.setValue( + de::min(de::max(0, int(cursorOrigin.y - d->viewRegion.height() / 2)), + int(d->geometry.height() - d->viewRegion.height())), .35); + + DGL_Translatef(0, -d->scrollOrigin, 0); } } + else + { + d->viewRegion = {{0, 0}, {SCREENWIDTH, SCREENHEIGHT}}; + } // Draw all child widgets that aren't hidden. - for(Widget *wi : d->children) + for (Widget *wi : d->children) { - if(wi->isHidden()) continue; - - FR_PushAttrib(); - wi->draw(); - FR_PopAttrib(); + if (!wi->isHidden()) + { + FR_PushAttrib(); + wi->draw(); + FR_PopAttrib(); + } } // How about a focus cursor? /// @todo cursor should be drawn on top of the page drawer. - if(showFocusCursor && focused) + if (showFocusCursor && focused) { - Hu_MenuDrawFocusCursor(cursorOrigin, focusedHeight, alpha); +#if defined (__JDOOM__) || defined (__JDOOM64__) + const float cursorScale = .75f; +#else + const float cursorScale = 1.f; +#endif + Hu_MenuDrawFocusCursor(cursorOrigin, cursorScale, alpha); } DGL_MatrixMode(DGL_MODELVIEW); @@ -565,7 +586,7 @@ drawTitle(d->title); // The page has its own drawer. - if(d->drawer) + if (d->drawer) { FR_PushAttrib(); d->drawer(*this, d->origin); @@ -573,9 +594,9 @@ } // How about some additional help/information for the focused item? - if(focused && !focused->helpInfo().isEmpty()) + if (focused && !focused->helpInfo().isEmpty()) { - Vector2i helpOrigin(SCREENWIDTH / 2, (SCREENHEIGHT / 2) + ((SCREENHEIGHT / 2 - 5) / cfg.common.menuScale)); + Vector2i helpOrigin(SCREENWIDTH / 2, SCREENHEIGHT - 5 / cfg.common.menuScale); Hu_MenuDrawPageHelp(focused->helpInfo(), helpOrigin); } } @@ -600,6 +621,20 @@ return d->origin; } +Page::Flags Page::flags() const +{ + return d->flags; +} + +Rectanglei Page::viewRegion() const +{ + if (d->flags & NoScroll) + { + return {{0, 0}, {SCREENWIDTH, SCREENHEIGHT}}; + } + return d->viewRegion.moved({0, int(d->scrollOrigin)}); +} + void Page::setX(int x) { d->origin.x = x; @@ -610,6 +645,11 @@ d->origin.y = y; } +void Page::setLeftColumnWidth(float columnWidthPercentage) +{ + d->leftColumnWidth = int(SCREENWIDTH * columnWidthPercentage); +} + void Page::setPreviousPage(Page *newPrevious) { d->previous = newPrevious; @@ -682,26 +722,20 @@ // Reset page timer. d->timer = 0; - if(d->children.isEmpty()) + if (d->children.empty()) + { return; // Presumably the widgets will be added later... + } - // (Re)init widgets. - for(Widget *wi : d->children) + // Notify widgets on the page. + for (Widget *wi : d->children) { - if(CVarToggleWidget *tog = maybeAs(wi)) - { - tog->setFlags(Widget::Active, tog->isDown()? SetFlags : UnsetFlags); - } - if(ListWidget *list = maybeAs(wi)) - { - // Determine number of potentially visible items. - list->updateVisibleSelection(); - } + wi->pageActivated(); } d->refocus(); - if(d->onActiveCallback) + if (d->onActiveCallback) { d->onActiveCallback(*this); } @@ -710,11 +744,10 @@ void Page::tick() { // Call the ticker of each child widget. - for(Widget *wi : d->children) + for (Widget *wi : d->children) { wi->tick(); } - d->timer++; } @@ -770,7 +803,7 @@ case MCMD_NAV_UP: case MCMD_NAV_DOWN: // Page navigation requires a focused widget. - if(Widget *focused = focusWidget()) + if (Widget *focused = focusWidget()) { int i = 0, giveFocus = indexOf(focused); do @@ -782,10 +815,11 @@ giveFocus = 0; } while(++i < d->children.count() && (d->children[giveFocus]->flags() & (Widget::Disabled | Widget::NoFocus | Widget::Hidden))); - if(giveFocus != indexOf(focusWidget())) + if (giveFocus != indexOf(focusWidget())) { S_LocalSound(cmd == MCMD_NAV_UP? SFX_MENU_NAV_UP : SFX_MENU_NAV_DOWN, NULL); setFocus(d->children[giveFocus]); + d->timer = 0; } } return true; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/buttonwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/buttonwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/buttonwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/buttonwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -32,9 +32,10 @@ DENG2_PIMPL_NOREF(ButtonWidget) { - String text; ///< Label text. - patchid_t patch = -1; ///< Used when drawing this instead of text, if set. - bool noAltText = false; + String text; ///< Label text. + patchid_t patch = -1; ///< Used when drawing this instead of text, if set. + bool noAltText = false; + bool silent = false; }; ButtonWidget::ButtonWidget(String const &text, patchid_t patch) @@ -57,18 +58,22 @@ Vector4f const &textColor = mnRendState->textColors[color()]; float t = (isFocused()? 1 : 0); - // Flash if focused. - if(isFocused() && cfg.common.menuTextFlashSpeed > 0) - { - float const speed = cfg.common.menuTextFlashSpeed / 2.f; - t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; - } + const Vector4f color = selectionFlashColor(textColor); + +// // Flash if focused. +// if (isFocused() && cfg.common.menuTextFlashSpeed > 0) +// { +// float const speed = cfg.common.menuTextFlashSpeed / 2.f; +// t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; +// } +// Vector4f const color = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); - Vector4f const color = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); + const float fadeout = scrollingFadeout(); + if (fadeout < .001f) return; FR_SetFont(fontId); - FR_SetColorAndAlpha(color.x, color.y, color.z, color.w); - DGL_Color4f(1, 1, 1, color.w); + FR_SetColorAndAlpha(color.x, color.y, color.z, color.w * fadeout); + DGL_Color4f(1, 1, 1, color.w * fadeout); if(d->patch >= 0) { @@ -79,7 +84,12 @@ } DGL_Enable(DGL_TEXTURE_2D); - WI_DrawPatch(d->patch, replacement, geometry().topLeft, ALIGN_TOPLEFT, 0, Hu_MenuMergeEffectWithDrawTextFlags(0)); + WI_DrawPatch(d->patch, + replacement, + geometry().topLeft, + ALIGN_TOPLEFT, + 0, + Hu_MenuMergeEffectWithDrawTextFlags(0)); DGL_Disable(DGL_TEXTURE_2D); return; @@ -93,25 +103,30 @@ int ButtonWidget::handleCommand(menucommand_e cmd) { - if(cmd == MCMD_SELECT) + if (cmd == MCMD_SELECT) { - if(!isActive()) + if (!isActive()) { setFlags(Active); execAction(Activated); } - - // We are not going to receive an "up event" so action that now. - S_LocalSound(SFX_MENU_ACCEPT, NULL); + // We are not going to receive a separate "up event". + if (!d->silent) + { + S_LocalSound(SFX_MENU_ACCEPT, NULL); + } setFlags(Active, UnsetFlags); execAction(Deactivated); - return true; } - return false; // Not eaten. } +void ButtonWidget::setSilent(bool silent) +{ + d->silent = silent; +} + void ButtonWidget::updateGeometry() { String useText = d->text; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/coloreditwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/coloreditwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/coloreditwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/coloreditwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -159,7 +159,9 @@ x += width; } - DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); + const float fadeout = scrollingFadeout(); + + DGL_Color4f(1, 1, 1, mnRendState->pageAlpha * fadeout); DGL_Enable(DGL_TEXTURE_2D); DGL_SetMaterialUI((world_Material *)P_ToPtr(DMU_MATERIAL, Materials_ResolveUriCString(borderGraphics[0])), DGL_REPEAT, DGL_REPEAT); @@ -224,7 +226,14 @@ DGL_Disable(DGL_TEXTURE_2D); DGL_SetNoMaterial(); - DGL_DrawRectf2Color(x, y, w, h, d->color.x, d->color.y, d->color.z, d->color.w * mnRendState->pageAlpha); + DGL_DrawRectf2Color(x, + y, + w, + h, + d->color.x, + d->color.y, + d->color.z, + d->color.w * mnRendState->pageAlpha * fadeout); } int ColorEditWidget::handleCommand(menucommand_e cmd) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartextualsliderwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -145,7 +145,7 @@ DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(mnRendState->textFonts[font()]); - FR_SetColorAndAlpha(textColor.x, textColor.y, textColor.z, textColor.w); + FR_SetColorAndAlpha(textColor.x, textColor.y, textColor.z, textColor.w * scrollingFadeout()); FR_DrawTextXY3(valueAsText.toUtf8().constData(), 0, 0, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); DGL_Disable(DGL_TEXTURE_2D); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/cvartogglewidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -30,11 +30,13 @@ DENG2_PIMPL_NOREF(CVarToggleWidget) { - State state = Up; - char const *cvarPath = nullptr; - int cvarValueMask = 0; - String downText; - String upText; + State state = Up; + const char *cvarPath = nullptr; + int cvarValueMask = 0; + String downText; + String upText; + + std::function stateChangeCallback; }; CVarToggleWidget::CVarToggleWidget(char const *cvarPath, int cvarValueMask, @@ -126,7 +128,15 @@ void CVarToggleWidget::setState(State newState) { - d->state = newState; + if (newState != d->state) + { + d->state = newState; + + if (d->stateChangeCallback) + { + d->stateChangeCallback(newState); + } + } } CVarToggleWidget::State CVarToggleWidget::state() const @@ -164,5 +174,16 @@ return d->upText; } +void CVarToggleWidget::setStateChangeCallback(const std::function &stateChanged) +{ + d->stateChangeCallback = stateChanged; +} + +void CVarToggleWidget::pageActivated() +{ + ButtonWidget::pageActivated(); + setFlags(Active, isDown()? SetFlags : UnsetFlags); +} + } // namespace menu } // namespace common diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/inlinelistwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/inlinelistwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/inlinelistwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/inlinelistwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -39,12 +39,12 @@ void InlineListWidget::draw() const { - Item const *item = items()[selection()]; - Vector4f const &textColor = mnRendState->textColors[color()]; + const Item * item = items()[selection()]; + const Vector4f color = selectionFlashColor(mnRendState->textColors[this->color()]); DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(mnRendState->textFonts[font()]); - FR_SetColorAndAlpha(textColor.x, textColor.y, textColor.z, textColor.w); + FR_SetColorAndAlpha(color.x, color.y, color.z, color.w * scrollingFadeout()); FR_DrawTextXY3(item->text().toUtf8().constData(), geometry().topLeft.x, geometry().topLeft.y, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/inputbindingwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -26,6 +26,9 @@ #include "m_ctrl.h" // controlconfig_t, etc.. #include "menu/page.h" // mnRendState +#include +#include + using namespace de; namespace common { @@ -43,11 +46,6 @@ MIBT_JOY }; -static void deleteBinding(bindingitertype_t /*type*/, int bid, char const * /*name*/, dd_bool /*isInverse*/, void * /*data*/) -{ - DD_Executef(true, "delbind %i", bid); -} - static char const *findInString(char const *str, char const *token, int n) { int tokenLen = strlen(token); @@ -65,236 +63,306 @@ return 0; } -static void iterateBindings(controlconfig_t const *binds, char const *bindings, int flags, void *data, - void (*callback)(bindingitertype_t type, int bid, char const *ev, dd_bool isInverse, void *data)) +static void drawSmallText(char const *string, int x, int y, float alpha) { - DENG2_ASSERT(binds != 0); + int height = FR_TextHeight(string); + + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PushMatrix(); - char const *ptr = strchr(bindings, ':'); - char const *begin, *end, *end2, *k, *bindingStart, *bindingEnd; - char buf[80], *b; - dd_bool isInverse; - int bid; + DGL_Translatef(x, y + height/2, 0); + DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); + DGL_Translatef(-x, -y - height/2, 0); - std::memset(buf, 0, sizeof(buf)); + FR_SetColorAndAlpha(1, 1, 1, alpha); + FR_DrawTextXY3(string, x, y, ALIGN_TOPLEFT, DTF_NO_EFFECTS); - while(ptr) + DGL_MatrixMode(DGL_MODELVIEW); + DGL_PopMatrix(); +} + +DENG2_PIMPL(InputBindingWidget) +{ + bool needGeometry = true; ///< Recalculate geometry based on bindings. + const int maxWidth = SCREENWIDTH * 55 / 100; + + Impl(Public *i) : Base(i) + {} + + void iterateBindings( + int flags, + const std::function< + void(bindingitertype_t type, int bid, char const *ev, dd_bool isInverse)> + &callback) const { - // Read the binding identifier. - for(k = ptr; k > bindings && *k != '@'; --k); + // Bindings are collected to this map so they're iterated in order. + std::map>> bindings; + + const controlconfig_t *binds = self().binds; + DENG2_ASSERT(binds != nullptr); - if(*k == '@') + char bindingsBuf[1024]; + if (binds->controlName) { - for(begin = k - 1; begin > bindings && isdigit(*(begin - 1)); --begin) {} - bid = strtol(begin, NULL, 10); + B_BindingsForControl( + 0, binds->controlName, BFCI_BOTH, bindingsBuf, sizeof(bindingsBuf)); } else { - // No identifier?? - bid = 0; + B_BindingsForCommand(binds->command, bindingsBuf, sizeof(bindingsBuf)); } - // Find the end of the entire binding. - bindingStart = k + 1; - bindingEnd = strchr(bindingStart, '@'); - if(!bindingEnd) - { - // Then point to the end of the string. - bindingEnd = strchr(k + 1, 0); - } + const char *ptr = strchr(bindingsBuf, ':'); + const char *begin, *end, *end2, *k, *bindingStart, *bindingEnd; + char buf[80], *b; + dd_bool isInverse; + int bid; - ptr++; - end = strchr(ptr, '-'); - if(!end) - return; + std::memset(buf, 0, sizeof(buf)); - end++; - b = buf; - while(*end && *end != ' ' && *end != '-' && *end != '+') + while (ptr) { - *b++ = *end++; - } - *b = 0; + // Read the binding identifier. + for (k = ptr; k > bindingsBuf && *k != '@'; --k) {;} - end2 = strchr(end, ' '); - if(!end2) - end = end + strlen(end); // Then point to the end. - else - end = end2; + if (*k == '@') + { + for (begin = k - 1; begin > bindingsBuf && isdigit(*(begin - 1)); --begin) {;} + bid = strtol(begin, NULL, 10); + } + else + { + // No identifier?? + bid = 0; + } - if(!findInString(bindingStart, "modifier-1-down", bindingEnd - bindingStart) && - (!(flags & MIBF_IGNORE_REPEATS) || !findInString(ptr, "-repeat", end - ptr))) - { - isInverse = (findInString(ptr, "-inverse", end - ptr) != NULL); + // Find the end of the entire binding. + bindingStart = k + 1; + bindingEnd = strchr(bindingStart, '@'); + if (!bindingEnd) + { + // Then point to the end of the string. + bindingEnd = strchr(k + 1, 0); + } - if(!strncmp(ptr, "key", 3) || - !strncmp(ptr, "joy-button", 10) || - !strncmp(ptr, "mouse-left", 10) || - !strncmp(ptr, "mouse-middle", 12) || - !strncmp(ptr, "mouse-right", 11)) + ptr++; + end = strchr(ptr, '-'); + if (!end) return; + + end++; + b = buf; + while (*end && *end != ' ' && *end != '-' && *end != '+') { - if(((binds->flags & CCF_INVERSE) && isInverse) || - ((binds->flags & CCF_NON_INVERSE) && !isInverse) || - !(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE))) - { - callback(!strncmp(ptr, "key", 3)? MIBT_KEY : - !strncmp(ptr, "mouse", 5)? MIBT_MOUSE : MIBT_JOY, bid, buf, - isInverse, data); - } + *b++ = *end++; + } + *b = 0; + + end2 = strchr(end, ' '); + if (!end2) + { + end = end + strlen(end); // Then point to the end. } else { - if(!(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE)) || (binds->flags & CCF_INVERSE)) - { - isInverse = !isInverse; - } - if(!strncmp(ptr, "joy", 3)) + end = end2; + } + + if (!findInString(bindingStart, "modifier-1-down", bindingEnd - bindingStart) && + (!(flags & MIBF_IGNORE_REPEATS) || !findInString(ptr, "-repeat", end - ptr))) + { + isInverse = (findInString(ptr, "-inverse", end - ptr) != NULL); + + if (!strncmp(ptr, "key", 3) || !strncmp(ptr, "joy-button", 10) || + !strncmp(ptr, "mouse-left", 10) || !strncmp(ptr, "mouse-middle", 12) || + !strncmp(ptr, "mouse-right", 11)) { - callback(MIBT_JOY, bid, buf, isInverse, data); + if (((binds->flags & CCF_INVERSE) && isInverse) || + ((binds->flags & CCF_NON_INVERSE) && !isInverse) || + !(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE))) + { + bindings[!strncmp(ptr, "key", 3) + ? MIBT_KEY + : !strncmp(ptr, "mouse", 5) ? MIBT_MOUSE : MIBT_JOY] + .emplace_back(bid, buf, isInverse); + } } - else if(!strncmp(ptr, "mouse", 5)) + else { - callback(MIBT_MOUSE, bid, buf, isInverse, data); + if (!(binds->flags & (CCF_INVERSE | CCF_NON_INVERSE)) || + (binds->flags & CCF_INVERSE)) + { + isInverse = !isInverse; + } + if (!strncmp(ptr, "joy", 3)) + { + bindings[MIBT_JOY].emplace_back(bid, buf, isInverse); + } + else if (!strncmp(ptr, "mouse", 5)) + { + bindings[MIBT_MOUSE].emplace_back(bid, buf, isInverse); + } } } - } - ptr = end; - while(*ptr == ' ') { ptr++; } + ptr = end; + while (*ptr == ' ') + { + ptr++; + } + ptr = strchr(ptr, ':'); + } - ptr = strchr(ptr, ':'); + for (auto iterType = bindings.begin(); iterType != bindings.end(); ++iterType) + { + for (const auto &bind : iterType->second) + { + callback(iterType->first, + std::get<0>(bind), + std::get<1>(bind).c_str(), + std::get<2>(bind)); + } + } } -} - -InputBindingWidget::InputBindingWidget() - : Widget() - , binds(0) -{ - setFont(MENU_FONT1); - setColor(MENU_COLOR1); -} - -InputBindingWidget::~InputBindingWidget() -{} - -static void drawSmallText(char const *string, int x, int y, float alpha) -{ - int height = FR_TextHeight(string); - - DGL_MatrixMode(DGL_MODELVIEW); - DGL_PushMatrix(); - - DGL_Translatef(x, y + height/2, 0); - DGL_Scalef(SMALL_SCALE, SMALL_SCALE, 1); - DGL_Translatef(-x, -y - height/2, 0); - - FR_SetColorAndAlpha(1, 1, 1, alpha); - FR_DrawTextXY3(string, x, y, ALIGN_TOPLEFT, DTF_NO_EFFECTS); - DGL_MatrixMode(DGL_MODELVIEW); - DGL_PopMatrix(); -} - -struct bindingdrawerdata_t -{ - Point2Raw origin; - float alpha; -}; - -static void drawBinding(bindingitertype_t type, int /*bid*/, const char *name, - dd_bool isInverse, void *context) -{ -#define BIND_GAP (2) + Vector2ui measureAndDraw(bool drawing = true) const + { + const auto widgetTopLeft = self().geometry().topLeft; + struct { + bool drawing; + float alpha; + Vector2i widgetTopLeft; + Vector2i origin; + Vector2i size; + } ctx = {drawing, + mnRendState->pageAlpha * self().scrollingFadeout(), + widgetTopLeft, + {0, 0}, + {0, 0}}; + + if (drawing) + { + if (ctx.alpha < .001f) return {}; + } + + iterateBindings( + MIBF_IGNORE_REPEATS, + [this, &ctx](bindingitertype_t type, int /*bid*/, const char *name, dd_bool isInverse) { + static const int BIND_GAP = 2; #if __JHERETIC__ - static float const bgRGB[] = { 0, .5f, 0 }; + static float const bgRGB[] = {0, .5f, 0}; #elif __JHEXEN__ - static float const bgRGB[] = { .5f, 0, 0 }; + static float const bgRGB[] = {.5f, 0, 0}; #else - static float const bgRGB[] = { 0, 0, 0 }; + static float const bgRGB[] = {0, 0, 0}; #endif + FR_SetFont(FID(GF_FONTA)); + const int lineHeight = FR_TextHeight("W"); - bindingdrawerdata_t *d = (bindingdrawerdata_t *)context; - - FR_SetFont(FID(GF_FONTA)); - - if(type == MIBT_KEY) - { - int const width = FR_TextWidth(name); - int const height = FR_TextHeight(name); - - DGL_SetNoMaterial(); - DGL_DrawRectf2Color(d->origin.x, d->origin.y, width * SMALL_SCALE + 2, height, bgRGB[0], bgRGB[1], bgRGB[2], d->alpha * .6f); + if (type == MIBT_KEY) + { + const int width = FR_TextWidth(name) * SMALL_SCALE; - DGL_Enable(DGL_TEXTURE_2D); - drawSmallText(name, d->origin.x + 1, d->origin.y, d->alpha); - DGL_Disable(DGL_TEXTURE_2D); + if (ctx.origin.x + width > maxWidth) + { + ctx.origin.x = 0; + ctx.origin.y += lineHeight + 1; + } + + if (ctx.drawing) + { + DGL_SetNoMaterial(); + DGL_DrawRectf2Color(ctx.widgetTopLeft.x + ctx.origin.x, + ctx.widgetTopLeft.y + ctx.origin.y, + width + 2, + lineHeight, + bgRGB[0], + bgRGB[1], + bgRGB[2], + ctx.alpha * .6f); + + DGL_Enable(DGL_TEXTURE_2D); + drawSmallText(name, + ctx.widgetTopLeft.x + ctx.origin.x + 1, + ctx.widgetTopLeft.y + ctx.origin.y, + ctx.alpha); + DGL_Disable(DGL_TEXTURE_2D); + } - d->origin.x += width * SMALL_SCALE + 2 + BIND_GAP; - } - else - { - char buf[256]; - sprintf(buf, "%s%c%s", type == MIBT_MOUSE? "mouse" : "joy", isInverse? '-' : '+', name); + ctx.origin.x += width + 2 + BIND_GAP; + } + else + { + char buf[256]; + sprintf(buf, + "%s%c%s", + type == MIBT_MOUSE ? "mouse" : "joy", + isInverse ? '-' : '+', + name); + + int const width = FR_TextWidth(buf) * SMALL_SCALE; + + if (ctx.origin.x + width > maxWidth) + { + ctx.origin.x = 0; + ctx.origin.y += lineHeight + 1; + } + + if (ctx.drawing) + { + DGL_Enable(DGL_TEXTURE_2D); + drawSmallText(buf, + ctx.widgetTopLeft.x + ctx.origin.x, + ctx.widgetTopLeft.y + ctx.origin.y, + ctx.alpha); + DGL_Disable(DGL_TEXTURE_2D); + } - int const width = FR_TextWidth(buf); - ///int const height = FR_TextHeight(temp); + ctx.origin.x += width + BIND_GAP; + } - DGL_Enable(DGL_TEXTURE_2D); - drawSmallText(buf, d->origin.x, d->origin.y, d->alpha); - DGL_Disable(DGL_TEXTURE_2D); + // Update dimensions as we go. + ctx.size = ctx.size.max({ctx.origin.x, ctx.origin.y + lineHeight}); + }); - d->origin.x += width * SMALL_SCALE + BIND_GAP; + return (ctx.size).toVector2ui(); } +}; -#undef BIND_GAP +InputBindingWidget::InputBindingWidget() + : Widget() + , binds(nullptr) + , d(new Impl(this)) +{ + setFont(MENU_FONT1); + setColor(MENU_COLOR1); } +InputBindingWidget::~InputBindingWidget() +{} + void InputBindingWidget::draw() const { - char buf[1024]; - if(binds->controlName) - { - B_BindingsForControl(0, binds->controlName, BFCI_BOTH, buf, sizeof(buf)); - } - else - { - B_BindingsForCommand(binds->command, buf, sizeof(buf)); - } - - bindingdrawerdata_t draw; - draw.origin.x = geometry().topLeft.x; - draw.origin.y = geometry().topLeft.y; - draw.alpha = mnRendState->pageAlpha; - iterateBindings(binds, buf, MIBF_IGNORE_REPEATS, &draw, drawBinding); + d->measureAndDraw(true); } int InputBindingWidget::handleCommand(menucommand_e cmd) { switch(cmd) { - case MCMD_DELETE: { - char buf[1024]; - + case MCMD_DELETE: S_LocalSound(SFX_MENU_CANCEL, NULL); - if(binds->controlName) - { - B_BindingsForControl(0, binds->controlName, BFCI_BOTH, buf, sizeof(buf)); - } - else - { - B_BindingsForCommand(binds->command, buf, sizeof(buf)); - } - - iterateBindings(binds, buf, 0, NULL, deleteBinding); - + d->iterateBindings(0, [](bindingitertype_t, int bid, const char *, dd_bool) { + DD_Executef(true, "delbind %i", bid); + }); + d->needGeometry = true; // If deleting the menuselect binding, automatically rebind it Return; // otherwise the user would be stuck without a way to make further bindings. - if(binds->command && !strcmp(binds->command, "menuselect")) + if (binds->command && !strcmp(binds->command, "menuselect")) { DD_Execute(true, "bindevent menu:key-return menuselect"); } - return true; } + return true; case MCMD_SELECT: S_LocalSound(SFX_MENU_CYCLE, NULL); @@ -314,8 +382,12 @@ void InputBindingWidget::updateGeometry() { - // @todo calculate visible dimensions properly! - geometry().setSize(Vector2ui(60, 10 * SMALL_SCALE)); + if (d->needGeometry) + { + d->needGeometry = false; + geometry().setSize(d->measureAndDraw(false /* just measure */)); + geometry().setWidth(d->maxWidth); + } } /** @@ -343,11 +415,11 @@ LOG_AS("InputBindingWidget"); // Only handle events when active. - if(!isActive()) return false; + if (!isActive()) return false; // We're only interested in events with an echoed, symbolic descriptor. String symbol = symbolicDescriptor(event); - if(symbol.isEmpty()) return false; + if (symbol.isEmpty()) return false; // We're only interested in button down events. if((symbol.beginsWith("key-") || @@ -369,7 +441,7 @@ } String cmd; - if(binds->command) + if (binds->command) { cmd = String("bindevent {%1:%2%3} {%4}") .arg(context) @@ -378,7 +450,7 @@ .arg(binds->command); // Check for repeats. - if((binds->flags & CCF_REPEAT) && symbol.endsWith("-down")) + if ((binds->flags & CCF_REPEAT) && symbol.endsWith("-down")) { cmd += String("; bindevent {%1:%2-repeat} {%3}") .arg(context) @@ -386,27 +458,25 @@ .arg(binds->command); } } - else if(binds->controlName) + else if (binds->controlName) { String stateFlags; // Extract the symbolic key/button name (exclude the state part). int const endOfName = symbol.indexOf('-', symbol.indexOf('-') + 1); - if(endOfName < 0) + if (endOfName < 0) { throw Error("InputBindingWidget::handleEvent_Privileged", "Invalid symbol:" + symbol); } String const name = symbol.left(endOfName); // Staged? - if(binds->flags & CCF_STAGED) + if (binds->flags & CCF_STAGED) { // Staging is buttons. - if(name.beginsWith("key-") || - name.beginsWith("joy-button") || - name.beginsWith("mouse-left") || - name.beginsWith("mouse-middle") || - name.beginsWith("mouse-right")) + if (name.beginsWith("key-") || name.beginsWith("joy-button") || + name.beginsWith("mouse-left") || name.beginsWith("mouse-middle") || + name.beginsWith("mouse-right")) { stateFlags += "-staged"; } @@ -414,11 +484,11 @@ // Inverted? bool inv = (binds->flags & CCF_INVERSE) != 0; - if(symbol.substr(endOfName).beginsWith("-neg")) + if (symbol.substr(endOfName).beginsWith("-neg")) { inv = !inv; } - if(inv) + if (inv) { stateFlags += "-inverse"; } @@ -444,6 +514,7 @@ setFlags(Active, UnsetFlags); DD_SetInteger(DD_SYMBOLIC_ECHO, false); S_LocalSound(SFX_MENU_ACCEPT, nullptr); + d->needGeometry = true; return true; } @@ -451,7 +522,7 @@ { DENG2_ASSERT(binds); // Map to a text definition? - if(PTR2INT(binds->text) > 0 && PTR2INT(binds->text) < NUMTEXT) + if (PTR2INT(binds->text) > 0 && PTR2INT(binds->text) < NUMTEXT) { return GET_TXT(PTR2INT(binds->text)); } @@ -461,7 +532,12 @@ String InputBindingWidget::bindContext() const { DENG2_ASSERT(binds); - return (binds->bindContext? binds->bindContext : "game"); + return (binds->bindContext ? binds->bindContext : "game"); +} + +void InputBindingWidget::pageActivated() +{ + d->needGeometry = true; } } // namespace menu diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/labelwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/labelwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/labelwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/labelwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -55,22 +55,27 @@ { fontid_t fontId = mnRendState->textFonts[font()]; Vector4f const &textColor = mnRendState->textColors[color()]; - float t = (isFocused()? 1 : 0); +// float t = (isFocused()? 1 : 0); - // Flash if focused. - if(isFocused() && cfg.common.menuTextFlashSpeed > 0) - { - float const speed = cfg.common.menuTextFlashSpeed / 2.f; - t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; - } +// // Flash if focused. +// if(isFocused() && cfg.common.menuTextFlashSpeed > 0) +// { +// float const speed = cfg.common.menuTextFlashSpeed / 2.f; +// t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; +// } + +// Vector4f const color = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); + + const Vector4f color = selectionFlashColor(textColor); - Vector4f const color = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); + const float fadeout = scrollingFadeout(); + if (fadeout < .001f) return; - DGL_Color4f(1, 1, 1, color.w); + DGL_Color4f(1, 1, 1, color.w * fadeout); FR_SetFont(fontId); - FR_SetColorAndAlpha(color.x, color.y, color.z, color.w); + FR_SetColorAndAlpha(color.x, color.y, color.z, color.w * fadeout); - if(d->patch) + if (d->patch) { String replacement; if(!(d->flags & MNTEXT_NO_ALTTEXT)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/lineeditwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/lineeditwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/lineeditwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/lineeditwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -131,28 +131,34 @@ DGL_Enable(DGL_TEXTURE_2D); FR_SetFont(fontId); + const float fadeout = scrollingFadeout(); + //int const numVisCharacters = de::clamp(0, useText.isNull()? 0 : useText.length(), d->maxVisibleChars); drawEditBackground(origin + Vector2i(MNDATA_EDIT_BACKGROUND_OFFSET_X, MNDATA_EDIT_BACKGROUND_OFFSET_Y), - geometry().width(), mnRendState->pageAlpha); + geometry().width(), mnRendState->pageAlpha * fadeout); //if(string) { - float t = 0; +// float t = 0; + Vector4f color = Vector4f(Vector3f(cfg.common.menuTextColors[MNDATA_EDIT_TEXT_COLORIDX]), 1.f); // Flash if focused? - if(!isActive() && isFocused() && cfg.common.menuTextFlashSpeed > 0) + if (!isActive()) /* && isFocused() && cfg.common.menuTextFlashSpeed > 0) { float const speed = cfg.common.menuTextFlashSpeed / 2.f; t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; + }*/ + { + color = selectionFlashColor(color); } - Vector4f color = de::lerp(Vector3f(cfg.common.menuTextColors[MNDATA_EDIT_TEXT_COLORIDX]), Vector3f(cfg.common.menuTextFlashColor), t); +// Vector4f color = de::lerp(Vector3f(cfg.common.menuTextColors[MNDATA_EDIT_TEXT_COLORIDX]), Vector3f(cfg.common.menuTextFlashColor), t); color *= light; color.w = textOpacity; // Draw the text: - FR_SetColorAndAlpha(color.x, color.y, color.z, color.w); + FR_SetColorAndAlpha(color.x, color.y, color.z, color.w * fadeout); FR_DrawTextXY3(useText.toUtf8().constData(), origin.x, origin.y, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); // Are we drawing a cursor? diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/listwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -59,9 +59,10 @@ DENG2_PIMPL_NOREF(ListWidget) { Items items; - int selection = 0; ///< Selected item (-1 if none). - int first = 0; ///< First visible item. - int numvis = 0; + int selection = 0; ///< Selected item (-1 if none). + int first = 0; ///< First visible item. + int numvis = 0; + bool reorderEnabled = false; ~Impl() { qDeleteAll(items); } }; @@ -100,7 +101,7 @@ FR_PushAttrib(); FR_SetFont(page().predefinedFont(mn_page_fontid_t(font()))); - RectRaw itemGeometry; + RectRaw itemGeometry{}; for(int i = 0; i < itemCount(); ++i) { Item *item = d->items[i]; @@ -124,13 +125,19 @@ Vector4f const &textColor = mnRendState->textColors[color()]; float t = flashSelection? 1 : 0; - if(flashSelection && cfg.common.menuTextFlashSpeed > 0) + Vector4f flashColor = textColor; + + if (flashSelection) /* && cfg.common.menuTextFlashSpeed > 0) { float const speed = cfg.common.menuTextFlashSpeed / 2.f; t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; + }*/ + { + flashColor = selectionFlashColor(flashColor); } - Vector4f const flashColor = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); + +// Vector4f const flashColor = de::lerp(textColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), textColor.w), t); Vector4f const dimColor = Vector4f(Vector3f(textColor) * MNDATA_LIST_NONSELECTION_LIGHT, textColor.w); if(d->first < d->items.count() && d->numvis > 0) @@ -142,13 +149,21 @@ int itemIdx = d->first; do { - Item const *item = d->items[itemIdx]; - Vector4f const &color = d->selection == itemIdx? (flashSelection? flashColor : textColor) : dimColor; + const Item *item = d->items[itemIdx]; + + const Vector4f &color = + d->selection == itemIdx ? (flashSelection ? flashColor : textColor) : dimColor; + + const int itemHeight = + FR_TextHeight(item->text().toUtf8().constData()) * (1 + MNDATA_LIST_LEADING); - FR_SetColorAndAlpha(color.x, color.y, color.z, color.w); + FR_SetColorAndAlpha(color.x, + color.y, + color.z, + color.w * scrollingFadeout(origin.y, origin.y + itemHeight)); FR_DrawTextXY3(item->text().toUtf8().constData(), origin.x, origin.y, ALIGN_TOPLEFT, Hu_MenuMergeEffectWithDrawTextFlags(0)); - origin.y += FR_TextHeight(item->text().toUtf8().constData()) * (1 + MNDATA_LIST_LEADING); - } while(++itemIdx < d->items.count() && itemIdx < d->first + d->numvis); + origin.y += itemHeight; + } while (++itemIdx < d->items.count() && itemIdx < d->first + d->numvis); DGL_Disable(DGL_TEXTURE_2D); } @@ -156,11 +171,11 @@ int ListWidget::handleCommand(menucommand_e cmd) { - switch(cmd) + switch (cmd) { case MCMD_NAV_DOWN: case MCMD_NAV_UP: - if(isActive()) + if (isActive()) { int oldSelection = d->selection; if(MCMD_NAV_DOWN == cmd) @@ -184,7 +199,7 @@ return false; // Not eaten. case MCMD_NAV_OUT: - if(isActive()) + if (isActive()) { S_LocalSound(SFX_MENU_CANCEL, NULL); setFlags(Active, UnsetFlags); @@ -194,7 +209,7 @@ return false; // Not eaten. case MCMD_SELECT: - if(!isActive()) + if (!isActive()) { S_LocalSound(SFX_MENU_ACCEPT, NULL); setFlags(Active); @@ -208,6 +223,18 @@ } return true; + case MCMD_NAV_LEFT: + case MCMD_NAV_RIGHT: + if (d->reorderEnabled && isActive()) + { + if (reorder(selection(), cmd == MCMD_NAV_LEFT ? -1 : +1)) + { + S_LocalSound(SFX_MENU_SLIDER_MOVE, NULL); + execAction(Modified); + } + } + return true; + default: return false; // Not eaten. } } @@ -239,9 +266,17 @@ } } +void ListWidget::pageActivated() +{ + Widget::pageActivated(); + + // Determine number of potentially visible items. + updateVisibleSelection(); +} + int ListWidget::itemData(int index) const { - if(index >= 0 && index < itemCount()) + if (index >= 0 && index < itemCount()) { return d->items[index]->userValue(); } @@ -283,5 +318,38 @@ return selectItem(findItem(userValue), flags); } +bool ListWidget::reorder(int itemIndex, int indexOffset) +{ + if (itemIndex + indexOffset < 0 || itemIndex + indexOffset >= d->items.size()) + { + return false; // Would go out of bounds. + } + + if (d->selection == itemIndex) + { + d->selection += indexOffset; + } + + while (indexOffset < 0) + { + std::swap(d->items[itemIndex - 1], d->items[itemIndex]); + --itemIndex; + ++indexOffset; + } + while (indexOffset > 0) + { + std::swap(d->items[itemIndex + 1], d->items[itemIndex]); + ++itemIndex; + --indexOffset; + } + return true; +} + +ListWidget &ListWidget::setReorderingEnabled(bool reorderEnabled) +{ + d->reorderEnabled = reorderEnabled; + return *this; +} + } // namespace menu } // namespace common diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/mobjpreviewwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/mobjpreviewwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/mobjpreviewwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/mobjpreviewwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -91,8 +91,8 @@ spriteinfo_t info; if(!R_GetSpriteInfo(sprite, spriteFrame, &info)) return; - Point2Raw origin(info.geometry.origin.x, info.geometry.origin.y); - Size2Raw size(info.geometry.size.width, info.geometry.size.height); + Point2Raw origin = {{{info.geometry.origin.x, info.geometry.origin.y}}}; + Size2Raw size = {{{info.geometry.size.width, info.geometry.size.height}}}; float scale = (size.height > size.width? (float)MNDATA_MOBJPREVIEW_HEIGHT / size.height : (float)MNDATA_MOBJPREVIEW_WIDTH / size.width); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/sliderwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/sliderwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/sliderwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/sliderwidget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -147,6 +147,9 @@ if(!R_GetPatchInfo(pSliderLeft, &leftInfo)) return; if(WIDTH <= 0 || HEIGHT <= 0) return; + const float fadeout = scrollingFadeout(); + if (fadeout < .001f) return; + Vector2f origin = geometry().topLeft; origin += Vector2f(MNDATA_SLIDER_OFFSET_X + leftInfo.geometry.size.width, MNDATA_SLIDER_OFFSET_Y) * MNDATA_SLIDER_SCALE; @@ -164,7 +167,7 @@ M_DrawGlowBar(from, to, HEIGHT * 1.1f, true, true, true, 0, 0, 0, mnRendState->pageAlpha * mnRendState->textShadow); } - DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); + DGL_Color4f(1, 1, 1, mnRendState->pageAlpha * fadeout); GL_DrawPatch(pSliderLeft, Vector2i(0, 0), ALIGN_TOPRIGHT, DPF_NO_OFFSETX); GL_DrawPatch(pSliderRight, Vector2i(MNDATA_SLIDER_SLOTS * WIDTH, 0)); @@ -172,7 +175,7 @@ DGL_SetPatch(pSliderMiddle, DGL_REPEAT, DGL_REPEAT); DGL_DrawRectf2Tiled(0, middleInfo.geometry.origin.y, MNDATA_SLIDER_SLOTS * WIDTH, HEIGHT, middleInfo.geometry.size.width, middleInfo.geometry.size.height); - DGL_Color4f(1, 1, 1, mnRendState->pageAlpha); + DGL_Color4f(1, 1, 1, mnRendState->pageAlpha * fadeout); GL_DrawPatch(pSliderHandle, Vector2i(d->thumbPos(), 1), ALIGN_TOP, DPF_NO_OFFSET); DGL_Disable(DGL_TEXTURE_2D); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/menu/widgets/widget.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -21,6 +21,7 @@ #include #include "common.h" #include "menu/widgets/widget.h" +#include "menu/page.h" #include "hu_menu.h" // menu sounds @@ -255,13 +256,11 @@ bool Widget::hasAction(Action id) const { - DENG2_ASSERT(id >= Modified && id <= FocusGained); return d->actions.contains(id); } Widget &Widget::setAction(Action id, ActionCallback callback) { - DENG2_ASSERT(id >= Modified && id <= FocusGained); if(callback) { d->actions.insert(id, callback); @@ -303,5 +302,46 @@ return d->userValue2; } +float Widget::scrollingFadeout() const +{ + const auto geom = geometry(); + return scrollingFadeout(geom.topLeft.y, geom.bottomRight.y); +} + +float Widget::scrollingFadeout(int yTop, int yBottom) const +{ + if (page().flags() & Page::NoScroll) + { + return 1.f; + } + + const float FADEOUT_LEN = 20; + const auto viewRegion = page().viewRegion(); + + if (yBottom < viewRegion.topLeft.y) + { + return de::max(0.f, 1.f - (viewRegion.topLeft.y - yBottom) / FADEOUT_LEN); + } + if (yTop > viewRegion.bottomRight.y) + { + return de::max(0.f, 1.f - (yTop - viewRegion.bottomRight.y) / FADEOUT_LEN); + } + return 1.f; +} + +Vector4f Widget::selectionFlashColor(const Vector4f &noFlashColor) const +{ + if (isFocused() && cfg.common.menuTextFlashSpeed > 0) + { + const float speed = cfg.common.menuTextFlashSpeed / 2.f; + const float t = (1 + sin(page().timer() / (float)TICSPERSEC * speed * DD_PI)) / 2; + return lerp(noFlashColor, Vector4f(Vector3f(cfg.common.menuTextFlashColor), 1.f), t); + } + return noFlashColor; +} + +void Widget::pageActivated() +{} + } // namespace menu } // namespace common diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_netcl.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_netcl.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_netcl.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_netcl.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -65,20 +65,21 @@ byte configFlags = Reader_ReadByte(msg); - GameRuleset gsRules(COMMON_GAMESESSION->rules()); // Initialize with a copy of the current rules. - gsRules.deathmatch = configFlags & 0x3; - gsRules.noMonsters = !(configFlags & 0x4? true : false); + GameRules gsRules(gfw_Session()->rules()); // Initialize with a copy of the current rules. + GameRules_Set(gsRules, deathmatch, configFlags & 0x3); + GameRules_Set(gsRules, noMonsters, !(configFlags & 0x4? true : false)); #if !__JHEXEN__ - gsRules.respawnMonsters = (configFlags & 0x8? true : false); + GameRules_Set(gsRules, respawnMonsters, (configFlags & 0x8? true : false)); #endif /// @todo Not applied?? //byte gsJumping = (configFlags & 0x10? true : false); - gsRules.skill = skillmode_t(Reader_ReadByte(msg)); + GameRules_Set(gsRules, skill, skillmode_t(Reader_ReadByte(msg))); + // Interpret skill modes outside the normal range as "spawn no things". - if(gsRules.skill < SM_BABY || gsRules.skill >= NUM_SKILL_MODES) + if(gsRules.values.skill < SM_BABY || gsRules.values.skill >= NUM_SKILL_MODES) { - gsRules.skill = SM_NOTHINGS; + GameRules_Set(gsRules, skill, SM_NOTHINGS); } coord_t gsGravity = Reader_ReadFloat(msg); @@ -96,10 +97,10 @@ /// @todo Automatically load the server's game if it is available. /// However, note that this can only occur if the server changes its game /// while a netgame is running (which currently will end the netgame). - if(COMMON_GAMESESSION->gameId().compare(Str_Text(gsGameId))) + if (gfw_GameId().compare(Str_Text(gsGameId))) { LOG_NET_ERROR("Game mismatch: server's identity key (%s) is different to yours (%s)") - << gsGameId << COMMON_GAMESESSION->gameId(); + << gsGameId << gfw_GameId(); DD_Execute(false, "net disconnect"); Uri_Delete(gsMapUri); return; @@ -114,24 +115,24 @@ // Do we need to change the map? if(gsFlags & GSF_CHANGE_MAP) { - COMMON_GAMESESSION->end(); - COMMON_GAMESESSION->begin(gsRules, Str_Text(gsEpisodeId), + gfw_Session()->end(); + gfw_Session()->begin(gsRules, Str_Text(gsEpisodeId), *reinterpret_cast(gsMapUri), - COMMON_GAMESESSION->mapEntryPoint() /*gsMapEntrance*/); + gfw_Session()->mapEntryPoint() /*gsMapEntrance*/); } else { /// @todo Breaks session management logic; rules cannot change once the session has /// begun and setting the current map and/or entrance is illogical at this point. - DENG2_ASSERT(!Str_Compare(gsEpisodeId, COMMON_GAMESESSION->episodeId().toLatin1().constData())); - DENG2_ASSERT(*reinterpret_cast(gsMapUri) == COMMON_GAMESESSION->mapUri()); + DENG2_ASSERT(!Str_Compare(gsEpisodeId, gfw_Session()->episodeId().toLatin1().constData())); + DENG2_ASSERT(*reinterpret_cast(gsMapUri) == gfw_Session()->mapUri()); - COMMON_GAMESESSION->applyNewRules(gsRules); + gfw_Session()->applyNewRules(gsRules); } // Set gravity. /// @todo This is a map-property, not a global property. - DD_SetVariable(DD_GRAVITY, &gsGravity); + DD_SetVariable(DD_MAP_GRAVITY, &gsGravity); // Camera init included? if(gsFlags & GSF_CAMERA_INIT) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_net.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_net.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_net.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_net.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -71,7 +71,7 @@ de::Uri map("Maps:", RC_NULL); if(!episodeId.isEmpty()) { - map = de::Uri(Defs().episodes.find("id", episodeId).gets("startMap"), RC_NULL); + map = de::makeUri(Defs().episodes.find("id", episodeId).gets("startMap")); DENG2_ASSERT(!map.isEmpty()); } return map; @@ -215,15 +215,15 @@ de::Uri mapUri = *reinterpret_cast(Con_GetUri("server-game-map")); if(mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); - GameRuleset rules(COMMON_GAMESESSION->rules()); // Make a copy of the current rules. - rules.skill = skillmode_t(cfg.common.netSkill); + GameRules rules(gfw_Session()->rules()); // Make a copy of the current rules. + GameRules_Set(rules, skill, skillmode_t(cfg.common.netSkill)); - COMMON_GAMESESSION->end(); + gfw_Session()->end(); try { // First try the configured map. - COMMON_GAMESESSION->begin(rules, episodeId, mapUri); + gfw_Session()->begin(rules, episodeId, mapUri); } catch(Error const &er) { @@ -233,7 +233,7 @@ LOG_INFO("Using the default map (%s) to start the server due to failure to load the configured map") << mapUri; - COMMON_GAMESESSION->begin(rules, episodeId, mapUri); + gfw_Session()->begin(rules, episodeId, mapUri); } G_SetGameAction(GA_NONE); /// @todo Necessary? @@ -243,7 +243,7 @@ int D_NetServerClose(int before) { - if(!before) + if (!before) { P_ResetPlayerRespawnClasses(); @@ -251,16 +251,15 @@ /// @todo fixme: "normal" is defined by the game rules config which may /// be changed from the command line (e.g., -fast, -nomonsters). /// In order to "restore normal" this logic is insufficient. - GameRuleset newRules(COMMON_GAMESESSION->rules()); - newRules.deathmatch = false; - newRules.noMonsters = false; + GameRules newRules(gfw_Session()->rules()); + GameRules_Set(newRules, deathmatch, 0); + GameRules_Set(newRules, noMonsters, false); #if __JHEXEN__ - newRules.randomClasses = false; + GameRules_Set(newRules, randomClasses, false); #endif - COMMON_GAMESESSION->applyNewRules(newRules); + gfw_Session()->applyNewRules(newRules); D_NetMessage(CONSOLEPLAYER, "NETGAME ENDS"); - D_NetClearBuffer(); } return true; @@ -295,15 +294,15 @@ D_NetClearBuffer(); // Start demo. - COMMON_GAMESESSION->endAndBeginTitle(); + gfw_Session()->endAndBeginTitle(); - /*GameRuleset newRules(COMMON_GAMESESSION->rules()); + /*GameRules newRules(gfw_Session()->rules()); newRules.deathmatch = false; newRules.noMonsters = false; #if __JHEXEN__ newRules.randomClasses = false; #endif - COMMON_GAMESESSION->applyNewRules(newRules);*/ + gfw_Session()->applyNewRules(newRules);*/ return true; } @@ -443,14 +442,14 @@ G_DemoEnds(); // Restore normal game state. - COMMON_GAMESESSION->rules().deathmatch = false; - COMMON_GAMESESSION->rules().noMonsters = false; + gfw_Rule(deathmatch) = false; + gfw_Session()->rules().noMonsters = false; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - COMMON_GAMESESSION->rules().respawnMonsters = false; + gfw_Rule(espawnMonsters) = false; #endif #if __JHEXEN__ - COMMON_GAMESESSION->rules().randomClasses = false; + gfw_Session()->rules().randomClasses = false; #endif break; #endif @@ -637,7 +636,7 @@ case GPT_DISMISS_HUDS: NetCl_DismissHUDs(reader); break; - + default: App_Log(DE2_NET_WARNING, "Game received unknown packet (type:%i)", type); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_netsv.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_netsv.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/network/d_netsv.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/network/d_netsv.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -100,17 +100,17 @@ void NetSv_UpdateGameConfigDescription() { - if(IS_CLIENT) return; + if (IS_CLIENT) return; - GameRuleset const &gameRules = COMMON_GAMESESSION->rules(); + GameRules const &gameRules = gfw_Session()->rules(); - QByteArray str = "skill" + QByteArray::number(gameRules.skill + 1); + QByteArray str = "skill" + QByteArray::number(gameRules.values.skill + 1); - if(gameRules.deathmatch > 1) + if (gameRules.values.deathmatch > 1) { - str += " dm" + QByteArray::number(gameRules.deathmatch); + str += " dm" + QByteArray::number(gameRules.values.deathmatch); } - else if(gameRules.deathmatch) + else if (gameRules.values.deathmatch) { str += " dm"; } @@ -119,18 +119,18 @@ str += " coop"; } - if(gameRules.noMonsters) + if (gameRules.values.noMonsters) { str += " nomonst"; } #if !__JHEXEN__ - if(gameRules.respawnMonsters) + if (gameRules.values.respawnMonsters) { str += " respawn"; } #endif - if(cfg.common.jumpEnabled) + if (cfg.common.jumpEnabled) { str += " jump"; } @@ -354,7 +354,7 @@ #if __JHEXEN__ // In Hexen map numbers must be translated (urgh...). - de::Uri mapUri = TranslateMapWarpNumber(COMMON_GAMESESSION->episodeId(), map); + de::Uri mapUri = TranslateMapWarpNumber(gfw_Session()->episodeId(), map); #else de::Uri mapUri = G_ComposeMapUri(episode, map); #endif @@ -563,7 +563,7 @@ NetSv_ResetPlayerFrags(plrNum); // Spawn the player into the world. - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { G_DeathMatchSpawnPlayer(plrNum); } @@ -572,7 +572,7 @@ playerclass_t pClass = P_ClassForPlayerWhenRespawning(plrNum, false); playerstart_t const *start; - if((start = P_GetPlayerStart(COMMON_GAMESESSION->mapEntryPoint(), plrNum, false))) + if((start = P_GetPlayerStart(gfw_Session()->mapEntryPoint(), plrNum, false))) { mapspot_t const *spot = &mapSpots[start->spot]; @@ -661,9 +661,9 @@ { if(!IS_NETWORK_SERVER) return; - AutoStr *gameId = AutoStr_FromTextStd(COMMON_GAMESESSION->gameId().toLatin1().constData()); - AutoStr *episodeId = AutoStr_FromTextStd(COMMON_GAMESESSION->episodeId().toLatin1().constData()); - de::Uri mapUri = COMMON_GAMESESSION->mapUri(); + AutoStr *gameId = AutoStr_FromTextStd(gfw_GameId().toLatin1().constData()); + AutoStr *episodeId = AutoStr_FromTextStd(gfw_Session()->episodeId().toLatin1().constData()); + de::Uri mapUri = gfw_Session()->mapUri(); // Print a short message that describes the game state. LOG_NET_NOTE("Sending game setup: %s %s %s %s") @@ -693,17 +693,17 @@ // Old map number. Presently unused. Writer_WriteByte(writer, 0); - Writer_WriteByte(writer, (COMMON_GAMESESSION->rules().deathmatch & 0x3) - | (!COMMON_GAMESESSION->rules().noMonsters? 0x4 : 0) + Writer_WriteByte(writer, (gfw_Rule(deathmatch) & 0x3) + | (!gfw_Rule(noMonsters)? 0x4 : 0) #if !__JHEXEN__ - | (COMMON_GAMESESSION->rules().respawnMonsters? 0x8 : 0) + | (gfw_Rule(respawnMonsters)? 0x8 : 0) #else | 0 #endif | (cfg.common.jumpEnabled? 0x10 : 0)); // Note that SM_NOTHINGS will result in a value of '7'. - Writer_WriteByte(writer, COMMON_GAMESESSION->rules().skill & 0x7); + Writer_WriteByte(writer, gfw_Rule(skill) & 0x7); Writer_WriteFloat(writer, (float)P_GetGravity()); if(flags & GSF_CAMERA_INIT) @@ -1136,7 +1136,7 @@ { #if __JDOOM__ || __JDOOM64__ if(!cfg.killMessages) return; - if(!COMMON_GAMESESSION->rules().deathmatch) return; + if(!gfw_Rule(deathmatch)) return; char buf[500]; buf[0] = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_inventory.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_inventory.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_inventory.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_inventory.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -190,7 +190,7 @@ #if __JHEXEN__ // Can't carry more than 1 puzzle item in coop netplay. if(count && type >= IIT_FIRSTPUZZITEM && IS_NETGAME && - !COMMON_GAMESESSION->rules().deathmatch) + !gfw_Rule(deathmatch)) { return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_saveg.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_saveg.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_saveg.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_saveg.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -250,7 +250,7 @@ type = sc_xg1; else #endif - if(!FEQUAL(flooroffx, 0) || !FEQUAL(flooroffy, 0) || !FEQUAL(ceiloffx, 0) || !FEQUAL(ceiloffy, 0)) + if(NON_ZERO(flooroffx) || NON_ZERO(flooroffy) || NON_ZERO(ceiloffx) || NON_ZERO(ceiloffy)) type = sc_ploff; else type = sc_normal; @@ -873,20 +873,20 @@ int const saveVersion = (*metadata)["version"].value().asNumber(); Uri *mapUri = Uri_NewWithPath2((*metadata)["mapUri"].value().asText().toUtf8().constData(), RC_NULL); - GameRuleset *rules = 0; + GameRules *rules = 0; if(metadata->hasSubrecord("gameRules")) { - rules = GameRuleset::fromRecord(metadata->subrecord("gameRules")); + rules = GameRules::fromRecord(metadata->subrecord("gameRules")); } // Do we need to change the map? - if(COMMON_GAMESESSION->mapUri() != *reinterpret_cast(mapUri)) + if(gfw_Session()->mapUri() != *reinterpret_cast(mapUri)) { - COMMON_GAMESESSION->begin(*mapUri, 0/*default*/, *rules); + gfw_Session()->begin(*mapUri, 0/*default*/, *rules); } else if(rules) { - COMMON_GAMESESSION->rules() = *rules; + gfw_Session()->rules() = *rules; } delete rules; rules = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_user.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_user.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_user.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_user.c 2018-12-11 07:08:21.000000000 +0000 @@ -57,6 +57,7 @@ #define ANG5 (ANG90/18) dd_bool onground; +float turboMul = 1.0f; // Multiplier for running speed. int maxHealth; // 100 #if __JDOOM__ || __JDOOM64__ @@ -312,9 +313,11 @@ if(IS_CLIENT && plrNum == CONSOLEPLAYER) return; +#if !defined (DENG_MOBILE) // On server, there must be valid coordinates. if(IS_SERVER && !Sv_CanTrustClientPos(plrNum)) return; +#endif // Unless there is a pending momentum fix, clear the mobj's momentum. if(ddpl->fixCounter.mom == ddpl->fixAcked.mom && !(ddpl->flags & DDPF_FIXMOM)) @@ -391,12 +394,12 @@ if(IS_NETWORK_SERVER) { // Server starts the walking animation for remote players. - if((!FEQUAL(dp->forwardMove, 0) || !FEQUAL(dp->sideMove, 0)) && + if((NON_ZERO(dp->forwardMove) || NON_ZERO(dp->sideMove)) && plrmo->state == &STATES[pClassInfo->normalState]) { P_MobjChangeState(plrmo, pClassInfo->runState); } - else if(P_PlayerInWalkState(player) && FEQUAL(dp->forwardMove, 0) && FEQUAL(dp->sideMove, 0)) + else if(P_PlayerInWalkState(player) && IS_ZERO(dp->forwardMove) && IS_ZERO(dp->sideMove)) { // If in a walking frame, stop moving. P_MobjChangeState(plrmo, pClassInfo->normalState); @@ -470,17 +473,17 @@ sideMove = 0; } - if(!FEQUAL(forwardMove, 0) && movemul) + if(NON_ZERO(forwardMove) && movemul) { P_Thrust(player, plrmo->angle, forwardMove * movemul); } - if(!FEQUAL(sideMove, 0) && movemul) + if(NON_ZERO(sideMove) && movemul) { P_Thrust(player, plrmo->angle - ANG90, sideMove * movemul); } - if((!FEQUAL(forwardMove, 0) || !FEQUAL(sideMove, 0)) && + if((NON_ZERO(forwardMove) || NON_ZERO(sideMove)) && plrmo->state == &STATES[pClassInfo->normalState]) { P_MobjChangeState(plrmo, pClassInfo->runState); @@ -700,7 +703,7 @@ return; pmo = player->plr->mo; - if(FEQUAL(pmo->mom[MX], 0) && FEQUAL(pmo->mom[MY], 0) && P_Random() < 64) + if(IS_ZERO(pmo->mom[MX]) && IS_ZERO(pmo->mom[MY]) && P_Random() < 64) { // Snout sniff P_SetPspriteNF(player, ps_weapon, S_SNOUTATK2); S_StartSound(SFX_PIG_ACTIVE1, pmo); // snort @@ -735,7 +738,7 @@ if(!IS_NETGAME || IS_CLIENT) { - if(FEQUAL(pmo->mom[MX], 0) && FEQUAL(pmo->mom[MY], 0) && P_Random() < 160) + if(IS_ZERO(pmo->mom[MX]) && IS_ZERO(pmo->mom[MY]) && P_Random() < 160) { // Twitch view angle pmo->angle += (P_Random() - P_Random()) << 19; } @@ -1030,7 +1033,7 @@ plrmo->flags2 &= ~MF2_FLY; plrmo->flags &= ~MF_NOGRAVITY; } - else if(!FEQUAL(player->brain.upMove, 0) && player->powers[PT_FLIGHT]) + else if(NON_ZERO(player->brain.upMove) && player->powers[PT_FLIGHT]) { player->flyHeight = player->brain.upMove * 10; if(!(plrmo->flags2 & MF2_FLY)) @@ -1223,10 +1226,10 @@ } else // Check for weapon change. -#if __JHERETIC__ || __JHEXEN__ - if(brain->changeWeapon != WT_NOCHANGE && !player->morphTics) +#if defined(__JHERETIC__) || defined(__JHEXEN__) + if (brain->changeWeapon != WT_NOCHANGE && !player->morphTics) #else - if(brain->changeWeapon != WT_NOCHANGE) + if (brain->changeWeapon != WT_NOCHANGE) #endif { // Direct slot selection. @@ -1253,7 +1256,11 @@ (cand = P_WeaponSlotCycle(cand, brain->cycleWeapon < 0)) != first); } - else if(brain->cycleWeapon) +#if defined(__JHERETIC__) || defined(__JHEXEN__) + else if (brain->cycleWeapon && player->morphTics == 0) +#else + else if (brain->cycleWeapon) +#endif { // Linear cycle. newweapon = P_PlayerFindWeapon(player, brain->cycleWeapon < 0); @@ -1332,28 +1339,24 @@ ST_LogRefresh(playerIdx); } -void P_PlayerThinkMap(player_t* player) +void P_PlayerThinkMap(player_t *player) { - uint playerIdx = player - players; - playerbrain_t* brain = &player->brain; + uint playerIdx = player - players; + playerbrain_t *brain = &player->brain; - if(brain->mapToggle) + if (brain->mapToggle) ST_AutomapOpen(playerIdx, !ST_AutomapIsOpen(playerIdx), false); - if(brain->mapFollow) + if (brain->mapFollow) ST_AutomapFollowMode(playerIdx); - if(brain->mapRotate) - { - cfg.common.automapRotate = !cfg.common.automapRotate; - ST_SetAutomapCameraRotation(playerIdx, cfg.common.automapRotate); - P_SetMessageWithFlags(player, (cfg.common.automapRotate ? AMSTR_ROTATEON : AMSTR_ROTATEOFF), LMF_NO_HIDE); - } + if (brain->mapRotate) + G_SetAutomapRotateMode(!cfg.common.automapRotate); // changes cvar as well - if(brain->mapZoomMax) + if (brain->mapZoomMax) ST_AutomapZoomMode(playerIdx); - if(brain->mapMarkAdd) + if (brain->mapMarkAdd) { mobj_t *pmo = player->plr->mo; ST_AutomapAddPoint(playerIdx, pmo->origin[VX], pmo->origin[VY], pmo->origin[VZ]); @@ -1600,7 +1603,7 @@ // Check for extra speed. P_GetControlState(playerNum, CTL_SPEED, &vel, NULL); - if(!FEQUAL(vel, 0) ^ (cfg.common.alwaysRun != 0)) + if(NON_ZERO(vel) ^ (cfg.common.alwaysRun != 0)) { // Hurry, good man! turnSpeedPerTic = pClassInfo->turnSpeed[1]; @@ -1710,11 +1713,11 @@ // Check for speed. P_GetControlState(playerNum, CTL_SPEED, &vel, 0); - brain->speed = (!FEQUAL(vel, 0)); + brain->speed = (NON_ZERO(vel)); // Check for strafe. //P_GetControlState(playerNum, CTL_MODIFIER_1, &vel, 0); - //strafe = (!FEQUAL(vel, 0)); + //strafe = (NON_ZERO(vel)); // Move status. P_GetControlState(playerNum, CTL_WALK, &vel, &off); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_view.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_view.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/p_view.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/p_view.c 2018-12-11 07:08:21.000000000 +0000 @@ -119,7 +119,16 @@ else { angle_t angle = (FINEANGLES / 20 * mapTime) & FINEMASK; - target = cfg.common.bobView * ((plr->bob / 2) * FIX2FLT(finesine[angle])); + double bobView = cfg.common.bobView; +#if __JDOOM__ + if (gameModeBits & (GM_DOOM_BFG | GM_DOOM2_BFG | GM_DOOM2_NERVE)) + { + // BFG Edition reduces view bobbing: + // https://doomwiki.org/wiki/Doom_3:_BFG_Edition + bobView *= .75; + } +#endif + target = bobView * ((plr->bob / 2) * FIX2FLT(finesine[angle])); } // Do the change gradually. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/r_common.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/r_common.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/r_common.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/r_common.c 2018-12-11 07:08:21.000000000 +0000 @@ -47,6 +47,7 @@ #include "p_actor.h" #include "player.h" #include "r_common.h" +#include "r_special.h" #include "x_hair.h" Size2Rawf viewScale = { 1, 1 }; @@ -316,28 +317,28 @@ void G_DrawViewPort(int port, RectRaw const *portGeometry, RectRaw const *windowGeometry, int player, int layer) { - switch(G_GameState()) + switch (G_GameState()) { case GS_MAP: { player_t* plr = players + player; dd_bool isAutomapObscuring = ST_AutomapObscures2(player, windowGeometry); - if(IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) + if (IS_CLIENT && (!Get(DD_GAME_READY) || !Get(DD_GOTFRAME))) return; - if(Con_GetInteger("rend-vr-mode") == 9) // Oculus Rift mode + if (cfg.common.automapNeverObscure || Con_GetInteger("rend-vr-mode") == 9) // Oculus Rift mode { // Automap will not cover the full view. isAutomapObscuring = false; } - switch(layer) + switch (layer) { case 0: // Primary layer (3D view). - if(!isAutomapObscuring) + if (!isAutomapObscuring) { G_RendPlayerView(player); -#if !defined(__JDOOM__) && !defined(__JHEXEN__) +#if defined(__JDOOM64__) G_RendSpecialFilter(player, windowGeometry); #endif } @@ -345,7 +346,7 @@ default: // HUD layer. // Crosshair. - if(!isAutomapObscuring && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam + if (!isAutomapObscuring && !(P_MobjIsCamera(plr->plr->mo) && Get(DD_PLAYBACK))) // $democam { X_Drawer(player); } @@ -357,7 +358,7 @@ break; } case GS_STARTUP: - if(layer == 0) + if (layer == 0) { DGL_DrawRectf2Color(0, 0, portGeometry->size.width, portGeometry->size.height, 0, 0, 0, 1); @@ -372,7 +373,5 @@ void G_ResetViewEffects() { GL_ResetViewEffects(); -#if __JDOOM__ - G_InitSpecialFilter(); -#endif + R_InitSpecialFilter(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/r_special.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/r_special.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/r_special.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/r_special.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,122 @@ +/** @file h_special.cpp Special color effects for the game view. + * + * @authors Copyright (c) 2018 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "r_special.h" +#include "common.h" + +static float appliedFilter[MAXPLAYERS]; + +#if defined(__JHERETIC__) +static byte ringShader = 0; +#endif + +void R_SpecialFilterRegister() +{ +#if defined(__JHERETIC__) + C_VAR_BYTE("rend-ring-effect", &ringShader, 0, 0, 1); +#endif + R_InitSpecialFilter(); +} + +void R_InitSpecialFilter() +{ + for(int i = 0; i < MAXPLAYERS; ++i) + { + appliedFilter[i] = -1; + } +} + +void R_ClearSpecialFilter(int player, float fadeDuration) +{ + if (appliedFilter[player] > 0) + { + DD_Executef(true, "postfx %i opacity 1; postfx %i none %f", player, player, fadeDuration); + appliedFilter[player] = -1; + } +} + +void R_UpdateSpecialFilterWithTimeDelta(int player, float delta) +{ + const player_t *plr = players + player; + const char * fxName = "none"; + float intensity = 1.f; + +#if defined(__JDOOM__) + { + // In HacX a simple blue shift is used instead. + if (gameMode == doom2_hacx) return; + + fxName = "monochrome.inverted"; + + int filter = plr->powers[PT_INVULNERABILITY]; + if (!filter) + { + // Clear the filter. + R_ClearSpecialFilter(player, delta); + return; + } + if (filter < 4 * 32 && !(filter & 8)) + { + intensity = 0; + } + } +#endif + +#if defined(__JHERETIC__) + { + delta = 0; // not animated + fxName = (ringShader == 0 ? "colorize.gold" : "colorize.inverted.gold"); + + const int filter = plr->powers[PT_INVULNERABILITY]; + if (!filter) + { + // Clear the filter. + R_ClearSpecialFilter(player, delta); + return; + } + if (filter <= BLINKTHRESHOLD && !(filter & 8)) + { + intensity = 0; + } + } +#endif + + if (gfw_CurrentGame() == GFW_HEXEN || gfw_CurrentGame() == GFW_DOOM64) + { + R_ClearSpecialFilter(player, delta); + return; + } + + // Activate the filter; load the shader if the effect was previously not in use. + if (appliedFilter[player] < 0) + { + DD_Executef(true, "postfx %i %s %f", player, fxName, delta); + } + + // Update filter opacity. + if (!FEQUAL(appliedFilter[player], intensity)) + { + DD_Executef(true, "postfx %i opacity %f", player, intensity); + appliedFilter[player] = intensity; + } +} + +void R_UpdateSpecialFilter(int player) +{ + R_UpdateSpecialFilterWithTimeDelta(player, .3f); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/dmu_lib.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/dmu_lib.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/dmu_lib.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/dmu_lib.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -641,14 +641,14 @@ uint const dmuSurfaceOriginFlags = DMU_OFFSET_XY | DMU_FLAG_FOR_SIDESECTION(section); float origin[2]; - if(FEQUAL(deltaXY[0], 0) && FEQUAL(deltaXY[1], 0)) return; + if(IS_ZERO(deltaXY[0]) && IS_ZERO(deltaXY[1])) return; P_GetFloatpv(side, dmuSurfaceOriginFlags, origin); - if(!FEQUAL(deltaXY[0], 0)) + if(NON_ZERO(deltaXY[0])) { origin[0] += deltaXY[0]; } - if(!FEQUAL(deltaXY[1], 0)) + if(NON_ZERO(deltaXY[1])) { origin[1] += deltaXY[1]; } @@ -670,14 +670,14 @@ DENG_ASSERT(plane); - if(FEQUAL(deltaXY[0], 0) && FEQUAL(deltaXY[1], 0)) return; + if(IS_ZERO(deltaXY[0]) && IS_ZERO(deltaXY[1])) return; P_GetFloatpv(plane, DMU_OFFSET_XY, origin); - if(!FEQUAL(deltaXY[0], 0)) + if(NON_ZERO(deltaXY[0])) { origin[0] += deltaXY[0]; } - if(!FEQUAL(deltaXY[1], 0)) + if(NON_ZERO(deltaXY[1])) { origin[1] += deltaXY[1]; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mapstatereader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mapstatereader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mapstatereader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mapstatereader.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -40,6 +40,7 @@ #include "r_common.h" #include "thinkerinfo.h" #include "gamesession.h" +#include "acs/system.h" namespace internal { @@ -675,7 +676,7 @@ { #if __JHEXEN__ beginSegment(ASEG_SCRIPTS); - COMMON_GAMESESSION->acsSystem().readMapState(thisPublic); + gfw_Session()->acsSystem().readMapState(thisPublic); // endSegment(); #endif } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mapstatewriter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mapstatewriter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mapstatewriter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mapstatewriter.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -28,6 +28,7 @@ #include "p_saveg.h" // SV_WriteSector, SV_WriteLine #include "polyobjs.h" #include "thinkerinfo.h" +#include "acs/system.h" #include #include @@ -238,7 +239,7 @@ { #if __JHEXEN__ beginSegment(ASEG_SCRIPTS); - COMMON_GAMESESSION->acsSystem().writeMapState(thisPublic); + gfw_Session()->acsSystem().writeMapState(thisPublic); // endSegment(); #endif } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mobj.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mobj.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/mobj.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/mobj.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -26,7 +26,10 @@ #include #include +#include #include +#include + #include "dmu_lib.h" #include "mapstatereader.h" #include "mapstatewriter.h" @@ -146,7 +149,7 @@ return; } - if(mo->origin[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) + if (mo->origin[VZ] > mo->floorZ && !mo->onMobj && !(mo->flags2 & MF2_FLY)) { // No friction when falling. return; @@ -179,8 +182,8 @@ { belowStandSpeed = (INRANGE_OF(mo->mom[MX], 0, STANDSPEED) && INRANGE_OF(mo->mom[MY], 0, STANDSPEED)); - isMovingPlayer = (!FEQUAL(player->plr->forwardMove, 0) || - !FEQUAL(player->plr->sideMove, 0)); + isMovingPlayer = (NON_ZERO(player->plr->forwardMove) || + NON_ZERO(player->plr->sideMove)); } // Stop player walking animation (only real players). @@ -230,6 +233,36 @@ return false; } +uint32_t Mobj_PrivateID(mobj_t const *mob) +{ + if (!mob) + { + return 0; + } + if (auto const *td = THINKER_DATA_MAYBE(mob->thinker, ThinkerData)) + { + return td->id(); + } + return 0; +} + +mobj_t *Mobj_FindByPrivateID(uint32_t privateId) +{ + if (privateId == 0) + { + return nullptr; + } + + if (auto *thinkerData = ThinkerData::find(de::Id(privateId))) + { + if (auto *mobjData = de::maybeAs(thinkerData)) + { + return mobjData->mobj(); + } + } + return nullptr; +} + dd_bool Mobj_IsPlayer(mobj_t const *mob) { if(!mob) return false; @@ -615,7 +648,7 @@ break; } - Writer_WriteInt32(writer, PTR2INT(mo->lastEnemy)); + Writer_WriteInt32(writer, 0); //PTR2INT(mo->lastEnemy)); #elif __JHERETIC__ Writer_WriteInt16(writer, msw->serialIdFor(mo->generator)); #endif @@ -854,12 +887,16 @@ #if __JHEXEN__ if(ver >= 4) { - tracer = INT2PTR(mobj_t, Reader_ReadInt32(reader)); + // This value has not been mangled properly. + /*tracer = */INT2PTR(mobj_t, Reader_ReadInt32(reader)); + tracer = nullptr; } if(ver >= 4) { - lastEnemy = INT2PTR(mobj_t, Reader_ReadInt32(reader)); + // This value has not been mangled properly. + /*lastEnemy =*/ INT2PTR(mobj_t, Reader_ReadInt32(reader)); + lastEnemy = nullptr; } #else if(ver >= 5) @@ -1027,3 +1064,88 @@ // Notify the engine. THINKER_DATA(mob->thinker, MobjThinkerData).damageReceived(damage, inflictor); } + +de::String Mobj_StateAsInfo(mobj_t const *mob) +{ + using de::String; + + QString str; + QTextStream os(&str); + os.setCodec("UTF-8"); + + os << "Mobj 0x" << String::number(Mobj_PrivateID(mob), 16) + << " {\n target = 0x" << String::number(Mobj_PrivateID(mob->target), 16) + << "\n onMobj = 0x" << String::number(Mobj_PrivateID(mob->onMobj), 16) + << "\n tracer = 0x" << String::number(Mobj_PrivateID(mob->tracer), 16); + + #if defined (__JHERETIC__) + { + os << "\n generator = 0x" << String::number(Mobj_PrivateID(mob->generator), 16); + } + #endif + + #if defined (__JHEXEN__) + { + os << "\n lastEnemy = 0x" << String::number(Mobj_PrivateID(mob->lastEnemy), 16); + } + #endif + + os << "\n}\n"; + + return str; +} + +void Mobj_RestoreObjectState(mobj_t *mob, de::Info::BlockElement const &state) +{ + static de::String const KEY_TARGET ("target"); + static de::String const KEY_ON_MOBJ ("onMobj"); + static de::String const KEY_TRACER ("tracer"); + static de::String const KEY_GENERATOR ("generator"); + static de::String const KEY_LAST_ENEMY ("lastEnemy"); + + bool ok; + uint32_t pid; + + pid = state.keyValue(KEY_TARGET).text.toUInt32(&ok, 0); + if (ok) + { + mob->target = Mobj_FindByPrivateID(pid); + //qDebug() << "mobj" << mob->thinker.id << "target" << pid << mob->target; + } + + pid = state.keyValue(KEY_ON_MOBJ).text.toUInt32(&ok, 0); + if (ok) + { + mob->onMobj = Mobj_FindByPrivateID(pid); + //qDebug() << "mobj" << mob->thinker.id << "onMobj" << pid << mob->onMobj; + } + + pid = state.keyValue(KEY_TRACER).text.toUInt32(&ok, 0); + if (ok) + { + mob->tracer = Mobj_FindByPrivateID(pid); + //qDebug() << "mobj" << mob->thinker.id << "tracer" << pid << mob->tracer; + } + + #if defined (__JHERETIC__) + { + pid = state.keyValue(KEY_GENERATOR).text.toUInt32(&ok, 0); + if (ok) + { + mob->generator = Mobj_FindByPrivateID(pid); + //qDebug() << "mobj" << mob->thinker.id << "generator" << pid << mob->generator; + } + } + #endif + + #if defined (__JHEXEN__) + { + pid = state.keyValue(KEY_LAST_ENEMY).text.toUInt32(&ok, 0); + if (ok) + { + mob->lastEnemy = Mobj_FindByPrivateID(pid); + //qDebug() << "mobj" << mob->thinker.id << "lastEnemy" << pid << mob->lastEnemy; + } + } + #endif +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_actor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_actor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_actor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_actor.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -74,23 +74,23 @@ DENG_UNUSED(noRespawn); #endif - if(mo->ddFlags & DDMF_REMOTE) + if (mo->ddFlags & DDMF_REMOTE) goto justDoIt; #if __JDOOM__ || __JDOOM64__ - if(!noRespawn) + if (!noRespawn) { - if( + if ( # if __JDOOM__ // Only respawn items in deathmatch 2 and optionally in coop. - !(COMMON_GAMESESSION->rules().deathmatch != 2 && - (!cfg.coopRespawnItems || !IS_NETGAME || COMMON_GAMESESSION->rules().deathmatch)) && + (gfw_Rule(deathmatch) == 2 || + (cfg.coopRespawnItems && IS_NETGAME && !gfw_Rule(deathmatch))) && # endif /*#elif __JDOOM64__ (spot->flags & MTF_RESPAWN) && # endif*/ - (mo->flags & MF_SPECIAL) && !(mo->flags & MF_DROPPED) + (mo->flags & MF_SPECIAL) && !(mo->flags & MF_DROPPED) # if __JDOOM__ || __JDOOM64__ - && (mo->type != MT_INV) && (mo->type != MT_INS) + && (mo->type != MT_INV) && (mo->type != MT_INS) # endif ) { @@ -102,7 +102,7 @@ #endif #if __JHEXEN__ - if((mo->flags & MF_COUNTKILL) && (mo->flags & MF_CORPSE)) + if ((mo->flags & MF_COUNTKILL) && (mo->flags & MF_CORPSE)) { P_RemoveCorpseInQueue(mo); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/player.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/player.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/player.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/player.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -41,6 +41,7 @@ #include "p_map.h" #include "p_saveg.h" #include "p_start.h" +#include "r_special.h" using namespace de; @@ -298,7 +299,7 @@ int fireMode = 0; #if __JHERETIC__ - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) fireMode = 0; // In deathmatch always use mode zero. else fireMode = (player->powers[PT_WEAPONLEVEL2]? 1 : 0); @@ -370,7 +371,7 @@ #if __JHERETIC__ // Heretic always uses lvl 0 ammo requirements in deathmatch - if(COMMON_GAMESESSION->rules().deathmatch && + if(gfw_Rule(deathmatch) && player->ammo[ammotype].owned < winf->mode[0].perShot[ammotype]) { // Not enough ammo of this type. Candidate is NOT good. @@ -517,7 +518,7 @@ int fireMode = 0; #if __JHERETIC__ // If deathmatch always use firemode two ammo requirements. - if(plr->powers[PT_WEAPONLEVEL2] && !COMMON_GAMESESSION->rules().deathmatch) + if(plr->powers[PT_WEAPONLEVEL2] && !gfw_Rule(deathmatch)) { fireMode = 1; } @@ -693,7 +694,7 @@ } #endif -void P_SetMessageWithFlags(player_t *pl, char const *msg, int flags) +void P_SetMessageWithFlags(const player_t *pl, char const *msg, int flags) { DENG2_ASSERT(pl); @@ -710,7 +711,7 @@ NetSv_SendMessage(pl - players, msg); } -void P_SetMessage(player_t *plr, char const *msg) +void P_SetMessage(const player_t *plr, char const *msg) { P_SetMessageWithFlags(plr, msg, 0); } @@ -1274,12 +1275,10 @@ player->update |= PSF_POWERS; de::zap(player->powers); -#if __JDOOM__ - G_UpdateSpecialFilterWithTimeDelta(plrNum, 0 /* instantly */); -#endif + R_UpdateSpecialFilterWithTimeDelta(plrNum, 0 /* instantly */); #if __JHEXEN__ - if(!newHub && !COMMON_GAMESESSION->rules().deathmatch) + if(!newHub && !gfw_Rule(deathmatch)) { player->powers[PT_FLIGHT] = flightPower; // Restore flight. } @@ -1290,7 +1289,7 @@ player->update |= PSF_KEYS; de::zap(player->keys); #else - if(!COMMON_GAMESESSION->rules().deathmatch && newHub) + if(!gfw_Rule(deathmatch) && newHub) { player->keys = 0; } @@ -1949,6 +1948,9 @@ /* WT_SEVENTH */ { "player-weapon-bfg", CVAR_DELIM }, /* WT_EIGHTH */ { "player-weapon-chainsaw", CVAR_DELIM }, /* WT_NINETH */ { "player-weapon-sshotgun", CVAR_DELIM }, + #if __JDOOM64__ + /* WT_TENTH */ { "player-weapon-unmaker", CVAR_DELIM }, + #endif #elif __JHERETIC__ /* WT_FIRST */ { "player-weapon-staff", CVAR_DELIM }, /* WT_SECOND */ { "player-weapon-goldwand", CVAR_DELIM }, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_map.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_map.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_map.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_map.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -89,7 +89,7 @@ { return (coord_t) cfg.common.netGravity / 100; } - return *((coord_t *) DD_GetVariable(DD_GRAVITY)); + return *((coord_t *) DD_GetVariable(DD_MAP_GRAVITY)); } /** @@ -195,7 +195,7 @@ return true; #elif __JDOOM__ // Monsters only stomp on a boss map. - if(!Mobj_IsPlayer(parm.stompMobj) && COMMON_GAMESESSION->mapUri().path() != "MAP30") + if(!Mobj_IsPlayer(parm.stompMobj) && gfw_Session()->mapUri().path() != "MAP30") return true; #endif } @@ -479,7 +479,7 @@ { if((thing->flags & MF_SHOOTABLE) && thing != tmThing->target) { - if(IS_NETGAME && !COMMON_GAMESESSION->rules().deathmatch && thing->player) + if(IS_NETGAME && !gfw_Rule(deathmatch) && thing->player) { return false; // don't attack other co-op players } @@ -850,10 +850,32 @@ if((thing->flags2 & MF2_PUSHABLE) && !(tmThing->flags2 & MF2_CANNOTPUSH)) { - // Push thing - thing->mom[MX] += tmThing->mom[MX] / 4; - thing->mom[MY] += tmThing->mom[MY] / 4; - NetSv_PlayerMobjImpulse(thing, tmThing->mom[MX]/4, tmThing->mom[MY]/4, 0); + // Push thing. + coord_t pushImpulse[2] = {tmThing->mom[MX] / 4, tmThing->mom[MY] / 4}; + + for (int axis = 0; axis < 2; ++axis) + { + // Do not exceed the momentum of the thing doing the pushing. + if (cfg.common.pushableMomentumLimitedToPusher) + { + coord_t maxIncrement = tmThing->mom[axis] - thing->mom[axis]; + if (thing->mom[axis] > 0 && pushImpulse[axis] > 0) + { + pushImpulse[axis] = de::max(0.0, de::min(pushImpulse[axis], maxIncrement)); + } + else if (thing->mom[axis] < 0 && pushImpulse[axis] < 0) + { + pushImpulse[axis] = de::min(0.0, de::max(pushImpulse[axis], maxIncrement)); + } + } + + thing->mom[axis] += pushImpulse[axis]; + } + + if (!de::fequal(pushImpulse[MX], 0) || !de::fequal(pushImpulse[MY], 0)) + { + NetSv_PlayerMobjImpulse(thing, float(pushImpulse[MX]), float(pushImpulse[MY]), 0); + } } // @fixme Kludge: Always treat blood as a solid. @@ -1101,7 +1123,12 @@ dd_bool P_CheckPositionXYZ(mobj_t *thing, coord_t x, coord_t y, coord_t z) { -#if !__JHEXEN__ +#if defined(__JHERETIC__) + if (thing->type != MT_POD) // vanilla onMobj behavior for pods + { + thing->onMobj = nullptr; + } +#elif !__JHEXEN__ thing->onMobj = 0; #endif thing->wallHit = false; @@ -1864,7 +1891,7 @@ divisor *= 2; // Can we get any closer? - if(FEQUAL(d[VZ] / divisor, 0)) + if(IS_ZERO(d[VZ] / divisor)) { break; // No. } @@ -2065,7 +2092,7 @@ #if __JDOOM__ || __JHEXEN__ || __JDOOM64__ if(Mobj_IsPlayer(shooterThing) && Mobj_IsPlayer(th) && - IS_NETGAME && !COMMON_GAMESESSION->rules().deathmatch) + IS_NETGAME && !gfw_Rule(deathmatch)) { // In co-op, players don't aim at fellow players (although manually aiming is // always possible). @@ -3029,7 +3056,7 @@ } else if(mo->flags2 & MF2_LOGRAV) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) { mo->mom[MZ] = -(P_GetGravity() / 32) * 2; } @@ -3040,7 +3067,7 @@ } else if(!(mo->flags & MF_NOGRAVITY)) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) { mo->mom[MZ] = -P_GetGravity() * 2; } @@ -3249,11 +3276,11 @@ } // A known ACScript? - if(COMMON_GAMESESSION->acsSystem().hasScript(xline->arg2)) + if(gfw_Session()->acsSystem().hasScript(xline->arg2)) { /// @todo fixme: Really interpret the first byte of xline_t::flags as a /// script argument? (I wonder if any scripts rely on this). -ds - COMMON_GAMESESSION->acsSystem() + gfw_Session()->acsSystem() .script(xline->arg2) .start(acs::Script::Args(&xline->arg3, 4/*3*/), parm.useMobj, icpt->line, 0); @@ -3281,11 +3308,11 @@ } // A known ACScript? - if(COMMON_GAMESESSION->acsSystem().hasScript(mob.args[1])) + if(gfw_Session()->acsSystem().hasScript(mob.args[1])) { /// @todo fixme: Really interpret the first byte of mobj_t::turnTime as a /// script argument? (I wonder if any scripts rely on this). -ds - COMMON_GAMESESSION->acsSystem() + gfw_Session()->acsSystem() .script(mob.args[1]) .start(acs::Script::Args(&mob.args[2], 4/*3*/), parm.useMobj, nullptr, 0); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_mapsetup.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_mapsetup.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_mapsetup.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_mapsetup.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -223,19 +223,19 @@ return false; // Don't spawn things flagged for Not Deathmatch if we're deathmatching. - if(COMMON_GAMESESSION->rules().deathmatch && (spot->flags & MSF_NOTDM)) + if(gfw_Rule(deathmatch) && (spot->flags & MSF_NOTDM)) return false; // Don't spawn things flagged for Not Coop if we're coop'in. - if(IS_NETGAME && !COMMON_GAMESESSION->rules().deathmatch && (spot->flags & MSF_NOTCOOP)) + if(IS_NETGAME && !gfw_Rule(deathmatch) && (spot->flags & MSF_NOTCOOP)) return false; // The special "spawn no things" skill mode means nothing is spawned. - if(COMMON_GAMESESSION->rules().skill == SM_NOTHINGS) + if(gfw_Rule(skill) == SM_NOTHINGS) return false; // Check for appropriate skill level. - if(!(spot->skillModes & (1 << COMMON_GAMESESSION->rules().skill))) + if(!(spot->skillModes & (1 << gfw_Rule(skill)))) return false; #if __JHEXEN__ @@ -249,7 +249,7 @@ return false; } } - else if(!COMMON_GAMESESSION->rules().deathmatch) + else if(!gfw_Rule(deathmatch)) { // Cooperative mode. @@ -493,7 +493,7 @@ P_DealPlayerStarts(0); - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { uint numDMStarts = P_GetNumPlayerStarts(true); uint playerCount = 0; @@ -635,18 +635,36 @@ #if __JHERETIC__ // Spawn a Firemace? App_Log(DE2_DEV_MAP_VERBOSE, "spawnMapObjects: %i Firemace spot(s)", maceSpotCount); - if(!IS_CLIENT && maceSpotCount) + if (gfw_MapInfoFlags() & MIF_SPAWN_ALL_FIREMACES) { - // Sometimes the Firemace doesn't show up if not in deathmatch. - if(COMMON_GAMESESSION->rules().deathmatch || M_Random() >= 64) + for (uint i = 0; i < maceSpotCount; ++i) { - if(mapspot_t const *spot = P_ChooseRandomMaceSpot()) + const mapspot_t *spot = &mapSpots[maceSpots[i]]; + if (checkMapSpotSpawnFlags(spot)) { - App_Log(DE2_DEV_MAP_VERBOSE, "spawnMapObjects: Spawning Firemace at (%g, %g, %g)", - spot->origin[VX], spot->origin[VY], spot->origin[VZ]); + P_SpawnMobjXYZ( + MT_WMACE, spot->origin[VX], spot->origin[VY], 0, spot->angle, MSF_Z_FLOOR); + } + } + } + else + { + if (!IS_CLIENT && maceSpotCount) + { + // Sometimes the Firemace doesn't show up if not in deathmatch. + if (gfw_Rule(deathmatch) || M_Random() >= 64) + { + if (mapspot_t const *spot = P_ChooseRandomMaceSpot()) + { + App_Log(DE2_DEV_MAP_VERBOSE, + "spawnMapObjects: Spawning Firemace at (%g, %g, %g)", + spot->origin[VX], + spot->origin[VY], + spot->origin[VZ]); - P_SpawnMobjXYZ(MT_WMACE, spot->origin[VX], spot->origin[VY], 0, - spot->angle, MSF_Z_FLOOR); + P_SpawnMobjXYZ( + MT_WMACE, spot->origin[VX], spot->origin[VY], 0, spot->angle, MSF_Z_FLOOR); + } } } } @@ -661,21 +679,21 @@ void P_SetupMap(de::Uri const &mapUri) { - if(IS_DEDICATED) + if (IS_DEDICATED) { - // Whenever the map changes, update the game rule config. - GameRuleset newRules(COMMON_GAMESESSION->rules()); // make a copy - newRules.skill = cfg.common.netSkill; - newRules.deathmatch = cfg.common.netDeathmatch; - newRules.noMonsters = cfg.common.netNoMonsters; + // Whenever the map changes, update the game rule config based on cvars. + GameRules newRules(gfw_Session()->rules()); + GameRules_Set(newRules, skill, cfg.common.netSkill); + GameRules_Set(newRules, deathmatch, cfg.common.netDeathmatch); + GameRules_Set(newRules, noMonsters, cfg.common.netNoMonsters); /*newRules.*/cfg.common.jumpEnabled = cfg.common.netJumping; #if __JDOOM__ || __JHERETIC__ || __JDOOM64__ - newRules.respawnMonsters = cfg.netRespawn; + GameRules_Set(newRules, respawnMonsters, cfg.netRespawn); #endif #if __JHEXEN__ - newRules.randomClasses = cfg.netRandomClass; + GameRules_Set(newRules, randomClasses, cfg.netRandomClass); #endif - COMMON_GAMESESSION->applyNewRules(newRules); + gfw_Session()->applyNewRules(newRules); } // If we're the server, let clients know the map will change. @@ -685,10 +703,10 @@ mapSetup = true; ::timerGame = 0; - if(COMMON_GAMESESSION->rules().deathmatch) + if (gfw_Rule(deathmatch)) { int parm = CommandLine_Check("-timer"); - if(parm && parm < CommandLine_Count() - 1) + if (parm && parm < CommandLine_Count() - 1) { ::timerGame = atoi(CommandLine_At(parm + 1)) * 35 * 60; } @@ -696,7 +714,7 @@ P_ResetWorldState(); - if(!P_MapChange(mapUri.compose().toUtf8().constData())) + if (!P_MapChange(mapUri.compose().toUtf8().constData())) { Con_Error("P_SetupMap: Failed changing/loading map \"%s\".\n", mapUri.compose().toUtf8().constData()); exit(1); // Unreachable. @@ -910,8 +928,8 @@ XG_Init(); #endif - COMMON_GAMESESSION->acsSystem().loadModuleForMap(mapUri); - COMMON_GAMESESSION->acsSystem().worldSystemMapChanged(); + gfw_Session()->acsSystem().loadModuleForMap(mapUri); + gfw_Session()->acsSystem().worldSystemMapChanged(); #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ P_FindSecrets(); @@ -1028,7 +1046,7 @@ plr->playerState = PST_REBORN; #if __JHEXEN__ - if(!IS_NETGAME || (IS_NETGAME != 0 && COMMON_GAMESESSION->rules().deathmatch != 0) || firstFragReset == 1) + if(!IS_NETGAME || (IS_NETGAME != 0 && gfw_Rule(deathmatch) != 0) || firstFragReset == 1) { memset(plr->frags, 0, sizeof(plr->frags)); firstFragReset = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_mapspec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_mapspec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_mapspec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_mapspec.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -25,6 +25,7 @@ #include "g_game.h" #include "gamesession.h" #include "p_mapsetup.h" +#include "acs/system.h" using namespace de; @@ -118,7 +119,7 @@ void P_NotifySectorFinished(int tag) { #if __JHEXEN__ - COMMON_GAMESESSION->acsSystem().forAllScripts([&tag] (acs::Script &script) + gfw_Session()->acsSystem().forAllScripts([&tag] (acs::Script &script) { script.sectorFinished(tag); return LoopContinue; @@ -131,7 +132,7 @@ void P_NotifyPolyobjFinished(int tag) { #if __JHEXEN__ - COMMON_GAMESESSION->acsSystem().forAllScripts([&tag] (acs::Script &script) + gfw_Session()->acsSystem().forAllScripts([&tag] (acs::Script &script) { script.polyobjFinished(tag); return LoopContinue; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_scroll.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_scroll.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_scroll.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_scroll.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -28,7 +28,7 @@ { DENG_ASSERT(s != 0); - if(FEQUAL(s->offset[0], 0) && FEQUAL(s->offset[1], 0)) return; + if(IS_ZERO(s->offset[0]) && IS_ZERO(s->offset[1])) return; // Side surface(s)? if(DMU_GetType(s->dmuObject) == DMU_SIDE) @@ -127,7 +127,7 @@ if(!dmuObject || elementBits <= 0) return 0; // Don't spawn a scroller with a zero-length offset vector. - if(FEQUAL(offsetXY[0], 0) && FEQUAL(offsetXY[1], 0)) + if(IS_ZERO(offsetXY[0]) && IS_ZERO(offsetXY[1])) { return 0; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_sound.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_sound.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_sound.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_sound.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -33,14 +33,26 @@ using namespace de; -void S_MapMusic(de::Uri const &mapUri) +bool S_MapMusic(de::Uri const &mapUri) { - Block const musicIdUtf8 = G_MapInfoForMapUri(mapUri).gets("music").toUtf8(); - if(S_StartMusic(musicIdUtf8.constData(), true)) + String musicId = G_MapInfoForMapUri(mapUri).gets("music"); + if (musicId.isEmpty()) + { + musicId = mapUri.path(); + } + if (S_StartMusic(musicId.toUtf8(), true)) { // Set the game status cvar for the map music. - Con_SetInteger2("map-music", Defs().getMusicNum(musicIdUtf8.constData()), SVF_WRITE_OVERRIDE); + Con_SetInteger2("map-music", Defs().getMusicNum(musicId.toUtf8()), SVF_WRITE_OVERRIDE); + return true; + } + else + { + // We don't have anything to play. + S_StopMusic(); + Con_SetInteger2("map-music", -1, SVF_WRITE_OVERRIDE); } + return false; } void S_SectorSound(Sector *sec, int id) @@ -105,10 +117,19 @@ if(mapNumber > 0) { - Record const &mapInfo = G_MapInfoForMapUri(G_ComposeMapUri(0, mapNumber - 1)); - if(Record *music = Defs().musics.tryFind("id", mapInfo.gets("music"))) + Record &mapInfo = G_MapInfoForMapUri(G_ComposeMapUri(0, mapNumber - 1)); + if (const Record *music = Defs().musics.tryFind("id", Str_Text(lumpName))) + { + // There is a music definition with this ID, let's use that. + mapInfo.set("music", Str_Text(lumpName)); + } + else { - music->set("lumpName", Str_Text(lumpName)); + // Modify the map's currently used music to override the music lump. + if (Record *music = Defs().musics.tryFind("id", mapInfo.gets("music"))) + { + music->set("lumpName", Str_Text(lumpName)); + } } } continue; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_start.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_start.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_start.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_start.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -365,7 +365,7 @@ { playerstart_t const *start = &playerStarts[i]; - if(start->entryPoint == COMMON_GAMESESSION->mapEntryPoint() && start->plrNum - 1 == pnum) + if(start->entryPoint == gfw_Session()->mapEntryPoint() && start->plrNum - 1 == pnum) return start; if(!start->entryPoint && start->plrNum - 1 == pnum) def = start; @@ -546,7 +546,7 @@ p->viewOffset[VX] = p->viewOffset[VY] = p->viewOffset[VZ] = 0; // Give all cards in death match mode. - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { #if __JHEXEN__ p->keys = 2047; @@ -714,7 +714,7 @@ } // Spawn at random spot if in death match. - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { G_DeathMatchSpawnPlayer(plrNum); return; @@ -752,7 +752,7 @@ int spawnFlags = 0; dd_bool makeCamera = false; - uint entryPoint = COMMON_GAMESESSION->mapEntryPoint(); + uint entryPoint = gfw_Session()->mapEntryPoint(); dd_bool foundSpot = false; playerstart_t const *assigned = P_GetPlayerStart(entryPoint, plrNum, false); @@ -959,7 +959,7 @@ } // If deathmatch, randomly spawn the active players. - if(COMMON_GAMESESSION->rules().deathmatch) + if(gfw_Rule(deathmatch)) { for(int i = 0; i < MAXPLAYERS; ++i) { @@ -1058,7 +1058,7 @@ playerclass_t pClass; #if __JHEXEN__ - if(COMMON_GAMESESSION->rules().randomClasses) + if (gfw_Rule(randomClasses)) { pClass = playerclass_t(P_Random() % 3); if(pClass == cfg.playerClass[playerNum]) // Not the same class, please. @@ -1070,20 +1070,19 @@ pClass = P_ClassForPlayerWhenRespawning(playerNum, false); } - if(IS_CLIENT) + if (IS_CLIENT) { - if(G_GameState() == GS_MAP) + if (G_GameState() == GS_MAP) { // Anywhere will do, for now. spawnPlayer(playerNum, pClass, -30000, -30000, 0, 0, MSF_Z_FLOOR, false, false, false); } - return; } // Now let's find an available deathmatch start. - if(numPlayerDMStarts < 2) + if (numPlayerDMStarts < 2) Con_Error("G_DeathMatchSpawnPlayer: Error, minimum of two " "(deathmatch) mapspots required for deathmatch."); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_tick.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_tick.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_tick.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_tick.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -31,6 +31,7 @@ #include "p_user.h" #include "player.h" #include "r_common.h" +#include "r_special.h" using namespace common; @@ -63,7 +64,7 @@ { if(!--timerGame) { - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); } } @@ -73,6 +74,7 @@ return; Thinker_Run(); + #if __JDOOM__ || __JDOOM64__ || __JHERETIC__ // Extended lines and sectors. XG_Ticker(); @@ -98,9 +100,7 @@ R_UpdateConsoleView(i); } -#ifdef __JDOOM__ - G_UpdateSpecialFilter(DISPLAYPLAYER); -#endif + R_UpdateSpecialFilter(DISPLAYPLAYER); // For par times, among other things. mapTime++; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_xgline.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_xgline.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_xgline.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_xgline.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -977,8 +977,8 @@ { LOG_AS(travsectors? "XL_TraverseSectors" : "XL_TraversePlanes"); - int tag; - mobj_t *mo; + int tag = 0; + mobj_t *mo = NULL; dd_bool ok, findSecTagged; if(xgDev) @@ -1180,10 +1180,10 @@ LOG_AS("XL_TraverseLines"); int i; - int tag; + int tag = 0; int reftype = rtype; char buff[50]; - Line *iter; + Line *iter = NULL; dd_bool findLineTagged; // Binary XG data from DD_XGDATA uses the old flag values. @@ -2085,7 +2085,7 @@ // Is this a secret exit? if(info->iparm[0] > 0) { - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); return false; } @@ -2095,7 +2095,7 @@ // (ip3) will be used to determine next map (1-based). if(info->iparm[3]) { - newMapUri = G_ComposeMapUri(COMMON_GAMESESSION->episodeId().toInt() - 1, info->iparm[3] - 1); + newMapUri = G_ComposeMapUri(gfw_Session()->episodeId().toInt() - 1, info->iparm[3] - 1); LOG_MAP_MSG_XGDEVONLY2("Next map set to \"%s\"", newMapUri); } } @@ -2105,13 +2105,13 @@ int const oldMapNumber = XL_ValidateLineRef(line, info->iparm[3], context2, "Map Number"); if(oldMapNumber > 0) { - newMapUri = G_ComposeMapUri(COMMON_GAMESESSION->episodeId().toInt() - 1, oldMapNumber - 1); + newMapUri = G_ComposeMapUri(gfw_Session()->episodeId().toInt() - 1, oldMapNumber - 1); } } if(newMapUri.isEmpty()) { - newMapUri = COMMON_GAMESESSION->mapUriForNamedExit("next"); + newMapUri = gfw_Session()->mapUriForNamedExit("next"); LOG_MAP_MSG_XGDEVONLY("Next map set to default for the 'next' exit"); } @@ -2120,7 +2120,7 @@ { // Backward compatibility dictates that invalid refs be interpreted to mean the start map // of the current episode (which is known to always exist). - newMapUri = de::Uri(COMMON_GAMESESSION->episodeDef()->gets("startMap"), RC_NULL); + newMapUri = de::makeUri(gfw_Session()->episodeDef()->gets("startMap")); } G_SetGameActionMapCompleted(newMapUri); @@ -2728,17 +2728,17 @@ // Check skill level. // SM_NOTHINGS will be interpreted as SM_BABY. - if(COMMON_GAMESESSION->rules().skill < 1) + if(gfw_Rule(skill) < 1) i = 1; - else if(COMMON_GAMESESSION->rules().skill > 3) + else if(gfw_Rule(skill) > 3) i = 4; else - i = 1 << (COMMON_GAMESESSION->rules().skill - 1); + i = 1 << (gfw_Rule(skill) - 1); if(!(info->flags2 & (i << LTF2_SKILL_SHIFT))) { LOG_MAP_MSG_XGDEVONLY2("Line %i: ABORTING EVENT due to skill level (%i)", - P_ToIndex(line) << COMMON_GAMESESSION->rules().skill); + P_ToIndex(line) << gfw_Rule(skill)); return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_xgsec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_xgsec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/common/src/world/p_xgsec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/common/src/world/p_xgsec.cpp 2018-12-11 07:08:21.000000000 +0000 @@ -962,10 +962,10 @@ { LOG_AS("XS_GetPlane"); - world_Material* otherMat; - coord_t otherHeight; - Sector* otherSec = NULL, *iter; - xline_t* xline; + world_Material *otherMat = NULL; + coord_t otherHeight = 0; + Sector* otherSec = NULL, *iter = NULL; + xline_t* xline = NULL; char buff[50]; if(refdata) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/directsound/res/audio_directsound.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/directsound/res/audio_directsound.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/directsound/res/audio_directsound.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/directsound/res/audio_directsound.rc 2018-12-11 07:08:21.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2009 Daniel Swanson + *\author Copyright (c) 2008-2009 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,7 +80,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsDirectSound.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -118,7 +118,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "dsDirectSound.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom1-ultimate.mapinfo doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom1-ultimate.mapinfo --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom1-ultimate.mapinfo 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom1-ultimate.mapinfo 2018-12-11 07:08:21.000000000 +0000 @@ -80,7 +80,7 @@ sky1 SKY1 0 nointermission par 30 -music E1M8 +music D_E1M8 titlepatch WILV07 cluster 1 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-bfg.mapinfo doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-bfg.mapinfo --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-bfg.mapinfo 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-bfg.mapinfo 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,271 @@ +; DOOM II (Doom 3 BFG Edition) + +episode MAP01 +name "Hell On Earth" +key h + +map MAP01 lookup HUSTR_1 +next MAP02 +warptrans 1 +sky1 SKY1 0 +par 30 +music D_RUNNIN +titlepatch CWILV00 + +map MAP02 lookup HUSTR_2 +next MAP03 +secretnext MAP33 +warptrans 2 +sky1 SKY1 0 +par 90 +music D_STALKS +titlepatch CWILV01 + +map MAP03 lookup HUSTR_3 +next MAP04 +warptrans 3 +sky1 SKY1 0 +par 120 +music D_COUNTD +titlepatch CWILV02 + +map MAP04 lookup HUSTR_4 +next MAP05 +warptrans 4 +sky1 SKY1 0 +par 120 +music D_BETWEE +titlepatch CWILV03 + +map MAP05 lookup HUSTR_5 +next MAP06 +warptrans 5 +sky1 SKY1 0 +par 90 +music D_DOOM +titlepatch CWILV04 + +map MAP06 lookup HUSTR_6 +next MAP07 +warptrans 6 +sky1 SKY1 0 +par 150 +music D_THE_DA +titlepatch CWILV05 + +map MAP07 lookup HUSTR_7 +next MAP08 +warptrans 7 +sky1 SKY1 0 +par 120 +music D_SHAWN +titlepatch CWILV06 + +map MAP08 lookup HUSTR_8 +next MAP09 +warptrans 8 +sky1 SKY1 0 +par 120 +music D_DDTBLU +titlepatch CWILV07 + +map MAP09 lookup HUSTR_9 +next MAP10 +warptrans 9 +sky1 SKY1 0 +par 270 +music D_IN_CIT +titlepatch CWILV08 + +map MAP10 lookup HUSTR_10 +next MAP11 +warptrans 10 +sky1 SKY1 0 +par 90 +music D_DEAD +titlepatch CWILV09 + +map MAP11 lookup HUSTR_11 +next MAP12 +warptrans 11 +sky1 SKY1 0 +par 210 +music D_STLKS2 +titlepatch CWILV10 + +map MAP12 lookup HUSTR_12 +next MAP13 +warptrans 12 +sky1 SKY2 0 +par 150 +music D_THEDA2 +titlepatch CWILV11 + +map MAP13 lookup HUSTR_13 +next MAP14 +warptrans 13 +sky1 SKY2 0 +par 150 +music D_DOOM2 +titlepatch CWILV12 + +map MAP14 lookup HUSTR_14 +next MAP15 +warptrans 14 +sky1 SKY2 0 +par 150 +music D_DDTBL2 +titlepatch CWILV13 + +map MAP15 lookup HUSTR_15 +next MAP16 +secretnext MAP31 +warptrans 15 +sky1 SKY2 0 +par 210 +music D_RUNNI2 +titlepatch CWILV14 + +map MAP16 lookup HUSTR_16 +next MAP17 +warptrans 16 +sky1 SKY2 0 +par 150 +music D_DEAD2 +titlepatch CWILV15 + +map MAP17 lookup HUSTR_17 +next MAP18 +warptrans 17 +sky1 SKY2 0 +par 420 +music D_STLKS3 +titlepatch CWILV16 + +map MAP18 lookup HUSTR_18 +next MAP19 +warptrans 18 +sky1 SKY2 0 +par 150 +music D_ROMERO +titlepatch CWILV17 + +map MAP19 lookup HUSTR_19 +next MAP20 +warptrans 19 +sky1 SKY2 0 +par 210 +music D_SHAWN2 +titlepatch CWILV18 + +map MAP20 lookup HUSTR_20 +next MAP21 +warptrans 20 +sky1 SKY2 0 +par 150 +music D_MESSAG +titlepatch CWILV19 + +map MAP21 lookup HUSTR_21 +next MAP22 +warptrans 21 +sky1 SKY3 0 +par 240 +music D_COUNT2 +titlepatch CWILV20 + +map MAP22 lookup HUSTR_22 +next MAP23 +warptrans 22 +sky1 SKY3 0 +par 150 +music D_DDTBL3 +titlepatch CWILV21 + +map MAP23 lookup HUSTR_23 +next MAP24 +warptrans 23 +sky1 SKY3 0 +par 180 +music D_AMPIE +titlepatch CWILV22 + +map MAP24 lookup HUSTR_24 +next MAP25 +warptrans 24 +sky1 SKY3 0 +par 150 +music D_THEDA3 +titlepatch CWILV23 + +map MAP25 lookup HUSTR_25 +next MAP26 +warptrans 25 +sky1 SKY3 0 +par 150 +music D_ADRIAN +titlepatch CWILV24 + +map MAP26 lookup HUSTR_26 +next MAP27 +warptrans 26 +sky1 SKY3 0 +par 300 +music D_MESSG2 +titlepatch CWILV25 + +map MAP27 lookup HUSTR_27 +next MAP28 +warptrans 27 +sky1 SKY3 0 +par 330 +music D_ROMER2 +titlepatch CWILV26 + +map MAP28 lookup HUSTR_28 +next MAP29 +warptrans 28 +sky1 SKY3 0 +par 420 +music D_TENSE +titlepatch CWILV27 + +map MAP29 lookup HUSTR_29 +next MAP30 +warptrans 29 +sky1 SKY3 0 +par 300 +music D_SHAWN3 +titlepatch CWILV28 + +map MAP30 lookup HUSTR_30 +warptrans 30 +sky1 SKY3 0 +par 180 +music D_OPENIN +titlepatch CWILV29 + +map MAP31 lookup HUSTR_31B +next MAP16 +secretnext MAP32 +warptrans 31 +sky1 SKY3 0 +par 120 +music D_EVIL +titlepatch CWILV30 + +map MAP32 lookup HUSTR_32B +next MAP16 +warptrans 32 +sky1 SKY3 0 +par 30 +music D_ULTIMA +titlepatch CWILV31 + +map MAP33 HUSTR_33 +next MAP03 +warptrans 33 +sky1 SKY3 0 +par 120 +music D_READ_M +titlepatch CWILV32 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-nerve.mapinfo doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-nerve.mapinfo --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-nerve.mapinfo 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-nerve.mapinfo 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,77 @@ +; Episode 1 ------------------------------------------------------------ + +episode MAP01 +name "No Rest for the Living" +key n + +map MAP01 lookup HUSTR_1 +next MAP02 +warptrans 1 +sky1 SKY1 0 +par 75 +music D_MESSAG +titlepatch CWILV00 + +map MAP02 lookup HUSTR_2 +next MAP03 +warptrans 2 +sky1 SKY1 0 +par 105 +music D_DDTBLU +titlepatch CWILV01 + +map MAP03 lookup HUSTR_3 +next MAP04 +warptrans 3 +sky1 SKY1 0 +par 120 +music D_DOOM +titlepatch CWILV02 + +map MAP04 lookup HUSTR_4 +next MAP05 +secretnext MAP09 +warptrans 4 +sky1 SKY1 0 +par 105 +music D_SHAWN +titlepatch CWILV03 + +map MAP05 lookup HUSTR_5 +next MAP06 +warptrans 5 +sky1 SKY1 0 +par 210 +music D_IN_CIT +titlepatch CWILV04 + +map MAP06 lookup HUSTR_6 +next MAP07 +warptrans 6 +sky1 SKY1 0 +par 105 +music D_THE_DA +titlepatch CWILV05 + +map MAP07 lookup HUSTR_7 +next MAP08 +warptrans 7 +sky1 SKY1 0 +par 165 +music D_IN_CIT +titlepatch CWILV06 + +map MAP08 lookup HUSTR_8 +warptrans 8 +sky1 SKY1 0 +par 105 +music D_SHAWN +titlepatch CWILV07 + +map MAP09 lookup HUSTR_9 +next MAP05 +warptrans 9 +sky1 SKY1 0 +par 135 +music D_DDTBLU +titlepatch CWILV08 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-tnt.mapinfo doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-tnt.mapinfo --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/data/doom2-tnt.mapinfo 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/data/doom2-tnt.mapinfo 2018-12-11 07:08:21.000000000 +0000 @@ -73,7 +73,7 @@ warptrans 9 sky1 SKY1 0 par 270 -music D_INCIT +music D_IN_CIT titlepatch CWILV08 map MAP10 lookup THUSTR_10 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/finales.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -12,23 +12,23 @@ # A better way would just be to use "text" and define the text # in the script, no need to go about modifying the Text defs. -InFine +InFine { ID = "title"; Script { # There is no skipping during the titlescreen loop. - NoSkip - + NoSkip + # Any event shows the menu. Trigger - + MARKER title_loop # Step 1. Patch back 0 0 "TITLEPIC" MusicOnce "intro" Wait 4.857 # Original wait is 170 tics. - + # Step 2. IF MODE:doom1-share PlayDemo "sdemo1.cdm" IF MODE:doom1 PlayDemo "rdemo1.cdm" @@ -37,16 +37,25 @@ # Step 3. Set back "CREDIT" Wait 5.714 # Original is 200 tics. - + # Step 4. IF MODE:doom1-share PlayDemo "sdemo2.cdm" IF MODE:doom1 PlayDemo "rdemo2.cdm" IF MODE:doom1-ultimate PlayDemo "udemo2.cdm" - + # Step 5. - IF MODE:doom1-ultimate Set back "CREDIT" ELSE Set back "HELP2" + IF MODE:doom1-ultimate DO + Set back "CREDIT" + GOTO Step5Wait + ; + IF MODE:doom1-bfg DO + Set back "CREDIT" + GOTO Step5Wait + ; + Set back "HELP2" + MARKER Step5Wait Wait 5.714 # 200 tics. - + # Step 6. IF MODE:doom1-share PlayDemo "sdemo3.cdm" IF MODE:doom1 PlayDemo "rdemo3.cdm" @@ -54,7 +63,7 @@ # Step 7. IF MODE:doom1-ultimate PlayDemo "udemo4.cdm" - + GOTO title_loop }; } @@ -81,6 +90,10 @@ Pause + IF MODE:doom1-bfg DO + Set back "CREDIT" + GOTO end + ; IF MODE:doom1-ultimate DO Set back "CREDIT" ; @@ -94,6 +107,7 @@ Set back "HELP2" ; ; + MARKER end Pause }; } @@ -110,10 +124,10 @@ TextDef msg 10 10 "E1TEXT" WaitText msg Wait 7 # The original TEXTWAIT is 250 tics. - + # Show shareware/registered or credits. NoFlat DelText msg - IF ultimate + IF ultimate Patch back 0 0 CREDIT ELSE Patch back 0 0 HELP2 @@ -179,28 +193,3 @@ sound "pistol"; set theend END6 }; } - -# The rest of this file is skipped if not DOOM - ultimate. -SkipIf Not doom1-ultimate; - -# Episode IV: Thy Flesh Consumed -Finale -{ - After = "E4M8"; - Script { - noskip # This is the end, no more levels after this. - music "victor" - flat Values:BGFLATE4 - wait 0.5 - textdef msg 10 10 "E4TEXT" - waittext msg - wait 7 # The original TEXTWAIT is 250 tics. - # Fade to the Deimos picture. - patch back 0 0 ENDPIC - alpha back 0 - in 2 alpha back 1; textalpha msg 0 - wait 2 - deltext msg - noflat - }; -} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/music.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/music.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/music.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/music.ded 2018-12-11 07:08:21.000000000 +0000 @@ -16,6 +16,7 @@ Music { ID = "e1m7"; Lump = "D_E1M7"; } Music { ID = "e1m8"; Lump = "D_E1M8"; } Music { ID = "e1m9"; Lump = "D_E1M9"; } + Music { ID = "e2m1"; Lump = "D_E2M1"; } Music { ID = "e2m2"; Lump = "D_E2M2"; } Music { ID = "e2m3"; Lump = "D_E2M3"; } @@ -25,6 +26,7 @@ Music { ID = "e2m7"; Lump = "D_E2M7"; } Music { ID = "e2m8"; Lump = "D_E2M8"; } Music { ID = "e2m9"; Lump = "D_E2M9"; } + Music { ID = "e3m1"; Lump = "D_E3M1"; } Music { ID = "e3m2"; Lump = "D_E3M2"; } Music { ID = "e3m3"; Lump = "D_E3M3"; } @@ -34,6 +36,17 @@ Music { ID = "e3m7"; Lump = "D_E3M7"; } Music { ID = "e3m8"; Lump = "D_E3M8"; } Music { ID = "e3m9"; Lump = "D_E3M9"; } + +Music { ID = "e4m1"; Lump = "D_E3M4"; } +Music { ID = "e4m2"; Lump = "D_E3M2"; } +Music { ID = "e4m3"; Lump = "D_E3M3"; } +Music { ID = "e4m4"; Lump = "D_E1M5"; } +Music { ID = "e4m5"; Lump = "D_E2M7"; } +Music { ID = "e4m6"; Lump = "D_E2M4"; } +Music { ID = "e4m7"; Lump = "D_E2M6"; } +Music { ID = "e4m8"; Lump = "D_E2M5"; } +Music { ID = "e4m9"; Lump = "D_E1M9"; } + Music { ID = "inter"; Lump = "D_INTER"; } Music { ID = "intro"; Lump = "D_INTRO"; } Music { ID = "bunny"; Lump = "D_BUNNY"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/patchmapinfo.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/patchmapinfo.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1/patchmapinfo.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1/patchmapinfo.ded 2018-12-11 07:08:21.000000000 +0000 @@ -5,57 +5,57 @@ Header { Version = 6; } # -# Music and Sky mods: doom1, doom1-ultimate, doom1-share +# Sky mods: doom1, doom1-ultimate, doom1-share # -Map Info mods "E1M1" if not custom { Music = "e1m1"; Sky = "sky1"; } -Map Info mods "E1M2" if not custom { Music = "e1m2"; Sky = "sky1"; } -Map Info mods "E1M3" if not custom { Music = "e1m3"; Sky = "sky1"; } -Map Info mods "E1M4" if not custom { Music = "e1m4"; Sky = "sky1"; } -Map Info mods "E1M5" if not custom { Music = "e1m5"; Sky = "sky1"; } +Map Info mods "E1M1" if not custom { Sky = "sky1"; } +Map Info mods "E1M2" if not custom { Sky = "sky1"; } +Map Info mods "E1M3" if not custom { Sky = "sky1"; } +Map Info mods "E1M4" if not custom { Sky = "sky1"; } +Map Info mods "E1M5" if not custom { Sky = "sky1"; } # The rest of this file is skipped if Chex SkipIf chex; -Map Info mods "E1M6" if not custom { Music = "e1m6"; Sky = "sky1"; } -Map Info mods "E1M7" if not custom { Music = "e1m7"; Sky = "sky1"; } -Map Info mods "E1M8" if not custom { Music = "e1m8"; Sky = "sky1"; } -Map Info mods "E1M9" if not custom { Music = "e1m9"; Sky = "sky1"; } +Map Info mods "E1M6" if not custom { Sky = "sky1"; } +Map Info mods "E1M7" if not custom { Sky = "sky1"; } +Map Info mods "E1M8" if not custom { Sky = "sky1"; } +Map Info mods "E1M9" if not custom { Sky = "sky1"; } # The rest of this file is skipped if DOOM1 Shareware SkipIf doom1-share; # Episode 2: -Map Info mods "E2M1" if not custom { Music = "e2m1"; Sky = "sky2"; } -Map Info mods "E2M2" if not custom { Music = "e2m2"; Sky = "sky2"; } -Map Info mods "E2M3" if not custom { Music = "e2m3"; Sky = "sky2"; } -Map Info mods "E2M4" if not custom { Music = "e2m4"; Sky = "sky2"; } -Map Info mods "E2M5" if not custom { Music = "e2m5"; Sky = "sky2"; } -Map Info mods "E2M6" if not custom { Music = "e2m6"; Sky = "sky2"; } -Map Info mods "E2M7" if not custom { Music = "e2m7"; Sky = "sky2"; } -Map Info mods "E2M8" if not custom { Music = "e2m8"; Sky = "sky2"; } -Map Info mods "E2M9" if not custom { Music = "e2m9"; Sky = "sky2"; } +Map Info mods "E2M1" if not custom { Sky = "sky2"; } +Map Info mods "E2M2" if not custom { Sky = "sky2"; } +Map Info mods "E2M3" if not custom { Sky = "sky2"; } +Map Info mods "E2M4" if not custom { Sky = "sky2"; } +Map Info mods "E2M5" if not custom { Sky = "sky2"; } +Map Info mods "E2M6" if not custom { Sky = "sky2"; } +Map Info mods "E2M7" if not custom { Sky = "sky2"; } +Map Info mods "E2M8" if not custom { Sky = "sky2"; } +Map Info mods "E2M9" if not custom { Sky = "sky2"; } # Episode 3: -Map Info mods "E3M1" if not custom { Music = "e3m1"; Sky = "sky3"; } -Map Info mods "E3M2" if not custom { Music = "e3m2"; Sky = "sky3"; } -Map Info mods "E3M3" if not custom { Music = "e3m3"; Sky = "sky3"; } -Map Info mods "E3M4" if not custom { Music = "e3m4"; Sky = "sky3"; } -Map Info mods "E3M5" if not custom { Music = "e3m5"; Sky = "sky3"; } -Map Info mods "E3M6" if not custom { Music = "e3m6"; Sky = "sky3"; } -Map Info mods "E3M7" if not custom { Music = "e3m7"; Sky = "sky3"; } -Map Info mods "E3M8" if not custom { Music = "e3m8"; Sky = "sky3"; } -Map Info mods "E3M9" if not custom { Music = "e3m9"; Sky = "sky3"; } +Map Info mods "E3M1" if not custom { Sky = "sky3"; } +Map Info mods "E3M2" if not custom { Sky = "sky3"; } +Map Info mods "E3M3" if not custom { Sky = "sky3"; } +Map Info mods "E3M4" if not custom { Sky = "sky3"; } +Map Info mods "E3M5" if not custom { Sky = "sky3"; } +Map Info mods "E3M6" if not custom { Sky = "sky3"; } +Map Info mods "E3M7" if not custom { Sky = "sky3"; } +Map Info mods "E3M8" if not custom { Sky = "sky3"; } +Map Info mods "E3M9" if not custom { Sky = "sky3"; } # The rest of this file is skipped if not DOOM1 Ultimate. SkipIf Not doom1-ultimate; # Episode 4: -Map Info mods "E4M1" if not custom { Music = "e3m4"; Sky = "sky4"; } -Map Info mods "E4M2" if not custom { Music = "e3m2"; Sky = "sky4"; } -Map Info mods "E4M3" if not custom { Music = "e3m3"; Sky = "sky4"; } -Map Info mods "E4M4" if not custom { Music = "e1m5"; Sky = "sky4"; } -Map Info mods "E4M5" if not custom { Music = "e2m7"; Sky = "sky4"; } -Map Info mods "E4M6" if not custom { Music = "e2m4"; Sky = "sky4"; } -Map Info mods "E4M7" if not custom { Music = "e2m6"; Sky = "sky4"; } -Map Info mods "E4M8" if not custom { Music = "e2m5"; Sky = "sky4"; } -Map Info mods "E4M9" if not custom { Music = "e1m9"; Sky = "sky4"; } +Map Info mods "E4M1" if not custom { Sky = "sky4"; } +Map Info mods "E4M2" if not custom { Sky = "sky4"; } +Map Info mods "E4M3" if not custom { Sky = "sky4"; } +Map Info mods "E4M4" if not custom { Sky = "sky4"; } +Map Info mods "E4M5" if not custom { Sky = "sky4"; } +Map Info mods "E4M6" if not custom { Sky = "sky4"; } +Map Info mods "E4M7" if not custom { Sky = "sky4"; } +Map Info mods "E4M8" if not custom { Sky = "sky4"; } +Map Info mods "E4M9" if not custom { Sky = "sky4"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-freedoom.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-freedoom.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-freedoom.ded 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-freedoom.ded 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,24 @@ +# +# DOOM (Ultimate) - Doomsday Engine definitions. +# +# For information about DED syntax and semantics, see http://dengine.net/dew/?title=DED +# + +# Include common definitions for games playable with jDoom. +Include "jdoom.ded"; + +# MAPINFO interoperability patches +Include "doom1/patchmapinfo.ded"; + +Include "doom1/anim.ded"; +Include "doom1/particles.ded"; +Include "doom1/skies.ded"; +Include "doom1/finales.ded"; +Include "doom1/fonts.ded"; +Include "doom1/lights.ded"; +Include "doom1/materials.ded"; +Include "doom1/materialenvironments.ded"; +Include "doom1/music.ded"; +Include "doom1/menu.ded"; +Include "doom1/hud.ded"; +Include "doom1/inlude.ded"; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate/finales.ded 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,21 @@ +# Episode IV: Thy Flesh Consumed +Finale +{ + After = "E4M8"; + Script { + noskip # This is the end, no more levels after this. + music "victor" + flat Values:BGFLATE4 + wait 0.5 + textdef msg 10 10 "E4TEXT" + waittext msg + wait 7 # The original TEXTWAIT is 250 tics. + # Fade to the Deimos picture. + patch back 0 0 ENDPIC + alpha back 0 + in 2 alpha back 1; textalpha msg 0 + wait 2 + deltext msg + noflat + }; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom1-ultimate.ded 2018-12-11 07:08:21.000000000 +0000 @@ -14,6 +14,7 @@ Include "doom1/particles.ded"; Include "doom1/skies.ded"; Include "doom1/finales.ded"; +Include "doom1-ultimate/finales.ded"; Include "doom1/fonts.ded"; Include "doom1/lights.ded"; Include "doom1/materials.ded"; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/finales.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -25,7 +25,16 @@ MARKER title_loop # Step 1. - Patch back 0 0 "TITLEPIC" + IF MODE:doom2-nerve DO + Patch back 0 0 "INTERPIC" + GOTO pic_set + ; + IF MODE:doom2-bfg DO + Patch back 0 0 "INTERPIC" + GOTO pic_set + ; + Patch back 0 0 "TITLEPIC" + MARKER pic_set MusicOnce "dm2ttl" Wait 13 # Original was 11; this'll play the whole song. @@ -40,8 +49,17 @@ PlayDemo "2demo2.cdm" # Step 5. + IF MODE:doom2-nerve DO + Patch back 0 0 "INTERPIC" + GOTO pic_set2 + ; + IF MODE:doom2-bfg DO + Patch back 0 0 "INTERPIC" + GOTO pic_set2 + ; Set back "TITLEPIC" - Music "dm2ttl" + MARKER pic_set2 + MusicOnce "dm2ttl" Wait 13 # Original was 11. # Step 6. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/music.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/music.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/music.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/music.ded 2018-12-11 07:08:21.000000000 +0000 @@ -42,3 +42,39 @@ Music { ID = "read_m"; Lump = "D_READ_M"; } Music { ID = "dm2ttl"; Lump = "D_DM2TTL"; } Music { ID = "dm2int"; Lump = "D_DM2INT"; } + +# Fallbacks based on map IDs: + +Music { ID = "map01"; Lump = "D_RUNNIN"; } +Music { ID = "map02"; Lump = "D_STALKS"; } +Music { ID = "map03"; Lump = "D_COUNTD"; } +Music { ID = "map04"; Lump = "D_BETWEE"; } +Music { ID = "map05"; Lump = "D_DOOM"; } +Music { ID = "map06"; Lump = "D_THE_DA"; } +Music { ID = "map07"; Lump = "D_SHAWN"; } +Music { ID = "map08"; Lump = "D_DDTBLU"; } +Music { ID = "map09"; Lump = "D_IN_CIT"; } +Music { ID = "map10"; Lump = "D_DEAD"; } +Music { ID = "map11"; Lump = "D_STLKS2"; } +Music { ID = "map12"; Lump = "D_THEDA2"; } +Music { ID = "map13"; Lump = "D_DOOM2"; } +Music { ID = "map14"; Lump = "D_DDTBL2"; } +Music { ID = "map15"; Lump = "D_RUNNI2"; } +Music { ID = "map16"; Lump = "D_DEAD2"; } +Music { ID = "map17"; Lump = "D_STLKS3"; } +Music { ID = "map18"; Lump = "D_ROMERO"; } +Music { ID = "map19"; Lump = "D_SHAWN2"; } +Music { ID = "map20"; Lump = "D_MESSAG"; } +Music { ID = "map21"; Lump = "D_COUNT2"; } +Music { ID = "map22"; Lump = "D_DDTBL3"; } +Music { ID = "map23"; Lump = "D_AMPIE"; } +Music { ID = "map24"; Lump = "D_THEDA3"; } +Music { ID = "map25"; Lump = "D_ADRIAN"; } +Music { ID = "map26"; Lump = "D_MESSG2"; } +Music { ID = "map27"; Lump = "D_ROMER2"; } +Music { ID = "map28"; Lump = "D_TENSE"; } +Music { ID = "map29"; Lump = "D_SHAWN3"; } +Music { ID = "map30"; Lump = "D_OPENIN"; } +Music { ID = "map31"; Lump = "D_EVIL"; } +Music { ID = "map32"; Lump = "D_ULTIMA"; } +Music { ID = "map33"; Lump = "D_READ_M"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/patchmapinfo.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/patchmapinfo.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2/patchmapinfo.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2/patchmapinfo.ded 2018-12-11 07:08:21.000000000 +0000 @@ -5,47 +5,47 @@ Header { Version = 6; } # -# Music & Sky mods: doom2, doom2-plut, doom2-tnt, hacx +# Sky mods: doom2, doom2-plut, doom2-tnt, hacx # -Map Info mods "MAP01" if not custom { Music = "runnin"; Sky = "sky1"; } -Map Info mods "MAP02" if not custom { Music = "stalks"; Sky = "sky1"; } -Map Info mods "MAP03" if not custom { Music = "countd"; Sky = "sky1"; } -Map Info mods "MAP04" if not custom { Music = "betwee"; Sky = "sky1"; } -Map Info mods "MAP05" if not custom { Music = "doom"; Sky = "sky1"; } -Map Info mods "MAP06" if not custom { Music = "the_da"; Sky = "sky1"; } -Map Info mods "MAP07" if not custom { Music = "shawn"; Sky = "sky1"; } -Map Info mods "MAP08" if not custom { Music = "ddtblu"; Sky = "sky1"; } -Map Info mods "MAP09" if not custom { Music = "in_cit"; Sky = "sky1"; } -Map Info mods "MAP10" if not custom { Music = "dead"; Sky = "sky1"; } -Map Info mods "MAP11" if not custom { Music = "stlks2"; Sky = "sky1"; } +Map Info mods "MAP01" if not custom { Sky = "sky1"; } +Map Info mods "MAP02" if not custom { Sky = "sky1"; } +Map Info mods "MAP03" if not custom { Sky = "sky1"; } +Map Info mods "MAP04" if not custom { Sky = "sky1"; } +Map Info mods "MAP05" if not custom { Sky = "sky1"; } +Map Info mods "MAP06" if not custom { Sky = "sky1"; } +Map Info mods "MAP07" if not custom { Sky = "sky1"; } +Map Info mods "MAP08" if not custom { Sky = "sky1"; } +Map Info mods "MAP09" if not custom { Sky = "sky1"; } +Map Info mods "MAP10" if not custom { Sky = "sky1"; } +Map Info mods "MAP11" if not custom { Sky = "sky1"; } # From MAP12 onwards, the sky changes to 'sky2' -Map Info mods "MAP12" if not custom { Music = "theda2"; Sky = "sky2"; } -Map Info mods "MAP13" if not custom { Music = "doom2"; Sky = "sky2"; } -Map Info mods "MAP14" if not custom { Music = "ddtbl2"; Sky = "sky2"; } -Map Info mods "MAP15" if not custom { Music = "runni2"; Sky = "sky2"; } -Map Info mods "MAP16" if not custom { Music = "dead2"; Sky = "sky2"; } -Map Info mods "MAP17" if not custom { Music = "stlks3"; Sky = "sky2"; } -Map Info mods "MAP18" if not custom { Music = "romero"; Sky = "sky2"; } -Map Info mods "MAP19" if not custom { Music = "shawn2"; Sky = "sky2"; } -Map Info mods "MAP20" if not custom { Music = "messag"; Sky = "sky2"; } +Map Info mods "MAP12" if not custom { Sky = "sky2"; } +Map Info mods "MAP13" if not custom { Sky = "sky2"; } +Map Info mods "MAP14" if not custom { Sky = "sky2"; } +Map Info mods "MAP15" if not custom { Sky = "sky2"; } +Map Info mods "MAP16" if not custom { Sky = "sky2"; } +Map Info mods "MAP17" if not custom { Sky = "sky2"; } +Map Info mods "MAP18" if not custom { Sky = "sky2"; } +Map Info mods "MAP19" if not custom { Sky = "sky2"; } +Map Info mods "MAP20" if not custom { Sky = "sky2"; } # From MAP21 onwards, the sky changes to 'sky3' -Map Info mods "MAP21" if not custom { Music = "count2"; Sky = "sky3"; } +Map Info mods "MAP21" if not custom { Sky = "sky3"; } -Map Info mods "MAP31" if not custom { Music = "evil"; Sky = "sky3"; } +Map Info mods "MAP31" if not custom { Sky = "sky3"; } # The rest of this file is skipped if HacX SkipIf hacx; -Map Info mods "MAP22" if not custom { Music = "ddtbl3"; Sky = "sky3"; } -Map Info mods "MAP23" if not custom { Music = "ampie"; Sky = "sky3"; } -Map Info mods "MAP24" if not custom { Music = "theda3"; Sky = "sky3"; } -Map Info mods "MAP25" if not custom { Music = "adrian"; Sky = "sky3"; } -Map Info mods "MAP26" if not custom { Music = "messg2"; Sky = "sky3"; } -Map Info mods "MAP27" if not custom { Music = "romer2"; Sky = "sky3"; } -Map Info mods "MAP28" if not custom { Music = "tense"; Sky = "sky3"; } -Map Info mods "MAP29" if not custom { Music = "shawn3"; Sky = "sky3"; } -Map Info mods "MAP30" if not custom { Music = "openin"; Sky = "sky3"; } +Map Info mods "MAP22" if not custom { Sky = "sky3"; } +Map Info mods "MAP23" if not custom { Sky = "sky3"; } +Map Info mods "MAP24" if not custom { Sky = "sky3"; } +Map Info mods "MAP25" if not custom { Sky = "sky3"; } +Map Info mods "MAP26" if not custom { Sky = "sky3"; } +Map Info mods "MAP27" if not custom { Sky = "sky3"; } +Map Info mods "MAP28" if not custom { Sky = "sky3"; } +Map Info mods "MAP29" if not custom { Sky = "sky3"; } +Map Info mods "MAP30" if not custom { Sky = "sky3"; } -Map Info mods "MAP32" if not custom { Music = "ultima"; Sky = "sky3"; } +Map Info mods "MAP32" if not custom { Sky = "sky3"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2.ded 2018-12-11 07:08:21.000000000 +0000 @@ -1,19 +1,21 @@ # # DOOM2 - Doomsday Engine definitions. # -# For information about DED syntax and semantics, see http://dengine.net/dew/?title=DED +# For information about DED syntax and semantics, see http://dengine.net/manual/ded # -# Include common definitions for games playable with jDoom. +# Include common definitions for games playable with the Doom plugin. Include "jdoom.ded"; # MAPINFO interoperability patches -Include "doom2/patchmapinfo.ded"; +IncludeIf Not doom2-nerve "doom2/patchmapinfo.ded"; +IncludeIf doom2-nerve "doom2-nerve/patchmapinfo.ded"; Include "doom1/anim.ded"; Include "doom2/anim.ded"; Include "doom2/skies.ded"; Include "doom2/finales.ded"; +IncludeIf doom2-nerve "doom2-nerve/finales.ded"; Include "doom1/fonts.ded"; Include "doom1/materials.ded"; Include "doom1/materialenvironments.ded"; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/finales.ded 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,266 @@ +Finale +{ + After = "MAP08"; + Script { + music "read_m" + flat Values:BGFLAT30 + wait 0.5 + text msg 10 10 "trouble was brewing again in your favorite\n + vacation spot... hell. some cyberdemon\n + punk thought he could turn hell into a\n + personal amusement park, and make earth\n + the ticket booth.\n\n + well that half-robot freak show didn't\n + know who was coming to the fair. there's\n + nothing like a shooting gallery full of\n + hellspawn to get the blood pumping...\n\n + now the walls of the demon's labyrinth\n + echo with the sound of his metallic limbs\n + hitting the floor. his death moan gurgles\n + out through the mess you left of his face.\n\n + this ride is closed." + waittext msg; wait 7 + skiphere + + #####====--- The Cast ---====##### + # Castloop continues forever. + # Quite a number of monsters here...! + noskip # No more skipping (pause waits for a key, though). + deltext msg + music "evil" + noflat; patch back 0 0 BOSSBACK + marker castloop + # Create a text for the name. + textdef name 160 180 CC_ZOMBIE + center name; rate name 0 + patch mo 160 170 POSSA1 # "mo" is used for all the monsters. + + # --- Zombieman --- + clranim mo + states mo POSS_RUN1 12 + states mo POSS_ATK1 2; picsound mo "pistol" + states mo POSS_ATK3 1 + repeat mo + seesound POSSESSED; pause; diesound POSSESSED + clranim mo + states mo POSS_DIE1 5 + waitanim mo; wait 0.43 + + # --- Shotgun Guy --- + clranim mo + states mo SPOS_RUN1 12 + states mo SPOS_ATK1 2; picsound mo "shotgn" + states mo SPOS_ATK3 1 + repeat mo + settextdef name CC_SHOTGUN + seesound SHOTGUY; pause; diesound SHOTGUY + clranim mo + states mo SPOS_DIE1 5 + waitanim mo; wait 0.43 + + # --- Heavy Weapon Dude --- + clranim mo + states mo CPOS_RUN1 12 + states mo CPOS_ATK1 2; picsound mo "shotgn" + states mo CPOS_ATK3 1; picsound mo "shotgn" + states mo CPOS_ATK4 1; picsound mo "shotgn" + states mo CPOS_ATK3 1; picsound mo "shotgn" + states mo CPOS_ATK4 1; picsound mo "shotgn" + states mo CPOS_ATK3 1; picsound mo "shotgn" + repeat mo + settextdef name CC_HEAVY + seesound CHAINGUY; pause; diesound CHAINGUY + clranim mo + states mo CPOS_DIE1 7 + waitanim mo; wait 0.43 + + # --- Imp --- + clranim mo + states mo TROO_RUN1 12 + states mo TROO_ATK1 3; picsound mo "claw" + repeat mo + settextdef name CC_IMP + seesound TROOP; pause; diesound TROOP + clranim mo + states mo TROO_DIE1 5 + waitanim mo; wait 0.43 + + # --- Demon --- + clranim mo + states mo SARG_RUN1 12 + states mo SARG_ATK1 2; picsound mo "sgtatk" + states mo SARG_ATK3 1 + repeat mo + settextdef name CC_DEMON + seesound SERGEANT; pause; diesound SERGEANT + clranim mo + states mo SARG_DIE1 6 + waitanim mo; wait 0.43 + + # --- Lost Soul --- + clranim mo + states mo SKULL_RUN1 12 + states mo SKULL_ATK1 2; picsound mo "sklatk" + states mo SKULL_ATK3 8 + repeat mo + settextdef name CC_LOST + seesound SKULL; pause; diesound SKULL + clranim mo + states mo SKULL_DIE1 6 + waitanim mo; wait 0.43 + + # --- Cacodemon --- + clranim mo + states mo HEAD_RUN1 12 + states mo HEAD_ATK1 2; picsound mo "firsht" + states mo HEAD_ATK3 1 + repeat mo + settextdef name CC_CACO + seesound HEAD; pause; diesound HEAD + clranim mo + states mo HEAD_DIE1 6 + waitanim mo; wait 0.43 + + # --- Hell Knight --- + clranim mo + states mo BOS2_RUN1 12 + states mo BOS2_ATK1 2; picsound mo "firsht" + states mo BOS2_ATK3 1 + repeat mo + settextdef name CC_HELL + seesound KNIGHT; pause; diesound KNIGHT + clranim mo + states mo BOS2_DIE1 7 + waitanim mo; wait 0.43 + + # --- Baron of Hell --- + clranim mo + states mo BOSS_RUN1 12 + states mo BOSS_ATK1 2; picsound mo "firsht" + states mo BOSS_ATK3 1 + repeat mo + settextdef name CC_BARON + seesound BRUISER; pause; diesound BRUISER + clranim mo + states mo BOSS_DIE1 7 + waitanim mo; wait 0.43 + + # --- Arachnotron --- + clranim mo + states mo BSPI_SIGHT 12 + states mo BSPI_ATK1 2; picsound mo "plasma" + states mo BSPI_ATK3 3; picsound mo "plasma" + states mo BSPI_ATK3 3; picsound mo "plasma" + states mo BSPI_ATK3 3; picsound mo "plasma" + states mo BSPI_ATK3 2 + repeat mo + settextdef name CC_ARACH + seesound BABY; pause; diesound BABY + clranim mo + states mo BSPI_DIE1 7 + waitanim mo; wait 0.43 + + # --- Pain Elemental --- + clranim mo + states mo PAIN_RUN1 12 + states mo PAIN_ATK1 3; picsound mo "sklatk" + states mo PAIN_ATK4 1 + repeat mo + settextdef name CC_PAIN + seesound PAIN; pause; diesound PAIN + clranim mo + states mo PAIN_DIE1 6 + waitanim mo; wait 0.43 + + # --- Revenant --- + clranim mo + states mo SKEL_RUN1 12 + states mo SKEL_MISS1 2; picsound mo "skeatk" + states mo SKEL_MISS3 2 + states mo SKEL_RUN1 12 + states mo SKEL_FIST1 2; picsound mo "skeswg" + states mo SKEL_FIST3 2; picsound mo "skepch" + repeat mo + settextdef name CC_REVEN + seesound UNDEAD; pause; diesound UNDEAD + clranim mo + states mo SKEL_DIE1 6 + waitanim mo; wait 0.43 + + # --- Mancubus --- + clranim mo + states mo FATT_RUN1 12 + states mo FATT_ATK1 2; picsound mo "firsht" + states mo FATT_ATK3 3; picsound mo "firsht" + states mo FATT_ATK6 3; picsound mo "firsht" + states mo FATT_ATK9 2 + repeat mo + settextdef name CC_MANCU + seesound FATSO; pause; diesound FATSO + clranim mo + states mo FATT_DIE1 10 + waitanim mo; wait 0.43 + + # --- Arch-Vile --- + clranim mo + states mo VILE_RUN1 12 + states mo VILE_ATK1 2; picsound mo "vilatk" + states mo VILE_ATK3 9 + repeat mo + settextdef name CC_ARCH + seesound VILE; pause; diesound VILE + clranim mo + states mo VILE_DIE1 10 + waitanim mo; wait 0.43 + + # --- The Spider Mastermind --- + clranim mo + states mo SPID_RUN1 12 + states mo SPID_ATK1 2; picsound mo "shotgn" + states mo SPID_ATK3 1; picsound mo "shotgn" + states mo SPID_ATK4 2; picsound mo "shotgn" + states mo SPID_ATK3 1; picsound mo "shotgn" + states mo SPID_ATK4 2; picsound mo "shotgn" + states mo SPID_ATK3 1; picsound mo "shotgn" + states mo SPID_ATK4 2; picsound mo "shotgn" + states mo SPID_ATK3 1; picsound mo "shotgn" + repeat mo + settextdef name CC_SPIDER + seesound SPIDER; pause; diesound SPIDER + clranim mo + states mo SPID_DIE1 11 + waitanim mo; wait 0.43 + + # --- Cyberdemon --- + clranim mo + states mo CYBER_RUN1 12 + states mo CYBER_ATK1 2; picsound mo "rlaunc" + states mo CYBER_ATK3 2; picsound mo "rlaunc" + states mo CYBER_ATK5 2; picsound mo "rlaunc" + repeat mo + settextdef name CC_CYBER + seesound CYBORG; pause; diesound CYBORG + clranim mo + states mo CYBER_DIE1 10 + waitanim mo; wait 0.43 + + # --- Our Hero (finally!) --- + clranim mo + states mo PLAY_RUN1 12 + states mo PLAY_ATK1 1 + repeat mo + settextdef name CC_HERO + seesound PLAYER; pause; diesound PLAYER + clranim mo + states mo PLAY_DIE1 7 + waitanim mo; wait 0.43 + + # Restart the loop. + goto castloop + }; +} + +Finale +{ + Before = "MAP07"; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/patchmapinfo.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/patchmapinfo.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/patchmapinfo.ded 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-nerve/patchmapinfo.ded 2018-12-11 07:08:21.000000000 +0000 @@ -0,0 +1,42 @@ +# +# DOOM2 - No Rest for the Living - Doomsday Engine definitions. +# +# For information about DED syntax and semantics, see http://dengine.net/manual/ded +# + +Map Info Mods "MAP01" if not custom { + Name = "The Earth Base" + Author = "Nerve Software" +} +Map Info Mods "MAP02" if not custom { + Name = "The Pain Labs" + Author = "Nerve Software" +} +Map Info Mods "MAP03" if not custom { + Name = "Canyon of the Dead" + Author = "Nerve Software" +} +Map Info Mods "MAP04" if not custom { + Name = "Hell Mountain" + Author = "Nerve Software" +} +Map Info Mods "MAP05" if not custom { + Name = "Vivisection" + Author = "Nerve Software" +} +Map Info Mods "MAP06" if not custom { + Name = "Inferno of Blood" + Author = "Nerve Software" +} +Map Info Mods "MAP07" if not custom { + Name = "Baron's Banquet" + Author = "Nerve Software" +} +Map Info Mods "MAP08" if not custom { + Name = "Tomb of Malevolence" + Author = "Nerve Software" +} +Map Info Mods "MAP09" if not custom { + Name = "March of the Demons" + Author = "Nerve Software" +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-plut/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-plut/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-plut/finales.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-plut/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -41,7 +41,7 @@ # Step 5. Set back "TITLEPIC" - Music "dm2ttl" + MusicOnce "dm2ttl" Wait 13 # Original was 11. # Step 6. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-tnt/finales.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-tnt/finales.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/doom2-tnt/finales.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/doom2-tnt/finales.ded 2018-12-11 07:08:21.000000000 +0000 @@ -41,7 +41,7 @@ # Step 5. Set back "TITLEPIC" - Music "dm2ttl" + MusicOnce "dm2ttl" Wait 13 # Original was 11. # Step 6. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/text.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/text.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/defs/text.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/defs/text.ded 2018-12-11 07:08:22.000000000 +0000 @@ -2032,3 +2032,18 @@ ID = "REBORNLOAD_CONFIRM"; Text = "Load save game\n\n'%s'?"; } + +Text { + ID = "HUSTR_31B"; + Text = "Map 31: IDKFA"; +} + +Text { + ID = "HUSTR_32B"; + Text = "Map 32: Keen"; +} + +Text { + ID = "HUSTR_33"; + Text = "Map 33: Betray"; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_api.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_api.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_api.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_api.h 2018-12-11 07:08:22.000000000 +0000 @@ -39,8 +39,6 @@ extern "C" { #endif -extern game_export_t gx; - DENG_USING_API(Base); DENG_USING_API(B); DENG_USING_API(Busy); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_main.h 2018-12-11 07:08:22.000000000 +0000 @@ -27,8 +27,6 @@ #include "doomdef.h" -DENG_EXTERN_C float turboMul; // Multiplier for turbo. - DENG_EXTERN_C gamemode_t gameMode; DENG_EXTERN_C int gameModeBits; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/doomdef.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/doomdef.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/doomdef.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/doomdef.h 2018-12-11 07:08:22.000000000 +0000 @@ -54,8 +54,6 @@ #define Set DD_SetInteger #define Get DD_GetInteger -DENG_EXTERN_C game_export_t gx; - // // Global parameters/defines. // @@ -76,6 +74,9 @@ doom2_freedm, doom2_freedoom, doom_freedoom, + doom_bfg, + doom2_bfg, + doom2_nerve, NUM_GAME_MODES } gamemode_t; @@ -91,9 +92,12 @@ #define GM_DOOM2_FREEDM 0x100 #define GM_DOOM2_FREEDOOM 0x200 #define GM_DOOM_FREEDOOM 0x400 +#define GM_DOOM_BFG 0x800 +#define GM_DOOM2_BFG 0x1000 +#define GM_DOOM2_NERVE 0x2000 -#define GM_ANY_DOOM (GM_DOOM|GM_DOOM_SHAREWARE|GM_DOOM_ULTIMATE|GM_DOOM_CHEX) -#define GM_ANY_DOOM2 (GM_DOOM2|GM_DOOM2_PLUT|GM_DOOM2_TNT|GM_DOOM2_HACX|GM_DOOM2_FREEDM) +#define GM_ANY_DOOM (GM_DOOM|GM_DOOM_BFG|GM_DOOM_SHAREWARE|GM_DOOM_ULTIMATE|GM_DOOM_CHEX|GM_DOOM_FREEDOOM) +#define GM_ANY_DOOM2 (GM_DOOM2|GM_DOOM2_BFG|GM_DOOM2_PLUT|GM_DOOM2_TNT|GM_DOOM2_NERVE|GM_DOOM2_HACX|GM_DOOM2_FREEDM|GM_DOOM2_FREEDOOM) #define GM_ANY (GM_ANY_DOOM|GM_ANY_DOOM2) #define SCREENWIDTH 320 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_refresh.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_refresh.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/d_refresh.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/d_refresh.h 2018-12-11 07:08:22.000000000 +0000 @@ -34,16 +34,6 @@ void G_RendPlayerView(int player); -void G_InitSpecialFilter(void); - -/** - * Draws a special filter over the screen (e.g. the inversing filter used - * when in god mode). - */ -void G_UpdateSpecialFilter(int player); - -void G_UpdateSpecialFilterWithTimeDelta(int player, float delta); - void D_DrawWindow(Size2Raw const *windowSize); void D_EndFrame(void); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/p_local.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/p_local.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/p_local.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/p_local.h 2018-12-11 07:08:22.000000000 +0000 @@ -77,7 +77,6 @@ #define sentient(mobj) ((mobj)->health > 0 && P_GetState((mobj)->type, SN_SEE)) -DENG_EXTERN_C float turboMul; DENG_EXTERN_C int maxAmmo[NUM_AMMO_TYPES]; DENG_EXTERN_C int clipAmmo[NUM_AMMO_TYPES]; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/include/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/include/version.h 2018-12-11 07:08:22.000000000 +0000 @@ -64,6 +64,6 @@ // For WIN32 version info: #define PLUGIN_DESC PLUGIN_NICENAME " " LIBDENG_PLUGINDESC -#define PLUGIN_COPYRIGHT "2000-2013, " DENGPROJECT_NICEAUTHOR +#define PLUGIN_COPYRIGHT "2000-2018, " DENGPROJECT_NICEAUTHOR #endif /* JDOOM_VERSION_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/bossbrain.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/bossbrain.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/bossbrain.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/bossbrain.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -148,7 +148,7 @@ return 0; d->easy ^= 1; - if(COMMON_GAMESESSION->rules().skill <= SM_EASY && (!d->easy)) + if(gfw_Rule(skill) <= SM_EASY && (!d->easy)) return 0; mobj_t *targ = d->targets[d->targetOn++]; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_api.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_api.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_api.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_api.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -53,9 +53,6 @@ using namespace de; -// The interface to the Doomsday engine. -game_export_t gx; - // Identifiers given to the games we register during startup. static char const *gameIds[NUM_GAME_MODES] = { @@ -69,7 +66,10 @@ "hacx", "doom2-freedm", "doom2-freedoom", - "doom-freedoom", + "doom1-freedoom", + "doom1-bfg", + "doom2-bfg", + "doom2-nerve", }; #define STARTUPPK3 "libdoom.pk3" @@ -79,170 +79,253 @@ static void setCommonParameters(Game &game) { game.addRequiredPackage("net.dengine.legacy.doom_2"); + + Record gameplayOptions; + gameplayOptions.set("fast", Record::withMembers("label", "Fast Monsters/Missiles", "type", "boolean", "default", false)); + gameplayOptions.set("respawn", Record::withMembers("label", "Respawn Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("noMonsters", Record::withMembers("label", "No Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("turbo", Record::withMembers("label", "Move Speed", "type", "number", "default", 1.0, "min", 0.1, "max", 4.0, "step", 0.1)); + game.objectNamespace().set(Game::DEF_OPTIONS, gameplayOptions); } /** * Register the game modes supported by this plugin. */ -int G_RegisterGames(int hookType, int param, void *data) +static int G_RegisterGames(int hookType, int param, void *data) { - DENG_UNUSED(hookType); DENG_UNUSED(param); DENG_UNUSED(data); + DENG2_UNUSED3(hookType, param, data); Games &games = DoomsdayApp::games(); /* HacX */ - Game &hacx = games.defineGame(gameIds[doom2_hacx], - Record::withMembers(Game::DEF_CONFIG_DIR, "hacx", - Game::DEF_TITLE, "HACX - Twitch 'n Kill", - Game::DEF_AUTHOR, "Banjo Software", - Game::DEF_RELEASE_DATE, "1997-09-01", - Game::DEF_FAMILY, "", - Game::DEF_TAGS, "hacx", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/hacx.mapinfo")); - hacx.addRequiredPackage("banjo.hacx"); - setCommonParameters(hacx); - //hacx.addResource(RC_PACKAGE, FF_STARTUP, "hacx.wad", "HACX-R;PLAYPAL"); - hacx.addResource(RC_DEFINITION, 0, "hacx.ded", 0); + { + Game &hacx = games.defineGame(gameIds[doom2_hacx], + Record::withMembers(Game::DEF_CONFIG_DIR, "hacx", + Game::DEF_TITLE, "HACX - Twitch 'n Kill", + Game::DEF_AUTHOR, "Banjo Software", + Game::DEF_RELEASE_DATE, "1997-09-01", + Game::DEF_FAMILY, "", + Game::DEF_TAGS, "hacx", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/hacx.mapinfo")); + hacx.addRequiredPackage("banjo.hacx"); + setCommonParameters(hacx); + hacx.addResource(RC_DEFINITION, 0, "hacx.ded", 0); + } /* Chex Quest */ - Game &chex = games.defineGame(gameIds[doom_chex], - Record::withMembers(Game::DEF_CONFIG_DIR, "chex", - Game::DEF_TITLE, "Chex(R) Quest", - Game::DEF_AUTHOR, "Digital Cafe", - Game::DEF_RELEASE_DATE, "1996-01-01", - Game::DEF_FAMILY, "", - Game::DEF_TAGS, "chex chexquest", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/chex.mapinfo")); - chex.addRequiredPackage("digitalcafe.chexquest"); - setCommonParameters(chex); - //chex.addResource(RC_PACKAGE, FF_STARTUP, "chex.wad", "E1M1;E4M1;_DEUTEX_;POSSH0M0"); - chex.addResource(RC_DEFINITION, 0, "chex.ded", 0); + { + Game &chex = games.defineGame(gameIds[doom_chex], + Record::withMembers(Game::DEF_CONFIG_DIR, "chex", + Game::DEF_TITLE, "Chex(R) Quest", + Game::DEF_AUTHOR, "Digital Cafe", + Game::DEF_RELEASE_DATE, "1996-01-01", + Game::DEF_FAMILY, "", + Game::DEF_TAGS, "chex chexquest", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/chex.mapinfo")); + chex.addRequiredPackage("digitalcafe.chexquest"); + setCommonParameters(chex); + chex.addResource(RC_DEFINITION, 0, "chex.ded", 0); + } /* DOOM2 (TNT) */ - Game &tnt = games.defineGame(gameIds[doom2_tnt], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "Final DOOM: TNT: Evilution", - Game::DEF_AUTHOR, "Team TNT", - Game::DEF_RELEASE_DATE, "1996-06-17", - Game::DEF_TAGS, "finaldoom tnt evilution", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-tnt.mapinfo")); - tnt.addRequiredPackage("com.idsoftware.finaldoom.tnt"); - setCommonParameters(tnt); - //tnt.addResource(RC_PACKAGE, FF_STARTUP, "tnt.wad", "CAVERN5;CAVERN7;STONEW1"); - tnt.addResource(RC_DEFINITION, 0, "doom2-tnt.ded", 0); + { + Game &tnt = games.defineGame(gameIds[doom2_tnt], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Final DOOM: TNT: Evilution", + Game::DEF_AUTHOR, "Team TNT", + Game::DEF_RELEASE_DATE, "1996-06-17", + Game::DEF_TAGS, "finaldoom tnt evilution", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-tnt.mapinfo")); + tnt.addRequiredPackage("com.idsoftware.finaldoom.tnt"); + setCommonParameters(tnt); + tnt.addResource(RC_DEFINITION, 0, "doom2-tnt.ded", 0); + } /* DOOM2 (Plutonia) */ - Game &plut = games.defineGame(gameIds[doom2_plut], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "Final DOOM: The Plutonia Experiment", - Game::DEF_AUTHOR, "Dario Casali and Milo Casali", - Game::DEF_RELEASE_DATE, "1996-06-17", - Game::DEF_TAGS, "finaldoom plutonia", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-plut.mapinfo")); - plut.addRequiredPackage("com.idsoftware.finaldoom.plutonia"); - setCommonParameters(plut); - //plut.addResource(RC_PACKAGE, FF_STARTUP, "plutonia.wad", "_DEUTEX_;MAP01;MAP25;MC5;MC11;MC16;MC20"); - plut.addResource(RC_DEFINITION, 0, "doom2-plut.ded", 0); + { + Game &plut = games.defineGame(gameIds[doom2_plut], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Final DOOM: The Plutonia Experiment", + Game::DEF_AUTHOR, "Dario Casali and Milo Casali", + Game::DEF_RELEASE_DATE, "1996-06-17", + Game::DEF_TAGS, "finaldoom plutonia", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-plut.mapinfo")); + plut.addRequiredPackage("com.idsoftware.finaldoom.plutonia"); + setCommonParameters(plut); + plut.addResource(RC_DEFINITION, 0, "doom2-plut.ded", 0); + } /* DOOM2 - Freedoom Phase 2 */ - Game &freedoom2 = games.defineGame(gameIds[doom2_freedoom], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "Freedoom: Phase 2", - Game::DEF_AUTHOR, "Freedoom Project", - Game::DEF_RELEASE_DATE, "2009-06-18", - Game::DEF_FAMILY, "", - Game::DEF_TAGS, "freedoom", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-freedoom.mapinfo")); - freedoom2.addRequiredPackage("freedoom.phase2"); - setCommonParameters(freedoom2); - //freedm.addResource(RC_PACKAGE, FF_STARTUP, "freedm.wad", "MAP01"); - freedoom2.addResource(RC_DEFINITION, 0, "doom2-freedoom.ded", 0); + { + Game &freedoom2 = games.defineGame(gameIds[doom2_freedoom], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Freedoom: Phase 2", + Game::DEF_AUTHOR, "Freedoom Project", + Game::DEF_RELEASE_DATE, "2009-06-18", + Game::DEF_FAMILY, "", + Game::DEF_TAGS, "freedoom", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-freedoom.mapinfo")); + freedoom2.addRequiredPackage("freedoom.phase2"); + setCommonParameters(freedoom2); + freedoom2.addResource(RC_DEFINITION, 0, "doom2-freedoom.ded", 0); + } /* DOOM2 - FreeDM */ - Game &freedm = games.defineGame(gameIds[doom2_freedm], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "FreeDM", - Game::DEF_AUTHOR, "Freedoom Project", - Game::DEF_RELEASE_DATE, "2015-12-23", - Game::DEF_FAMILY, "", - Game::DEF_TAGS, "freedoom multiplayer", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-freedm.mapinfo")); - freedm.addRequiredPackage("freedoom.freedm"); - setCommonParameters(freedm); - //freedm.addResource(RC_PACKAGE, FF_STARTUP, "freedm.wad", "MAP01"); - freedm.addResource(RC_DEFINITION, 0, "doom2-freedm.ded", 0); - - /* DOOM2 */ - Game &d2 = games.defineGame(gameIds[doom2], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "DOOM 2: Hell on Earth", - Game::DEF_AUTHOR, "id Software", - Game::DEF_RELEASE_DATE, "1994-09-30", - Game::DEF_TAGS, "doom2", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2.mapinfo")); - d2.addRequiredPackage("com.idsoftware.doom2"); - setCommonParameters(d2); - //d2.addResource(RC_PACKAGE, FF_STARTUP, "doom2f.wad;doom2.wad", "MAP01;MAP02;MAP03;MAP04;MAP10;MAP20;MAP25;MAP30;VILEN1;VILEO1;VILEQ1;GRNROCK"); - d2.addResource(RC_DEFINITION, 0, "doom2.ded", 0); - - /* DOOM (Ultimate) */ - Game &ultimate = games.defineGame(gameIds[doom_ultimate], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "Ultimate DOOM", - Game::DEF_AUTHOR, "id Software", - Game::DEF_RELEASE_DATE, "1995-04-30", - Game::DEF_TAGS, "doom", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-ultimate.mapinfo")); - ultimate.addRequiredPackage("com.idsoftware.doom.ultimate"); - setCommonParameters(ultimate); - //ultimate.addResource(RC_PACKAGE, FF_STARTUP, "doomu.wad;doom.wad", "E4M1;E4M2;E4M3;E4M4;E4M5;E4M6;E4M7;E4M8;E4M9;M_EPI4"); - ultimate.addResource(RC_DEFINITION, 0, "doom1-ultimate.ded", 0); + { + Game &freedm = games.defineGame(gameIds[doom2_freedm], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "FreeDM", + Game::DEF_AUTHOR, "Freedoom Project", + Game::DEF_RELEASE_DATE, "2015-12-23", + Game::DEF_FAMILY, "", + Game::DEF_TAGS, "freedoom multiplayer", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-freedm.mapinfo")); + freedm.addRequiredPackage("freedoom.freedm"); + setCommonParameters(freedm); + freedm.addResource(RC_DEFINITION, 0, "doom2-freedm.ded", 0); + } + + /* DOOM II */ + { + Game &d2 = games.defineGame(gameIds[doom2], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "DOOM 2: Hell on Earth", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "1994-09-30", + Game::DEF_TAGS, "doom2", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2.mapinfo")); + d2.addRequiredPackage("com.idsoftware.doom2"); + setCommonParameters(d2); + d2.addResource(RC_DEFINITION, 0, "doom2.ded", 0); + } + + /* DOOM II (BFG Edition) */ + { + Game &d2Bfg = games.defineGame(gameIds[doom2_bfg], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "DOOM 2: Hell on Earth (BFG Edition)", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "2012-10-16", + Game::DEF_TAGS, "doom2 bfg", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-bfg.mapinfo")); + d2Bfg.addRequiredPackage("com.idsoftware.doom2.bfg"); + setCommonParameters(d2Bfg); + d2Bfg.addResource(RC_DEFINITION, 0, "doom2.ded", 0); + } + + /* No Rest for the Living (BFG Edition) */ + { + Game &nerve = games.defineGame(gameIds[doom2_nerve], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "No Rest for the Living", + Game::DEF_AUTHOR, "Nerve Software", + Game::DEF_RELEASE_DATE, "2012-10-16", + Game::DEF_TAGS, "doom2 bfg expansion", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom2-nerve.mapinfo")); + nerve.addRequiredPackage("com.idsoftware.doom2.bfg"); + nerve.addRequiredPackage("com.nervesoftware.norestfortheliving"); + setCommonParameters(nerve); + nerve.addResource(RC_DEFINITION, 0, "doom2.ded", 0); + } + + /* Ultimate DOOM */ + { + Game &ultimate = games.defineGame(gameIds[doom_ultimate], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Ultimate DOOM", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "1995-04-30", + Game::DEF_TAGS, "doom", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-ultimate.mapinfo")); + ultimate.addRequiredPackage("com.idsoftware.doom.ultimate"); + setCommonParameters(ultimate); + ultimate.addResource(RC_DEFINITION, 0, "doom1-ultimate.ded", 0); + } + + /* Ultimate DOOM (BFG Edition) */ + { + Game &doomBfg = games.defineGame(gameIds[doom_bfg], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Ultimate DOOM (BFG Edition)", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "2012-10-16", + Game::DEF_TAGS, "doom bfg", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-ultimate.mapinfo")); + doomBfg.addRequiredPackage("com.idsoftware.doom.bfg"); + setCommonParameters(doomBfg); + doomBfg.addResource(RC_DEFINITION, 0, "doom1-ultimate.ded", 0); + } /* DOOM */ - Game &d1 = games.defineGame(gameIds[doom], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "DOOM Registered", - Game::DEF_AUTHOR, "id Software", - Game::DEF_RELEASE_DATE, "1993-12-10", - Game::DEF_TAGS, "doom", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1.mapinfo")); - d1.addRequiredPackage("com.idsoftware.doom"); - setCommonParameters(d1); - //d1.addResource(RC_PACKAGE, FF_STARTUP, "doom.wad", "E2M1;E2M2;E2M3;E2M4;E2M5;E2M6;E2M7;E2M8;E2M9;E3M1;E3M2;E3M3;E3M4;E3M5;E3M6;E3M7;E3M8;E3M9;CYBRE1;CYBRD8;FLOOR7_2"); - d1.addResource(RC_DEFINITION, 0, "doom1.ded", 0); + { + Game &d1 = games.defineGame(gameIds[doom], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "DOOM Registered", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "1993-12-10", + Game::DEF_TAGS, "doom", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1.mapinfo")); + d1.addRequiredPackage("com.idsoftware.doom"); + setCommonParameters(d1); + d1.addResource(RC_DEFINITION, 0, "doom1.ded", 0); + } /* DOOM (Shareware) */ - Game &shareware = games.defineGame(gameIds[doom_shareware], - Record::withMembers(Game::DEF_CONFIG_DIR, "doom", - Game::DEF_TITLE, "DOOM Shareware", - Game::DEF_AUTHOR, "id Software", - Game::DEF_RELEASE_DATE, "1993-12-10", - Game::DEF_TAGS, "doom shareware", - Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, - Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, - Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-share.mapinfo")); - shareware.addRequiredPackage("com.idsoftware.doom.shareware"); - setCommonParameters(shareware); - //shareware.addResource(RC_PACKAGE, FF_STARTUP, "doom1.wad", "E1M1;E1M2;E1M3;E1M4;E1M5;E1M6;E1M7;E1M8;E1M9;D_E1M1;FLOOR4_8;FLOOR7_2"); - shareware.addResource(RC_DEFINITION, 0, "doom1-share.ded", 0); + { + Game &shareware = games.defineGame(gameIds[doom_shareware], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "DOOM Shareware", + Game::DEF_AUTHOR, "id Software", + Game::DEF_RELEASE_DATE, "1993-12-10", + Game::DEF_TAGS, "doom shareware", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-share.mapinfo")); + shareware.addRequiredPackage("com.idsoftware.doom.shareware"); + setCommonParameters(shareware); + shareware.addResource(RC_DEFINITION, 0, "doom1-share.ded", 0); + } + + /* DOOM - Freedoom Phase 1 */ + { + Game &freedoom1 = games.defineGame(gameIds[doom_freedoom], + Record::withMembers(Game::DEF_CONFIG_DIR, "doom", + Game::DEF_TITLE, "Freedoom: Phase 1", + Game::DEF_AUTHOR, "Freedoom Project", + Game::DEF_RELEASE_DATE, "2009-06-18", + Game::DEF_FAMILY, "", + Game::DEF_TAGS, "freedoom", + Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, + Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, + Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/doom1-ultimate.mapinfo")); + freedoom1.addRequiredPackage("freedoom.phase1"); + setCommonParameters(freedoom1); + freedoom1.addResource(RC_DEFINITION, 0, "doom1-freedoom.ded", 0); + } return true; #undef STARTUPPK3 @@ -251,7 +334,7 @@ /** * Called right after the game plugin is selected into use. */ -DENG_EXTERN_C void DP_Load(void) +DENG_ENTRYPOINT void DP_Load(void) { Plug_AddHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); gfw_SetCurrentGame(GFW_DOOM); @@ -260,12 +343,12 @@ /** * Called when the game plugin is freed from memory. */ -DENG_EXTERN_C void DP_Unload(void) +DENG_ENTRYPOINT void DP_Unload(void) { Plug_RemoveHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); } -DENG_EXTERN_C void G_PreInit(char const *gameId) +void G_PreInit(char const *gameId) { /// \todo Refactor me away. { size_t i; @@ -292,63 +375,37 @@ return true; } -/** - * Takes a copy of the engine's entry points and exported data. Returns - * a pointer to the structure that contains our entry points and exports. - */ -DENG_EXTERN_C game_export_t *GetGameAPI(void) +DENG_ENTRYPOINT void *GetGameAPI(char const *name) { - // Clear all of our exports. - memset(&gx, 0, sizeof(gx)); - - // Fill in the data for the exports. - gx.apiSize = sizeof(gx); - gx.PreInit = G_PreInit; - gx.PostInit = D_PostInit; - gx.Shutdown = D_Shutdown; - gx.TryShutdown = G_TryShutdown; - gx.Ticker = G_Ticker; - gx.DrawViewPort = G_DrawViewPort; - gx.DrawWindow = D_DrawWindow; - gx.FinaleResponder = FI_PrivilegedResponder; - gx.PrivilegedResponder = G_PrivilegedResponder; - gx.Responder = G_Responder; - gx.EndFrame = D_EndFrame; - gx.MobjThinker = P_MobjThinker; - gx.MobjFriction = Mobj_Friction; - gx.MobjCheckPositionXYZ = P_CheckPositionXYZ; - gx.MobjTryMoveXYZ = P_TryMoveXYZ; - gx.SectorHeightChangeNotification = P_HandleSectorHeightChange; - gx.UpdateState = G_UpdateState; - gx.GetInteger = D_GetInteger; - gx.GetVariable = D_GetVariable; - - gx.NetServerStart = D_NetServerStarted; - gx.NetServerStop = D_NetServerClose; - gx.NetConnect = D_NetConnect; - gx.NetDisconnect = D_NetDisconnect; - gx.NetPlayerEvent = D_NetPlayerEvent; - gx.NetWorldEvent = D_NetWorldEvent; - gx.HandlePacket = D_HandlePacket; - - // Data structure sizes. - gx.mobjSize = sizeof(mobj_t); - gx.polyobjSize = sizeof(Polyobj); - - gx.FinalizeMapChange = (void (*)(void const *)) P_FinalizeMapChange; - - // These really need better names. Ideas? - gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; - gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; + if (auto *ptr = Common_GetGameAPI(name)) + { + return ptr; + } - return &gx; + #define HASH_ENTRY(Name, Func) std::make_pair(QByteArray(Name), de::function_cast(Func)) + static QHash const funcs( + { + HASH_ENTRY("DrawWindow", D_DrawWindow), + HASH_ENTRY("EndFrame", D_EndFrame), + HASH_ENTRY("GetInteger", D_GetInteger), + HASH_ENTRY("GetPointer", D_GetVariable), + HASH_ENTRY("PostInit", D_PostInit), + HASH_ENTRY("PreInit", G_PreInit), + HASH_ENTRY("Shutdown", D_Shutdown), + HASH_ENTRY("TryShutdown", G_TryShutdown), + }); + #undef HASH_ENTRY + + auto found = funcs.find(name); + if (found != funcs.end()) return found.value(); + return nullptr; } /** * This function is called automatically when the plugin is loaded for the first time. * We let the engine know what we'd like to do. */ -DENG_EXTERN_C void DP_Initialize() +DENG_ENTRYPOINT void DP_Initialize() { Plug_AddHook(HOOK_STARTUP, G_RegisterGames); } @@ -357,11 +414,26 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C char const *deng_LibraryType(void) +DENG_ENTRYPOINT char const *deng_LibraryType(void) { return "deng-plugin/game"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_doom_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + DENG_SYMBOL_PTR(name, DP_Load); + DENG_SYMBOL_PTR(name, DP_Unload); + DENG_SYMBOL_PTR(name, GetGameAPI); + qWarning() << name << "not found in doom"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(B); DENG_DECLARE_API(Busy); @@ -409,3 +481,5 @@ DENG_GET_API(DE_API_THINKER, Thinker); DENG_GET_API(DE_API_URI, Uri); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_main.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -34,12 +34,11 @@ #include "m_argv.h" #include "p_map.h" #include "saveslots.h" +#include "r_common.h" using namespace de; using namespace common; -float turboMul; // Multiplier for turbo. - gamemode_t gameMode; int gameModeBits; @@ -243,7 +242,7 @@ sizeof(cfg.common.hudColor))); cfg.common.hudColor[CA] = 1; - cfg.common.hudFog = 1; + cfg.common.hudFog = 5; cfg.common.hudIconAlpha = 1; cfg.common.xhairAngle = 0; cfg.common.xhairSize = .5f; @@ -321,7 +320,7 @@ cfg.common.automapBack[2] = 0.f; cfg.common.automapOpacity = .7f; cfg.common.automapLineAlpha = .7f; - cfg.common.automapLineWidth = 1.1f; + cfg.common.automapLineWidth = 3.0f; cfg.common.automapShowDoors = true; cfg.common.automapDoorGlow = 8; cfg.common.automapHudDisplay = 2; @@ -384,8 +383,6 @@ // Do the common pre init routine; G_CommonPreInit(); - - G_InitSpecialFilter(); } void D_PostInit() @@ -410,31 +407,36 @@ } // Get skill / episode / map from parms. - ::defaultGameRules.skill = /*startSkill =*/ SM_MEDIUM; + gfw_SetDefaultRule(skill, /*startSkill =*/ SM_MEDIUM); - if(cmdLine.check("-altdeath")) + if (cmdLine.check("-altdeath")) { ::cfg.common.netDeathmatch = 2; } - else if(cmdLine.check("-deathmatch")) + else if (cmdLine.check("-deathmatch")) { ::cfg.common.netDeathmatch = 1; } - ::defaultGameRules.fast = cfg.common.defaultRuleFastMonsters; + gfw_SetDefaultRule(fast, cfg.common.defaultRuleFastMonsters); // Apply these rules. - ::defaultGameRules.noMonsters = cmdLine.check("-nomonsters")? true : false; - ::defaultGameRules.respawnMonsters = cmdLine.check("-respawn") ? true : false; - ::defaultGameRules.fast = cmdLine.check("-fast") ? true : false; + gfw_SetDefaultRule(noMonsters, + cmdLine.has("-nomonsters") || + gfw_GameProfile()->optionValue("noMonsters").isTrue()); + gfw_SetDefaultRule(respawnMonsters, + cmdLine.has("-respawn") || + gfw_GameProfile()->optionValue("respawn").isTrue()); + gfw_SetDefaultRule(fast, + cmdLine.has("-fast") || gfw_GameProfile()->optionValue("fast").isTrue()); - if(::defaultGameRules.deathmatch) + if (gfw_DefaultRule(deathmatch)) { - if(int arg = cmdLine.check("-timer", 1)) + if (int arg = cmdLine.check("-timer", 1)) { bool isNumber; int mins = cmdLine.at(arg + 1).toInt(&isNumber); - if(isNumber) + if (isNumber) { LOG_NOTE("Maps will end after %i %s") << mins << (mins == 1? "minute" : "minutes"); @@ -442,27 +444,12 @@ } } - // Change the turbo multiplier? - ::turboMul = 1.0f; - if(int arg = cmdLine.check("-turbo")) - { - int scale = 200; - if(arg + 1 < cmdLine.count() && !cmdLine.isOption(arg + 1)) - { - scale = cmdLine.at(arg + 1).toInt(); - } - scale = de::clamp(10, scale, 400); - - LOG_NOTE("Turbo scale: %i%%") << scale; - ::turboMul = scale / 100.f; - } - // Load a saved game? - if(int arg = cmdLine.check("-loadgame", 1)) + if (int arg = cmdLine.check("-loadgame", 1)) { - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(cmdLine.at(arg + 1))) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(cmdLine.at(arg + 1))) { - if(sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) + if (sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) { // No further initialization is to be done. return; @@ -471,10 +458,10 @@ } // Change the default skill mode? - if(int arg = cmdLine.check("-skill", 1)) + if (int arg = cmdLine.check("-skill", 1)) { int skillNumber = cmdLine.at(arg + 1).toInt(); - ::defaultGameRules.skill = (skillmode_t)(skillNumber > 0? skillNumber - 1 : skillNumber); + gfw_SetDefaultRule(skill, skillmode_t(skillNumber > 0? skillNumber - 1 : skillNumber)); } G_AutoStartOrBeginTitleLoop(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_refresh.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_refresh.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/d_refresh.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/d_refresh.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -37,61 +37,6 @@ float quitDarkenOpacity = 0; -static float appliedFilter[MAXPLAYERS]; - -void G_InitSpecialFilter() -{ - for(int i = 0; i < MAXPLAYERS; ++i) - { - appliedFilter[i] = -1; - } -} - -void G_UpdateSpecialFilterWithTimeDelta(int player, float delta) -{ - // In HacX a simple blue shift is used instead. - if(gameMode == doom2_hacx) return; - - player_t *plr = players + player; - - int filter = plr->powers[PT_INVULNERABILITY]; - if(!filter) - { - // Clear the filter. - if(appliedFilter[player] > 0) - { - DD_Executef(true, "postfx %i opacity 1; postfx %i none %f", player, player, delta); - appliedFilter[player] = -1; - } - return; - } - - float str = 1; // Full inversion. - if(filter < 4 * 32 && !(filter & 8)) - { - str = 0; - } - - // Activate the filter. - if(appliedFilter[player] < 0) - { - DD_Executef(true, "postfx %i monochrome.inverted %f", player, delta); - } - - // Update filter opacity. - if(!FEQUAL(appliedFilter[player], str)) - { - DD_Executef(true, "postfx %i opacity %f", player, str); - } - - appliedFilter[player] = str; -} - -void G_UpdateSpecialFilter(int player) -{ - G_UpdateSpecialFilterWithTimeDelta(player, .3f); -} - dd_bool R_ViewFilterColor(float rgba[4], int filter) { if(!rgba) return false; @@ -103,7 +48,7 @@ rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; - rgba[CA] = (COMMON_GAMESESSION->rules().deathmatch? 1.0f : cfg.common.filterStrength) * (filter+1) / (float)NUMREDPALS; + rgba[CA] = (gfw_Rule(deathmatch)? 1.0f : cfg.common.filterStrength) * (filter+1) / (float)NUMREDPALS; return true; } @@ -274,7 +219,7 @@ } // How about fullbright? - DD_SetInteger(DD_FULLBRIGHT, isFullBright); + DD_SetInteger(DD_RENDER_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/hud/widgets/weaponslotwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/hud/widgets/weaponslotwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/hud/widgets/weaponslotwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/hud/widgets/weaponslotwidget.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -128,7 +128,7 @@ float const textOpacity = (activeHud == 0? 1 : uiRendState->pageAlpha * cfg.common.statusbarCounterAlpha); //float const iconOpacity = (fullscreen == 0? 1 : uiRendState->pageAlpha * cfg.common.statusbarCounterAlpha); - if(G_Ruleset_Deathmatch()) return; + if(gfw_Rule(deathmatch)) return; if(ST_AutomapIsOpen(player()) && cfg.common.automapHudDisplay == 0) return; if(P_MobjIsCamera(players[player()].plr->mo) && Get(DD_PLAYBACK)) return; @@ -165,7 +165,7 @@ { Rect_SetWidthHeight(&geometry(), 0, 0); - if(G_Ruleset_Deathmatch()) return; + if(gfw_Rule(deathmatch)) return; if(ST_AutomapIsOpen(player()) && cfg.common.automapHudDisplay == 0) return; if(P_MobjIsCamera(players[player()].plr->mo) && Get(DD_PLAYBACK)) return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/intermission.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/intermission.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/intermission.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/intermission.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -58,7 +58,7 @@ interludestate_t beginState; ///< State at which this animation begins/becomes visible. Animation(Vector2i const &origin, int tics, StringList patchNames, - de::Uri const &mapUri = de::Uri("Maps:", RC_NULL), + de::Uri const &mapUri = de::makeUri("Maps:"), interludestate_t beginState = ILS_SHOW_STATS) : origin (origin) , tics (tics) @@ -132,14 +132,14 @@ static void drawChar(QChar const ch, Vector2i const &origin, int alignFlags = ALIGN_TOPLEFT, int textFlags = DTF_NO_TYPEIN) { - Point2Raw const rawOrigin(origin.x, origin.y); + const Point2Raw rawOrigin = {{{origin.x, origin.y}}}; FR_DrawChar3(ch.toLatin1(), &rawOrigin, alignFlags, textFlags); } static void drawText(String const &text, Vector2i const &origin, int alignFlags = ALIGN_TOPLEFT, int textFlags = DTF_NO_TYPEIN) { - Point2Raw const rawOrigin(origin.x, origin.y); + const Point2Raw rawOrigin = {{{origin.x, origin.y}}}; FR_DrawText3(text.toUtf8().constData(), &rawOrigin, alignFlags, textFlags); } @@ -204,37 +204,37 @@ << Animation( Vector2i( 64, 24), 11, StringList() << String("wia00900") << String("wia00901") << String("wia00902") ); episode1Locations - << Location( Vector2i(185, 164), de::Uri("Maps:E1M1", RC_NULL) ) - << Location( Vector2i(148, 143), de::Uri("Maps:E1M2", RC_NULL) ) - << Location( Vector2i( 69, 122), de::Uri("Maps:E1M3", RC_NULL) ) - << Location( Vector2i(209, 102), de::Uri("Maps:E1M4", RC_NULL) ) - << Location( Vector2i(116, 89), de::Uri("Maps:E1M5", RC_NULL) ) - << Location( Vector2i(166, 55), de::Uri("Maps:E1M6", RC_NULL) ) - << Location( Vector2i( 71, 56), de::Uri("Maps:E1M7", RC_NULL) ) - << Location( Vector2i(135, 29), de::Uri("Maps:E1M8", RC_NULL) ) - << Location( Vector2i( 71, 24), de::Uri("Maps:E1M9", RC_NULL) ); + << Location( Vector2i(185, 164), de::makeUri("Maps:E1M1") ) + << Location( Vector2i(148, 143), de::makeUri("Maps:E1M2") ) + << Location( Vector2i( 69, 122), de::makeUri("Maps:E1M3") ) + << Location( Vector2i(209, 102), de::makeUri("Maps:E1M4") ) + << Location( Vector2i(116, 89), de::makeUri("Maps:E1M5") ) + << Location( Vector2i(166, 55), de::makeUri("Maps:E1M6") ) + << Location( Vector2i( 71, 56), de::makeUri("Maps:E1M7") ) + << Location( Vector2i(135, 29), de::makeUri("Maps:E1M8") ) + << Location( Vector2i( 71, 24), de::makeUri("Maps:E1M9") ); episode2Anims - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10000"), de::Uri("Maps:E2M2", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10100"), de::Uri("Maps:E2M3", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10200"), de::Uri("Maps:E2M4", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10300"), de::Uri("Maps:E2M5", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10400"), de::Uri("Maps:E2M6", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10400"), de::Uri("Maps:E2M9", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10500"), de::Uri("Maps:E2M7", RC_NULL) ) - << Animation( Vector2i(128, 136), 0, StringList() << String("wia10600"), de::Uri("Maps:E2M8", RC_NULL) ) - << Animation( Vector2i(192, 144), 11, StringList() << String("wia10700") << String("wia10701") << String("wia10702"), de::Uri("Maps:E2M9", RC_NULL), ILS_SHOW_NEXTMAP ); + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10000"), de::makeUri("Maps:E2M2") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10100"), de::makeUri("Maps:E2M3") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10200"), de::makeUri("Maps:E2M4") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10300"), de::makeUri("Maps:E2M5") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10400"), de::makeUri("Maps:E2M6") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10400"), de::makeUri("Maps:E2M9") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10500"), de::makeUri("Maps:E2M7") ) + << Animation( Vector2i(128, 136), 0, StringList() << String("wia10600"), de::makeUri("Maps:E2M8") ) + << Animation( Vector2i(192, 144), 11, StringList() << String("wia10700") << String("wia10701") << String("wia10702"), de::makeUri("Maps:E2M9"), ILS_SHOW_NEXTMAP ); episode2Locations - << Location( Vector2i(254, 25), de::Uri("Maps:E2M1", RC_NULL) ) - << Location( Vector2i( 97, 50), de::Uri("Maps:E2M2", RC_NULL) ) - << Location( Vector2i(188, 64), de::Uri("Maps:E2M3", RC_NULL) ) - << Location( Vector2i(128, 78), de::Uri("Maps:E2M4", RC_NULL) ) - << Location( Vector2i(214, 92), de::Uri("Maps:E2M5", RC_NULL) ) - << Location( Vector2i(133, 130), de::Uri("Maps:E2M6", RC_NULL) ) - << Location( Vector2i(208, 136), de::Uri("Maps:E2M7", RC_NULL) ) - << Location( Vector2i(148, 140), de::Uri("Maps:E2M8", RC_NULL) ) - << Location( Vector2i(235, 158), de::Uri("Maps:E2M9", RC_NULL) ); + << Location( Vector2i(254, 25), de::makeUri("Maps:E2M1") ) + << Location( Vector2i( 97, 50), de::makeUri("Maps:E2M2") ) + << Location( Vector2i(188, 64), de::makeUri("Maps:E2M3") ) + << Location( Vector2i(128, 78), de::makeUri("Maps:E2M4") ) + << Location( Vector2i(214, 92), de::makeUri("Maps:E2M5") ) + << Location( Vector2i(133, 130), de::makeUri("Maps:E2M6") ) + << Location( Vector2i(208, 136), de::makeUri("Maps:E2M7") ) + << Location( Vector2i(148, 140), de::makeUri("Maps:E2M8") ) + << Location( Vector2i(235, 158), de::makeUri("Maps:E2M9") ); episode3Anims << Animation( Vector2i(104, 168), 11, StringList() << String("wia20000") << String("wia20001") << String("wia20002") ) @@ -245,15 +245,15 @@ << Animation( Vector2i( 40, 0), 8, StringList() << String("wia20500") << String("wia20501") << String("wia20502") ); episode3Locations - << Location( Vector2i(156, 168), de::Uri("Maps:E3M1", RC_NULL) ) - << Location( Vector2i( 48, 154), de::Uri("Maps:E3M2", RC_NULL) ) - << Location( Vector2i(174, 95), de::Uri("Maps:E3M3", RC_NULL) ) - << Location( Vector2i(265, 75), de::Uri("Maps:E3M4", RC_NULL) ) - << Location( Vector2i(130, 48), de::Uri("Maps:E3M5", RC_NULL) ) - << Location( Vector2i(279, 23), de::Uri("Maps:E3M6", RC_NULL) ) - << Location( Vector2i(198, 48), de::Uri("Maps:E3M7", RC_NULL) ) - << Location( Vector2i(140, 25), de::Uri("Maps:E3M8", RC_NULL) ) - << Location( Vector2i(281, 136), de::Uri("Maps:E3M9", RC_NULL) ); + << Location( Vector2i(156, 168), de::makeUri("Maps:E3M1") ) + << Location( Vector2i( 48, 154), de::makeUri("Maps:E3M2") ) + << Location( Vector2i(174, 95), de::makeUri("Maps:E3M3") ) + << Location( Vector2i(265, 75), de::makeUri("Maps:E3M4") ) + << Location( Vector2i(130, 48), de::makeUri("Maps:E3M5") ) + << Location( Vector2i(279, 23), de::makeUri("Maps:E3M6") ) + << Location( Vector2i(198, 48), de::makeUri("Maps:E3M7") ) + << Location( Vector2i(140, 25), de::makeUri("Maps:E3M8") ) + << Location( Vector2i(281, 136), de::makeUri("Maps:E3M9") ); } void IN_Shutdown() @@ -345,14 +345,14 @@ { // Newer versions of the savegame format include a breakdown of the maps previously visited // during the current game session. - if(COMMON_GAMESESSION->allVisitedMaps().isEmpty()) + if(gfw_Session()->allVisitedMaps().isEmpty()) { // For backward compatible intermission behavior we'll have to use a specially prepared // version of this information, using the original map progression assumptions. if(!(gameModeBits & GM_ANY_DOOM2)) { bool isNumber; - int oldEpisodeNum = COMMON_GAMESESSION->episodeId().toInt(&isNumber) - 1; // 1-based + int oldEpisodeNum = gfw_Session()->episodeId().toInt(&isNumber) - 1; // 1-based DENG2_ASSERT(isNumber); DENG2_UNUSED(isNumber); @@ -372,7 +372,7 @@ return visited.toList(); } } - return COMMON_GAMESESSION->allVisitedMaps(); + return gfw_Session()->allVisitedMaps(); } static void drawBackground() @@ -382,7 +382,7 @@ GL_DrawPatch(pBackground, Vector2i(0, 0), ALIGN_TOPLEFT, DPF_NO_OFFSET); - if(Animations const *anims = animationsForEpisode(COMMON_GAMESESSION->episodeId())) + if(Animations const *anims = animationsForEpisode(gfw_Session()->episodeId())) { FR_SetFont(FID(GF_FONTB)); FR_LoadDefaultAttrib(); @@ -531,7 +531,7 @@ */ static void beginAnimations() { - Animations const *anims = animationsForEpisode(COMMON_GAMESESSION->episodeId()); + Animations const *anims = animationsForEpisode(gfw_Session()->episodeId()); if(!anims) return; for(int i = 0; i < anims->count(); ++i) @@ -565,7 +565,7 @@ static void animateBackground() { - Animations const *anims = animationsForEpisode(COMMON_GAMESESSION->episodeId()); + Animations const *anims = animationsForEpisode(gfw_Session()->episodeId()); if(!anims) return; for(int i = 0; i < anims->count(); ++i) @@ -656,7 +656,7 @@ */ static void drawLocationMarks() { - Locations const *locations = locationsForEpisode(COMMON_GAMESESSION->episodeId()); + Locations const *locations = locationsForEpisode(gfw_Session()->episodeId()); if(!locations) return; DGL_Enable(DGL_TEXTURE_2D); @@ -1185,7 +1185,7 @@ static void tickShowStats() { - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { updateDeathmatchStats(); return; @@ -1303,7 +1303,7 @@ static void drawStats() { - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { drawDeathmatchStats(); } @@ -1380,7 +1380,7 @@ static void loadData() { - String const episodeId = COMMON_GAMESESSION->episodeId(); + String const episodeId = gfw_Session()->episodeId(); // Determine which patch to use for the background. pBackground = R_DeclarePatch(backgroundPatchForEpisode(episodeId).toUtf8().constData()); @@ -1520,7 +1520,7 @@ } } - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { initDeathmatchStats(); beginAnimations(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/m_cheat.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/m_cheat.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/m_cheat.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/m_cheat.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -36,6 +36,7 @@ #include "gamesession.h" #include "hu_msg.h" #include "p_user.h" +#include "p_sound.h" #include "player.h" using namespace de; @@ -78,8 +79,8 @@ } // Lookup and try to enqueue the Music for the referenced episode and map. - Record const &mapInfo = G_MapInfoForMapUri(TranslateMapWarpNumber(episodeId, warpNumber)); - if(S_StartMusic(mapInfo.gets("music").toUtf8().constData(), true /*loop it*/)) + const auto mapUri = TranslateMapWarpNumber(episodeId, warpNumber); + if (S_MapMusic(mapUri)) { P_SetMessageWithFlags(plr, STSTR_MUS, LMF_NO_HIDE); return true; @@ -93,7 +94,7 @@ { DENG2_UNUSED2(args, numArgs); - if(IS_NETGAME && COMMON_GAMESESSION->rules().deathmatch) + if(IS_NETGAME && gfw_Rule(deathmatch)) return false; if(player < 0 || player >= MAXPLAYERS) @@ -198,7 +199,7 @@ NetCl_CheatRequest("god"); } else if((IS_NETGAME && !netSvAllowCheats) || - COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -245,7 +246,7 @@ NetCl_CheatRequest("noclip"); } else if((IS_NETGAME && !netSvAllowCheats) || - COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -418,7 +419,7 @@ } if(IS_NETGAME && !netSvAllowCheats) return false; - if(COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; player_t *plr = &players[player]; @@ -553,7 +554,7 @@ NetCl_CheatRequest("kill"); } else if((IS_NETGAME && !netSvAllowCheats) || - COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -578,7 +579,7 @@ if(!plrMo) return true; String const text = String("Map:%1 position:%2") - .arg(COMMON_GAMESESSION->mapUri().asText()) + .arg(gfw_Session()->mapUri().asText()) .arg(Vector3d(plrMo->origin).asText()); P_SetMessageWithFlags(plr, text.toUtf8().constData(), LMF_NO_HIDE); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_enemy.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_enemy.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_enemy.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_enemy.c 2018-12-11 07:08:22.000000000 +0000 @@ -420,7 +420,7 @@ VALIDCOUNT++; Mobj_TouchedLinesIterator(mobj, PIT_AvoidDropoff, &parm); - if(FEQUAL(parm.direction[VX], 0) && FEQUAL(parm.direction[VY], 0)) + if(IS_ZERO(parm.direction[VX]) && IS_ZERO(parm.direction[VY])) return false; // The mobj should attempt to move away from the drop off. @@ -679,7 +679,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE && !G_Ruleset_Fast()) + if(gfw_Rule(skill) != SM_NIGHTMARE && !gfw_Rule(fast)) { newChaseDir(actor); } @@ -702,8 +702,8 @@ // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { - if(!(G_Ruleset_Skill() != SM_NIGHTMARE && - !G_Ruleset_Fast() && actor->moveCount)) + if(!(gfw_Rule(skill) != SM_NIGHTMARE && + !gfw_Rule(fast) && actor->moveCount)) { if(checkMissileRange(actor)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_inter.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_inter.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_inter.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_inter.c 2018-12-11 07:08:22.000000000 +0000 @@ -81,8 +81,8 @@ } // Give double the number of rounds at easy/nightmare skill levels. - if(G_Ruleset_Skill() == SM_BABY || - G_Ruleset_Skill() == SM_NIGHTMARE) + if(gfw_Rule(skill) == SM_BABY || + gfw_Rule(skill) == SM_NIGHTMARE) { numRounds *= 2; } @@ -125,7 +125,7 @@ static dd_bool shouldForceWeaponChange(dd_bool dropped) { - return IS_NETGAME && G_Ruleset_Deathmatch() == 1 && !dropped; + return IS_NETGAME && gfw_Rule(deathmatch) == 1 && !dropped; } static int numAmmoClipsToGiveWithWeapon(dd_bool dropped) @@ -134,7 +134,7 @@ if(dropped) return 1; // Give extra clips in deathmatch. - return (IS_NETGAME && G_Ruleset_Deathmatch() == 1)? 5 : 2; + return (IS_NETGAME && gfw_Rule(deathmatch) == 1)? 5 : 2; } static dd_bool giveOneWeapon(player_t *plr, weapontype_t weaponType, dd_bool dropped) @@ -174,7 +174,7 @@ plr->update |= PSF_OWNED_WEAPONS; // Animate a pickup bonus flash? - if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped) + if(IS_NETGAME && gfw_Rule(deathmatch) != 2 && !dropped) { plr->bonusCount += BONUSADD; } @@ -534,7 +534,7 @@ if(plr->weapons[weaponType].owned) { // Leave placed weapons forever on net games. - if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped) + if(IS_NETGAME && gfw_Rule(deathmatch) != 2 && !dropped) return false; } @@ -551,7 +551,7 @@ } } - if(IS_NETGAME && G_Ruleset_Deathmatch() != 2 && !dropped) + if(IS_NETGAME && gfw_Rule(deathmatch) != 2 && !dropped) { // Leave placed weapons forever on net games. return false; @@ -1135,7 +1135,7 @@ if(source && source->player && source->player != target->player) { // Co-op damage disabled? - if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) + if(IS_NETGAME && !gfw_Rule(deathmatch) && cfg.noCoopDamage) return 0; // Same color, no damage? @@ -1152,7 +1152,7 @@ } player = target->player; - if(player && G_Ruleset_Skill() == SM_BABY) + if(player && gfw_Rule(skill) == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_lights.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_lights.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_lights.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_lights.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -397,7 +397,7 @@ if(!list) return; float lightLevel = 0; - if(!FEQUAL(max, 0)) + if(NON_ZERO(max)) lightLevel = max; IterList_SetIteratorDirection(list, ITERLIST_FORWARD); @@ -408,7 +408,7 @@ { // If Max = 0 means to search for the highest light level in the // surrounding sector. - if(FEQUAL(max, 0)) + if(IS_ZERO(max)) { lightLevel = P_GetFloatp(sec, DMU_LIGHT_LEVEL); float otherLevel = DDMINFLOAT; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_maputl.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_maputl.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_maputl.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_maputl.c 2018-12-11 07:08:22.000000000 +0000 @@ -128,7 +128,7 @@ // If any momentum, mark object as 'falling' using engine-internal // flags. - if(!FEQUAL(mo->mom[MX], 0) || !FEQUAL(mo->mom[MY], 0)) + if(NON_ZERO(mo->mom[MX]) || NON_ZERO(mo->mom[MY])) { mo->intFlags |= MIF_FALLING; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_mobj.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_mobj.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_mobj.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_mobj.c 2018-12-11 07:08:22.000000000 +0000 @@ -433,14 +433,14 @@ // Update gravity's effect on momentum. if(mo->flags2 & MF2_LOGRAV) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= (gravity / 8); } else if(!(mo->flags & MF_NOGRAVITY)) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; @@ -625,7 +625,7 @@ if(!(mo->flags & MF_COUNTKILL)) return; - if(!G_Ruleset_RespawnMonsters()) + if(!gfw_Rule(respawnMonsters)) return; mo->moveCount++; @@ -652,14 +652,14 @@ info = &MOBJINFO[type]; // Not for deathmatch? - if(G_Ruleset_Deathmatch() && (info->flags & MF_NOTDMATCH)) + if(gfw_Rule(deathmatch) && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. if(IS_NETGAME) { // Cooperative weapons? - if(cfg.noCoopWeapons && !G_Ruleset_Deathmatch() && type >= MT_CLIP && + if(cfg.noCoopWeapons && !gfw_Rule(deathmatch) && type >= MT_CLIP && type <= MT_SUPERSHOTGUN) return NULL; @@ -700,7 +700,7 @@ } // Don't spawn any monsters? - if(G_Ruleset_NoMonsters() && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) + if(gfw_Rule(noMonsters) && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) return NULL; if(info->flags & MF_SOLID) @@ -726,7 +726,7 @@ // Let the engine know about solid objects. P_SetDoomsdayFlags(mo); - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) mo->reactionTime = info->reactionTime; mo->lastLook = P_Random() % MAXPLAYERS; @@ -943,7 +943,7 @@ if(source->player) { // Allow free-aim with the BFG in deathmatch? - if(G_Ruleset_Deathmatch() && cfg.netBFGFreeLook == 0 && type == MT_BFG) + if(gfw_Rule(deathmatch) && cfg.netBFGFreeLook == 0 && type == MT_BFG) th->mom[MZ] = 0; else th->mom[MZ] = th->info->speed * slope; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_spec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_spec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/p_spec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/p_spec.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -257,7 +257,7 @@ case 52: // EXIT! - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; case 53: @@ -340,7 +340,7 @@ case 124: // Secret EXIT. - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); break; case 125: @@ -628,7 +628,7 @@ P_DamageMobj(player->plr->mo, NULL, NULL, 20, false); if(player->health <= 10) - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; } } @@ -798,7 +798,7 @@ P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0); xline->special = 0; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; case 14: @@ -914,7 +914,7 @@ P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0); xline->special = 0; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); break; case 55: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/st_stuff.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/st_stuff.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom/src/st_stuff.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom/src/st_stuff.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -158,7 +158,7 @@ float armsBGX = 0; dd_bool haveArms = false; patchinfo_t armsInfo; - if(!G_Ruleset_Deathmatch()) + if(!gfw_Rule(deathmatch)) { haveArms = R_GetPatchInfo(pArmsBackground, &armsInfo); @@ -571,7 +571,7 @@ HudWidget &mnGroup = GUI_FindWidgetById(hud->groupIds[UWG_MAPNAME]); mnGroup.setOpacity(ST_AutomapOpacity(localPlayer)); int availHeight = displayRegion.size.height - (drawnSize.height > 0 ? drawnSize.height : 0); - Size2Raw size(displayRegion.size.width, availHeight); + Size2Raw size = {{{displayRegion.size.width, availHeight}}}; mnGroup.setMaximumSize(size); GUI_DrawWidget(&mnGroup, &displayRegion.origin); @@ -742,7 +742,7 @@ automap.clearAllPoints(true/*silent*/); #if !__JHEXEN__ - if(G_Ruleset_Skill() == SM_BABY && cfg.common.automapBabyKeys) + if(gfw_Rule(skill) == SM_BABY && cfg.common.automapBabyKeys) { automap.setFlags(automap.flags() | AWF_SHOW_KEYS); } @@ -754,9 +754,9 @@ #endif // Are we re-centering on a followed mobj? - if(mobj_t *mob = automap.followMobj()) + if (mobj_t *mob = automap.followMobj()) { - automap.setCameraOrigin(Vector2d(mob->origin)); + automap.setCameraOrigin(Vector2d(mob->origin), true); } if(IS_NETGAME) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/d64_api.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/d64_api.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/d64_api.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/d64_api.h 2018-12-11 07:08:22.000000000 +0000 @@ -39,8 +39,6 @@ extern "C" { #endif -extern game_export_t gx; - DENG_USING_API(Base); DENG_USING_API(B); DENG_USING_API(Busy); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/d_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/d_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/d_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/d_main.h 2018-12-11 07:08:22.000000000 +0000 @@ -27,8 +27,6 @@ #include "doomdef.h" -DENG_EXTERN_C float turboMul; // Multiplier for turbo. - DENG_EXTERN_C gamemode_t gameMode; DENG_EXTERN_C int gameModeBits; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/doomdef.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/doomdef.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/doomdef.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/doomdef.h 2018-12-11 07:08:22.000000000 +0000 @@ -53,8 +53,6 @@ #define Set DD_SetInteger #define Get DD_GetInteger -DENG_EXTERN_C game_export_t gx; - // // Global parameters/defines. // diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/include/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/include/version.h 2018-12-11 07:08:22.000000000 +0000 @@ -63,6 +63,6 @@ // For WIN32 version info: #define PLUGIN_DESC PLUGIN_NICENAME " " LIBDENG_PLUGINDESC -#define PLUGIN_COPYRIGHT "2003-2013, " DENGPROJECT_NICEAUTHOR +#define PLUGIN_COPYRIGHT "2003-2018, " DENGPROJECT_NICEAUTHOR #endif /* JDOOM64_VERSION_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d64_api.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d64_api.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d64_api.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d64_api.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -49,9 +49,6 @@ using namespace de; -// The interface to the Doomsday engine. -game_export_t gx; - // Identifiers given to the games we register during startup. static char const *gameIds[NUM_GAME_MODES] = { @@ -61,7 +58,7 @@ /** * Register the game modes supported by this plugin. */ -int G_RegisterGames(int hookType, int param, void* data) +static int G_RegisterGames(int hookType, int param, void* data) { DENG_UNUSED(hookType); DENG_UNUSED(param); DENG_UNUSED(data); @@ -85,7 +82,7 @@ /** * Called right after the game plugin is selected into use. */ -DENG_EXTERN_C void DP_Load(void) +DENG_ENTRYPOINT void DP_Load(void) { Plug_AddHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); gfw_SetCurrentGame(GFW_DOOM64); @@ -94,12 +91,12 @@ /** * Called when the game plugin is freed from memory. */ -DENG_EXTERN_C void DP_Unload(void) +DENG_ENTRYPOINT void DP_Unload(void) { Plug_RemoveHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); } -DENG_EXTERN_C void G_PreInit(char const *gameId) +void G_PreInit(char const *gameId) { /// \todo Refactor me away. { size_t i; @@ -126,63 +123,37 @@ return true; } -/** - * Takes a copy of the engine's entry points and exported data. Returns - * a pointer to the structure that contains our entry points and exports. - */ -DENG_EXTERN_C game_export_t *GetGameAPI(void) +DENG_ENTRYPOINT void *GetGameAPI(char const *name) { - // Clear all of our exports. - memset(&gx, 0, sizeof(gx)); - - // Fill in the data for the exports. - gx.apiSize = sizeof(gx); - gx.PreInit = G_PreInit; - gx.PostInit = D_PostInit; - gx.Shutdown = D_Shutdown; - gx.TryShutdown = G_TryShutdown; - gx.Ticker = G_Ticker; - gx.DrawViewPort = G_DrawViewPort; - gx.DrawWindow = D_DrawWindow; - gx.FinaleResponder = FI_PrivilegedResponder; - gx.PrivilegedResponder = G_PrivilegedResponder; - gx.Responder = G_Responder; - gx.EndFrame = D_EndFrame; - gx.MobjThinker = P_MobjThinker; - gx.MobjFriction = Mobj_Friction; - gx.MobjCheckPositionXYZ = P_CheckPositionXYZ; - gx.MobjTryMoveXYZ = P_TryMoveXYZ; - gx.SectorHeightChangeNotification = P_HandleSectorHeightChange; - gx.UpdateState = G_UpdateState; - gx.GetInteger = D_GetInteger; - gx.GetVariable = D_GetVariable; - - gx.NetServerStart = D_NetServerStarted; - gx.NetServerStop = D_NetServerClose; - gx.NetConnect = D_NetConnect; - gx.NetDisconnect = D_NetDisconnect; - gx.NetPlayerEvent = D_NetPlayerEvent; - gx.NetWorldEvent = D_NetWorldEvent; - gx.HandlePacket = D_HandlePacket; - - // Data structure sizes. - gx.mobjSize = sizeof(mobj_t); - gx.polyobjSize = sizeof(Polyobj); - - gx.FinalizeMapChange = (void (*)(void const *)) P_FinalizeMapChange; - - // These really need better names. Ideas? - gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; - gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; + if (auto *ptr = Common_GetGameAPI(name)) + { + return ptr; + } - return &gx; + #define HASH_ENTRY(Name, Func) std::make_pair(QByteArray(Name), de::function_cast(Func)) + static QHash const funcs( + { + HASH_ENTRY("DrawWindow", D_DrawWindow), + HASH_ENTRY("EndFrame", D_EndFrame), + HASH_ENTRY("GetInteger", D_GetInteger), + HASH_ENTRY("GetPointer", D_GetVariable), + HASH_ENTRY("PostInit", D_PostInit), + HASH_ENTRY("PreInit", G_PreInit), + HASH_ENTRY("Shutdown", D_Shutdown), + HASH_ENTRY("TryShutdown", G_TryShutdown), + }); + #undef HASH_ENTRY + + auto found = funcs.find(name); + if (found != funcs.end()) return found.value(); + return nullptr; } /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -DENG_EXTERN_C void DP_Initialize() +DENG_ENTRYPOINT void DP_Initialize() { Plug_AddHook(HOOK_STARTUP, G_RegisterGames); } @@ -191,11 +162,26 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C const char* deng_LibraryType(void) +DENG_ENTRYPOINT const char* deng_LibraryType(void) { return "deng-plugin/game"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_doom64_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + DENG_SYMBOL_PTR(name, DP_Load); + DENG_SYMBOL_PTR(name, DP_Unload); + DENG_SYMBOL_PTR(name, GetGameAPI); + qWarning() << name << "not found in doom64"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(B); DENG_DECLARE_API(Busy); @@ -243,3 +229,5 @@ DENG_GET_API(DE_API_THINKER, Thinker); DENG_GET_API(DE_API_URI, Uri); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d_main.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -40,8 +40,6 @@ using namespace de; using namespace common; -float turboMul; // Multiplier for turbo. - gamemode_t gameMode; int gameModeBits; @@ -167,7 +165,7 @@ cfg.common.hudColor[0] = 1; cfg.common.hudColor[1] = cfg.common.hudColor[2] = 0; cfg.common.hudColor[3] = 0.75f; - cfg.common.hudFog = 1; + cfg.common.hudFog = 5; cfg.common.hudIconAlpha = 0.5f; cfg.common.xhairAngle = 0; cfg.common.xhairSize = .5f; @@ -260,7 +258,7 @@ cfg.common.automapBack[2] = 0.f; cfg.common.automapOpacity = .7f; cfg.common.automapLineAlpha = .7f; - cfg.common.automapLineWidth = 1.1f; + cfg.common.automapLineWidth = 3.0f; cfg.common.automapShowDoors = true; cfg.common.automapDoorGlow = 8; cfg.common.automapHudDisplay = 2; @@ -333,7 +331,7 @@ } // Get skill / episode / map from parms. - ::defaultGameRules.skill = /*startSkill =*/ SM_MEDIUM; + gfw_SetDefaultRule(skill, /*startSkill =*/ SM_MEDIUM); if(cmdLine.check("-altdeath")) { @@ -345,11 +343,11 @@ } // Apply these rules. - ::defaultGameRules.noMonsters = cmdLine.check("-nomonsters")? true : false; - ::defaultGameRules.respawnMonsters = cmdLine.check("-respawn") ? true : false; - ::defaultGameRules.fast = cmdLine.check("-fast") ? true : false; + gfw_SetDefaultRule(noMonsters , cmdLine.has("-nomonsters")); + gfw_SetDefaultRule(respawnMonsters, cmdLine.has("-respawn") ); + gfw_SetDefaultRule(fast , cmdLine.has("-fast") ); - if(::defaultGameRules.deathmatch) + if (gfw_DefaultRule(deathmatch)) { if(int arg = cmdLine.check("-timer", 1)) { @@ -363,21 +361,6 @@ } } - // Change the turbo multiplier? - ::turboMul = 1.0f; - if(int arg = cmdLine.check("-turbo")) - { - int scale = 200; - if(arg + 1 < cmdLine.count() && !cmdLine.isOption(arg + 1)) - { - scale = cmdLine.at(arg + 1).toInt(); - } - scale = de::clamp(10, scale, 400); - - LOG_NOTE("Turbo scale: %i%%") << scale; - ::turboMul = scale / 100.f; - } - // Load a saved game? if(int arg = cmdLine.check("-loadgame", 1)) { @@ -392,10 +375,10 @@ } // Change the default skill mode? - if(int arg = cmdLine.check("-skill", 1)) + if (auto arg = cmdLine.check("-skill", 1)) { - int skillNumber = cmdLine.at(arg + 1).toInt(); - ::defaultGameRules.skill = (skillmode_t)(skillNumber > 0? skillNumber - 1 : skillNumber); + int const skillNumber = arg.params.first().toInt(); + gfw_SetDefaultRule(skill, skillmode_t(skillNumber > 0? skillNumber - 1 : skillNumber)); } G_AutoStartOrBeginTitleLoop(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d_refresh.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d_refresh.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/d_refresh.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/d_refresh.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -88,7 +88,7 @@ rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; - rgba[CA] = (G_Ruleset_Deathmatch()? 1.0f : cfg.common.filterStrength) * filter / 9.f; + rgba[CA] = (gfw_Rule(deathmatch)? 1.0f : cfg.common.filterStrength) * filter / 9.f; return true; } @@ -206,7 +206,7 @@ } // How about fullbright? - DD_SetInteger(DD_FULLBRIGHT, isFullBright); + DD_SetInteger(DD_RENDER_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/intermission.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/intermission.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/intermission.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/intermission.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -83,14 +83,14 @@ static void drawChar(QChar const ch, Vector2i const &origin, int alignFlags = ALIGN_TOPLEFT, int textFlags = DTF_NO_TYPEIN) { - Point2Raw const rawOrigin(origin.x, origin.y); + const Point2Raw rawOrigin = {{{origin.x, origin.y}}}; FR_DrawChar3(ch.toLatin1(), &rawOrigin, alignFlags, textFlags); } static void drawText(String const &text, Vector2i const &origin, int alignFlags = ALIGN_TOPLEFT, int textFlags = DTF_NO_TYPEIN) { - Point2Raw const rawOrigin(origin.x, origin.y); + const Point2Raw rawOrigin = {{{origin.x, origin.y}}}; FR_DrawText3(text.toUtf8().constData(), &rawOrigin, alignFlags, textFlags); } @@ -764,7 +764,7 @@ static void tickShowStats() { - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { updateDeathmatchStats(); return; @@ -879,7 +879,7 @@ static void drawStats() { - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { drawDeathmatchStats(); } @@ -1077,7 +1077,7 @@ } } - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { initDeathmatchStats(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/m_cheat.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/m_cheat.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/m_cheat.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/m_cheat.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -75,7 +75,7 @@ NetCl_CheatRequest("god"); } else if((IS_NETGAME && !netSvAllowCheats) - || COMMON_GAMESESSION->rules().skill == SM_HARD) + || gfw_Rule(skill) == SM_HARD) { return false; } @@ -125,7 +125,7 @@ NetCl_CheatRequest("noclip"); } else if((IS_NETGAME && !netSvAllowCheats) - || COMMON_GAMESESSION->rules().skill == SM_HARD) + || gfw_Rule(skill) == SM_HARD) { return false; } @@ -317,7 +317,7 @@ { return false; } - else if(COMMON_GAMESESSION->rules().skill == SM_HARD) + else if(gfw_Rule(skill) == SM_HARD) { return false; } @@ -488,7 +488,7 @@ { char textBuffer[256]; sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", - COMMON_GAMESESSION->mapUri().path().toUtf8().constData(), + gfw_Session()->mapUri().path().toUtf8().constData(), plrMo->origin[VX], plrMo->origin[VY], plrMo->origin[VZ]); P_SetMessageWithFlags(plr, textBuffer, LMF_NO_HIDE); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_enemy.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_enemy.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_enemy.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_enemy.c 2018-12-11 07:08:22.000000000 +0000 @@ -419,7 +419,7 @@ VALIDCOUNT++; Mobj_TouchedLinesIterator(mobj, PIT_AvoidDropoff, &parm); - if(FEQUAL(parm.direction[VX], 0) && FEQUAL(parm.direction[VY], 0)) + if(IS_ZERO(parm.direction[VX]) && IS_ZERO(parm.direction[VY])) return false; // The mobj should attempt to move away from the drop off. @@ -988,7 +988,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(!G_Ruleset_Fast()) + if(!gfw_Rule(fast)) { newChaseDir(actor); } @@ -1011,7 +1011,7 @@ // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { - if(G_Ruleset_Fast() || !actor->moveCount || G_Ruleset_Skill() == SM_HARD) + if(gfw_Rule(fast) || !actor->moveCount || gfw_Rule(skill) == SM_HARD) { if(checkMissileRange(actor)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_inter.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_inter.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_inter.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_inter.c 2018-12-11 07:08:22.000000000 +0000 @@ -66,7 +66,7 @@ else num = clipAmmo[ammo] / 2; - if (G_Ruleset_Skill() == SM_BABY) + if (gfw_Rule(skill) == SM_BABY) { // Give double ammo in trainer mode. num <<= 1; @@ -98,7 +98,7 @@ dd_bool gaveWeapon; int numClips; - if (IS_NETGAME && (G_Ruleset_Deathmatch() != 2) && !dropped) + if (IS_NETGAME && (gfw_Rule(deathmatch) != 2) && !dropped) { // leave placed weapons forever on net games if (player->weapons[weapon].owned) @@ -114,7 +114,7 @@ if (!weaponInfo[weapon][player->class_].mode[0].ammoType[i]) continue; // Weapon does not take this type of ammo. - if (G_Ruleset_Deathmatch()) + if (gfw_Rule(deathmatch)) numClips = 5; else numClips = 2; @@ -124,7 +124,7 @@ } // Should we change weapon automatically? - P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, G_Ruleset_Deathmatch() == 1); + P_MaybeChangeWeapon(player, weapon, AT_NOAMMO, gfw_Rule(deathmatch) == 1); // Maybe unhide the HUD? ST_HUDUnHide(player - players, HUE_ON_PICKUP_WEAPON); @@ -1053,7 +1053,7 @@ if (source && source->player && source->player != target->player) { // Co-op damage disabled? - if (IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) + if (IS_NETGAME && !gfw_Rule(deathmatch) && cfg.noCoopDamage) return 0; // Same color, no damage? @@ -1070,7 +1070,7 @@ } player = target->player; - if (player && G_Ruleset_Skill() == SM_BABY) + if (player && gfw_Rule(skill) == SM_BABY) damage >>= 1; // take half damage in trainer mode // jd64 > diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_maputl.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_maputl.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_maputl.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_maputl.c 2018-12-11 07:08:22.000000000 +0000 @@ -127,7 +127,7 @@ // If any momentum, mark object as 'falling' using engine-internal // flags. - if(!FEQUAL(mo->mom[MX], 0) || !FEQUAL(mo->mom[MY], 0)) + if(NON_ZERO(mo->mom[MX]) || NON_ZERO(mo->mom[MY])) { mo->intFlags |= MIF_FALLING; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_mobj.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_mobj.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_mobj.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_mobj.c 2018-12-11 07:08:22.000000000 +0000 @@ -531,7 +531,7 @@ #endif // Handle X and Y momentums. - if(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0) || (mobj->flags & MF_SKULLFLY)) + if(NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY]) || (mobj->flags & MF_SKULLFLY)) { P_MobjMoveXY(mobj); @@ -552,7 +552,7 @@ mobj->floorClip = -MAX_BOB_OFFSET; } } - else if(!FEQUAL(mobj->origin[VZ], mobj->floorZ) || !FEQUAL(mobj->mom[MZ], 0)) + else if(!FEQUAL(mobj->origin[VZ], mobj->floorZ) || NON_ZERO(mobj->mom[MZ])) { P_MobjMoveZ(mobj); if(mobj->thinker.function != (thinkfunc_t) P_MobjThinker) // Must've been removed. @@ -653,7 +653,7 @@ if(!(mobj->flags & MF_COUNTKILL)) return; - if(!G_Ruleset_RespawnMonsters()) + if(!gfw_Rule(respawnMonsters)) return; mobj->moveCount++; @@ -692,14 +692,14 @@ return NULL; // Not for deathmatch? - if(G_Ruleset_Deathmatch() && (info->flags & MF_NOTDMATCH)) + if(gfw_Rule(deathmatch) && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. if(IS_NETGAME) { // Cooperative weapons? - if(cfg.noCoopWeapons && !G_Ruleset_Deathmatch() && type >= MT_CLIP && + if(cfg.noCoopWeapons && !gfw_Rule(deathmatch) && type >= MT_CLIP && type <= MT_SUPERSHOTGUN) return NULL; @@ -719,7 +719,7 @@ } // Don't spawn any monsters? - if(G_Ruleset_NoMonsters() && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) + if(gfw_Rule(noMonsters) && ((info->flags & MF_COUNTKILL) || type == MT_SKULL)) return NULL; if(info->flags & MF_SOLID) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_spec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_spec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/p_spec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/p_spec.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -329,7 +329,7 @@ case 52: // EXIT! - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; case 53: @@ -412,7 +412,7 @@ case 124: // Secret EXIT - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); break; case 125: @@ -945,7 +945,7 @@ P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_SWTCHX, false, 0); xline->special = 0; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; case 14: @@ -1061,7 +1061,7 @@ P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0); xline->special = 0; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); break; case 55: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/st_stuff.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/st_stuff.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/doom64/src/st_stuff.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/doom64/src/st_stuff.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -225,8 +225,8 @@ HudWidget& mapNameGroup = GUI_FindWidgetById(hud->groupIds[UWG_MAPNAME]); mapNameGroup.setOpacity(ST_AutomapOpacity(playerId)); - Size2Raw remainingVertical(displayRegion.size.width, - displayRegion.size.height - (regionRendered.height > 0 ? regionRendered.height : 0)); + Size2Raw remainingVertical = {{{displayRegion.size.width, + displayRegion.size.height - (regionRendered.height > 0 ? regionRendered.height : 0)}}}; mapNameGroup.setMaximumSize(remainingVertical); @@ -352,7 +352,7 @@ } // Enable keyboard guide for "baby" mode - if (G_Ruleset_Skill() == SM_BABY && cfg.common.automapBabyKeys) + if (gfw_Rule(skill) == SM_BABY && cfg.common.automapBabyKeys) { map.setFlags(map.flags() | AWF_SHOW_KEYS); } @@ -370,7 +370,7 @@ if (followTarget) { - map.setCameraOrigin(Vector2d(followTarget->origin)); + map.setCameraOrigin(Vector2d(followTarget->origin), true); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/example/include/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/example/include/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/example/include/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/example/include/version.h 2018-12-11 07:08:22.000000000 +0000 @@ -49,6 +49,6 @@ // For WIN32 version info: #define PLUGIN_DESC PLUGIN_NICENAME " " LIBDENG_PLUGINDESC -#define PLUGIN_COPYRIGHT "2003-2013, " DENGPROJECT_NICEAUTHOR +#define PLUGIN_COPYRIGHT "2003-2018, " DENGPROJECT_NICEAUTHOR #endif /* EXAMPLE_PLUGIN_VERSION_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/example/src/example.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/example/src/example.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/example/src/example.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/example/src/example.c 2018-12-11 07:08:22.000000000 +0000 @@ -55,7 +55,7 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * during plugin loading, before DP_Initialize(). */ -DENG_EXTERN_C char const *deng_LibraryType(void) +DENG_EXTERN_C DENG_VISIBLE_SYMBOL char const *deng_LibraryType(void) { return "deng-plugin/generic"; } @@ -64,7 +64,7 @@ * This function is called automatically when the plugin is loaded. We let the * engine know what we'd like to do. */ -DENG_EXTERN_C void DP_Initialize(void) +DENG_EXTERN_C DENG_VISIBLE_SYMBOL void DP_Initialize(void) { Plug_AddHook(HOOK_STARTUP, ExampleHook); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/api/audio_fluidsynth.def doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/api/audio_fluidsynth.def --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/api/audio_fluidsynth.def 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/api/audio_fluidsynth.def 2018-12-11 07:08:22.000000000 +0000 @@ -1,6 +1,6 @@ LIBRARY AUDIO_FLUIDSYNTH -; All exports should be prefixed DS_. +; All exports should be prefixed DS_ or DM_. EXPORTS @@ -19,6 +19,6 @@ DM_Music_Set DM_Music_Pause DM_Music_Stop -DM_Music_SongBuffer -DM_Music_Play +; DM_Music_SongBuffer +; DM_Music_Play DM_Music_PlayFile diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/CMakeLists.txt 2018-12-11 07:08:22.000000000 +0000 @@ -5,16 +5,18 @@ project (DENG_FLUIDSYNTH) include (../PluginConfig.cmake) -find_package (PkgConfig) - set (tgt audio_fluidsynth) # Make an embedded build by default? -if (APPLE) +if (APPLE OR MINGW_GLIB_DIR) set (embed ON) elseif (UNIX) set (embed OFF) endif () +if (WIN32 AND NOT MINGW_GLIB_DIR) + message (STATUS "Not building ${tgt} because the MinGW version of GLib is required on Windows (set MINGW_GLIB_DIR)") + return () +endif () option (DENG_FLUIDSYNTH_EMBEDDED "Compile FluidSynth as part of the ${tgt} plugin" ${embed} @@ -23,11 +25,14 @@ if (DENG_FLUIDSYNTH_EMBEDDED) find_package (Glib) - # Bundle library dependencies on macOS. - foreach (fn ${GLIB_LIBRARIES}) - list (APPEND macRes ${fn},Frameworks) - endforeach () - deng_find_resources (${macRes}) + if (APPLE) + # Bundle library dependencies on macOS. + foreach (fn ${GLIB_LIBRARIES}) + list (APPEND macRes ${fn},Frameworks) + endforeach () + deng_find_resources (${macRes}) + add_definitions (-DDARWIN=1) + endif () add_definitions ( -D_BSD_SOURCE -DFLUIDSYNTH_NOT_A_DLL -DWITH_FLOAT @@ -41,9 +46,6 @@ -DHAVE_FCNTL_H -DHAVE_ERRNO_H ) endif () - if (APPLE) - add_definitions (-DDARWIN=1) - endif () set (FS_DIR ${DENG_EXTERNAL_SOURCE_DIR}/fluidsynth) include_directories ( @@ -95,6 +97,7 @@ else () # We will use the libfluidsynth installed on the system. + find_package (PkgConfig) pkg_check_modules (FLUIDSYNTH fluidsynth) if (NOT FLUIDSYNTH_FOUND) message (STATUS "Not building ${tgt} because \"fluidsynth\" not found (using pkg-config).\n\ @@ -133,10 +136,3 @@ else () target_link_libraries (${tgt} PRIVATE ${FLUIDSYNTH_LIBRARIES}) endif () - -# win32 { -# RC_FILE = res/fluidsynth.rc -# -# QMAKE_LFLAGS += /DEF:\"$$PWD/api/dsfluidsynth.def\" -# OTHER_FILES += api/dsfluidsynth.def -# } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/include/driver_fluidsynth.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/include/driver_fluidsynth.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/include/driver_fluidsynth.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/include/driver_fluidsynth.h 2018-12-11 07:08:22.000000000 +0000 @@ -48,7 +48,7 @@ fluid_audio_driver_t* DMFluid_Driver(); audiointerface_sfx_generic_t* DMFluid_Sfx(); -#define MAX_SYNTH_GAIN 0.4 +#define MAX_SYNTH_GAIN 0.4f #define DSFLUIDSYNTH_TRACE(args) LOGDEV_AUDIO_XVERBOSE("[FluidSynth] ", args) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/res/audio_fluidsynth.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/res/audio_fluidsynth.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/res/audio_fluidsynth.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/res/audio_fluidsynth.rc 2018-12-11 07:08:22.000000000 +0000 @@ -3,8 +3,8 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2013 Daniel Swanson - *\author Copyright © 2011-2017 Jaakko Keränen + *\author Copyright (c) 2008-2013 Daniel Swanson + *\author Copyright (c) 2011-2018 Jaakko Keränen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -81,7 +81,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsFluidSynth.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -119,7 +119,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "dsFluidSynth.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/res/resource.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/res/resource.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/res/resource.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/res/resource.h 2018-12-11 07:08:22.000000000 +0000 @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by fluidsynth.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 102 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/src/driver_fluidsynth.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/src/driver_fluidsynth.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/src/driver_fluidsynth.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/src/driver_fluidsynth.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -55,7 +55,7 @@ */ int DS_Init(void) { - if(fsSynth) + if (fsSynth) { return true; // Already initialized. } @@ -66,12 +66,14 @@ // Create the synthesizer. fsSynth = new_fluid_synth(fsConfig); - if(!fsSynth) + if (!fsSynth) { App_Log(DE2_AUDIO_ERROR, "[FluidSynth] Failed to create synthesizer"); return false; } + fluid_synth_set_gain(DMFluid_Synth(), MAX_SYNTH_GAIN); + #ifndef FLUIDSYNTH_NOT_A_DLL // Create the output driver that will play the music. std::string driverName = FLUIDSYNTH_DEFAULT_DRIVER_NAME; @@ -82,7 +84,7 @@ } fluid_settings_setstr(fsConfig, "audio.driver", driverName.c_str()); fsDriver = new_fluid_audio_driver(fsConfig, fsSynth); - if(!fsDriver) + if (!fsDriver) { App_Log(DE2_AUDIO_ERROR, "[FluidSynth] Failed to load audio driver '%s'", driverName.c_str()); return false; @@ -100,13 +102,13 @@ */ void DS_Shutdown(void) { - if(!fsSynth) return; + if (!fsSynth) return; DMFluid_Shutdown(); DSFLUIDSYNTH_TRACE("DS_Shutdown."); - if(fsDriver) + if (fsDriver) { delete_fluid_audio_driver(fsDriver); } @@ -123,9 +125,9 @@ */ void DS_Event(int type) { - if(!fsSynth) return; + if (!fsSynth) return; - if(type == SFXEV_END) + if (type == SFXEV_END) { // End of frame, do an update. DMFluid_Update(); @@ -134,14 +136,14 @@ int DS_Set(int prop, const void* ptr) { - //if(!fmodSystem) return false; + //if (!fmodSystem) return false; - switch(prop) + switch (prop) { case AUDIOP_SOUNDFONT_FILENAME: { const char* path = reinterpret_cast(ptr); DSFLUIDSYNTH_TRACE("DS_Set: Soundfont = " << path); - if(!path || !strlen(path)) + if (!path || !strlen(path)) { // Use the default. path = 0; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/src/fluidsynth_music.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/src/fluidsynth_music.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fluidsynth/src/fluidsynth_music.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fluidsynth/src/fluidsynth_music.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -86,7 +86,7 @@ Sys_Lock(_mutex); int avail; - if(_writePos >= _readPos) + if (_writePos >= _readPos) { avail = _writePos - _readPos; } @@ -108,11 +108,11 @@ // No need to split? const int remainder = _end - _writePos; - if(length <= remainder) + if (length <= remainder) { memcpy(_writePos, data, length); _writePos += length; - if(_writePos == _end) _writePos = _buf; // May wrap around. + if (_writePos == _end) _writePos = _buf; // May wrap around. } else { @@ -144,11 +144,11 @@ length = MIN_OF(length, avail); const int remainder = _end - _readPos; - if(length <= remainder) + if (length <= remainder) { memcpy(data, _readPos, length); _readPos += length; - if(_readPos == _end) _readPos = _buf; // May wrap around. + if (_readPos == _end) _readPos = _buf; // May wrap around. } else { @@ -173,7 +173,7 @@ }; static RingBuffer* blockBuffer; -static float musicVolume; +static float musicVolume = 1.0f; /** * Thread entry point for the synthesizer. Runs until the song is stopped. @@ -187,9 +187,9 @@ byte samples[BLOCK_SIZE]; - while(!workerShouldStop) + while (!workerShouldStop) { - if(blockBuffer->availableForWriting() < BLOCK_SIZE) + if (blockBuffer->availableForWriting() < BLOCK_SIZE) { // We should not or cannot produce samples right now, let's sleep for a while. Thread_Sleep(50); @@ -225,7 +225,7 @@ DENG_UNUSED(buf); DENG_ASSERT(buf == sfxBuf); - if(blockBuffer->availableForReading() >= int(size)) + if (blockBuffer->availableForReading() >= int(size)) { //DSFLUIDSYNTH_TRACE("Streaming out " << size << " bytes."); blockBuffer->read(data, size); @@ -252,7 +252,7 @@ */ static void startPlayer() { - if(DMFluid_Driver()) return; + if (DMFluid_Driver()) return; DENG_ASSERT(!worker); DENG_ASSERT(sfxBuf == NULL); @@ -285,7 +285,7 @@ { DENG_ASSERT(DMFluid_Driver() == NULL); - if(worker) + if (worker) { DSFLUIDSYNTH_TRACE("stopWorker: Stopping thread " << worker); @@ -300,18 +300,18 @@ static void stopPlayer() { DSFLUIDSYNTH_TRACE("stopPlayer: fsPlayer " << fsPlayer); - if(!fsPlayer) return; + if (!fsPlayer) return; - if(!DMFluid_Driver()) + if (!DMFluid_Driver()) { + stopWorker(); + // Destroy the sfx buffer. DENG_ASSERT(sfxBuf != 0); DSFLUIDSYNTH_TRACE("stopPlayer: Destroying SFX buffer " << sfxBuf); DMFluid_Sfx()->Destroy(sfxBuf); sfxBuf = 0; - - stopWorker(); } delete_fluid_player(fsPlayer); @@ -324,7 +324,7 @@ int DM_Music_Init(void) { - if(blockBuffer) return true; + if (blockBuffer) return true; musicVolume = 1.f; blockBuffer = new RingBuffer(MAX_BLOCKS * BLOCK_SIZE); @@ -333,13 +333,13 @@ void DMFluid_Shutdown(void) { - if(!blockBuffer) return; + if (!blockBuffer) return; stopPlayer(); delete blockBuffer; blockBuffer = 0; - if(fsPlayer) + if (fsPlayer) { delete_fluid_player(fsPlayer); fsPlayer = 0; @@ -355,18 +355,18 @@ void DMFluid_SetSoundFont(const char* fileName) { - if(sfontId >= 0) + if (sfontId >= 0) { // First unload the previous font. fluid_synth_sfunload(DMFluid_Synth(), sfontId, false); sfontId = -1; } - if(!fileName) return; + if (!fileName) return; // Load the new one. sfontId = fluid_synth_sfload(DMFluid_Synth(), fileName, true); - if(sfontId >= 0) + if (sfontId >= 0) { App_Log(DE2_LOG_VERBOSE, "FluidSynth: Loaded SF2 soundfont \"%s\" with id:%i", fileName, sfontId); } @@ -378,18 +378,14 @@ void DM_Music_Set(int prop, float value) { - switch(prop) + switch (prop) { case MUSIP_VOLUME: musicVolume = value; - if(sfxBuf) + if (sfxBuf) { DMFluid_Sfx()->Set(sfxBuf, SFXBP_VOLUME, musicVolume); } - else if(DMFluid_Driver()) - { - fluid_synth_set_gain(DMFluid_Synth(), MAX_SYNTH_GAIN * musicVolume); - } DSFLUIDSYNTH_TRACE("Music_Set: MUSIP_VOLUME = " << musicVolume); break; @@ -400,10 +396,10 @@ int DM_Music_Get(int prop, void* ptr) { - switch(prop) + switch (prop) { case MUSIP_ID: - if(ptr) + if (ptr) { strcpy((char*) ptr, "FluidSynth/Ext (MIDI only)"); return true; @@ -411,7 +407,7 @@ break; case MUSIP_PLAYING: { - if(!fsPlayer) return false; + if (!fsPlayer) return false; int playing = (fluid_player_get_status(fsPlayer) == FLUID_PLAYER_PLAYING); DSFLUIDSYNTH_TRACE("Music_Get: MUSIP_PLAYING = " << playing); return playing; @@ -444,9 +440,9 @@ void DM_Music_Pause(int setPause) { - if(!fsPlayer || !sfxBuf) return; + if (!fsPlayer || !sfxBuf) return; - if(setPause) + if (setPause) { DMFluid_Sfx()->Stop(sfxBuf); DSFLUIDSYNTH_TRACE("Song paused."); @@ -460,18 +456,27 @@ int DM_Music_PlayFile(const char *filename, int looped) { - if(!filename) return false; + if (!filename) return false; + +#if defined (WIN32) + // Using MinGW. + QString pathStr = filename; + pathStr.replace("\\", "/"); + QByteArray const path = pathStr.toUtf8(); +#else + QByteArray const path = filename; +#endif - if(!fluid_is_midifile(filename)) + if (!fluid_is_midifile(path)) { // It doesn't look like MIDI. - App_Log(DE2_LOG_VERBOSE, "[FluidSynth] Cannot play \"%s\": not a MIDI file", filename); + App_Log(DE2_LOG_VERBOSE, "[FluidSynth] Cannot play \"%s\": not a MIDI file", path.constData()); return false; } - if(sfontId < 0) + if (sfontId < 0) { - App_Log(DE2_LOG_VERBOSE, "[FluidSynth] Cannot play \"%s\" without an SF2 soundfont", filename); + App_Log(DE2_LOG_VERBOSE, "[FluidSynth] Cannot play \"%s\" without an SF2 soundfont", path.constData()); return false; } @@ -482,13 +487,13 @@ // Create a new player. fsPlayer = new_fluid_player(DMFluid_Synth()); - fluid_player_add(fsPlayer, filename); + fluid_player_add(fsPlayer, path); fluid_player_set_loop(fsPlayer, looped? -1 /*infinite times*/ : 1); fluid_player_play(fsPlayer); startPlayer(); - DSFLUIDSYNTH_TRACE("PlayFile: playing '" << filename << "' using player " + DSFLUIDSYNTH_TRACE("PlayFile: playing '" << path.constData() << "' using player " << fsPlayer << " looped:" << looped << " sfont:" << sfontId); return true; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/api/audio_fmod.def doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/api/audio_fmod.def --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/api/audio_fmod.def 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/api/audio_fmod.def 2018-12-11 07:08:22.000000000 +0000 @@ -39,10 +39,10 @@ DM_Music_PlayFile ; CD audio interface -DM_CDAudio_Init -DM_CDAudio_Update -DM_CDAudio_Set -DM_CDAudio_Get -DM_CDAudio_Pause -DM_CDAudio_Stop -DM_CDAudio_Play +;DM_CDAudio_Init +;DM_CDAudio_Update +;DM_CDAudio_Set +;DM_CDAudio_Get +;DM_CDAudio_Pause +;DM_CDAudio_Stop +;DM_CDAudio_Play diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/include/driver_fmod.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/include/driver_fmod.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/include/driver_fmod.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/include/driver_fmod.h 2018-12-11 07:08:22.000000000 +0000 @@ -72,7 +72,7 @@ LOGDEV_AUDIO_WARNING("[FMOD] Error at %s, line %i: (%d) %s") << __FILE__ << __LINE__ << result << FMOD_ErrorString(result); \ } -extern FMOD::System* fmodSystem; +extern FMOD::System *fmodSystem; #include "fmod_sfx.h" #include "fmod_music.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/include/fmod_cd.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/include/fmod_cd.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/include/fmod_cd.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/include/fmod_cd.h 2018-12-11 07:08:22.000000000 +0000 @@ -44,6 +44,8 @@ #include "api_audiod_mus.h" +#if 0 + #ifdef __cplusplus extern "C" { #endif @@ -63,5 +65,6 @@ // Internal: void DMFmod_CDAudio_Shutdown(void); +#endif #endif /* end of include guard: __FMOD_CD_H__ */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/res/audio_fmod.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/res/audio_fmod.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/res/audio_fmod.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/res/audio_fmod.rc 2018-12-11 07:08:22.000000000 +0000 @@ -3,8 +3,8 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2011 Daniel Swanson - *\author Copyright © 2011-2017 Jaakko Keränen + *\author Copyright (c) 2008-2011 Daniel Swanson + *\author Copyright (c) 2011-2018 Jaakko Keränen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -81,7 +81,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsFMOD.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -119,7 +119,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "dsFMOD.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/driver_fmod.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/driver_fmod.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/driver_fmod.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/driver_fmod.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -1,12 +1,12 @@ /** * @file driver_fmod.cpp - * FMOD Ex audio plugin. @ingroup dsfmod + * FMOD Studio low-level audio plugin. @ingroup dsfmod * * @authors Copyright © 2011-2017 Jaakko Keränen * * @par License * GPL: http://www.gnu.org/licenses/gpl.html (with exception granted to allow - * linking against FMOD Ex) + * linking against FMOD Studio) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by the @@ -19,14 +19,14 @@ * http://www.gnu.org/licenses * * Special Exception to GPLv2: - * Linking the Doomsday Audio Plugin for FMOD Ex (audio_fmod) statically or + * Linking the Doomsday Audio Plugin for FMOD Studio (audio_fmod) statically or * dynamically with other modules is making a combined work based on * audio_fmod. Thus, the terms and conditions of the GNU General Public License * cover the whole combination. In addition, as a special exception, the * copyright holders of audio_fmod give you permission to combine audio_fmod * with free software programs or libraries that are released under the GNU - * LGPL and with code included in the standard release of "FMOD Ex Programmer's - * API" under the "FMOD Ex Programmer's API" license (or modified versions of + * LGPL and with code included in the standard release of "FMOD Studio Programmer's + * API" under the "FMOD Studio Programmer's API" license (or modified versions of * such code, with unchanged license). You may copy and distribute such a * system following the terms of the GNU GPL for audio_fmod and the licenses of * the other code concerned, provided that you include the source code of that @@ -49,16 +49,49 @@ #include "doomsday.h" #include +#include #include +#include #include +#include +#include -FMOD::System* fmodSystem = 0; +FMOD::System *fmodSystem = 0; + +struct Driver +{ + de::String name; + FMOD_GUID guid; + int systemRate; + FMOD_SPEAKERMODE speakerMode; + int speakerModeChannels; +}; +static QVector fmodDrivers; + +static const char *speakerModeText(FMOD_SPEAKERMODE mode) +{ + switch (mode) + { + case FMOD_SPEAKERMODE_DEFAULT: return "Default"; + case FMOD_SPEAKERMODE_RAW: return "Raw"; + case FMOD_SPEAKERMODE_MONO: return "Mono"; + case FMOD_SPEAKERMODE_STEREO: return "Stereo"; + case FMOD_SPEAKERMODE_QUAD: return "Quad"; + case FMOD_SPEAKERMODE_SURROUND: return "Surround"; + case FMOD_SPEAKERMODE_5POINT1: return "5.1"; + case FMOD_SPEAKERMODE_7POINT1: return "7.1"; + default: break; + } + return ""; +} /** - * Initialize the FMOD Ex sound driver. + * Initialize the FMOD Studio low-level sound driver. */ int DS_Init(void) { + using namespace de; + if (fmodSystem) { return true; // Already initialized. @@ -73,6 +106,51 @@ return false; } + // Print the credit required by FMOD license. + LOG_AUDIO_NOTE("FMOD by Firelight Technologies Pty Ltd"); + + // Check what kind of drivers are available. + { + int numDrivers = 0; + fmodSystem->getNumDrivers(&numDrivers); + fmodDrivers.resize(numDrivers); + std::unique_ptr names(new de::ArrayValue); + for (int i = 0; i < numDrivers; ++i) + { + auto &drv = fmodDrivers[i]; + char nameBuf[512]; + zap(nameBuf); + fmodSystem->getDriverInfo(i, nameBuf, sizeof(nameBuf), + &drv.guid, &drv.systemRate, + &drv.speakerMode, &drv.speakerModeChannels); + drv.name = String::format("%s (%s)", nameBuf, speakerModeText(drv.speakerMode)); + names->add(TextValue(drv.name)); + + LOG_AUDIO_MSG("FMOD driver %i: \"%s\" Rate:%iHz Mode:%s Channels:%i") + << i << drv.name + << drv.systemRate + << speakerModeText(drv.speakerMode) + << drv.speakerModeChannels; + } + ScriptSystem::get()["Audio"]["outputs"].value() + .add(new TextValue("fmod"), names.release()); + } + + // Select the configured driver. + { + int configuredDriverIndex = Config::get().geti("audio.output", 0); + if (configuredDriverIndex < fmodDrivers.size()) + { + result = fmodSystem->setDriver(configuredDriverIndex); + if (result != FMOD_OK) + { + LOG_AUDIO_ERROR("Failed to select FMOD audio driver: %s") + << fmodDrivers[configuredDriverIndex].name; + } + } + } + +#if 0 #ifdef WIN32 { // Figure out the system's configured default speaker mode. @@ -112,9 +190,12 @@ { fmodSystem->setSpeakerMode(FMOD_SPEAKERMODE_SRS5_1_MATRIX); } +#endif // Initialize FMOD. - if ((result = fmodSystem->init(50, FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_HRTF_LOWPASS, 0)) != FMOD_OK) + if ((result = fmodSystem->init( + 50, FMOD_INIT_NORMAL | FMOD_INIT_3D_RIGHTHANDED | FMOD_INIT_CHANNEL_LOWPASS, 0)) != + FMOD_OK) { LOGDEV_AUDIO_ERROR("FMOD init failed: (%d) %s") << result << FMOD_ErrorString(result); fmodSystem->release(); @@ -124,7 +205,8 @@ // Options. FMOD_ADVANCEDSETTINGS settings; - zeroStruct(settings); + de::zap(settings); + settings.cbSize = sizeof(settings); settings.HRTFMaxAngle = 360; settings.HRTFMinAngle = 180; settings.HRTFFreq = 11000; @@ -149,9 +231,6 @@ } #endif - // Print the credit required by FMOD license. - LOG_AUDIO_NOTE("FMOD Sound System (c) Firelight Technologies Pty, Ltd., 1994-2013"); - LOGDEV_AUDIO_VERBOSE("[FMOD] Initialized"); return true; } @@ -162,7 +241,7 @@ void DS_Shutdown(void) { DMFmod_Music_Shutdown(); - DMFmod_CDAudio_Shutdown(); + //DMFmod_CDAudio_Shutdown(); DSFMOD_TRACE("DS_Shutdown."); fmodSystem->release(); @@ -211,13 +290,52 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C const char* deng_LibraryType(void) +DENG_ENTRYPOINT const char* deng_LibraryType(void) { return "deng-plugin/audio"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_audio_fmod_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DS_Init) + DENG_SYMBOL_PTR(name, DS_Shutdown) + DENG_SYMBOL_PTR(name, DS_Event) + DENG_SYMBOL_PTR(name, DS_Set) + DENG_SYMBOL_PTR(name, DS_SFX_Init) + DENG_SYMBOL_PTR(name, DS_SFX_CreateBuffer) + DENG_SYMBOL_PTR(name, DS_SFX_DestroyBuffer) + DENG_SYMBOL_PTR(name, DS_SFX_Load) + DENG_SYMBOL_PTR(name, DS_SFX_Reset) + DENG_SYMBOL_PTR(name, DS_SFX_Play) + DENG_SYMBOL_PTR(name, DS_SFX_Stop) + DENG_SYMBOL_PTR(name, DS_SFX_Refresh) + DENG_SYMBOL_PTR(name, DS_SFX_Set) + DENG_SYMBOL_PTR(name, DS_SFX_Setv) + DENG_SYMBOL_PTR(name, DS_SFX_Listener) + DENG_SYMBOL_PTR(name, DS_SFX_Listenerv) + DENG_SYMBOL_PTR(name, DS_SFX_Getv) + DENG_SYMBOL_PTR(name, DM_Music_Init) + DENG_SYMBOL_PTR(name, DM_Music_Update) + DENG_SYMBOL_PTR(name, DM_Music_Get) + DENG_SYMBOL_PTR(name, DM_Music_Set) + DENG_SYMBOL_PTR(name, DM_Music_Pause) + DENG_SYMBOL_PTR(name, DM_Music_Stop) + DENG_SYMBOL_PTR(name, DM_Music_SongBuffer) + DENG_SYMBOL_PTR(name, DM_Music_Play) + DENG_SYMBOL_PTR(name, DM_Music_PlayFile) + qWarning() << name << "not found in audio_fmod"; + return nullptr; +} + +#else + DENG_DECLARE_API(Con); DENG_API_EXCHANGE( DENG_GET_API(DE_API_CONSOLE, Con); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_cd.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_cd.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_cd.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_cd.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -38,6 +38,8 @@ * exception.) */ +#if 0 + #include "driver_fmod.h" #include @@ -207,3 +209,6 @@ cdSound->release(); cdSound = nullptr; } } + +#endif + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_music.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_music.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_music.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_music.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -66,15 +66,20 @@ static std::string soundFontFileName; static FMOD_RESULT F_CALLBACK -musicCallback(FMOD_CHANNEL* chanPtr, FMOD_CHANNEL_CALLBACKTYPE type, - void* /*commanddata1*/, void* /*commanddata2*/) +musicCallback(FMOD_CHANNELCONTROL *channelcontrol, + FMOD_CHANNELCONTROL_TYPE controltype, + FMOD_CHANNELCONTROL_CALLBACK_TYPE callbacktype, + void * /*commanddata1*/, void * /*commanddata2*/) { - if(reinterpret_cast(chanPtr) != music) + if (controltype != FMOD_CHANNELCONTROL_CHANNEL) + return FMOD_OK; + + if (reinterpret_cast(channelcontrol) != music) return FMOD_OK; // Safety check. - switch(type) + switch (callbacktype) { - case FMOD_CHANNEL_CALLBACKTYPE_END: + case FMOD_CHANNELCONTROL_CALLBACK_END: // The music has stopped. music = 0; break; @@ -87,9 +92,9 @@ static void releaseSong() { - if(song) + if (song) { - if(needReleaseSong) + if (needReleaseSong) { DSFMOD_TRACE("releaseSong: Song " << song << " will be released."); song->release(); @@ -106,7 +111,7 @@ static void releaseSongBuffer() { - if(songBuffer) + if (songBuffer) { delete songBuffer; songBuffer = 0; @@ -115,7 +120,7 @@ void setDefaultStreamBufferSize() { - if(!fmodSystem) return; + if (!fmodSystem) return; FMOD_RESULT result; result = fmodSystem->setStreamBufferSize(16*1024, FMOD_TIMEUNIT_RAWBYTES); @@ -135,7 +140,7 @@ void DMFmod_Music_Shutdown(void) { - if(!fmodSystem) return; + if (!fmodSystem) return; releaseSongBuffer(); releaseSong(); @@ -154,7 +159,7 @@ /// @internal void DMFmod_Music_SetSoundFont(char const *fileName) { - if(fileName && fileName[0]) + if (fileName && fileName[0]) { soundFontFileName = fileName; } @@ -166,14 +171,14 @@ void DMFmod_Music_Set(int prop, float value) { - if(!fmodSystem) + if (!fmodSystem) return; - switch(prop) + switch (prop) { case MUSIP_VOLUME: musicVolume = value; - if(music) music->setVolume(musicVolume); + if (music) music->setVolume(musicVolume); DSFMOD_TRACE("Music_Set: MUSIP_VOLUME = " << musicVolume); break; @@ -189,10 +194,10 @@ int DMFmod_Music_Get(int prop, void* ptr) { - switch(prop) + switch (prop) { case MUSIP_ID: - if(ptr) + if (ptr) { strcpy((char*) ptr, "FMOD/Ext"); return true; @@ -200,7 +205,7 @@ break; case MUSIP_PLAYING: - if(!fmodSystem) return false; + if (!fmodSystem) return false; return music != 0; // NULL when not playing. default: @@ -222,7 +227,7 @@ void DMFmod_Music_Stop(void) { - if(!fmodSystem || !music) return; + if (!fmodSystem || !music) return; DSFMOD_TRACE("Music_Stop."); @@ -236,13 +241,13 @@ static bool startSong() { - if(!fmodSystem || !song) return false; + if (!fmodSystem || !song) return false; - if(music) music->stop(); + if (music) music->stop(); // Start playing the song. FMOD_RESULT result; - result = fmodSystem->playSound(FMOD_CHANNEL_FREE, song, true, &music); + result = fmodSystem->playSound(song, nullptr, true, &music); DSFMOD_ERRCHECK(result); // Properties. @@ -268,9 +273,9 @@ int DM_Music_Play(int looped) { - if(!fmodSystem) return false; + if (!fmodSystem) return false; - if(songBuffer) + if (songBuffer) { // Get rid of the old song. releaseSong(); @@ -280,7 +285,7 @@ FMOD_CREATESOUNDEXINFO extra; zeroStruct(extra); extra.length = songBuffer->size; - if(endsWith(soundFontFileName.c_str(), ".dls")) + if (endsWith(soundFontFileName.c_str(), ".dls")) { extra.dlsname = soundFontFileName.c_str(); } @@ -303,7 +308,7 @@ void DMFmod_Music_Pause(int setPause) { - if(!fmodSystem || !music) return; + if (!fmodSystem || !music) return; music->setPaused(setPause != 0); } @@ -315,7 +320,7 @@ void* DM_Music_SongBuffer(unsigned int length) { - if(!fmodSystem) return NULL; + if (!fmodSystem) return NULL; releaseSongBuffer(); @@ -329,7 +334,7 @@ int DM_Music_PlayFile(const char *filename, int looped) { - if(!fmodSystem) return false; + if (!fmodSystem) return false; // Get rid of the current song. releaseSong(); @@ -339,7 +344,7 @@ FMOD_CREATESOUNDEXINFO extra; zeroStruct(extra); - if(endsWith(soundFontFileName.c_str(), ".dls")) + if (endsWith(soundFontFileName.c_str(), ".dls")) { extra.dlsname = soundFontFileName.c_str(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_sfx.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_sfx.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/fmod/src/fmod_sfx.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/fmod/src/fmod_sfx.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -74,7 +74,7 @@ * @param newMode @c true, if the channel should be head-relative. */ void setRelativeMode(bool newMode) { - if(newMode) { + if (newMode) { mode &= ~FMOD_3D_WORLDRELATIVE; mode |= FMOD_3D_HEADRELATIVE; } @@ -82,7 +82,7 @@ mode |= FMOD_3D_WORLDRELATIVE; mode &= ~FMOD_3D_HEADRELATIVE; } - if(channel) channel->setMode(mode); + if (channel) channel->setMode(mode); } }; @@ -123,7 +123,7 @@ const char* sfxPropToString(int prop) { - switch(prop) + switch (prop) { case SFXBP_VOLUME: return "SFXBP_VOLUME"; case SFXBP_FREQUENCY: return "SFXBP_FREQUENCY"; @@ -143,20 +143,26 @@ return *reinterpret_cast(buf->ptr); } -static FMOD_RESULT F_CALLBACK channelCallback(FMOD_CHANNEL* chanPtr, - FMOD_CHANNEL_CALLBACKTYPE type, - void* /*commanddata1*/, - void* /*commanddata2*/) +static FMOD_RESULT F_CALLBACK channelCallback(FMOD_CHANNELCONTROL *channelcontrol, + FMOD_CHANNELCONTROL_TYPE controltype, + FMOD_CHANNELCONTROL_CALLBACK_TYPE callbacktype, + void *, + void *) { - FMOD::Channel *channel = reinterpret_cast(chanPtr); + if (controltype != FMOD_CHANNELCONTROL_CHANNEL) + { + return FMOD_OK; + } + + FMOD::Channel *channel = reinterpret_cast(channelcontrol); sfxbuffer_t *buf = 0; - switch(type) + switch (callbacktype) { - case FMOD_CHANNEL_CALLBACKTYPE_END: + case FMOD_CHANNELCONTROL_CALLBACK_END: // The sound has ended, mark the channel. - channel->getUserData(reinterpret_cast(&buf)); - if(buf) + channel->getUserData(reinterpret_cast(&buf)); + if (buf) { LOGDEV_AUDIO_XVERBOSE("[FMOD] channelCallback: sfxbuffer %p stops", buf); buf->flags &= ~SFXBF_PLAYING; @@ -220,15 +226,17 @@ free(buf); } +#if 0 static void toSigned8bit(const unsigned char* source, int size, RawSamplePCM8& output) { output.clear(); output.resize(size); - for(int i = 0; i < size; ++i) + for (int i = 0; i < size; ++i) { output[i] = char(source[i]) - 128; } } +#endif static FMOD_RESULT F_CALLBACK pcmReadCallback(FMOD_SOUND* soundPtr, void* data, unsigned int datalen) { @@ -267,7 +275,7 @@ */ void DS_SFX_Load(sfxbuffer_t* buf, struct sfxsample_s* sample) { - if(!fmodSystem || !buf || !sample) return; + if (!fmodSystem || !buf || !sample) return; bool streaming = (buf->flags & SFXBF_STREAM) != 0; @@ -289,7 +297,7 @@ buf << sample->size << sample->rate << sample->bytesPer); // If it has a sample, release it later. - if(info.sound) + if (info.sound) { DENG2_GUARD(streams); LOGDEV_AUDIO_XVERBOSE("[FMOD] SFX_Load: Releasing buffer's old Sound %p", info.sound); @@ -297,19 +305,18 @@ streams.value.erase(info.sound); } - RawSamplePCM8 signConverted; + //RawSamplePCM8 signConverted; const char* sampleData = reinterpret_cast(sample->data); - if(!streaming) + if (!streaming) { - if(sample->bytesPer == 1) + /*if (sample->bytesPer == 1) { // Doomsday gives us unsigned 8-bit audio samples. toSigned8bit(reinterpret_cast(sample->data), sample->size, signConverted); sampleData = &signConverted[0]; - } + }*/ info.mode = FMOD_OPENMEMORY | FMOD_OPENRAW | - FMOD_HARDWARE | (buf->flags & SFXBF_3D? FMOD_3D : FMOD_2D) | (buf->flags & SFXBF_REPEAT? FMOD_LOOP_NORMAL : 0); } @@ -317,7 +324,6 @@ { info.mode = FMOD_OPENUSER | FMOD_CREATESTREAM | - FMOD_HARDWARE | FMOD_LOOP_NORMAL; params.numchannels = 2; /// @todo Make this configurable. @@ -326,7 +332,7 @@ params.pcmreadcallback = pcmReadCallback; sampleData = 0; // will be streamed } - if(buf->flags & SFXBF_3D) + if (buf->flags & SFXBF_3D) { info.mode |= FMOD_3D_WORLDRELATIVE; } @@ -338,7 +344,7 @@ LOGDEV_AUDIO_XVERBOSE("[FMOD] SFX_Load: created Sound %p%s", info.sound << (streaming? " as streaming" : "")); - if(streaming) + if (streaming) { DENG2_GUARD(streams); // Keep a record of the playing stream for the PCM read callback. @@ -366,7 +372,7 @@ */ void DS_SFX_Reset(sfxbuffer_t* buf) { - if(!buf) + if (!buf) return; LOGDEV_AUDIO_XVERBOSE("[FMOD] SFX_Reset: sfxbuffer %p", buf); @@ -376,14 +382,14 @@ buf->flags &= ~SFXBF_RELOAD; BufferInfo& info = bufferInfo(buf); - if(info.sound) + if (info.sound) { DENG2_GUARD(streams); LOGDEV_AUDIO_XVERBOSE("[FMOD] SFX_Reset: releasing Sound %p", info.sound); info.sound->release(); streams.value.erase(info.sound); } - if(info.channel) + if (info.channel) { info.channel->setCallback(0); info.channel->setUserData(0); @@ -395,17 +401,17 @@ void DS_SFX_Play(sfxbuffer_t* buf) { // Playing is quite impossible without a sample. - if(!buf || !buf->sample) + if (!buf || !buf->sample) return; BufferInfo& info = bufferInfo(buf); assert(info.sound != 0); FMOD_RESULT result; - result = fmodSystem->playSound(FMOD_CHANNEL_FREE, info.sound, true, &info.channel); + result = fmodSystem->playSound(info.sound, nullptr, true, &info.channel); DSFMOD_ERRCHECK(result); - if(!info.channel) return; + if (!info.channel) return; // Set the properties of the sound. info.channel->setPan(info.pan); @@ -413,7 +419,7 @@ info.channel->setVolume(info.volume); info.channel->setUserData(buf); info.channel->setCallback(channelCallback); - if(buf->flags & SFXBF_3D) + if (buf->flags & SFXBF_3D) { // 3D properties. info.channel->set3DMinMaxDistance(info.minDistanceMeters, @@ -476,42 +482,42 @@ */ void DS_SFX_Set(sfxbuffer_t* buf, int prop, float value) { - if(!buf) + if (!buf) return; BufferInfo& info = bufferInfo(buf); - switch(prop) + switch (prop) { case SFXBP_VOLUME: - if(FEQUAL(info.volume, value)) return; // No change. + if (FEQUAL(info.volume, value)) return; // No change. assert(value >= 0); info.volume = value; - if(info.channel) info.channel->setVolume(info.volume); + if (info.channel) info.channel->setVolume(info.volume); break; case SFXBP_FREQUENCY: { unsigned int newFreq = (unsigned int) (buf->rate * value); - if(buf->freq == newFreq) return; // No change. + if (buf->freq == newFreq) return; // No change. buf->freq = newFreq; - if(info.channel) info.channel->setFrequency(float(buf->freq)); + if (info.channel) info.channel->setFrequency(float(buf->freq)); break; } case SFXBP_PAN: - if(FEQUAL(info.pan, value)) return; // No change. + if (FEQUAL(info.pan, value)) return; // No change. info.pan = value; - if(info.channel) info.channel->setPan(info.pan); + if (info.channel) info.channel->setPan(info.pan); break; case SFXBP_MIN_DISTANCE: info.minDistanceMeters = value; - if(info.channel) info.channel->set3DMinMaxDistance(info.minDistanceMeters, + if (info.channel) info.channel->set3DMinMaxDistance(info.minDistanceMeters, info.maxDistanceMeters); break; case SFXBP_MAX_DISTANCE: info.maxDistanceMeters = value; - if(info.channel) info.channel->set3DMinMaxDistance(info.minDistanceMeters, + if (info.channel) info.channel->set3DMinMaxDistance(info.minDistanceMeters, info.maxDistanceMeters); break; @@ -535,20 +541,20 @@ */ void DS_SFX_Setv(sfxbuffer_t* buf, int prop, float* values) { - if(!fmodSystem || !buf) return; + if (!fmodSystem || !buf) return; BufferInfo& info = bufferInfo(buf); - switch(prop) + switch (prop) { case SFXBP_POSITION: info.position.set(values); - if(info.channel) info.channel->set3DAttributes(&info.position, &info.velocity); + if (info.channel) info.channel->set3DAttributes(&info.position, &info.velocity); break; case SFXBP_VELOCITY: info.velocity.set(values); - if(info.channel) info.channel->set3DAttributes(&info.position, &info.velocity); + if (info.channel) info.channel->set3DAttributes(&info.position, &info.velocity); break; default: @@ -563,7 +569,7 @@ */ void DS_SFX_Listener(int prop, float value) { - switch(prop) + switch (prop) { case SFXLP_UNITS_PER_METER: unitsPerMeter = value; @@ -589,87 +595,103 @@ } /** - * Convert linear volume 0..1 to logarithmic -10000..0. + * Convert linear volume 0..1 to a logarithmic range. */ -static int linearToLog(float vol) +static float linearToLog(float linear) { - if(vol <= 0) return -10000; - if(vol >= 1) return 0; + return 10.f * std::log10(linear); +} - // Straighten the volume curve. - return std::min(std::max(-10000, (int) (100 * 20 * std::log10(vol))), 0); +/** + * Convert dB value to a linear 0..1 value. + */ +static float logToLinear(float db) +{ + return std::pow(10.f, db/10.f); } +//static float scaleLogarithmic(float db, float scale, de::Rangef const &range) +//{ +// return range.clamp(linearToLog(scale * logToLinear(db))); +//} + /** * Update the ambient reverb properties. * * @param reverb Array of NUM_REVERB_DATA parameters (see SRD_*). */ -static void updateListenerEnvironmentSettings(float* reverb) +static void updateListenerEnvironmentSettings(float *reverb) { - if(!fmodSystem || !reverb) return; + if (!fmodSystem || !reverb) return; DSFMOD_TRACE("updateListenerEnvironmentSettings: " << reverb[0] << " " << reverb[1] << " " << reverb[2] << " " << reverb[3]); // No reverb? - if(reverb[SFXLP_REVERB_VOLUME] == 0 && reverb[SFXLP_REVERB_SPACE] == 0 && - reverb[SFXLP_REVERB_DECAY] == 0 && reverb[SFXLP_REVERB_DAMPING] == 0) + if (reverb[SFXLP_REVERB_VOLUME] == 0 && reverb[SFXLP_REVERB_SPACE] == 0 && + reverb[SFXLP_REVERB_DECAY] == 0 && reverb[SFXLP_REVERB_DAMPING] == 0) { FMOD_REVERB_PROPERTIES noReverb = FMOD_PRESET_OFF; - fmodSystem->setReverbAmbientProperties(&noReverb); + fmodSystem->setReverbProperties(0, &noReverb); return; } - const static FMOD_REVERB_PROPERTIES presetPlain = FMOD_PRESET_PLAIN; - const static FMOD_REVERB_PROPERTIES presetConcertHall = FMOD_PRESET_CONCERTHALL; - const static FMOD_REVERB_PROPERTIES presetAuditorium = FMOD_PRESET_AUDITORIUM; - const static FMOD_REVERB_PROPERTIES presetCave = FMOD_PRESET_CAVE; - const static FMOD_REVERB_PROPERTIES presetGeneric = FMOD_PRESET_GENERIC; - const static FMOD_REVERB_PROPERTIES presetRoom = FMOD_PRESET_ROOM; + static FMOD_REVERB_PROPERTIES const presetPlain = FMOD_PRESET_PLAIN; + static FMOD_REVERB_PROPERTIES const presetConcertHall = FMOD_PRESET_CONCERTHALL; + static FMOD_REVERB_PROPERTIES const presetAuditorium = FMOD_PRESET_AUDITORIUM; + static FMOD_REVERB_PROPERTIES const presetCave = FMOD_PRESET_CAVE; + static FMOD_REVERB_PROPERTIES const presetGeneric = FMOD_PRESET_GENERIC; + static FMOD_REVERB_PROPERTIES const presetRoom = FMOD_PRESET_ROOM; float space = reverb[SFXLP_REVERB_SPACE]; - if(reverb[SFXLP_REVERB_DECAY] > .5) + if (reverb[SFXLP_REVERB_DECAY] > .5) { // This much decay needs at least the Generic environment. - if(space < .2) + if (space < .2) space = .2f; } // Choose a preset based on the size of the space. FMOD_REVERB_PROPERTIES props; - if(space >= 1) + if (space >= 1) props = presetPlain; - else if(space >= .8) + else if (space >= .8) props = presetConcertHall; - else if(space >= .6) + else if (space >= .6) props = presetAuditorium; - else if(space >= .4) + else if (space >= .4) props = presetCave; - else if(space >= .2) + else if (space >= .2) props = presetGeneric; else props = presetRoom; // Overall reverb volume adjustment. - props.Room = linearToLog(reverb[SFXLP_REVERB_VOLUME]); + //props.WetLevel = scaleLogarithmic(props.WetLevel, reverb[SFXLP_REVERB_VOLUME], de::Rangef(-80.f, 0.f)); + props.WetLevel = de::Rangef(-80.f, 0.f).clamp(linearToLog((logToLinear(props.WetLevel) + reverb[SFXLP_REVERB_VOLUME])/6.f)); //setEAXdw(DSPROPERTY_EAXLISTENER_ROOM, volLinearToLog(rev[SFXLP_REVERB_VOLUME])); // Reverb decay. - float decay = (reverb[SFXLP_REVERB_DECAY] - .5f) * 1.5f + 1; - props.DecayTime = std::min(std::max(0.1f, props.DecayTime * decay), 20.f); + float const decayFactor = 1.f + (reverb[SFXLP_REVERB_DECAY] - .5f) * 1.5f; + props.DecayTime = std::min(std::max(100.f, props.DecayTime * decayFactor), 20000.f); //mulEAXf(DSPROPERTY_EAXLISTENER_DECAYTIME, val, EAXLISTENER_MINDECAYTIME, EAXLISTENER_MAXDECAYTIME); // Damping. - float damping = std::max(.1f, 1.1f * (1.2f - reverb[SFXLP_REVERB_DAMPING])); - props.RoomHF = linearToLog(std::pow(10.f, props.RoomHF / 2000.f) * damping); + //props.HighCut = de::Rangef(20, 20000).clamp(20000 * std::pow(1.f - reverb[SFXLP_REVERB_DAMPING], 2.f)); + props.HighCut = de::Rangef(20, 20000).clamp(props.HighCut * std::pow(1.f - reverb[SFXLP_REVERB_DAMPING], 2.f)); + //float const damping = std::max(.1f, 1.1f * (1.2f - reverb[SFXLP_REVERB_DAMPING])); + //props.RoomHF = linearToLog(std::pow(10.f, props.RoomHF / 2000.f) * damping); //mulEAXdw(DSPROPERTY_EAXLISTENER_ROOMHF, val); + qDebug() << "WetLevel:" << props.WetLevel << "dB" << "input:" << reverb[SFXLP_REVERB_VOLUME] + << "DecayTime:" << props.DecayTime << "ms" + << "HighCut:" << props.HighCut << "Hz"; + // A slightly increased roll-off. (Not in FMOD?) //props.RoomRolloffFactor = 1.3f; - fmodSystem->setReverbAmbientProperties(&props); + fmodSystem->setReverbProperties(0, &props); } /** @@ -677,7 +699,7 @@ */ void DS_SFX_Listenerv(int prop, float* values) { - switch(prop) + switch (prop) { case SFXLP_POSITION: listener.position.set(values); @@ -714,12 +736,12 @@ */ int DS_SFX_Getv(int prop, void *values) { - switch(prop) + switch (prop) { case SFXIP_DISABLE_CHANNEL_REFRESH: { /// The return value is a single 32-bit int. int *wantDisable = reinterpret_cast(values); - if(wantDisable) + if (wantDisable) { // Channel refresh is handled by FMOD, so we don't need to do anything. *wantDisable = true; @@ -728,7 +750,7 @@ case SFXIP_ANY_SAMPLE_RATE_ACCEPTED: { int *anySampleRate = reinterpret_cast(values); - if(anySampleRate) + if (anySampleRate) { // FMOD can resample on the fly as needed. *anySampleRate = true; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/data/heretic.mapinfo doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/data/heretic.mapinfo --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/data/heretic.mapinfo 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/data/heretic.mapinfo 2018-12-11 07:08:22.000000000 +0000 @@ -225,3 +225,15 @@ sky1 SKY3 0 music MUS_E2M6 cluster 3 + +; Episode 4 ------------------------------------------------------------ + +; This is a hidden episode. +episode E4M1 +name "" + +map E4M1 "American's Legacy" +warptrans 1 +sky1 SKY1 0 +music MUS_E1M6 +cluster 4 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/flags.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/flags.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/flags.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/flags.ded 2018-12-11 07:08:22.000000000 +0000 @@ -1,4 +1,4 @@ -# libheretic: Flags +# Heretic: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } @@ -59,3 +59,5 @@ # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } Flag { ID = "mf3_clientaction"; Value = 0x2; } +Flag { ID = "mf3_nomorph"; Value = 0x4; } + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/heretic/music.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/heretic/music.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/heretic/music.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/heretic/music.ded 2018-12-11 07:08:22.000000000 +0000 @@ -7,6 +7,10 @@ Header { Version = 5; } +Music { ID = "titl"; Lump = "MUS_TITL"; } +Music { ID = "intr"; Lump = "MUS_INTR"; } +Music { ID = "cptd"; Lump = "MUS_CPTD"; } + Music { ID = "e1m1"; Lump = "MUS_E1M1"; } Music { ID = "e1m2"; Lump = "MUS_E1M2"; } Music { ID = "e1m3"; Lump = "MUS_E1M3"; } @@ -16,16 +20,47 @@ Music { ID = "e1m7"; Lump = "MUS_E1M7"; } Music { ID = "e1m8"; Lump = "MUS_E1M8"; } Music { ID = "e1m9"; Lump = "MUS_E1M9"; } + Music { ID = "e2m1"; Lump = "MUS_E2M1"; } Music { ID = "e2m2"; Lump = "MUS_E2M2"; } Music { ID = "e2m3"; Lump = "MUS_E2M3"; } Music { ID = "e2m4"; Lump = "MUS_E2M4"; } +Music { ID = "e2m5"; Lump = "MUS_E1M4"; } Music { ID = "e2m6"; Lump = "MUS_E2M6"; } Music { ID = "e2m7"; Lump = "MUS_E2M7"; } Music { ID = "e2m8"; Lump = "MUS_E2M8"; } Music { ID = "e2m9"; Lump = "MUS_E2M9"; } + +Music { ID = "e3m1"; Lump = "MUS_E1M1"; } Music { ID = "e3m2"; Lump = "MUS_E3M2"; } Music { ID = "e3m3"; Lump = "MUS_E3M3"; } -Music { ID = "titl"; Lump = "MUS_TITL"; } -Music { ID = "intr"; Lump = "MUS_INTR"; } -Music { ID = "cptd"; Lump = "MUS_CPTD"; } +Music { ID = "e3m4"; Lump = "MUS_E1M6"; } +Music { ID = "e3m5"; Lump = "MUS_E1M3"; } +Music { ID = "e3m6"; Lump = "MUS_E1M2"; } +Music { ID = "e3m7"; Lump = "MUS_E1M5"; } +Music { ID = "e3m8"; Lump = "MUS_E1M9"; } +Music { ID = "e3m9"; Lump = "MUS_E2M6"; } + +Music { ID = "e4m1"; Lump = "MUS_E1M6"; } +Music { ID = "e4m2"; Lump = "MUS_E1M2"; } +Music { ID = "e4m3"; Lump = "MUS_E1M3"; } +Music { ID = "e4m4"; Lump = "MUS_E1M4"; } +Music { ID = "e4m5"; Lump = "MUS_E1M5"; } +Music { ID = "e4m6"; Lump = "MUS_E1M1"; } +Music { ID = "e4m7"; Lump = "MUS_E1M7"; } +Music { ID = "e4m8"; Lump = "MUS_E1M8"; } +Music { ID = "e4m9"; Lump = "MUS_E1M9"; } + +Music { ID = "e5m1"; Lump = "MUS_E2M1"; } +Music { ID = "e5m2"; Lump = "MUS_E2M2"; } +Music { ID = "e5m3"; Lump = "MUS_E2M3"; } +Music { ID = "e5m4"; Lump = "MUS_E2M4"; } +Music { ID = "e5m5"; Lump = "MUS_E1M4"; } +Music { ID = "e5m6"; Lump = "MUS_E2M6"; } +Music { ID = "e5m7"; Lump = "MUS_E2M7"; } +Music { ID = "e5m8"; Lump = "MUS_E2M8"; } +Music { ID = "e5m9"; Lump = "MUS_E2M9"; } + +Music { ID = "e6m1"; Lump = "MUS_E3M2"; } +Music { ID = "e6m2"; Lump = "MUS_E3M3"; } +Music { ID = "e6m3"; Lump = "MUS_E1M6"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/heretic/patchmapinfo.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/heretic/patchmapinfo.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/heretic/patchmapinfo.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/heretic/patchmapinfo.ded 2018-12-11 07:08:22.000000000 +0000 @@ -5,69 +5,69 @@ Header { Version = 6; } # -# Music and Sky mods: heretic, heretic-share, heretic-ext +# Sky mods: heretic, heretic-share, heretic-ext # -Map Info mods "E1M1" if not custom { Music = "e1m1"; Sky = "sky1"; } -Map Info mods "E1M2" if not custom { Music = "e1m2"; Sky = "sky1"; } -Map Info mods "E1M3" if not custom { Music = "e1m3"; Sky = "sky1"; } -Map Info mods "E1M4" if not custom { Music = "e1m4"; Sky = "sky1"; } -Map Info mods "E1M5" if not custom { Music = "e1m5"; Sky = "sky1"; } -Map Info mods "E1M6" if not custom { Music = "e1m6"; Sky = "sky1"; } -Map Info mods "E1M7" if not custom { Music = "e1m7"; Sky = "sky1"; } -Map Info mods "E1M8" if not custom { Music = "e1m8"; Sky = "sky1"; } -Map Info mods "E1M9" if not custom { Music = "e1m9"; Sky = "sky1"; } +Map Info mods "E1M1" if not custom { Sky = "sky1"; } +Map Info mods "E1M2" if not custom { Sky = "sky1"; } +Map Info mods "E1M3" if not custom { Sky = "sky1"; } +Map Info mods "E1M4" if not custom { Sky = "sky1"; } +Map Info mods "E1M5" if not custom { Sky = "sky1"; } +Map Info mods "E1M6" if not custom { Sky = "sky1"; } +Map Info mods "E1M7" if not custom { Sky = "sky1"; } +Map Info mods "E1M8" if not custom { Sky = "sky1"; } +Map Info mods "E1M9" if not custom { Sky = "sky1"; } # The rest of the file is skipped if Heretic Shareware. SkipIf heretic-share; # Episode 2: -Map Info mods "E2M1" if not custom { Music = "e2m1"; Sky = "sky2"; } -Map Info mods "E2M2" if not custom { Music = "e2m2"; Sky = "sky2"; } -Map Info mods "E2M3" if not custom { Music = "e2m3"; Sky = "sky2"; } -Map Info mods "E2M4" if not custom { Music = "e2m4"; Sky = "sky2"; } -Map Info mods "E2M5" if not custom { Music = "e1m4"; Sky = "sky2"; } -Map Info mods "E2M6" if not custom { Music = "e2m6"; Sky = "sky2"; } -Map Info mods "E2M7" if not custom { Music = "e2m7"; Sky = "sky2"; } -Map Info mods "E2M8" if not custom { Music = "e2m8"; Sky = "sky2"; } -Map Info mods "E2M9" if not custom { Music = "e2m9"; Sky = "sky2"; } +Map Info mods "E2M1" if not custom { Sky = "sky2"; } +Map Info mods "E2M2" if not custom { Sky = "sky2"; } +Map Info mods "E2M3" if not custom { Sky = "sky2"; } +Map Info mods "E2M4" if not custom { Sky = "sky2"; } +Map Info mods "E2M5" if not custom { Sky = "sky2"; } +Map Info mods "E2M6" if not custom { Sky = "sky2"; } +Map Info mods "E2M7" if not custom { Sky = "sky2"; } +Map Info mods "E2M8" if not custom { Sky = "sky2"; } +Map Info mods "E2M9" if not custom { Sky = "sky2"; } # Episode 3: -Map Info mods "E3M1" if not custom { Music = "e1m1"; Sky = "sky3"; } -Map Info mods "E3M2" if not custom { Music = "e3m2"; Sky = "sky3"; } -Map Info mods "E3M3" if not custom { Music = "e3m3"; Sky = "sky3"; } -Map Info mods "E3M4" if not custom { Music = "e1m6"; Sky = "sky3"; } -Map Info mods "E3M5" if not custom { Music = "e1m3"; Sky = "sky3"; } -Map Info mods "E3M6" if not custom { Music = "e1m2"; Sky = "sky3"; } -Map Info mods "E3M7" if not custom { Music = "e1m5"; Sky = "sky3"; } -Map Info mods "E3M8" if not custom { Music = "e1m9"; Sky = "sky3"; } -Map Info mods "E3M9" if not custom { Music = "e2m6"; Sky = "sky3"; } +Map Info mods "E3M1" if not custom { Sky = "sky3"; } +Map Info mods "E3M2" if not custom { Sky = "sky3"; } +Map Info mods "E3M3" if not custom { Sky = "sky3"; } +Map Info mods "E3M4" if not custom { Sky = "sky3"; } +Map Info mods "E3M5" if not custom { Sky = "sky3"; } +Map Info mods "E3M6" if not custom { Sky = "sky3"; } +Map Info mods "E3M7" if not custom { Sky = "sky3"; } +Map Info mods "E3M8" if not custom { Sky = "sky3"; } +Map Info mods "E3M9" if not custom { Sky = "sky3"; } # The rest of the file is skipped if not Heretic Extended. SkipIf Not heretic-ext; # Episode 4: -Map Info mods "E4M1" if not custom { Music = "e1m6"; Sky = "sky1"; } -Map Info mods "E4M2" if not custom { Music = "e1m2"; Sky = "sky1"; } -Map Info mods "E4M3" if not custom { Music = "e1m3"; Sky = "sky1"; } -Map Info mods "E4M4" if not custom { Music = "e1m4"; Sky = "sky1"; } -Map Info mods "E4M5" if not custom { Music = "e1m5"; Sky = "sky1"; } -Map Info mods "E4M6" if not custom { Music = "e1m1"; Sky = "sky1"; } -Map Info mods "E4M7" if not custom { Music = "e1m7"; Sky = "sky1"; } -Map Info mods "E4M8" if not custom { Music = "e1m8"; Sky = "sky1"; } -Map Info mods "E4M9" if not custom { Music = "e1m9"; Sky = "sky1"; } +Map Info mods "E4M1" if not custom { Sky = "sky1"; } +Map Info mods "E4M2" if not custom { Sky = "sky1"; } +Map Info mods "E4M3" if not custom { Sky = "sky1"; } +Map Info mods "E4M4" if not custom { Sky = "sky1"; } +Map Info mods "E4M5" if not custom { Sky = "sky1"; } +Map Info mods "E4M6" if not custom { Sky = "sky1"; } +Map Info mods "E4M7" if not custom { Sky = "sky1"; } +Map Info mods "E4M8" if not custom { Sky = "sky1"; } +Map Info mods "E4M9" if not custom { Sky = "sky1"; } # Episode 5: -Map Info mods "E5M1" if not custom { Music = "e2m1"; Sky = "sky3"; } -Map Info mods "E5M2" if not custom { Music = "e2m2"; Sky = "sky3"; } -Map Info mods "E5M3" if not custom { Music = "e2m3"; Sky = "sky3"; } -Map Info mods "E5M4" if not custom { Music = "e2m4"; Sky = "sky3"; } -Map Info mods "E5M5" if not custom { Music = "e1m4"; Sky = "sky3"; } -Map Info mods "E5M6" if not custom { Music = "e2m6"; Sky = "sky3"; } -Map Info mods "E5M7" if not custom { Music = "e2m7"; Sky = "sky3"; } -Map Info mods "E5M8" if not custom { Music = "e2m8"; Sky = "sky3"; } -Map Info mods "E5M9" if not custom { Music = "e2m9"; Sky = "sky3"; } +Map Info mods "E5M1" if not custom { Sky = "sky3"; } +Map Info mods "E5M2" if not custom { Sky = "sky3"; } +Map Info mods "E5M3" if not custom { Sky = "sky3"; } +Map Info mods "E5M4" if not custom { Sky = "sky3"; } +Map Info mods "E5M5" if not custom { Sky = "sky3"; } +Map Info mods "E5M6" if not custom { Sky = "sky3"; } +Map Info mods "E5M7" if not custom { Sky = "sky3"; } +Map Info mods "E5M8" if not custom { Sky = "sky3"; } +Map Info mods "E5M9" if not custom { Sky = "sky3"; } # Episode 6: -Map Info mods "E6M1" if not custom { Music = "e3m2"; Sky = "sky1"; } -Map Info mods "E6M2" if not custom { Music = "e3m3"; Sky = "sky1"; } -Map Info mods "E6M3" if not custom { Music = "e1m6"; Sky = "sky1"; } +Map Info mods "E6M1" if not custom { Sky = "sky1"; } +Map Info mods "E6M2" if not custom { Sky = "sky1"; } +Map Info mods "E6M3" if not custom { Sky = "sky1"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/objects.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/objects.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/defs/objects.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/defs/objects.ded 2018-12-11 07:08:22.000000000 +0000 @@ -456,6 +456,7 @@ Mass = 100; Flags = "mf_solid mf_noblood mf_shootable mf_dropoff mf_viewalign"; Flags2 = "mf2_windthrust mf2_pushable mf2_slide mf2_passmobj mf2_telestomp"; + Flags3 = "mf3_nomorph"; } Thing { @@ -2503,6 +2504,7 @@ Mass = 40; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_windthrust mf2_footclip mf2_passmobj"; + Flags3 = "mf3_nomorph"; } Thing { @@ -2930,6 +2932,7 @@ Mass = 325; Flags = "mf_solid mf_shootable mf_countkill mf_noblood"; Flags2 = "mf2_passmobj"; + Flags3 = "mf3_nomorph"; } Thing { @@ -3383,7 +3386,7 @@ Mass = 800; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; - Flags3 = "mf3_noinfight"; + Flags3 = "mf3_noinfight mf3_nomorph"; } Thing { @@ -3438,7 +3441,7 @@ Mass = 300; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; - Flags3 = "mf3_noinfight"; + Flags3 = "mf3_noinfight mf3_nomorph"; } Thing { @@ -3570,7 +3573,7 @@ Damage = 7; Flags = "mf_solid mf_shootable mf_countkill mf_dropoff"; Flags2 = "mf2_footclip mf2_passmobj mf2_boss"; - Flags3 = "mf3_noinfight"; + Flags3 = "mf3_noinfight mf3_nomorph"; } Thing { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/doomdef.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/doomdef.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/doomdef.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/doomdef.h 2018-12-11 07:08:22.000000000 +0000 @@ -54,8 +54,6 @@ #define Set DD_SetInteger #define Get DD_GetInteger -DENG_EXTERN_C game_export_t gx; - // // Global parameters/defines. // diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_api.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_api.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_api.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_api.h 2018-12-11 07:08:22.000000000 +0000 @@ -39,8 +39,6 @@ extern "C" { #endif -extern game_export_t gx; - DENG_USING_API(Base); DENG_USING_API(B); DENG_USING_API(Busy); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_main.h 2018-12-11 07:08:22.000000000 +0000 @@ -27,8 +27,6 @@ #include "doomdef.h" -DENG_EXTERN_C float turboMul; // Multiplier for turbo. - DENG_EXTERN_C gamemode_t gameMode; DENG_EXTERN_C int gameModeBits; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_refresh.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_refresh.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/h_refresh.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/h_refresh.h 2018-12-11 07:08:22.000000000 +0000 @@ -35,11 +35,6 @@ void G_RendPlayerView(int player); -/** - * Draws a special filter over the screen. - */ -void G_RendSpecialFilter(int player, RectRaw const *region); - void H_DrawViewPort(int port, RectRaw const *portGeometry, RectRaw const *windowGeometry, int player, int layer); void H_DrawWindow(Size2Raw const *windowSize); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/p_local.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/p_local.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/p_local.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/p_local.h 2018-12-11 07:08:22.000000000 +0000 @@ -94,7 +94,6 @@ #define USE_MACE_AMMO_2 5 DENG_EXTERN_C mobj_t *missileMobj; -DENG_EXTERN_C float turboMul; #ifdef __cplusplus extern "C" { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/p_mobj.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/p_mobj.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/p_mobj.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/p_mobj.h 2018-12-11 07:08:22.000000000 +0000 @@ -156,6 +156,7 @@ #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting #define MF3_CLIENTACTION 0x00000002 // States' action funcs are executed by client +#define MF3_NOMORPH 0x00000004 // Mobj cannot be morphed to Chicken // --- mobj.intflags --- (added in MOBJ_SAVEVERSION 6) // Internal mobj flags cannot be set using an external definition. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/include/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/include/version.h 2018-12-11 07:08:22.000000000 +0000 @@ -64,6 +64,6 @@ // For WIN32 version info: #define PLUGIN_DESC PLUGIN_NICENAME " " LIBDENG_PLUGINDESC -#define PLUGIN_COPYRIGHT "2000-2013, " DENGPROJECT_NICEAUTHOR +#define PLUGIN_COPYRIGHT "2000-2018, " DENGPROJECT_NICEAUTHOR #endif /* JHERETIC_VERSION_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_api.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_api.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_api.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_api.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -49,9 +49,6 @@ using namespace de; -// The interface to the Doomsday engine. -game_export_t gx; - // Identifiers given to the games we register during startup. static char const *gameIds[NUM_GAME_MODES] = { @@ -60,10 +57,20 @@ "heretic-ext", }; +static void setCommonParameters(Game &game) +{ + Record gameplayOptions; + gameplayOptions.set("fast", Record::withMembers("label", "Fast Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("respawn", Record::withMembers("label", "Respawn Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("noMonsters", Record::withMembers("label", "No Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("turbo", Record::withMembers("label", "Move Speed", "type", "number", "default", 1.0, "min", 0.1, "max", 4.0, "step", 0.1)); + game.objectNamespace().set(Game::DEF_OPTIONS, gameplayOptions); +} + /** * Register the game modes supported by this plugin. */ -int G_RegisterGames(int hookType, int param, void* data) +static int G_RegisterGames(int hookType, int param, void* data) { Games &games = DoomsdayApp::games(); @@ -89,6 +96,7 @@ extended.addResource(RC_DEFINITION, 0, "heretic-ext.ded", 0); extended.setRequiredPackages(StringList() << "com.ravensoftware.heretic.extended" << "net.dengine.legacy.heretic_2"); + setCommonParameters(extended); /* Heretic */ Game &htc = games.defineGame(gameIds[heretic], @@ -105,6 +113,7 @@ htc.addResource(RC_DEFINITION, 0, "heretic.ded", 0); htc.setRequiredPackages(StringList() << "com.ravensoftware.heretic" << "net.dengine.legacy.heretic_2"); + setCommonParameters(htc); /* Heretic (Shareware) */ Game &shareware = games.defineGame(gameIds[heretic_shareware], @@ -121,6 +130,7 @@ shareware.addResource(RC_DEFINITION, 0, "heretic-share.ded", 0); shareware.setRequiredPackages(StringList() << "com.ravensoftware.heretic.shareware" << "net.dengine.legacy.heretic_2"); + setCommonParameters(shareware); return true; #undef STARTUPPK3 @@ -130,7 +140,7 @@ /** * Called right after the game plugin is selected into use. */ -DENG_EXTERN_C void DP_Load(void) +DENG_ENTRYPOINT void DP_Load(void) { Plug_AddHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); gfw_SetCurrentGame(GFW_HERETIC); @@ -139,12 +149,12 @@ /** * Called when the game plugin is freed from memory. */ -DENG_EXTERN_C void DP_Unload(void) +DENG_ENTRYPOINT void DP_Unload(void) { Plug_RemoveHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); } -DENG_EXTERN_C void G_PreInit(char const *gameId) +void G_PreInit(char const *gameId) { /// \todo Refactor me away. { size_t i; @@ -171,64 +181,37 @@ return true; } -/** - * Takes a copy of the engine's entry points and exported data. Returns - * a pointer to the structure that contains our entry points and exports. - */ -DENG_EXTERN_C game_export_t *GetGameAPI(void) +DENG_ENTRYPOINT void *GetGameAPI(char const *name) { - // Clear all of our exports. - memset(&gx, 0, sizeof(gx)); - - // Fill in the data for the exports. - gx.apiSize = sizeof(gx); - gx.PreInit = G_PreInit; - gx.PostInit = H_PostInit; - gx.TryShutdown = G_TryShutdown; - gx.Shutdown = H_Shutdown; - gx.Ticker = G_Ticker; - gx.DrawViewPort = G_DrawViewPort; - gx.DrawWindow = H_DrawWindow; - gx.FinaleResponder = FI_PrivilegedResponder; - gx.PrivilegedResponder = G_PrivilegedResponder; - gx.Responder = G_Responder; - gx.EndFrame = H_EndFrame; - gx.MobjThinker = P_MobjThinker; - gx.MobjFriction = Mobj_Friction; - gx.MobjCheckPositionXYZ = P_CheckPositionXYZ; - gx.MobjTryMoveXYZ = P_TryMoveXYZ; - gx.SectorHeightChangeNotification = P_HandleSectorHeightChange; - gx.UpdateState = G_UpdateState; - - gx.GetInteger = H_GetInteger; - gx.GetVariable = H_GetVariable; - - gx.NetServerStart = D_NetServerStarted; - gx.NetServerStop = D_NetServerClose; - gx.NetConnect = D_NetConnect; - gx.NetDisconnect = D_NetDisconnect; - gx.NetPlayerEvent = D_NetPlayerEvent; - gx.NetWorldEvent = D_NetWorldEvent; - gx.HandlePacket = D_HandlePacket; - - // Data structure sizes. - gx.mobjSize = sizeof(mobj_t); - gx.polyobjSize = sizeof(Polyobj); - - gx.FinalizeMapChange = (void (*)(void const *)) P_FinalizeMapChange; - - // These really need better names. Ideas? - gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; - gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; + if (auto *ptr = Common_GetGameAPI(name)) + { + return ptr; + } - return &gx; + #define HASH_ENTRY(Name, Func) std::make_pair(QByteArray(Name), de::function_cast(Func)) + static QHash const funcs( + { + HASH_ENTRY("DrawWindow", H_DrawWindow), + HASH_ENTRY("EndFrame", H_EndFrame), + HASH_ENTRY("GetInteger", H_GetInteger), + HASH_ENTRY("GetPointer", H_GetVariable), + HASH_ENTRY("PostInit", H_PostInit), + HASH_ENTRY("PreInit", G_PreInit), + HASH_ENTRY("Shutdown", H_Shutdown), + HASH_ENTRY("TryShutdown", G_TryShutdown), + }); + #undef HASH_ENTRY + + auto found = funcs.find(name); + if (found != funcs.end()) return found.value(); + return nullptr; } /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -DENG_EXTERN_C void DP_Initialize(void) +DENG_ENTRYPOINT void DP_Initialize(void) { Plug_AddHook(HOOK_STARTUP, G_RegisterGames); } @@ -237,11 +220,26 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C char const *deng_LibraryType(void) +DENG_ENTRYPOINT char const *deng_LibraryType(void) { return "deng-plugin/game"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_heretic_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + DENG_SYMBOL_PTR(name, DP_Load); + DENG_SYMBOL_PTR(name, DP_Unload); + DENG_SYMBOL_PTR(name, GetGameAPI); + qWarning() << name << "not found in heretic"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(B); DENG_DECLARE_API(Busy); @@ -289,3 +287,5 @@ DENG_GET_API(DE_API_THINKER, Thinker); DENG_GET_API(DE_API_URI, Uri); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_main.cpp 2018-12-11 07:08:22.000000000 +0000 @@ -40,8 +40,6 @@ using namespace de; using namespace common; -float turboMul; // Multiplier for turbo. - gamemode_t gameMode; int gameModeBits; @@ -253,7 +251,7 @@ cfg.common.automapBack[2] = 1.0f; cfg.common.automapOpacity = 1.0f; cfg.common.automapLineAlpha = 1.0f; - cfg.common.automapLineWidth = 1.1f; + cfg.common.automapLineWidth = 3.0f; cfg.common.automapShowDoors = true; cfg.common.automapDoorGlow = 8; cfg.common.automapHudDisplay = 2; @@ -322,6 +320,34 @@ G_CommonPreInit(); } +static void initAmmoInfo() +{ + static const int defaultMaxAmmo[NUM_AMMO_TYPES] = {100, 50, 200, 200, 20, 150}; + + static const char *ammoName[NUM_AMMO_TYPES] = { + "Crystal", + "Arrow", + "Orb", + "Rune", + "FireOrb", + "MSphere", + }; + + for (int i = AT_FIRST; i < NUM_AMMO_TYPES; ++i) + { + const String name = ammoName[i]; + if (const ded_value_t *value = Defs().getValueById("Player|Max ammo|" + name)) + { + // Note: `maxAmmo` is a global variable from p_inter.c + maxAmmo[i] = String(value->text).toInt(); + } + else + { + maxAmmo[i] = defaultMaxAmmo[i]; + } + } +} + void H_PostInit() { CommandLine &cmdLine = DENG2_APP->commandLine(); @@ -332,49 +358,39 @@ G_CommonPostInit(); + initAmmoInfo(); P_InitWeaponInfo(); IN_Init(); // Game parameters. ::monsterInfight = 0; - if(ded_value_t const *infight = Defs().getValueById("AI|Infight")) + if (ded_value_t const *infight = Defs().getValueById("AI|Infight")) { ::monsterInfight = String(infight->text).toInt(); } // Defaults for skill, episode and map. - ::defaultGameRules.skill = /*startSkill =*/ SM_MEDIUM; + gfw_SetDefaultRule(skill, SM_MEDIUM); - if(cmdLine.check("-deathmatch")) + if (cmdLine.check("-deathmatch")) { ::cfg.common.netDeathmatch = true; } // Apply these game rules. - ::defaultGameRules.noMonsters = cmdLine.check("-nomonsters")? true : false; - ::defaultGameRules.respawnMonsters = cmdLine.check("-respawn") ? true : false; - - // Change the turbo multiplier? - ::turboMul = 1.0f; - if(int arg = cmdLine.check("-turbo")) - { - int scale = 200; - if(arg + 1 < cmdLine.count() && !cmdLine.isOption(arg + 1)) - { - scale = cmdLine.at(arg + 1).toInt(); - } - scale = de::clamp(10, scale, 400); - - LOG_NOTE("Turbo scale: %i%%") << scale; - ::turboMul = scale / 100.f; - } + gfw_SetDefaultRule(noMonsters, + cmdLine.check("-nomonsters") || + gfw_GameProfile()->optionValue("noMonsters").isTrue()); + gfw_SetDefaultRule(respawnMonsters, + cmdLine.check("-respawn") || + gfw_GameProfile()->optionValue("respawn").isTrue()); // Load a saved game? - if(int arg = cmdLine.check("-loadgame", 1)) + if (auto arg = cmdLine.check("-loadgame", 1)) { - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(cmdLine.at(arg + 1))) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(arg.params.first())) { - if(sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) + if (sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) { // No further initialization is to be done. return; @@ -383,10 +399,10 @@ } // Change the default skill mode? - if(int arg = cmdLine.check("-skill", 1)) + if (auto arg = cmdLine.check("-skill", 1)) { - int skillNumber = cmdLine.at(arg + 1).toInt(); - ::defaultGameRules.skill = (skillmode_t)(skillNumber > 0? skillNumber - 1 : skillNumber); + int const skillNumber = arg.params.first().toInt(); + gfw_SetDefaultRule(skill, skillmode_t(skillNumber > 0 ? skillNumber - 1 : skillNumber)); } G_AutoStartOrBeginTitleLoop(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_refresh.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_refresh.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/h_refresh.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/h_refresh.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -38,6 +38,7 @@ float quitDarkenOpacity = 0; +#if 0 void G_RendSpecialFilter(int player, RectRaw const *region) { player_t *plr = players + player; @@ -64,6 +65,7 @@ // Restore the normal rendering state. DGL_BlendMode(BM_NORMAL); } +#endif dd_bool R_ViewFilterColor(float rgba[4], int filter) { @@ -76,7 +78,7 @@ rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; - rgba[CA] = (COMMON_GAMESESSION->rules().deathmatch? 1.0f : cfg.common.filterStrength) * filter / 8.f; // Full red with filter 8. + rgba[CA] = (gfw_Rule(deathmatch)? 1.0f : cfg.common.filterStrength) * filter / 8.f; // Full red with filter 8. return true; } else if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) @@ -163,7 +165,7 @@ } // How about fullbright? - DD_SetInteger(DD_FULLBRIGHT, isFullBright); + DD_SetInteger(DD_RENDER_FULLBRIGHT, isFullBright); // Render the view with possible custom filters. R_RenderPlayerView(player); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/intermission.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/intermission.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/intermission.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/intermission.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -105,37 +105,37 @@ if(!episode1Locations.isEmpty()) return; episode1Locations - << Location( Vector2i(172, 78), de::Uri("Maps:E1M1", RC_NULL) ) - << Location( Vector2i( 86, 90), de::Uri("Maps:E1M2", RC_NULL) ) - << Location( Vector2i( 73, 66), de::Uri("Maps:E1M3", RC_NULL) ) - << Location( Vector2i(159, 95), de::Uri("Maps:E1M4", RC_NULL) ) - << Location( Vector2i(148, 126), de::Uri("Maps:E1M5", RC_NULL) ) - << Location( Vector2i(132, 54), de::Uri("Maps:E1M6", RC_NULL) ) - << Location( Vector2i(131, 74), de::Uri("Maps:E1M7", RC_NULL) ) - << Location( Vector2i(208, 138), de::Uri("Maps:E1M8", RC_NULL) ) - << Location( Vector2i( 52, 10), de::Uri("Maps:E1M9", RC_NULL) ); + << Location( Vector2i(172, 78), de::makeUri("Maps:E1M1") ) + << Location( Vector2i( 86, 90), de::makeUri("Maps:E1M2") ) + << Location( Vector2i( 73, 66), de::makeUri("Maps:E1M3") ) + << Location( Vector2i(159, 95), de::makeUri("Maps:E1M4") ) + << Location( Vector2i(148, 126), de::makeUri("Maps:E1M5") ) + << Location( Vector2i(132, 54), de::makeUri("Maps:E1M6") ) + << Location( Vector2i(131, 74), de::makeUri("Maps:E1M7") ) + << Location( Vector2i(208, 138), de::makeUri("Maps:E1M8") ) + << Location( Vector2i( 52, 10), de::makeUri("Maps:E1M9") ); episode2Locations - << Location( Vector2i(218, 57), de::Uri("Maps:E2M1", RC_NULL) ) - << Location( Vector2i(137, 81), de::Uri("Maps:E2M2", RC_NULL) ) - << Location( Vector2i(155, 124), de::Uri("Maps:E2M3", RC_NULL) ) - << Location( Vector2i(171, 68), de::Uri("Maps:E2M4", RC_NULL) ) - << Location( Vector2i(250, 86), de::Uri("Maps:E2M5", RC_NULL) ) - << Location( Vector2i(136, 98), de::Uri("Maps:E2M6", RC_NULL) ) - << Location( Vector2i(203, 90), de::Uri("Maps:E2M7", RC_NULL) ) - << Location( Vector2i(220, 140), de::Uri("Maps:E2M8", RC_NULL) ) - << Location( Vector2i(279, 106), de::Uri("Maps:E2M9", RC_NULL) ); + << Location( Vector2i(218, 57), de::makeUri("Maps:E2M1") ) + << Location( Vector2i(137, 81), de::makeUri("Maps:E2M2") ) + << Location( Vector2i(155, 124), de::makeUri("Maps:E2M3") ) + << Location( Vector2i(171, 68), de::makeUri("Maps:E2M4") ) + << Location( Vector2i(250, 86), de::makeUri("Maps:E2M5") ) + << Location( Vector2i(136, 98), de::makeUri("Maps:E2M6") ) + << Location( Vector2i(203, 90), de::makeUri("Maps:E2M7") ) + << Location( Vector2i(220, 140), de::makeUri("Maps:E2M8") ) + << Location( Vector2i(279, 106), de::makeUri("Maps:E2M9") ); episode3Locations - << Location( Vector2i( 86, 99), de::Uri("Maps:E3M1", RC_NULL) ) - << Location( Vector2i(124, 103), de::Uri("Maps:E3M2", RC_NULL) ) - << Location( Vector2i(154, 79), de::Uri("Maps:E3M3", RC_NULL) ) - << Location( Vector2i(202, 83), de::Uri("Maps:E3M4", RC_NULL) ) - << Location( Vector2i(178, 59), de::Uri("Maps:E3M5", RC_NULL) ) - << Location( Vector2i(142, 58), de::Uri("Maps:E3M6", RC_NULL) ) - << Location( Vector2i(219, 66), de::Uri("Maps:E3M7", RC_NULL) ) - << Location( Vector2i(247, 57), de::Uri("Maps:E3M8", RC_NULL) ) - << Location( Vector2i(107, 80), de::Uri("Maps:E3M9", RC_NULL) ); + << Location( Vector2i( 86, 99), de::makeUri("Maps:E3M1") ) + << Location( Vector2i(124, 103), de::makeUri("Maps:E3M2") ) + << Location( Vector2i(154, 79), de::makeUri("Maps:E3M3") ) + << Location( Vector2i(202, 83), de::makeUri("Maps:E3M4") ) + << Location( Vector2i(178, 59), de::makeUri("Maps:E3M5") ) + << Location( Vector2i(142, 58), de::makeUri("Maps:E3M6") ) + << Location( Vector2i(219, 66), de::makeUri("Maps:E3M7") ) + << Location( Vector2i(247, 57), de::makeUri("Maps:E3M8") ) + << Location( Vector2i(107, 80), de::makeUri("Maps:E3M9") ); } void IN_Shutdown() @@ -210,12 +210,12 @@ { // Newer versions of the savegame format include a breakdown of the maps previously visited // during the current game session. - if(COMMON_GAMESESSION->allVisitedMaps().isEmpty()) + if(gfw_Session()->allVisitedMaps().isEmpty()) { // For backward compatible intermission behavior we'll have to use a specially prepared // version of this information, using the original map progression assumptions. bool isNumber; - int oldEpisodeNum = COMMON_GAMESESSION->episodeId().toInt(&isNumber) - 1; // 1-based + int oldEpisodeNum = gfw_Session()->episodeId().toInt(&isNumber) - 1; // 1-based DENG2_ASSERT(isNumber); DENG2_UNUSED(isNumber); @@ -234,7 +234,7 @@ } return visited.toList(); } - return COMMON_GAMESESSION->allVisitedMaps(); + return gfw_Session()->allVisitedMaps(); } void IN_End() @@ -311,7 +311,7 @@ */ static void drawLocationMarks(bool drawYouAreHere = false, bool flashCurrent = true) { - Locations const *locations = locationsForEpisode(COMMON_GAMESESSION->episodeId()); + Locations const *locations = locationsForEpisode(gfw_Session()->episodeId()); if(!locations) return; DGL_Enable(DGL_TEXTURE_2D); @@ -931,7 +931,7 @@ static void loadData() { - String const episodeId = COMMON_GAMESESSION->episodeId(); + String const episodeId = gfw_Session()->episodeId(); // Determine which patch to use for the background. pBackground = R_DeclarePatch(backgroundPatchForEpisode(episodeId).toUtf8().constData()); @@ -1053,7 +1053,7 @@ advanceState = false; interTime = 0; oldInterTime = 0; - haveLocationMap = locationsForEpisode(COMMON_GAMESESSION->episodeId()) != 0; + haveLocationMap = locationsForEpisode(gfw_Session()->episodeId()) != 0; } void IN_Begin(wbstartstruct_t const &wbstartstruct) @@ -1086,7 +1086,7 @@ { initShowStats(); } - else if( /*IS_NETGAME && */ !COMMON_GAMESESSION->rules().deathmatch) + else if( /*IS_NETGAME && */ !gfw_Rule(deathmatch)) { initNetgameStats(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/m_cheat.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/m_cheat.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/m_cheat.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/m_cheat.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -106,7 +106,7 @@ player_t *plr = &players[player]; - if(COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -140,7 +140,7 @@ DENG2_UNUSED2(args, numArgs); DENG2_ASSERT(player >= 0 && player < MAXPLAYERS); - if(COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; if(plr->morphTics) return false; @@ -167,7 +167,7 @@ DENG2_UNUSED2(args, numArgs); DENG2_ASSERT(player >= 0 && player < MAXPLAYERS); - if(COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -186,7 +186,7 @@ DENG2_UNUSED2(args, numArgs); DENG2_ASSERT(player >= 0 && player < MAXPLAYERS); - if(IS_NETGAME && COMMON_GAMESESSION->rules().deathmatch) return false; + if(IS_NETGAME && gfw_Rule(deathmatch)) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -228,7 +228,7 @@ { NetCl_CheatRequest("god"); } - else if((IS_NETGAME && !netSvAllowCheats) || COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -269,7 +269,7 @@ { NetCl_CheatRequest("noclip"); } - else if((IS_NETGAME && !netSvAllowCheats) || COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -436,7 +436,7 @@ return true; } - if((IS_NETGAME && !netSvAllowCheats) || COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) return false; plr = &players[player]; @@ -652,7 +652,7 @@ { NetCl_CheatRequest("kill"); } - else if((IS_NETGAME && !netSvAllowCheats) || COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -683,7 +683,7 @@ if(!plrMo) return true; sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", - COMMON_GAMESESSION->mapUri().path().toUtf8().constData(), + gfw_Session()->mapUri().path().toUtf8().constData(), plrMo->origin[VX], plrMo->origin[VY], plrMo->origin[VZ]); P_SetMessageWithFlags(plr, textBuffer, LMF_NO_HIDE); @@ -718,7 +718,7 @@ { NetCl_CheatRequest("chicken"); } - else if((IS_NETGAME && !netSvAllowCheats) || COMMON_GAMESESSION->rules().skill == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_enemy.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_enemy.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_enemy.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_enemy.c 2018-12-11 07:08:23.000000000 +0000 @@ -426,7 +426,7 @@ VALIDCOUNT++; Mobj_TouchedLinesIterator(mobj, PIT_AvoidDropoff, &parm); - if(FEQUAL(parm.direction[VX], 0) && FEQUAL(parm.direction[VY], 0)) + if(IS_ZERO(parm.direction[VX]) && IS_ZERO(parm.direction[VY])) return false; // The mobj should attempt to move away from the drop off. @@ -620,8 +620,8 @@ actor->threshold--; } - if(G_Ruleset_Skill() == SM_NIGHTMARE || - G_Ruleset_Fast()) + if(gfw_Rule(skill) == SM_NIGHTMARE || + gfw_Rule(fast)) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; @@ -660,7 +660,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) { newChaseDir(actor); } @@ -681,7 +681,7 @@ // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { - if(!(G_Ruleset_Skill() != SM_NIGHTMARE && actor->moveCount)) + if(!(gfw_Rule(skill) != SM_NIGHTMARE && actor->moveCount)) { if(P_CheckMissileRange(actor)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_inter.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_inter.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_inter.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_inter.c 2018-12-11 07:08:23.000000000 +0000 @@ -36,7 +36,8 @@ #define BONUSADD (6) // Maximum number of rounds for each ammo type. -int maxAmmo[NUM_AMMO_TYPES] = { 100, 50, 200, 200, 20, 150 }; +// (initialized in initAmmoInfo()) +int maxAmmo[NUM_AMMO_TYPES]; // Numer of rounds to give with a backpack for each ammo type. int backpackAmmo[NUM_AMMO_TYPES] = { 10, 5, 10, 20, 1, 0 }; @@ -68,8 +69,8 @@ } // Give extra rounds at easy/nightmare skill levels. - if(G_Ruleset_Skill() == SM_BABY || - G_Ruleset_Skill() == SM_NIGHTMARE) + if(gfw_Rule(skill) == SM_BABY || + gfw_Rule(skill) == SM_NIGHTMARE) { numRounds += numRounds >> 1; } @@ -147,7 +148,7 @@ plr->update |= PSF_OWNED_WEAPONS; // Animate a pickup bonus flash? - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) { plr->bonusCount += BONUSADD; } @@ -429,7 +430,7 @@ { mo->flags &= ~MF_SPECIAL; - if(G_Ruleset_Deathmatch() && (mo->type != MT_ARTIINVULNERABILITY) && + if(gfw_Rule(deathmatch) && (mo->type != MT_ARTIINVULNERABILITY) && (mo->type != MT_ARTIINVISIBILITY)) { P_MobjChangeState(mo, S_DORMANTARTI1); @@ -555,7 +556,7 @@ if(plr->weapons[weaponType].owned) { // Leave placed weapons forever on net games. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) return false; } @@ -573,7 +574,7 @@ } // Leave placed weapons forever on net games. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) return false; return pickedWeapon; @@ -956,7 +957,7 @@ break; default: - if(G_Ruleset_Deathmatch() && !(special->flags & MF_DROPPED)) + if(gfw_Rule(deathmatch) && !(special->flags & MF_DROPPED)) { special->flags &= ~MF_SPECIAL; special->flags2 |= MF2_DONTDRAW; @@ -1126,43 +1127,32 @@ static dd_bool morphMonster(mobj_t *actor) { - mobj_t *fog, *chicken, *target; + mobj_t * fog, *chicken, *target; mobjtype_t moType; - coord_t pos[3]; - angle_t angle; - int ghost; + coord_t pos[3]; + angle_t angle; + int ghost; DENG_ASSERT(actor != 0); - if(actor->player) - return false; + if (actor->player) return false; - moType = actor->type; - switch(moType) - { - case MT_POD: - case MT_CHICKEN: - case MT_HEAD: - case MT_MINOTAUR: - case MT_SORCERER1: - case MT_SORCERER2: - return false; + // Originally hardcoded to specific mobj types. + if (actor->flags3 & MF3_NOMORPH) return false; - default: - break; - } + moType = actor->type; memcpy(pos, actor->origin, sizeof(pos)); - angle = actor->angle; - ghost = actor->flags & MF_SHADOW; + angle = actor->angle; + ghost = actor->flags & MF_SHADOW; target = actor->target; - if((chicken = P_SpawnMobj(MT_CHICKEN, pos, angle, 0))) + if ((chicken = P_SpawnMobj(MT_CHICKEN, pos, angle, 0))) { P_MobjChangeState(actor, S_FREETARGMOBJ); - if((fog = P_SpawnMobjXYZ(MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, - angle + ANG180, 0))) + if ((fog = P_SpawnMobjXYZ( + MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, angle + ANG180, 0))) S_StartSound(SFX_TELEPT, fog); chicken->special2 = moType; @@ -1204,7 +1194,7 @@ if(!player->plr->mo) return; /// @todo Do this in the inventory code? - if(G_Ruleset_Skill() == SM_BABY && normalCount * 25 >= saveHealth) + if(gfw_Rule(skill) == SM_BABY && normalCount * 25 >= saveHealth) { // Use quartz flasks. count = (saveHealth + 24) / 25; @@ -1224,7 +1214,7 @@ P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } - else if(G_Ruleset_Skill() == SM_BABY && + else if(gfw_Rule(skill) == SM_BABY && superCount * 100 + normalCount * 25 >= saveHealth) { // Use mystic urns and quartz flasks. @@ -1292,7 +1282,7 @@ if(source && source->player && source->player != target->player) { // Co-op damage disabled? - if(IS_NETGAME && !G_Ruleset_Deathmatch() && cfg.noCoopDamage) + if(IS_NETGAME && !gfw_Rule(deathmatch) && cfg.noCoopDamage) return 0; // Same color, no damage? @@ -1314,7 +1304,7 @@ } player = target->player; - if(player && G_Ruleset_Skill() == SM_BABY) + if(player && gfw_Rule(skill) == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the @@ -1542,7 +1532,7 @@ } if(damage >= player->health && - (G_Ruleset_Skill() == SM_BABY || G_Ruleset_Deathmatch()) && + (gfw_Rule(skill) == SM_BABY || gfw_Rule(deathmatch)) && !player->morphTics) { // Try to use some inventory health. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_maputl.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_maputl.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_maputl.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_maputl.c 2018-12-11 07:08:23.000000000 +0000 @@ -127,7 +127,7 @@ Mobj_TouchedLinesIterator(mo, PIT_ApplyTorque, mo); // If any momentum, mark object as 'falling' using engine-internal flags - if(!FEQUAL(mo->mom[MX], 0) || !FEQUAL(mo->mom[MY], 0)) + if(NON_ZERO(mo->mom[MX]) || NON_ZERO(mo->mom[MY])) { mo->intFlags |= MIF_FALLING; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_mobj.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_mobj.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_mobj.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_mobj.c 2018-12-11 07:08:23.000000000 +0000 @@ -244,7 +244,7 @@ mo->mom[MX] = mom[MX]; mo->mom[MY] = mom[MY]; - if(FEQUAL(mom[MX], 0) && FEQUAL(mom[MY], 0)) + if(IS_ZERO(mom[MX]) && IS_ZERO(mom[MY])) { if(mo->flags & MF_SKULLFLY) { @@ -383,9 +383,11 @@ // Adjust height. mo->origin[VZ] += mo->mom[MZ]; - if((mo->flags2 & MF2_FLY) && - mo->onMobj && mo->origin[VZ] > mo->onMobj->origin[VZ] + mo->onMobj->height) + if ((mo->flags2 & MF2_FLY) && mo->onMobj && + mo->origin[VZ] > mo->onMobj->origin[VZ] + mo->onMobj->height) + { mo->onMobj = NULL; // We were on a mobj, we are NOT now. + } if((mo->flags & MF_FLOAT) && mo->target && !P_MobjIsCamera(mo->target)) { @@ -447,17 +449,16 @@ } // Do some fly-bobbing. - if(mo->player && mo->player->plr->mo == mo && - (mo->flags2 & MF2_FLY) && mo->origin[VZ] > mo->floorZ && - !mo->onMobj && (mapTime & 2)) + if (mo->player && mo->player->plr->mo == mo && (mo->flags2 & MF2_FLY) && + mo->origin[VZ] > mo->floorZ && !mo->onMobj && (mapTime & 2)) { mo->origin[VZ] += FIX2FLT(finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]); } // Clip movement. Another thing? - if(mo->onMobj && mo->origin[VZ] <= mo->onMobj->origin[VZ] + mo->onMobj->height) + if (mo->onMobj && mo->origin[VZ] <= mo->onMobj->origin[VZ] + mo->onMobj->height) { - if(mo->mom[MZ] < 0) + if (mo->mom[MZ] < 0) { if(mo->player && mo->mom[MZ] < -gravity * 8 && !(mo->flags2 & MF2_FLY)) { @@ -471,8 +472,10 @@ mo->mom[MZ] = 0; } - if(FEQUAL(mo->mom[MZ], 0)) + if (IS_ZERO(mo->mom[MZ])) + { mo->origin[VZ] = mo->onMobj->origin[VZ] + mo->onMobj->height; + } if((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { @@ -483,7 +486,8 @@ // The floor. if(mo->origin[VZ] <= mo->floorZ) - { // Hit the floor. + { + // Hit the floor. dd_bool movingDown; // Note (id): @@ -584,14 +588,14 @@ } else if(mo->flags2 & MF2_LOGRAV) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->flags & MF_NOGRAVITY)) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; @@ -666,43 +670,242 @@ P_MobjRemove(mobj, true); } +// Fake the zmovement so that we can check if a move is legal +// (from vanilla Heretic) +static void P_FakeZMovement(mobj_t *mo) +{ + coord_t dist = 0; + coord_t delta = 0; + // + // adjust height + // + mo->origin[VZ] += mo->mom[VZ]; + if (mo->flags & MF_FLOAT && mo->target) + { + // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) + { + dist = M_ApproxDistance(mo->origin[VX] - mo->target->origin[VX], + mo->origin[VY] - mo->target->origin[VY]); + delta = (mo->target->origin[VZ] + (mo->height / 2)) - mo->origin[VZ]; + if (delta < 0 && dist < -(delta * 3)) + mo->origin[VZ] -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->origin[VZ] += FLOATSPEED; + } + } + if (mo->player && mo->flags2 & MF2_FLY && !(mo->origin[VZ] <= mo->floorZ) && (mapTime & 2)) + { + mo->origin[VZ] += finesine[(FINEANGLES / 20 * mapTime >> 2) & FINEMASK]; + } + + // + // clip movement + // + if (mo->origin[VZ] <= mo->floorZ) + { + // Hit the floor + mo->origin[VZ] = mo->floorZ; + if (mo->mom[VZ] < 0) + { + mo->mom[VZ] = 0; + } + if (mo->flags & MF_SKULLFLY) + { + // The skull slammed into something + mo->mom[VZ] = -mo->mom[VZ]; + } + if (MOBJINFO[mo->type].states[SN_CRASH] && (mo->flags & MF_CORPSE)) + { + return; + } + } + else if (mo->flags2 & MF2_LOGRAV) + { + coord_t GRAVITY = XS_Gravity(Mobj_Sector(mo)); + + if (FEQUAL(mo->mom[VZ], 0)) + mo->mom[VZ] = -(GRAVITY / 8) * 2; + else + mo->mom[VZ] -= GRAVITY / 8; + } + else if (!(mo->flags & MF_NOGRAVITY)) + { + coord_t GRAVITY = XS_Gravity(Mobj_Sector(mo)); + + if (FEQUAL(mo->mom[VZ], 0)) + mo->mom[VZ] = -GRAVITY * 2; + else + mo->mom[VZ] -= GRAVITY; + } + + if (mo->origin[VZ] + mo->height > mo->ceilingZ) + { + // hit the ceiling + if (mo->mom[VZ] > 0) mo->mom[VZ] = 0; + mo->origin[VZ] = mo->ceilingZ - mo->height; + if (mo->flags & MF_SKULLFLY) + { + // the skull slammed into something + mo->mom[VZ] = -mo->mom[VZ]; + } + } +} + +struct checkonmobjz_s +{ + mobj_t *checkThing; + mobj_t *onMobj; +}; + +static int PIT_CheckOnmobjZ(mobj_t *thing, void *dataPtr) +{ + struct checkonmobjz_s *data = dataPtr; + const mobj_t * tmthing = data->checkThing; + coord_t blockdist; + + if (thing == tmthing) + { + // Don't clip against self + return false; + } + if (!(thing->flags & (MF_SOLID | MF_SPECIAL | MF_SHOOTABLE))) + { + // Can't hit thing + return false; + } + blockdist = thing->radius + tmthing->radius; + if (fabs(thing->origin[VX] - tmthing->origin[VX]) >= blockdist || + fabs(thing->origin[VY] - tmthing->origin[VY]) >= blockdist) + { + // Didn't hit thing + return false; + } + if (tmthing->origin[VZ] > thing->origin[VZ] + thing->height) + { + return false; + } + else if (tmthing->origin[VZ] + tmthing->height < thing->origin[VZ]) + { + // under thing + return false; + } + if (thing->flags & MF_SOLID) + { + data->onMobj = thing; + } + return (thing->flags & MF_SOLID) != 0; +} + +// Checks if the new Z position is legal +// (from vanilla Heretic) +static mobj_t *P_CheckOnmobj(mobj_t *thing) +{ +#if 0 + int xl,xh,yl,yh,bx,by; + subsector_t *newsubsec; + fixed_t x; + fixed_t y; + mobj_t oldmo; + + x = thing->x; + y = thing->y; + tmthing = thing; + tmflags = thing->flags; + oldmo = *thing; // save the old mobj before the fake zmovement + P_FakeZMovement(tmthing); +#endif + + coord_t oldOrigin[3]; + coord_t oldMom[3]; + AABoxd bounds; + + struct checkonmobjz_s data = {thing, NULL}; + + memcpy(oldOrigin, thing->origin, sizeof(oldOrigin)); + memcpy(oldMom, thing->mom, sizeof(oldMom)); + + P_FakeZMovement(thing); + +// tmx = x; +// tmy = y; + +// tmbbox[BOXTOP] = y + tmthing->radius; +// tmbbox[BOXBOTTOM] = y - tmthing->radius; +// tmbbox[BOXRIGHT] = x + tmthing->radius; +// tmbbox[BOXLEFT] = x - tmthing->radius; + +// newsubsec = R_PointInSubsector (x,y); +// ceilingline = NULL; + +//// +//// the base floor / ceiling is from the subsector that contains the +//// point. Any contacted lines the step closer together will adjust them +//// +// tmfloorz = tmdropoffz = newsubsec->sector->floorheight; +// tmceilingz = newsubsec->sector->ceilingheight; + +// validcount++; +// numspechit = 0; + + if (!(thing->flags & MF_NOCLIP)) + { + bounds.minX = thing->origin[VX] - thing->radius; + bounds.minY = thing->origin[VY] - thing->radius; + bounds.maxX = thing->origin[VX] + thing->radius; + bounds.maxY = thing->origin[VY] + thing->radius; + + VALIDCOUNT++; + Mobj_BoxIterator(&bounds, PIT_CheckOnmobjZ, &data); + } + + // Restore state. + memcpy(thing->origin, oldOrigin, sizeof(oldOrigin)); + memcpy(thing->mom, oldMom, sizeof(oldMom)); + + return data.onMobj; +} + void P_MobjThinker(void *thinkerPtr) { mobj_t *mobj = thinkerPtr; - if(IS_CLIENT && !ClMobj_IsValid(mobj)) - return; // We should not touch this right now. + if (IS_CLIENT && !ClMobj_IsValid(mobj)) return; // We should not touch this right now. - if(mobj->type == MT_BLASTERFX1) + if (mobj->type == MT_BLASTERFX1) { - int i; + int i; coord_t frac[3]; coord_t z; dd_bool changexy; // Handle movement - if(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0) || !FEQUAL(mobj->mom[MZ], 0) || - !FEQUAL(mobj->origin[VZ], mobj->floorZ)) + if (NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY]) || NON_ZERO(mobj->mom[MZ]) || + !FEQUAL(mobj->origin[VZ], mobj->floorZ)) { frac[MX] = mobj->mom[MX] / 8; frac[MY] = mobj->mom[MY] / 8; frac[MZ] = mobj->mom[MZ] / 8; - changexy = (!FEQUAL(frac[MX], 0) || !FEQUAL(frac[MY], 0)); - for(i = 0; i < 8; ++i) + changexy = (NON_ZERO(frac[MX]) || NON_ZERO(frac[MY])); + for (i = 0; i < 8; ++i) { - if(changexy) + if (changexy) { - if(!P_TryMoveXY(mobj, mobj->origin[VX] + frac[MX], - mobj->origin[VY] + frac[MY], false, false)) - { // Blocked move. + if (!P_TryMoveXY(mobj, + mobj->origin[VX] + frac[MX], + mobj->origin[VY] + frac[MY], + false, + false)) + { + // Blocked move. P_ExplodeMissile(mobj); return; } } mobj->origin[VZ] += frac[MZ]; - if(mobj->origin[VZ] <= mobj->floorZ) + if (mobj->origin[VZ] <= mobj->floorZ) { // Hit the floor. mobj->origin[VZ] = mobj->floorZ; @@ -711,35 +914,40 @@ return; } - if(mobj->origin[VZ] + mobj->height > mobj->ceilingZ) - { // Hit the ceiling. + if (mobj->origin[VZ] + mobj->height > mobj->ceilingZ) + { + // Hit the ceiling. mobj->origin[VZ] = mobj->ceilingZ - mobj->height; P_ExplodeMissile(mobj); return; } - if(changexy && (P_Random() < 64)) + if (changexy && (P_Random() < 64)) { z = mobj->origin[VZ] - 8; - if(z < mobj->floorZ) + if (z < mobj->floorZ) { z = mobj->floorZ; } - P_SpawnMobjXYZ(MT_BLASTERSMOKE, mobj->origin[VX], mobj->origin[VY], - z, P_Random() << 24, 0); + P_SpawnMobjXYZ(MT_BLASTERSMOKE, + mobj->origin[VX], + mobj->origin[VY], + z, + P_Random() << 24, + 0); } } } // Advance the state. - if(mobj->tics != -1) + if (mobj->tics != -1) { mobj->tics--; - while(!mobj->tics) + while (!mobj->tics) { - if(!P_MobjChangeState(mobj, mobj->state->nextState)) - { // Mobj was removed. + if (!P_MobjChangeState(mobj, mobj->state->nextState)) + { // Mobj was removed. return; } } @@ -753,69 +961,101 @@ P_UpdateHealthBits(mobj); // Handle X and Y momentums. - if(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0) || (mobj->flags & MF_SKULLFLY)) + if (NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY]) || (mobj->flags & MF_SKULLFLY)) { - // Detect moves into invalid positions. - /* -#if _DEBUG - dd_bool beforeOk = P_CheckPosition(mobj, mobj->origin); -#endif - */ - P_MobjMoveXY(mobj); - //assert(!beforeOk || P_CheckPosition(mobj, mobj->origin)); - - //// @todo decent NOP/NULL/Nil function pointer please. - if(mobj->thinker.function == (thinkfunc_t) NOPFUNC) + if (mobj->thinker.function == (thinkfunc_t) NOPFUNC) + { return; // Mobj was removed. + } } - if(mobj->flags2 & MF2_FLOATBOB) - { // Floating item bobbing motion. + if (mobj->flags2 & MF2_FLOATBOB) + { + // Floating item bobbing motion. // Keep it on the floor. mobj->origin[VZ] = mobj->floorZ; // Negative floorclip raises the mobj off the floor. mobj->floorClip = -mobj->special1; - if(mobj->floorClip < -MAX_BOB_OFFSET) + if (mobj->floorClip < -MAX_BOB_OFFSET) { // We don't want it going through the floor. mobj->floorClip = -MAX_BOB_OFFSET; } } - else if(!FEQUAL(mobj->origin[VZ], mobj->floorZ) || !FEQUAL(mobj->mom[MZ], 0)) + else if (!FEQUAL(mobj->origin[VZ], mobj->floorZ) || NON_ZERO(mobj->mom[MZ])) { coord_t oldZ = mobj->origin[VZ]; - P_MobjMoveZ(mobj); - if(mobj->thinker.function != (thinkfunc_t) P_MobjThinker) - return; // mobj was removed + if (mobj->type == MT_POD) + { + // Use vanilla behavior for gas pods. The newer routines do not produce the + // correct behavior when pods interact with each other. + if ((mobj->onMobj = P_CheckOnmobj(mobj)) == NULL) + { + P_MobjMoveZ(mobj); + } + else + { + // Stop pod's downward momentum when landing on something. + if (/*mobj->player &&*/ mobj->mom[VZ] < 0) + { + mobj->mom[VZ] = 0; + } + // This is exclusive to pods, so the code below is not relevant. + /* + if (mobj->player && (onmo->player || onmo->type == MT_POD)) + { + mobj->mom[VX] = onmo->mom[VX]; + mobj->mom[VY] = onmo->mom[VY]; + if (onmo->origin[VZ] < onmo->floorZ) + { + mobj->origin[VZ] += onmo->floorZ - onmo->origin[VZ]; + if (onmo->player) + { + onmo->player->viewHeight -= onmo->floorZ - onmo->origin[VZ]; + onmo->player->viewHeightDelta = + (VIEWHEIGHT - onmo->player->viewHeight) / 8; + } + onmo->origin[VZ] = onmo->floorZ; + } + } + */ + } + } + else + { + P_MobjMoveZ(mobj); + } + + if (mobj->thinker.function != (thinkfunc_t) P_MobjThinker) return; // mobj was removed /** * @todo Instead of this post-move check, we should fix the root cause why * the SKULLFLYer is ending up in an invalid position during P_MobjMoveZ(). * If only the movement validity checks weren't so convoluted... -jk */ - if((mobj->flags & MF_SKULLFLY) && !P_CheckPosition(mobj, mobj->origin)) + if ((mobj->flags & MF_SKULLFLY) && !P_CheckPosition(mobj, mobj->origin)) { // Let's not get stuck. - if(mobj->origin[VZ] > oldZ && mobj->mom[VZ] > 0) mobj->mom[VZ] = 0; - if(mobj->origin[VZ] < oldZ && mobj->mom[VZ] < 0) mobj->mom[VZ] = 0; + if (mobj->origin[VZ] > oldZ && mobj->mom[VZ] > 0) mobj->mom[VZ] = 0; + if (mobj->origin[VZ] < oldZ && mobj->mom[VZ] < 0) mobj->mom[VZ] = 0; mobj->origin[VZ] = oldZ; } } // Non-sentient objects at rest. - else if(!(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0)) && !sentient(mobj) && - !mobj->player && !((mobj->flags & MF_CORPSE) && cfg.slidingCorpses)) + else if (!(NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY])) && !sentient(mobj) && + !mobj->player && !((mobj->flags & MF_CORPSE) && cfg.slidingCorpses)) { /** * Objects fall off ledges if they are hanging off slightly push off * of ledge if hanging more than halfway off. */ - if(mobj->origin[VZ] > mobj->dropOffZ && // Only objects contacting dropoff - !(mobj->flags & MF_NOGRAVITY) && cfg.fallOff) + if (mobj->origin[VZ] > mobj->dropOffZ && // Only objects contacting dropoff + !(mobj->flags & MF_NOGRAVITY) && cfg.fallOff) { P_ApplyTorque(mobj); } @@ -826,11 +1066,12 @@ } } - if(cfg.slidingCorpses) + if (cfg.slidingCorpses) { - if(((mobj->flags & MF_CORPSE) ? mobj->origin[VZ] > mobj->dropOffZ : - mobj->origin[VZ] - mobj->dropOffZ > 24) && // Only objects contacting drop off. - !(mobj->flags & MF_NOGRAVITY)) // Only objects which fall. + if (((mobj->flags & MF_CORPSE) + ? mobj->origin[VZ] > mobj->dropOffZ + : mobj->origin[VZ] - mobj->dropOffZ > 24) && // Only objects contacting drop off. + !(mobj->flags & MF_NOGRAVITY)) // Only objects which fall. { P_ApplyTorque(mobj); // Apply torque. } @@ -842,18 +1083,17 @@ } // $vanish: dead monsters disappear after some time. - if(cfg.corpseTime && (mobj->flags & MF_CORPSE) && mobj->corpseTics != -1) + if (cfg.corpseTime && (mobj->flags & MF_CORPSE) && mobj->corpseTics != -1) { - if(++mobj->corpseTics < cfg.corpseTime * TICSPERSEC) + if (++mobj->corpseTics < cfg.corpseTime * TICSPERSEC) { mobj->translucency = 0; // Opaque. } - else if(mobj->corpseTics < cfg.corpseTime * TICSPERSEC + VANISHTICS) + else if (mobj->corpseTics < cfg.corpseTime * TICSPERSEC + VANISHTICS) { // Translucent during vanishing. mobj->translucency = - ((mobj->corpseTics - - cfg.corpseTime * TICSPERSEC) * 255) / VANISHTICS; + ((mobj->corpseTics - cfg.corpseTime * TICSPERSEC) * 255) / VANISHTICS; } else { @@ -864,39 +1104,33 @@ } // Cycle through states, calling action functions at transitions. - if(mobj->tics != -1) + if (mobj->tics != -1) { mobj->tics--; P_MobjAngleSRVOTicker(mobj); // "angle-servo"; smooth actor turning. // You can cycle through multiple states in a tic. - if(!mobj->tics) + if (!mobj->tics) { P_MobjClearSRVO(mobj); - if(!P_MobjChangeState(mobj, mobj->state->nextState)) - return; // Freed itself. + if (!P_MobjChangeState(mobj, mobj->state->nextState)) return; // Freed itself. } } - else if(!IS_CLIENT) + else if (!IS_CLIENT) { // Check for nightmare respawn. - if(!(mobj->flags & MF_COUNTKILL)) - return; + if (!(mobj->flags & MF_COUNTKILL)) return; - if(!G_Ruleset_RespawnMonsters()) - return; + if (!gfw_Rule(respawnMonsters)) return; mobj->moveCount++; - if(mobj->moveCount < 12 * 35) - return; + if (mobj->moveCount < 12 * 35) return; - if(mapTime & 31) - return; + if (mapTime & 31) return; - if(P_Random() > 4) - return; + if (P_Random() > 4) return; P_NightmareRespawn(mobj); } @@ -930,7 +1164,7 @@ */ // Not for deathmatch? - if(G_Ruleset_Deathmatch() && (info->flags & MF_NOTDMATCH)) + if(gfw_Rule(deathmatch) && (info->flags & MF_NOTDMATCH)) return NULL; // Check for specific disabled objects. @@ -958,7 +1192,7 @@ } // Don't spawn any monsters? - if(G_Ruleset_NoMonsters() && (info->flags & MF_COUNTKILL)) + if(gfw_Rule(noMonsters) && (info->flags & MF_COUNTKILL)) return 0; if(info->flags & MF_SOLID) @@ -979,7 +1213,7 @@ mo->selector = 0; P_UpdateHealthBits(mo); // Set the health bits of the selector. - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) mo->reactionTime = info->reactionTime; mo->lastLook = P_Random() % MAXPLAYERS; @@ -1056,6 +1290,12 @@ mapspot_t const *mapSpot; Sector *sector; + if (gfw_MapInfoFlags() & MIF_SPAWN_ALL_FIREMACES) + { + // Randomized Firemace spawning is disabled. + return; + } + DENG_ASSERT(mo && mo->type == MT_WMACE); App_Log(DE2_DEV_MAP_MSG, "P_RepositionMace: Repositioning mobj [%p], thinkerId:%i", mo, mo->thinker.id); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_pspr.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_pspr.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_pspr.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_pspr.c 2018-12-11 07:08:23.000000000 +0000 @@ -718,7 +718,7 @@ } if(ball->special3 != MAGIC_JUNK && ball->origin[VZ] <= ball->floorZ && - !FEQUAL(ball->mom[MZ], 0)) + NON_ZERO(ball->mom[MZ])) { // Bounce. ball->special3 = MAGIC_JUNK; @@ -824,7 +824,7 @@ return; } - if(ball->origin[VZ] <= ball->floorZ && !FEQUAL(ball->mom[MZ], 0)) + if(ball->origin[VZ] <= ball->floorZ && NON_ZERO(ball->mom[MZ])) { // Bounce. newAngle = false; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_spec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_spec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_spec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_spec.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -391,7 +391,7 @@ case 52: // EXIT! - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); break; case 53: @@ -438,7 +438,7 @@ case 105: // Secret EXIT - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); break; case 106: @@ -1000,7 +1000,7 @@ if(cyclingMaps && mapCycleNoExit) break; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("next")); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("next")); P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0); xline->special = 0; break; @@ -1097,7 +1097,7 @@ if(cyclingMaps && mapCycleNoExit) break; - G_SetGameActionMapCompleted(COMMON_GAMESESSION->mapUriForNamedExit("secret"), 0, true); + G_SetGameActionMapCompleted(gfw_Session()->mapUriForNamedExit("secret"), 0, true); P_ToggleSwitch((Side *)P_GetPtrp(line, DMU_FRONT), SFX_NONE, false, 0); xline->special = 0; break; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_telept.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_telept.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/p_telept.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/p_telept.c 2018-12-11 07:08:23.000000000 +0000 @@ -223,7 +223,7 @@ playerstart_t const *start; // Get a random deathmatch start. - if((start = P_GetPlayerStart(0, G_Ruleset_Deathmatch()? -1 : 0, G_Ruleset_Deathmatch()))) + if((start = P_GetPlayerStart(0, gfw_Rule(deathmatch)? -1 : 0, gfw_Rule(deathmatch)))) { mapspot_t const *spot = &mapSpots[start->spot]; P_Teleport(player->plr->mo, spot->origin[VX], spot->origin[VY], spot->angle, true); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/st_stuff.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/st_stuff.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/heretic/src/st_stuff.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/heretic/src/st_stuff.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -165,7 +165,10 @@ if(offset) DGL_Translatef(offset->x, offset->y, 0); DGL_Scalef(cfg.common.statusbarScale, cfg.common.statusbarScale, 1); - if(!(iconOpacity < 1)) + const bool godEyes = ((P_GetPlayerCheats(&players[wi->player()]) & CF_GODMODE) || + players[wi->player()].powers[PT_INVULNERABILITY]); + + if (!(iconOpacity < 1)) { // We can just render the full thing as normal. // Top bits. @@ -178,14 +181,14 @@ // Faces. GL_DrawPatch(pStatusbar, Vector2i(ORIGINX, ORIGINY)); - if(P_GetPlayerCheats(&players[wi->player()]) & CF_GODMODE) + if (godEyes) { GL_DrawPatch(pGodLeft, Vector2i(ORIGINX + 16 , ORIGINY + 9)); GL_DrawPatch(pGodRight, Vector2i(ORIGINX + 287, ORIGINY + 9)); } patchid_t panel = Hu_InventoryIsOpen(wi->player())? pInvBar - : G_Ruleset_Deathmatch() ? pStatBar : pLifeBar; + : gfw_Rule(deathmatch) ? pStatBar : pLifeBar; GL_DrawPatch(panel, Vector2i(ORIGINX + 34, ORIGINY + 2)); DGL_Disable(DGL_TEXTURE_2D); @@ -209,7 +212,7 @@ DGL_DrawCutRectf2Tiled(ORIGINX+34, ORIGINY+33, 248, 9, 320, 42, 34, 33, ORIGINX, ORIGINY+191, 16, 8); // Faces. - if(P_GetPlayerCheats(&players[wi->player()]) & CF_GODMODE) + if (godEyes) { // If GOD mode we need to cut windows DGL_DrawCutRectf2Tiled(ORIGINX, ORIGINY, 34, 42, 320, 42, 0, 0, ORIGINX+16, ORIGINY+9, 16, 8); @@ -225,7 +228,7 @@ } patchid_t panel = Hu_InventoryIsOpen(wi->player())? pInvBar - : G_Ruleset_Deathmatch() ? pStatBar : pLifeBar; + : gfw_Rule(deathmatch) ? pStatBar : pLifeBar; GL_DrawPatch(panel, Vector2i(ORIGINX + 34, ORIGINY + 2)); DGL_Disable(DGL_TEXTURE_2D); @@ -736,7 +739,7 @@ automap.clearAllPoints(true/*silent*/); #if !__JHEXEN__ - if(G_Ruleset_Skill() == SM_BABY && cfg.common.automapBabyKeys) + if(gfw_Rule(skill) == SM_BABY && cfg.common.automapBabyKeys) { automap.setFlags(automap.flags() | AWF_SHOW_KEYS); } @@ -750,7 +753,7 @@ // Are we re-centering on a followed mobj? if(mobj_t *mob = automap.followMobj()) { - automap.setCameraOrigin(Vector2d(mob->origin)); + automap.setCameraOrigin(Vector2d(mob->origin), true); } if(IS_NETGAME) @@ -1204,9 +1207,9 @@ void ST_SetAutomapCameraRotation(int localPlayer, dd_bool yes) { - if(auto *autmap = ST_TryFindAutomapWidget(localPlayer)) + if(auto *automap = ST_TryFindAutomapWidget(localPlayer)) { - autmap->setCameraRotationMode(CPP_BOOL(yes)); + automap->setCameraRotationMode(CPP_BOOL(yes)); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/defs/flags.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/defs/flags.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/defs/flags.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/defs/flags.ded 2018-12-11 07:08:23.000000000 +0000 @@ -1,4 +1,4 @@ -# libhexen: Flags +# Hexen: Flags # Mobj flags: Flag { ID = "mf_special"; Value = 0x1; } @@ -70,6 +70,8 @@ # Mobj flags3: Flag { ID = "mf3_noinfight"; Value = 0x1; } Flag { ID = "mf3_clientaction"; Value = 0x2; } +Flag { ID = "mf3_noblast"; Value = 0x4; } +Flag { ID = "mf3_nomorph"; Value = 0x8; } # # Obsolete (unused) flags: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/defs/objects.ded doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/defs/objects.ded --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/defs/objects.ded 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/defs/objects.ded 2018-12-11 07:08:23.000000000 +0000 @@ -6947,6 +6947,7 @@ Mass = 60; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_windthrust mf2_floorclip mf2_passmobj mf2_pushwall mf2_telestomp"; + Flags3 = "mf3_nomorph"; } Thing { @@ -9144,6 +9145,7 @@ Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; + Flags3 = "mf3_nomorph"; } Thing { @@ -9171,6 +9173,7 @@ Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; + Flags3 = "mf3_nomorph"; } Thing { @@ -9198,6 +9201,7 @@ Mass = 100; Flags = "mf_solid mf_shootable mf_countkill"; Flags2 = "mf2_floorclip mf2_passmobj mf2_telestomp mf2_pushwall mf2_mcross"; + Flags3 = "mf3_nomorph"; } Thing { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/h2def.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/h2def.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/h2def.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/h2def.h 2018-12-11 07:08:23.000000000 +0000 @@ -81,8 +81,6 @@ #define Set DD_SetInteger #define Get DD_GetInteger -DENG_EXTERN_C game_export_t gx; - // // Global parameters/defines. // diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/p_mobj.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/p_mobj.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/p_mobj.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/p_mobj.h 2018-12-11 07:08:23.000000000 +0000 @@ -159,7 +159,8 @@ #define MF3_NOINFIGHT 0x00000001 // Mobj will never be targeted for in-fighting #define MF3_CLIENTACTION 0x00000002 // States' action funcs are executed by client -#define MF3_NOBLAST 0x00000004 // Never affected by A_BlastRadius. +#define MF3_NOBLAST 0x00000004 // Never affected by A_BlastRadius +#define MF3_NOMORPH 0x00000008 // Mobj cannot be morphed to Pig typedef enum dirtype_s { DI_EAST, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/p_sound.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/p_sound.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/p_sound.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/p_sound.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,46 +0,0 @@ -/** - * @file p_sound.h - * Sound related utility routines. - * - * @authors Copyright © 2004-2017 Jaakko Keränen - * @authors Copyright © 2007-2013 Daniel Swanson - * - * @par License - * GPL: http://www.gnu.org/licenses/gpl.html - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. This program is distributed in the hope that it - * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty - * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General - * Public License for more details. You should have received a copy of the GNU - * General Public License along with this program; if not, write to the Free - * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - */ - -#ifndef LIBHEXEN_SOUND_H -#define LIBHEXEN_SOUND_H - -#ifndef __JHEXEN__ -# error "Using jHexen headers without __JHEXEN__" -#endif - -#define MAX_SND_DIST (2025) -#define MAX_CHANNELS (16) - -int S_GetSoundID(const char* name); - -/** - * Starts the song of the specified map, updating the currentmap definition - * in the process. - * - * @param episode Logical episode. - * @param map Logical map number. - */ -void S_MapMusic(uint episode, uint map); - -void S_ParseSndInfoLump(void); - -#endif // LIBHEXEN_SOUND_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/version.h 2018-12-11 07:08:23.000000000 +0000 @@ -64,6 +64,6 @@ // For WIN32 version info: #define PLUGIN_DESC PLUGIN_NICENAME " " LIBDENG_PLUGINDESC -#define PLUGIN_COPYRIGHT "1999-2013, " DENGPROJECT_NICEAUTHOR +#define PLUGIN_COPYRIGHT "1999-2018, " DENGPROJECT_NICEAUTHOR #endif /* JHEXEN_VERSION_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/x_api.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/x_api.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/x_api.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/x_api.h 2018-12-11 07:08:23.000000000 +0000 @@ -39,8 +39,6 @@ extern "C" { #endif -extern game_export_t gx; - DENG_USING_API(Base); DENG_USING_API(B); DENG_USING_API(Busy); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/x_main.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/x_main.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/include/x_main.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/include/x_main.h 2018-12-11 07:08:23.000000000 +0000 @@ -27,8 +27,6 @@ #include "h2def.h" -DENG_EXTERN_C float turboMul; // Multiplier for turbo. - DENG_EXTERN_C gamemode_t gameMode; DENG_EXTERN_C int gameModeBits; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/a_action.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/a_action.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/a_action.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/a_action.c 2018-12-11 07:08:23.000000000 +0000 @@ -86,7 +86,7 @@ if(actor->args[0]) { // Spawn an item. - if(!G_Ruleset_NoMonsters() || + if(!gfw_Rule(noMonsters) || !(MOBJINFO[TranslateThingType[actor->args[0]]]. flags & MF_COUNTKILL)) { @@ -237,7 +237,7 @@ if(P_Random() > 64) { - if(FEQUAL(actor->mom[MX], 0) && FEQUAL(actor->mom[MY], 0)) + if(IS_ZERO(actor->mom[MX]) && IS_ZERO(actor->mom[MY])) { P_ThrustMobj(actor, actor->target->angle, FIX2FLT(P_Random() << 9) + 1); @@ -858,7 +858,7 @@ if(actor->args[0]) { // Spawn an item. - if(!G_Ruleset_NoMonsters() || + if(!gfw_Rule(noMonsters) || !(MOBJINFO[TranslateThingType[actor->args[0]]]. flags & MF_COUNTKILL)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/h2_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/h2_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/h2_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/h2_main.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -43,8 +43,6 @@ using namespace de; using namespace common; -float turboMul; // Multiplier for turbo. - gamemode_t gameMode; int gameModeBits; @@ -245,7 +243,7 @@ cfg.common.automapBack[2] = 1.0f; cfg.common.automapOpacity = 1.0f; cfg.common.automapLineAlpha = 1.0f; - cfg.common.automapLineWidth = 1.1f; + cfg.common.automapLineWidth = 3.0f; cfg.common.automapShowDoors = true; cfg.common.automapDoorGlow = 8; cfg.common.automapHudDisplay = 2; @@ -310,45 +308,32 @@ P_InitWeaponInfo(); // Defaults for skill, episode and map. - ::defaultGameRules.skill = /*startSkill =*/ SM_MEDIUM; - - ::cfg.common.netDeathmatch = cmdLine.check("-deathmatch")? true : false; + gfw_SetDefaultRule(skill, /*startSkill =*/ SM_MEDIUM); - ::defaultGameRules.noMonsters = cmdLine.check("-nomonsters")? true : false; - ::defaultGameRules.randomClasses = cmdLine.check("-randclass") ? true : false; + ::cfg.common.netDeathmatch = cmdLine.check("-deathmatch") ? true : false; - // Change the turbo multiplier? - ::turboMul = 1.0f; - if(int arg = cmdLine.check("-turbo")) - { - int scale = 200; - if(arg + 1 < cmdLine.count() && !cmdLine.isOption(arg + 1)) - { - scale = cmdLine.at(arg + 1).toInt(); - } - scale = de::clamp(10, scale, 400); - - LOG_NOTE("Turbo scale: %i%%") << scale; - ::turboMul = scale / 100.f; - } + gfw_SetDefaultRule(noMonsters, + cmdLine.has("-nomonsters") || + gfw_GameProfile()->optionValue("noMonsters").isTrue()); + gfw_SetDefaultRule(randomClasses, cmdLine.has("-randclass")); // Process sound definitions. SndInfoParser(AutoStr_FromText("Lumps:SNDINFO")); // Process sound sequence scripts. String scriptPath("Lumps:SNDSEQ"); - if(int arg = cmdLine.check("-scripts", 1)) + if (auto arg = cmdLine.check("-scripts", 1)) { - scriptPath = cmdLine.at(arg + 1) + "SNDSEQ.txt"; + scriptPath = arg.params.first()/"SNDSEQ.txt"; } SndSeqParser(AutoStr_FromTextStd(scriptPath.toUtf8().constData())); // Load a saved game? - if(int arg = cmdLine.check("-loadgame", 1)) + if (auto arg = cmdLine.check("-loadgame", 1)) { - if(SaveSlot *sslot = G_SaveSlots().slotByUserInput(cmdLine.at(arg + 1))) + if (SaveSlot *sslot = G_SaveSlots().slotByUserInput(arg.params.first())) { - if(sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) + if (sslot->isUserWritable() && G_SetGameActionLoadSession(sslot->id())) { // No further initialization is to be done. return; @@ -357,31 +342,31 @@ } // Change the default skill mode? - if(int arg = cmdLine.check("-skill", 1)) + if (auto arg = cmdLine.check("-skill", 1)) { - int skillNumber = cmdLine.at(arg + 1).toInt(); - ::defaultGameRules.skill = skillmode_t( skillNumber > 0? skillNumber - 1 : skillNumber ); + int const skillNumber = arg.params.first().toInt(); + gfw_SetDefaultRule(skill, skillmode_t(skillNumber > 0? skillNumber - 1 : skillNumber)); } // Change the default player class? playerclass_t defPlayerClass = PCLASS_NONE; - if(int arg = cmdLine.check("-class", 1)) + if (auto arg = cmdLine.check("-class", 1)) { bool isNumber; - playerclass_t pClass = playerclass_t( cmdLine.at(arg + 1).toInt(&isNumber) ); - if(isNumber && VALID_PLAYER_CLASS(pClass)) + int const pClass = arg.params.first().toInt(&isNumber); + if (isNumber && VALID_PLAYER_CLASS(pClass)) { - if(!PCLASS_INFO(pClass)->userSelectable) + if (!PCLASS_INFO(pClass)->userSelectable) { - LOG_WARNING("Non-user-selectable player class '%i' specified with -class") << int( pClass ); + LOG_WARNING("Non-user-selectable player class '%i' specified with -class") << pClass; } } else { - LOG_WARNING("Invalid player class '%i' specified with -class") << int( pClass ); + LOG_WARNING("Invalid player class '%i' specified with -class") << pClass; } } - if(defPlayerClass != PCLASS_NONE) + if (defPlayerClass != PCLASS_NONE) { ::cfg.playerClass[CONSOLEPLAYER] = defPlayerClass; LOG_NOTE("Player Class: '%s'") << PCLASS_INFO(defPlayerClass)->niceName; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/hrefresh.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/hrefresh.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/hrefresh.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/hrefresh.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -47,7 +47,7 @@ rgba[CR] = 1; rgba[CG] = 0; rgba[CB] = 0; - rgba[CA] = (G_Ruleset_Deathmatch()? 1.0f : cfg.common.filterStrength) * filter / 8.f; // Full red with filter 8. + rgba[CA] = (gfw_Rule(deathmatch)? 1.0f : cfg.common.filterStrength) * filter / 8.f; // Full red with filter 8. return true; } else if(filter >= STARTBONUSPALS && filter < STARTBONUSPALS + NUMBONUSPALS) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/intermission.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/intermission.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/intermission.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/intermission.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -132,7 +132,7 @@ void IN_Begin(wbstartstruct_t const & /*wbstartstruct*/) { - DENG2_ASSERT(G_Ruleset_Deathmatch()); + DENG2_ASSERT(gfw_Rule(deathmatch)); WI_initVariables(); loadPics(); @@ -296,7 +296,7 @@ } } - if(G_Ruleset_Deathmatch() && interTime < 140) + if(gfw_Rule(deathmatch) && interTime < 140) { // Wait for 4 seconds before allowing a skip. if(skipIntermission == 1) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/lightninganimator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/lightninganimator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/lightninganimator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/lightninganimator.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -21,6 +21,7 @@ #include "jhexen.h" #include "lightninganimator.h" +#include "g_common.h" #include #include "dmu_lib.h" @@ -216,17 +217,17 @@ d->nextFlash = 0; d->sectorLightLevels.clear(); - if(COMMON_GAMESESSION->mapInfo().geti("flags") & MIF_LIGHTNING) + if (gfw_MapInfoFlags() & MIF_LIGHTNING) { int numLightningSectors = 0; - for(int i = 0; i < numsectors; ++i) + for (int i = 0; i < numsectors; ++i) { - if(isLightningSector((Sector *)P_ToPtr(DMU_SECTOR, i))) + if (isLightningSector(static_cast(P_ToPtr(DMU_SECTOR, i)))) { numLightningSectors++; } } - if(numLightningSectors > 0) + if (numLightningSectors > 0) { d->sectorLightLevels.resize(numLightningSectors); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/m_cheat.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/m_cheat.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/m_cheat.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/m_cheat.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -21,9 +21,6 @@ #include "jhexen.h" #include "m_cheat.h" - -#include -#include #include "d_net.h" #include "d_netcl.h" #include "d_netsv.h" @@ -35,6 +32,10 @@ #include "p_inventory.h" #include "p_user.h" #include "player.h" +#include "acs/system.h" + +#include +#include typedef eventsequencehandler_t cheatfunc_t; @@ -52,7 +53,7 @@ static inline acs::System &acscriptSys() { - return COMMON_GAMESESSION->acsSystem(); + return gfw_Session()->acsSystem(); } CHEAT_FUNC(Class); @@ -101,7 +102,7 @@ player_t *plr = &players[player]; if(IS_NETGAME) return false; - if(G_Ruleset_Skill() == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -118,7 +119,7 @@ player_t *plr = &players[player]; - if(G_Ruleset_Skill() == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; if(plr->morphTics) return false; @@ -161,7 +162,7 @@ player_t *plr = &players[player]; - if(G_Ruleset_Skill() == SM_NIGHTMARE) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -208,8 +209,8 @@ player_t *plr = &players[player]; - if(IS_NETGAME && G_Ruleset_Deathmatch()) return false; - if(G_Ruleset_Skill() == SM_NIGHTMARE) return false; + if(IS_NETGAME && gfw_Rule(deathmatch)) return false; + if(gfw_Rule(skill) == SM_NIGHTMARE) return false; // Dead players can't cheat. if(plr->health <= 0) return false; @@ -253,7 +254,7 @@ { NetCl_CheatRequest("god"); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -292,7 +293,7 @@ { NetCl_CheatRequest("noclip"); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -457,7 +458,7 @@ return true; } - if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) return false; player_t *plr = &players[player]; @@ -637,7 +638,7 @@ { NetCl_CheatRequest("kill"); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -665,7 +666,7 @@ char textBuffer[256]; sprintf(textBuffer, "MAP [%s] X:%g Y:%g Z:%g", - COMMON_GAMESESSION->mapUri().path().toUtf8().constData(), + gfw_Session()->mapUri().path().toUtf8().constData(), plrMo->origin[VX], plrMo->origin[VY], plrMo->origin[VZ]); P_SetMessageWithFlags(plr, textBuffer, LMF_NO_HIDE); @@ -700,7 +701,7 @@ { NetCl_CheatRequest("pig"); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -748,7 +749,7 @@ AutoStr *cmd = Str_Appendf(AutoStr_NewStd(), "class %i", (int)newClass); NetCl_CheatRequest(Str_Text(cmd)); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } @@ -787,7 +788,7 @@ AutoStr *cmd = Str_Appendf(AutoStr_NewStd(), "runscript %i", scriptNum); NetCl_CheatRequest(Str_Text(cmd)); } - else if((IS_NETGAME && !netSvAllowCheats) || G_Ruleset_Skill() == SM_NIGHTMARE) + else if((IS_NETGAME && !netSvAllowCheats) || gfw_Rule(skill) == SM_NIGHTMARE) { return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_enemy.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_enemy.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_enemy.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_enemy.c 2018-12-11 07:08:23.000000000 +0000 @@ -535,7 +535,7 @@ actor->threshold--; } - if(G_Ruleset_Skill() == SM_NIGHTMARE /*|| gameRules.fast*/) + if(gfw_Rule(skill) == SM_NIGHTMARE /*|| gameRules.fast*/) { // Monsters move faster in nightmare mode actor->tics -= actor->tics / 2; @@ -575,7 +575,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) P_NewChaseDir(actor); return; } @@ -595,7 +595,7 @@ // Check for missile attack. if((state = P_GetState(actor->type, SN_MISSILE)) != S_NULL) { - if(!(G_Ruleset_Skill() != SM_NIGHTMARE && actor->moveCount)) + if(!(gfw_Rule(skill) != SM_NIGHTMARE && actor->moveCount)) { if(P_CheckMissileRange(actor)) { @@ -969,7 +969,7 @@ actor->target = 0; - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { // Quick search for players. int i; @@ -1684,7 +1684,7 @@ actor->threshold--; } - if(G_Ruleset_Skill() == SM_NIGHTMARE /*|| gameRules.fast*/) + if(gfw_Rule(skill) == SM_NIGHTMARE /*|| gameRules.fast*/) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; @@ -1723,7 +1723,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) P_NewChaseDir(actor); return; } @@ -1863,7 +1863,7 @@ actor->threshold--; } - if(G_Ruleset_Skill() == SM_NIGHTMARE /*|| gameRules.fast*/) + if(gfw_Rule(skill) == SM_NIGHTMARE /*|| gameRules.fast*/) { // Monsters move faster in nightmare mode. actor->tics -= actor->tics / 2; @@ -1902,7 +1902,7 @@ if(actor->flags & MF_JUSTATTACKED) { actor->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) P_NewChaseDir(actor); return; } @@ -3885,7 +3885,7 @@ mo->threshold--; } - if(G_Ruleset_Skill() == SM_NIGHTMARE /*|| gameRules.fast*/) + if(gfw_Rule(skill) == SM_NIGHTMARE /*|| gameRules.fast*/) { // Monsters move faster in nightmare mode. mo->tics -= mo->tics / 2; @@ -3923,7 +3923,7 @@ if(mo->flags & MF_JUSTATTACKED) { mo->flags &= ~MF_JUSTATTACKED; - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) P_NewChaseDir(mo); return; } @@ -3961,7 +3961,7 @@ // Check for missile attack. if((state = P_GetState(mo->type, SN_MISSILE)) != S_NULL) { - if(G_Ruleset_Skill() != SM_NIGHTMARE && mo->moveCount) + if(gfw_Rule(skill) != SM_NIGHTMARE && mo->moveCount) goto nomissile; if(!P_CheckMissileRange(mo)) goto nomissile; @@ -4018,7 +4018,7 @@ void C_DECL A_ClassBossHealth(mobj_t *mo) { - if(IS_NETGAME && !G_Ruleset_Deathmatch()) // Co-op only. + if(IS_NETGAME && !gfw_Rule(deathmatch)) // Co-op only. { if(!mo->special1) { @@ -4100,7 +4100,7 @@ mobj_t* pmo; int i; - if(!FEQUAL(mo->mom[MX], 0) || !FEQUAL(mo->mom[MY], 0) || !FEQUAL(mo->mom[MZ], 0)) + if(NON_ZERO(mo->mom[MX]) || NON_ZERO(mo->mom[MY]) || NON_ZERO(mo->mom[MZ])) { mo->tics = 105; return; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_inter.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_inter.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_inter.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_inter.c 2018-12-11 07:08:23.000000000 +0000 @@ -306,8 +306,8 @@ } // Give extra rounds at easy/nightmare skill levels. - if(G_Ruleset_Skill() == SM_BABY || - G_Ruleset_Skill() == SM_NIGHTMARE) + if(gfw_Rule(skill) == SM_BABY || + gfw_Rule(skill) == SM_NIGHTMARE) { numRounds += numRounds / 2; } @@ -371,7 +371,7 @@ // Always attempt to give mana unless this a cooperative game and the // player already has this weapon piece. - if(!(IS_NETGAME && !G_Ruleset_Deathmatch() && plr->weapons[weaponType].owned)) + if(!(IS_NETGAME && !gfw_Rule(deathmatch) && plr->weapons[weaponType].owned)) { if(P_GiveAmmo(plr, ammoType, 25)) { @@ -416,7 +416,7 @@ } // Leave placed weapons forever on net games. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) return false; return gaveWeapons != 0; @@ -447,7 +447,7 @@ if(plr->class_ != matchClass) { // Can't pick up wrong-class weapons in coop netplay. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) return false; return P_GiveAmmo(plr, AT_BLUEMANA, 20) | P_GiveAmmo(plr, AT_GREENMANA, 20); @@ -455,7 +455,7 @@ // Always attempt to give mana unless this a cooperative game and the // player already has this weapon piece. - if(!((plr->pieces & (1 << piece)) && IS_NETGAME && !G_Ruleset_Deathmatch())) + if(!((plr->pieces & (1 << piece)) && IS_NETGAME && !gfw_Rule(deathmatch))) { gaveAmmo = P_GiveAmmo(plr, AT_BLUEMANA, 20) | P_GiveAmmo(plr, AT_GREENMANA, 20); } @@ -463,7 +463,7 @@ if(plr->pieces & (1 << piece)) { // Already has the piece. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) // Cooperative net-game. + if(IS_NETGAME && !gfw_Rule(deathmatch)) // Cooperative net-game. return false; // Deathmatch or single player. @@ -476,7 +476,7 @@ plr->pieces |= (1 << piece); // In a cooperative net-game, give the "lesser" pieces also. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) { for(int i = 0; i < piece; ++i) { @@ -735,7 +735,7 @@ static void setDormantItem(mobj_t *mo) { mo->flags &= ~MF_SPECIAL; - if(G_Ruleset_Deathmatch() && !(mo->flags2 & MF2_DROPPED)) + if(gfw_Rule(deathmatch) && !(mo->flags2 & MF2_DROPPED)) { if(mo->type == MT_ARTIINVULNERABILITY) { @@ -1136,7 +1136,7 @@ if(plr->class_ != matchClass) { // Leave placed weapons forever on net games. - if(IS_NETGAME && !G_Ruleset_Deathmatch()) + if(IS_NETGAME && !gfw_Rule(deathmatch)) return false; } @@ -1317,8 +1317,8 @@ if((wasUsed = giveItem(player, item))) { // Should we leave this item for others? - if(!((info->flags & IIF_LEAVE_COOP) && IS_NETGAME && !G_Ruleset_Deathmatch()) && - !((info->flags & IIF_LEAVE_DEATHMATCH) && IS_NETGAME && G_Ruleset_Deathmatch())) + if(!((info->flags & IIF_LEAVE_COOP) && IS_NETGAME && !gfw_Rule(deathmatch)) && + !((info->flags & IIF_LEAVE_DEATHMATCH) && IS_NETGAME && gfw_Rule(deathmatch))) removeItem = true; } } @@ -1386,7 +1386,7 @@ break; default: - if(G_Ruleset_Deathmatch() && !(special->flags2 & MF2_DROPPED)) + if(gfw_Rule(deathmatch) && !(special->flags2 & MF2_DROPPED)) P_HideSpecialThing(special); else P_MobjRemove(special, false); @@ -1469,7 +1469,7 @@ if(source && source->player) { // Check for frag changes. - if(target->player && G_Ruleset_Deathmatch()) + if(target->player && gfw_Rule(deathmatch)) { if(target == source) { @@ -1574,7 +1574,7 @@ * * @todo This should be a Thing definition flag. */ - if(IS_NETGAME && !G_Ruleset_Deathmatch() && source && source->player && + if(IS_NETGAME && !gfw_Rule(deathmatch) && source && source->player && source->player->plr && (target->type == MT_CENTAUR || target->type == MT_CENTAURLEADER || target->type == MT_DEMON || @@ -1784,68 +1784,56 @@ return true; } -dd_bool P_MorphMonster(mobj_t* actor) +dd_bool P_MorphMonster(mobj_t *actor) { - mobj_t* master, *monster, *fog; + mobj_t * master, *monster, *fog; mobjtype_t moType; - coord_t pos[3]; - mobj_t oldMonster; - angle_t oldAngle; + coord_t pos[3]; + mobj_t oldMonster; + angle_t oldAngle; + + if (actor->player) return (false); + if (!(actor->flags & MF_COUNTKILL)) return false; + if (actor->flags2 & MF2_BOSS) return false; - if(actor->player) - return (false); - if(!(actor->flags & MF_COUNTKILL)) - return false; - if(actor->flags2 & MF2_BOSS) - return false; + // Originally hardcoded to specific mobj types. + if (actor->flags3 & MF3_NOMORPH) return false; moType = actor->type; - switch(moType) - { - case MT_PIG: - case MT_FIGHTER_BOSS: - case MT_CLERIC_BOSS: - case MT_MAGE_BOSS: - return false; - - default: - break; - } /// @todo Do this properly! oldMonster = *actor; - pos[VX] = actor->origin[VX]; - pos[VY] = actor->origin[VY]; - pos[VZ] = actor->origin[VZ]; + pos[VX] = actor->origin[VX]; + pos[VY] = actor->origin[VY]; + pos[VZ] = actor->origin[VZ]; oldAngle = actor->angle; - if(!(monster = P_SpawnMobj(MT_PIG, pos, oldMonster.angle, 0))) - return false; + if (!(monster = P_SpawnMobj(MT_PIG, pos, oldMonster.angle, 0))) return false; P_MobjRemoveFromTIDList(actor); P_MobjChangeState(actor, S_FREETARGMOBJ); - if((fog = P_SpawnMobjXYZ(MT_TFOG, pos[VX], pos[VY], - pos[VZ] + TELEFOGHEIGHT, oldAngle + ANG180, 0))) + if ((fog = P_SpawnMobjXYZ( + MT_TFOG, pos[VX], pos[VY], pos[VZ] + TELEFOGHEIGHT, oldAngle + ANG180, 0))) S_StartSound(SFX_TELEPORT, fog); monster->special2 = moType; monster->special1 = MORPHTICS + P_Random(); monster->flags |= (oldMonster.flags & MF_SHADOW); - monster->target = oldMonster.target; - monster->tid = oldMonster.tid; + monster->target = oldMonster.target; + monster->tid = oldMonster.tid; monster->special = oldMonster.special; P_MobjInsertIntoTIDList(monster, oldMonster.tid); memcpy(monster->args, oldMonster.args, 5); // Check for turning off minotaur power for active icon. - if(moType == MT_MINOTAUR) + if (moType == MT_MINOTAUR) { master = oldMonster.tracer; - if(master && master->health > 0) + if (master && master->health > 0) { - if(!ActiveMinotaur(master->player)) + if (!ActiveMinotaur(master->player)) { master->player->powers[PT_MINOTAUR] = 0; } @@ -1865,7 +1853,7 @@ if(!player->plr->mo) return; /// @todo Do this in the inventory code? - if(G_Ruleset_Skill() == SM_BABY && normalCount * 25 >= saveHealth) + if(gfw_Rule(skill) == SM_BABY && normalCount * 25 >= saveHealth) { // Use quartz flasks. count = (saveHealth + 24) / 25; @@ -1885,7 +1873,7 @@ P_InventoryTake(plrnum, IIT_SUPERHEALTH, false); } } - else if(G_Ruleset_Skill() == SM_BABY && + else if(gfw_Rule(skill) == SM_BABY && superCount * 100 + normalCount * 25 >= saveHealth) { // Use mystic urns and quartz flasks. @@ -2043,7 +2031,7 @@ return 0; // Invulnerable, and won't wake up. player = target->player; - if(player && G_Ruleset_Skill() == SM_BABY) + if(player && gfw_Rule(skill) == SM_BABY) damage /= 2; // Take half damage in trainer mode. // Use the cvar damage multiplier netMobDamageModifier only if the @@ -2083,7 +2071,7 @@ { if(target->player) { - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) P_TeleportToDeathmatchStarts(target); else P_TeleportToPlayerStarts(target); @@ -2285,7 +2273,7 @@ } if(damage >= player->health && - ((G_Ruleset_Skill() == SM_BABY) || G_Ruleset_Deathmatch()) && + ((gfw_Rule(skill) == SM_BABY) || gfw_Rule(deathmatch)) && !player->morphTics) { // Try to use some inventory health. @@ -2484,7 +2472,7 @@ if((target->flags2 & MF2_INVULNERABLE) && damage < 10000) return 0; // mobj is invulnerable. - if(G_Ruleset_Skill() == SM_BABY) + if(gfw_Rule(skill) == SM_BABY) { // Take half damage in trainer mode damage /= 2; @@ -2497,7 +2485,7 @@ } if(damage >= player->health && - (G_Ruleset_Skill() == SM_BABY || G_Ruleset_Deathmatch()) && + (gfw_Rule(skill) == SM_BABY || gfw_Rule(deathmatch)) && !player->morphTics) { // Try to use some inventory health. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_maputl.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_maputl.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_maputl.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_maputl.c 2018-12-11 07:08:23.000000000 +0000 @@ -41,7 +41,7 @@ if(!(mo->flags & MF_SHOOTABLE) || (mo->flags2 & MF2_DORMANT) || ((mo->type == MT_MINOTAUR) && (mo->tracer == params->source)) || - (IS_NETGAME && !G_Ruleset_Deathmatch() && mo->player)) + (IS_NETGAME && !gfw_Rule(deathmatch) && mo->player)) { return false; // Continue iteration. } @@ -64,7 +64,7 @@ if(!(mo->flags & MF_SHOOTABLE) || (mo->flags2 & MF2_DORMANT) || ((mo->type == MT_MINOTAUR) && (mo->tracer == params->source->tracer)) || - (IS_NETGAME && !G_Ruleset_Deathmatch() && mo->player)) + (IS_NETGAME && !gfw_Rule(deathmatch) && mo->player)) { return false; // Continue iteration. } @@ -84,7 +84,7 @@ !(mo->flags2 & MF2_DORMANT)) { if(!(mo->flags & MF_SHOOTABLE) || - (IS_NETGAME && !G_Ruleset_Deathmatch() && mo->player)) + (IS_NETGAME && !gfw_Rule(deathmatch) && mo->player)) { return false; // Continue iteration. } @@ -110,7 +110,7 @@ !(mo->flags2 & MF2_DORMANT)) { if(!(mo->flags & MF_SHOOTABLE) || - (IS_NETGAME && !G_Ruleset_Deathmatch() && mo->player) || + (IS_NETGAME && !gfw_Rule(deathmatch) && mo->player) || mo == params->source->target) { return false; // Continue iteration. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_mobj.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_mobj.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_mobj.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_mobj.c 2018-12-11 07:08:23.000000000 +0000 @@ -278,7 +278,7 @@ if(P_CameraXYMovement(mo)) return; - if(FEQUAL(mo->mom[MX], 0) && FEQUAL(mo->mom[MY], 0)) + if(IS_ZERO(mo->mom[MX]) && IS_ZERO(mo->mom[MY])) { if(mo->flags & MF_SKULLFLY) { @@ -789,14 +789,14 @@ } else if(mo->flags2 & MF2_LOGRAV) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -(gravity / 8) * 2; else mo->mom[MZ] -= gravity / 8; } else if(!(mo->flags & MF_NOGRAVITY)) { - if(FEQUAL(mo->mom[MZ], 0)) + if(IS_ZERO(mo->mom[MZ])) mo->mom[MZ] = -gravity * 2; else mo->mom[MZ] -= gravity; @@ -910,13 +910,13 @@ dd_bool changexy; // Handle movement. - if(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0) || !FEQUAL(mobj->mom[MZ], 0) || + if(NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY]) || NON_ZERO(mobj->mom[MZ]) || !FEQUAL(mobj->origin[VZ], mobj->floorZ)) { frac[VX] = mobj->mom[MX] / 8; frac[VY] = mobj->mom[MY] / 8; frac[VZ] = mobj->mom[MZ] / 8; - changexy = (!FEQUAL(frac[VX], 0) || !FEQUAL(frac[VY], 0)); + changexy = (NON_ZERO(frac[VX]) || NON_ZERO(frac[VY])); for(i = 0; i < 8; ++i) { @@ -1005,7 +1005,7 @@ // Handle X and Y momentums tmBlockingMobj = NULL; - if(!FEQUAL(mobj->mom[MX], 0) || !FEQUAL(mobj->mom[MY], 0) || + if(NON_ZERO(mobj->mom[MX]) || NON_ZERO(mobj->mom[MY]) || (mobj->flags & MF_SKULLFLY)) { P_MobjMoveXY(mobj); @@ -1032,7 +1032,7 @@ mobj->floorClip = -MAX_BOB_OFFSET; } } - else if(!FEQUAL(mobj->origin[VZ], mobj->floorZ) || !FEQUAL(mobj->mom[MZ], 0) || tmBlockingMobj) + else if(!FEQUAL(mobj->origin[VZ], mobj->floorZ) || NON_ZERO(mobj->mom[MZ]) || tmBlockingMobj) { // Handle Z momentum and gravity if(mobj->flags2 & MF2_PASSMOBJ) @@ -1136,11 +1136,11 @@ */ // Not for deathmatch? - if(G_Ruleset_Deathmatch() && (info->flags & MF_NOTDMATCH)) + if(gfw_Rule(deathmatch) && (info->flags & MF_NOTDMATCH)) return NULL; // Don't spawn any monsters? - if(G_Ruleset_NoMonsters() && (info->flags & MF_COUNTKILL)) + if(gfw_Rule(noMonsters) && (info->flags & MF_COUNTKILL)) return NULL; if(info->flags & MF_SOLID) @@ -1162,7 +1162,7 @@ mo->selector = 0; P_UpdateHealthBits(mo); // Set the health bits of the selector. - if(G_Ruleset_Skill() != SM_NIGHTMARE) + if(gfw_Rule(skill) != SM_NIGHTMARE) { mo->reactionTime = info->reactionTime; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_pspr.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_pspr.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_pspr.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_pspr.c 2018-12-11 07:08:23.000000000 +0000 @@ -1570,7 +1570,7 @@ pmo->target = mo->target; pmo->args[0] = 10; // Initial turn value. pmo->args[1] = 0; // Initial look angle. - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { // Ghosts last slightly less longer in DeathMatch. pmo->health = 85; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_spec.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_spec.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_spec.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_spec.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -49,7 +49,7 @@ static inline acs::System &acscriptSys() { - return COMMON_GAMESESSION->acsSystem(); + return gfw_Session()->acsSystem(); } LightningAnimator lightningAnimator; @@ -370,7 +370,7 @@ if(!(mo && mo->player && mo->player->playerState == PST_DEAD)) { // Assume the referenced map is from the current episode. - dint epIdx = COMMON_GAMESESSION->episodeId().toInt(); + dint epIdx = gfw_Session()->episodeId().toInt(); if(epIdx > 0) epIdx -= 1; dint mapIdx = args[0]; if(mapIdx > 0) mapIdx -= 1; @@ -387,15 +387,15 @@ if(!(mo && mo->player && mo->player->playerState == PST_DEAD)) { success = true; - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { // Winning in deathmatch goes back to the first map of the current episode. - G_SetGameActionMapCompleted(de::Uri(COMMON_GAMESESSION->episodeDef()->gets("startMap"), RC_NULL)); + G_SetGameActionMapCompleted(de::makeUri(gfw_Session()->episodeDef()->gets("startMap"))); } else { // Passing a URI with an empty path starts the Finale - G_SetGameActionMapCompleted(de::Uri("Maps:", RC_NULL)); + G_SetGameActionMapCompleted(de::makeUri("Maps:")); } } } @@ -426,13 +426,13 @@ acs::Script::Args const scriptArgs(&args[2], 3); // Assume the referenced map is from the current episode. - dint epIdx = COMMON_GAMESESSION->episodeId().toInt(); + dint epIdx = gfw_Session()->episodeId().toInt(); if(epIdx > 0) epIdx -= 1; dint mapIdx = args[1]; - de::Uri const mapUri = (mapIdx == 0? COMMON_GAMESESSION->mapUri() + de::Uri const mapUri = (mapIdx == 0? gfw_Session()->mapUri() : G_ComposeMapUri(epIdx, mapIdx - 1) ); - if(COMMON_GAMESESSION->mapUri() == mapUri) + if(gfw_Session()->mapUri() == mapUri) { if(acscriptSys().hasScript(scriptNumber)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_telept.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_telept.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_telept.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_telept.c 2018-12-11 07:08:23.000000000 +0000 @@ -254,7 +254,7 @@ { playerstart_t const *start; - if((start = P_GetPlayerStart(0, G_Ruleset_Deathmatch()? -1 : 0, G_Ruleset_Deathmatch()))) + if((start = P_GetPlayerStart(0, gfw_Rule(deathmatch)? -1 : 0, gfw_Rule(deathmatch)))) { mapspot_t const *spot = &mapSpots[start->spot]; P_Teleport(player->plr->mo, spot->origin[VX], spot->origin[VY], spot->angle, true); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_things.c doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_things.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/p_things.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/p_things.c 2018-12-11 07:08:23.000000000 +0000 @@ -155,7 +155,7 @@ searcher = -1; tid = args[0]; moType = TranslateThingType[args[1]]; - if(G_Ruleset_NoMonsters() && (MOBJINFO[moType].flags & MF_COUNTKILL)) + if(gfw_Rule(noMonsters) && (MOBJINFO[moType].flags & MF_COUNTKILL)) { // Don't spawn monsters if -nomonsters return false; @@ -206,7 +206,7 @@ searcher = -1; tid = args[0]; moType = TranslateThingType[args[1]]; - if(G_Ruleset_NoMonsters() && (MOBJINFO[moType].flags & MF_COUNTKILL)) + if(gfw_Rule(noMonsters) && (MOBJINFO[moType].flags & MF_COUNTKILL)) { // Don't spawn monsters if -nomonsters return false; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/st_stuff.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/st_stuff.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/st_stuff.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/st_stuff.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -208,7 +208,7 @@ { GL_DrawPatch(pStatBar, Vector2i(ORIGINX + 38, ORIGINY)); - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) { GL_DrawPatch(pKills, Vector2i(ORIGINX + 38, ORIGINY)); } @@ -308,16 +308,16 @@ patchinfo_t pStatBarInfo; if(R_GetPatchInfo(pStatBar, &pStatBarInfo)) { - x = ORIGINX + (G_Ruleset_Deathmatch() ? 68 : 38); + x = ORIGINX + (gfw_Rule(deathmatch) ? 68 : 38); y = ORIGINY; - w = G_Ruleset_Deathmatch()?214:244; + w = gfw_Rule(deathmatch)?214:244; h = 31; DGL_SetPatch(pStatBar, DGL_CLAMP_TO_EDGE, DGL_CLAMP_TO_EDGE); - DGL_DrawCutRectf2Tiled(x, y, w, h, pStatBarInfo.geometry.size.width, pStatBarInfo.geometry.size.height, G_Ruleset_Deathmatch()?30:0, 0, ORIGINX+190, ORIGINY, 57, 30); + DGL_DrawCutRectf2Tiled(x, y, w, h, pStatBarInfo.geometry.size.width, pStatBarInfo.geometry.size.height, gfw_Rule(deathmatch)?30:0, 0, ORIGINX+190, ORIGINY, 57, 30); } GL_DrawPatch(pWeaponSlot[pClass], Vector2i(ORIGINX + 190, ORIGINY)); - if(G_Ruleset_Deathmatch()) + if(gfw_Rule(deathmatch)) GL_DrawPatch(pKills, Vector2i(ORIGINX + 38, ORIGINY)); } else @@ -623,9 +623,9 @@ #endif // Are we re-centering on a followed mobj? - if(mobj_t *mob = automap.followMobj()) + if (mobj_t *mob = automap.followMobj()) { - automap.setCameraOrigin(Vector2d(mob->origin)); + automap.setCameraOrigin(Vector2d(mob->origin), true); } if(IS_NETGAME) @@ -676,7 +676,6 @@ // If the automap was left open; close it. automap.open(false, true /*instantly*/); initAutomapForCurrentMap(automap); - automap.setCameraFollowMode(CPP_BOOL(cfg.common.automapRotate)); hud->stopped = false; } @@ -1344,7 +1343,7 @@ availHeight = displayRegion.size.height - (drawnSize.height > 0 ? drawnSize.height : 0); HudWidget &mnGroup = GUI_FindWidgetById(hud->groupIds[UWG_MAPNAME]); mnGroup.setOpacity(ST_AutomapOpacity(playerNum)); - Size2Raw size(displayRegion.size.width, availHeight); + Size2Raw size = {{{displayRegion.size.width, availHeight}}}; mnGroup.setMaximumSize(size); GUI_DrawWidget(&mnGroup, &displayRegion.origin); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/x_api.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/x_api.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/hexen/src/x_api.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/hexen/src/x_api.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -49,9 +49,6 @@ using namespace de; -// The interface to the Doomsday engine. -game_export_t gx; - // Identifiers given to the games we register during startup. static char const *gameIds[NUM_GAME_MODES] = { @@ -71,12 +68,17 @@ { //game.addResource(RC_PACKAGE, FF_STARTUP, STARTUPPK3, 0); game.addRequiredPackage("net.dengine.legacy.hexen_2"); + + Record gameplayOptions; + gameplayOptions.set("noMonsters", Record::withMembers("label", "No Monsters", "type", "boolean", "default", false)); + gameplayOptions.set("turbo", Record::withMembers("label", "Move Speed", "type", "number", "default", 1.0, "min", 0.1, "max", 4.0, "step", 0.1)); + game.objectNamespace().set(Game::DEF_OPTIONS, gameplayOptions); } /** * Register the game modes supported by this plugin. */ -int G_RegisterGames(int, int, void *) +static int G_RegisterGames(int, int, void *) { Games &games = DoomsdayApp::games(); @@ -90,7 +92,7 @@ Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/hexen-dk.mapinfo")); - deathkings.addRequiredPackage("com.ravensoftware.hexen"); + deathkings.addRequiredPackage("com.ravensoftware.hexen com.ravensoftware.hexen.mac"); deathkings.addRequiredPackage("com.ravensoftware.hexen.deathkings"); setCommonParameters(deathkings); //deathkings.addResource(RC_PACKAGE, FF_STARTUP, "hexdd.wad", "MAP59;MAP60"); @@ -107,7 +109,7 @@ Game::DEF_LEGACYSAVEGAME_NAME_EXP, LEGACYSAVEGAMENAMEEXP, Game::DEF_LEGACYSAVEGAME_SUBFOLDER, LEGACYSAVEGAMESUBFOLDER, Game::DEF_MAPINFO_PATH, "$(App.DataPath)/$(GamePlugin.Name)/hexen.mapinfo")); - hxn.addRequiredPackage("com.ravensoftware.hexen_1.1"); + hxn.addRequiredPackage("com.ravensoftware.hexen_1.1 com.ravensoftware.hexen.mac_1.1"); setCommonParameters(hxn); //hxn.addResource(RC_PACKAGE, FF_STARTUP, "hexen.wad", "MAP08;MAP22;TINTTAB;FOGMAP;TRANTBLA;DARTA1;ARTIPORK;SKYFOG;TALLYTOP;GROVER"); hxn.addResource(RC_DEFINITION, 0, "hexen.ded", 0); @@ -167,7 +169,7 @@ /** * Called right after the game plugin is selected into use. */ -DENG_EXTERN_C void DP_Load(void) +DENG_ENTRYPOINT void DP_Load(void) { Plug_AddHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); gfw_SetCurrentGame(GFW_HEXEN); @@ -176,7 +178,7 @@ /** * Called when the game plugin is freed from memory. */ -DENG_EXTERN_C void DP_Unload(void) +DENG_ENTRYPOINT void DP_Unload(void) { Plug_RemoveHook(HOOK_VIEWPORT_RESHAPE, R_UpdateViewport); } @@ -208,63 +210,37 @@ return true; } -/** - * Takes a copy of the engine's entry points and exported data. Returns - * a pointer to the structure that contains our entry points and exports. - */ -DENG_EXTERN_C game_export_t *GetGameAPI(void) +DENG_ENTRYPOINT void *GetGameAPI(char const *name) { - // Clear all of our exports. - memset(&gx, 0, sizeof(gx)); - - // Fill in the data for the exports. - gx.apiSize = sizeof(gx); - gx.PreInit = G_PreInit; - gx.PostInit = X_PostInit; - gx.TryShutdown = G_TryShutdown; - gx.Shutdown = X_Shutdown; - gx.Ticker = G_Ticker; - gx.DrawViewPort = G_DrawViewPort; - gx.DrawWindow = X_DrawWindow; - gx.FinaleResponder = FI_PrivilegedResponder; - gx.PrivilegedResponder = G_PrivilegedResponder; - gx.Responder = G_Responder; - gx.EndFrame = X_EndFrame; - gx.MobjThinker = P_MobjThinker; - gx.MobjFriction = Mobj_Friction; - gx.MobjCheckPositionXYZ = P_CheckPositionXYZ; - gx.MobjTryMoveXYZ = P_TryMoveXYZ; - gx.SectorHeightChangeNotification = P_HandleSectorHeightChange; - gx.UpdateState = G_UpdateState; - gx.GetInteger = X_GetInteger; - gx.GetVariable = X_GetVariable; - - gx.NetServerStart = D_NetServerStarted; - gx.NetServerStop = D_NetServerClose; - gx.NetConnect = D_NetConnect; - gx.NetDisconnect = D_NetDisconnect; - gx.NetPlayerEvent = D_NetPlayerEvent; - gx.NetWorldEvent = D_NetWorldEvent; - gx.HandlePacket = D_HandlePacket; - - // Data structure sizes. - gx.mobjSize = sizeof(mobj_t); - gx.polyobjSize = sizeof(Polyobj); - - gx.FinalizeMapChange = (void (*)(void const *)) P_FinalizeMapChange; - - // These really need better names. Ideas? - gx.HandleMapDataPropertyValue = P_HandleMapDataPropertyValue; - gx.HandleMapObjectStatusReport = P_HandleMapObjectStatusReport; + if (auto *ptr = Common_GetGameAPI(name)) + { + return ptr; + } - return &gx; + #define HASH_ENTRY(Name, Func) std::make_pair(QByteArray(Name), de::function_cast(Func)) + static QHash const funcs( + { + HASH_ENTRY("DrawWindow", X_DrawWindow), + HASH_ENTRY("EndFrame", X_EndFrame), + HASH_ENTRY("GetInteger", X_GetInteger), + HASH_ENTRY("GetPointer", X_GetVariable), + HASH_ENTRY("PostInit", X_PostInit), + HASH_ENTRY("PreInit", G_PreInit), + HASH_ENTRY("Shutdown", X_Shutdown), + HASH_ENTRY("TryShutdown", G_TryShutdown), + }); + #undef HASH_ENTRY + + auto found = funcs.find(name); + if (found != funcs.end()) return found.value(); + return nullptr; } /** * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -DENG_EXTERN_C void DP_Initialize(void) +DENG_ENTRYPOINT void DP_Initialize(void) { Plug_AddHook(HOOK_STARTUP, G_RegisterGames); } @@ -273,11 +249,26 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C char const *deng_LibraryType(void) +DENG_ENTRYPOINT char const *deng_LibraryType(void) { return "deng-plugin/game"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_hexen_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + DENG_SYMBOL_PTR(name, DP_Load); + DENG_SYMBOL_PTR(name, DP_Unload); + DENG_SYMBOL_PTR(name, GetGameAPI); + qWarning() << name << "not found in hexen"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(B); DENG_DECLARE_API(Busy); @@ -326,3 +317,4 @@ DENG_GET_API(DE_API_URI, Uri); ) +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/include/importdeh.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/include/importdeh.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/include/importdeh.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/include/importdeh.h 2018-12-11 07:08:23.000000000 +0000 @@ -33,8 +33,6 @@ #include #include -DENG_EXTERN_C void DP_Initialize(); - // Internal: extern ded_t *ded; // @todo Remove me. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/res/importdeh.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/res/importdeh.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/res/importdeh.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/res/importdeh.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2009 Daniel Swanson + *\author Copyright (c) 2008-2009 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,7 +80,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""importdeh.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -118,7 +118,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "importdeh.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/src/dehreader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/src/dehreader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/src/dehreader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/src/dehreader.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -240,12 +240,12 @@ void parse() { - LOG_AS_STRING(stackDepth == 1? "DehReader" : QString("[%1]").arg(stackDepth - 1)); + LOG_AS_STRING(stackDepth == 1? "DehReader" : String("[%1]").arg(stackDepth - 1)); skipToNextLine(); // Attempt to parse the DeHackEd patch signature and version numbers. - if(line.beginsWith("Patch File for DeHackEd v", Qt::CaseInsensitive)) + if(line.beginsWith("Patch File for DeHackEd v", String::CaseInsensitive)) { skipToNextLine(); parsePatchSignature(); @@ -274,12 +274,12 @@ try { /// @note Some sections have their own grammar quirks! - if(line.beginsWith("include", Qt::CaseInsensitive)) // BEX + if(line.beginsWith("include", String::CaseInsensitive)) // BEX { parseInclude(line.substr(7).leftStrip()); skipToNextSection(); } - else if(line.beginsWith("Thing", Qt::CaseInsensitive)) + else if(line.beginsWith("Thing", String::CaseInsensitive)) { Record *mobj; Record dummyMobj; @@ -300,7 +300,7 @@ skipToNextLine(); parseThing(*mobj, mobj == &dummyMobj); } - else if(line.beginsWith("Frame", Qt::CaseInsensitive)) + else if(line.beginsWith("Frame", String::CaseInsensitive)) { Record *state; Record dummyState; @@ -321,7 +321,7 @@ skipToNextLine(); parseFrame(*state, state == &dummyState); } - else if(line.beginsWith("Pointer", Qt::CaseInsensitive)) + else if(line.beginsWith("Pointer", String::CaseInsensitive)) { Record *state; Record dummyState; @@ -342,7 +342,7 @@ skipToNextLine(); parsePointer(*state, state == &dummyState); } - else if(line.beginsWith("Sprite", Qt::CaseInsensitive)) + else if(line.beginsWith("Sprite", String::CaseInsensitive)) { ded_sprid_t *sprite; Dummy dummySprite; @@ -363,7 +363,7 @@ skipToNextLine(); parseSprite(sprite, sprite == &dummySprite); } - else if(line.beginsWith("Ammo", Qt::CaseInsensitive)) + else if(line.beginsWith("Ammo", String::CaseInsensitive)) { String const arg = line.substr(4).leftStrip(); int ammoNum = 0; @@ -378,7 +378,7 @@ skipToNextLine(); parseAmmo(ammoNum, ignore); } - else if(line.beginsWith("Weapon", Qt::CaseInsensitive)) + else if(line.beginsWith("Weapon", String::CaseInsensitive)) { String const arg = line.substr(6).leftStrip(); int weaponNum = 0; @@ -393,7 +393,7 @@ skipToNextLine(); parseWeapon(weaponNum, ignore); } - else if(line.beginsWith("Sound", Qt::CaseInsensitive)) + else if(line.beginsWith("Sound", String::CaseInsensitive)) { ded_sound_t *sound; Dummy dummySound; @@ -414,7 +414,7 @@ skipToNextLine(); parseSound(sound, sound == &dummySound); } - else if(line.beginsWith("Text", Qt::CaseInsensitive)) + else if(line.beginsWith("Text", String::CaseInsensitive)) { String args = line.substr(4).leftStrip(); int firstArgEnd = args.indexOf(' '); @@ -443,12 +443,12 @@ parseText(oldSize, newSize); } - else if(line.beginsWith("Misc", Qt::CaseInsensitive)) + else if(line.beginsWith("Misc", String::CaseInsensitive)) { skipToNextLine(); parseMisc(); } - else if(line.beginsWith("Cheat", Qt::CaseInsensitive)) + else if(line.beginsWith("Cheat", String::CaseInsensitive)) { if(!(!patchIsCustom && DoomsdayApp::game().id() == "hacx")) { @@ -456,41 +456,41 @@ } skipToNextSection(); } - else if(line.beginsWith("[CODEPTR]", Qt::CaseInsensitive)) // BEX + else if(line.beginsWith("[CODEPTR]", String::CaseInsensitive)) // BEX { skipToNextLine(); parseCodePointers(); } - else if(line.beginsWith("[PARS]", Qt::CaseInsensitive)) // BEX + else if(line.beginsWith("[PARS]", String::CaseInsensitive)) // BEX { skipToNextLine(); parsePars(); } - else if(line.beginsWith("[STRINGS]", Qt::CaseInsensitive)) // BEX + else if(line.beginsWith("[STRINGS]", String::CaseInsensitive)) // BEX { skipToNextLine(); parseStrings(); } - else if(line.beginsWith("[HELPER]", Qt::CaseInsensitive)) // Eternity + else if(line.beginsWith("[HELPER]", String::CaseInsensitive)) // Eternity { // Not yet supported (Helper Dogs from MBF). //skipToNextLine(); parseHelper(); skipToNextSection(); } - else if(line.beginsWith("[SPRITES]", Qt::CaseInsensitive)) // Eternity + else if(line.beginsWith("[SPRITES]", String::CaseInsensitive)) // Eternity { // Not yet supported. //skipToNextLine(); parseSprites(); skipToNextSection(); } - else if(line.beginsWith("[SOUNDS]", Qt::CaseInsensitive)) // Eternity + else if(line.beginsWith("[SOUNDS]", String::CaseInsensitive)) // Eternity { skipToNextLine(); parseSounds(); } - else if(line.beginsWith("[MUSIC]", Qt::CaseInsensitive)) // Eternity + else if(line.beginsWith("[MUSIC]", String::CaseInsensitive)) // Eternity { skipToNextLine(); parseMusic(); @@ -645,7 +645,7 @@ } } - void parseInclude(QString arg) + void parseInclude(String arg) { if(flags & NoInclude) { @@ -672,7 +672,7 @@ { DehReaderFlags includeFlags = flags & DehReaderFlagsIncludeMask; - if(arg.startsWith("notext ", Qt::CaseInsensitive)) + if(arg.beginsWith("notext ", String::CaseInsensitive)) { includeFlags |= NoText; arg.remove(0, 7); @@ -804,7 +804,7 @@ String var, expr; parseAssignmentStatement(line, var, expr); - if(var.endsWith(" frame", Qt::CaseInsensitive)) + if(var.endsWith(" frame", String::CaseInsensitive)) { StateMapping const *mapping; String const dehStateName = var.left(var.size() - 6); @@ -842,7 +842,7 @@ } } } - else if(var.endsWith(" sound", Qt::CaseInsensitive)) + else if(var.endsWith(" sound", String::CaseInsensitive)) { SoundMapping const *mapping; String const dehSoundName = var.left(var.size() - 6); @@ -1122,7 +1122,7 @@ << stateNum << state.gets("id") << state.geti("frame"); } } - else if(var.startsWith("Unknown ", Qt::CaseInsensitive)) + else if(var.beginsWith("Unknown ", String::CaseInsensitive)) { int const miscIdx = var.substr(8).toInt(0, 10, String::AllowSuffix); int const value = expr.toInt(0, 10, String::AllowSuffix); @@ -1141,7 +1141,7 @@ } } } - else if(var.beginsWith("Args", Qt::CaseInsensitive)) // Eternity + else if(var.beginsWith("Args", String::CaseInsensitive)) // Eternity { LOG_WARNING("DeHackEd Frame.%s is not supported") << var; } @@ -1326,7 +1326,7 @@ String var, expr; parseAssignmentStatement(line, var, expr); - if(var.endsWith(" frame", Qt::CaseInsensitive)) + if(var.endsWith(" frame", String::CaseInsensitive)) { String const dehStateName = var.left(var.size() - 6); int const value = expr.toInt(0, 0, String::AllowSuffix); @@ -1454,7 +1454,7 @@ try { - if(line.beginsWith("par", Qt::CaseInsensitive)) + if(line.beginsWith("par", String::CaseInsensitive)) { String const argStr = line.substr(3).leftStrip(); if(argStr.isEmpty()) @@ -1606,7 +1606,7 @@ String var, expr; parseAssignmentStatement(line, var, expr); - if(var.startsWith("Frame ", Qt::CaseInsensitive)) + if(var.beginsWith("Frame ", String::CaseInsensitive)) { int const stateNum = var.substr(6).toInt(0, 0, String::AllowSuffix); if(stateNum < 0 || stateNum >= ded->states.size()) @@ -1620,7 +1620,7 @@ // Compose the action name. String action = expr.rightStrip(); - if(!action.startsWith("A_", Qt::CaseInsensitive)) + if(!action.beginsWith("A_", String::CaseInsensitive)) action.prepend("A_"); action.truncate(32); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/src/importdeh.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/src/importdeh.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importdeh/src/importdeh.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importdeh/src/importdeh.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -145,9 +145,10 @@ { if (bundle->format() == DataBundle::Dehacked) { + String const bundleRoot = bundle->rootPath(); for (Value const *path : bundle->packageMetadata().geta("dataFiles").elements()) { - readFile2(path->asText()); + readFile2(bundleRoot / path->asText()); } } } @@ -177,7 +178,7 @@ * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -void DP_Initialize() +DENG_ENTRYPOINT void DP_Initialize() { Plug_AddHook(HOOK_DEFS, DefsHook); } @@ -186,11 +187,23 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -extern "C" char const *deng_LibraryType() +DENG_ENTRYPOINT char const *deng_LibraryType() { return "deng-plugin/generic"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_importdeh_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + qWarning() << name << "not found in importdeh"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(Con); DENG_DECLARE_API(Def); @@ -202,3 +215,5 @@ DENG_GET_API(DE_API_DEFINITIONS, Def); DENG_GET_API(DE_API_FILE_SYSTEM, F); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/res/importidtech1.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/res/importidtech1.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/res/importidtech1.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/res/importidtech1.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2014 Daniel Swanson + *\author Copyright (c) 2008-2014 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,7 +80,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine id Tech 1 resource converter plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2014, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""importidtech1.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -118,7 +118,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine id Tech 1 resource converter plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2014, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "importidtech1.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/importidtech1.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/importidtech1.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/importidtech1.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/importidtech1.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -128,7 +128,7 @@ * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -extern "C" void DP_Initialize() +DENG_ENTRYPOINT void DP_Initialize() { Plug_AddHook(HOOK_MAP_CONVERT, ConvertMapHook); Plug_AddHook(HOOK_MAPINFO_CONVERT, ConvertMapInfoHook); @@ -138,11 +138,23 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -extern "C" char const *deng_LibraryType() +DENG_ENTRYPOINT char const *deng_LibraryType() { return "deng-plugin/generic"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_importidtech1_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + qWarning() << name << "not found in importidtech1"; + return nullptr; +} + +#else + DENG_DECLARE_API(Base); DENG_DECLARE_API(F); DENG_DECLARE_API(Map); @@ -158,3 +170,5 @@ DENG_GET_API(DE_API_MAP_EDIT, MPE); DENG_GET_API(DE_API_URI, Uri); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/mapimporter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/mapimporter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/mapimporter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/mapimporter.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -866,7 +866,7 @@ { if(i->xArgs[1] <= 0) { - LOG_MAP_WARNING("Linedef missing (probably #%d) in explicit polyobj (tag:%d)") << n + 1 << tag; + LOGDEV_MAP_WARNING("Linedef missing (probably #%d) in explicit polyobj (tag:%d)") << n + 1 << tag; return false; } @@ -892,7 +892,7 @@ { if(i->xType == PO_LINE_EXPLICIT && i->xArgs[0] == tag) { - LOG_MAP_WARNING("Linedef missing (#%d) in explicit polyobj (tag:%d)") << n << tag; + LOGDEV_MAP_WARNING("Linedef missing (#%d) in explicit polyobj (tag:%d)") << n << tag; return false; } } @@ -906,7 +906,7 @@ if(polyLines.isEmpty()) { - LOG_MAP_WARNING("Failed to locate a single line for polyobj (tag:%d)") << tag; + LOGDEV_MAP_WARNING("Failed to locate a single line for polyobj (tag:%d)") << tag; return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/mapinfotranslator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/mapinfotranslator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importidtech1/src/mapinfotranslator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importidtech1/src/mapinfotranslator.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -224,9 +224,9 @@ String const gameIdKey = DoomsdayApp::game().id(); if(gameIdKey.beginsWith("doom1") || gameIdKey.beginsWith("heretic")) { - return de::Uri(String("Maps:E%1M%2").arg(episode+1).arg(map+1), RC_NULL); + return de::makeUri(String("Maps:E%1M%2").arg(episode+1).arg(map+1)); } - return de::Uri(String("Maps:MAP%1").arg(map+1, 2, 10, QChar('0')), RC_NULL); + return de::makeUri(String("Maps:MAP%1").arg(map+1, 2, 10, QChar('0'))); } static uint mapWarpNumberFor(de::Uri const &mapUri) @@ -238,7 +238,7 @@ { return de::max(path.substr(3).toInt(0, 10, String::AllowSuffix), 1); } - if(path.beginsWith("map", Qt::CaseInsensitive)) + if(path.beginsWith("map", String::CaseInsensitive)) { return de::max(path.substr(3).toInt(0, 10, String::AllowSuffix), 1); } @@ -297,8 +297,8 @@ while(lexer.readToken()) { String tok = Str_Text(lexer.token()); - if(tok.beginsWith("cd_", Qt::CaseInsensitive) && - tok.endsWith("_track", Qt::CaseInsensitive)) + if(tok.beginsWith("cd_", String::CaseInsensitive) && + tok.endsWith("_track", String::CaseInsensitive)) { String const pubName = tok.substr(3, tok.length() - 6 - 3); MusicMappings::const_iterator found = musicMap.constFind(pubName); @@ -600,7 +600,7 @@ int mapNumber = String(Str_Text(tok)).toInt(&isNumber); // 1-based if(!isNumber) { - mapUri = de::Uri(Str_Text(tok), RC_NULL); + mapUri = de::makeUri(Str_Text(tok)); if(mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); mapInfo.set((isSecret? "secretNextMap" : "nextMap"), mapUri.compose()); } @@ -625,7 +625,7 @@ int mapNumber = mapRef.toInt(&isNumber); // 1-based if(!isNumber) { - mapUri = de::Uri(mapRef, RC_NULL); + mapUri = de::makeUri(mapRef); if(mapUri.scheme().isEmpty()) mapUri.setScheme("Maps"); } else @@ -752,7 +752,7 @@ info->set("hub", hubNum); continue; } - if(String(Str_Text(lexer.token())).beginsWith("compat_", Qt::CaseInsensitive)) // ZDoom + if(String(Str_Text(lexer.token())).beginsWith("compat_", String::CaseInsensitive)) // ZDoom { LOG_WARNING("MAPINFO Map.%s is not supported.") << lexer.token(); lexer.readNumber(); @@ -1232,12 +1232,12 @@ { LOGDEV_MAP_VERBOSE("Warp %u translated to map %s, hub %i") << map << info.gets("id") << info.geti("hub"); - return de::Uri(info.gets("id"), RC_NULL); + return de::makeUri(info.gets("id")); } LOGDEV_MAP_VERBOSE("Warp %u matches map %s, but it has no hub") << map << info.gets("id"); - matchedWithoutHub = de::Uri(info.gets("id"), RC_NULL); + matchedWithoutHub = de::makeUri(info.gets("id")); } } @@ -1415,35 +1415,47 @@ for(auto const pair : defs.mapInfos) { MapInfo const &info = pair.second; - if(custom != info.getb("custom")) continue; + + const bool isCustomMapInfo = info.getb("custom"); + + if(custom != isCustomMapInfo) continue; de::Uri mapUri(info.gets("id"), RC_NULL); - if(mapUri.path().isEmpty()) continue; + if (mapUri.path().isEmpty()) continue; - String const mapId = toMapId(mapUri); + const String mapId = toMapId(mapUri); + const String musicLumpName = info.gets("music"); + bool addedMusicDef = false; - String const musicId = mapId + "_music"; - os << "\n\nMusic {" - << "\n ID = \"" + musicId + "\";"; - String const musicLumpName = info.gets("music"); - if(!musicLumpName.isEmpty()) + if (isCustomMapInfo && (!musicLumpName.isEmpty() || info.geti("cdTrack"))) { - os << "\n Lump = \"" + musicLumpName + "\";"; + addedMusicDef = true; + + // Add a music def for this custom music. + os << "\n\nMusic {" + << "\n ID = \"" + mapId + "\";"; // music ID == map ID + if (!musicLumpName.isEmpty()) + { + os << "\n Lump = \"" + musicLumpName + "\";"; + } + os << "\n CD Track = " << info.geti("cdTrack") << ";" + << "\n}"; } - os << "\n CD Track = " + String::number(info.geti("cdTrack")) + ";" - << "\n}"; - bool const doubleSky = info.getb("doubleSky"); + const bool doubleSky = info.getb("doubleSky"); os << "\n\nMap Info {" << "\n ID = \"" + mapId + "\";" << "\n Title = \"" + info.gets("title") + "\";"; - if(!info.getb("custom")) + if (!isCustomMapInfo) { os << "\n Author = \"" + String(Str_Text(gameInfo.author)) + "\";"; } - os << "\n Fade Table = \"" + info.gets("fadeTable") + "\";" - << "\n Music = \"" + musicId + "\";"; + os << "\n Fade Table = \"" + info.gets("fadeTable") + "\";"; + if (addedMusicDef) + { + os << "\n Music = \"" + mapId + "\";"; + } de::Uri titleImageUri(info.gets("titleImage"), RC_NULL); if(!titleImageUri.path().isEmpty()) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importsave/res/importsave.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importsave/res/importsave.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importsave/res/importsave.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importsave/res/importsave.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2014 Daniel Swanson + *\author Copyright (c) 2008-2014 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,7 +80,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2014, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""importsave.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -118,7 +118,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2014, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "importsave.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importudmf/res/importudmf.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importudmf/res/importudmf.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importudmf/res/importudmf.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importudmf/res/importudmf.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,8 +3,8 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2016-2017 Jaakko Keränen - *\author Copyright © 2008-2014 Daniel Swanson + *\author Copyright (c) 2016-2018 Jaakko Keränen + *\author Copyright (c) 2008-2014 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -37,11 +37,11 @@ VS_VERSION_INFO VERSIONINFO FILEVERSION PLUGIN_VERSION_NUMBER PRODUCTVERSION PLUGIN_VERSION_NUMBER -# ifdef _DEBUG +#ifdef _DEBUG FILEFLAGSMASK VS_FF_DEBUG | VS_FF_PRERELEASE -# else +#else FILEFLAGSMASK 0 -# endif +#endif FILEOS VOS_NT_WINDOWS32 FILETYPE VFT_DLL FILESUBTYPE VFT2_UNKNOWN @@ -54,7 +54,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine UDMF map importer plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2016, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2016-2018, deng Team\0" VALUE "OriginalFilename", "importudmf.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importudmf/src/importudmf.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importudmf/src/importudmf.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/importudmf/src/importudmf.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/importudmf/src/importudmf.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -331,7 +331,7 @@ * This function is called automatically when the plugin is loaded. * We let the engine know what we'd like to do. */ -extern "C" void DP_Initialize() +DENG_ENTRYPOINT void DP_Initialize() { Plug_AddHook(HOOK_MAP_CONVERT, importMapHook); } @@ -340,11 +340,23 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -extern "C" char const *deng_LibraryType() +DENG_ENTRYPOINT char const *deng_LibraryType() { return "deng-plugin/generic"; } +#if defined (DENG_STATIC_LINK) + +DENG_EXTERN_C void *staticlib_importudmf_symbol(char const *name) +{ + DENG_SYMBOL_PTR(name, deng_LibraryType) + DENG_SYMBOL_PTR(name, DP_Initialize); + qWarning() << name << "not found in importudmf"; + return nullptr; +} + +#else + DENG_DECLARE_API(Map); DENG_DECLARE_API(Material); DENG_DECLARE_API(MPE); @@ -354,3 +366,5 @@ DENG_GET_API(DE_API_MATERIALS, Material); DENG_GET_API(DE_API_MAP_EDIT, MPE); ) + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/libgamefw/include/gamefw/libgamefw.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/libgamefw/include/gamefw/libgamefw.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/libgamefw/include/gamefw/libgamefw.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/libgamefw/include/gamefw/libgamefw.h 2018-12-11 07:08:23.000000000 +0000 @@ -55,7 +55,7 @@ #define IS_SERVER (DD_GetInteger(DD_SERVER)) #define IS_CLIENT (DD_GetInteger(DD_CLIENT)) #define IS_NETGAME (DD_GetInteger(DD_NETGAME)) -#define IS_DEDICATED (DD_GetInteger(DD_DEDICATED)) +#define IS_DEDICATED (DD_GetInteger(DD_NOVIDEO)) #define CONSOLEPLAYER (DD_GetInteger(DD_CONSOLEPLAYER)) #define DISPLAYPLAYER (DD_GetInteger(DD_DISPLAYPLAYER)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/openal/res/audio_openal.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/openal/res/audio_openal.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/openal/res/audio_openal.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/openal/res/audio_openal.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2009 Daniel Swanson + *\author Copyright (c) 2008-2009 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,7 +80,7 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""dsOpenAL.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" @@ -118,7 +118,7 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" VALUE "OriginalFilename", "dsOpenAL.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/openal/src/driver_openal.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/openal/src/driver_openal.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/openal/src/driver_openal.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/openal/src/driver_openal.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -40,6 +40,9 @@ #ifdef HAVE_AL_H # include # include +#elif defined (DENG_IOS) +# include +# include #else # include # include @@ -505,7 +508,7 @@ * Declares the type of the plugin so the engine knows how to treat it. Called * automatically when the plugin is loaded. */ -DENG_EXTERN_C const char* deng_LibraryType(void) +DENG_EXTERN_C DENG_VISIBLE_SYMBOL const char* deng_LibraryType(void) { return "deng-plugin/audio"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/PluginConfig.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/PluginConfig.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/PluginConfig.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/PluginConfig.cmake 2018-12-11 07:08:20.000000000 +0000 @@ -23,7 +23,12 @@ endif () list (APPEND _src ${_winres}) endif () - add_library (${target} MODULE ${_src} ${DENG_RESOURCES}) + if (DENG_STATIC_LINK) + set (_libType STATIC) + else () + set (_libType MODULE) + endif () + add_library (${target} ${_libType} ${_src} ${DENG_RESOURCES}) target_include_directories (${target} PUBLIC "${DENG_API_DIR}" PRIVATE "${DENG_SOURCE_DIR}/sdk/libgui/include" @@ -33,18 +38,39 @@ set_target_properties (${target} PROPERTIES FOLDER Plugins) if (APPLE) + if (IOS) + set_property (TARGET ${target} PROPERTY XCODE_ATTRIBUTE_DEAD_CODE_STRIPPING NO) + link_framework (${target} PUBLIC Foundation) + link_framework (${target} PUBLIC CoreFoundation) + link_framework (${target} PUBLIC MobileCoreServices) + link_framework (${target} PUBLIC UIKit) + link_framework (${target} PUBLIC Security) + target_link_libraries (${target} PUBLIC + debug ${QT_LIBS}/libqtpcre_debug.a + optimized ${QT_LIBS}/libqtpcre.a + ) + endif () # The plugins have some messy code. set_property (TARGET ${target} APPEND PROPERTY COMPILE_OPTIONS -Wno-missing-braces ) + set (_extraRPath) + if (NOT DENG_ENABLE_DEPLOYQT) + set (_extraRPath ${QT_LIBS}) + endif () set_target_properties (${target} PROPERTIES BUNDLE ON MACOSX_BUNDLE_INFO_PLIST ${DENG_SOURCE_DIR}/cmake/MacOSXPluginBundleInfo.plist.in BUILD_WITH_INSTALL_RPATH ON # staging prevents CMake's own rpath fixing - INSTALL_RPATH "@executable_path/../Frameworks" + INSTALL_RPATH "@loader_path/../Frameworks;@executable_path/../Frameworks;${_extraRPath}" ) + set (_extraRPath) macx_set_bundle_name ("net.dengine.plugin.${target}") - set (MACOSX_BUNDLE_BUNDLE_EXECUTABLE "${target}.bundle/Contents/MacOS/${target}") + if (IOS) + set (MACOSX_BUNDLE_BUNDLE_EXECUTABLE "${target}.bundle/${target}") + else () + set (MACOSX_BUNDLE_BUNDLE_EXECUTABLE "${target}.bundle/Contents/MacOS/${target}") + endif () # Stage plugins for symlinking/copying into the client app later. # This is needed because we want access to these even in a build where the # plugins are not installed yet -- the staging directory symlinks to the @@ -57,13 +83,15 @@ "${stage}/${target}.bundle" ) # Fix the Qt framework install names manually. - deng_bundle_install_names (${target} - SCRIPT_NAME "qtlibs" - LD_PATH "@executable_path/../Frameworks" - QtCore.framework/Versions/5/QtCore - QtNetwork.framework/Versions/5/QtNetwork - VERBATIM - ) + if (DENG_ENABLE_DEPLOYQT) + deng_bundle_install_names (${target} + SCRIPT_NAME "qtlibs" + LD_PATH "@executable_path/../Frameworks" + QtCore.framework/Versions/5/QtCore + QtNetwork.framework/Versions/5/QtNetwork + VERBATIM + ) + endif () deng_xcode_attribs (${target}) deng_bundle_resources () else () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/winmm/res/audio_winmm.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/winmm/res/audio_winmm.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/plugins/winmm/res/audio_winmm.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/plugins/winmm/res/audio_winmm.rc 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,7 @@ * License: GPL * Online License Link: http://www.gnu.org/licenses/gpl.html * - *\author Copyright © 2008-2009 Daniel Swanson + *\author Copyright (c) 2008-2009 Daniel Swanson * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -80,8 +80,8 @@ " VALUE ""FileDescription"", PLUGIN_NICENAME "" (Doomsday Engine audio plugin)\0""\r\n" " VALUE ""FileVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", PLUGIN_NICENAME ""\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, deng Team\0""\r\n" - " VALUE ""OriginalFilename"", ""dsWinMM.dll\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, deng Team\0""\r\n" + " VALUE ""OriginalFilename"", ""audio_winmm.dll\0""\r\n" " VALUE ""ProductName"", PLUGIN_NICENAME ""\0""\r\n" " VALUE ""ProductVersion"", PLUGIN_VERSION_TEXT ""\0""\r\n" " END\r\n" @@ -118,8 +118,8 @@ VALUE "FileDescription", PLUGIN_NICENAME " (Doomsday Engine audio plugin)\0" VALUE "FileVersion", PLUGIN_VERSION_TEXT "\0" VALUE "InternalName", PLUGIN_NICENAME "\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, deng Team\0" - VALUE "OriginalFilename", "dsWinMM.dll\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, deng Team\0" + VALUE "OriginalFilename", "audio_winmm.dll\0" VALUE "ProductName", PLUGIN_NICENAME "\0" VALUE "ProductVersion", PLUGIN_VERSION_TEXT "\0" END diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/remotefeeduser.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/remotefeeduser.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/remotefeeduser.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/remotefeeduser.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,42 @@ +/** @file remotefeeduser.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef SERVER_REMOTEFEEDUSER_H +#define SERVER_REMOTEFEEDUSER_H + +#include "users.h" +#include + +class RemoteFeedUser : public User +{ +public: + /** + * Construct a new RemoteFeedUser. + * + * @param socket Network connection to the user. Ownership taken. + */ + RemoteFeedUser(de::Socket *socket); + + de::Address address() const override; + +private: + DENG2_PRIVATE(d) +}; + + +#endif // SERVER_REMOTEFEEDUSER_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/server/sv_pool.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/server/sv_pool.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/server/sv_pool.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/server/sv_pool.h 2018-12-11 07:08:23.000000000 +0000 @@ -100,7 +100,7 @@ delta_t delta; // The header. dt_mobj_t mo; // The data of the delta. - mobjdelta_s() : mo(thinker_s::InitializeToZero) {} + mobjdelta_s() { de::zap(mo.thinker); } } mobjdelta_t; typedef struct { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/serverapp.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/serverapp.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/serverapp.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/serverapp.h 2018-12-11 07:08:23.000000000 +0000 @@ -39,6 +39,8 @@ ServerApp(int &argc, char **argv); ~ServerApp(); + de::duint32 instanceId() const; + /** * Sets up all the subsystems of the application. Must be called before the * event loop is started. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/serversystem.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/serversystem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/serversystem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/serversystem.h 2018-12-11 07:08:23.000000000 +0000 @@ -82,6 +82,13 @@ void convertToShellUser(RemoteUser *user); + void convertToRemoteFeedUser(RemoteUser *user); + + /** + * Returns the total number of connected users (of all types). + */ + int userCount() const; + /** * Prints the status of the server into the log. */ @@ -105,6 +112,6 @@ void N_PrintNetworkStatus(void); extern char *nptIPAddress; // cvar -extern int nptIPPort; // cvar +extern int nptIPPort; // cvar #endif // SERVERSYSTEM_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/shelluser.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/shelluser.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/shelluser.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/shelluser.h 2018-12-11 07:08:23.000000000 +0000 @@ -22,6 +22,7 @@ #include #include +#include "users.h" /** * Remote user of a shell connection. @@ -34,7 +35,7 @@ * * @ingroup server */ -class ShellUser : public de::shell::Link +class ShellUser : public de::shell::Link, public User { Q_OBJECT @@ -56,6 +57,8 @@ void sendMapOutline(); void sendPlayerInfo(); + de::Address address() const override; + protected slots: void handleIncomingPackets(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/shellusers.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/shellusers.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/shellusers.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/shellusers.h 2018-12-11 07:08:23.000000000 +0000 @@ -21,42 +21,20 @@ #ifndef SERVER_SHELLUSERS_H #define SERVER_SHELLUSERS_H -#include -#include #include +#include "users.h" #include "shelluser.h" /** * All remote shell users. */ -class ShellUsers : public QObject -, DENG2_OBSERVES(World, MapChange) +class ShellUsers : public Users, DENG2_OBSERVES(World, MapChange) { - Q_OBJECT - public: ShellUsers(); - ~ShellUsers(); - - /** - * Adds a new remote shell user to the set of connected users. Users are - * automatically removed from this collection and deleted when they are - * disconnected. - * - * @param user User. Ownership transferred. - */ - void add(ShellUser *user); - - int count() const; - - void worldMapChanged(); - -public slots: - void sendPlayerInfoToAll(); - -protected slots: - void userDisconnected(); + void add(User *shellUser) override; + void worldMapChanged() override; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/users.h doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/users.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/include/users.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/include/users.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,66 @@ +/** @file users.h Users: connected clients. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef SERVER_USERS_H +#define SERVER_USERS_H + +#include +#include + +/** + * Abstract base class representing a connected client. + */ +class User +{ +public: + virtual ~User() {} + + virtual de::Address address() const = 0; + + DENG2_CAST_METHODS() + DENG2_DEFINE_AUDIENCE(Disconnect, void userDisconnected(User &)) +}; + +/** + * A set of connected clients. + */ +class Users +{ +public: + Users(); + + virtual ~Users(); + + /** + * Adds a new user to the set of connected users. Users are automatically removed + * from this collection and deleted when they are disconnected. + * + * @param user User. Ownership transferred. + */ + virtual void add(User *user); + + int count() const; + + de::LoopResult forUsers(std::function func); + +private: + DENG2_PRIVATE(d) +}; + + +#endif // SERVER_USERS_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/res/windows/doomsday.rc doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/res/windows/doomsday.rc --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/res/windows/doomsday.rc 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/res/windows/doomsday.rc 2018-12-11 07:08:23.000000000 +0000 @@ -82,7 +82,7 @@ " VALUE ""FileDescription"", ""Doomsday Engine Server\0""\r\n" " VALUE ""FileVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" " VALUE ""InternalName"", ""Doomsday Engine Server\0""\r\n" - " VALUE ""LegalCopyright"", ""Copyright © 2003-2012, Deng Team\0""\r\n" + " VALUE ""LegalCopyright"", ""Copyright (c) 2003-2018, Deng Team\0""\r\n" " VALUE ""OriginalFilename"", ""Doomsday-Server.exe\0""\r\n" " VALUE ""ProductName"", ""Doomsday Engine Server\0""\r\n" " VALUE ""ProductVersion"", DOOMSDAY_VERSION_TEXT ""\0""\r\n" @@ -132,7 +132,7 @@ VALUE "FileDescription", "Doomsday Engine Server\0" VALUE "FileVersion", DOOMSDAY_VERSION_TEXT "\0" VALUE "InternalName", "Doomsday Engine Server\0" - VALUE "LegalCopyright", "Copyright © 2003-2012, Deng Team\0" + VALUE "LegalCopyright", "Copyright (c) 2003-2018, Deng Team\0" VALUE "OriginalFilename", "Doomsday-Server.exe\0" VALUE "ProductName", "Doomsday Engine Server\0" VALUE "ProductVersion", DOOMSDAY_VERSION_TEXT "\0" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/remotefeeduser.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/remotefeeduser.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/remotefeeduser.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/remotefeeduser.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,215 @@ +/** @file remotefeeduser.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "remotefeeduser.h" + +#include +#include +#include +#include +#include + +using namespace de; + +DENG2_PIMPL(RemoteFeedUser) +{ + using QueryId = RemoteFeedQueryPacket::Id; + + struct Transfer + { + QueryId queryId; + Block data; + duint64 position = 0; + + Transfer(QueryId id = 0) : queryId(id) + {} + }; + + std::unique_ptr socket; + RemoteFeedProtocol protocol; + LockableT> transfers; + + Impl(Public *i, Socket *s) : Base(i), socket(s) + { + LOG_NET_MSG("Setting up RemoteFeedUser %p") << thisPublic; + + // The RemoteFeed protocol does not require ordered messages. + socket->setRetainOrder(false); + + QObject::connect(s, &Socket::messagesReady, [this] () { receiveMessages(); }); + QObject::connect(s, &Socket::allSent, [this] () { continueFileTransfers(); }); + QObject::connect(s, &Socket::disconnected, [this] () + { + DENG2_FOR_PUBLIC_AUDIENCE(Disconnect, i) + { + i->userDisconnected(self()); + } + }); + + // We took over an open socket, there may already be messages waiting. + receiveMessages(); + } + + void receiveMessages() + { + DENG2_ASSERT_IN_MAIN_THREAD(); + + LOG_AS("RemoteFeedUser"); + while (socket->hasIncoming()) + { + try + { + std::unique_ptr message { socket->receive() }; + std::shared_ptr packet { protocol.interpret(*message) }; + + LOG_NET_MSG("received packet '%s'") << packet->type(); + + if (protocol.recognize(*packet) == RemoteFeedProtocol::Query) + { + async([this, packet] () + { + return handleQueryAsync(packet->as()); + }, + [this] (Packet *response) + { + if (std::unique_ptr p { response }) + { + socket->sendPacket(*p); + } + else + { + continueFileTransfers(); + } + }); + } + } + catch (Error const &er) + { + LOG_NET_ERROR("Error during query: %s") << er.asText(); + } + } + } + + void continueFileTransfers() + { + DENG2_ASSERT_IN_MAIN_THREAD(); + try + { + if (socket->bytesBuffered() > 0) return; // Too soon. + + std::unique_ptr response; + + // Send the next block of the first file in the transfer queue. + { + DENG2_GUARD(transfers); + + if (transfers.value.isEmpty()) return; + + response.reset(new RemoteFeedFileContentsPacket); + + dsize const blockSize = 128 * 1024; + auto &xfer = transfers.value.front(); + + response->setId(xfer.queryId); + response->setFileSize(xfer.data.size()); + response->setStartOffset(xfer.position); + response->setData(xfer.data.mid(xfer.position, blockSize)); + + xfer.position += response->data().size(); + if (xfer.position >= xfer.data.size()) + { + // That was all. + transfers.value.pop_front(); + } + } + + if (response) + { + socket->sendPacket(*response); + } + } + catch (Error const &er) + { + LOG_NET_ERROR("Error during file transfer to %s: %s") + << socket->peerAddress().asText() + << er.asText(); + } + } + + Packet *handleQueryAsync(RemoteFeedQueryPacket const &query) + { + // Note: This is executed in a background thread. + try + { + // Make sure the file system is ready for use. + FS::waitForIdle(); + + std::unique_ptr response; + + switch (query.query()) + { + case RemoteFeedQueryPacket::ListFiles: + response.reset(new RemoteFeedMetadataPacket); + response->setId(query.id()); + if (auto const *folder = FS::tryLocate(query.path())) + { + response->addFolder(*folder); + } + else + { + LOG_NET_WARNING("%s not found!") << query.path(); + } + LOG_NET_MSG("%s") << response->metadata().asText(); + return response.release(); + + case RemoteFeedQueryPacket::FileContents: { + Transfer xfer(query.id()); + if (auto const *file = FS::tryLocate(query.path())) + { + *file >> xfer.data; + } + else + { + LOG_NET_WARNING("%s not found!") << query.path(); + } + LOG_NET_MSG("New file transfer: %s size:%i") + << query.path() + << xfer.data.size(); + DENG2_GUARD(transfers); + transfers.value.push_back(xfer); + break; } + } + } + catch (Error const &er) + { + LOG_NET_ERROR("Error while handling remote feed query from %s: %s") + << query.from().asText() << er.asText(); + } + return nullptr; + } +}; + +RemoteFeedUser::RemoteFeedUser(Socket *socket) + : d(new Impl(this, socket)) +{} + +Address RemoteFeedUser::address() const +{ + DENG2_ASSERT(d->socket); + return d->socket->peerAddress(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/remoteuser.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/remoteuser.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/remoteuser.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/remoteuser.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -119,7 +119,7 @@ //ddstring_t msg; - int length = command.size(); + auto const length = command.size(); // If the command is too long, it'll be considered invalid. if (length >= 256) @@ -132,7 +132,7 @@ if (command == "Info?") { shell::ServerInfo const info = ServerApp::currentServerInfo(); - Block const msg = "Info\n" + composeJSON(info); + Block const msg = "Info\n" + composeJSON(info.asRecord()); LOGDEV_NET_VERBOSE("Info reply:\n%s") << String::fromUtf8(msg); self() << msg; } @@ -151,6 +151,12 @@ Writer(serialized).withHeader() << packet; self() << Block("MapOutline\n" + serialized.compressed()); } + else if (command == "RemoteFeed") + { + // This connection will be only doing file system operations. + App_ServerSystem().convertToRemoteFeedUser(thisPublic); + return false; + } else if (length >= 5 && command.startsWith("Shell")) { if (length == 5) @@ -246,6 +252,8 @@ Socket *RemoteUser::takeSocket() { Socket *sock = d->socket; + QObject::disconnect(sock, SIGNAL(disconnected()), this, SLOT(socketDisconnected())); + QObject::disconnect(sock, SIGNAL(messagesReady()), this, SLOT(handleIncomingPackets())); d->socket = 0; d->state = Disconnected; // not signaled return sock; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/server/sv_main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/server/sv_main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/server/sv_main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/server/sv_main.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -989,7 +989,8 @@ { int i; - if (!isDedicated) return; + DENG_ASSERT(isDedicated); + //if (!isDedicated) return; // Note last angles for all players. for (i = 0; i < DDMAXPLAYERS; ++i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/serverapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/serverapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/serverapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/serverapp.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -28,11 +28,14 @@ #include #include +#include +#include +#include #include #include -#include +#include +#include #include -#include #include "serverapp.h" #include "serverplayer.h" @@ -56,6 +59,8 @@ static ServerApp *serverAppSingleton = 0; +static String const PATH_SERVER_FILES = "/sys/server/public"; + static void handleAppTerminate(char const *msg) { LogBuffer::get().flush(); @@ -67,12 +72,14 @@ , DENG2_OBSERVES(DoomsdayApp, GameUnload) , DENG2_OBSERVES(DoomsdayApp, ConsoleRegistration) , DENG2_OBSERVES(DoomsdayApp, PeriodicAutosave) +, DENG2_OBSERVES(PackageLoader, Activity) { QScopedPointer serverSystem; QScopedPointer resources; QScopedPointer audioSys; ClientServerWorld world; InFineSystem infineSys; + duint32 serverId; Impl(Public *i) : Base(i) @@ -83,6 +90,12 @@ self().audienceForGameUnload() += this; self().audienceForConsoleRegistration() += this; self().audienceForPeriodicAutosave() += this; + PackageLoader::get().audienceForActivity() += this; + + // Each running server instance is given a random identifier. + serverId = randui32() & 0x7fffffff; + + LOG_NET_NOTE("Server instance ID: %08x") << serverId; } ~Impl() @@ -91,32 +104,30 @@ DD_Shutdown(); } - void publishAPIToPlugin(::Library *plugin) + void publishAPIToPlugin(::Library *plugin) override { DD_PublishAPIs(plugin); } - void consoleRegistration() + void consoleRegistration() override { DD_ConsoleRegister(); } - void aboutToUnloadGame(Game const &/*gameBeingUnloaded*/) + void aboutToUnloadGame(Game const &/*gameBeingUnloaded*/) override { if (netGame && isServer) { N_ServerClose(); } - infineSystem().reset(); - if (App_GameLoaded()) { Con_SaveDefaults(); } } - void periodicAutosave() + void periodicAutosave() override { if (Config::exists()) { @@ -125,6 +136,29 @@ Con_SaveDefaultsIfChanged(); } + void initServerFiles() + { + // Packages available to clients via RemoteFeed use versioned identifiers because + // a client may already have a different version of the package. + + Folder &files = self().fileSystem().makeFolder(PATH_SERVER_FILES); + auto *feed = new PackageFeed(PackageLoader::get(), + PackageFeed::LinkVersionedIdentifier); + feed->setFilter([] (Package const &pkg) + { + return !pkg.matchTags(pkg.file(), "\\b(vanilla|core)\\b"); + }); + files.attach(feed); + } + + void setOfLoadedPackagesChanged() override + { + if (Folder *files = FS::tryLocate(PATH_SERVER_FILES)) + { + files->populate(); + } + } + #ifdef UNIX void printVersionToStdOut() { @@ -187,6 +221,11 @@ serverAppSingleton = 0; } +duint32 ServerApp::instanceId() const +{ + return d->serverId; +} + void ServerApp::initialize() { Libdeng_Init(); @@ -218,6 +257,8 @@ initSubsystems(); DoomsdayApp::initialize(); + d->initServerFiles(); + // Initialize. #if WIN32 if (!DD_Win32_Init()) @@ -250,18 +291,19 @@ } } -shell::ServerInfo ServerApp::currentServerInfo() +shell::ServerInfo ServerApp::currentServerInfo() // static { shell::ServerInfo info; // Let's figure out what we want to tell about ourselves. + info.setServerId(ServerApp::app().d->serverId); info.setCompatibilityVersion(DOOMSDAY_VERSION); info.setPluginDescription(String::format("%s %s", - reinterpret_cast(gx.GetVariable(DD_PLUGIN_NAME)), - reinterpret_cast(gx.GetVariable(DD_PLUGIN_VERSION_SHORT)))); + reinterpret_cast(gx.GetPointer(DD_PLUGIN_NAME)), + reinterpret_cast(gx.GetPointer(DD_PLUGIN_VERSION_SHORT)))); info.setGameId(game().id()); - info.setGameConfig(reinterpret_cast(gx.GetVariable(DD_GAME_CONFIG))); + info.setGameConfig(reinterpret_cast(gx.GetPointer(DD_GAME_CONFIG))); info.setName(serverName); info.setDescription(serverInfo); @@ -285,6 +327,10 @@ info.setMap(mapPath); } + // The master server will use the public IP address where an announcement came from, + // so we don't necessarily have to specify a valid address. The port is required, though. + info.setAddress({"localhost", duint16(nptIPPort)}); + // This will only work if the server has a public IP address. QHostInfo const host = QHostInfo::fromName(QHostInfo::localHostName()); foreach (QHostAddress hostAddr, host.addresses()) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/serversystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/serversystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/serversystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/serversystem.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -33,6 +33,7 @@ #include "serverapp.h" #include "shellusers.h" #include "remoteuser.h" +#include "remotefeeduser.h" #include "server/sv_def.h" #include "server/sv_frame.h" @@ -52,7 +53,7 @@ using namespace de; char *nptIPAddress = (char *) ""; ///< Public domain for clients to connect to (cvar). -int nptIPPort = 0; ///< Server TCP port (cvar). +int nptIPPort = 0; ///< Server TCP port (cvar). static de::duint16 Server_ListenPort() { @@ -71,6 +72,7 @@ QHash users; ShellUsers shellUsers; + Users remoteFeedUsers; Impl(Public *i) : Base(i) {} ~Impl() { deinit(); } @@ -215,7 +217,14 @@ { LOG_MSG("%i shell user%s") << shellUsers.count() - << (shellUsers.count() == 1? "" : "s"); + << DENG2_PLURAL_S(shellUsers.count()); + } + + if (remoteFeedUsers.count()) + { + LOG_MSG("%i remote file system user%s") + << remoteFeedUsers.count() + << DENG2_PLURAL_S(remoteFeedUsers.count()); } N_PrintBufferInfo(); @@ -278,6 +287,24 @@ d->shellUsers.add(new ShellUser(socket)); } +void ServerSystem::convertToRemoteFeedUser(RemoteUser *user) +{ + DENG2_ASSERT(user); + + Socket *socket = user->takeSocket(); + LOGDEV_NET_VERBOSE("Remote user %s converted to remote file system user") << user->id(); + user->deleteLater(); + + d->remoteFeedUsers.add(new RemoteFeedUser(socket)); +} + +int ServerSystem::userCount() const +{ + return d->remoteFeedUsers.count() + + d->shellUsers.count() + + d->users.size(); +} + void ServerSystem::timeChanged(Clock const &clock) { if (Sys_IsShuttingDown()) @@ -285,14 +312,8 @@ Garbage_Recycle(); - // Adjust loop rate depending on whether players are in game. - int count = 0; - for (int i = 1; i < DDMAXPLAYERS; ++i) - { - if (DD_Player(i)->publicData().inGame) count++; - } - - DENG2_TEXT_APP->loop().setRate(count? 35 : 3); + // Adjust loop rate depending on whether users are connected. + DENG2_TEXT_APP->loop().setRate(userCount()? 35 : 3); Loop_RunTics(); @@ -334,8 +355,10 @@ d->users.remove(u->id()); - LOG_NET_VERBOSE("%i remote users and %i shell users remain") - << d->users.size() << d->shellUsers.count(); + LOG_NET_VERBOSE("Remaining user count: %i remote, %i shell, %i filesys") + << d->users.size() + << d->shellUsers.count() + << d->remoteFeedUsers.count(); } void ServerSystem::printStatus() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/shelluser.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/shelluser.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/shelluser.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/shelluser.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -41,7 +42,7 @@ DENG2_PIMPL(ShellUser), public LogSink { /// Log entries to be sent are collected here. - shell::LogEntryPacket logEntryPacket; + LockableT logEntryPacket; Impl(Public &i) : Base(i) { @@ -56,7 +57,8 @@ LogSink &operator << (LogEntry const &entry) { - logEntryPacket.add(entry); + DENG2_GUARD(logEntryPacket); + logEntryPacket.value.add(entry); return *this; } @@ -67,19 +69,31 @@ /** * Sends the accumulated log entries over the link. + * Note that any thread can flush the log sinks. */ void flush() { - if (!logEntryPacket.isEmpty() && self().status() == shell::Link::Connected) + Loop::mainCall([this] () { - self() << logEntryPacket; - logEntryPacket.clear(); - } + DENG2_GUARD(logEntryPacket); + if (!logEntryPacket.value.isEmpty() && self().status() == shell::Link::Connected) + { + self() << logEntryPacket.value; + logEntryPacket.value.clear(); + } + }); } }; ShellUser::ShellUser(Socket *socket) : shell::Link(socket), d(new Impl(*this)) { + connect(this, &Link::disconnected, [this] () + { + DENG2_FOR_AUDIENCE(Disconnect, i) + { + i->userDisconnected(*this); + } + }); connect(this, SIGNAL(packetsReady()), this, SLOT(handleIncomingPackets())); } @@ -110,7 +124,7 @@ * state packet. */ - String rules = reinterpret_cast(gx.GetVariable(DD_GAME_CONFIG)); + String rules = reinterpret_cast(gx.GetPointer(DD_GAME_CONFIG)); // Check the map's information. String mapId; @@ -172,6 +186,11 @@ *this << *packet; } +Address ShellUser::address() const +{ + return Link::address(); +} + void ShellUser::handleIncomingPackets() { forever diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/shellusers.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/shellusers.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/shellusers.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/shellusers.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -19,6 +19,7 @@ #include "shellusers.h" #include "dd_main.h" +#include #include using namespace de; @@ -27,79 +28,45 @@ DENG2_PIMPL_NOREF(ShellUsers) { - QSet users; - QTimer *infoTimer; + QTimer infoTimer; Impl() { - infoTimer = new QTimer; - infoTimer->setInterval(PLAYER_INFO_INTERVAL); - } - - ~Impl() - { - delete infoTimer; + infoTimer.setInterval(PLAYER_INFO_INTERVAL); } }; ShellUsers::ShellUsers() : d(new Impl) { // Player information is sent periodically to all shell users. - connect(d->infoTimer, SIGNAL(timeout()), this, SLOT(sendPlayerInfoToAll())); - d->infoTimer->start(); -} - -ShellUsers::~ShellUsers() -{ - d->infoTimer->stop(); - - foreach (ShellUser *user, d->users) + QObject::connect(&d->infoTimer, &QTimer::timeout, [this] () { - delete user; - } + forUsers([this] (User &user) + { + user.as().sendPlayerInfo(); + return LoopContinue; + }); + }); + d->infoTimer.start(); } -void ShellUsers::add(ShellUser *user) +void ShellUsers::add(User *user) { - LOG_NET_NOTE("New shell user from %s") << user->address(); - - d->users.insert(user); - connect(user, SIGNAL(disconnected()), this, SLOT(userDisconnected())); + DENG2_ASSERT(is(user)); + Users::add(user); - user->sendInitialUpdate(); -} - -int ShellUsers::count() const -{ - return d->users.size(); + LOG_NET_NOTE("New shell user from %s") << user->address(); + user->as().sendInitialUpdate(); } void ShellUsers::worldMapChanged() { - foreach (ShellUser *user, d->users) + forUsers([this] (User &user) { - user->sendGameState(); - user->sendMapOutline(); - user->sendPlayerInfo(); - } -} - -void ShellUsers::sendPlayerInfoToAll() -{ - foreach (ShellUser *user, d->users) - { - user->sendPlayerInfo(); - } -} - -void ShellUsers::userDisconnected() -{ - DENG2_ASSERT(dynamic_cast(sender()) != 0); - - ShellUser *user = static_cast(sender()); - d->users.remove(user); - - LOG_NET_NOTE("Shell user from %s has disconnected") << user->address(); - - user->deleteLater(); + ShellUser &shellUser = user.as(); + shellUser.sendGameState(); + shellUser.sendMapOutline(); + shellUser.sendPlayerInfo(); + return LoopContinue; + }); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/users.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/users.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/apps/server/src/users.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/apps/server/src/users.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,72 @@ +/** @file users.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "users.h" +#include + +using namespace de; + +DENG2_PIMPL_NOREF(Users) +, DENG2_OBSERVES(User, Disconnect) +{ + QSet users; + + void userDisconnected(User &user) override + { + LOG_NET_MSG("User from %s has disconnected") << user.address(); + + user.audienceForDisconnect -= this; + users.remove(&user); + de::trash(&user); + } +}; + +Users::Users() : d(new Impl) +{} + +Users::~Users() +{ + foreach (User *user, d->users) + { + delete user; + } +} + +void Users::add(User *user) +{ + DENG2_ASSERT(user); + d->users.insert(user); + user->audienceForDisconnect += d; +} + +LoopResult Users::forUsers(std::function func) +{ + foreach (User *user, d->users) + { + if (auto result = func(*user)) + { + return result; + } + } + return LoopContinue; +} + +int Users::count() const +{ + return d->users.size(); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/buildpackage.py doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/buildpackage.py --- doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/buildpackage.py 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/buildpackage.py 2018-12-11 07:08:23.000000000 +0000 @@ -1,34 +1,35 @@ #!/usr/bin/env python2.7 # # Command line utility for zipping a directory of files into a .pack. -# Checks that the required Info file is present. +# Checks that the required Info file is present. # # Usage: # buildpackage (pack-dir) (output-dir) # -import sys, os, os.path, zipfile +from __future__ import print_function +import sys, os, os.path, zipfile, time if len(sys.argv) < 2: - print "Usage: %s (pack-dir) (output-dir)" % sys.argv[0] + print("Usage: %s (pack-dir) (output-dir)" % sys.argv[0]) sys.exit(0) # Check quiet flag. class Package: def __init__(self, sourcePath): self.sourcePath = sourcePath - + def build(self, outputPath): # Ensure the output path exists. try: os.makedirs(outputPath) except: pass - + outputName = os.path.join(outputPath, os.path.basename(self.sourcePath)) - pack = zipfile.ZipFile(outputName, 'w', zipfile.ZIP_DEFLATED) + pack = zipfile.ZipFile(outputName, 'w', zipfile.ZIP_DEFLATED) contents = [] - + # Index the contents of the folder recursively. def descend(path): for name in os.listdir(os.path.join(self.sourcePath, path)): @@ -40,7 +41,7 @@ else: internalPath = name fullPath = os.path.join(self.sourcePath, internalPath) - + if os.path.isfile(fullPath): contents.append((fullPath, internalPath)) elif os.path.isdir(fullPath): @@ -52,17 +53,21 @@ for full, internal in contents: if internal.lower() == 'info' or internal.lower() == 'info.dei': foundInfo = True - break + break if not foundInfo: - print "No 'Info' file found in \"%s\"!" % self.sourcePath + print("No 'Info' file found in \"%s\"!" % self.sourcePath) sys.exit(1) - + # Write entries in alphabetical order. + date_time = time.gmtime(int(os.environ.get('SOURCE_DATE_EPOCH', time.time()))) for full, internal in sorted(contents): - pack.write(full, internal) - + info = zipfile.ZipInfo(internal, date_time) + info.external_attr = 0o644 << 16 + with open(full, 'rb') as f: + pack.writestr(info, f.read()) + # Write it out. - print "Wrote %s (contains %i files)." % (outputName.replace("\\", "/"), len(pack.namelist())) + print("Wrote %s (contains %i files)." % (outputName.replace("\\", "/"), len(pack.namelist()))) pack.close() if __name__ == "__main__": diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/Makefile.xcpacks doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/Makefile.xcpacks --- doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/Makefile.xcpacks 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/Makefile.xcpacks 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,49 @@ +# Makefile for packaging all needed packages for the Xcode iOS build. + +ROOT := $(SRCROOT)/.. +SCRIPTS := $(SRCROOT)/../build/scripts +CLIENT_DATA := ${ROOT}/apps/client/data +DOOM_DATA := ${ROOT}/apps/plugins/doom/data +HERETIC_DATA := {ROOT}/apps/plugins/heretic/data +HEXEN_DATA := {ROOT}/apps/plugins/hexen/data +DOOM64_DATA := ${ROOT}/apps/plugins/doom64/data + +STDLIB_FILES := $(shell find $(ROOT)/sdk/libcore/net.dengine.stdlib.pack) +STDLIB_GUI_FILES := $(shell find $(ROOT)/sdk/libgui/net.dengine.stdlib.gui.pack) +BASE_FILES := $(shell find $(ROOT)/apps/libdoomsday/net.dengine.base.pack) +CLIENT_FILES := $(shell find $(ROOT)/apps/client/net.dengine.client.pack | \ + sed -e 's/ /\\ /g') + +PACK_FILES := \ + $(wildcard ${CLIENT_DATA}/fonts/*.dfn) \ + $(wildcard ${CLIENT_DATA}/graphics/*.png) \ + $(wildcard ${CLIENT_DATA}/graphics/*.pcx) \ + $(wildcard ${DOOM_DATA}/lumps/*.lmp) \ + $(wildcard ${DOOM_DATA}/*.mapinfo) \ + $(wildcard ${DOOM_DATA}/*.txt)\ + $(wildcard ${HERETIC_DATA}/lumps/*.lmp) \ + $(wildcard ${HERETIC_DATA}/*.mapinfo) \ + $(wildcard ${HERETIC_DATA}/*.txt) \ + $(wildcard ${HEXEN_DATA}/lumps/*.lmp) \ + $(wildcard ${HEXEN_DATA}/*.mapinfo) \ + $(wildcard ${HEXEN_DATA}/*.txt) \ + $(wildcard ${DOOM64_DATA}/lumps/*.lmp) \ + $(wildcard ${DOOM64_DATA}/*.mapinfo) \ + $(wildcard ${DOOM64_DATA}/*.txt) + +all: doomsday.pk3 libdoom.pk3 libheretic.pk3 libhexen.pk3 net.dengine.stdlib.pack net.dengine.stdlib.gui.pack net.dengine.base.pack net.dengine.client.pack + +doomsday.pk3 libdoom.pk3 libheretic.pk3 libhexen.pk3: ${PACK_FILES} + cd ${SCRIPTS} && ./packres.py --quiet $(PROJECT_TEMP_DIR) + +net.dengine.stdlib.pack: ${STDLIB_FILES} + ${SCRIPTS}/buildpackage.py $(ROOT)/sdk/libcore/net.dengine.stdlib.pack $(PROJECT_TEMP_DIR) + +net.dengine.stdlib.gui.pack: ${STDLIB_GUI_FILES} + ${SCRIPTS}/buildpackage.py $(ROOT)/sdk/libgui/net.dengine.stdlib.gui.pack $(PROJECT_TEMP_DIR) + +net.dengine.base.pack: ${BASE_FILES} + ${SCRIPTS}/buildpackage.py $(ROOT)/apps/libdoomsday/net.dengine.base.pack $(PROJECT_TEMP_DIR) + +net.dengine.client.pack: ${CLIENT_FILES} + ${SCRIPTS}/buildpackage.py $(ROOT)/apps/client/net.dengine.client.pack $(PROJECT_TEMP_DIR) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/packres.py doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/packres.py --- doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/packres.py 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/packres.py 2018-12-11 07:08:23.000000000 +0000 @@ -3,11 +3,12 @@ # that Doomsday needs at runtime. The PK3 files are organized using the # traditional data/ and defs/ structure. +from __future__ import print_function import sys, os, os.path, zipfile if len(sys.argv) < 2: - print "Usage: %s pk3-target-dir" % sys.argv[0] - print "(run in build/scripts/)" + print("Usage: %s pk3-target-dir" % sys.argv[0]) + print("(run in build/scripts/)") sys.exit(0) # Check quiet flag. @@ -27,7 +28,7 @@ self.files += fileNamesArray def msg(self, text): - if not quietMode: print text + if not quietMode: print(text) def create(self, name): full_name = os.path.join(target_dir, name) @@ -61,7 +62,7 @@ process_dir(full_src, dest) # Write it out. - print "Created %s (with %i files)." % (os.path.normpath(full_name), len(pk3.namelist())) + print("Created %s (with %i files)." % (os.path.normpath(full_name), len(pk3.namelist()))) pk3.close() # First up, doomsday.pk3. @@ -79,6 +80,8 @@ ('plugins/doom/data/doom1-share.mapinfo', 'data/jdoom/doom1-share.mapinfo'), ('plugins/doom/data/doom1-ultimate.mapinfo', 'data/jdoom/doom1-ultimate.mapinfo'), ('plugins/doom/data/doom1.mapinfo', 'data/jdoom/doom1.mapinfo'), + ('plugins/doom/data/doom2-bfg.mapinfo', 'data/jdoom/doom2-bfg.mapinfo'), + ('plugins/doom/data/doom2-nerve.mapinfo', 'data/jdoom/doom2-nerve.mapinfo'), ('plugins/doom/data/doom2-plut.mapinfo', 'data/jdoom/doom2-plut.mapinfo'), ('plugins/doom/data/doom2-tnt.mapinfo', 'data/jdoom/doom2-tnt.mapinfo'), ('plugins/doom/data/doom2-freedoom.mapinfo', 'data/jdoom/doom2-freedoom.mapinfo'), diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/xcmoc.py doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/xcmoc.py --- doomsday-stable-2.0.3.2464+xenial/doomsday/build/scripts/xcmoc.py 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/build/scripts/xcmoc.py 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,83 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- + +# xcmoc.py +# Run Qt moc on all classes that contain Q_OBJECT +# +# Created by Jaakko Keränen on 2017-05-07. +# Copyright © 2017 Jaakko Keränen + +import sys, os, re, subprocess, hashlib + +IGNORED_HEADERS = ['glwindow.h'] + +def contains_qobject(fn): + for line in open(fn, 'rt').readlines(): + if 'Q_OBJECT' in line: + return True + return False + +def find_headers(dir_path): + headers = [] + for fn in os.listdir(dir_path): + if fn in IGNORED_HEADERS: continue + file_path = os.path.join(dir_path, fn) + if os.path.isdir(file_path): + headers += find_headers(file_path) + elif fn.endswith('.h'): + if contains_qobject(file_path): + headers.append(os.path.abspath(file_path)) + return headers + +# def find_source(name, dir_path = os.path.join(sys.argv[1], 'src')): +# for fn in os.listdir(dir_path): +# file_path = os.path.join(dir_path, fn) +# if os.path.isdir(file_path): +# found = find_source(name, file_path) +# if found: return found +# elif fn == name[:-2] + '.cpp': +# return os.path.abspath(file_path) +# return None + +def md5sum(text): + m = hashlib.md5() + m.update(text.encode()) + m.update(os.getenv('GCC_PREPROCESSOR_DEFINITIONS').encode()) + m.update(os.getenv('HEADER_SEARCH_PATHS').encode()) + return m.hexdigest() + +#print "Running moc in", sys.argv[1] +OUT_DIR = os.getenv('PROJECT_TEMP_DIR') +try: + os.makedirs(OUT_DIR) +except: + pass + +headers = find_headers(sys.argv[1]) + +QT_DIR = os.getenv('QT_DIR') +defines = ['-D%s' % d for d in os.getenv('GCC_PREPROCESSOR_DEFINITIONS').split()] +includes = ['-I%s' % d for d in re.split(r"(?<=\w)\s", os.getenv('HEADER_SEARCH_PATHS'))] +args = ['%s/bin/moc' % QT_DIR] + defines + includes + +compilation = ['/* This file is autogenerated by xcmoc.py */'] + +for header in headers: + header_name = os.path.basename(header) + dir_path = os.path.dirname(header) + moc_name = '%s_moc_%s.cpp' % (md5sum(dir_path), header_name[:-2]) + moc_path = os.path.join(OUT_DIR, moc_name) + + compilation.append('#include "%s"' % moc_name) + + # Check timestamps. + if not os.path.exists(moc_path) or \ + os.path.getmtime(header) > os.path.getmtime(moc_path): + print 'Running moc:', header_name + subprocess.check_output(args + [header, '-o', moc_path], stderr=subprocess.STDOUT) + +comp_path = os.path.join(OUT_DIR, '%s_moc_compilation.cpp' % os.getenv('TARGETNAME')) + +open(comp_path, 'wt').write("\n".join(compilation) + "\n") + + \ No newline at end of file diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/.clang-format doomsday-stable-2.1.0.2900+xenial/doomsday/.clang-format --- doomsday-stable-2.0.3.2464+xenial/doomsday/.clang-format 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/.clang-format 2018-12-11 07:08:16.000000000 +0000 @@ -0,0 +1,106 @@ +Language: Cpp +AccessModifierOffset: -4 +AlignAfterOpenBracket: Align +AlignConsecutiveAssignments: true +AlignConsecutiveDeclarations: true +AlignEscapedNewlines: Left +AlignOperands: true +AlignTrailingComments: true +AllowAllParametersOfDeclarationOnNextLine: false +AllowShortBlocksOnASingleLine: false +AllowShortCaseLabelsOnASingleLine: true +AllowShortFunctionsOnASingleLine: Inline +AllowShortIfStatementsOnASingleLine: true +AllowShortLoopsOnASingleLine: false +AlwaysBreakAfterDefinitionReturnType: None +AlwaysBreakAfterReturnType: None +AlwaysBreakBeforeMultilineStrings: false +AlwaysBreakTemplateDeclarations: false +BinPackArguments: false +BinPackParameters: true +BraceWrapping: + AfterClass: true + AfterControlStatement: true + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: false + AfterUnion: true + BeforeCatch: true + BeforeElse: true + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: false + SplitEmptyNamespace: true +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakBeforeInheritanceComma: true +BreakBeforeTernaryOperators: true +BreakConstructorInitializersBeforeComma: true +BreakConstructorInitializers: BeforeComma +BreakAfterJavaFieldAnnotations: false +BreakStringLiterals: true +ColumnLimit: 100 +CommentPragmas: '^ IWYU pragma:' +CompactNamespaces: true +ConstructorInitializerAllOnOneLineOrOnePerLine: false +ConstructorInitializerIndentWidth: 4 +ContinuationIndentWidth: 4 +Cpp11BracedListStyle: true +DerivePointerAlignment: false +DisableFormat: false +ExperimentalAutoDetectBinPacking: false +FixNamespaceComments: true +ForEachMacros: + - foreach + - Q_FOREACH + - BOOST_FOREACH +#IncludeBlocks: Preserve +IncludeCategories: + - Regex: '^"(llvm|llvm-c|clang|clang-c)/' + Priority: 2 + - Regex: '^(<|"(gtest|gmock|isl|json)/)' + Priority: 3 + - Regex: '.*' + Priority: 1 +IncludeIsMainRegex: '(Test)?$' +IndentCaseLabels: true +IndentPPDirectives: AfterHash +IndentWidth: 4 +IndentWrappedFunctionNames: false +JavaScriptQuotes: Leave +JavaScriptWrapImports: true +KeepEmptyLinesAtTheStartOfBlocks: true +MacroBlockBegin: '' +MacroBlockEnd: '' +MaxEmptyLinesToKeep: 1 +NamespaceIndentation: None +ObjCBlockIndentWidth: 2 +ObjCSpaceAfterProperty: true +ObjCSpaceBeforeProtocolList: false +PenaltyBreakAssignment: 2 +PenaltyBreakBeforeFirstCallParameter: 19 +PenaltyBreakComment: 300 +PenaltyBreakFirstLessLess: 120 +PenaltyBreakString: 1000 +PenaltyExcessCharacter: 1000000 +PenaltyReturnTypeOnItsOwnLine: 200 +PointerAlignment: Right +ReflowComments: false +SortIncludes: false +SortUsingDeclarations: true +SpaceAfterCStyleCast: true +SpaceAfterTemplateKeyword: true +SpaceBeforeAssignmentOperators: true +SpaceBeforeParens: ControlStatements +SpaceInEmptyParentheses: false +SpacesBeforeTrailingComments: 1 +SpacesInAngles: false +SpacesInContainerLiterals: true +SpacesInCStyleCastParentheses: false +SpacesInParentheses: false +SpacesInSquareBrackets: false +Standard: Cpp11 +TabWidth: 4 +UseTab: Never diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/config/DengGuiConfig.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/config/DengGuiConfig.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/config/DengGuiConfig.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/config/DengGuiConfig.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,10 +1,20 @@ # find_package (Qt5 COMPONENTS Gui OpenGL REQUIRED) find_package (DengCore REQUIRED) -# Deng::libgui may exist in the current build, in which case using +# Deng::libgui may exist in the current build, in which case using # a previously installed version is inappropriate. if (NOT TARGET Deng::libgui) include ("${CMAKE_CURRENT_LIST_DIR}/DengGui.cmake") endif () list (APPEND DENG_REQUIRED_PACKAGES net.dengine.stdlib.gui) + +if (DENG_OPENGL_API STREQUAL "3.3") + add_definitions (-DDENG_OPENGL=330) +elseif (DENG_OPENGL_API STREQUAL "GLES3") + add_definitions (-DDENG_OPENGL_ES=30) +elseif (DENG_OPENGL_API STREQUAL "GLES2") + add_definitions (-DDENG_OPENGL_ES=20) +else () + message (FATAL_ERROR "Invalid value for OpenGL API: ${DENG_OPENGL_API}") +endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Config.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Config.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Config.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Config.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -3,7 +3,9 @@ # All CMakeLists should include this file to gain access to the overall # project configuration. -cmake_policy (SET CMP0053 OLD) # Warning from Qt 5.8.0 modules +if (POLICY CMP0068) + cmake_policy (SET CMP0068 OLD) # macOS: RPATH affects install_name +endif () get_filename_component (_where "${CMAKE_CURRENT_SOURCE_DIR}" NAME) message (STATUS "Configuring ${_where}...") @@ -36,6 +38,11 @@ set (DENG_CONFIGURATION_TYPES ${CMAKE_BUILD_TYPE}) endif () +if (UNIX AND NOT APPLE) + set (UNIX_LINUX YES) + include (GNUInstallDirs) +endif() + include (Macros) include (Arch) include (BuildTypes) @@ -45,10 +52,6 @@ include (Options) include (Packaging) -if (UNIX AND NOT APPLE) - include (GNUInstallDirs) -endif() - # Install directories. set (DENG_INSTALL_DATA_DIR "share/doomsday") set (DENG_INSTALL_DOC_DIR "share/doc") @@ -91,9 +94,23 @@ find_package (Qt4 REQUIRED) endif () +# Check for mobile platforms. +if (NOT QMAKE_XSPEC_CHECKED) + qmake_query (xspec "QMAKE_XSPEC") + set (QMAKE_XSPEC ${xspec} CACHE STRING "Value of QMAKE_XSPEC") + set (QMAKE_XSPEC_CHECKED YES CACHE BOOL "QMAKE_XSPEC has been checked") + mark_as_advanced (QMAKE_XSPEC) + mark_as_advanced (QMAKE_XSPEC_CHECKED) + if (QMAKE_XSPEC STREQUAL "macx-ios-clang") + set (IOS YES CACHE BOOL "Building for iOS platform") + endif () +endif () + # Platform-Specific Configuration -------------------------------------------- -if (APPLE) +if (IOS) + include (PlatformiOS) +elseif (APPLE) include (PlatformMacx) elseif (WIN32) include (PlatformWindows) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindFMOD.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindFMOD.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindFMOD.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindFMOD.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -2,19 +2,20 @@ set (_oldPath ${FMOD_FMOD_H}) -find_file (FMOD_FMOD_H api/inc/fmod.h +find_file (FMOD_FMOD_H api/lowlevel/inc/fmod.h PATHS "${FMOD_DIR}" HINTS ENV DENG_DEPEND_PATH - PATH_SUFFIXES "FMOD" "FMOD Programmers API" + PATH_SUFFIXES "FMOD" "FMOD Programmers API" "FMOD Studio API Windows" NO_DEFAULT_PATH + NO_CMAKE_FIND_ROOT_PATH ) mark_as_advanced (FMOD_FMOD_H) if (NOT _oldPath STREQUAL FMOD_FMOD_H) if (FMOD_FMOD_H) - message (STATUS "Looking for FMOD Ex - found") + message (STATUS "Looking for FMOD Low Level Programmer API - found") else () - message (STATUS "Looking for FMOD Ex - not found (set the FMOD_DIR variable)") + message (STATUS "Looking for FMOD Low Level Programmer API - not found (set the FMOD_DIR variable)") endif () endif () @@ -24,25 +25,39 @@ add_library (fmodex INTERFACE) target_include_directories (fmodex INTERFACE ${fmodInc}) - if (APPLE) - set (fmodLib "${fmodApi}/lib/libfmodex.dylib") + set (fmodInstLib) + if (IOS) + if (IOS_PLATFORM STREQUAL SIMULATOR) + set (fmodLib "${fmodApi}/lib/libfmod_iphonesimulator.a") + else () + set (fmodLib "${fmodApi}/lib/libfmod_iphoneos.a") + endif () + if (NOT EXISTS ${fmodLib}) + message (FATAL_ERROR "iOS version of FMOD library not found: ${FMOD_FMOD_H}") + endif () + link_framework (fmodex INTERFACE AVFoundation) + link_framework (fmodex INTERFACE AudioToolbox) + elseif (APPLE) + set (fmodLib "${fmodApi}/lib/libfmod.dylib") set (fmodInstLib ${fmodLib}) elseif (MSVC) if (ARCH_BITS EQUAL 64) - set (fmodLib "${fmodApi}/lib/fmodex64_vc.lib") - set (fmodInstLib "${fmodApi}/fmodex64.dll") + set (fmodLib "${fmodApi}/lib/fmod64_vc.lib") + set (fmodInstLib "${fmodApi}/lib/fmod64.dll") else () - set (fmodLib "${fmodApi}/lib/fmodex_vc.lib") - set (fmodInstLib "${fmodApi}/fmodex.dll") + set (fmodLib "${fmodApi}/lib/fmod_vc.lib") + set (fmodInstLib "${fmodApi}/lib/fmod.dll") endif () elseif (UNIX) if (ARCH_BITS EQUAL 64) - set (fmodLib ${fmodApi}/lib/libfmodex64.so) + set (fmodLib ${fmodApi}/lib/x86_64/libfmod.so) else () - set (fmodLib ${fmodApi}/lib/libfmodex.so) + set (fmodLib ${fmodApi}/lib/x86/libfmod.so) endif () set (fmodInstLib ${fmodLib}) endif () target_link_libraries (fmodex INTERFACE ${fmodLib}) - deng_install_library (${fmodInstLib}) + if (fmodInstLib) + deng_install_library (${fmodInstLib}) + endif () endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindGlib.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindGlib.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindGlib.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindGlib.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,3 +1,7 @@ +if (WIN32) + set (MINGW_GLIB_DIR "" CACHE PATH "GLib 2.0 SDK directory (mingw)") +endif () + if (APPLE AND GLIB_STATIC_DIR AND GETTEXT_STATIC_DIR) # Use the static versions of GLib and its dependencies. add_library (glib INTERFACE) @@ -14,6 +18,26 @@ ) link_framework (glib INTERFACE CoreFoundation) link_framework (glib INTERFACE CoreServices) +elseif (MINGW_GLIB_DIR) + add_library (glib INTERFACE) + target_link_libraries (glib INTERFACE + ${MINGW_GLIB_DIR}/${DENG_ARCH}/lib/libglib-2.0-0.lib + ${MINGW_GLIB_DIR}/${DENG_ARCH}/lib/libgthread-2.0-0.lib + ws2_32.lib + ) + target_include_directories (glib INTERFACE + ${MINGW_GLIB_DIR}/${DENG_ARCH}/include/glib-2.0 + ${MINGW_GLIB_DIR}/${DENG_ARCH}/lib/glib-2.0/include + ) + if (DENG_ARCH STREQUAL x86) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libgcc_s_dw2-1.dll) + endif () + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libglib-2.0-0.dll) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libgthread-2.0-0.dll) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libintl-8.dll) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libiconv-2.dll) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libpcre-1.dll) + deng_install_library (${MINGW_GLIB_DIR}/${DENG_ARCH}/bin/libwinpthread-1.dll) else () # Find GLib via pkg-config. find_package (PkgConfig) @@ -23,4 +47,4 @@ get_property (GLIB_LIBRARIES TARGET glib PROPERTY INTERFACE_LINK_LIBRARIES ) -endif () \ No newline at end of file +endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindOculusVR.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindOculusVR.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindOculusVR.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindOculusVR.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,3 +1,7 @@ +if (IOS) + return () +endif () + # This is the version of LibOVR that is required. set (LIBOVR_REQUIRED_VERSION 0.5.0.1) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindQt.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindQt.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindQt.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindQt.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,6 +1,6 @@ # Qmake is used to find out the Qt install location. if (NOT QMAKE) - find_program (QMAKE NAMES qmake-qt5 qt5-qmake qmake qmake-qt4 qt4-qmake + find_program (QMAKE NAMES qmake-qt5 qt5-qmake qmake qmake-qt4 qt4-qmake ${QT_QMAKE_EXECUTABLE} PATHS ENV PATH HINTS ${QT_QMAKE_EXECUTABLE} ENV DENG_DEPEND_PATH DOC "Path of the qmake executable to use" @@ -50,6 +50,10 @@ set (QT_LIBS ${_qtLibs} CACHE PATH "Qt library directory") mark_as_advanced (QT_LIBS) + qmake_query (_qtPlugins "QT_INSTALL_PLUGINS") + set (QT_PLUGINS ${_qtPlugins} CACHE PATH "Qt plugins directory") + mark_as_advanced (QT_PLUGINS) + qmake_query (QT_BINS "QT_INSTALL_BINS") if (APPLE) set (MACDEPLOYQT_COMMAND "${QT_BINS}/macdeployqt" CACHE PATH diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindSDL2.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindSDL2.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/FindSDL2.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/FindSDL2.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,9 +1,9 @@ find_package (PkgConfig QUIET) -if (PKG_CONFIG_FOUND) +if (PKG_CONFIG_FOUND AND NOT IOS) add_pkgconfig_interface_library (SDL2 OPTIONAL sdl2) add_pkgconfig_interface_library (SDL2_mixer OPTIONAL SDL2_mixer) -elseif (WIN32) +elseif (WIN32) # Try to locate SDL2 from the local system (assuming Windows). set (_oldPath ${SDL2_LIBRARY}) file (GLOB _hints ${SDL2_DIR}/SDL2* $ENV{DENG_DEPEND_PATH}/SDL2*) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/InstallPrefix.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/InstallPrefix.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/InstallPrefix.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/InstallPrefix.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,3 +1,10 @@ +if (IOS) + # On iOS, we'll install files into the app bundle instead of + # any user-specified location. + set (CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/apps/client/\${BUILD_TYPE}\${EFFECTIVE_PLATFORM_NAME}) + return () +endif () + set (_oldPrefix ${CMAKE_INSTALL_PREFIX}) # Install destination. PREFIX can be used to set the location manually. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/iOSBundleInfo.plist.in doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/iOSBundleInfo.plist.in --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/iOSBundleInfo.plist.in 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/iOSBundleInfo.plist.in 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,53 @@ + + + + + CFBundleExecutable + Doomsday + CFBundleDisplayName + Doomsday + CFBundleIdentifier + net.dengine.Doomsday + CFBundleVersion + ${DENG_VERSION} + LSRequiresIPhoneOS + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UILaunchStoryboardName + LaunchScreen + CFBundleIcons + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon20x20 + AppIcon29x29 + AppIcon40x40 + AppIcon60x60 + + + + CFBundleIcons~ipad + + CFBundlePrimaryIcon + + CFBundleIconFiles + + AppIcon20x20 + AppIcon29x29 + AppIcon40x40 + AppIcon60x60 + AppIcon76x76 + AppIcon83.5x83.5 + + + + + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Macros.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Macros.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Macros.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Macros.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -112,17 +112,21 @@ macro (deng_target_rpath target) if (APPLE) + set (_extraRPath) + if (NOT DENG_ENABLE_DEPLOYQT) + # Not deployed; include the local Qt library path in @rpath. + set (_extraRPath "${QT_LIBS}") + endif () set_target_properties (${target} PROPERTIES - INSTALL_RPATH "@loader_path/../Frameworks;@executable_path/../${DENG_INSTALL_LIB_DIR}" + INSTALL_RPATH "@loader_path/../Frameworks;@executable_path/../${DENG_INSTALL_LIB_DIR};${_extraRPath}" ) if (${target} MATCHES "test_.*") # These won't be deployed, so we can use the full path. - qmake_query (_qtLibPath QT_INSTALL_LIBS) set_property (TARGET ${target} APPEND PROPERTY - INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_LIB_DIR};${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_PLUGIN_DIR};${_qtLibPath}" + INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_LIB_DIR};${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_PLUGIN_DIR};${QT_LIBS}" ) - set (_qtLibPath) endif () + set (_extraRPath) elseif (UNIX) set_property (TARGET ${target} PROPERTY INSTALL_RPATH @@ -237,6 +241,7 @@ # The original source files should not be compiled any more. # They remain part of the project so they are available in the IDE. set_property (SOURCE ${_mergingSources} PROPERTY HEADER_FILE_ONLY YES) + set_property (SOURCE ${_turbo} PROPERTY SKIP_AUTOMOC YES) list (APPEND SOURCES ${_turbo};${_mergingSources}) set (_files) set (_mergingSources) @@ -335,15 +340,25 @@ message (FATAL_ERROR "deng_package: \"${outName}\" not found") endif () set (outDir ${CMAKE_CURRENT_BINARY_DIR}) + # Build the package immediately during the CMake run. execute_process (COMMAND ${PYTHON_EXECUTABLE} - "${DENG_SOURCE_DIR}/build/scripts/buildpackage.py" - ${fullPath} ${outDir} + "${DENG_SOURCE_DIR}/build/scripts/buildpackage.py" ${fullPath} ${outDir} OUTPUT_VARIABLE msg OUTPUT_STRIP_TRAILING_WHITESPACE ) clean_paths (msg ${msg}) message (STATUS "${msg}") - add_custom_target (${packName}) + # Find all the source files for the package. + file (GLOB_RECURSE packSrc "${fullPath}/*") + list_remove_matches (packSrc ".*\\.DS_Store") + # Ensure the package gets rebuilt if the source files are edited. + add_custom_command (OUTPUT ${outDir}/${outName} + COMMAND "${DENG_SOURCE_DIR}/build/scripts/buildpackage.py" ${fullPath} ${outDir} + DEPENDS ${packSrc} + COMMENT "Packaging ${packName}..." + ) + # The package target is used for dependency tracking and deployment. + add_custom_target (${packName} SOURCES ${packSrc}) set_target_properties (${packName} PROPERTIES DENG_LOCATION "${outDir}/${outName}" FOLDER Packages @@ -355,10 +370,12 @@ # the packages need to be made available separately. set (packComponent sdk) endif () - install (FILES ${outDir}/${outName} - DESTINATION ${DENG_INSTALL_DATA_DIR} - COMPONENT ${packComponent} - ) + if (NOT IOS) + install (FILES ${outDir}/${outName} + DESTINATION ${DENG_INSTALL_DATA_DIR} + COMPONENT ${packComponent} + ) + endif () if (MSVC) # In addition to installing, copy the packages to the build products # directories so that executables can be run in them. @@ -400,7 +417,11 @@ sublist (_src 1 -1 ${ARGV}) deng_filter_platform_sources (_src ${_src}) # Define the target and namespace alias. - add_library (${target} SHARED ${_src}) + if (NOT IOS) + add_library (${target} SHARED ${_src}) + else () + add_library (${target} STATIC ${_src}) + endif () set (_src) add_library (Deng::${target} ALIAS ${target}) # Libraries use the "deng_" prefix. @@ -412,7 +433,7 @@ set (_outName) # Compiler settings. deng_target_defaults (${target}) - if (APPLE) + if (APPLE AND NOT IOS) set_property (TARGET ${target} PROPERTY BUILD_WITH_INSTALL_RPATH ON) add_custom_command (TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} @@ -468,16 +489,32 @@ \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/Contents/PlugIns/*/*.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/Contents/Frameworks/*.dylib\" \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/Contents/Frameworks/*.framework\" + \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/PlugIns/*.bundle/*\" + \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/PlugIns/*.bundle\" + \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app/*.dylib\" ) foreach (fn IN LISTS fw) + set (_skip NO) + if (fn MATCHES \".*app/PlugIns.*\" AND NOT fn MATCHES \".*\\\\.bundle$\") + get_filename_component (fn2 \${fn} NAME) + if (NOT fn MATCHES \".*\${fn2}.bundle/\${fn2}$\") + set (_skip YES) + message (STATUS \"Skipping \${fn} -- not an executable\") + endif () + endif () + if (NOT _skip) message (STATUS \"Signing \${fn}...\") execute_process (COMMAND ${CODESIGN_COMMAND} --verbose - -s \"${DENG_CODESIGN_APP_CERT}\" \"\${fn}\" + -s \"${DENG_CODESIGN_APP_CERT}\" + ${DENG_FW_CODESIGN_EXTRA_FLAGS} + \"\${fn}\" ) + endif () endforeach (fn) - message (STATUS \"Signing ${_outName}.app using '${DENG_CODESIGN_APP_CERT}'...\") + message (STATUS \"Signing \${CMAKE_INSTALL_PREFIX}/${_outName}.app using '${DENG_CODESIGN_APP_CERT}'...\") execute_process (COMMAND ${CODESIGN_COMMAND} --verbose --force -s \"${DENG_CODESIGN_APP_CERT}\" + ${DENG_CODESIGN_EXTRA_FLAGS} \"\${CMAKE_INSTALL_PREFIX}/${_outName}.app\" )") endif () @@ -559,13 +596,15 @@ endfunction (add_pkgconfig_interface_library) function (fix_bundled_install_names binaryFile) + if (IOS) + return () + endif () if (NOT EXISTS ${binaryFile}) message (FATAL_ERROR "fix_bundled_install_names: ${binaryFile} not found") endif () if (binaryFile MATCHES ".*\\.bundle") set (ref "@loader_path/../Frameworks") else () - #set (ref "@executable_path/../Frameworks") set (ref "@rpath") endif () sublist (libs 1 -1 ${ARGV}) @@ -622,8 +661,12 @@ file (GENERATE OUTPUT "${scriptName}" CONTENT " set (CMAKE_MODULE_PATH ${DENG_SOURCE_DIR}/cmake) set (CMAKE_INSTALL_NAME_TOOL ${CMAKE_INSTALL_NAME_TOOL}) +set (IOS ${IOS}) +if (NOT IOS) + set (bundleSubDir Contents/MacOS) +endif () include (Macros) -fix_bundled_install_names (\"${CMAKE_CURRENT_BINARY_DIR}/\${INT_DIR}/${target}.bundle/Contents/MacOS/${target}\" +fix_bundled_install_names (\"${CMAKE_CURRENT_BINARY_DIR}/\${INT_DIR}/${target}.bundle/\${bundleSubDir}/${target}\" \"${libs}\")\n") add_custom_command (TARGET ${target} POST_BUILD COMMAND ${CMAKE_COMMAND} -DINT_DIR=${CMAKE_CFG_INTDIR} -P "${scriptName}" @@ -633,18 +676,12 @@ # macOS: Install the libraries of a dependency target into the application bundle. function (deng_install_bundle_deps target) - if (APPLE) + if (APPLE AND NOT IOS) sublist (_deps 1 -1 ${ARGV}) get_property (_outName TARGET ${target} PROPERTY OUTPUT_NAME) set (_fwDir "${_outName}.app/Contents/Frameworks") foreach (_dep ${_deps}) if (TARGET ${_dep}) - # get_property (bundleLibs TARGET ${_dep} PROPERTY MACOSX_BUNDLED_LIBRARIES) - # if (bundleLibs) - # foreach (_lib ${bundleLibs}) - # message ("bundle this: ${_lib}") - # endforeach (_lib) - # else () if (_dep MATCHES "Deng::(.*)") install (FILES $ DESTINATION ${_fwDir}) else () @@ -656,12 +693,7 @@ install (FILES ${_tlib} DESTINATION ${_fwDir}) endif () endforeach (_tlib) - # Cannot use this (CMake bug?); instead use the foreach above. - # install (FILES $ - # DESTINATION ${_fwDir} - # ) endif () - #endif () endif () endforeach (_dep) endif () @@ -670,7 +702,10 @@ # Run the Qt deploy utility on the target, resolving any local system # dependencies. function (deng_install_deployqt target) - if (UNIX AND NOT APPLE) + if (NOT DENG_ENABLE_DEPLOYQT) + return () + endif () + if (UNIX_LINUX) return () # No need to deploy Qt. endif () get_property (_outName TARGET ${target} PROPERTY OUTPUT_NAME) @@ -756,7 +791,7 @@ # Not applicable to macOS because libraries are not installed but instead # bundled with the applicatino. macro (deng_install_library library) - if (UNIX AND NOT APPLE) + if (UNIX_LINUX) string (REGEX REPLACE "(.*)\\.so" "\\1-*.so" versioned ${library}) file (GLOB _links ${library}.* ${versioned}) install (FILES ${library} ${_links} @@ -790,6 +825,8 @@ set (pfm UNIX) # man pages are always for Unix elseif (type STREQUAL RTF) set (descText "rich text document") + elseif (type STREQUAL HTML) + set (descText "HTML document") else () set (descText "text document") if (WIN32) @@ -800,8 +837,13 @@ get_filename_component (_name ${file} NAME) add_custom_command ( OUTPUT ${file} - COMMAND "${AMETHYST_COMMAND}" ${AMETHYST_FLAGS} -d${type} -d${pfm} ${opts} - -o${_name} ${ameSourceDir}/${mainSrc} + COMMAND "${AMETHYST_COMMAND}" + ${AMETHYST_FLAGS} + -d${type} + -d${pfm} + ${opts} + -o${_name} + ${ameSourceDir}/${mainSrc} DEPENDS ${_ameSrc} COMMENT "Compiling ${descText}..." ) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Options.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Options.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Options.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Options.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,5 +1,5 @@ # Source merging by default is enabled only for debug builds, or never with -# multiconfiguration projects because all configurations must use the +# multiconfiguration projects because all configurations must use the # same set of source files. if (MSVC OR XCODE_VERSION) set (DENG_ENABLE_TURBO_DEFAULT OFF) # multiconfiguration projects @@ -11,13 +11,14 @@ endif () endif () -option (DENG_ENABLE_TURBO "Enable/disable Turbo mode (source merging)" - ${DENG_ENABLE_TURBO_DEFAULT}) -option (DENG_ENABLE_GUI "Enable/disable the client and all GUI related functionality" ON) -option (DENG_ENABLE_SDK "Enable/disable installation of the Doomsday 2 SDK" ON) -option (DENG_ENABLE_TOOLS "Compile the Doomsday tools" ON) +option (DENG_ENABLE_TURBO "Enable/disable Turbo mode (source merging)" ${DENG_ENABLE_TURBO_DEFAULT}) +option (DENG_ENABLE_GUI "Enable/disable the client and all GUI related functionality" ON) +option (DENG_ENABLE_SERVER "Enable/disable the server executable" ON) +option (DENG_ENABLE_SDK "Enable/disable installation of the Doomsday 2 SDK" ON) +option (DENG_ENABLE_TOOLS "Compile the Doomsday tools" ON) +option (DENG_ENABLE_DEPLOYQT "Enable/disable the *deployqt tool" ON) -if (CCACHE_FOUND OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") +if (APPLE OR CCACHE_FOUND OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU") # GCC seems to have trouble with cotire when using C++11. set (DENG_ENABLE_COTIRE_DEFAULT OFF) # just use the cache else () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Packaging.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Packaging.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Packaging.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Packaging.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -101,14 +101,14 @@ INSTALL_TYPES gui ) cpack_add_component (fmod - DISPLAY_NAME "FMOD Ex Audio Plugin" + DISPLAY_NAME "FMOD Audio Plugin" DESCRIPTION "Audio plugin supporting 3D effects and SF2 soundfonts (non-GPL)." DEPENDS client INSTALL_TYPES gui ) cpack_add_component (sdk DISPLAY_NAME "SDK" - DESCRIPTION "C++ headers and build configuration files for Doomsday 2." + DESCRIPTION "C++ headers, libraries, and build configuration files to create Doomsday 2 plugins." DISABLED DEPENDS libs packs INSTALL_TYPES sdk diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformGenericUnix.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformGenericUnix.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformGenericUnix.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformGenericUnix.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -2,13 +2,18 @@ # Convince the compiler to enable C++11. include (CheckCXXCompilerFlag) -check_cxx_compiler_flag ("-std=c++11" COMPILER_SUPPORTS_CXX11) -check_cxx_compiler_flag ("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +if (IOS) + set (COMPILER_SUPPORTS_CXX11 YES) +else () + check_cxx_compiler_flag ("-std=c++11" COMPILER_SUPPORTS_CXX11) + check_cxx_compiler_flag ("-std=c++0x" COMPILER_SUPPORTS_CXX0X) +endif () + if (COMPILER_SUPPORTS_CXX11) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") - set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11") + append_unique (CMAKE_CXX_FLAGS "-std=c++11") + append_unique (CMAKE_C_FLAGS "-std=c11") elseif (COMPILER_SUPPORTS_CXX0X) - set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x") + append_unique (CMAKE_CXX_FLAGS "-std=c++0x") else () message (FATAL_ERROR "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.") endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformiOS.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformiOS.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformiOS.cmake 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformiOS.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,91 @@ +include (PlatformGenericUnix) + +set (DENG_PLATFORM_SUFFIX ios) +#set (DENG_AMETHYST_PLATFORM IOS) + +set (DENG_STATIC_LINK YES) + +# Install the documentation in the app bundle. +set (DENG_INSTALL_DOC_DIR "Doomsday.app/Contents/Resources/doc") +#set (DENG_INSTALL_MAN_DIR ${DENG_INSTALL_DOC_DIR}) + +# Code signing. +#set (DENG_CODESIGN_APP_CERT "" CACHE STRING "ID of the certificate for signing applications.") +#find_program (CODESIGN_COMMAND codesign) +#mark_as_advanced (CODESIGN_COMMAND) + +# Detect macOS version. +#execute_process (COMMAND sw_vers -productVersion +# OUTPUT_VARIABLE MACOS_VERSION +# OUTPUT_STRIP_TRAILING_WHITESPACE +#) + +# option (DENG_IOS_SIMULATOR "Target the iPhoneSimulator platform" ON) +# +# if (DENG_IOS_SIMULATOR) +# set (DENG_IOS_PLATFORM "iPhoneSimulator") +# else () +# set (DENG_IOS_PLATFORM "iPhoneOS") +# endif () +# +# execute_process ( +# COMMAND xcode-select -p +# OUTPUT_VARIABLE XCODE_DEVROOT +# OUTPUT_STRIP_TRAILING_WHITESPACE +# ) + +#set (DENG_IOS_SDKVER "10.3") +#set (DENG_IOS_DEVROOT "${XCODE_DEVROOT}/Platforms/${DENG_IOS_PLATFORM}.platform/Developer") +#set (CMAKE_OSX_DEPLOYMENT_TARGET "${DENG_IOS_SDKVER}") +#set (CMAKE_OSX_SYSROOT "${DENG_IOS_DEVROOT}/SDKs/${DENG_IOS_PLATFORM}${DENG_IOS_SDKVER}.sdk" +# CACHE PATH "Sysroot path" +#) +if (IOS_PLATFORM STREQUAL SIMULATOR) + set (CMAKE_OSX_ARCHITECTURES "x86_64") +else () + set (CMAKE_OSX_ARCHITECTURES "arm64") +endif () + +append_unique (CMAKE_CXX_FLAGS "-fvisibility=hidden") +append_unique (CMAKE_CXX_FLAGS "-fvisibility-inlines-hidden") +append_unique (CMAKE_CXX_FLAGS "-Wno-inconsistent-missing-override") +append_unique (CMAKE_C_FLAGS "-Wno-shorten-64-to-32") +append_unique (CMAKE_CXX_FLAGS "-Wno-shorten-64-to-32") + +add_definitions ( + -DDENG_STATIC_LINK=1 + -DDENG_APPLE=1 + -DDENG_MOBILE=1 + -DDENG_IOS=1 + -DDENG_BASE_DIR="." +) + +set (DENG_FIXED_ASM_DEFAULT OFF) + +set (XCODE_ATTRIBUTE_USE_HEADERMAP NO) + +macro (link_framework target linkType fw) + find_library (${fw}_LIBRARY ${fw}) + if (${fw}_LIBRARY STREQUAL "${fw}_LIBRARY-NOTFOUND") + message (FATAL_ERROR "link_framework: ${fw} framework not found") + endif () + mark_as_advanced (${fw}_LIBRARY) + target_link_libraries (${target} ${linkType} ${${fw}_LIBRARY}) +endmacro (link_framework) + +macro (deng_xcode_attribs target) + if (IOS_PLATFORM STREQUAL SIMULATOR) + set_target_properties (${target} PROPERTIES + XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES + ) + endif () + # set_target_properties (${target} PROPERTIES + # XCODE_ATTRIBUTE_GCC_SYMBOLS_PRIVATE_EXTERN NO + # XCODE_ATTRIBUTE_GCC_INLINES_ARE_PRIVATE_EXTERN NO + # ) +endmacro (deng_xcode_attribs) + +macro (macx_set_bundle_name name) + # Underscores are not allowed in bundle identifiers. + string (REPLACE "_" "." MACOSX_BUNDLE_BUNDLE_NAME ${name}) +endmacro (macx_set_bundle_name) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformMacx.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformMacx.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformMacx.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformMacx.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -20,6 +20,8 @@ add_definitions ( -DMACOSX=1 + -DDENG_APPLE=1 + -DDENG_PLATFORM_ID="mac10_10-${DENG_ARCH}" # Fallback basedir for command line apps. -DDENG_BASE_DIR="${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_DATA_DIR}" ) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformUnix.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformUnix.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformUnix.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformUnix.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -13,13 +13,32 @@ set (DENG_PLATFORM_SUFFIX x11) set (DENG_AMETHYST_PLATFORM UNIX) +set (DENG_BASE_DIR "" CACHE STRING "Base directory path (defaults to {prefix}/${DENG_INSTALL_DATA_DIR})") +set (DENG_LIBRARY_DIR "" CACHE STRING "Plugin directory path (defaults to {prefix}/${DENG_INSTALL_PLUGIN_DIR})") + add_definitions ( -DDENG_X11 - -D__USE_BSD + -D__USE_BSD -D_GNU_SOURCE=1 - -DDENG_BASE_DIR="${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_DATA_DIR}" - -DDENG_LIBRARY_DIR="${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_PLUGIN_DIR}" ) +if (DENG_BASE_DIR) + add_definitions (-DDENG_BASE_DIR="${DENG_BASE_DIR}") +else () + add_definitions (-DDENG_BASE_DIR="${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_DATA_DIR}") +endif () +if (NOT DENG_LIBRARY_DIR STREQUAL "") + add_definitions (-DDENG_LIBRARY_DIR="${DENG_LIBRARY_DIR}") +else () + add_definitions (-DDENG_LIBRARY_DIR="${CMAKE_INSTALL_PREFIX}/${DENG_INSTALL_PLUGIN_DIR}") +endif () + +if (CPACK_GENERATOR STREQUAL DEB) + add_definitions (-DDENG_PLATFORM_ID="ubuntu18-${DENG_ARCH}") +elseif (CPACK_GENERATOR STREQUAL RPM) + add_definitions (-DDENG_PLATFORM_ID="fedora23-${DENG_ARCH}") +else () + add_definitions (-DDENG_PLATFORM_ID="source") +endif () if (CMAKE_COMPILER_IS_GNUCXX) # The tree FRE optimization causes crashes with GCC 6 (Yakkety). diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformWindows.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformWindows.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/PlatformWindows.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/PlatformWindows.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -14,10 +14,11 @@ -D_WIN32_WINNT=0x0601 -D_CRT_SECURE_NO_WARNINGS -D_USE_MATH_DEFINES + -DDENG_PLATFORM_ID="win-${DENG_ARCH}" ) # Code signing. -set (DENG_SIGNTOOL_CERT "" CACHE FILEPATH "Name of the certificate for signing files.") +set (DENG_SIGNTOOL_CERT "" CACHE STRING "Name of the certificate for signing files.") set (DENG_SIGNTOOL_PIN "" CACHE STRING "PIN for signing key.") set (DENG_SIGNTOOL_TIMESTAMP "" CACHE STRING "URL of the signing timestamp server.") find_program (SIGNTOOL_COMMAND signtool) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Version.cmake doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Version.cmake --- doomsday-stable-2.0.3.2464+xenial/doomsday/cmake/Version.cmake 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/cmake/Version.cmake 2018-12-11 07:08:23.000000000 +0000 @@ -1,11 +1,11 @@ set (DENG_VERSION_MAJOR 2) -set (DENG_VERSION_MINOR 0) -set (DENG_VERSION_PATCH 3) +set (DENG_VERSION_MINOR 1) +set (DENG_VERSION_PATCH 0) set (DENG_VERSION ${DENG_VERSION_MAJOR}.${DENG_VERSION_MINOR}.${DENG_VERSION_PATCH}) # Binary compatibility version for shared libraries / APIs. -set (DENG_COMPAT_VERSION 2.0) +set (DENG_COMPAT_VERSION 2.1) string (REPLACE . , DENG_VERSION_WINDOWS "${DENG_VERSION}.${DENG_BUILD}") if (NOT DEFINED DENG_BUILD) @@ -18,7 +18,7 @@ Stable ) -set (DENG_TEAM_COPYRIGHT "Copyright (c) 2003-2017 Deng Team") +set (DENG_TEAM_COPYRIGHT "Copyright (c) 2003-2018 Deng Team") # Build Configuration -------------------------------------------------------- diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/CMakeLists.txt 2018-12-11 07:08:17.000000000 +0000 @@ -8,7 +8,9 @@ add_subdirectory (sdk) add_subdirectory (apps) -if (DENG_ENABLE_TOOLS) - add_subdirectory (tools) +if (NOT IOS) + if (DENG_ENABLE_TOOLS) + add_subdirectory (tools) + endif () + add_subdirectory (tests) endif () -add_subdirectory (tests) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday.6 doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday.6 --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday.6 2017-10-01 00:40:34.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday.6 2018-12-11 07:08:45.000000000 +0000 @@ -1,5 +1,5 @@ .\" manual page generated by Amethyst (mdoc+tbl) -.Dd lokakuuta 1, 2017 +.Dd joulukuuta 11, 2018 .Os .Dt "DOOMSDAY" 6 .Sh NAME @@ -26,7 +26,7 @@ .Sy -game option, the specified files will be loaded at startup. Without .Sy -game -they are just registered as available files and can then be added into game profiles in the Home screen. It is also possible to load data files at runtime by opening the Packages sidebar (see TASK BAR) or with the +they are just registered as available files that can then be loaded in games. It is also possible to load data files at runtime by opening the Packages sidebar (see TASK BAR) or with the .Sy load console command. .It Sy -game | -g @@ -50,6 +50,10 @@ .Bl -tag -width 14n -offset indent .It Sy -center Center the window (when not in fullscreen mode). +.It Sy -command | -cmd +Execute a console command during startup. Multiple commands can be joined together with semicolons. Note that console variables have game plugin specific values, so if you change cvar values using this option without loading a game (with -game), your values will be overwritten when a game plugin is loaded. +.It Sy -connect +Attempts to connect to the server running at the given network address. Equivalent to the console command connect. .It Sy -devlog | -nodevlog Enables or disables developer log entries. These are useful for debugging and/or troubleshooting, but are too verbose or technical for everyday use. .It Sy -dpi @@ -63,7 +67,7 @@ .It Sy -fullscreen | -nofullscreen Enable or disable fullscreen mode. .It Sy -icd | -imusic | -isfx -Set the audio backend for CD playback, music, and sound effects. The following audio backends are available: +Set the audio plugin for CD playback, music, and sound effects. The following plugins are available: .Bl -dash -compact -offset indent .It dummy @@ -77,29 +81,43 @@ openal .El .It Sy -fontsize -Set a scaling factor for UI fonts. For example: +Set a scaling factor for UI fonts. This is applied separately from the overall UI scale setting (see CONFIGURATION). For example: .Sy -fontsize .Sy 1.5 .It Sy -loglevel Set the log output level. The levels are: XVerbose, Verbose, Message, Note, Warning, Error, Critical. .It Sy -maximize | -nomaximize Maximize the window, or set the window to non-maximized mode. +.It Sy -noaudio +Disable all audio (sound effects and music). +.It Sy -noautoselect +Do not try to automatically select a game to load. Only has effect when +.Sy -game +is not used. Doomsday will always start in the Home screen or, when starting a server, not at all. +.It Sy -nodiscovery +Disable discovery of servers on the local network. .It Sy -nofsaa Disable antialiasing. .It Sy -nojoy Disable gamepads and other game controllers. .It Sy -nomouse Disable mouse input. +.It Sy -nomusic +Disable music. +.It Sy -nosfx +Disable sound effects. .It Sy -novsync Disable vsync. .It Sy -out Set the name of the log output file. The file is always written to the runtime folder. This option overrides the default doomsday.out. +.It Sy -parse | -p +Load and execute the specified file that contains console commands. Behavior is similar to +.Sy -command +with the exception that the commands are loaded from a file. .It Sy -packs Set additional folders where to find packages. Works similar to -iwad. .It Sy -reset Reset the engine configuration to default values. In practice, this just erases the contents of the persist.pack file that stores configuration variables and UI state. The affected variables include, for example, game window size and position, and log filter settings. -.It Sy -speaker51 | -speaker71 | -speakerprologic -Overrides the FMOD backend's speaker mode (surround 5.1, 7.1, or SRS 5.1/Prologic/Prologic2). This option can also be changed in Audio Settings (see CONFIGURATION). .It Sy -verbose | -v Print verbose log messages. Specify more than once for extra verbosity. .It Sy -vvv @@ -127,7 +145,7 @@ .It runtime/doomsday.out Log message output file. .It runtime/savegames/ -Folder containing all saved games. Each game has its own subfolder for saves. Note that the subfolders are game-specific rather than profile-specific; if you create custom game profiles, their saves will be written in the same subfolder as saves from the default game profile. +Folder containing all saved games. Each game has its own subfolder for saves. .El .Pp .Ss "Additional Files" @@ -145,7 +163,7 @@ .Ed .Ed .It /etc/doomsday/paths -System-level paths configuration (basedir, libdir, iwaddir). This is checked after ~/.doomsday/paths. The syntax of the file (http://wiki.dengine.net/w/Configuration#Unix_system-level_config_files) is documented in the wiki. +System-level paths configuration (basedir, libdir, iwaddir). This is checked after ~/.doomsday/paths. The syntax of the file (https://manual.dengine.net/guide/configuration) is documented in the wiki. .It ~/.doomsday/defaults User's own defaults (similar to the system-level defaults; see above). .It ~/.doomsday/paths @@ -200,7 +218,7 @@ .br .Tn Game Library .br -.Tn Packages +.Tn Mods .br .Tn Multiplayer .br @@ -257,7 +275,7 @@ Graphics: .Bl -dash -compact -offset indent .It -OpenGL 2.1 renderer +OpenGL 3.3 renderer .It World movement smoothing (actors, monsters, missiles, surfaces) to remove the original games' limitation of 35 FPS .It @@ -309,7 +327,7 @@ .It External music files in MP3 and other formats .It -Uses FMOD Ex (http://www.fmod.org/) for audio playback (sound effects, music, CD audio tracks) +Uses FMOD (http://www.fmod.org/) for audio playback (sound effects, music, CD audio tracks) .It Supports the open source SDL_mixer (http://www.libsdl.org/projects/SDL_mixer/) for sound effects and music files .It @@ -325,21 +343,23 @@ .It Clients can join games in progress .It +Clients automatically download PWADs loaded on server +.It Automatic discovery of servers running on the local network .It Central master server for discovery of servers on the internet .It Standalone server running as a daemon/background process .It -Standalone Doomsday Shell (http://wiki.dengine.net/w/Shell) tool for server management (both local and remote) +Standalone Doomsday Shell (https://manual.dengine.net/Shell) tool for server management (both local and remote) .El .Pp Other: .Bl -dash -compact -offset indent .It -Cross-platform (http://wiki.dengine.net/w/Supported_platforms), runs on Qt (http://qt.io/) +Cross-platform (https://manual.dengine.net/Supported_platforms), runs on Qt (http://qt.io/) .It -Open source (see Getting Started page (http://wiki.dengine.net/w/Getting_started)) +Open source (see Getting Started (https://manual.dengine.net/devel)) .It Plugin based extensible architecture .El @@ -350,7 +370,7 @@ .It At least one WAD file from the original Doom, Heretic, Hexen, or other supported game .It -GPU with OpenGL 2.1 hardware acceleration +GPU with OpenGL 3.3 hardware acceleration .El .Pp .Sh "GAMES" @@ -413,6 +433,11 @@ l l l l l l l l l + l l l + l l l + l l l + l l l + l l l l l l. Plugin Game ID Description Doom doom1-share Shareware Doom v1.9 @@ -423,6 +448,11 @@ doom2-tnt Final Doom: TNT Evilution chex Chex Quest hacx HacX + doom1-freedoom Freedoom Phase 1 + doom2-freedoom Freedoom Phase 2 + doom1-bfg Ultimate Doom (Doom 3 BFG Edition) + doom2-bfg Doom 2 (Doom 3 BFG Edition) + doom2-nerve No Rest for the Living Heretic heretic-share Shareware Heretic heretic Registered Heretic heretic-ext Heretic: Shadow of the Serpent Riders** @@ -436,9 +466,9 @@ ** = has episodes 4 and 5 .Pp .Sh "HOME SCREEN" -The Home screen in Doomsday 2 is a full replacement for the separate front-end application that was used in earlier versions. In Home you can manage your game profiles, resource packs and other add-ons, and join multiplayer games. +The Home screen in Doomsday 2 is a full replacement for the separate front-end application that was used in earlier versions. In Home you can manage your game library, resource packs and other add-ons, and join multiplayer games. .Pp -Home consists of a number of scrollable tabs. There are several ways to switch to a different tab: +Home consists of a number of scrollable tabs. There are several ways to navigate between tabs: .Pp .Bl -dash -compact -offset indent .It @@ -446,16 +476,23 @@ .It Left and right arrow keys move focus to an adjacent tab. .It -Shortcut keys: D, H, X, O, M, and P (while not entering text in a text field.) +Shortcut keys: D, H, X, O, M, and S (while not entering text in a text field.) .It Click on the left or right edge of the screen. .El .Pp .Ss "Game Library" .Pp -The game library tabs list all the available game profiles and saved games associated with them. Each game profile can be configured to use a set of additional packages (data files, resource packs). +The game library lists all the available games and their associated save files. Each game can be configured to load additional mods (WADs, PK3s, data files, resource packs). You can also add new customized games based on one of the built-in games. .Pp -The appearance of the game tabs can be changed in User Interface settings (see CONFIGURATION). You can hide the game library description texts, and choose whether unplayable game profiles are visible. You can also hide entire game tabs, if you are not interested in a particular family of games. +In User Interface settings you can hide entire game tabs, if you are not interested in a particular family of games. See CONFIGURATION for more details. +.Pp +.Sy Sorting +.Sy games +.Sy in +.Sy the +.Sy library. +If you have lots of games available, it may be helpful to change the game library view options so you can more easily find the game you are looking for. Click on the "..." button under the tab title to see the view options. .Pp .Sy Starting .Sy a @@ -464,27 +501,27 @@ .Sy or .Sy without .Sy additional -.Sy packages. -Click on a profile to select it, or move the selection with the arrow keys. When selected, Package and Play buttons slide in. The Package button shows a number for how many additional packages have been configured. Click Play or double-click the profile to start the game. +.Sy mods. +Click on a game to select it, or move the selection with the arrow keys. When selected, Mods and Play buttons slide in. The Mods button shows a number for how many additional mods have been selected for loading. Click Play or double-click the game to start the game. .Pp .Sy Selecting -.Sy packages. -Click the profile's Package button to choose which additional packages are going to be loaded when the game is started. On the left side of the dialog, you have a list of the packages attached to the profile. On the right, you can browse the available packages. The package browser works similarly to the Packages tab, and it has a search field and Info buttons (see PACKAGES). To add a package to the profile, click the Plus button or double-click the package. +.Sy mods. +Click the game's Mods button to choose which additional mods are going to be loaded when the game is started. On the left side of the dialog, you have a list of the mods selected for loading. On the right, you can browse the available mods. The mods browser works similarly to the Mods tab, and it has a search field and Info buttons (see MODS). To add a mod to the game, click the Plus button or double-click the mod. .Pp .Sy Loading .Sy a .Sy saved .Sy game. -All saved games are listed under the game profile they were created in. Click on a save to select it, and then press the profile's Play button. Clicking on an already selected save will unselect it. +All saved games are listed below the game they were created in. Click on a save to select it, and then press the game's Play button. Clicking on an already selected save will unselect it. .Pp .Bl -tag -width "NOTE: " .It Sy NOTE: -Old savegames created with Doomsday 1.x do not contain information about which data files and packages were in use when the save was created, so Doomsday can't determine which profile they belong to. Such saves are listed under each profile of the game. +Old savegames created with Doomsday 1.x do not contain information about which data files and mods were in use when the save was created, so Doomsday can't determine which game they belong to. Such saves are listed under each variant of the game. .El .Pp .Sy Savegame .Sy information. -Right-click on a saved game to see information about the save: which data files and packages were in use, the overall game parameteres, current map, and other status information. +Right-click on a saved game to see information about the save: which data files and mods were in use, the overall game parameteres, current map, and other status information. .Pp .Sy Deleting .Sy a @@ -492,36 +529,37 @@ .Sy game. When a savegame is selected, a small X button appears next to it. Clicking the X lets you delete the save. .Pp +.Sy Save +.Sy folders. +Each game is assigned a unique save folder where all the save files of the game are kept. Right-click on a profile and select "Show Save Folder" to open the folder in operating system file browser. Note that custom games created in version 2.0 or earlier share a save folder with the built-in game. You can use the "Create New Save Folder" menu item to create a new save folder for the custom game, but you will need to manually move the existing save files over there. +.Pp .Sy Creating .Sy a -.Sy new -.Sy profile. -At the bottom of each profile list, there is a Plus button that creates a new, empty profile. In the profile parameters, you can choose which game will be used, and which packages are selected for loading. Note that game profiles cannot have a name that is identical to an already existing game profile name. +.Sy custom +.Sy game. +At the bottom of each game tab, there is a Plus button that creates a new customized game. In the game settings, you can choose which game mode will be used, and which mods are selected for loading. Note that game cannot have a name that is identical to an already existing game in the library. .Pp .Sy Duplicate, .Sy edit, .Sy and .Sy delete -.Sy profiles. -Any profile can be duplicated by right-clicking on it and selecting "Duplicate". Profiles can also be edited to change their name and the set of selected packages. +.Sy games. +Any game can be duplicated by right-clicking on it and selecting "Duplicate". Games can also be edited to change their name, the primary data file (IWAD), and the set of selected mods. .Pp -.Ss "Packages" +.Ss "Mods" .Pp -The Packages tab is used to browse the available packages. With the exception of game IWAD files, the Packages tab shows all the data files that Doomsday can load. You can also quickly try out individual packages in one your existing game profiles. +The Mods tab is used to browse the available mods and other packages. The Mods tab shows all the data files that Doomsday knows about. You can also quickly try out individual mods in one your games. .Pp .Sy Configuring .Sy the -.Sy folders -.Sy where -.Sy packages -.Sy are -.Sy found. -To let Doomsday know where your packages can be found, either select "Folders" in the Packages tab's actions menu (the "..." button under the tab title), or go to Data Files settings (see CONFIGURATION). The packages will not be copied or moved from wherever you keep them. +.Sy mod +.Sy search +.Sy folders. +To let Doomsday know where your mods can be found, either select "Settings" in the Mods tab's actions menu (the "..." button under the tab title), or go to Data Files settings (see CONFIGURATION). The mods will not be copied or moved from wherever you keep them. .Pp -.Sy Searching -.Sy for -.Sy packages. -The packages list may contains hundreds of items, so you may want to find the package you're looking for by entering some search terms. Enter the words to search in the search field at the top of the list. The search is limited to package metadata; the actual file contents are not accessed. When entering multiple words, only packages whose metadata contains all the words are shown. +.Sy Browsing +.Sy mods. +The mods list may contains hundreds of items, so you may want to find the mods you're looking for by entering some search terms. Enter the words to search for in the search field at the top of the list. The search is limited to metadata; the actual file contents are not accessed. When entering multiple words, only mods whose metadata contains all the words are shown. .Pp .Sy Special .Sy search @@ -529,38 +567,42 @@ Some search words have a special meaning: .Bl -bullet -offset indent .It -"hidden": Only packages that are normally hidden will be shown. Packages that are hidden by default include, for example, packages inside other packages that will get automatically loaded. +"gamedata": Primary game data files (IWADs). +.It +"hidden": Only mods that are normally hidden will be shown. Mods that are hidden by default include, for example, mods inside other packages that will get automatically loaded. +.It +"loaded": Only show currently loaded mods. This is useful when browsing mods while playing a game. .It -"loaded": Only show currently loaded packages. This is useful when browsing packages while playing a game. +"core": Doomsday's own core packages. These will be automatically loaded as needed. .El .Pp .Sy Viewing .Sy information .Sy about .Sy a -.Sy package. -Right-click a package or click on the "..." button to view information about it. In the case of WAD files, all the maps in the WAD are listed so you'll know which map to start when playing. The info popup also shows the game title picture found in the package, and readme notes provided by the author. In some cases, Doomsday can make a guess about the game that the package is meant to be used with. +.Sy mod. +Right-click a mod or click on the "..." button to view information about it. In the case of WAD files, all the maps in the WAD are listed so you'll know which map to start when playing. The info popup also shows the game title picture found in the mod, and readme notes provided by the author. In some cases, Doomsday can make a guess about the game that the mod is meant to be used with. .Pp .Sy Quickly .Sy trying .Sy out .Sy a -.Sy package. -One of the most useful features of the Packages tab is quickly loading a package in one your games. This will make no changes to your profiles. Simply open the package info popup and click on "Play in...". However, you should first check that the package actually is compatible with the game you are playing. Also be aware that if you are already in a game, it will be unloaded first and any unsaved progress will be lost. +.Sy mod. +One of the most useful features of the Mods tab is quickly loading a mod in one your games. This will make no changes to your existing games. Simply open the mod info popup (as explained above) and click on "Play in...". However, you should first check that the mod actually is compatible with the game you are playing. Also be aware that if you are already running a game, it will be unloaded first and any unsaved progress will be lost. .Pp .Sy Quickly .Sy adding .Sy a -.Sy package +.Sy mod .Sy to .Sy a -.Sy profile. -The "Add to..." button in the package info popup will add the package to one of your existing game profiles. The profiles that already have the package are labeled "ADDED" in the list. +.Sy game. +The "Add to..." button in the mod info popup will add the mod to one of your existing games. The games that already have the mod are tagged "ADDED" in the list. .Pp .Sy Configuring .Sy optional .Sy contents. -Some packages have optional subcomponents. For instance, add-ons that use the Snowberry Box format may include both opt-in and opt-out packages. When viewing information about this kind of collections, an additional "Options" button is shown in the package info popup. This will let you enable or disable individual contained sub-packages. +Some mods have optional subcomponents. For instance, add-ons that use the Snowberry Box format may include both opt-in and opt-out mods. When viewing information about this kind of collections, an additional "Options" button is shown in the mod info popup. This will let you enable or disable individual contained mods. .Pp .Ss "Multiplayer" .Pp @@ -569,7 +611,7 @@ .Sy Viewing .Sy server .Sy information. -Right-click a server in the list to view status information about it. The same popup can be opened by clicking the small "..." button in the server description. The status information includes: +Right-click a server in the list to view information about it. The same popup can be opened by clicking the small "..." button in the server description. The status information includes: .Bl -dash -compact -offset indent .It ping time @@ -578,7 +620,7 @@ .It outline of the current map .It -list of packages loaded on the server +list of mods loaded on the server .It list of connected players .It @@ -588,7 +630,7 @@ .Sy Joining .Sy a .Sy game. -Join an open multiplayer game by clicking "Join" either in the server list or in the server information popup. +Join an open multiplayer game by clicking "Join" either in the server list or in the server information popup. Any missing mods are downloaded automatically after you click the button. .Pp .Sy Player .Sy name @@ -606,9 +648,7 @@ .Sy Failure .Sy to .Sy connect? -There are several reasons why you may not be able to join a multiplayer game. You will be notified if you don't have the same packages that the server is using. You can review the required packages in the server information popup. Connectivity problems can also be due to your firewall or network address translation (NAT) (https://en.wikipedia.org/wiki/Network_address_translation). -.Pp -Doomsday uses TCP network connections for multiplayer games. If you host a game and are behind a firewall or using NAT, you must make sure that other computers are able to open TCP connections to your computer. This entails opening the appropriate incoming TCP ports on your firewall and/or configuring the NAT so that the correct ports are routed to your computer. +Connectivity problems can also be due to your firewall or network address translation (NAT) (https://en.wikipedia.org/wiki/Network_address_translation). Doomsday uses TCP network connections for multiplayer games. If you host a game and are behind a firewall or using NAT, you must make sure that other computers are able to open TCP connections to your computer. This entails opening the appropriate incoming TCP ports on your firewall and/or configuring the NAT so that the correct ports are routed to your computer. .Pp Additionally, UDP ports 13209-13224 are used for detecting servers running on the local network; if you are experiencing problems with autodetecting local servers, check that your firewall isn't blocking these UDP ports on either end. .Pp @@ -636,7 +676,7 @@ .Pp If your server is not public (i.e.\&, announced to the master server), a client can connect to it manually using the IP address or domain name. .Pp -For more information about the Shell, see Shell Help in the wiki (http://wiki.dengine.net/w/Shell_Help). +For more information about the Shell, see Shell Help in the wiki (https://manual.dengine.net/Shell_Help). .Pp .Sh "TASK BAR" The task bar is a central element of Doomsday's UI. It is available at all times and provides access to key features of the engine. For example, you can modify configuration settings, show the Home screen, and unload the current game. @@ -653,12 +693,12 @@ .Sy Browsing .Sy and .Sy loading -.Sy packages. -"Browse Packages..." opens the package list in a sidebar where packages can be loaded and unloaded manually. You can also view information about packages like in the Home screen. The sidebar is only available when a game is loaded. You can use the "loaded" keyword to filter the list so that only the currently loaded packages are listed. +.Sy mods. +"Browse Mods..." opens the mod browser in a sidebar where mods can be loaded and unloaded manually. You can also view information about mods like in the Home screen. The sidebar is only available when a game is loaded. You can use the "loaded" keyword to filter the list so that only the currently loaded mods are listed. .Pp .Bl -tag -width "NOTE: " .It Sy NOTE: -Data from newly loaded packages may not be used until a new map is started in the game. Use of external textures can be enabled and disabled in Renderer settings. +Data from newly loaded mods may not be used until a new map is started in the game. Use of external textures can be enabled and disabled in Renderer settings. .El .Pp .Sy Checking @@ -712,8 +752,8 @@ .El .Pp .Sy Audio -.Sy backends. -Some of the audio options are dependent on the active audio backend(s). For example, a MIDI sound font is supported by the FMOD and Fluidsynth plugins. 3D sound and reverb are supported by FMOD, OpenAL, and DirectSound. The audio backend can be reconfigured on the fly; any changes are applied when you close the popup. +.Sy backend. +Audio output capabilities vary based on operating system and audio hardware. Doomsday's audio backend can be configured according to your needs primarily via the selection of audio interface plugins. The recommendation on all platforms is FMOD for sound effects and FluidSynth for music, because these two enable software-based rendering of both 3D sound effects and MIDI music. Some of the audio options are dependent on the active audio plugins. For example, a MIDI sound font is supported by the FMOD and FluidSynth plugins. 3D sound and reverb are supported by FMOD, OpenAL, and DirectSound. The audio backend can be reconfigured on the fly; any changes are applied when you press the "Apply" button. .Pp .Sy Game .Sy controllers. @@ -731,8 +771,8 @@ .Pp .Sy Local .Sy multiplayer -.Sy packages. -By default, clients are not allowed to load packages in addition to what the server is using. This avoids any potential compatibility issues with the client's packages overriding some of the game's definitions. However, you can manually enable local packages in Network settings. You can then select additional local packages for multiplayer games in the server information popup before joining the game. +.Sy mods. +By default, clients are not allowed to load mods in addition to what the server is using. This avoids any potential compatibility issues with the client's mods overriding some of the game's definitions. However, you can manually enable local mods in Network settings. You can then select additional local mods for multiplayer games in the server information popup before joining the game. .Pp .Sy User .Sy Interface @@ -776,11 +816,11 @@ .Sy basics. Type .Sy help -to get started. This prints some basic information about how to use the console, and commands for listing all the available console commands and variables (http://wiki.dengine.net/w/consolevariable). At any time, press Tab to autocomplete the word being typed. This will pop up a list of all possible completions, including the current values for any variables. You can change console variable values as follows: +to get started. This prints some basic information about how to use the console, and commands for listing all the available console commands and variables (https://manual.dengine.net/consolevariable). At any time, press Tab to autocomplete the word being typed. This will pop up a list of all possible completions, including the current values for any variables. You can change console variable values as follows: .Pp .Bd -ragged -offset indent -.Sy sound-info -.Sy 1 +.Sy rend-camera-fov +.Sy 110 .Ed .Pp .Sy Shortcut @@ -804,23 +844,21 @@ .El .Pp .Sh "SEE ALSO" -Additional documentation is available in the Doomsday Engine Wiki (http://wiki.dengine.net/). +Additional documentation is available in the Doomsday Manual (https://manual.dengine.net/). .Pp .Bl -bullet -offset indent .It -Version history (http://wiki.dengine.net/w/Category:Releases) -.It -User's Guide: wiki articles to help play games with Doomsday (http://wiki.dengine.net/w/Category:User%27s_Guide) +Getting started with Doomsday (https://manual.dengine.net/guide) .It -Author's Guide: wiki articles for map and resource pack/addon authors (http://wiki.dengine.net/w/Category:Author%27s_Guide) +Version history (https://manual.dengine.net/version) .It -Doomsday 2 packages and assets (http://wiki.dengine.net/w/Packages) +Doomsday 1 resources (https://manual.dengine.net/modding/overview_of_resources_doomsday_1.x) .It -Definitions Reference: DED and finale script syntax (http://wiki.dengine.net/w/DED) +Doomsday 2 packages and assets (https://manual.dengine.net/assets) .It -Project roadmap and features in planning (http://tracker.dengine.net/projects/deng/roadmap) +Definitions Reference: DED and finale script syntax (https://manual.dengine.net/ded) .It -Programmer's Guide: technical wiki articles for developers (http://wiki.dengine.net/w/Category:Programmer%27s_Guide) +Project roadmap and features in planning (https://tracker.dengine.net/projects/deng/roadmap) .El .Pp .Sh "AUTHOR" @@ -859,10 +897,6 @@ .Sy Jarvis did early network testing with jDoom and jHeretic and generously contributed essential computer hardware components. .Pp -.Sy Jaakko -.Sy Ker\[:a]nen -created the Doomsday Engine and is the lead developer of the project. -.Pp .Sy Kees .Sy Meijs packaged Doomsday for Debian and hosted an Apt repository of Debian packages. @@ -872,4 +906,8 @@ is a developer in the Deng Team, original author of the dengine.net (http://dengine.net) website backend, and former maintainer of the jDoom Resource Pack. .Pp .Sy Vermil -regularly provides in-depth feedback and bug reports and is an expert in all things related to DOOM-based games. +regularly provides in-depth feedback and bug reports and is an expert in all things related to DOOM-based games. +.Pp +.Sy Jaakko +.Sy Ker\[:a]nen +created the Doomsday Engine and is the lead developer of the project. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday-server.6 doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday-server.6 --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday-server.6 2017-10-01 00:40:34.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday-server.6 2018-12-11 07:08:45.000000000 +0000 @@ -1,5 +1,5 @@ .\" manual page generated by Amethyst (mdoc+tbl) -.Dd lokakuuta 1, 2017 +.Dd joulukuuta 11, 2018 .Os .Dt "DOOMSDAY-SERVER" 6 .Sh NAME diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday-shell-text.6 doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday-shell-text.6 --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/doomsday-shell-text.6 2017-10-01 00:40:34.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/doomsday-shell-text.6 2018-12-11 07:08:45.000000000 +0000 @@ -1,5 +1,5 @@ .\" manual page generated by Amethyst (mdoc+tbl) -.Dd lokakuuta 1, 2017 +.Dd joulukuuta 11, 2018 .Os .Dt "DOOMSDAY-SHELL-TEXT" 6 .Sh NAME @@ -29,7 +29,7 @@ .It Disconnect Disconnect the current connection. The server will not be stopped. .It Start local server -Starts a new Doomsday server on the local machine. A dialog will open for configuring the game mode, server's TCP port, and other launch options. You must ensure that Doomsday will be able to locate the required IWAD files (http://wiki.dengine.net/w/IWAD). After the server launches, a connection to it is opened automatically. +Starts a new Doomsday server on the local machine. A dialog will open for configuring the game mode, server's TCP port, and other launch options. You must ensure that Doomsday will be able to locate the required IWAD files (https://manual.dengine.net/IWAD). After the server launches, a connection to it is opened automatically. .It Scroll to bottom Scrolls the log entry history down to the bottom of the buffer, to the latest received log entry. .It About diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/credit.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/credit.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/credit.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/credit.ame 2018-12-11 07:08:23.000000000 +0000 @@ -20,9 +20,6 @@ @strong{David Jarvis} did early network testing with jDoom and jHeretic and generously contributed essential computer hardware components. -@strong{Jaakko Keränen} created the Doomsday Engine and is the lead developer -of the project. - @strong{Kees Meijs} packaged Doomsday for Debian and hosted an Apt repository of Debian packages. @@ -32,3 +29,6 @@ @strong{Vermil} regularly provides in-depth feedback and bug reports and is an expert in all things related to DOOM-based games. + +@strong{Jaakko Keränen} created the Doomsday Engine and is the lead developer +of the project. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/features.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/features.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/features.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/features.ame 2018-12-11 07:08:23.000000000 +0000 @@ -13,7 +13,7 @@ Graphics: @list/thin{ - @item OpenGL 2.1 renderer + @item OpenGL 3.3 renderer @item World @wikiterm{movement smoothing} (actors, monsters, missiles, surfaces) to remove the original games' limitation of 35 FPS @item Stereoscopic rendering modes: anaglyph, side-by-side, cross-eye and parallel viewing @item @wikiterm{Bloom}, @wikiterm{vignette}, and @wikiterm{fog} effects @@ -43,7 +43,7 @@ @item 3D positional sound effects @item Environmental @wikiterm{echo and reverb} effects @item External @wikiterm{music files} in MP3 and other formats - @item Uses @link{FMOD Ex}{http://www.fmod.org/} for audio playback (sound effects, music, CD audio tracks) + @item Uses @link{FMOD}{http://www.fmod.org/} for audio playback (sound effects, music, CD audio tracks) @item Supports the open source @link{SDL_mixer}{http://www.libsdl.org/projects/SDL_mixer/} for sound effects and music files @ifndef{WIN32}{@item FluidSynth for MIDI playback using @wikiterm{SF2} soundfonts} @ifdef{WIN32}{@item DirectSound3D, EAX 2.0 (32-bit only), Windows Multimedia (for MIDI)} @@ -54,6 +54,7 @@ @list/thin{ @item Supports up to @wikiterm{15 player games} @item Clients can join games in progress + @item Clients automatically download PWADs loaded on server @item Automatic discovery of servers running on the local network @item Central @wikiterm{master server} for discovery of servers on the internet @item Standalone @wikiterm{server} running as a daemon/background process @@ -63,7 +64,7 @@ Other: @list/thin{ @item @wikilink{Cross-platform}{Supported_platforms}, runs on @link{Qt}{http://qt.io/} - @item Open source (see @wikilink{Getting Started page}{Getting_started}) + @item Open source (see @wikilink{Getting Started}{devel}) @item @wikiterm{Plugin} based @wikiterm{extensible architecture} } @@ -72,11 +73,11 @@ @list{ @item At least one WAD file from the original Doom, Heretic, Hexen, or other supported game @ifndef{UNIX}{ - @item Minimum OS version: - @ifdef{WIN32}{Windows Vista} - @ifdef{MACOSX}{macOS 10.8} + @item Minimum OS version: + @ifdef{WIN32}{Windows 7} + @ifdef{MACOSX}{macOS 10.10} } @ifdef{WIN32}{@item DirectX 8 (or newer)} @ifdef{MACOSX}{@item Supported CPU architectures: 64-bit/32-bit Intel} - @item GPU with OpenGL 2.1 hardware acceleration + @item GPU with OpenGL 3.3 hardware acceleration } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/games.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/games.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/games.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/games.ame 2018-12-11 07:08:23.000000000 +0000 @@ -72,6 +72,11 @@ @tab doom2-tnt @tab Final Doom: TNT Evilution @row @tab chex @tab Chex Quest @row @tab hacx @tab HacX @row + @tab doom1-freedoom @tab Freedoom Phase 1 @row + @tab doom2-freedoom @tab Freedoom Phase 2 @row + @tab doom1-bfg @tab Ultimate Doom (Doom 3 BFG Edition) @row + @tab doom2-bfg @tab Doom 2 (Doom 3 BFG Edition)@row + @tab doom2-nerve @tab No Rest for the Living @row @plugin{Heretic} @tab heretic-share @tab Shareware Heretic @row diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/readme.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/readme.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/readme.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/readme.ame 2018-12-11 07:08:23.000000000 +0000 @@ -6,8 +6,8 @@ @macro{TITLE}{ doomsday } } @macro{ONELINER}{ Enhanced source port of Doom, Heretic and Hexen } -@macro{VERSION}{ Version 2.0 } -@macro{AUTHOR}{ Deng Team } +@macro{VERSION}{ Version 2.1 } +@macro{AUTHOR}{ Jaakko Keränen (skyjake), Daniel Swanson (DaniJ) & Contributors } @macro{LINK}{ http://dengine.net/ } @require{amestd} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/seealso.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/seealso.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/seealso.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/seealso.ame 2018-12-11 07:08:23.000000000 +0000 @@ -1,14 +1,12 @@ @chapter{ See also } -Additional documentation is available in the @link{Doomsday Engine -Wiki}{http://wiki.dengine.net/}. +Additional documentation is available in the @link{Doomsday Manual}{https://manual.dengine.net/}. @list{ - @item @link{Version history}{http://wiki.dengine.net/w/Category:Releases} - @item @link{User's Guide: wiki articles to help play games with Doomsday}{http://wiki.dengine.net/w/Category:User%27s_Guide} - @item @link{Author's Guide: wiki articles for map and resource pack/addon authors}{http://wiki.dengine.net/w/Category:Author%27s_Guide} - @item @link{Doomsday 2 packages and assets}{http://wiki.dengine.net/w/Packages} - @item @link{Definitions Reference: DED and finale script syntax}{http://wiki.dengine.net/w/DED} - @item @link{Project roadmap and features in planning}{http://tracker.dengine.net/projects/deng/roadmap} - @item @link{Programmer's Guide: technical wiki articles for developers}{http://wiki.dengine.net/w/Category:Programmer%27s_Guide} + @item @wikilink{Getting started with Doomsday}{guide} + @item @wikilink{Version history}{version} + @item @wikilink{Doomsday 1 resources}{modding/overview_of_resources_doomsday_1.x} + @item @wikilink{Doomsday 2 packages and assets}{assets} + @item @wikilink{Definitions Reference: DED and finale script syntax}{ded} + @item @link{Project roadmap and features in planning}{https://tracker.dengine.net/projects/deng/roadmap} } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/commandline.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/commandline.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/commandline.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/commandline.ame 2018-12-11 07:08:23.000000000 +0000 @@ -1,10 +1,10 @@ @ifndef{MANPAGE}{ @chapter{ Command line usage } - + It is possible to launch Doomsday directly from the command line. If all data files can be found under the default directories, the engine should be able to launch itself without further assistance. If not, command line - options must be used to configure data file locations and other settings. + options must be used to configure data file locations and other settings. } @else{ @chapter{ Synopsis } @@ -26,14 +26,14 @@ } @deflist{ - + @item{@opt{-file} | @opt{-f}} Specify one or more data files or packages (@file{.pack}, PK3, WAD, LMP) to load at startup. When used together with the @opt{-game} option, the specified files will be loaded at startup. - Without @opt{-game} they are just registered as available files and can - then be added into game profiles in the Home screen. It is also possible to - load data files at runtime by opening the Packages sidebar (see - @ref{taskbar}{Task Bar}) or with the @cmd{load} console command. + Without @opt{-game} they are just registered as available files that can + then be loaded in games. It is also possible to load data files at runtime + by opening the Packages sidebar (see @ref{taskbar}{Task Bar}) or with the + @cmd{load} console command. @item{@opt{-game} | @opt{-g}} Sets the game to load after startup. If omitted, the Home screen will be shown after startup. See @@ -63,6 +63,15 @@ @item{@opt{-center}} Center the window (when not in fullscreen mode). + @item{@opt{-command} | @opt{-cmd}} Execute a console command during + startup. Multiple commands can be joined together with semicolons. Note + that console variables have game plugin specific values, so if you change + cvar values using this option without loading a game (with @opt{-game}), + your values will be overwritten when a game plugin is loaded. + + @item{@opt{-connect}} Attempts to connect to the server running at the + given network address. Equivalent to the console command @cmd{connect}. + @item{@opt{-devlog} | @opt{-nodevlog}} Enables or disables developer log entries. These are useful for debugging and/or troubleshooting, but are too verbose or technical for everyday use. @@ -71,7 +80,7 @@ @ifdef{WIN32}{The desktop UI scaling factor is automatically detected and used by Doomsday. This option will override it.} For example: @opt{-dpi 2.0}} - + @item{@opt{-errors}} Set the name of the error output file. The file is written to the runtime folder. This output file is created in addition to the usual @file{doomsday.out}. For example: @opt{-errors errors.out} @@ -79,65 +88,77 @@ @item{@opt{-fullscreen} | @opt{-nofullscreen}} Enable or disable fullscreen mode. - @item{@opt{-icd} | @opt{-imusic} | @opt{-isfx}} Set the audio backend for - CD playback, music, and sound effects. The following audio backends are - available: + @item{@opt{-icd} | @opt{-imusic} | @opt{-isfx}} Set the audio plugin for + CD playback, music, and sound effects. The following plugins are + available: @list/thin{ - @item dummy + @item dummy @item fmod @ifndef{WIN32}{@item fluidsynth} @item sdlmixer @item openal @ifdef{WIN32}{@item dsound @item winmm} } - - @item{@opt{-fontsize}} Set a scaling factor for UI fonts. For example: - @opt{-fontsize 1.5} - + + @item{@opt{-fontsize}} Set a scaling factor for UI fonts. This is applied + separately from the overall UI scale setting (see + @ref{config}{Configuration}). For example: @opt{-fontsize 1.5} + @item{@opt{-loglevel}} Set the log output level. The levels are: XVerbose, Verbose, Message, Note, Warning, Error, Critical. - + @item{@opt{-maximize} | @opt{-nomaximize}} Maximize the window, or set the window to non-maximized mode. - + + @item{@opt{-noaudio}} Disable all audio (sound effects and music). + + @item{@opt{-noautoselect}} Do not try to automatically select a game to + load. Only has effect when @opt{-game} is not used. Doomsday will always + start in the Home screen or, when starting a server, not at all. + + @item{@opt{-nodiscovery}} Disable discovery of servers on the local network. + @item{@opt{-nofsaa}} Disable antialiasing. - + @item{@opt{-nojoy}} Disable gamepads and other game controllers. - + @item{@opt{-nomouse}} Disable mouse input. - + + @item{@opt{-nomusic}} Disable music. + + @item{@opt{-nosfx}} Disable sound effects. + @item{@opt{-novsync}} Disable vsync. - + @item{@opt{-out}} Set the name of the log output file. The file is always written to the runtime folder. This option overrides the default @file{doomsday.out}. - + + @item{@opt{-parse} | @opt{-p}} Load and execute the specified file that + contains console commands. Behavior is similar to @opt{-command} with the + exception that the commands are loaded from a file. + @item{@opt{-packs}} Set additional folders where to find packages. Works similar to @opt{-iwad}. - + @item{@opt{-reset}} Reset the engine configuration to default values. In practice, this just erases the contents of the @file{persist.pack} file that stores configuration variables and UI state. The affected variables include, for example, game window size and position, and log filter settings. - - @item{@opt{-speaker51} | @opt{-speaker71} | @opt{-speakerprologic}} - Overrides the FMOD backend's speaker mode (surround 5.1, 7.1, or SRS - 5.1/Prologic/Prologic2). This option can also be changed in Audio Settings - (see @ref{config}{Configuration}). - + @item{@opt{-verbose} | @opt{-v}} Print verbose log messages. Specify more than once for extra verbosity. @item{@opt{-vvv}} Enables all log messages (normal and developer, all levels). - + @item{@opt{-warp}} When starting directly into a game using @opt{-game}, automatically also jump to a specific map. The map can be specified either as the map number, a pair of numbers (episode and map), or the map identifier (e.g., "MAP12"). - + @ifndef{MACOSX}{@item{@opt{-width} | @opt{-height}} Set the horizontal/vertical display resolution when in fullscreen mode.} - + } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_common.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_common.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_common.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_common.ame 2018-12-11 07:08:23.000000000 +0000 @@ -13,8 +13,5 @@ @item{@file{runtime/doomsday.out}} Log message output file. @item{@file{runtime/savegames/}} Folder containing all saved games. Each - game has its own subfolder for saves. Note that the subfolders are - game-specific rather than profile-specific; if you create custom game - profiles, their saves will be written in the same subfolder as saves from - the default game profile. + game has its own subfolder for saves. } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_macos.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_macos.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_macos.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_macos.ame 2018-12-11 07:08:23.000000000 +0000 @@ -3,13 +3,11 @@ @include{technical/files_common} -@ifdef{MACOSX}{ +@ifdef{MACOSX}{ @a{paths_file} Additional files: - @deflist{ - @item{@file{~/.doomsday/paths}} Customized file path - configuration (@var{basedir}, @var{libdir}, @var{iwaddir}). The - @wikilink{syntax of the - file}{Configuration#Unix_system-level_config_files} is documented in - the wiki. + @deflist{ + @item{@file{~/.doomsday/paths}} Customized file path configuration + (@var{basedir}, @var{libdir}, @var{iwaddir}). The @wikilink{syntax of + the file}{guide/configuration} is documented in the wiki. } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_unix.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_unix.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/technical/files_unix.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/technical/files_unix.ame 2018-12-11 07:08:23.000000000 +0000 @@ -6,7 +6,7 @@ @section{ Additional files } @deflist{ - + @item{@file{/etc/doomsday/defaults}} System-level default configuration. This is checked after @file{~/.doomsday/defaults}. For example: @@ -18,8 +18,7 @@ @item{@file{/etc/doomsday/paths}} @a{paths_file} System-level paths configuration (@var{basedir}, @var{libdir}, @var{iwaddir}). This is checked after @file{~/.doomsday/paths}. The @wikilink{syntax of the - file}{Configuration#Unix_system-level_config_files - } is documented in the wiki. + file}{guide/configuration} is documented in the wiki. @item{@file{~/.doomsday/defaults}} User's own defaults (similar to the system-level @file{defaults}; see above). @@ -29,5 +28,5 @@ @item{@file{/usr/share/doomsday/}} Data files for the engine and game plugins. - + } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/ui/home.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/ui/home.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/ui/home.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/ui/home.ame 2018-12-11 07:08:23.000000000 +0000 @@ -2,123 +2,140 @@ The Home screen in Doomsday 2 is a full replacement for the separate front-end application that was used in earlier versions. In Home you can manage your game -profiles, resource packs and other add-ons, and join multiplayer games. +library, resource packs and other add-ons, and join multiplayer games. -Home consists of a number of scrollable tabs. There are several ways to switch -to a different tab: +Home consists of a number of scrollable tabs. There are several ways to navigate +between tabs: @list/thin{ @item Click on the tab names in the top of the screen. @item Left and right arrow keys move focus to an adjacent tab. - @item Shortcut keys: @kbd{D}, @kbd{H}, @kbd{X}, @kbd{O}, @kbd{M}, and @kbd{P} (while not entering text in a text field.) + @item Shortcut keys: @kbd{D}, @kbd{H}, @kbd{X}, @kbd{O}, @kbd{M}, and + @kbd{S} (while not entering text in a text field.) @item Click on the left or right edge of the screen. } @section{ Game library } -The game library tabs list all the available game profiles and saved games -associated with them. Each game profile can be configured to use a set of -additional packages (data files, resource packs). - -The appearance of the game tabs can be changed in User Interface settings (see -@ref{config}{Configuration}). You can hide the game library description texts, -and choose whether unplayable game profiles are visible. You can also hide -entire game tabs, if you are not interested in a particular family of games. - -@parag{Starting a game with or without additional packages.} Click on a profile -to select it, or move the selection with the arrow keys. When selected, Package -and Play buttons slide in. The Package button shows a number for how many -additional packages have been configured. Click Play or double-click the -profile to start the game. - -@parag{Selecting packages.} Click the profile's Package button to choose which -additional packages are going to be loaded when the game is started. On the -left side of the dialog, you have a list of the packages attached to the -profile. On the right, you can browse the available packages. The package -browser works similarly to the Packages tab, and it has a search field and Info -buttons (see @ref{packages}{Packages}). To add a package to the profile, click -the Plus button or double-click the package. - -@parag{Loading a saved game.} All saved games are listed under the game profile -they were created in. Click on a save to select it, and then press the -profile's Play button. Clicking on an already selected save will unselect it. - -@notice{Old savegames created with Doomsday 1.x do not contain information -about which data files and packages were in use when the save was created, so -Doomsday can't determine which profile they belong to. Such saves are listed -under each profile of the game.} +The game library lists all the available games and their associated save files. +Each game can be configured to load additional mods (WADs, PK3s, data files, +resource packs). You can also add new customized games based on one of the +built-in games. + +In User Interface settings you can hide entire game tabs, if you are not +interested in a particular family of games. See @ref{config}{Configuration} for +more details. + +@parag{Sorting games in the library.} If you have lots of games available, it +may be helpful to change the game library view options so you can more easily +find the game you are looking for. Click on the @ui{...} button under the tab +title to see the view options. + +@parag{Starting a game with or without additional mods.} Click on a game to +select it, or move the selection with the arrow keys. When selected, Mods and +Play buttons slide in. The Mods button shows a number for how many additional +mods have been selected for loading. Click Play or double-click the game to +start the game. + +@parag{Selecting mods.} Click the game's Mods button to choose which additional +mods are going to be loaded when the game is started. On the left side of the +dialog, you have a list of the mods selected for loading. On the right, you can +browse the available mods. The mods browser works similarly to the Mods tab, and +it has a search field and Info buttons (see @ref{packages}{Mods}). To add a mod +to the game, click the Plus button or double-click the mod. + +@parag{Loading a saved game.} All saved games are listed below the game they +were created in. Click on a save to select it, and then press the game's Play +button. Clicking on an already selected save will unselect it. + +@notice{Old savegames created with Doomsday 1.x do not contain information about +which data files and mods were in use when the save was created, so Doomsday +can't determine which game they belong to. Such saves are listed under each +variant of the game.} @parag{Savegame information.} Right-click on a saved game to see information -about the save: which data files and packages were in use, the overall game +about the save: which data files and mods were in use, the overall game parameteres, current map, and other status information. - + @parag{Deleting a saved game.} When a savegame is selected, a small X button appears next to it. Clicking the X lets you delete the save. -@parag{Creating a new profile.} At the bottom of each profile list, there is a -Plus button that creates a new, empty profile. In the profile parameters, you -can choose which game will be used, and which packages are selected for -loading. Note that game profiles cannot have a name that is identical to an -already existing game profile name. - -@parag{Duplicate, edit, and delete profiles.} Any profile can be duplicated by -right-clicking on it and selecting @ui{Duplicate}. Profiles can also be edited -to change their name and the set of selected packages. - -@a{packages}@section{ Packages } - -The Packages tab is used to browse the available @wikiterm{packages}. With the -exception of game IWAD files, the Packages tab shows all the data files that -Doomsday can load. You can also quickly try out individual packages in one your -existing game profiles. - -@parag{Configuring the folders where packages are found.} To let Doomsday know -where your packages can be found, either select @ui{Folders} in the Packages -tab's actions menu (the @ui{...} button under the tab title), or go to Data -Files settings (see @ref{config}{Configuration}). The packages will not be -copied or moved from wherever you keep them. - -@parag{Searching for packages.} The packages list may contains hundreds of -items, so you may want to find the package you're looking for by entering some -search terms. Enter the words to search in the search field at the top of the -list. The search is limited to package metadata; the actual file contents are -not accessed. When entering multiple words, only packages whose metadata -contains all the words are shown. +@parag{Save folders.} Each game is assigned a unique save folder +where all the save files of the game are kept. Right-click on a profile and +select @ui{Show Save Folder} to open the folder in @ifdef{WIN32}{Windows +Explorer}@else{@ifdef{MACOSX}{Finder}@else{operating system file browser}}. +Note that custom games created in version 2.0 or earlier share a save +folder with the built-in game. You can use the @ui{Create New Save Folder} menu +item to create a new save folder for the custom game, but you will need to +manually move the existing save files over there. + +@parag{Creating a custom game.} At the bottom of each game tab, there is a Plus +button that creates a new customized game. In the game settings, you can choose +which game mode will be used, and which mods are selected for loading. Note that +game cannot have a name that is identical to an already existing game in the +library. + +@parag{Duplicate, edit, and delete games.} Any game can be duplicated by +right-clicking on it and selecting @ui{Duplicate}. Games can also be edited to +change their name, the primary data file (IWAD), and the set of selected mods. + +@a{packages}@section{ Mods } + +The Mods tab is used to browse the available @wikiterm{mods} and other +@wikiterm{packages}. The Mods tab shows all the data files that Doomsday knows +about. You can also quickly try out individual mods in one your games. + +@parag{Configuring the mod search folders.} To let Doomsday know where your mods +can be found, either select @ui{Settings} in the Mods tab's actions menu (the +@ui{...} button under the tab title), or go to Data Files settings (see +@ref{config}{Configuration}). The mods will not be copied or moved from wherever +you keep them. + +@parag{Browsing mods.} The mods list may contains hundreds of items, so you may +want to find the mods you're looking for by entering some search terms. Enter +the words to search for in the search field at the top of the list. The search +is limited to metadata; the actual file contents are not accessed. When entering +multiple words, only mods whose metadata contains all the words are shown. @parag{Special search keywords.} Some search words have a special meaning: @list{ - @item @dquote{hidden}: Only packages that are normally hidden will be - shown. Packages that are hidden by default include, for example, packages - inside other packages that will get automatically loaded. + @item @dquote{gamedata}: Primary game data files (IWADs). + + @item @dquote{hidden}: Only mods that are normally hidden will be shown. + Mods that are hidden by default include, for example, mods inside other + packages that will get automatically loaded. - @item @dquote{loaded}: Only show currently loaded packages. This is useful - when browsing packages while playing a game. + @item @dquote{loaded}: Only show currently loaded mods. This is useful when + browsing mods while playing a game. + + @item @dquote{core}: Doomsday's own core packages. These will be + automatically loaded as needed. } -@parag{Viewing information about a package.} Right-click a package or click on +@parag{Viewing information about a mod.} Right-click a mod or click on the @ui{...} button to view information about it. In the case of WAD files, all the maps in the WAD are listed so you'll know which map to start when playing. -The info popup also shows the game title picture found in the package, and +The info popup also shows the game title picture found in the mod, and readme notes provided by the author. In some cases, Doomsday can make a guess -about the game that the package is meant to be used with. +about the game that the mod is meant to be used with. -@parag{Quickly trying out a package.} One of the most useful features of the -Packages tab is quickly loading a package in one your games. This will make no -changes to your profiles. Simply open the package info popup and click on -@ui{Play in...}. However, you should first check that the package actually is -compatible with the game you are playing. Also be aware that if you are already -in a game, it will be unloaded first and any unsaved progress will be lost. - -@parag{Quickly adding a package to a profile.} The @ui{Add to...} button in the -package info popup will add the package to one of your existing game profiles. -The profiles that already have the package are labeled @ui{ADDED} in the list. - -@parag{Configuring optional contents.} Some packages have optional -subcomponents. For instance, add-ons that use the @wikiterm{Snowberry Box} -format may include both opt-in and opt-out packages. When viewing information -about this kind of collections, an additional @ui{Options} button is shown in -the package info popup. This will let you enable or disable individual -contained sub-packages. +@parag{Quickly trying out a mod.} One of the most useful features of the Mods +tab is quickly loading a mod in one your games. This will make no changes to +your existing games. Simply open the mod info popup (as explained above) and +click on @ui{Play in...}. However, you should first check that the mod actually +is compatible with the game you are playing. Also be aware that if you are +already running a game, it will be unloaded first and any unsaved progress will +be lost. + +@parag{Quickly adding a mod to a game.} The @ui{Add to...} button in the mod +info popup will add the mod to one of your existing games. The games that +already have the mod are tagged @ui{ADDED} in the list. + +@parag{Configuring optional contents.} Some mods have optional subcomponents. +For instance, add-ons that use the @wikiterm{Snowberry Box} format may include +both opt-in and opt-out mods. When viewing information about this kind of +collections, an additional @ui{Options} button is shown in the mod info popup. +This will let you enable or disable individual contained mods. @section{ Multiplayer } @@ -128,19 +145,20 @@ server is also automatically queried for any public servers. @parag{Viewing server information.} Right-click a server in the list to view -status information about it. The same popup can be opened by clicking the small +information about it. The same popup can be opened by clicking the small @ui{...} button in the server description. The status information includes: @list/thin{ @item ping time @item which game and map is currently running @item outline of the current map - @item list of packages loaded on the server + @item list of mods loaded on the server @item list of connected players @item server version } @parag{Joining a game.} Join an open multiplayer game by clicking @ui{Join} -either in the server list or in the server information popup. +either in the server list or in the server information popup. Any missing mods +are downloaded automatically after you click the button. @parag{Player name and color.} When a game is running (after joining a multiplayer game or also in single-player), go to the game's @ui{Options} menu @@ -153,26 +171,23 @@ Multiplayer tab's actions menu (@ui{...} under the tab title), and enter the server's IP address or domain name. -@parag{Failure to connect?} There are several reasons why you may not be able -to join a multiplayer game. You will be notified if you don't have the same -packages that the server is using. You can review the required packages in the -server information popup. Connectivity problems can also be due to your +@parag{Failure to connect?} Connectivity problems can also be due to your firewall or @link{network address translation -(NAT)}{https://en.wikipedia.org/wiki/Network_address_translation}. - -Doomsday uses TCP network connections for multiplayer games. If you host a game -and are behind a firewall or using NAT, you must make sure that other computers -are able to open TCP connections to your computer. This entails opening the -appropriate incoming TCP ports on your firewall and/or configuring the NAT so -that the correct ports are routed to your computer. +(NAT)}{https://en.wikipedia.org/wiki/Network_address_translation}. Doomsday uses +TCP network connections for multiplayer games. If you host a game and are behind +a firewall or using NAT, you must make sure that other computers are able to +open TCP connections to your computer. This entails opening the appropriate +incoming TCP ports on your firewall and/or configuring the NAT so that the +correct ports are routed to your computer. Additionally, UDP ports 13209-13224 are used for detecting servers running on the local network; if you are experiencing problems with autodetecting local servers, check that your firewall isn't blocking these UDP ports on either end. -A server opens one TCP port for listening to incoming connections. The port -must be open for incoming TCP traffic in the firewall. The port number is -configured with the console variable @var{net-ip-port}. By default, a server uses TCP port 13209. +A server opens one TCP port for listening to incoming connections. The port must +be open for incoming TCP traffic in the firewall. The port number is configured +with the console variable @var{net-ip-port}. By default, a server uses TCP port +13209. Clients do not require any firewall configuration for incoming connections. A client only needs to be able to reach the server via the server's TCP port. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/ui/taskbar.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/ui/taskbar.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/readme/ui/taskbar.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/readme/ui/taskbar.ame 2018-12-11 07:08:23.000000000 +0000 @@ -16,14 +16,14 @@ Doomsday's UI. It is only shown once, but you can manually show it again by selecting @ui{Help: Show Tutorial}. -@parag{Browsing and loading packages.} @ui{Browse Packages...} opens the -package list in a sidebar where packages can be loaded and unloaded manually. -You can also view information about packages like in the Home screen. The +@parag{Browsing and loading mods.} @ui{Browse Mods...} opens the +mod browser in a sidebar where mods can be loaded and unloaded manually. +You can also view information about mods like in the Home screen. The sidebar is only available when a game is loaded. You can use the @dquote{loaded} keyword to filter the list so that only the currently loaded -packages are listed. +mods are listed. -@notice{Data from newly loaded packages may not be used until a new map is +@notice{Data from newly loaded mods may not be used until a new map is started in the game. Use of external textures can be enabled and disabled in Renderer settings.} @@ -79,11 +79,16 @@ @item @ui{Stretched}: The aspect ratio is unrestricted and adapts to window dimensions. Game elements may appear too wide or tall with this setting. } -@parag{Audio backends.} Some of the audio options are dependent on the active -audio backend(s). For example, a MIDI sound font is supported by the FMOD and -Fluidsynth plugins. 3D sound and reverb are supported by FMOD, OpenAL, and -DirectSound. The audio backend can be reconfigured on the fly; any changes are -applied when you close the popup. +@parag{Audio backend.} Audio output capabilities vary based on operating system +and audio hardware. Doomsday's audio backend can be configured according to your +needs primarily via the selection of audio interface plugins. The recommendation +on all platforms is FMOD for sound effects and FluidSynth for music, because +these two enable software-based rendering of both 3D sound effects and MIDI +music. Some of the audio options are dependent on the active audio plugins. For +example, a MIDI sound font is supported by the FMOD and FluidSynth plugins. 3D +sound and reverb are supported by FMOD, OpenAL, and DirectSound. The audio +backend can be reconfigured on the fly; any changes are applied when you press +the @ui{Apply} button. @parag{Game controllers.} Doomsday comes with a few preset bindings for different gamepads. To use one of the presets, click on the @ui{Game Controller @@ -103,11 +108,11 @@ additionally want to disable mouse filtering by toggling the @ui{Filter X Axis} and @ui{Filter Y Axis} options. -@parag{Local multiplayer packages.} By default, clients are not allowed to load -packages in addition to what the server is using. This avoids any potential -compatibility issues with the client's packages overriding some of the game's -definitions. However, you can manually enable local packages in Network -settings. You can then select additional local packages for multiplayer games +@parag{Local multiplayer mods.} By default, clients are not allowed to load +mods in addition to what the server is using. This avoids any potential +compatibility issues with the client's mods overriding some of the game's +definitions. However, you can manually enable local mods in Network +settings. You can then select additional local mods for multiplayer games in the server information popup before joining the game. @parag{User Interface settings.} The @ui{Scale} setting applies to the Doomsday @@ -150,7 +155,7 @@ This will pop up a list of all possible completions, including the current values for any variables. You can change console variable values as follows: -@samp{@cmd{sound-info 1}} +@samp{@cmd{rend-camera-fov 110}} @parag{Shortcut key.} You should set up a console shortcut key if you find yourself going to the console often. The shortcut defaults to @kbd{Tilde} (U.S. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/server/server.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/server/server.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/server/server.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/server/server.ame 2018-12-11 07:08:23.000000000 +0000 @@ -1,7 +1,7 @@ $ Man page for doomsday-server @macro{TITLE}{ doomsday-server } @macro{ONELINER}{ Doomsday Engine multiplayer daemon } -@macro{VERSION}{ Version 2.0 } +@macro{VERSION}{ Version 2.1 } @macro{AUTHOR}{ Deng Team } @macro{LINK}{ http://dengine.net/ } @require{amestd} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doc/shell-text/shell-text.ame doomsday-stable-2.1.0.2900+xenial/doomsday/doc/shell-text/shell-text.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/doc/shell-text/shell-text.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doc/shell-text/shell-text.ame 2018-12-11 07:08:23.000000000 +0000 @@ -1,7 +1,7 @@ $ Man page for doomsday-shell-text @macro{TITLE}{ doomsday-shell-text } @macro{ONELINER}{ Utility for controlling and monitoring Doomsday servers } -@macro{VERSION}{ Version 2.0 } +@macro{VERSION}{ Version 2.1 } @macro{AUTHOR}{ Deng Team } @macro{LINK}{ http://dengine.net/ } @require{amestd} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doomsday.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/doomsday.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/doomsday.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doomsday.doxy 2018-12-11 07:08:23.000000000 +0000 @@ -131,7 +131,7 @@ GENERATE_HTML = YES HTML_OUTPUT = . HTML_FILE_EXTENSION = .html -HTML_HEADER = +HTML_HEADER = doxygen_header.html HTML_FOOTER = HTML_STYLESHEET = doxygen.css HTML_EXTRA_FILES = diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doxygen.css doomsday-stable-2.1.0.2900+xenial/doomsday/doxygen.css --- doomsday-stable-2.0.3.2464+xenial/doomsday/doxygen.css 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doxygen.css 2018-12-11 07:08:23.000000000 +0000 @@ -1,10 +1,15 @@ /* Doomsday API Documentation Style */ -@import url(http://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,700italic,400,700,300); +@import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:300italic,400italic,700italic,400,700,300); +@import url(http://dengine.net/theme/stylesheets/topbar.css); body, .tabs, .tabs2, .tabs3, #MSearchField, .SelectItem, .SRSymbol, .SRScope { - font-family: "Open Sans" !important; + font-family: "Source Sans Pro" !important; + font-size: 13pt; +} +#MSearchField { + font-size: 12px; } .tabs2 { @@ -16,7 +21,7 @@ } body { - max-width: 900px; + max-width: 50em; margin-left: auto; margin-right: auto; @@ -32,7 +37,8 @@ /* Navigation tabs */ ul.sm-dox { - background: #eee !important; + background-color: rgba(255, 255, 255, 0.6) !important; + background-image: none !important; } .tabs, .tabs2, .tabs3, .tablist li, @@ -106,11 +112,10 @@ } .memitem { - background-color: rgba(255, 255, 255, 0.9); + background-color: rgba(255, 255, 255, 0.5); color: #555; padding: 0; margin-bottom: 1.2em; - box-shadow: 0 0 24px -8px rgb(110, 110, 110); } .memdoc { @@ -154,10 +159,10 @@ div.summary, div.qindex, div.qindex + table { - background-color: rgba(255, 255, 255, 0.7); - box-shadow: 0 0 24px -8px rgb(110, 110, 110); - color: #444; - padding: 1.2em; + /*background-color: rgba(255, 255, 255, 0.7); + color: #444;*/ + color: black; + padding: 1.2em 0; } /*div.contents > :not(.textblock) > code:first-child { @@ -202,7 +207,7 @@ div.textblock p small { font-weight: 300; - color: #888; + color: #666; } div.textblock p small a { @@ -733,6 +738,13 @@ color: #555; } +h2.memtitle .permalink a { + display: none; +} +h2.memtitle .overload { + color: #888; +} + .memItemRight a:first-child, .memTemplItemRight a:first-child { font-weight: bold; @@ -741,13 +753,13 @@ .memItemRight br { display: none; } table.memberdecls .memItemLeft, .memTemplItemLeft { - background-color: rgba(255, 255, 255, 0.95); + background-color: rgba(255, 255, 255, 0.7); padding-left: 0.6em; min-width: 200px; } table.memberdecls .mdescLeft { - background-color: rgba(255, 255, 255, 0.85); + background-color: rgba(255, 255, 255, 0.8); min-width: 200px; } @@ -984,7 +996,6 @@ table.directory { background-color: rgba(255, 255, 255, 0.75); - box-shadow: 0 0 24px -8px rgb(110, 110, 110); color: #888; padding: 0; border-collapse: collapse; @@ -1409,7 +1420,7 @@ } #titlearea { - padding: 6px 0px; + padding: 30px 0 6px 0; margin: 0px; width: 100%; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/doxygen_header.html doomsday-stable-2.1.0.2900+xenial/doomsday/doxygen_header.html --- doomsday-stable-2.0.3.2464+xenial/doomsday/doxygen_header.html 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/doxygen_header.html 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,70 @@ + + + + + + + + +$projectname: $title +$title + + + +$treeview +$search +$mathjax + +$extrastylesheet + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+
$projectname +  $projectnumber +
+
$projectbrief
+
+
$projectbrief
+
$searchbox
+
+ + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/external/assimp/code/Bitmap.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/external/assimp/code/Bitmap.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/external/assimp/code/Bitmap.cpp 2017-10-01 00:40:34.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/external/assimp/code/Bitmap.cpp 2018-12-11 07:08:44.000000000 +0000 @@ -83,7 +83,7 @@ } template - inline std::size_t Copy(uint8_t* data, T& field) { + inline std::size_t Copy(uint8_t* data, const T &field) { std::memcpy(data, &AI_BE(field), sizeof(field)); return sizeof(field); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/external/fluidsynth/src/config_win32.h doomsday-stable-2.1.0.2900+xenial/doomsday/external/fluidsynth/src/config_win32.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/external/fluidsynth/src/config_win32.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/external/fluidsynth/src/config_win32.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,45 @@ +#define VERSION FLUIDSYNTH_VERSION + +#define HAVE_STRING_H 1 +#define HAVE_STDLIB_H 1 +#define HAVE_STDIO_H 1 +#define HAVE_MATH_H 1 +#define HAVE_STDARG_H 1 +#define HAVE_FCNTL_H 1 +#define HAVE_LIMITS_H 1 +#define HAVE_IO_H 1 +#define HAVE_WINDOWS_H 1 + +#define DSOUND_SUPPORT 0 +#define WINMIDI_SUPPORT 0 +#define WITH_FLOAT 1 + +//#define snprintf _snprintf +#define strcasecmp _stricmp + +#if _MSC_VER < 1500 +#define vsnprintf _vsnprintf +#endif + +#define STDIN_FILENO 0 +#define STDOUT_FILENO 1 +#define STDERR_FILENO 2 + + +#define WITH_PROFILING 0 + +#pragma warning(disable : 4244) +#pragma warning(disable : 4101) +#pragma warning(disable : 4305) +#pragma warning(disable : 4996) + +#ifndef inline +#define inline __inline +#endif + +typedef int socklen_t; + +#include + +typedef uint8_t u_int8_t; +typedef uint32_t u_int32_t; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/dialogs/messagedialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/dialogs/messagedialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/dialogs/messagedialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/dialogs/messagedialog.h 2018-12-11 07:08:23.000000000 +0000 @@ -38,6 +38,8 @@ LabelWidget &title(); LabelWidget &message(); + void setLayoutWidth(const Rule &); + enum LayoutBehavior { ExcludeHidden, IncludeHidden }; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/atlasproceduralimage.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/atlasproceduralimage.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/atlasproceduralimage.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/atlasproceduralimage.h 2018-12-11 07:08:23.000000000 +0000 @@ -39,7 +39,7 @@ { public: AtlasProceduralImage(GuiWidget &owner) - : _owner(owner), _atlas(0), _id(Id::None), _needUpdate(false) + : _owner(owner), _atlas(0), _id(Id::None), _needUpdate(false), _imageOwned(true) {} ~AtlasProceduralImage() @@ -69,7 +69,10 @@ { if (_atlas) { - _atlas->release(_id); + if (_imageOwned) + { + _atlas->release(_id); + } _atlas = 0; _id = Id::None; } @@ -79,7 +82,18 @@ { _image = image; _needUpdate = true; - setSize(image.size()); + _imageOwned = true; + setPointSize(image.size() * image.pointRatio()); + } + + void setPreallocatedImage(Id const &id, float pointRatio = 1.f) + { + _image = Image(); + _needUpdate = false; + _imageOwned = false; + _id = id; + _atlas = &ownerAtlas(); + setPointSize(_atlas->imageRect(id).size() * pointRatio); } bool update() @@ -120,6 +134,7 @@ Image _image; Id _id; bool _needUpdate; + bool _imageOwned; }; } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/baseguiapp.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/baseguiapp.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/baseguiapp.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/baseguiapp.h 2018-12-11 07:08:23.000000000 +0000 @@ -24,6 +24,7 @@ #include #include +#include #include /** @@ -50,9 +51,20 @@ virtual void glDeinit(); void initSubsystems(SubsystemInitFlags flags = DefaultSubsystems); - double dpiFactor() const; /** + * The ratio of pixels per point. For example, this is 2.0 if there are two pixels per point. + */ + const Rule &pixelRatio() const; + + /** + * Sets a new pixel ratio. This replaces the initial automatically detected pixel ratio. + * + * @param pixelRatio Pixel ratio. + */ + void setPixelRatio(float pixelRatio); + + /** * Enters the "native UI" mode that temporarily switches the main window to a * regular window and restores the desktop display mode. This allows the user to * access native UI widgets normally. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/basewindow.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/basewindow.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/basewindow.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/basewindow.h 2018-12-11 07:08:23.000000000 +0000 @@ -20,10 +20,16 @@ #define LIBAPPFW_BASEWINDOW_H #include "../libappfw.h" - -#include #include +#if !defined (DENG_MOBILE) +# include +# define LIBAPPFW_BASEWINDOW_SUPER de::PersistentGLWindow +#else +# include +# define LIBAPPFW_BASEWINDOW_SUPER de::GLWindow +#endif + namespace de { class WindowTransform; @@ -38,7 +44,7 @@ * * @ingroup appfw */ -class LIBAPPFW_PUBLIC BaseWindow : public PersistentGLWindow +class LIBAPPFW_PUBLIC BaseWindow : public LIBAPPFW_BASEWINDOW_SUPER { public: BaseWindow(String const &id); @@ -82,6 +88,10 @@ */ virtual void drawWindowContent() = 0; +#if defined (DENG_MOBILE) + String configName(String const &key) const; +#endif + protected: /** * Called when a draw request has been received. This method should carry out any diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/data.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/data.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/data.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/data.h 2018-12-11 07:08:23.000000000 +0000 @@ -104,6 +104,8 @@ */ virtual Pos find(Item const &item) const = 0; + virtual Pos findLabel(String const &label) const = 0; + /** * Finds the position of an item with a specific data. * diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/filtereddata.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/filtereddata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/filtereddata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/filtereddata.h 2018-12-11 07:08:23.000000000 +0000 @@ -78,6 +78,7 @@ Item &at(Pos pos) override; Item const &at(Pos pos) const override; Pos find(Item const &item) const override; + Pos findLabel(String const &label) const override; Pos findData(QVariant const &data) const override; void sort(SortMethod method = Ascending) override { Data::sort(method); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/gridlayout.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/gridlayout.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/gridlayout.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/gridlayout.h 2018-12-11 07:08:23.000000000 +0000 @@ -21,6 +21,7 @@ #include "../ui/defs.h" #include "../GuiWidget" +#include namespace de { @@ -33,7 +34,7 @@ * * @ingroup appfw */ -class LIBAPPFW_PUBLIC GridLayout +class LIBAPPFW_PUBLIC GridLayout : public ISizeRule { public: enum Mode { @@ -125,8 +126,8 @@ int widgetCellSpan(GuiWidget const &widget) const; - Rule const &width() const; - Rule const &height() const; + Rule const &width() const override; + Rule const &height() const override; Rule const &columnLeft(int col) const; Rule const &columnRight(int col) const; Rule const &columnWidth(int col) const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/guirootwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/guirootwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/guirootwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/guirootwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -30,6 +30,7 @@ namespace de { +class AnimationVector2; class FocusWidget; class GuiWidget; class Painter; @@ -82,6 +83,8 @@ * Returns the default projection for 2D graphics. */ Matrix4f projMatrix2D() const; + + AnimationVector2 &rootOffset(); void routeMouse(Widget *routeTo); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/guiwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/guiwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/guiwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/guiwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -331,7 +331,7 @@ * @param span Animation transition span. * @param startDelay Starting delay. */ - void setOpacity(float opacity, TimeDelta span = 0, TimeDelta startDelay = 0); + void setOpacity(float opacity, TimeSpan span = 0, TimeSpan startDelay = 0); /** * Determines the widget's opacity animation. @@ -435,7 +435,7 @@ MouseClickStatus handleMouseClick(Event const &event, MouseEvent::Button button = MouseEvent::Left); - + /** * Requests the widget to refresh its geometry, if it has any static * geometry. Normally this does not need to be called. It is provided @@ -461,6 +461,14 @@ */ PopupWidget *findParentPopup() const; + void collectNotReadyAssets(AssetGroup &collected, + CollectMode = CollectMode::OnlyVisible) override; + + /** + * Blocks until all assets in the widget tree are Ready. + */ + void waitForAssetsReady(); + public slots: /** * Puts the widget in garbage to be deleted at the next recycling. @@ -479,20 +487,27 @@ static Rectanglef normalizedRect(Rectanglei const &rect, Rectanglei const &containerRect); - static float toDevicePixels(float logicalPixels); + static float pointsToPixels(float points); + static float pixelsToPoints(float pixels); - inline static int toDevicePixels(int logicalPixels) { - return int(toDevicePixels(float(logicalPixels))); + inline static int pointsToPixels(int points) { + return int(pointsToPixels(float(points))); } - inline static duint toDevicePixels(duint logicalPixels) { - return duint(toDevicePixels(float(logicalPixels))); + inline static duint pointsToPixels(duint points) { + return duint(pointsToPixels(float(points))); } template - static Vector2 toDevicePixels(Vector2 const &type) { - return Vector2(typename Vector2::ValueType(toDevicePixels(type.x)), - typename Vector2::ValueType(toDevicePixels(type.y))); + static Vector2 pointsToPixels(Vector2 const &type) { + return Vector2(typename Vector2::ValueType(pointsToPixels(type.x)), + typename Vector2::ValueType(pointsToPixels(type.y))); + } + + template + static Vector2 pixelsToPoints(Vector2 const &type) { + return Vector2(typename Vector2::ValueType(pixelsToPoints(type.x)), + typename Vector2::ValueType(pixelsToPoints(type.y))); } static ColorTheme invertColorTheme(ColorTheme theme); @@ -504,8 +519,6 @@ */ static void recycleTrashedWidgets(); - static void collectNotReadyAssets(AssetGroup &collected, Widget &widget); - protected: /** * Called by GuiWidget::update() the first time an update is being carried diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/item.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/item.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/item.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/item.h 2018-12-11 07:08:23.000000000 +0000 @@ -59,6 +59,7 @@ ActivationClosesPopup = 0x100, Separator = 0x200, Annotation = 0x400 | Separator, + ClosesParentPopup = 0x800, DefaultSemantics = ShownAsLabel }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/listdata.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/listdata.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/listdata.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/listdata.h 2018-12-11 07:08:23.000000000 +0000 @@ -42,6 +42,7 @@ Item &at(Pos pos); Item const &at(Pos pos) const; Pos find(Item const &item) const; + Pos findLabel(String const &label) const; Pos findData(QVariant const &data) const; Data &clear(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/margins.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/margins.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/margins.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/margins.h 2018-12-11 07:08:23.000000000 +0000 @@ -54,6 +54,7 @@ Margins &setRight (Rule const &rule); Margins &setTop (Rule const &rule); Margins &setBottom(Rule const &rule); + Margins &setTopBottom(Rule const &rule) { return setTop(rule).setBottom(rule); } Margins &set (ui::Direction dir, Rule const &rule); Margins &set (Rule const &rule); Margins &setAll (Margins const &margins); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/painter.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/painter.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/painter.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/painter.h 2018-12-11 07:08:23.000000000 +0000 @@ -47,6 +47,10 @@ public: Painter(); + /** + * Initializes the Painter for drawing. This must be called on every frame, before + * drawing anything. + */ void init(); void deinit(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/proceduralimage.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/proceduralimage.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/proceduralimage.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/proceduralimage.h 2018-12-11 07:08:23.000000000 +0000 @@ -40,16 +40,15 @@ public: typedef Vector2f Size; typedef Vector4f Color; - //typedef GLBufferT DefaultVertexBuf; public: - ProceduralImage(Size const &size = Size()); + ProceduralImage(Size const &pointSize = Size()); virtual ~ProceduralImage(); - Size size() const; + Size pointSize() const; // in points Color color() const; - void setSize(Size const &size); + void setPointSize(Size const &pointSize); void setColor(Color const &color); /** @@ -67,7 +66,7 @@ DENG2_CAST_METHODS() private: - Size _size; + Size _pointSize; Color _color; }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/sequentiallayout.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/sequentiallayout.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/sequentiallayout.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/sequentiallayout.h 2018-12-11 07:08:23.000000000 +0000 @@ -21,6 +21,7 @@ #include "../ui/defs.h" #include "../GuiWidget" +#include namespace de { @@ -33,7 +34,7 @@ * * @ingroup appfw */ -class LIBAPPFW_PUBLIC SequentialLayout +class LIBAPPFW_PUBLIC SequentialLayout : public ISizeRule { public: SequentialLayout(Rule const &startX, @@ -87,8 +88,8 @@ int size() const; bool isEmpty() const; - Rule const &width() const; - Rule const &height() const; + Rule const &width() const override; + Rule const &height() const override; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/style.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/style.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/style.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/style.h 2018-12-11 07:08:23.000000000 +0000 @@ -38,6 +38,9 @@ class LIBAPPFW_PUBLIC Style { public: + DENG2_DEFINE_AUDIENCE2(Change, void styleChanged(Style &)) + +public: Style(); virtual ~Style(); @@ -76,6 +79,8 @@ virtual GuiWidget *sharedBlurWidget() const; + virtual void performUpdate(); + public: /** * Returns the current global application UI style. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/styleproceduralimage.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/styleproceduralimage.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/styleproceduralimage.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/styleproceduralimage.h 2018-12-11 07:08:23.000000000 +0000 @@ -34,7 +34,10 @@ { public: StyleProceduralImage(DotPath const &styleImageId, GuiWidget &owner, float angle = 0) - : _owner(owner), _imageId(styleImageId), _id(Id::None), _angle(angle) + : _owner(owner) + , _imageId(styleImageId) + , _id(Id::None) + , _angle(angle) { if (_owner.hasRoot()) { @@ -60,8 +63,9 @@ void alloc() { + const Image &img = Style::get().images().image(_imageId); + setPointSize(img.size() * img.pointRatio()); _id = root().styleTexture(_imageId); - setSize(root().atlas().imageRect(_id).size()); } Id const &allocId() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/subwidgetitem.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/subwidgetitem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/framework/subwidgetitem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/framework/subwidgetitem.h 2018-12-11 07:08:23.000000000 +0000 @@ -48,12 +48,25 @@ , _constructor(constructor) , _dir(openingDirection) {} + SubwidgetItem(Semantics semantics, String const &label, ui::Direction openingDirection, + WidgetConstructor constructor) + : ImageItem(semantics, label) + , _constructor(constructor) + , _dir(openingDirection) {} + SubwidgetItem(Image const &image, String const &label, ui::Direction openingDirection, WidgetConstructor constructor) : ImageItem(ShownAsButton, image, label) , _constructor(constructor) , _dir(openingDirection) {} + SubwidgetItem(Image const &image, Semantics semantics, String const &label, + ui::Direction openingDirection, WidgetConstructor constructor) + : ImageItem(semantics, image, label) + , _constructor(constructor) + , _dir(openingDirection) + {} + PopupWidget *makeWidget() const { return _constructor(); } ui::Direction openingDirection() const { return _dir; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/commandwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/commandwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/commandwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/commandwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -20,6 +20,7 @@ #define LIBAPPFW_COMMANDWIDGET_H #include "../LineEditWidget" +#include "../IPersistent" namespace de { @@ -31,7 +32,7 @@ * * @ingroup guiWidgets */ -class LIBAPPFW_PUBLIC CommandWidget : public LineEditWidget +class LIBAPPFW_PUBLIC CommandWidget : public LineEditWidget, public IPersistent { Q_OBJECT @@ -48,6 +49,10 @@ bool handleControlKey(int qtKey, KeyModifiers const &mods) override; + // IPersistent. + void operator >> (PersistentState &toState) const override; + void operator << (PersistentState const &fromState) override; + public slots: /** * Moves the current contents of the command line to the history. The diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/dialogwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/dialogwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/dialogwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/dialogwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -36,7 +36,7 @@ * the bottom of the dialog, for the actions available to the user. * * The contents of the dialog should be placed under the scroll area returned - * by DialogWidget::content() and positioned in relation to its content rule. + * by DialogWidget::area() and positioned in relation to its content rule. * When the dialog is set up, one must define the size of the content scroll * area (width and height rules). * @@ -180,6 +180,8 @@ */ void setMinimumContentWidth(Rule const &minWidth); + void setMaximumContentHeight(Rule const &maxHeight); + MenuWidget &buttonsMenu(); /** @@ -211,6 +213,8 @@ */ void setAcceptanceAction(RefArg action); + de::Action *acceptanceAction() const; + /** * Shows the dialog and blocks execution until the dialog is closed -- * another event loop is started for event processing. Call either accept() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/directoryarraywidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/directoryarraywidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/directoryarraywidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/directoryarraywidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -35,6 +35,7 @@ protected: String labelForElement(Value const &value) const override; + void elementCreated(LabelWidget &, const ui::Item &) override; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/documentwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/documentwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/documentwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/documentwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -24,6 +24,8 @@ namespace de { +class ProgressWidget; + /** * Widget for displaying large amounts of text. * @@ -74,7 +76,17 @@ * * @param maxWidth Maximum width of a text line. */ - void setMaximumLineWidth(int maxWidth); + void setMaximumLineWidth(const Rule &maxWidth); + + /** + * Set one of the style colors. + * + * @param id Color identifier. + * @param colorName Name of the color. + */ + void setStyleColor(Font::RichFormat::Color id, DotPath const &colorName); + + ProgressWidget &progress(); // Events. void viewResized(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/fadetoblackwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/fadetoblackwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/fadetoblackwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/fadetoblackwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -34,11 +34,11 @@ public: FadeToBlackWidget(); - void initFadeFromBlack(TimeDelta const &span); + void initFadeFromBlack(TimeSpan const &span); - void initFadeToBlack(TimeDelta const &span); + void initFadeToBlack(TimeSpan const &span); - void start(TimeDelta const &delay = 0.0); + void start(TimeSpan const &delay = 0.0); void pause(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/focuswidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/focuswidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/focuswidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/focuswidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -42,6 +42,11 @@ void fadeIn(); void fadeOut(); + /** + * Determines whether the focus widget is active and flashing. + */ + bool isKeyboardFocusActive() const; + // Events. void update() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/foldpanelwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/foldpanelwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/foldpanelwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/foldpanelwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -64,6 +64,10 @@ GuiWidget &content() const; +public: + static FoldPanelWidget *makeOptionsGroup(const String &name, const String &heading, + GuiWidget *parent); + public slots: void toggleFold(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/labelwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/labelwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/labelwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/labelwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -27,6 +27,7 @@ namespace de { class GLUniform; +class GridLayout; class Image; /** @@ -199,11 +200,19 @@ * The image's actual size will be overridden by this size. * @param size Image size. */ - void setOverrideImageSize(Vector2f const &size); + void setOverrideImageSize(const Rule &width, const Rule &height); - Vector2f overrideImageSize() const; + void setOverrideImageSize(const ISizeRule &size) + { + setOverrideImageSize(size.width(), size.height()); + } + + void setOverrideImageSize(const Rule &widthAndHeight) + { + setOverrideImageSize(widthAndHeight, widthAndHeight); + } - void setOverrideImageSize(float widthAndHeight); + RulePair overrideImageSize() const; void setImageScale(float scaleFactor); @@ -251,7 +260,7 @@ * to the appropriate height in the specified time span. * @param span Animation time span for the appearance. */ - void setAppearanceAnimation(AppearanceAnimation method, TimeDelta const &span = 0.0); + void setAppearanceAnimation(AppearanceAnimation method, TimeSpan const &span = 0.0); // Events. void update() override; @@ -265,7 +274,9 @@ void contentLayout(ContentLayout &layout); public: - static LabelWidget *newWithText(String const &label, GuiWidget *parent = 0); + static LabelWidget *newWithText(const String &text, GuiWidget *parent = nullptr); + static LabelWidget *appendSeparatorWithText(const String &text, GuiWidget *parent = nullptr, + GridLayout *appendToGrid = nullptr); protected: void glInit() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/lineeditwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/lineeditwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/lineeditwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/lineeditwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -78,6 +78,12 @@ public: static KeyModifiers modifiersFromKeyEvent(KeyEvent::Modifiers const &keyMods); +#if defined (DENG_MOBILE) +protected slots: + void userEnteredText(QString); + void userFinishedTextEntry(); +#endif + signals: void enterPressed(QString text); void editorContentChanged(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/menuwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/menuwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/menuwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/menuwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -188,6 +188,9 @@ */ void subWidgetOpened(de::PanelWidget *panel); +protected: + void updateStyle() override; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/panelwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/panelwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/panelwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/panelwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -49,11 +49,15 @@ */ DENG2_DEFINE_AUDIENCE2(Close, void panelBeingClosed(PanelWidget &)) + enum AnimationStyle { Bouncy, EasedOut, Smooth }; + public: PanelWidget(String const &name = String()); void setWaitForContentReady(bool yes); + void setAnimationStyle(AnimationStyle style); + /** * Enables or disables mouse event eating. The default is that a panel eats * events that hit it. @@ -101,7 +105,7 @@ bool isOpeningOrClosing() const; - void close(TimeDelta delayBeforeClosing); + void close(TimeSpan delayBeforeClosing); // Events. void viewResized() override; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/popupmenuwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/popupmenuwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/popupmenuwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/popupmenuwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -35,9 +35,9 @@ PopupMenuWidget(String const &name = String()); void setParentPopup(PopupWidget *parentPopup); + PopupWidget *parentPopup() const; MenuWidget &menu() const; - ui::Data &items() { return menu().items(); } void useInfoStyle(bool yes = true); @@ -51,6 +51,7 @@ void glMakeGeometry(GuiVertexBuilder &verts) override; void preparePanelForOpening() override; void panelClosing() override; + void updateStyle() override; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/popupwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/popupwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/popupwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/popupwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -103,6 +103,13 @@ ColorTheme colorTheme() const; + /** + * Sets the color of the popup outline. By default, popups do not have an outline. + * + * @param outlineColor Outline color. + */ + void setOutlineColor(DotPath const &outlineColor); + void setCloseButtonVisible(bool enable); /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/progresswidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/progresswidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/progresswidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/progresswidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -82,7 +82,7 @@ */ void setRange(Rangei const &range, Rangef const &visualRange = Rangef(0.f, 1.f)); - void setProgress(int currentProgress, TimeDelta const &transitionSpan = 0.5); + void setProgress(int currentProgress, TimeSpan const &transitionSpan = 0.5); // Events. void update(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/scrollareawidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -67,6 +67,7 @@ void setContentHeight(int height); void setContentHeight(Rule const &height); void setContentSize(Rule const &width, Rule const &height); + void setContentSize(ISizeRule const &dimensions); void setContentSize(Vector2i const &size); void setContentSize(Vector2ui const &size); @@ -109,11 +110,11 @@ * @param to Scroll position. * @param span Animation time span. */ - void scroll(Vector2i const &to, TimeDelta span = 0); + void scroll(Vector2i const &to, TimeSpan span = 0); - void scrollX(int to, TimeDelta span = 0); - void scrollY(int to, TimeDelta span = 0); - void scrollY(Rule const &to, TimeDelta span = 0); + void scrollX(int to, TimeSpan span = 0); + void scrollY(int to, TimeSpan span = 0); + void scrollY(Rule const &to, TimeSpan span = 0); bool isScrollable() const; @@ -153,15 +154,15 @@ bool handleEvent(Event const &event) override; public slots: - void scrollToTop(TimeDelta span = 0.3); + void scrollToTop(TimeSpan span = 0.3); /** * Moves the scroll offset of the widget to the bottom of the content. */ - void scrollToBottom(TimeDelta span = 0.3); + void scrollToBottom(TimeSpan span = 0.3); - void scrollToLeft(TimeDelta span = 0.3); - void scrollToRight(TimeDelta span = 0.3); + void scrollToLeft(TimeSpan span = 0.3); + void scrollToRight(TimeSpan span = 0.3); /** * Moves the scroll offset to center on the given widget. @@ -169,7 +170,7 @@ * @param widget Widget to center on. * @param span Animation duration. */ - void scrollToWidget(GuiWidget const &widget, TimeDelta span = 0.3); + void scrollToWidget(GuiWidget const &widget, TimeSpan span = 0.3); /** * Finds the topmost scroll area that can be scrolled. May return this widget diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/sliderwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/sliderwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/sliderwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/sliderwidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -37,6 +37,9 @@ Q_OBJECT public: + DENG2_DEFINE_AUDIENCE2(Change, void sliderValueChanged(SliderWidget &)) + +public: SliderWidget(String const &name = String()); void setRange(Rangei const &intRange, int step = 1); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/togglewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/togglewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/togglewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/togglewidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -34,6 +34,12 @@ Q_OBJECT public: + enum Flag { + DefaultFlags = 0, + WithoutIndicator = 0x1, + }; + Q_DECLARE_FLAGS(Flags, Flag) + enum ToggleState { Active, Inactive @@ -45,7 +51,7 @@ DENG2_DEFINE_AUDIENCE2(Toggle, void toggleStateChanged(ToggleWidget &toggle)) public: - ToggleWidget(String const &name = String()); + ToggleWidget(Flags const &flags = DefaultFlags, String const &name = String()); /** * Sets the toggle state of the widget. @@ -73,6 +79,8 @@ DENG2_PRIVATE(d) }; +Q_DECLARE_OPERATORS_FOR_FLAGS(ToggleWidget::Flags) + } // namespace de #endif // LIBAPPFW_TOGGLEWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/variablearraywidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/variablearraywidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/variablearraywidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/variablearraywidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -62,11 +62,15 @@ ui::Item *makeItem(Value const &value); + // Events. + bool handleEvent(Event const &event) override; + signals: void arrayChanged(); protected: virtual String labelForElement(Value const &value) const; + virtual void elementCreated(LabelWidget &, const ui::Item &); public slots: void updateFromVariable(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/variablechoicewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/variablechoicewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/include/de/widgets/variablechoicewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/include/de/widgets/variablechoicewidget.h 2018-12-11 07:08:23.000000000 +0000 @@ -38,8 +38,11 @@ /// Thrown when the variable is gone and someone tries to access it. @ingroup errors DENG2_ERROR(VariableMissingError); + enum VariableType { Number, Text }; + public: - VariableChoiceWidget(Variable &variable, String const &name = String()); + VariableChoiceWidget(Variable &variable, VariableType variableType, + String const &name = String()); Variable &variable() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/baseguiapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/baseguiapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/baseguiapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/baseguiapp.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -91,19 +92,21 @@ return 0; } -DENG2_PIMPL_NOREF(BaseGuiApp) +DENG2_PIMPL(BaseGuiApp) +, DENG2_OBSERVES(Variable, Change) { Binder binder; QScopedPointer uiState; GLShaderBank shaders; WaveformBank waveforms; VRConfig vr; - double dpiFactor = 1.0; + float windowPixelRatio = 1.0f; ///< Without user's Config.ui.scaleConfig + ConstantRule *pixelRatio = new ConstantRule; -#ifdef WIN32 - Impl() + Impl(Public *i) : Base(i) { - // Use the Direct2D API to find out the desktop DPI factor. +#if defined(WIN32) + // Use the Direct2D API to find out the desktop pixel ratio. ID2D1Factory *d2dFactory = nullptr; HRESULT hr = D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED, &d2dFactory); if (SUCCEEDED(hr)) @@ -111,18 +114,28 @@ FLOAT dpiX = 96; FLOAT dpiY = 96; d2dFactory->GetDesktopDpi(&dpiX, &dpiY); - dpiFactor = dpiX / 96.0; + windowPixelRatio = dpiX / 96.0; d2dFactory->Release(); d2dFactory = nullptr; } - } #endif + } + + ~Impl() override + { + releaseRef(pixelRatio); + } + + void variableValueChanged(Variable &, const Value &) override + { + self().setPixelRatio(windowPixelRatio); + } }; BaseGuiApp::BaseGuiApp(int &argc, char **argv) - : GuiApp(argc, argv), d(new Impl) + : GuiApp(argc, argv), d(new Impl(this)) { - d->binder.init(scriptSystem().nativeModule("App")) + d->binder.init(scriptSystem()["App"]) << DENG2_FUNC (App_AddFontMapping, "addFontMapping", "family" << "mappings") << DENG2_FUNC (App_LoadFont, "loadFont", "fileName"); } @@ -135,35 +148,44 @@ d->shaders.clear(); } -double BaseGuiApp::dpiFactor() const -{ - return d->dpiFactor; -} - void BaseGuiApp::initSubsystems(SubsystemInitFlags flags) { GuiApp::initSubsystems(flags); -#ifndef WIN32 -# ifdef DENG2_QT_5_0_OR_NEWER - d->dpiFactor = devicePixelRatio(); -# else - d->dpiFactor = 1.0; -# endif +#if !defined(WIN32) + d->windowPixelRatio = float(devicePixelRatio()); #endif - - // The "-dpi" option overrides the detected DPI factor. + // The "-dpi" option overrides the detected pixel ratio. if (auto dpi = commandLine().check("-dpi", 1)) { - d->dpiFactor = dpi.params.at(0).toDouble(); + d->windowPixelRatio = dpi.params.at(0).toFloat(); } + setPixelRatio(d->windowPixelRatio); + + Config::get("ui.scaleFactor").audienceForChange() += d; + + d->uiState.reset(new PersistentState("UIState")); +} + +const Rule &BaseGuiApp::pixelRatio() const +{ + return *d->pixelRatio; +} + +void BaseGuiApp::setPixelRatio(float pixelRatio) +{ + d->windowPixelRatio = pixelRatio; // Apply the overall UI scale factor. - d->dpiFactor *= config().getf("ui.scaleFactor", 1.f); + pixelRatio *= config().getf("ui.scaleFactor", 1.0f); - scriptSystem().nativeModule("DisplayMode").set("DPI_FACTOR", d->dpiFactor); + if (!fequal(d->pixelRatio->value(), pixelRatio)) + { + LOG_VERBOSE("Pixel ratio changed to %.1f") << pixelRatio; - d->uiState.reset(new PersistentState("UIState")); + d->pixelRatio->set(pixelRatio); + scriptSystem()["DisplayMode"].set("PIXEL_RATIO", Value::Number(pixelRatio)); + } } BaseGuiApp &BaseGuiApp::app() @@ -193,23 +215,32 @@ void BaseGuiApp::beginNativeUIMode() { +#if !defined (DENG_MOBILE) // Switch temporarily to windowed mode. Not needed on macOS because the display mode // is never changed on that platform. -#ifndef MACOSX - auto &win = static_cast(GLWindow::main()); - win.saveState(); - int const windowedMode[] = { - BaseWindow::Fullscreen, false, - BaseWindow::End - }; - win.changeAttributes(windowedMode); + #if !defined (MACOSX) + { + auto &win = static_cast(GLWindow::main()); + win.saveState(); + int const windowedMode[] = { + BaseWindow::Fullscreen, false, + BaseWindow::End + }; + win.changeAttributes(windowedMode); + } + #endif #endif } void BaseGuiApp::endNativeUIMode() { -#ifndef MACOSX - static_cast(GLWindow::main()).restoreState(); +#if !defined (DENG_MOBILE) + #if !defined (MACOSX) + { + static_cast(GLWindow::main()).restoreState(); + } + #endif #endif -} +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/basewindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/basewindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/basewindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/basewindow.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -91,8 +91,12 @@ }; BaseWindow::BaseWindow(String const &id) - : PersistentGLWindow(id) +#if !defined (DENG_MOBILE) + : LIBAPPFW_BASEWINDOW_SUPER(id) , d(new Impl(this)) +#else + : d(new Impl(this)) +#endif {} void BaseWindow::setTransform(WindowTransform &xf) @@ -115,8 +119,10 @@ { if (isGLReady()) { +#if !defined (DENG_MOBILE) // Don't run the main loop until after the paint event has been dealt with. DENG2_GUI_APP->loop().pause(); +#endif return true; // Go ahead. } return false; @@ -173,8 +179,19 @@ vr.oculusRift().endFrame(); } +#if !defined (DENG_MOBILE) // The timer loop was paused when the frame was requested to be drawn. DENG2_GUI_APP->loop().resume(); +#endif } + +#if defined (DENG_MOBILE) + +String BaseWindow::configName(String const &key) const +{ + return QString("window.main.%1").arg(key); +} + +#endif } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/childwidgetorganizer.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -516,7 +516,7 @@ // This will ensure that differences in item heights will not accumulate // and cause the estimated PVS to become too inaccurate. float error = virtualStrut->value() - estimated.start * averageItemHeight; - correctionPerUnit = -error / GuiWidget::toDevicePixels(100); + correctionPerUnit = -error / GuiWidget::pointsToPixels(100); totalCorrection = de::abs(error); } // Apply correction to the virtual strut. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/dialogs/directorylistdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/dialogs/directorylistdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/dialogs/directorylistdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/dialogs/directorylistdialog.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -19,7 +19,7 @@ #include "de/DirectoryListDialog" #include "de/DirectoryArrayWidget" -#include +#include namespace de { @@ -47,7 +47,7 @@ Id groupId; std::unique_ptr group(new Group); - self().area().add(group->title = new LabelWidget); + self().area().add(group->title = new LabelWidget("group-title")); group->title->setText(title); group->title->setMaximumTextWidth(self().area().rule().width() - self().margins().width()); @@ -57,7 +57,7 @@ group->title->setTextColor("accent"); group->title->margins().setTop("gap"); - self().area().add(group->description = new LabelWidget); + self().area().add(group->description = new LabelWidget("group-desc")); group->description->setText(description); group->description->setFont("small"); group->description->setTextColor("altaccent"); @@ -69,10 +69,10 @@ group->description->margins().setBottom(ConstantRule::zero()); group->array.set(new ArrayValue); - group->list = new DirectoryArrayWidget(group->array); + group->list = new DirectoryArrayWidget(group->array, "group-direc-array"); group->list->margins().setZero(); - //self().add(group->list->detachAddButton(self().area().rule().width())); - //group->list->addButton().hide(); + self().add(group->list->detachAddButton(self().area().rule().width())); + group->list->addButton().hide(); self().area().add(group->list); QObject::connect(group->list, SIGNAL(arrayChanged()), @@ -87,11 +87,14 @@ : MessageDialog(name) , d(new Impl(this)) { + area().enableIndicatorDraw(true); buttons() << new DialogButtonItem(Default | Accept) - << new DialogButtonItem(Reject); - /*<< new DialogButtonItem(Action, style().images().image("create"), + << new DialogButtonItem(Reject) + << new DialogButtonItem(Action, style().images().image("create"), tr("Add Folder"), - new SignalAction(&d->list->addButton(), SLOT(trigger())));*/ + new CallbackAction([this]() { + (*d->groups.begin())->list->addButton().trigger(); + })); } Id DirectoryListDialog::addGroup(String const &title, String const &description) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/dialogs/messagedialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/dialogs/messagedialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/dialogs/messagedialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/dialogs/messagedialog.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -26,17 +26,18 @@ DENG_GUI_PIMPL(MessageDialog) { - LabelWidget *title; - LabelWidget *message; + LabelWidget * title; + LabelWidget * message; DialogContentStylist buttonStylist; + const Rule * layoutWidth = nullptr; Impl(Public *i) : Base(i) { ScrollAreaWidget &area = self().area(); // Create widgets. - area.add(title = new LabelWidget); - area.add(message = new LabelWidget); + area.add(title = new LabelWidget("title")); + area.add(message = new LabelWidget("message")); // Configure style. title->setFont("title"); @@ -44,7 +45,7 @@ title->setSizePolicy(ui::Fixed, ui::Expand); title->setAlignment(ui::AlignLeft); title->setTextAlignment(ui::AlignRight); - title->setOverrideImageSize(title->font().ascent().valuei()); + title->setOverrideImageSize(title->font().ascent()); title->setImageColor(style().colors().colorf("accent")); title->setTextGap("gap"); title->setTextLineAlignment(ui::AlignLeft); @@ -52,9 +53,16 @@ message->setAlignment(ui::AlignLeft); message->setTextLineAlignment(ui::AlignLeft); + layoutWidth = holdRef(rule("dialog.message.width")); + updateLayout(); } + ~Impl() override + { + releaseRef(layoutWidth); + } + void updateLayout(LayoutBehavior behavior = ExcludeHidden) { ScrollAreaWidget &area = self().area(); @@ -62,7 +70,7 @@ // Simple vertical layout. SequentialLayout layout(area.contentRule().left(), area.contentRule().top()); - layout.setOverrideWidth(rule("dialog.message.width")); + layout.setOverrideWidth(*layoutWidth); // Put all the widgets into the layout. foreach (GuiWidget *w, area.childWidgets()) @@ -74,7 +82,7 @@ } } - area.setContentSize(layout.width(), layout.height()); + area.setContentSize(layout); } }; @@ -106,6 +114,11 @@ return *d->message; } +void MessageDialog::setLayoutWidth(const Rule &layoutWidth) +{ + changeRef(d->layoutWidth, layoutWidth); +} + void MessageDialog::updateLayout(LayoutBehavior behavior) { d->updateLayout(behavior); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/filtereddata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/filtereddata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/filtereddata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/filtereddata.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -216,6 +216,15 @@ return InvalidPos; } +Data::Pos FilteredData::findLabel(String const &label) const +{ + for (Pos i = 0; i < Pos(d->items.size()); ++i) + { + if (d->items.at(i)->label() == label) return i; + } + return InvalidPos; +} + Data::Pos FilteredData::findData(QVariant const &data) const { for (Pos i = 0; i < Pos(d->items.size()); ++i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/fontlinewrapping.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/fontlinewrapping.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/fontlinewrapping.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/fontlinewrapping.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -316,7 +316,7 @@ Lines wrapRange(Rangei const &rangeToWrap, int maxWidth, int subsequentMaxWidth = 0, int initialIndent = 0) { - int const MIN_LINE_WIDTH = 150 * DENG2_BASE_GUI_APP->dpiFactor(); + int const MIN_LINE_WIDTH = roundi(150.f * DENG2_BASE_GUI_APP->pixelRatio().value()); bool const isTabbed = (subsequentMaxWidth > 0); indent = initialIndent; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/gltextcomposer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/gltextcomposer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/gltextcomposer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/gltextcomposer.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -33,8 +33,9 @@ String text; FontLineWrapping const *wraps = nullptr; Font::RichFormat format; - bool needRedo = false; + bool needRedo = false; ///< Release completely and allocate. Rangei visibleLineRange { MAX_VISIBLE_RANGE }; ///< Only these lines will be updated/drawn. + bool visibleLineRangeChanged = false; int maxGeneratedWidth = 0; struct Line { @@ -148,16 +149,19 @@ bool allocLines() { + DENG2_GUARD(wraps); + bool changed = false; - for (int i = 0; i < wraps->height(); ++i) + const int wrapsHeight = wraps->height(); + for (int i = 0; i < wrapsHeight; ++i) { - FontLineWrapping::LineInfo const &info = wraps->lineInfo(i); + const auto &info = wraps->lineInfo(i); if (i < lines.size()) { // Is the rasterized copy up to date? - if (/*!isLineVisible(i) ||*/ matchingSegments(i, info)) + if (matchingSegments(i, info)) { // This line can be kept as is. continue; @@ -354,7 +358,7 @@ void GLTextComposer::release() { d->releaseLines(); - d->visibleLineRange = MAX_VISIBLE_RANGE; + setRange(MAX_VISIBLE_RANGE); setState(false); } @@ -373,7 +377,7 @@ if (d->wraps != &wrappedLines) { d->wraps = &wrappedLines; - //forceUpdate(); + d->needRedo = true; setState(false); } } @@ -387,6 +391,7 @@ { d->format.clear(); d->text = d->format.initFromStyledText(styledText); + d->needRedo = true; setState(false); } @@ -394,12 +399,17 @@ { d->text = text; d->format = format; + d->needRedo = true; setState(false); } void GLTextComposer::setRange(Rangei const &visibleLineRange) { - d->visibleLineRange = visibleLineRange; + if (d->visibleLineRange != visibleLineRange) + { + d->visibleLineRange = visibleLineRange; + d->visibleLineRangeChanged = true; + } } Rangei GLTextComposer::range() const @@ -409,26 +419,33 @@ bool GLTextComposer::update() { - DENG2_ASSERT(d->wraps != 0); + DENG2_ASSERT(d->wraps); - // If a font hasn't been defined, there isn't much to do. - if (!d->wraps->hasFont()) return false; + bool changed = false; + // If a font hasn't been defined, there isn't much to do. + if (!d->wraps->hasFont()) + { + return false; + } if (d->font != &d->wraps->font()) { d->font = &d->wraps->font(); - forceUpdate(); + d->needRedo = true; } - if (d->needRedo) { d->releaseLines(); d->needRedo = false; + changed = d->allocLines(); + } + else if (d->visibleLineRangeChanged) + { + changed = d->allocLines(); + d->visibleLineRangeChanged = false; } - setState(true); - - return d->allocLines(); + return changed; } void GLTextComposer::forceUpdate() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/guirootwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/guirootwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/guirootwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/guirootwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -43,7 +43,7 @@ static DotPath const ID_DOT = "GuiRootWidget.dot"; #ifdef DENG2_QT_5_0_OR_NEWER -# define DPI_SCALED(x) ((x) * DENG2_BASE_GUI_APP->dpiFactor()) +# define DPI_SCALED(x) ((x) * DENG2_BASE_GUI_APP->pixelRatio().value()) #else # define DPI_SCALED(x) (x) #endif @@ -122,6 +122,7 @@ GLUniform uTexAtlas; TextureBank texBank; ///< Bank for the atlas contents. Painter painter; + AnimationVector2 rootOffset; FocusWidget *focusIndicator; bool noFramesDrawnYet; QList *> focusStack; @@ -319,7 +320,13 @@ Matrix4f GuiRootWidget::projMatrix2D() const { RootWidget::Size const size = viewSize(); - return Matrix4f::ortho(0, size.x, 0, size.y); + return Matrix4f::ortho(0, size.x, 0, size.y) * + Matrix4f::translate(d->rootOffset.value()); +} + +AnimationVector2 &GuiRootWidget::rootOffset() +{ + return d->rootOffset; } void GuiRootWidget::routeMouse(Widget *routeTo) @@ -336,8 +343,9 @@ { window().glActivate(); - if (event.type() == Event::MouseButton && - event.as().state() != MouseEvent::Released) + if ((event.type() == Event::MouseButton && + event.as().state() != MouseEvent::Released) || + event.type() == Event::MouseWheel) { d->focusIndicator->fadeOut(); } @@ -430,6 +438,12 @@ void GuiRootWidget::draw() { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif + + DENG2_ASSERT_IN_RENDER_THREAD(); + d->focusIndicator->initialize(); if (d->noFramesDrawnYet) @@ -459,6 +473,12 @@ void GuiRootWidget::drawUntil(Widget &until) { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif + + DENG2_ASSERT_IN_RENDER_THREAD(); + d->painter.setNormalizedScissor(); NotifyArgs args = notifyArgsForDraw(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/guiwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/guiwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/guiwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/guiwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -39,6 +39,7 @@ DENG2_PIMPL(GuiWidget) , DENG2_OBSERVES(Widget, ChildAddition) , DENG2_OBSERVES(ui::Margins, Change) +, DENG2_OBSERVES(Style, Change) #ifdef DENG2_DEBUG , DENG2_OBSERVES(Widget, ParentChange) #endif @@ -98,13 +99,15 @@ self().audienceForChildAddition() += this; margins.audienceForChange() += this; + Style::get().audienceForChange() += this; + #ifdef DENG2_DEBUG self().audienceForParentChange() += this; rule.setDebugName(self().path()); #endif } - ~Impl() + ~Impl() override { qDeleteAll(eventHandlers); @@ -125,19 +128,19 @@ #endif } - void marginsChanged() + void marginsChanged() override { flags |= StyleChanged; } #ifdef DENG2_DEBUG - void widgetParentChanged(Widget &, Widget *, Widget *) + void widgetParentChanged(Widget &, Widget *, Widget *) override { rule.setDebugName(self().path()); } #endif - void widgetChildAdded(Widget &child) + void widgetChildAdded(Widget &child) override { if (self().hasRoot()) { @@ -168,11 +171,10 @@ if (self().isClipped()) { - int const CULL_SAFETY_WIDTH = 50; // avoid pop-in when scrolling + const int CULL_SAFETY_WIDTH = int(pointsToPixels(40)); // avoid pop-in when scrolling // Clipped widgets are guaranteed to be within their rectangle. - return !visibleArea.overlaps(self().rule().recti().expanded( - GuiWidget::toDevicePixels(CULL_SAFETY_WIDTH))); + return !visibleArea.overlaps(self().rule().recti().expanded(CULL_SAFETY_WIDTH)); } // Otherwise widgets may draw anywhere in the view. return visibleArea.isNull(); @@ -185,7 +187,7 @@ blur.reset(new BlurState); // The blurred version of the view is downsampled. - blur->size = (self().root().viewSize() / GuiWidget::toDevicePixels(4)).max(Vector2ui(1, 1)); + blur->size = (self().root().viewSize() / GuiWidget::pointsToPixels(4)).max(Vector2ui(1, 1)); for (int i = 0; i < 2; ++i) { @@ -238,15 +240,6 @@ blur.reset(); } - void reinitBlur() - { - if (blur) - { - deinitBlur(); - initBlur(); - } - } - void updateBlurredBackground() { if (blur) @@ -345,9 +338,9 @@ void updateOpacityForDisabledWidgets() { float const opac = (self().isDisabled()? .3f : 1.f); - if (opacityWhenDisabled.target() != opac) + if (!fequal(opacityWhenDisabled.target(), opac)) { - opacityWhenDisabled.setValue(opac, .3f); + opacityWhenDisabled.setValue(opac, 0.3); } if ((flags & FirstUpdateAfterCreation) || !attribs.testFlag(AnimateOpacityWhenEnabledOrDisabled)) @@ -469,7 +462,7 @@ break; } // Very close edges are considered contacting. - if (edgeDistance >= 0 && edgeDistance < toDevicePixels(5)) + if (edgeDistance >= 0 && edgeDistance < pointsToPixels(5)) { return edgeDistance; } @@ -554,9 +547,21 @@ return bestWidget? bestWidget : thisPublic; } - static float toDevicePixels(double logicalPixels) + void styleChanged(Style &) override { - return float(logicalPixels * DENG2_BASE_GUI_APP->dpiFactor()); + deinitBlur(); + flags |= StyleChanged; + // updateStyle() will be called during the next update(). + } + + static inline float pointsToPixels(double points) + { + return float(points) * DENG2_BASE_GUI_APP->pixelRatio().value(); + } + + static inline float pixelsToPoints(double pixels) + { + return float(pixels) / DENG2_BASE_GUI_APP->pixelRatio().value(); } }; @@ -700,9 +705,14 @@ rectf.bottom() / contSize.y)); } -float GuiWidget::toDevicePixels(float logicalPixels) +float GuiWidget::pointsToPixels(float points) { - return Impl::toDevicePixels(logicalPixels); + return Impl::pointsToPixels(points); +} + +float GuiWidget::pixelsToPoints(float pixels) +{ + return Impl::pixelsToPoints(pixels); } Rectanglef GuiWidget::normalizedRect() const @@ -771,7 +781,7 @@ return d->background; } -void GuiWidget::setOpacity(float opacity, TimeDelta span, TimeDelta startDelay) +void GuiWidget::setOpacity(float opacity, TimeSpan span, TimeSpan startDelay) { d->opacity.setValue(opacity, span, startDelay); } @@ -895,7 +905,7 @@ void GuiWidget::viewResized() { - d->reinitBlur(); + d->deinitBlur(); } void GuiWidget::update() @@ -1193,14 +1203,14 @@ void GuiWidget::glMakeGeometry(GuiVertexBuilder &verts) { auto &rootWgt = root(); - float const thick = d->toDevicePixels(d->background.thickness); + float const thick = d->pointsToPixels(d->background.thickness); // Is there a solid fill? if (d->background.solidFill.w > 0) { if (d->background.type == Background::GradientFrameWithRoundedFill) { - Rectanglei const recti = rule().recti().shrunk(d->toDevicePixels(2)); + Rectanglei const recti = rule().recti().shrunk(d->pointsToPixels(2)); verts.makeQuad(recti.shrunk(thick), d->background.solidFill, rootWgt.atlas().imageRectf(rootWgt.solidRoundCorners()).middle()); verts.makeFlexibleFrame(recti, thick, d->background.solidFill, @@ -1224,19 +1234,19 @@ case Background::GradientFrameWithThinBorder: if (d->background.type == Background::GradientFrameWithThinBorder) { - verts.makeFlexibleFrame(rule().recti().shrunk(d->toDevicePixels(2)), + verts.makeFlexibleFrame(rule().recti().shrunk(d->pointsToPixels(2)), thick, Vector4f(0, 0, 0, .5f), rootWgt.atlas().imageRectf(rootWgt.boldRoundCorners())); } - verts.makeFlexibleFrame(rule().recti().shrunk(d->toDevicePixels(1)), + verts.makeFlexibleFrame(rule().recti().shrunk(d->pointsToPixels(1)), thick, d->background.color, rootWgt.atlas().imageRectf(rootWgt.boldRoundCorners())); break; case Background::Rounded: - verts.makeFlexibleFrame(rule().recti().shrunk(d->toDevicePixels(d->background.thickness - 4)), + verts.makeFlexibleFrame(rule().recti().shrunk(d->pointsToPixels(d->background.thickness - 4)), thick, d->background.color, rootWgt.atlas().imageRectf(rootWgt.roundCorners())); @@ -1307,25 +1317,17 @@ } } -void GuiWidget::collectNotReadyAssets(AssetGroup &collected, Widget &widget) +void GuiWidget::collectNotReadyAssets(AssetGroup &collected, CollectMode collectMode) { - if (auto *assetGroup = maybeAs(widget)) +#if defined (DENG2_DEBUG) + if (!rule().isFullyDefined()) { - if (!assetGroup->assets().isReady()) - { - collected += *assetGroup; - - LOGDEV_XVERBOSE("Found " _E(m) "NotReady" _E(.) " asset %s (%p)", - widget.path() << &widget); - } - } - else - { - foreach (Widget *child, widget.children()) - { - collectNotReadyAssets(collected, *child); - } + qDebug() << path() << "rule rectangle not fully defined"; + qDebug("%s", rule().description().toLatin1().constData()); + qDebug("Widget layout will be undefined"); } +#endif + Widget::collectNotReadyAssets(collected, collectMode); } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/listdata.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/listdata.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/listdata.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/listdata.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -57,6 +57,15 @@ return InvalidPos; } +Data::Pos ListData::findLabel(String const &label) const +{ + for (Pos i = 0; i < size(); ++i) + { + if (at(i).label() == label) return i; + } + return InvalidPos; +} + Data::Pos ListData::findData(QVariant const &data) const { for (Pos i = 0; i < size(); ++i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/painter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/painter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/painter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/painter.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -30,11 +30,11 @@ DENG2_PIMPL(Painter), public Asset { - GLAtlasBuffer vertexBuf; ///< Per-frame allocations. - GLDrawQueue queue; - GLProgram batchProgram; - GLUniform uMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; - Rectanglef normScissorRect; + GLAtlasBuffer vertexBuf; ///< Per-frame allocations. + GLDrawQueue queue; + GLProgram batchProgram; + GLUniform uMvpMatrix{"uMvpMatrix", GLUniform::Mat4}; + Rectanglef normScissorRect; Impl(Public *i) : Base(i) @@ -74,6 +74,7 @@ { d->init(); } + d->queue.beginFrame(); } void Painter::deinit() @@ -106,19 +107,19 @@ void Painter::setNormalizedScissor(Rectanglef const &normScissorRect) { - DENG2_ASSERT(normScissorRect.left() >= 0); - DENG2_ASSERT(normScissorRect.right() <= 1); - DENG2_ASSERT(normScissorRect.top() >= 0); - DENG2_ASSERT(normScissorRect.bottom() <= 1); + d->normScissorRect = normScissorRect & Rectanglef(0, 0, 1, 1); - d->normScissorRect = normScissorRect; + DENG2_ASSERT(d->normScissorRect.left() >= 0); + DENG2_ASSERT(d->normScissorRect.right() <= 1); + DENG2_ASSERT(d->normScissorRect.top() >= 0); + DENG2_ASSERT(d->normScissorRect.bottom() <= 1); Rectangleui const vp = GLState::current().viewport(); - Rectangleui scis = Rectangleui(Vector2ui(normScissorRect.left() * vp.width(), - normScissorRect.top() * vp.height()), - Vector2ui(std::ceil(normScissorRect.right() * vp.width()), - std::ceil(normScissorRect.bottom() * vp.height()))) + Rectangleui scis = Rectangleui(Vector2ui(d->normScissorRect.left() * vp.width(), + d->normScissorRect.top() * vp.height()), + Vector2ui(std::ceil(d->normScissorRect.right() * vp.width()), + std::ceil(d->normScissorRect.bottom() * vp.height()))) .moved(vp.topLeft); scis = GLState::current().target().scaleToActiveRect(scis); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/proceduralimage.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/proceduralimage.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/proceduralimage.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/proceduralimage.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -13,22 +13,23 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/ProceduralImage" namespace de { -ProceduralImage::ProceduralImage(Size const &size) : _size(size), _color(1, 1, 1, 1) +ProceduralImage::ProceduralImage(Size const &pointSize) + : _pointSize(pointSize), _color(1, 1, 1, 1) {} ProceduralImage::~ProceduralImage() {} -ProceduralImage::Size ProceduralImage::size() const +ProceduralImage::Size ProceduralImage::pointSize() const { - return _size; + return _pointSize; } ProceduralImage::Color ProceduralImage::color() const @@ -36,9 +37,9 @@ return _color; } -void ProceduralImage::setSize(Size const &size) +void ProceduralImage::setPointSize(Size const &pointSize) { - _size = size; + _pointSize = pointSize; } void ProceduralImage::setColor(Color const &color) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/style.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/style.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/style.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/style.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -17,9 +17,11 @@ */ #include "de/Style" +#include "de/BaseGuiApp" +#include "de/GuiRootWidget" -#include #include +#include #include #include #include @@ -30,17 +32,25 @@ namespace de { DENG2_PIMPL(Style) +, DENG2_OBSERVES(Variable, Change) { - Record module; - RuleBank rules; - FontBank fonts; + Record module; + RuleBank rules; + FontBank fonts; ColorBank colors; ImageBank images; + const Package *loadedPack; - Impl(Public *i) : Base(i) + const Variable &pixelRatio = ScriptSystem::get()["DisplayMode"]["PIXEL_RATIO"]; + const Variable &uiTranslucency = Config::get("ui.translucency"); + + Impl(Public *i) + : Base(i) + , rules(DENG2_BASE_GUI_APP->pixelRatio()) { // The Style is available as a native module. App::scriptSystem().addNativeModule("Style", module); + pixelRatio.audienceForChange() += this; } void clear() @@ -51,14 +61,25 @@ images.clear(); module.clear(); + + loadedPack = nullptr; } - void load(Package const &pack) + void updateFontSizeFactor() { + float fontSize = 1.f; if (CommandLine::ArgWithParams arg = App::commandLine().check("-fontsize", 1)) { - fonts.setFontSizeFactor(arg.params.at(0).toFloat()); + fontSize = arg.params.at(0).toFloat(); } + fonts.setFontSizeFactor(fontSize); + } + + void load(Package const &pack) + { + loadedPack = &pack; + + updateFontSizeFactor(); rules .addFromInfo(pack.root().locate("rules.dei")); fonts .addFromInfo(pack.root().locate("fonts.dei")); @@ -71,8 +92,31 @@ module.add(new Variable("colors", new RecordValue(colors), Variable::AllowRecord)); module.add(new Variable("images", new RecordValue(images), Variable::AllowRecord)); } + + void variableValueChanged(Variable &, const Value &) override + { + if (loadedPack) + { + LOG_MSG("UI style being updated due to pixel ratio change"); + +#if defined (WIN32) + /* + * KLUDGE: The operating system provides fonts scaled according to the desktop + * scaling factor. The user's scaling factor affects the sizing of the fonts + * on Windows via this value; on other platforms, the font definitions use + * DisplayMode.PIXEL_RATIO directly. (Should do that on Windows, too?) + */ + updateFontSizeFactor(); +#endif + self().performUpdate(); + } + } + + DENG2_PIMPL_AUDIENCE(Change) }; +DENG2_AUDIENCE_METHOD(Style, Change) + Style::Style() : d(new Impl(this)) {} @@ -199,7 +243,7 @@ bool Style::isBlurringAllowed() const { - return true; + return d->uiTranslucency.value().isTrue(); } GuiWidget *Style::sharedBlurWidget() const @@ -207,6 +251,16 @@ return nullptr; } +void Style::performUpdate() +{ + d->fonts.reload(); + + DENG2_FOR_AUDIENCE2(Change, i) + { + i->styleChanged(*this); + } +} + static Style *theAppStyle = nullptr; Style &Style::get() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/textdrawable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/textdrawable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/textdrawable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/textdrawable.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -212,6 +212,7 @@ Font::RichFormat::IStyle const *style { nullptr }; String styledText; Font const *font { nullptr }; + float fontHeight = 0.f; int wrapWidth { 0 }; Wrapper *visibleWrap; ///< For drawing. LockableUniquePointer incoming; ///< Latest finished wrapping. @@ -334,16 +335,16 @@ if (d->styledText != styledText) { d->styledText = styledText; - d->beginWrapTask(); } } void TextDrawable::setFont(Font const &font) { - if (d->font != &font) + if (d->font != &font || !fequal(d->fontHeight, font.height().value())) { - d->font = &font; + d->font = &font; + d->fontHeight = font.height().value(); d->beginWrapTask(); // Redo the contents. } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/vr/vrconfig.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/vr/vrconfig.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/vr/vrconfig.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/vr/vrconfig.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -218,7 +218,7 @@ return radianToDegree(2.f * std::atan2(x / aspect, 1.f)); } - return horizFovDegrees / aspect; + return clamp(1.f, horizFovDegrees / aspect, 179.f); } Matrix4f VRConfig::projectionMatrix(float fovDegrees, @@ -232,7 +232,10 @@ return oculusRift().projection(nearClip, farClip) * Matrix4f::translate(oculusRift().eyeOffset() * mapUnits); } + return Matrix4f::perspective(fovDegrees, viewAspect(viewPortSize), nearClip, farClip) * + Matrix4f::translate(Vector3f(-eyeShift(), 0, 0)); +#if 0 float const yfov = verticalFieldOfView(fovDegrees, viewPortSize); float const fH = std::tan(.5f * degreeToRadian(yfov)) * nearClip; float const fW = fH * viewAspect(viewPortSize); @@ -256,6 +259,7 @@ -fH, fH, nearClip, farClip) * Matrix4f::translate(Vector3f(-eyeShift(), 0, 0)); +#endif } OculusRift &VRConfig::oculusRift() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/vrwindowtransform.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/vrwindowtransform.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/vrwindowtransform.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/vrwindowtransform.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -36,9 +36,11 @@ GLTextureFramebuffer unwarpedFB; // Row-interleaved drawing: + GLTextureFramebuffer rowInterLeftFB; GLTextureFramebuffer rowInterRightFB; Drawable rowInterDrawable; GLUniform rowInterUniformTex { "uTex", GLUniform::Sampler2D }; + GLUniform rowInterUniformTex2 { "uTex2", GLUniform::Sampler2D }; bool rowInterNeedRelease = true; Impl(Public *i) @@ -49,6 +51,7 @@ ~Impl() { vrCfg.oculusRift().deinit(); + rowInterLeftFB.glDeinit(); rowInterRightFB.glDeinit(); } @@ -69,12 +72,17 @@ float displayModeDependentUIScalingFactor() const { - if (GuiWidget::toDevicePixels(1) == 1) return 1.0f; // Not enough pixels for good-quality scaling. +#if defined (DENG_MOBILE) + return 1.0f; +#else + if (GuiWidget::pointsToPixels(1) == 1) return 1.0f; // Not enough pixels for good-quality scaling. // Since the UI style doesn't yet support scaling at runtime based on // display resolution (or any other factor). - return 1.f / Rangef(.5f, 1.0f).clamp((width() - GuiWidget::toDevicePixels(256.f)) / - GuiWidget::toDevicePixels(768.f)); + return 1.f / Rangef(.5f, 1.0f) + .clamp((width()) / + GuiWidget::pointsToPixels(640.f)); +#endif } void drawContent() const @@ -105,8 +113,7 @@ // Set render target to offscreen temporarily. GLState::push() .setTarget(unwarpedFB) - .setViewport(Rectangleui::fromSize(unwarpedFB.size())) - .apply(); + .setViewport(Rectangleui::fromSize(unwarpedFB.size())); unwarpedFB.unsetActiveRect(true); GLTextureFramebuffer::Size const fbSize = unwarpedFB.size(); @@ -129,7 +136,7 @@ } unwarpedFB.unsetActiveRect(true); - GLState::pop().apply(); + GLState::pop(); vrCfg.enableFrustumShift(); // restore default } @@ -147,21 +154,24 @@ typedef GLBufferT VBuf; VBuf *buf = new VBuf; rowInterDrawable.addBuffer(buf); - rowInterDrawable.program().build(// Vertex shader: - Block("attribute highp vec4 aVertex; " - "attribute highp vec2 aUV; " - "varying highp vec2 vUV; " - "void main(void) {" - "gl_Position = aVertex; " - "vUV = aUV; }"), - // Fragment shader: - Block("uniform sampler2D uTex; " - "varying highp vec2 vUV; " - "void main(void) { " - "if(int(mod(gl_FragCoord.y - 1023.5, 2.0)) != 1) { discard; }\n" - "gl_FragColor = texture2D(uTex, vUV); }")) - << rowInterUniformTex; - buf->setVertices(gl::TriangleStrip, + rowInterDrawable.program().build( // Vertex shader: + Block("in highp vec4 aVertex; " + "in highp vec2 aUV; " + "out highp vec2 vUV; " + "void main(void) {" + "gl_Position = aVertex; " + "vUV = aUV; }"), + // Fragment shader: + Block("uniform sampler2D uTex; " + "uniform sampler2D uTex2; " + "in highp vec2 vUV; " + "void main(void) { " + //"if (int(mod(gl_FragCoord.y - 1023.5, 2.0)) != 1) { discard; }\n" + //"if ((int(gl_FragCoord.y) & 1) == 0) { discard; }" + "out_FragColor = ((int(gl_FragCoord.y) & 1) == 0 ? texture(uTex, vUV) :" + "texture(uTex2, vUV)); }")) + << rowInterUniformTex << rowInterUniformTex2; + buf->setVertices(gl::TriangleStrip, VBuf::Builder().makeQuad(Rectanglef(-1, -1, 2, 2), Rectanglef(0, 0, 1, 1)), gl::Static); } @@ -244,25 +254,25 @@ case VRConfig::GreenMagenta: // Left eye view vrCfg.setCurrentEye(VRConfig::LeftEye); - GLState::push().setColorMask(gl::WriteGreen | gl::WriteAlpha).apply(); // Left eye view green + GLState::push().setColorMask(gl::WriteGreen | gl::WriteAlpha); // Left eye view green drawContent(); // Right eye view vrCfg.setCurrentEye(VRConfig::RightEye); - GLState::current().setColorMask(gl::WriteRed | gl::WriteBlue | gl::WriteAlpha).apply(); // Right eye view magenta + GLState::current().setColorMask(gl::WriteRed | gl::WriteBlue | gl::WriteAlpha); // Right eye view magenta drawContent(); - GLState::pop().apply(); + GLState::pop(); break; case VRConfig::RedCyan: // Left eye view vrCfg.setCurrentEye(VRConfig::LeftEye); - GLState::push().setColorMask(gl::WriteRed | gl::WriteAlpha).apply(); // Left eye view red + GLState::push().setColorMask(gl::WriteRed | gl::WriteAlpha); // Left eye view red drawContent(); // Right eye view vrCfg.setCurrentEye(VRConfig::RightEye); - GLState::current().setColorMask(gl::WriteGreen | gl::WriteBlue | gl::WriteAlpha).apply(); // Right eye view cyan + GLState::current().setColorMask(gl::WriteGreen | gl::WriteBlue | gl::WriteAlpha); // Right eye view cyan drawContent(); - GLState::pop().apply(); + GLState::pop(); break; case VRConfig::QuadBuffered: @@ -288,34 +298,45 @@ break; case VRConfig::RowInterleaved: { +#if !defined (DENG_MOBILE) // Use absolute screen position of window to determine whether the // first scan line is odd or even. QPoint ulCorner(0, 0); ulCorner = self().window().mapToGlobal(ulCorner); // widget to screen coordinates - bool const rowParityIsEven = ((ulCorner.y() % 2) == 0); + bool const rowParityIsEven = ((int(ulCorner.y()) % 2) == 0); - // Draw left eye view directly to the screen + rowInterNeedRelease = false; + + // Draw the left eye view. + rowInterLeftFB.glInit(); + rowInterLeftFB.resize(GLFramebuffer::Size(width(), height())); + rowInterLeftFB.colorTexture().setFilter(gl::Linear, gl::Linear, gl::MipNone); + rowInterLeftFB.colorTexture().glApplyParameters(); + GLState::push() + .setTarget(rowInterLeftFB) + .setViewport(Rectangleui::fromSize(rowInterLeftFB.size())); vrCfg.setCurrentEye(rowParityIsEven? VRConfig::LeftEye : VRConfig::RightEye); drawContent(); + GLState::pop(); - // Draw right eye view to FBO - rowInterNeedRelease = false; + // Draw right the eye view. rowInterRightFB.glInit(); rowInterRightFB.resize(GLFramebuffer::Size(width(), height())); rowInterRightFB.colorTexture().setFilter(gl::Linear, gl::Linear, gl::MipNone); rowInterRightFB.colorTexture().glApplyParameters(); GLState::push() .setTarget(rowInterRightFB) - .setViewport(Rectangleui::fromSize(rowInterRightFB.size())) - .apply(); + .setViewport(Rectangleui::fromSize(rowInterRightFB.size())); vrCfg.setCurrentEye(rowParityIsEven ? VRConfig::RightEye : VRConfig::LeftEye); drawContent(); - GLState::pop().apply(); + GLState::pop(); // Draw right eye view to the screen from FBO color texture vrInitRowInterleaved(); - rowInterUniformTex = rowInterRightFB.colorTexture(); + rowInterUniformTex = rowInterLeftFB.colorTexture(); + rowInterUniformTex2 = rowInterRightFB.colorTexture(); rowInterDrawable.draw(); +#endif break; } @@ -373,7 +394,7 @@ // Adjust effective UI size for stereoscopic rendering. size.x = size.y * d->vrCfg.oculusRift().aspect(); //size.y *= d->vrCfg.oculusRift().aspect(); - size *= GuiWidget::toDevicePixels(1) * .75f; + size *= GuiWidget::pointsToPixels(1) * .75f; break; // Allow UI to squish in top/bottom and SBS mode: 3D hardware will unsquish them diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/buttonwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/buttonwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/buttonwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/buttonwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -29,16 +29,16 @@ DENG_GUI_PIMPL(ButtonWidget), DENG2_OBSERVES(Action, Triggered) { - State state = Up; + State state { Up }; DotPath bgColorId { "background" }; DotPath borderColorId { "text" }; - HoverColorMode hoverColorMode = ReplaceColor; - ColorTheme colorTheme = Normal; - Background::Type bgType = Background::GradientFrame; - Action *action = nullptr; + HoverColorMode hoverColorMode { ReplaceColor }; + ColorTheme colorTheme { Normal }; + Background::Type bgType { Background::GradientFrame }; + Action *action { nullptr }; Animation scale { 1.f }; Animation frameOpacity { .08f, Animation::Linear }; - bool animating = false; + bool animating { false }; DotPath hoverTextColor; DotPath originalTextColor; Vector4f originalTextModColor; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/choicewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/choicewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/choicewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/choicewidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -56,14 +56,16 @@ }; PopupMenuWidget *choices; - IndirectRule *maxWidth; - Data::Pos selected; ///< One item is always selected. - String noSelectionHint; + IndirectRule * maxWidth; + Data::Pos selected; ///< One item is always selected. + String noSelectionHint; Impl(Public *i) : Base(i), selected(Data::InvalidPos) { maxWidth = new IndirectRule; + self().setMaximumTextWidth(rule("choice.item.width.max")); + self().setTextLineAlignment(ui::AlignLeft); self().setFont("choice.selected"); choices = new PopupMenuWidget; @@ -102,7 +104,11 @@ void widgetCreatedForItem(GuiWidget &widget, ui::Item const &item) { - if (ButtonWidget *but = maybeAs(widget)) + if (auto *label = maybeAs(widget)) + { + label->setMaximumTextWidth(rule("choice.item.width.max")); + } + if (auto *but = maybeAs(widget)) { // Make sure the created buttons have an action that updates the // selected item. @@ -131,7 +137,8 @@ esc.parse(items().at(i).label()); widest = de::max(widest, font.advanceWidth(esc.plainText())); } - maxWidth->setSource(Const(widest) + self().margins().width()); + maxWidth->setSource(OperatorRule::minimum(rule("choice.item.width.max"), + Const(widest) + self().margins().width())); } Data const &items() const @@ -235,12 +242,9 @@ void ChoiceWidget::setSelected(Data::Pos pos) { - if (d->selected != pos) - { - d->selected = pos; - d->updateButtonWithSelection(); - d->updateItemHighlight(); - } + d->selected = pos; + d->updateButtonWithSelection(); + d->updateItemHighlight(); } bool ChoiceWidget::isValidSelection() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/commandwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/commandwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/commandwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/commandwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -18,6 +18,7 @@ #include "de/CommandWidget" #include "de/DocumentPopupWidget" +#include "de/PersistentState" #include "de/Style" #include @@ -28,14 +29,14 @@ DENG_GUI_PIMPL(CommandWidget) { shell::EditorHistory history; - DocumentPopupWidget *popup; ///< Popup for autocompletions. - bool allowReshow; ///< Contents must still be valid. + DocumentPopupWidget *popup; ///< Popup for autocompletions. + bool allowReshow; ///< Contents must still be valid. Impl(Public *i) : Base(i), history(i), allowReshow(false) { // Popup for autocompletions. popup = new DocumentPopupWidget; - popup->document().setMaximumLineWidth(640); + popup->document().setMaximumLineWidth(rule("editor.completion.linewidth")); popup->document().setScrollBarColor("inverted.accent"); // Height for the content: depends on the document height (plus margins), but at @@ -145,6 +146,19 @@ return false; } +void CommandWidget::operator >> (PersistentState &toState) const +{ + int const MAX_PERSISTENT_HISTORY = 200; + toState.objectNamespace().set(name().concatenateMember("history"), + new ArrayValue(d->history.fullHistory(MAX_PERSISTENT_HISTORY))); +} + +void CommandWidget::operator << (PersistentState const &fromState) +{ + d->history.setFullHistory(fromState.objectNamespace() + .getStringList(name().concatenateMember("history"))); +} + void CommandWidget::dismissContentToHistory() { d->history.goToLatest(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/compositorwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/compositorwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/compositorwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/compositorwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -184,8 +184,6 @@ { if (!d->shouldBeDrawn()) return; - //LIBGUI_GL.glEnable(GL_TEXTURE_2D); - DENG2_ASSERT(d->nextBufIndex > 0); Impl::Buffer *buf = d->buffers[d->nextBufIndex - 1]; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/dialogwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/dialogwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/dialogwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/dialogwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -31,7 +31,7 @@ namespace de { -static TimeDelta const FLASH_ANIM_SPAN = 0.75; +static TimeSpan const FLASH_ANIM_SPAN = 0.75; /** * Compares dialog button items to determine the order in which they @@ -102,6 +102,7 @@ QScopedPointer untrapper; DialogContentStylist stylist; IndirectRule *minWidth; + Rule const *maxContentHeight = nullptr; Impl(Public *i, Flags const &dialogFlags) : Base(i) @@ -112,7 +113,7 @@ , needButtonUpdate(false) , animatingGlow(false) { - minWidth = new IndirectRule; + minWidth = new IndirectRule; // Initialize the border glow. normalGlow = style().colors().colorf("glow").w; @@ -129,7 +130,7 @@ buttons->setItems(mainButtonItems); buttons->organizer().audienceForWidgetCreation() += this; buttons->organizer().audienceForWidgetUpdate() += this; - + extraButtons = new MenuWidget("extra"); extraButtons->margins().setTop(""); extraButtons->setItems(extraButtonItems); @@ -166,26 +167,26 @@ // Will a title be included? if (flags & WithHeading) { - heading = new LabelWidget; + heading = new LabelWidget("heading"); heading->setFont("heading"); heading->margins() .setBottom("") .setTop (rule("gap") + rule("dialog.gap")) .setLeft(rule("gap") + rule("dialog.gap")); - heading->setSizePolicy(ui::Filled, ui::Expand); + heading->setSizePolicy(ui::Expand, ui::Expand); heading->setTextColor("accent"); heading->setImageColor(style().colors().colorf("accent")); - heading->setOverrideImageSize(heading->font().ascent().valuei()); + heading->setOverrideImageSize(heading->font().ascent()); heading->setTextGap("dialog.gap"); + heading->setAlignment(ui::AlignLeft); heading->setTextAlignment(ui::AlignRight); heading->setTextLineAlignment(ui::AlignLeft); heading->setFillMode(LabelWidget::FillWithText); container->add(heading); heading->rule() - .setInput(Rule::Top, self().rule().top()) - .setInput(Rule::Left, self().rule().left()) - .setInput(Rule::Right, area->rule().right()); + .setInput(Rule::Top, self().rule().top()) + .setInput(Rule::Left, self().rule().left()); area->rule().setInput(Rule::Top, heading->rule().bottom()); } @@ -223,6 +224,7 @@ ~Impl() { releaseRef(minWidth); + releaseRef(maxContentHeight); releaseRef(acceptAction); } @@ -263,6 +265,10 @@ { changeRef(maxHeight, *maxHeight - self().anchor().top() - rule("gap")); } + if (maxContentHeight) + { + changeRef(maxHeight, OperatorRule::minimum(*maxHeight, *maxContentHeight)); + } // Scrollable area content height. AutoRef areaContentHeight = area->contentRule().height() + area->margins().height(); @@ -340,7 +346,7 @@ ButtonWidget &but = widget.as(); // Button images must be a certain size. - but.setOverrideImageSize(style().fonts().font("default").height().valuei()); + but.setOverrideImageSize(style().fonts().font("default").height()); // Set default label? if (item.label().isEmpty()) @@ -438,7 +444,7 @@ { bg = self().infoStyleBackground(); } - else if (Style::get().isBlurringAllowed()) + else if (style().isBlurringAllowed()) { /// @todo Should use the Style for this. bg.type = Background::SharedBlurWithBorderGlow; @@ -460,6 +466,7 @@ d->stylist.setContainer(area()); setOpeningDirection(ui::NoDirection); d->updateBackground(); + area().enableIndicatorDraw(true); } DialogWidget::Modality DialogWidget::modality() const @@ -495,6 +502,11 @@ d->minWidth->setSource(minWidth); } +void DialogWidget::setMaximumContentHeight(const de::Rule &maxHeight) +{ + changeRef(d->maxContentHeight, maxHeight); +} + MenuWidget &DialogWidget::buttonsMenu() { return *d->buttons; @@ -532,7 +544,7 @@ { DialogButtonItem const &item = d->buttonItems.at(i).as(); - if ((item.role() & IdMask) == roleId) + if ((item.role() & IdMask) == uint(roleId)) { return &d->buttonWidget(item); } @@ -567,6 +579,11 @@ changeRef(d->acceptAction, action); } +Action *DialogWidget::acceptanceAction() const +{ + return d->acceptAction; +} + int DialogWidget::exec(GuiRootWidget &root) { d->modality = Modal; @@ -577,10 +594,30 @@ prepare(); - int result = d->subloop.exec(); + int result = 0; + try + { +#if defined (DENG_MOBILE) + // The subloop will likely access the root independently. + root.unlock(); +#endif - finish(result); + result = d->subloop.exec(); +#if defined (DENG_MOBILE) + root.lock(); +#endif + } + catch (...) + { +#if defined (DENG_MOBILE) + // The lock needs to be reacquired in any case. + root.lock(); +#endif + throw; + } + + finish(result); return result; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/directoryarraywidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/directoryarraywidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/directoryarraywidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/directoryarraywidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -20,12 +20,17 @@ #include "de/BaseGuiApp" #include "de/BaseWindow" +#include +#include #include #include +#include #include namespace de { +static String const CFG_LAST_FOLDER("resource.latestDirectory"); + DENG2_PIMPL_NOREF(DirectoryArrayWidget) {}; @@ -39,16 +44,17 @@ // Use a native dialog to select the IWAD folder. DENG2_BASE_GUI_APP->beginNativeUIMode(); - QFileDialog dlg(nullptr, - tr("Select Folder"), - ".", ""); + QFileDialog dlg(nullptr, tr("Select Folder"), + Config::get().gets(CFG_LAST_FOLDER, "."), ""); dlg.setFileMode(QFileDialog::Directory); dlg.setReadOnly(true); //dlg.setNameFilter("*.wad"); dlg.setLabelText(QFileDialog::Accept, tr("Select")); if (dlg.exec()) { - elementsMenu().items() << makeItem(TextValue(dlg.selectedFiles().at(0))); + String dir = dlg.selectedFiles().at(0); + Config::get().set(CFG_LAST_FOLDER, dir.fileNamePath()); + elementsMenu().items() << makeItem(TextValue(dir)); setVariableFromWidget(); } @@ -63,4 +69,98 @@ return NativePath(value.asText()).pretty(); } +static const String RECURSE_TOGGLE_NAME("recurse-toggle"); + +/** + * Controller that syncs state between Config.resource.recurseFolders and the toggles + * in the DirectoryArrayWidget items. Destroys itself after the item widget is deleted. + */ +struct RecurseToggler + : DENG2_OBSERVES(ToggleWidget, Toggle) + , DENG2_OBSERVES(Widget, Deletion) + , DENG2_OBSERVES(ui::Item, Change) + , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate) +{ + DirectoryArrayWidget *owner; + ToggleWidget * tog; + const ui::Item * item; + + RecurseToggler(DirectoryArrayWidget *owner, LabelWidget &element, const ui::Item &item) + : owner(owner) + , item(&item) + { + tog = &element.guiFind(RECURSE_TOGGLE_NAME)->as(); + item.audienceForChange() += this; + element.audienceForDeletion() += this; + tog->audienceForToggle() += this; + owner->elementsMenu().organizer().audienceForWidgetUpdate() += this; + } + + static Variable &recursed() + { + return Config::get("resource.recursedFolders"); + } + + TextValue key() const + { + return {item->data().toString()}; + } + + void fetch() + { + if (recursed().value().contains(key())) + { + tog->setActive(recursed().value().element(key()).isTrue()); + } + } + + void toggleStateChanged(ToggleWidget &toggle) override + { + recursed().value().setElement(key(), new NumberValue(toggle.isActive())); + emit owner->arrayChanged(); + } + + void widgetBeingDeleted(Widget &) override + { + item->audienceForChange() -= this; + // tog is already gone + trash(this); + } + + void itemChanged(const ui::Item &) override + { + fetch(); + } + + void widgetUpdatedForItem(GuiWidget &, const ui::Item &) override + { + fetch(); + } +}; + +void DirectoryArrayWidget::elementCreated(LabelWidget &element, const ui::Item &item) +{ + element.setSizePolicy(ui::Fixed, ui::Expand); + element.setAlignment(ui::AlignLeft); + element.setTextLineAlignment(ui::AlignLeft); + element.setMaximumTextWidth(rule().width()); + element.rule().setInput(Rule::Width, rule().width() - margins().width()); + + // Add a toggle for configuration recurse mode. + auto *tog = new ToggleWidget(ToggleWidget::DefaultFlags, RECURSE_TOGGLE_NAME); + element.add(tog); + tog->setText("Subdirs"); + tog->setActive(true); // recurse is on by default + tog->set(Background()); + tog->setFont("small"); + tog->margins().setLeft("unit").setRight("gap").setTop("unit").setBottom("unit"); + tog->setSizePolicy(ui::Expand, ui::Expand); + tog->rule() + .setInput(Rule::Right, element.rule().right() - rule("gap")) + .setMidAnchorY(element.rule().midY()); + element.margins().setRight(tog->rule().width() + rule("gap")); + + new RecurseToggler(this, element, item); // deletes itself +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/documentwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/documentwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/documentwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/documentwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -24,17 +24,13 @@ namespace de { -//static int const ID_BACKGROUND = 1; // does not scroll -//static int const ID_TEXT = 2; // scrolls - DENG_GUI_PIMPL(DocumentWidget), public Font::RichFormat::IStyle { - //typedef DefaultVertexBuf VertexBuf; - ProgressWidget *progress = nullptr; // Style. + DotPath colorIds[Font::RichFormat::MaxColors]; ColorBank::Color normalColor; ColorBank::Color highlightColor; ColorBank::Color dimmedColor; @@ -43,7 +39,7 @@ // State. ui::SizePolicy widthPolicy = ui::Expand; - int maxLineWidth; + const Rule *maxLineWidth = nullptr; ConstantRule *contentMaxWidth = new ConstantRule(0); int oldScrollY = 0; String styledText; @@ -51,20 +47,22 @@ // GL objects. TextDrawable glText; - //Drawable drawable; - //Matrix4f modelMatrix; - //GLState clippedTextState; - //GLUniform uMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; - //GLUniform uScrollMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; - //GLUniform uColor { "uColor", GLUniform::Vec4 }; GuiVertexBuilder bgVerts; GuiVertexBuilder textVerts; Matrix4f scrollMvpMatrix; Impl(Public *i) : Base(i) { + colorIds[Font::RichFormat::NormalColor] = "document.normal"; + colorIds[Font::RichFormat::HighlightColor] = "document.highlight"; + colorIds[Font::RichFormat::DimmedColor] = "document.dimmed"; + colorIds[Font::RichFormat::AccentColor] = "document.accent"; + colorIds[Font::RichFormat::DimAccentColor] = "document.dimaccent"; + updateStyle(); + maxLineWidth = holdRef(rule("document.line.width")); + // Widget to show while lines are being wrapped. progress = new ProgressWidget("progress-indicator"); progress->setColor("progress.dark.wheel"); @@ -72,24 +70,23 @@ progress->rule().setRect(self().rule()); progress->hide(); self().add(progress); - - maxLineWidth = GuiWidget::toDevicePixels(1000); } ~Impl() { releaseRef(contentMaxWidth); + releaseRef(maxLineWidth); } void updateStyle() { Style const &st = style(); - normalColor = st.colors().color("document.normal"); - highlightColor = st.colors().color("document.highlight"); - dimmedColor = st.colors().color("document.dimmed"); - accentColor = st.colors().color("document.accent"); - dimAccentColor = st.colors().color("document.dimaccent"); + normalColor = st.colors().color(colorIds[Font::RichFormat::NormalColor]); + highlightColor = st.colors().color(colorIds[Font::RichFormat::HighlightColor]); + dimmedColor = st.colors().color(colorIds[Font::RichFormat::DimmedColor]); + accentColor = st.colors().color(colorIds[Font::RichFormat::AccentColor]); + dimAccentColor = st.colors().color(colorIds[Font::RichFormat::DimAccentColor]); glText.setFont(self().font()); self().requestGeometry(); @@ -142,24 +139,12 @@ glText.init(atlas(), self().font(), this); self().setIndicatorUv(atlas().imageRectf(root().solidWhitePixel()).middle()); - - /*drawable.addBuffer(ID_BACKGROUND, new VertexBuf); - drawable.addBuffer(ID_TEXT, new VertexBuf); - - shaders().build(drawable.program(), "generic.textured.color_ucolor") - << uMvpMatrix << uColor << uAtlas(); - - shaders().build(drawable.addProgram(ID_TEXT), "generic.textured.color_ucolor") - << uScrollMvpMatrix << uColor << uAtlas(); - drawable.setProgram(ID_TEXT, drawable.program(ID_TEXT)); - drawable.setState(ID_TEXT, clippedTextState);*/ } void glDeinit() { atlas().audienceForReposition() -= this; glText.deinit(); - //drawable.clear(); bgVerts.clear(); textVerts.clear(); } @@ -190,7 +175,7 @@ int wrapWidth; if (widthPolicy == ui::Expand) { - wrapWidth = maxLineWidth; + wrapWidth = maxLineWidth->valuei(); } else { @@ -214,12 +199,7 @@ // Background and scroll indicator. bgVerts.clear(); - //VertexBuf::Builder verts; self().glMakeGeometry(bgVerts); - /*drawable.buffer(ID_BACKGROUND) - .setVertices(gl::TriangleStrip, verts, self().isScrolling()? gl::Dynamic : gl::Static);*/ - - //uMvpMatrix = root().projMatrix2D(); if (!progress->isVisible()) { @@ -239,10 +219,8 @@ glText.setRange(visRange); glText.update(); // alloc visible lines - //VertexBuf::Builder verts; textVerts.clear(); glText.makeVertices(textVerts, Vector2i(0, 0), ui::AlignLeft); - //drawable.buffer(ID_TEXT).setVertices(gl::TriangleStrip, verts, gl::Static); // Update content size to match the generated vertices exactly. self().setContentWidth(glText.verticesMaxWidth()); @@ -261,8 +239,6 @@ { updateGeometry(); - //painter.flush(); - Vector4f const color = Vector4f(1, 1, 1, self().visibleOpacity()); auto &painter = root().painter(); @@ -278,18 +254,11 @@ // Update the scissor for the text. auto const oldClip = painter.normalizedScissor(); painter.setNormalizedScissor(oldClip & self().normalizedContentRect()); - //GLState::push() - //clippedTextState = GLState::current(); - /*clippedTextState.setNormalizedScissor(self().normalizedContentRect());*/ - - //drawable.draw(); painter.setColor(color); painter.drawTriangleStrip(textVerts); painter.setNormalizedScissor(oldClip); painter.setModelViewProjection(root().projMatrix2D()); } - - //GLState::pop(); } }; @@ -309,10 +278,6 @@ { // Show the progress indicator until the text is ready for drawing. d->textVerts.clear(); - /*if (d->drawable.hasBuffer(ID_TEXT)) - { - d->drawable.buffer(ID_TEXT).clear(); - }*/ d->progress->show(); @@ -351,18 +316,32 @@ requestGeometry(); } -void DocumentWidget::setMaximumLineWidth(int maxWidth) +void DocumentWidget::setMaximumLineWidth(const Rule &maxWidth) { - d->maxLineWidth = maxWidth; + changeRef(d->maxLineWidth, maxWidth); d->contentMaxWidth->set(0); requestGeometry(); } +void DocumentWidget::setStyleColor(Font::RichFormat::Color id, DotPath const &colorName) +{ + DENG2_ASSERT(id != Font::RichFormat::AltAccentColor); // FIXME: not implemented! + + if (id >= 0 && id < Font::RichFormat::MaxColors) + { + d->colorIds[id] = colorName; + updateStyle(); + } +} + +ProgressWidget &DocumentWidget::progress() +{ + return *d->progress; +} + void DocumentWidget::viewResized() { ScrollAreaWidget::viewResized(); - - //d->uMvpMatrix = root().projMatrix2D(); requestGeometry(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/fadetoblackwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/fadetoblackwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/fadetoblackwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/fadetoblackwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -22,7 +22,7 @@ DENG2_PIMPL_NOREF(FadeToBlackWidget) { - TimeDelta span = 1; + TimeSpan span = 1; bool started = false; }; @@ -31,21 +31,21 @@ set(Background(Vector4f(0, 0, 0, 1))); } -void FadeToBlackWidget::initFadeFromBlack(TimeDelta const &span) +void FadeToBlackWidget::initFadeFromBlack(TimeSpan const &span) { setOpacity(1); d->span = span; d->started = false; } -void FadeToBlackWidget::initFadeToBlack(TimeDelta const &span) +void FadeToBlackWidget::initFadeToBlack(TimeSpan const &span) { setOpacity(0); d->span = span; d->started = false; } -void FadeToBlackWidget::start(TimeDelta const &delay) +void FadeToBlackWidget::start(TimeSpan const &delay) { d->started = true; setOpacity(fequal(opacity().target(), 1)? 0 : 1, d->span, delay); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/focuswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/focuswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/focuswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/focuswidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -22,7 +22,7 @@ namespace de { -static TimeDelta FLASH_SPAN = .5; +static TimeSpan FLASH_SPAN = .5; DENG2_PIMPL(FocusWidget) { @@ -96,6 +96,11 @@ d->fadeOpacity = 0.f; } +bool FocusWidget::isKeyboardFocusActive() const +{ + return d->fadeOpacity > 0 && d->reference; +} + void FocusWidget::update() { setOpacity(d->fadeOpacity * (d->reference? d->reference->visibleOpacity() : 0.f)); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/foldpanelwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/foldpanelwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/foldpanelwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/foldpanelwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -25,7 +25,7 @@ using namespace ui; -static TimeDelta const INDICATOR_ANIM_SPAN = 0.6; +static TimeSpan const INDICATOR_ANIM_SPAN = 0.4; DENG2_PIMPL_NOREF(FoldPanelWidget) { @@ -53,7 +53,7 @@ bool changed = animating; float target = (fold.isOpen()? 0 : 90); - if (target != angle.target()) + if (!fequal(target, angle.target())) { angle.setValue(target, INDICATOR_ANIM_SPAN); animating = true; @@ -65,8 +65,8 @@ needSize = false; changed = true; - float h = fold.title().font().height().value(); - setSize(Vector2f(h, h)); + const float h = pixelsToPoints(fold.title().font().height().value()); + setPointSize({h, h}); } // Stop animating? @@ -112,7 +112,7 @@ ButtonWidget *FoldPanelWidget::makeTitle(String const &text) { - d->title.reset(new ButtonWidget); + d->title.reset(new ButtonWidget("fold-title")); d->title->setSizePolicy(Expand, Expand); d->title->setText(text); @@ -164,6 +164,24 @@ return PanelWidget::content(); } +FoldPanelWidget *FoldPanelWidget::makeOptionsGroup(const String &name, const String &heading, + GuiWidget *parent) +{ + auto *fold = new FoldPanelWidget(name); + parent->add(fold->makeTitle(heading)); + parent->add(fold); + fold->title().setSizePolicy(ui::Fixed, ui::Expand); + fold->title().setFont("separator.label"); + fold->title().margins().setTop("gap"); +// fold->title().set(Background(Vector4f(1, 0, 1, .5f))); + fold->title().setImageAlignment(ui::AlignRight); + fold->title().rule() + .setInput(Rule::Left, fold->rule().left()) + .setInput(Rule::Bottom, fold->rule().top()) + .setInput(Rule::Width, fold->rule().width()); + return fold; +} + void FoldPanelWidget::toggleFold() { if (!isOpen()) @@ -182,7 +200,7 @@ { // Insert the content back into the panel. PanelWidget::setContent(d->container); - d->container = 0; + d->container = nullptr; } if (d->title) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/gridpopupwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/gridpopupwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/gridpopupwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/gridpopupwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -33,6 +33,7 @@ : PopupWidget(name), d(new Impl) { setOpeningDirection(ui::Up); + setOutlineColor("popup.outline"); d->container = new GuiWidget; setContent(d->container); @@ -54,22 +55,22 @@ LabelWidget &GridPopupWidget::addSeparatorLabel(String const &labelText) { - auto *label = LabelWidget::newWithText(_E(D) + labelText, d->container); - label->setFont("separator.label"); - label->margins().setTop("gap"); - d->layout.setCellAlignment(Vector2i(0, d->layout.gridSize().y), ui::AlignLeft); - d->layout.append(*label, 2); - return *label; +// auto *label = LabelWidget::newWithText(_E(D) + labelText, d->container); +// label->setFont("separator.label"); +// label->margins().setTop("gap"); +// d->layout.setCellAlignment(Vector2i(0, d->layout.gridSize().y), ui::AlignLeft); +// d->layout.append(*label, 2); + return *LabelWidget::appendSeparatorWithText(labelText, d->container, &d->layout); } -GridPopupWidget &GridPopupWidget::operator << (GuiWidget *widget) +GridPopupWidget &GridPopupWidget::operator<<(GuiWidget *widget) { d->container->add(widget); d->layout << *widget; return *this; } -GridPopupWidget &GridPopupWidget::operator << (Rule const &rule) +GridPopupWidget &GridPopupWidget::operator<<(Rule const &rule) { d->layout << rule; return *this; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/labelwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/labelwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/labelwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/labelwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -21,9 +21,10 @@ #include "de/AtlasProceduralImage" #include "de/StyleProceduralImage" -#include #include #include +#include +#include namespace de { @@ -45,7 +46,8 @@ TextShadow textShadow = NoShadow; DotPath textShadowColorId { "label.shadow" }; ContentFit imageFit; - Vector2f overrideImageSize; + const Rule *overrideImageWidth = nullptr; + const Rule *overrideImageHeight = nullptr; float imageScale; Vector4f imageColor; Vector4f textGLColor; @@ -58,7 +60,7 @@ Rule const *outHeight; AnimationRule *appearSize; LabelWidget::AppearanceAnimation appearType; - TimeDelta appearSpan; + TimeSpan appearSpan; // Style. DotPath gapId; @@ -74,7 +76,6 @@ String styledText; TextDrawable glText; mutable Vector2ui latestTextSize; - //bool wasVisible; std::unique_ptr image; std::unique_ptr overlayImage; @@ -100,7 +101,6 @@ , gapId ("label.gap") , shaderId ("generic.textured.color_ucolor") , richStyle (0) - //, wasVisible (true) { width = new ConstantRule(0); height = new ConstantRule(0); @@ -121,11 +121,13 @@ releaseRef(outHeight); releaseRef(appearSize); releaseRef(maxTextWidth); + releaseRef(overrideImageWidth); + releaseRef(overrideImageHeight); } void updateStyle() { - Style const &st = self().style(); + const Style &st = style(); gap = rule(gapId).valuei(); @@ -226,7 +228,7 @@ bool hasImage() const { - return image && image->size() != ProceduralImage::Size(0, 0); + return image && image->pointSize() != ProceduralImage::Size(0, 0); } bool hasText() const @@ -236,15 +238,16 @@ Vector2f imageSize() const { - Vector2f size = image? image->size() : Vector2f(); + Vector2f size = image ? pointsToPixels(image->pointSize()) : Vector2f(); + // Override components separately. - if (overrideImageSize.x > 0) + if (overrideImageWidth) { - size.x = overrideImageSize.x; + size.x = overrideImageWidth->value(); } - if (overrideImageSize.y > 0) + if (overrideImageHeight) { - size.y = overrideImageSize.y; + size.y = overrideImageHeight->value(); } return size; } @@ -505,12 +508,15 @@ // Update the image on the atlas. if (image && image->update()) { + updateSize(); self().requestGeometry(); } if (overlayImage && overlayImage->update()) { + updateSize(); self().requestGeometry(); } + glText.setLineWrapWidth(availableTextWidth()); if (glText.update()) { @@ -618,6 +624,8 @@ void LabelWidget::setImage(ProceduralImage *procImage) { d->image.reset(procImage); + d->updateSize(); + requestGeometry(); } void LabelWidget::setStyleImage(DotPath const &id, String const &heightFromFont) @@ -627,7 +635,7 @@ setImage(new StyleProceduralImage(id, *this)); if (!heightFromFont.isEmpty()) { - setOverrideImageSize(style().fonts().font(heightFromFont).height().value()); + setOverrideImageSize(style().fonts().font(heightFromFont).height()); } } } @@ -728,6 +736,18 @@ d->imageFit = fit; } +void LabelWidget::setOverrideImageSize(const Rule &width, const Rule &height) +{ + changeRef(d->overrideImageWidth, width); + changeRef(d->overrideImageHeight, height); +} + +RulePair LabelWidget::overrideImageSize() const +{ + return {d->overrideImageWidth ? *d->overrideImageWidth : ConstantRule::zero(), + d->overrideImageHeight ? *d->overrideImageHeight : ConstantRule::zero()}; +} + void LabelWidget::setMaximumTextWidth(int pixels) { setMaximumTextWidth(Const(pixels)); @@ -749,21 +769,6 @@ d->richStyle = richStyle; } -void LabelWidget::setOverrideImageSize(Vector2f const &size) -{ - d->overrideImageSize = size; -} - -Vector2f LabelWidget::overrideImageSize() const -{ - return d->overrideImageSize; -} - -void LabelWidget::setOverrideImageSize(float widthAndHeight) -{ - d->overrideImageSize = Vector2f(widthAndHeight, widthAndHeight); -} - void LabelWidget::setImageScale(float scaleFactor) { d->imageScale = scaleFactor; @@ -836,7 +841,7 @@ { Rectanglef textBox = Rectanglef::fromSize(textSize()); ui::applyAlignment(d->lineAlign, textBox, layout.text); - int const boxSize = toDevicePixels(114); + int const boxSize = pointsToPixels(114); Vector2f const off(0, textBox.height() * .08f); Vector2f const hoff(textBox.height()/2, 0); verts.makeFlexibleFrame(Rectanglef(textBox.midLeft() + hoff + off, @@ -852,7 +857,7 @@ if (d->overlayImage) { - Rectanglef rect = Rectanglef::fromSize(d->overlayImage->size()); + Rectanglef rect = Rectanglef::fromSize(pointsToPixels(d->overlayImage->pointSize())); applyAlignment(d->overlayAlign, rect, contentRect()); d->overlayImage->glMakeGeometry(verts, rect); } @@ -868,12 +873,6 @@ return false; } -/*void LabelWidget::viewResized() -{ - GuiWidget::viewResized(); - updateModelViewProjection(d->uMvpMatrix); -}*/ - void LabelWidget::setWidthPolicy(SizePolicy policy) { d->horizPolicy = policy; @@ -900,7 +899,7 @@ } } -void LabelWidget::setAppearanceAnimation(AppearanceAnimation method, TimeDelta const &span) +void LabelWidget::setAppearanceAnimation(AppearanceAnimation method, TimeSpan const &span) { d->appearType = method; d->appearSpan = span; @@ -915,10 +914,10 @@ } } -LabelWidget *LabelWidget::newWithText(String const &label, GuiWidget *parent) +LabelWidget *LabelWidget::newWithText(const String &text, GuiWidget *parent) { LabelWidget *w = new LabelWidget; - w->setText(label); + w->setText(text); if (parent) { parent->add(w); @@ -926,4 +925,19 @@ return w; } +LabelWidget *LabelWidget::appendSeparatorWithText(const String &text, GuiWidget *parent, + GridLayout *appendToGrid) +{ + std::unique_ptr w(newWithText(text, parent)); + w->setTextColor("accent"); + w->setFont("separator.label"); + w->margins().setTop("gap"); + if (appendToGrid) + { + appendToGrid->setCellAlignment(Vector2i(0, appendToGrid->gridSize().y), ui::AlignLeft); + appendToGrid->append(*w, 2); + } + return w.release(); +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/lineeditwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/lineeditwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/lineeditwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/lineeditwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -28,11 +28,16 @@ #include #include +#if defined (DENG_MOBILE) +# include +# include +#endif + namespace de { using namespace ui; -static TimeDelta const HEIGHT_ANIM_SPAN = .5f; +static TimeSpan const HEIGHT_ANIM_SPAN = .5f; static duint const ID_BUF_TEXT = 1; static duint const ID_BUF_CURSOR = 2; @@ -100,6 +105,7 @@ wraps.setFont(*font); wraps.clear(); composer.setWrapping(wraps); + composer.forceUpdate(); contentChanged(false); } @@ -293,8 +299,8 @@ Vector2i const cp = d->wraps.charTopLeftInPixels(cursorPos.y, cursorPos.x) + contentRect().topLeft; - return Rectanglei(cp + toDevicePixels(Vector2i(-1, 0)), - cp + Vector2i(toDevicePixels(1), d->font->height().valuei())); + return Rectanglei(cp + pointsToPixels(Vector2i(-1, 0)), + cp + Vector2i(pointsToPixels(1), d->font->height().valuei())); } void LineEditWidget::setColorTheme(ColorTheme theme) @@ -341,7 +347,7 @@ Vector2i const startPos = linePos(comp.start); Vector2i const endPos = linePos(comp.end); - Vector2i const offset = contentRect.topLeft + Vector2i(0, d->font->ascent().valuei() + toDevicePixels(2)); + Vector2i const offset = contentRect.topLeft + Vector2i(0, d->font->ascent().valuei() + pointsToPixels(2)); // It may span multiple lines. for (int i = startPos.y; i <= endPos.y; ++i) @@ -350,7 +356,7 @@ Vector2i start = d->wraps.charTopLeftInPixels(i, i == startPos.y? startPos.x : span.start) + offset; Vector2i end = d->wraps.charTopLeftInPixels(i, i == endPos.y? endPos.x : span.end) + offset; - verts.makeQuad(Rectanglef(start, end + toDevicePixels(Vector2i(0, 1))), + verts.makeQuad(Rectanglef(start, end + pointsToPixels(Vector2i(0, 1))), Vector4f(1, 1, 1, 1), solidWhiteUv.middle()); } } @@ -377,10 +383,30 @@ { d->hint->setOpacity(0); } + +#if defined (DENG_MOBILE) + { + auto &win = root().window(); + emit win.textEntryRequest(); + + // Text entry happens via OS virtual keyboard. + connect(&win, &GLWindow::userEnteredText, this, &LineEditWidget::userEnteredText); + connect(&win, &GLWindow::userFinishedTextEntry, this, &LineEditWidget::userFinishedTextEntry); + } +#endif } void LineEditWidget::focusLost() { +#if defined (DENG_MOBILE) + { + auto &win = root().window(); + disconnect(&win, &GLWindow::userEnteredText, this, &LineEditWidget::userEnteredText); + disconnect(&win, &GLWindow::userFinishedTextEntry, this, &LineEditWidget::userFinishedTextEntry); + emit win.textEntryDismiss(); + } +#endif + d->contentChanged(false /* don't notify */); if (d->hint && d->showingHint()) @@ -389,6 +415,18 @@ } } +#if defined (DENG_MOBILE) +void LineEditWidget::userEnteredText(QString text) +{ + setText(text); +} + +void LineEditWidget::userFinishedTextEntry() +{ + root().popFocus(); +} +#endif + void LineEditWidget::update() { GuiWidget::update(); @@ -457,6 +495,11 @@ } } + if (is(event) && event.as().qtKey() == Qt::Key_Enter) + { + qDebug() << "LineEditWidget: Enter key" << event.type() << hasFocus(); + } + // Only handle keys when focused. if (hasFocus() && event.isKeyDown()) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/menuwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -159,6 +159,14 @@ setWidget(_item.makeWidget(), _item.openingDirection()); _widget->setDeleteAfterDismissed(true); + if (_item.semantics().testFlag(Item::ClosesParentPopup)) + { + // PopupMenuWidget has a MenuWidget as content. + if (auto *selfPopup = maybeAs(d->self().parentGuiWidget())) + { + QObject::connect(_widget.get(), SIGNAL(closed()), selfPopup, SLOT(close())); + } + } SubAction::trigger(); } @@ -712,4 +720,10 @@ } } +void MenuWidget::updateStyle() +{ + ScrollAreaWidget::updateStyle(); + updateLayout(); +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/notificationareawidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/notificationareawidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/notificationareawidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/notificationareawidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -32,7 +32,7 @@ DENG_GUI_PIMPL(NotificationAreaWidget) , DENG2_OBSERVES(Widget, Deletion) { - static TimeDelta const ANIM_SPAN; + static TimeSpan const ANIM_SPAN; AnimationRule *shift; QMap shown; @@ -91,7 +91,7 @@ self().show(); } - void hide(TimeDelta const &span = ANIM_SPAN) + void hide(TimeSpan const &span = ANIM_SPAN) { shift->set(self().rule().height() + rule("gap"), span); shift->setStyle(Animation::EaseIn); @@ -147,7 +147,7 @@ } }; -TimeDelta const NotificationAreaWidget::Impl::ANIM_SPAN = 0.5; +TimeSpan const NotificationAreaWidget::Impl::ANIM_SPAN = 0.5; NotificationAreaWidget::NotificationAreaWidget(String const &name) : GuiWidget(name) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/panelwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/panelwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/panelwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/panelwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -30,14 +30,13 @@ namespace de { -static TimeDelta const OPENING_ANIM_SPAN = 0.4; -static TimeDelta const CLOSING_ANIM_SPAN = 0.3; +constexpr double OPENING_ANIM_SPAN = 0.3; +constexpr double OPENING_ANIM_SPAN_EASED_OUT = 0.18; +constexpr double CLOSING_ANIM_SPAN = 0.22; DENG_GUI_PIMPL(PanelWidget) , DENG2_OBSERVES(Asset, StateChange) { - //typedef DefaultVertexBuf VertexBuf; - bool waitForContentReady = true; bool eatMouseEvents = true; bool opened = false; @@ -45,13 +44,12 @@ ui::SizePolicy secondaryPolicy = ui::Expand; GuiWidget *content = nullptr; AnimationRule *openingRule; + AnimationStyle openingStyle = EasedOut; QTimer dismissTimer; std::unique_ptr pendingShow; // GL objects. GuiVertexBuilder verts; - //Drawable drawable; - //GLUniform uMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; Impl(Public *i) : Base(i) { @@ -67,16 +65,10 @@ releaseRef(openingRule); } - void glInit() - { - /*drawable.addBuffer(new VertexBuf); - shaders().build(drawable.program(), "generic.textured.color") - << uMvpMatrix << uAtlas();*/ - } + void glInit() {} void glDeinit() { - //drawable.clear(); verts.clear(); } @@ -87,15 +79,13 @@ void updateLayout() { - DENG2_ASSERT(content != 0); - // Widget's size depends on the opening animation. if (isVerticalAnimation()) { self().rule().setInput(Rule::Height, *openingRule); if (secondaryPolicy == ui::Expand) { - self().rule().setInput(Rule::Width, content->rule().width()); + self().rule().setInput(Rule::Width, content ? content->rule().width() : Const(0)); } } else @@ -103,7 +93,7 @@ self().rule().setInput(Rule::Width, *openingRule); if (secondaryPolicy == ui::Expand) { - self().rule().setInput(Rule::Height, content->rule().height()); + self().rule().setInput(Rule::Height, content ? content->rule().height() : Const(0)); } } } @@ -114,15 +104,12 @@ if (self().hasChangedPlace(pos) || self().geometryRequested()) { self().requestGeometry(false); - - //VertexBuf::Builder verts; verts.clear(); self().glMakeGeometry(verts); - //drawable.buffer().setVertices(gl::TriangleStrip, verts, gl::Static); } } - void startOpeningAnimation(TimeDelta span) + void startOpeningAnimation(TimeSpan span) { if (isVerticalAnimation()) { @@ -132,10 +119,16 @@ { openingRule->set(content->rule().width(), span); } - openingRule->setStyle(Animation::Bounce, 12); + + switch (openingStyle) + { + case Bouncy: openingRule->setStyle(Animation::Bounce, 12); break; + case EasedOut: openingRule->setStyle(Animation::EaseOutSofter); break; + case Smooth: openingRule->setStyle(Animation::EaseBoth); break; + } } - void close(TimeDelta delay) + void close(TimeSpan delay) { if (!opened) return; @@ -145,7 +138,16 @@ // Begin the closing animation. openingRule->set(0, CLOSING_ANIM_SPAN + delay, delay); - openingRule->setStyle(Animation::EaseIn); + switch (openingStyle) + { + case Bouncy: + case EasedOut: + openingRule->setStyle(Animation::EaseIn); + break; + case Smooth: + openingRule->setStyle(Animation::EaseBoth); + break; + } self().panelClosing(); @@ -157,7 +159,7 @@ emit self().closed(); dismissTimer.start(); - dismissTimer.setInterval((CLOSING_ANIM_SPAN + delay).asMilliSeconds()); + dismissTimer.setInterval(TimeSpan(CLOSING_ANIM_SPAN + delay).asMilliSeconds()); } void waitForAssetsInContent() @@ -170,7 +172,7 @@ LOGDEV_XVERBOSE("Checking for assets that need waiting for...", ""); DENG2_ASSERT(content); - GuiWidget::collectNotReadyAssets(*pendingShow, *content); + content->collectNotReadyAssets(*pendingShow); if (pendingShow->isEmpty()) { @@ -214,6 +216,7 @@ { setBehavior(ChildHitClipping); setBehavior(ChildVisibilityClipping); + d->updateLayout(); // initial, empty layout hide(); } @@ -222,7 +225,12 @@ d->waitForContentReady = yes; } -void de::PanelWidget::setEatMouseEvents(bool yes) +void PanelWidget::setAnimationStyle(AnimationStyle style) +{ + d->openingStyle = style; +} + +void PanelWidget::setEatMouseEvents(bool yes) { d->eatMouseEvents = yes; } @@ -294,7 +302,7 @@ return !d->openingRule->animation().done(); } -void PanelWidget::close(TimeDelta delayBeforeClosing) +void PanelWidget::close(TimeSpan delayBeforeClosing) { d->close(delayBeforeClosing); } @@ -302,9 +310,6 @@ void PanelWidget::viewResized() { GuiWidget::viewResized(); - - //d->uMvpMatrix = root().projMatrix2D(); - requestGeometry(); } @@ -322,7 +327,6 @@ // Eat buttons that land on the panel. if (hitTest(mouse.pos())) { - //root().setFocus(0); return true; } } @@ -346,7 +350,8 @@ preparePanelForOpening(); // Start the opening animation. - d->startOpeningAnimation(OPENING_ANIM_SPAN); + d->startOpeningAnimation(d->openingStyle == EasedOut ? OPENING_ANIM_SPAN_EASED_OUT + : OPENING_ANIM_SPAN); d->opened = true; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/popupmenuwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/popupmenuwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/popupmenuwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/popupmenuwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -62,7 +62,7 @@ void alloc() { _id = root().solidWhitePixel(); - setSize(Vector2f(1, 1)); + setPointSize({1, 1}); } void glInit() override @@ -155,13 +155,6 @@ setButtonColors(*b); b->setSizePolicy(ui::Expand, ui::Expand); - - if (!is(b)) - { - b->setTextGap("dialog.gap"); - b->setOverrideImageSize(style().fonts().font("default").height().valuei()); - } - b->audienceForStateChange() += this; // Triggered actions close the menu. @@ -174,6 +167,15 @@ void widgetUpdatedForItem(GuiWidget &widget, ui::Item const &item) { + if (ButtonWidget *b = maybeAs(widget)) + { + if (!is(b)) + { + b->setTextGap("dialog.gap"); + b->setOverrideImageSize(style().fonts().font("default").height()); + } + } + if (item.semantics().testFlag(ui::Item::Annotation)) { if (!App::config().getb(VAR_SHOW_ANNOTATIONS)) @@ -223,6 +225,7 @@ void updateItemHitRules() { GridLayout const &layout = self().menu().layout(); + AutoRef halfUnit = self().rule("halfunit"); foreach (GuiWidget *widget, self().menu().childWidgets()) { @@ -234,10 +237,12 @@ // We want items to be hittable throughout the width of the menu, however // restrict this to the item's column if there are multiple columns. widget->hitRule() - .setInput(Rule::Left, (!cell.x? self().rule().left() : - layout.columnLeft(cell.x))) - .setInput(Rule::Right, (cell.x == layout.gridSize().x - 1? self().rule().right() : - layout.columnRight(cell.x))); + .setInput(Rule::Left, (!cell.x? + self().rule().left() + : layout.columnLeft(cell.x)) + halfUnit) + .setInput(Rule::Right, ((cell.x == layout.gridSize().x - 1)? + self().rule().right() + : layout.columnRight(cell.x)) - halfUnit); } } } @@ -408,12 +413,26 @@ } } } + + void updateLayout() + { + auto &menu = self().menu(); + + menu.updateLayout(); + menu.rule().setInput( + Rule::Height, + OperatorRule::minimum(menu.rule().inputRule(Rule::Height), + root().viewHeight() - self().margins().height())); + updateItemHitRules(); + updateItemMargins(); + } }; PopupMenuWidget::PopupMenuWidget(String const &name) : PopupWidget(name), d(new Impl(this)) { setContent(new MenuWidget(name.isEmpty()? "" : name + "-content")); + setOutlineColor("popup.outline"); menu().setGridSize(1, ui::Expand, 0, ui::Expand); @@ -427,6 +446,11 @@ d->parentPopup.reset(parentPopup); } +PopupWidget *PopupMenuWidget::parentPopup() const +{ + return d->parentPopup; +} + MenuWidget &PopupMenuWidget::menu() const { return static_cast(content()); @@ -471,14 +495,7 @@ void PopupMenuWidget::preparePanelForOpening() { - // Redo the layout. - menu().updateLayout(); - menu().rule().setInput(Rule::Height, - OperatorRule::minimum(menu().rule().inputRule(Rule::Height), - root().viewHeight() - margins().height())); - d->updateItemHitRules(); - d->updateItemMargins(); - + d->updateLayout(); PopupWidget::preparePanelForOpening(); } @@ -500,4 +517,15 @@ menu().dismissPopups(); } +void PopupMenuWidget::updateStyle() +{ + PopupWidget::updateStyle(); + for (ui::DataPos i = 0; i < menu().items().size(); ++i) + { + // Force update of the item widgets. + menu().items().at(i).notifyChange(); + } + d->updateLayout(); +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/popupwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/popupwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/popupwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/popupwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -33,11 +33,13 @@ DENG_GUI_PIMPL(PopupWidget) { - bool flexibleDir = true; ColorTheme colorTheme = Normal; + bool flexibleDir = true; bool deleteAfterDismiss = false; bool clickToClose = true; bool outsideClickOngoing = false; + DotPath outlineColorId; + ColorBank::Colorf outlineColor; SafeWidgetPtr realParent; RuleRectangle anchor; Rule const *marker; @@ -194,6 +196,8 @@ Style const &st = style(); bool const opaqueBackground = (self().levelOfNesting() > 0); + outlineColor = st.colors().colorf(outlineColorId); + if (colorTheme == Inverted) { self().set(self().infoStyleBackground()); @@ -329,6 +333,12 @@ return d->colorTheme; } +void PopupWidget::setOutlineColor(const DotPath &outlineColor) +{ + d->outlineColorId = outlineColor; + d->updateStyle(); +} + void PopupWidget::setCloseButtonVisible(bool enable) { if (enable && !d->close) @@ -431,17 +441,22 @@ v.rgba = background().solidFill; v.texCoord = root().atlas().imageRectf(root().solidWhitePixel()).middle(); - int marker = d->marker->valuei(); + int const marker = d->marker->valuei(); Vector2i anchorPos = d->anchorPos(); + bool markerVisible = false; if (dir == ui::Up) { // Can't put the anchor too close to the edges. anchorPos.x = clamp(2 * marker, anchorPos.x, int(root().viewSize().x) - 2*marker); - v.pos = anchorPos; tri << v; - v.pos = anchorPos + Vector2i(-marker, -marker); tri << v; - v.pos = anchorPos + Vector2i(marker, -marker); tri << v; + if (anchorPos.y > rule().bottom().valuei()) + { + v.pos = anchorPos; tri << v; + v.pos = anchorPos + Vector2i(-marker, -marker); tri << v; + v.pos = anchorPos + Vector2i(marker, -marker); tri << v; + markerVisible = true; + } } else if (dir == ui::Left) { @@ -451,19 +466,109 @@ v.pos = anchorPos; tri << v; v.pos = anchorPos + Vector2i(-marker, marker); tri << v; v.pos = anchorPos + Vector2i(-marker, -marker); tri << v; + markerVisible = true; } } else if (dir == ui::Right) { - v.pos = anchorPos; tri << v; - v.pos = anchorPos + Vector2i(marker, -marker); tri << v; - v.pos = anchorPos + Vector2i(marker, marker); tri << v; + if (anchorPos.x < rule().left().valuei()) + { + v.pos = anchorPos; tri << v; + v.pos = anchorPos + Vector2i(marker, -marker); tri << v; + v.pos = anchorPos + Vector2i(marker, marker); tri << v; + markerVisible = true; + } } else { - v.pos = anchorPos; tri << v; - v.pos = anchorPos + Vector2i(marker, marker); tri << v; - v.pos = anchorPos + Vector2i(-marker, marker); tri << v; + if (anchorPos.y < rule().top().valuei()) + { + v.pos = anchorPos; tri << v; + v.pos = anchorPos + Vector2i(marker, marker); tri << v; + v.pos = anchorPos + Vector2i(-marker, marker); tri << v; + markerVisible = true; + } + } + + // Outline. + if (d->outlineColor.w > 0.f) + { + tri << v; // discontinued + + Rectanglei const rect = rule().recti(); + int const ow = GuiWidget::pointsToPixels(2); + int const halfOw = ow/2; + int const midOw = ow + halfOw; + + v.rgba = d->outlineColor; + + // Top edge. + v.pos = rect.topLeft + Vector2i(-ow, -ow); tri << v << v; + v.pos = rect.topLeft; tri << v; + + if (markerVisible && dir == ui::Down) + { + v.pos = Vector2i(anchorPos.x - marker - halfOw, rect.top() - ow); tri << v; + v.pos += Vector2i(halfOw, ow); tri << v; + + v.pos = anchorPos + Vector2i(0, -midOw); tri << v; + v.pos.y += midOw; tri << v; + + v.pos = Vector2i(anchorPos.x + marker + halfOw, rect.top() - ow); tri << v; + v.pos += Vector2i(-halfOw, ow); tri << v; + } + + // Right edge. + v.pos = rect.topRight() + Vector2i(ow, -ow); tri << v; + v.pos = rect.topRight(); tri << v; + + if (markerVisible && dir == ui::Left) + { + v.pos = Vector2i(rect.right() + ow, anchorPos.y - marker - halfOw); tri << v; + v.pos += Vector2i(-ow, halfOw); tri << v; + + v.pos = anchorPos + Vector2i(midOw, 0); tri << v; + v.pos.x += -midOw; tri << v; + + v.pos = Vector2i(rect.right() + ow, anchorPos.y + marker + halfOw); tri << v; + v.pos += Vector2i(-ow, -halfOw); tri << v; + } + + // Bottom edge. + v.pos = rect.bottomRight + Vector2i(ow, ow); tri << v; + v.pos = rect.bottomRight; tri << v; + + if (markerVisible && dir == ui::Up) + { + v.pos = Vector2i(anchorPos.x + marker + halfOw, rect.bottom() + ow); tri << v; + v.pos += Vector2i(-halfOw, -ow); tri << v; + + v.pos = anchorPos + Vector2i(0, midOw); tri << v; + v.pos.y += -midOw; tri << v; + + v.pos = Vector2i(anchorPos.x - marker - halfOw, rect.bottom() + ow); tri << v; + v.pos += Vector2i(halfOw, -ow); tri << v; + } + + // Left edge. + v.pos = rect.bottomLeft() + Vector2i(-ow, ow); tri << v; + v.pos = rect.bottomLeft(); tri << v; + + if (markerVisible && dir == ui::Right) + { + v.pos = Vector2i(rect.left() - ow, anchorPos.y + marker + halfOw); tri << v; + v.pos += Vector2i(ow, -halfOw); tri << v; + + v.pos = anchorPos + Vector2i(-midOw, 0); tri << v; + v.pos.x += midOw; tri << v; + + v.pos = Vector2i(rect.left() - ow, anchorPos.y - marker - halfOw); tri << v; + v.pos += Vector2i(ow, halfOw); tri << v; + } + + // Back to top. + v.pos = rect.topLeft + Vector2i(-ow, -ow); tri << v; + v.pos = rect.topLeft; tri << v; } verts += tri; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/progresswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/progresswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/progresswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/progresswidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -192,7 +192,7 @@ setImageScale(1); // Resize to the height of the default font. - setOverrideImageSize(style().fonts().font("default").height().value()); + setOverrideImageSize(style().fonts().font("default").height()); d->updateStyle(); } @@ -256,7 +256,7 @@ setMode(Ranged); } -void ProgressWidget::setProgress(int currentProgress, TimeDelta const &transitionSpan) +void ProgressWidget::setProgress(int currentProgress, TimeSpan const &transitionSpan) { DENG2_GUARD(d); @@ -277,7 +277,7 @@ // Keep rotating the wheel. Time const now = Time(); if (!d->updateAt.isValid()) d->updateAt = now; - TimeDelta const elapsed = d->updateAt.since(); + TimeSpan const elapsed = d->updateAt.since(); d->updateAt = now; d->angle = de::wrap(d->angle + float(elapsed * d->rotationSpeed), 0.f, 360.f); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/scriptcommandwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/scriptcommandwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/scriptcommandwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/scriptcommandwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -157,7 +157,7 @@ try { Value const &result = d->process.context().evaluator().result(); - if (!result.is()) + if (!is(result)) { String msg = DENG2_CHAR_RIGHT_DOUBLEARROW " " _E(>)_E(m) + result.asText(); LOG_SCR_MSG(msg); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/scrollareawidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -41,27 +41,25 @@ Rule *maxX; Rule *maxY; - Origin origin = Top; - bool pageKeysEnabled = true; - bool scrollingEnabled = true; - Animation scrollOpacity { 0 }; - int scrollBarWidth = 0; - Rectanglef indicatorUv; - bool indicatorAnimating = false; String scrollBarColorId { "accent" }; ColorBank::Colorf scrollBarColor; ColorBank::Colorf scrollBarHoverColor; - bool scrollBarGrabbed = false; + Animation scrollOpacity { 0 }; + Origin origin = Top; + int scrollBarWidth { 0 }; int grabOffset; + bool scrollBarGrabbed { false }; + bool indicatorAnimating { false }; + bool pageKeysEnabled { true }; + bool scrollingEnabled { true }; + // GL objects. - bool indicatorDrawEnabled = false; - bool scrollBarHover = false; + bool indicatorDrawEnabled { false }; + bool scrollBarHover { false }; + Rectanglef indicatorUv; Rectanglef scrollBarVisRect; Rectanglef scrollBarLaneRect; - //Drawable drawable; - //GLUniform uMvpMatrix { "uMvpMatrix", GLUniform::Mat4 }; - //GLUniform uColor { "uColor", GLUniform::Vec4 }; GuiVertexBuilder verts; Impl(Public *i) : Base(i) @@ -145,12 +143,17 @@ Vector2i const viewSize = self().viewportSize(); if (viewSize == Vector2i()) return RectanglefPair(); - auto const &margins = self().margins(); - - int const indHeight = de::clamp( + const auto &margins = self().margins(); + const float contentHeight = float(contentRule.height().value()); + int indHeight = 0; + + if (contentHeight > 0) + { + indHeight = de::clamp( margins.height().valuei(), - int(float(viewSize.y * viewSize.y) / float(contentRule.height().value())), + int(float(viewSize.y * viewSize.y) / contentHeight), viewSize.y / 2); + } float indPos = self().scrollPositionY().value() / self().maximumScrollY().value(); if (origin == Top) indPos = 1 - indPos; @@ -258,6 +261,13 @@ setContentHeight(height); } +void ScrollAreaWidget::setContentSize(ISizeRule const &dimensions) +{ + DENG2_GUARD(d); + setContentWidth(dimensions.width()); + setContentHeight(dimensions.height()); +} + void ScrollAreaWidget::setContentSize(Vector2i const &size) { DENG2_GUARD(d); @@ -372,24 +382,24 @@ return Vector2i(maximumScrollX().valuei(), maximumScrollY().valuei()); } -void ScrollAreaWidget::scroll(Vector2i const &to, TimeDelta span) +void ScrollAreaWidget::scroll(Vector2i const &to, TimeSpan span) { scrollX(to.x, span); scrollY(to.y, span); } -void ScrollAreaWidget::scrollX(int to, TimeDelta span) +void ScrollAreaWidget::scrollX(int to, TimeSpan span) { d->x->set(de::clamp(0, to, maximumScrollX().valuei()), span); } -void ScrollAreaWidget::scrollY(int to, TimeDelta span) +void ScrollAreaWidget::scrollY(int to, TimeSpan span) { d->y->set(de::clamp(0, to, maximumScrollY().valuei()), span); d->restartScrollOpacityFade(); } -void ScrollAreaWidget::scrollY(Rule const &to, TimeDelta span) +void ScrollAreaWidget::scrollY(Rule const &to, TimeSpan span) { d->y->set(OperatorRule::clamped(to, Const(0), maximumScrollY()), span); d->restartScrollOpacityFade(); @@ -418,6 +428,7 @@ void ScrollAreaWidget::enableIndicatorDraw(bool enabled) { d->indicatorDrawEnabled = enabled; + d->restartScrollOpacityFade(); } bool ScrollAreaWidget::handleEvent(Event const &event) @@ -461,7 +472,7 @@ if (mouse.wheelMotion() == MouseEvent::FineAngle) { d->y->set(de::clamp(0, int(d->y->animation().target()) + - toDevicePixels(mouse.wheel().y / 2 * (d->origin == Top? -1 : 1)), + pointsToPixels(mouse.wheel().y / 2 * (d->origin == Top? -1 : 1)), d->maxY->valuei()), .05f); d->restartScrollOpacityFade(); } @@ -489,7 +500,7 @@ { if (event.type() == Event::MousePosition) { - bool const hovering = (d->scrollBarVisRect.expanded(toDevicePixels(1)) + bool const hovering = (d->scrollBarVisRect.expanded(pointsToPixels(1)) .contains(event.as().pos())); d->setScrollBarHovering(hovering); } @@ -553,7 +564,7 @@ return GuiWidget::handleEvent(event); } -void ScrollAreaWidget::scrollToTop(TimeDelta span) +void ScrollAreaWidget::scrollToTop(TimeSpan span) { if (d->origin == Top) { @@ -565,7 +576,7 @@ } } -void ScrollAreaWidget::scrollToBottom(TimeDelta span) +void ScrollAreaWidget::scrollToBottom(TimeSpan span) { if (d->origin == Top) { @@ -577,17 +588,17 @@ } } -void ScrollAreaWidget::scrollToLeft(TimeDelta span) +void ScrollAreaWidget::scrollToLeft(TimeSpan span) { scrollX(0, span); } -void ScrollAreaWidget::scrollToRight(TimeDelta span) +void ScrollAreaWidget::scrollToRight(TimeSpan span) { scrollX(maximumScrollX().valuei(), span); } -void ScrollAreaWidget::scrollToWidget(GuiWidget const &widget, TimeDelta span) +void ScrollAreaWidget::scrollToWidget(GuiWidget const &widget, TimeSpan span) { int off = widget.rule().midY().valuei() - contentRule().top().valuei() - rule().height().valuei()/2; @@ -632,7 +643,7 @@ Vector4f const barOpacity { 1, 1, 1, d->scrollOpacity }; - verts.makeQuad(d->scrollBarVisRect.expanded((d->scrollBarHover? toDevicePixels(1) : 0)), + verts.makeQuad(d->scrollBarVisRect.expanded((d->scrollBarHover ? pointsToPixels(1) : 0)), barOpacity * d->scrollBarColor, d->indicatorUv); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/sliderwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/sliderwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/sliderwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/sliderwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -221,7 +221,7 @@ // Range dots. int numDots = de::clamp(5, round(range.size() / step) + 1, 11); - int dotSpace = (sliderArea.width() - endLabelSize) / toDevicePixels(1.f); // in logical space + int dotSpace = (sliderArea.width() - endLabelSize) / pointsToPixels(1.f); int dotX = sliderArea.topLeft.x + endLabelSize / 2; float altAlpha = 0; if (dotSpace / numDots > 30) @@ -233,7 +233,7 @@ for (int i = 0; i < numDots; ++i) { // dotSpace converted back to device pixels. - Vector2i dotPos(dotX + toDevicePixels(dotSpace * float(i) / float(numDots - 1)), + Vector2i dotPos(dotX + pointsToPixels(dotSpace * float(i) / float(numDots - 1)), sliderArea.middle().y); Vector4f dotColor = textColor; @@ -251,8 +251,8 @@ Rectanglei slider = sliderValueRect(); verts.makeQuad(slider.expanded(2), state == Grabbed? textColor : invTextColor, atlas().imageRectf(root().solidWhitePixel()).middle()); - verts.makeFlexibleFrame(slider.expanded(SliderWidget::toDevicePixels(5)), - SliderWidget::toDevicePixels(6), + verts.makeFlexibleFrame(slider.expanded(pointsToPixels(5)), + pointsToPixels(6), Vector4f(1, 1, 1, frameOpacity), atlas().imageRectf(root().boldRoundCorners())); @@ -379,6 +379,8 @@ self().requestGeometry(); emit self().valueChanged(v); + + DENG2_FOR_PUBLIC_AUDIENCE2(Change, i) i->sliderValueChanged(self()); } } @@ -451,8 +453,12 @@ } } } + + DENG2_PIMPL_AUDIENCE(Change) }; +DENG2_AUDIENCE_METHOD(SliderWidget, Change) + SliderWidget::SliderWidget(String const &name) : GuiWidget(name), d(new Impl(this)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/tabwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/tabwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/tabwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/tabwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -134,7 +134,7 @@ } if (sel) { - TimeDelta span = .2; + TimeSpan span = .2; if (!selLeft) { // Initialize the animated rules for positioning the diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/togglewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/togglewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/togglewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/togglewidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -25,7 +25,7 @@ namespace de { -static TimeDelta const SWITCH_ANIM_SPAN = 0.3; +static TimeSpan const SWITCH_ANIM_SPAN = 0.3; DENG2_PIMPL(ToggleWidget), DENG2_OBSERVES(ButtonWidget, Press) @@ -39,7 +39,8 @@ _pos(0, Animation::EaseBoth), _animating(false) { - setSize(style().images().image("toggle.onoff").size()); + const Image &img = style().images().image("toggle.onoff"); + setPointSize(img.size() * img.pointRatio()); updateStyle(); } @@ -48,7 +49,7 @@ void setState(ToggleState st, bool animate) { - _pos.setValue(st == Active? 1 : 0, animate? SWITCH_ANIM_SPAN : TimeDelta()); + _pos.setValue(st == Active? 1 : 0, animate? SWITCH_ANIM_SPAN : TimeSpan()); _animating = true; } @@ -85,11 +86,11 @@ verts.makeQuad(recti, _accentColor * p + _textColor * (1-p) * .8f, atlas().imageRectf(onOff)); // The flipper. - int flipWidth = size().x - size().y + GuiWidget::toDevicePixels(2); - Rectanglei flip = Rectanglei::fromSize(recti.topLeft + - Vector2i(GuiWidget::toDevicePixels(1) + de::round(p * (size().x - flipWidth)), - GuiWidget::toDevicePixels(1)), - Vector2ui(flipWidth, size().y) - toDevicePixels(Vector2ui(2, 2))); + const int flipWidth = pointSize().x - pointSize().y + 2; + Rectanglei flip = Rectanglei::fromSize( + recti.topLeft + pointsToPixels(Vector2i( + 1 + de::round(p * (pointSize().x - flipWidth)), 1)), + pointsToPixels(Vector2ui(flipWidth, pointSize().y) - Vector2ui(2, 2))); verts.makeQuad(flip, _bgColor * Vector4f(1, 1, 1, 3), atlas().imageRectf(_owner.root().solidWhitePixel()).middle()); } @@ -114,13 +115,12 @@ ToggleProceduralImage *procImage; // not owned bool hasBeenUpdated = false; - Impl(Public *i) - : Base(i), - state(Inactive), - procImage(new ToggleProceduralImage(*i)) + Impl(Public *i, Flags const &flags) + : Base(i) + , state(Inactive) + , procImage(!(flags & WithoutIndicator)? new ToggleProceduralImage(*i) : nullptr) { - self().setImage(procImage); // base class owns it - + if (procImage) self().setImage(procImage); // base class owns it self().audienceForPress() += this; } @@ -137,7 +137,9 @@ DENG2_AUDIENCE_METHOD(ToggleWidget, Toggle) -ToggleWidget::ToggleWidget(String const &name) : ButtonWidget(name), d(new Impl(this)) +ToggleWidget::ToggleWidget(Flags const &flags, String const &name) + : ButtonWidget(name) + , d(new Impl(this, flags)) { setTextAlignment(ui::AlignRight); setTextLineAlignment(ui::AlignLeft); @@ -148,7 +150,10 @@ if (d->state != state) { d->state = state; - d->procImage->setState(state, hasBeenUpdated()); + if (d->procImage) + { + d->procImage->setState(state, hasBeenUpdated()); + } if (notify) { @@ -165,7 +170,10 @@ void ToggleWidget::finishAnimation() { - d->procImage->finishAnimation(); + if (d->procImage) + { + d->procImage->finishAnimation(); + } } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablearraywidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablearraywidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablearraywidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablearraywidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -27,12 +27,13 @@ , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetCreation) , DENG2_OBSERVES(ChildWidgetOrganizer, WidgetUpdate) { - Variable *var = nullptr; + Variable * var = nullptr; IndirectRule *maxWidth; - MenuWidget *menu; + MenuWidget * menu; ButtonWidget *addButton; ButtonWidget *deleteButton; - ui::DataPos hoverItem = ui::Data::InvalidPos; + ui::DataPos hoverItem = ui::Data::InvalidPos; + bool mouseWasInside = false; /// Notifies the widget when the mouse is over one of the items. struct HoverHandler : public GuiWidget::IEventHandler @@ -60,13 +61,14 @@ menu->organizer().audienceForWidgetCreation() += this; menu->organizer().audienceForWidgetUpdate() += this; menu->setGridSize(1, ui::Expand, 0, ui::Expand); + menu->layout().setRowPadding(2 * rule("unit")); updateFromVariable(); var.audienceForDeletion() += this; var.audienceForChange() += this; } - ~Impl() + ~Impl() override { releaseRef(maxWidth); } @@ -79,13 +81,16 @@ deleteButton->rule().setMidAnchorY(widget.rule().midY()); } - void widgetCreatedForItem(GuiWidget &widget, ui::Item const &) override + void widgetCreatedForItem(GuiWidget &widget, ui::Item const &item) override { auto &label = widget.as(); label.setSizePolicy(ui::Expand, ui::Expand); label.setMaximumTextWidth(*maxWidth); - widget.margins().setLeftRight("").setTopBottom(RuleBank::UNIT); + widget.margins().setRight("").setTopBottom(""); + widget.margins().setLeft("");//deleteButton->rule().width()); widget.addEventHandler(new HoverHandler(self())); + + self().elementCreated(label, item); } void widgetUpdatedForItem(GuiWidget &widget, ui::Item const &item) override @@ -163,6 +168,7 @@ d->deleteButton->margins().setLeft(RuleBank::UNIT).setRight("dialog.gap"); d->deleteButton->setBehavior(Focusable, UnsetFlags); d->deleteButton->set(Background()); + d->deleteButton->hide(); d->menu->margins() .setLeft(d->deleteButton->rule().width()) @@ -171,8 +177,9 @@ d->menu->enableScrolling(false); d->menu->enablePageKeys(false); d->menu->rule() - .setLeftTop(margins().left() + rule().left(), - margins().top() + rule().top()); + .setLeftTop(/*margins().left() + */rule().left(), + margins().top() + rule().top()) + .setInput(Rule::Right, rule().right() - 2 * rule("gap")); d->addButton->setFont("small"); d->addButton->setStyleImage("create", d->addButton->fontId()); @@ -202,6 +209,8 @@ add(d->menu); add(d->deleteButton); add(d->addButton); + + d->menu->updateLayout(); } Variable &VariableArrayWidget::variable() const @@ -219,6 +228,11 @@ return value.asText(); } +void VariableArrayWidget::elementCreated(LabelWidget &, const ui::Item &) +{ + // Derived class may customize the label. +} + ButtonWidget &VariableArrayWidget::addButton() { return *d->addButton; @@ -245,6 +259,22 @@ return item; } +bool VariableArrayWidget::handleEvent(Event const &event) +{ + // Hide the delete button when mouse leaves the widget's bounds. + if (event.isMouse()) + { + MouseEvent const &mouse = event.as(); + bool const isInside = rule().recti().contains(mouse.pos()); + if (d->mouseWasInside && !isInside) + { + d->deleteButton->hide(); + } + d->mouseWasInside = isInside; + } + return GuiWidget::handleEvent(event); +} + void VariableArrayWidget::updateFromVariable() { d->updateFromVariable(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablechoicewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablechoicewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablechoicewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablechoicewidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -23,14 +23,17 @@ namespace de { -/// @todo Add support for TextValue in addition to NumberValue. DENG2_PIMPL(VariableChoiceWidget), DENG2_OBSERVES(Variable, Deletion), DENG2_OBSERVES(Variable, Change ) { Variable *var; + VariableType variableType; - Impl(Public *i, Variable &variable) : Base(i), var(&variable) + Impl(Public *i, Variable &variable, VariableType vt) + : Base(i) + , var(&variable) + , variableType(vt) { updateFromVariable(); @@ -40,9 +43,9 @@ void updateFromVariable() { - if (!var) return; + if (!var || self().items().isEmpty()) return; - if (var->value().is()) + if (variableType == Text) { self().setSelected(self().items().findData(var->value().asText())); } @@ -57,7 +60,7 @@ if (!var) return; var->audienceForChange() -= this; - if (var->value().is()) + if (variableType == Text) { var->set(TextValue(self().selectedItem().data().toString())); } @@ -80,8 +83,10 @@ } }; -VariableChoiceWidget::VariableChoiceWidget(Variable &variable, String const &name) - : ChoiceWidget(name), d(new Impl(this, variable)) +VariableChoiceWidget::VariableChoiceWidget(Variable &variable, VariableType variableType, + String const &name) + : ChoiceWidget(name) + , d(new Impl(this, variable, variableType)) { connect(this, SIGNAL(selectionChangedByUser(uint)), this, SLOT(setVariableFromWidget())); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablesliderwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablesliderwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variablesliderwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variablesliderwidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -94,7 +94,7 @@ : SliderWidget(name) , d(new Impl(this, variable)) { - if (!variable.value().is()) + if (!is(variable.value())) { // Animation is the only other supported type. d->valueType = VariableSliderWidget::Animation; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variabletogglewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variabletogglewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/widgets/variabletogglewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/widgets/variabletogglewidget.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -79,11 +79,13 @@ }; VariableToggleWidget::VariableToggleWidget(Variable &variable, String const &name) - : ToggleWidget(name), d(new Impl(this, variable)) + : ToggleWidget(DefaultFlags, name) + , d(new Impl(this, variable)) {} VariableToggleWidget::VariableToggleWidget(String const &label, Variable &variable, String const &name) - : ToggleWidget(name), d(new Impl(this, variable)) + : ToggleWidget(DefaultFlags, name) + , d(new Impl(this, variable)) { setText(label); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/windowsystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/windowsystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libappfw/src/windowsystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libappfw/src/windowsystem.cpp 2018-12-11 07:08:23.000000000 +0000 @@ -18,11 +18,13 @@ #include "de/WindowSystem" #include +#include // for updating pixel ratio #include namespace de { DENG2_PIMPL(WindowSystem) +, DENG2_OBSERVES(GLWindow, PixelRatio) { typedef QMap Windows; Windows windows; @@ -65,6 +67,14 @@ processLatestMousePosition(); } } + + void windowPixelRatioChanged(GLWindow &win) + { + if (&win == &BaseWindow::main()) + { + DENG2_BASE_GUI_APP->setPixelRatio(float(win.pixelRatio())); + } + } }; WindowSystem::WindowSystem() @@ -79,6 +89,7 @@ void WindowSystem::addWindow(String const &id, BaseWindow *window) { + window->audienceForPixelRatio() += d; d->windows.insert(id, window); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/CMakeLists.txt 2018-12-11 07:08:23.000000000 +0000 @@ -37,13 +37,14 @@ file (GLOB_RECURSE HEADERS include/de/[a-zA-Z]*) file (GLOB SOURCES src/*.cpp src/*.h src/core/*.h) -deng_merge_sources (concurrency src/concurrency/*.cpp) -deng_merge_sources (core src/core/*.cpp) -deng_merge_sources (data src/data/*.cpp) -deng_merge_sources (filesys src/filesys/*.cpp) -deng_merge_sources (net src/net/*.cpp) -deng_merge_sources (scriptsys src/scriptsys/*.cpp) -deng_merge_sources (widgets src/widgets/*.cpp) +deng_merge_sources (concurrency src/concurrency/*.cpp) +deng_merge_sources (core src/core/*.cpp) +deng_merge_sources (data src/data/*.cpp) +deng_merge_sources (filesys src/filesys/*.cpp) +deng_merge_sources (filesys_remote src/filesys/remote/*.cpp) +deng_merge_sources (net src/net/*.cpp) +deng_merge_sources (scriptsys src/scriptsys/*.cpp) +deng_merge_sources (widgets src/widgets/*.cpp) if (WIN32) # Update the resource file. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/Async doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/Async --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/Async 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/Async 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "concurrency/async.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/AsyncCallback doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/AsyncCallback --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/AsyncCallback 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/AsyncCallback 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "concurrency/asynccallback.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/asynccallback.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/asynccallback.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/asynccallback.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/asynccallback.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,74 @@ +/** @file asynccallback.h Asynchronous callback utility. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_ASYNCCALLBACK_H +#define LIBDENG2_ASYNCCALLBACK_H + +#include + +namespace de { + +template +class AsyncCallback +{ +public: + AsyncCallback(Type callback) + : _callback(callback) + {} + + bool isValid() const + { + return _callback != nullptr; + } + + template + void call(Args... args) + { + if (isValid()) + { + _callback(args...); + } + _done.post(); + } + + void cancel() + { + _callback = nullptr; + _done.post(); + } + + void wait(TimeSpan const &timeout) + { + try + { + _done.wait(timeout); + } + catch (Waitable::TimeOutError const &) + { + cancel(); + } + } + +private: + Type _callback; + Waitable _done; +}; + +} // namespace de + +#endif // LIBDENG2_ASYNCCALLBACK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/async.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/async.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/async.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/async.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,160 @@ +/** @file asynctask.h Asynchoronous task with a completion callback. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_ASYNCTASK_H +#define LIBDENG2_ASYNCTASK_H + +#include "../App" +#include "../Loop" +#include "../String" + +#include +#include +#include + +namespace de { + +struct DENG2_PUBLIC AsyncTask : public QThread +{ + virtual ~AsyncTask() {} + virtual void abort() = 0; + virtual void invalidate() = 0; +}; + +namespace internal { + +template +class AsyncTaskThread : public AsyncTask +{ + Task task; + decltype(task()) result {}; // can't be void + Completion completion; + bool valid; + + void run() override + { + try + { + result = task(); + } + catch (...) + {} + notifyCompletion(); + } + + void notifyCompletion() + { + Loop::mainCall([this] () + { + if (valid) completion(result); + deleteLater(); + }); + } + + void invalidate() override + { + valid = false; + } + +public: + AsyncTaskThread(Task task, Completion completion) + : task(std::move(task)) + , completion(std::move(completion)) + , valid(true) + {} + + AsyncTaskThread(Task const &task) + : task(task) + , valid(false) + {} + + void abort() override + { + terminate(); + notifyCompletion(); + } +}; + +} // namespace internal + +/** + * Executes an asynchronous callback in a background thread. + * + * After the background thread finishes, the result from the callback is passed to + * another callback that is called in the main thread. + * + * Must be called from the main thread. + * + * If it is possible that the completion becomes invalid (e.g., the object that + * started the operation is destroyed), you should use AsyncScope to automatically + * invalidate the completion callbacks of the started tasks. + * + * @param task Task callback. If an exception is thrown here, it will be + * quietly caught, and the completion callback will be called with + * a default-constructed result value. Note that if you return a + * pointer to an object and intend to pass ownership to the + * completion callback, the object will leak if the completion has + * been invalidated. Therefore, you should always pass ownership via + * std::shared_ptr or other reference-counted type. + * + * @param completion Completion callback to be called in the main thread. Takes one + * argument matching the type of the return value from @a task. + * + * @return Background thread object. The thread will delete itself after the completion + * callback has been called. You can pass this to AsyncScope for keeping track of. + */ +template +AsyncTask *async(Task task, Completion completion) +{ + DENG2_ASSERT_IN_MAIN_THREAD(); + auto *t = new internal::AsyncTaskThread(std::move(task), std::move(completion)); + t->start(); + // Note: The thread will delete itself when finished. + return t; +} + +/*template +AsyncTask *async(Task const &task) +{ + auto *t = new internal::AsyncTaskThread(task); + t->start(); + // Note: The thread will delete itself when finished. + return t; +}*/ + +/** + * Utility for invalidating the completion callbacks of async tasks whose initiator + * has gone out of scope. + */ +class DENG2_PUBLIC AsyncScope +{ +public: + AsyncScope() = default; + ~AsyncScope(); + + AsyncScope &operator += (AsyncTask *task); + bool isAsyncFinished() const; + void waitForFinished(TimeSpan timeout = 0.0); + +private: + LockableT> _tasks; +}; + +} // namespace de + +#endif // LIBDENG2_ASYNCTASK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/waitable.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/waitable.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/concurrency/waitable.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/concurrency/waitable.h 2018-12-11 07:08:23.000000000 +0000 @@ -53,7 +53,11 @@ /// Wait for the specified period of time to secure the /// resource. If timeout occurs, an exception is thrown. - void wait(TimeDelta const &timeOut) const; + void wait(TimeSpan const &timeOut) const; + + /// Wait for the specified period of time to secure the + /// resource. If timeout occurs, returns @c false. + bool tryWait(TimeSpan const &timeOut) const; /// Mark the resource as available by incrementing the /// semaphore value. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/ConditionalTrigger doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/ConditionalTrigger --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/ConditionalTrigger 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/ConditionalTrigger 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "data/conditionaltrigger.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/app.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/app.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/app.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/app.h 2018-12-11 07:08:23.000000000 +0000 @@ -52,6 +52,7 @@ class System; class UnixInfo; +namespace filesys { class RemoteFeedRelay; } namespace game { class Game; } /** @@ -124,8 +125,8 @@ * * This method must be called before initSubsystems(). * - * @param path Location of the @em Config.de script file. The default path of the - * script is "/modules/Config.de". + * @param path Location of the @em Config.ds script file. The default path of the + * script is "/modules/Config.ds". */ void setConfigScript(Path const &path); @@ -220,11 +221,13 @@ */ NativePath nativeBasePath(); +#if !defined (DENG_STATIC_LINK) /** * Returns the native path of where to load binaries (plugins). This * is where "/bin" points to. */ NativePath nativePluginBinaryPath(); +#endif /** * Returns the native path where user-specific runtime files should be @@ -296,6 +299,11 @@ static PackageLoader &packageLoader(); /** + * Returns the remote feed relay that manages connections to remote file repositories. + */ + static filesys::RemoteFeedRelay &remoteFeedRelay(); + + /** * Convenience method for finding all files matching a certain name or partial path * from all loaded packages. * @@ -346,6 +354,12 @@ static Variable &config(String const &name); /** + * Returns the web API URL. Always includes the protocol and ends with a slash. + * @return Configured web API URL. + */ + static String apiUrl(); + + /** * Returns the Unix system-level configuration preferences. */ static UnixInfo &unixInfo(); @@ -394,7 +408,7 @@ public: /** * Determines if the currently executing thread is the application's main - * (UI) thread. + * thread. */ static bool inMainThread(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/asset.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/asset.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/asset.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/asset.h 2018-12-11 07:08:23.000000000 +0000 @@ -72,6 +72,8 @@ */ virtual bool isReady() const; + void waitForState(State s) const; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/clock.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/clock.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/clock.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/clock.h 2018-12-11 07:08:23.000000000 +0000 @@ -52,13 +52,13 @@ virtual void setTime(Time const ¤tTime); - void advanceTime(TimeDelta const &span); + void advanceTime(TimeSpan const &span); /** * Returns the amount of time elapsed since the clock was created. * @return Elapsed time. */ - TimeDelta elapsed() const; + TimeSpan elapsed() const; /** * Returns a reference to the current time. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/commandline.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/commandline.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/commandline.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/commandline.h 2018-12-11 07:08:23.000000000 +0000 @@ -24,9 +24,13 @@ #include #include -#include #include +#if !defined (DENG_MOBILE) +# include +# define DENG_HAVE_QPROCESS +#endif + #include "../libcore.h" #include "../String" #include "../NativePath" @@ -224,6 +228,8 @@ */ bool matches(String const &full, String const &fullOrAlias) const; +#if defined (DENG_HAVE_QPROCESS) + /** * Spawns a new process using the command line. The first argument * specifies the file name of the executable. Returns immediately @@ -245,6 +251,8 @@ QProcess *executeProcess() const; +#endif + static CommandLine &get(); private: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/config.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/config.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/config.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/config.h 2018-12-11 07:08:23.000000000 +0000 @@ -52,6 +52,9 @@ class DENG2_PUBLIC Config : public RecordAccessor, public IObject { public: + enum ReadStatus { WasNotRead, SameVersion, DifferentVersion }; + +public: /** * Constructs a new configuration. * @@ -60,7 +63,7 @@ Config(Path const &path); /// Read configuration from files. - void read(); + ReadStatus read(); /// Writes the configuration to /home. void write() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/garbage.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/garbage.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/garbage.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/garbage.h 2018-12-11 07:08:23.000000000 +0000 @@ -88,6 +88,13 @@ DENG2_PUBLIC void Garbage_Recycle(void); /** + * Clears the garbage contents without actually freeing any memory. This + * should only be called under exceptional circumstances to quickly dismiss + * all recycled memory. Everything in the trash will leak! + */ +DENG2_PUBLIC void Garbage_ForgetAndLeak(void); + +/** * Frees all pointers in every thread's garbage if they are using a specific * destructor function. * diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/highperformancetimer.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/highperformancetimer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/highperformancetimer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/highperformancetimer.h 2018-12-11 07:08:23.000000000 +0000 @@ -35,7 +35,7 @@ /** * Returns the amount of time elapsed since the creation of the timer. */ - TimeDelta elapsed() const; + TimeSpan elapsed() const; /** * Returns the time when the timer was started. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/library.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/library.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/library.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/library.h 2018-12-11 07:08:23.000000000 +0000 @@ -23,15 +23,25 @@ #include "../libcore.h" #include "../NativePath" -#include -#include - /** * Convenience macro for accessing symbols that have a type defined in de::Library * with the type name matching the symbol name. */ #define DENG2_SYMBOL(Name) symbol(#Name) +#if defined (DENG_STATIC_LINK) +typedef void *(*StaticSymbolFunc)(char const *name); +#define DENG2_IMPORT_LIBRARY(name) \ + DENG2_EXTERN_C void * staticlib_##name##_symbol(char const *); \ + struct Importer_##name { \ + Importer_##name() { \ + de::Library::importStaticLibrary(#name, staticlib_##name##_symbol); \ + } \ + }; \ + static Importer_##name importer_##name; +#endif + + namespace de { class Audio; @@ -125,6 +135,11 @@ typedef char const *(*deng_GetString)(dint id); typedef void *(*deng_GetAddress)(dint id); typedef void (*deng_Ticker)(ddouble tickLength); + +#if defined (DENG_STATIC_LINK) + static void importStaticLibrary(char const *name, StaticSymbolFunc symbolFunc); + static StringList staticLibraries(); +#endif public: /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/logbuffer.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/logbuffer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/logbuffer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/logbuffer.h 2018-12-11 07:08:23.000000000 +0000 @@ -155,7 +155,7 @@ * * @param interval Interval for autoflushing. */ - void setAutoFlushInterval(TimeDelta const &interval); + void setAutoFlushInterval(TimeSpan const &interval); enum OutputChangeBehavior { FlushFirstToOldOutputs, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/log.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/log.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/log.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/log.h 2018-12-11 07:08:23.000000000 +0000 @@ -487,6 +487,7 @@ void setValue(char const *s); void setValue(String const &s); void setValue(Base const &arg); + void setValue(std::array const &typecode); template Arg &set(ValueType const &s) { setValue(s); return *this; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/loop.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/loop.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/loop.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/loop.h 2018-12-11 07:08:23.000000000 +0000 @@ -58,7 +58,9 @@ * * @param freqHz Frequency in Hz. */ - void setRate(int freqHz); + void setRate(double freqHz); + + double rate() const; /** * Starts the loop. @@ -86,7 +88,7 @@ * @param delay Time to wait before calling. * @param func Callback to call. */ - static void timer(TimeDelta const &delay, std::function func); + static void timer(TimeSpan const &delay, std::function func); static Loop &get(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/matrix.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/matrix.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/matrix.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/matrix.h 2018-12-11 07:08:23.000000000 +0000 @@ -354,15 +354,16 @@ return m; } static Matrix4 perspective(Type fov, Type aspectRatio, Type nearDistance = 1.f, Type farDistance = 1000.f) { - Type const halfWidth = std::tan(Type(.5) * degreeToRadian(fov)); - Type const halfHeight = halfWidth / aspectRatio; - Type const depth = farDistance - nearDistance; + const Type fovx = degreeToRadian(fov); + const Type f = Type(1.0) / Type(std::tan(Type(0.5) * fovx)); + const Type A = farDistance + nearDistance; + const Type B = nearDistance - farDistance; Matrix4 m(Zero); - m.at(0, 0) = Type(1) / halfWidth; - m.at(1, 1) = Type(1) / halfHeight; - m.at(2, 2) = -(farDistance + nearDistance) / depth; - m.at(2, 3) = -Type(1); - m.at(3, 2) = -Type(2) * farDistance * nearDistance / depth; + m.at(0, 0) = f; + m.at(1, 1) = f * aspectRatio; + m.at(2, 2) = A / B; + m.at(3, 2) = Type(-1.0); + m.at(2, 3) = (Type(2.0) * farDistance * nearDistance) / B; return m; } static Matrix4 perspectiveZoom(Type width, Type height, Type nearDist = 1.f, Type farDist = 1000.f, Type zoom = 1.f) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/range.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/range.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/range.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/range.h 2018-12-11 07:08:23.000000000 +0000 @@ -62,7 +62,7 @@ return de::wrap(i, start, end); } inline Type random() const { - return start + frand() * size(); + return start + randf() * size(); } inline Range &operator |= (Type const &value) { start = de::min(start, value); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/vector.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/vector.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/vector.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/vector.h 2018-12-11 07:08:23.000000000 +0000 @@ -157,7 +157,13 @@ Vector2 operator - () const { return Vector2(-x, -y); } - Vector2 operator * (ddouble scalar) const { + Vector2 operator * (int scalar) const { + return Vector2(Type(x * scalar), Type(y * scalar)); + } + Vector2 operator * (float scalar) const { + return Vector2(Type(x * scalar), Type(y * scalar)); + } + Vector2 operator * (double scalar) const { return Vector2(Type(x * scalar), Type(y * scalar)); } Vector2 operator * (Vector2 const &other) const { @@ -720,6 +726,11 @@ Vector2 zw() const { return swizzle(*this, AxisZ, AxisW); } Vector3 xyz() const { return *this; } Vector4 zyxw() const { return swizzle(*this, AxisZ, AxisY, AxisX, AxisW); } + Vector4 replaced(int index, Type const &value) const { + Vector4 v = *this; + v[index] = value; + return v; + } public: Type w; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/version.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/version.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/core/version.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/core/version.h 2018-12-11 07:08:23.000000000 +0000 @@ -56,6 +56,8 @@ */ Version(); + Version(int major, int minor, int patch, int buildNumber = 0); + /** * Version information. * @@ -80,12 +82,6 @@ bool isValid() const; /** - * Returns a version string in the form "x.y.z". If a release - * label is defined, it will be included, too: "x.y.z-label". - */ - String base() const; - - /** * Returns a version string in the form "x.y.z". */ String compactNumber() const; @@ -121,6 +117,11 @@ bool operator > (Version const &other) const; /** + * Returns a user agent string for network requests. + */ + String userAgent() const; + + /** * Determines the operating system. */ static String operatingSystem(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/arrayvalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/arrayvalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/arrayvalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/arrayvalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -49,6 +49,7 @@ public: ArrayValue(); ArrayValue(ArrayValue const &other); + ArrayValue(StringList const &strings); ArrayValue(std::initializer_list values); /** @@ -78,7 +79,7 @@ /** * Adds a new TextValue to the elements of the array. The value is * added to the end of the list of elements. - * param text Text to add to the array. + * @param text Text to add to the array. */ void add(String const &text); @@ -88,14 +89,12 @@ /** * Pops the last element and gives its ownership to the caller. - * * @return Last element of the array. Ownership transferred. */ Value *popLast(); /** * Pops the first element and gives its ownership to the caller. - * * @return First element of the array. Ownership transferred. */ Value *popFirst(); @@ -111,7 +110,6 @@ /** * Replaces an existing Value in the array. The previous value * at the index will be destroyed. - * * @param index Index of the Value. * @param value New value. The array takes ownership of the object. */ @@ -124,28 +122,29 @@ void remove(dint index); /** + * Finds the element maching @a value and returns its index. + * @param value Value to find. + * @return Index of the element, or -1 if not found. + */ + dint indexOf(const Value &value) const; + + /** * Adds a value to the array. - * * @param value Value to add. Array gets ownership. - * * @return Reference to the array. */ ArrayValue &operator << (Value *value); /** * Adds a value to the array. - * * @param value Value to add. A duplicate of this value is added to the array. - * * @return Reference to the array. */ ArrayValue &operator << (Value const &value); /** * Returns a reference to a value in the array. - * * @param index Index of the element. - * * @return Element at the index. */ Value const &at(dint index) const; @@ -211,7 +210,7 @@ Value const &element(dint index) const; Value const &operator [] (dint index) const; - String asTextUsingInfoSyntax() const; + String asInfo() const; private: Elements::iterator indexToIterator(dint index); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/bank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/bank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/bank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/bank.h 2018-12-11 07:08:23.000000000 +0000 @@ -190,13 +190,13 @@ /** * Notified when a data item has been loaded to memory (cache level - * InMemory). May be called from the background thread, if one is running. + * InMemory). Notification are always called in the main thread. */ DENG2_DEFINE_AUDIENCE2(Load, void bankLoaded(DotPath const &path)) /** * Notified when a data item's cache level changes (in addition to the Load - * notification). + * notification). Notification are always called in the main thread. */ DENG2_DEFINE_AUDIENCE2(CacheLevel, void bankCacheLevelChanged(DotPath const &path, CacheLevel level)) @@ -287,6 +287,15 @@ bool has(DotPath const &path) const; /** + * Returns the source of an item. + * + * @param path Identifier of a data item. + * + * @return Source. + */ + ISource &source(const DotPath &path) const; + + /** * Iterates through the entire contents of the bank. * * @param func Function that gets called with the path of each item. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/bitfield.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/bitfield.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/bitfield.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/bitfield.h 2018-12-11 07:08:23.000000000 +0000 @@ -122,7 +122,7 @@ BitField(BitField const &other); BitField(Block const &data); - BitField &operator = (BitField const &other); + BitField &operator=(BitField const &other); /** * Sets the elements of the bit field. @@ -165,8 +165,8 @@ */ Block data() const; - bool operator == (BitField const &other) const; - bool operator != (BitField const &other) const; + bool operator==(BitField const &other) const; + bool operator!=(BitField const &other) const; /** * Determines which elements in this pack are different when compared to @a diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/block.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/block.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/block.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/block.h 2018-12-11 07:08:23.000000000 +0000 @@ -23,6 +23,7 @@ #include "../IByteArray" #include "../IBlock" #include "../ISerializable" +#include "../Writer" #include @@ -137,6 +138,14 @@ static Block join(QList const &blocks, Block const &sep = Block()); }; +template +Block md5Hash(Args... args) { + Block data; + Writer writer(data); + writer.writeMultiple(args...); + return data.md5Hash(); +} + } // namespace de #endif // LIBDENG2_BLOCK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/blockvalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/blockvalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/blockvalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/blockvalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -45,6 +45,7 @@ operator IByteArray &(); Block &block(); + Block const &block() const; /// Empties the block value. void clear(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/byteorder.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/byteorder.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/byteorder.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/byteorder.h 2018-12-11 07:08:23.000000000 +0000 @@ -40,7 +40,7 @@ * @param networkValue Value in network byte order. * @param hostValue Value in the host's host byte order. */ - virtual void networkToHost(duint16 const &networkValue, duint16 &hostValue) const = 0; + virtual void networkToHost(duint16 networkValue, duint16 &hostValue) const = 0; /** * Converts a 32-bit unsigned integer from network byte order to the host order. @@ -48,7 +48,7 @@ * @param networkValue Value in network byte order. * @param hostValue Value in the host's host byte order. */ - virtual void networkToHost(duint32 const &networkValue, duint32 &hostValue) const = 0; + virtual void networkToHost(duint32 networkValue, duint32 &hostValue) const = 0; /** * Converts a 64-bit unsigned integer from network byte order to the host order. @@ -56,7 +56,7 @@ * @param networkValue Value in network byte order. * @param hostValue Value in the host's host byte order. */ - virtual void networkToHost(duint64 const &networkValue, duint64 &hostValue) const = 0; + virtual void networkToHost(duint64 networkValue, duint64 &hostValue) const = 0; /** * Converts a 16-bit unsigned integer from host byte order to the network order. @@ -64,7 +64,7 @@ * @param hostValue Value in the host's host byte order. * @param networkValue Value in network byte order is written here. */ - virtual void hostToNetwork(duint16 const &hostValue, duint16 &networkValue) const = 0; + virtual void hostToNetwork(duint16 hostValue, duint16 &networkValue) const = 0; /** * Converts a 32-bit unsigned integer from host byte order to the network order. @@ -72,7 +72,7 @@ * @param hostValue Value in the host's host byte order. * @param networkValue Value in network byte order is written here. */ - virtual void hostToNetwork(duint32 const &hostValue, duint32 &networkValue) const = 0; + virtual void hostToNetwork(duint32 hostValue, duint32 &networkValue) const = 0; /** * Converts a 64-bit unsigned integer from host byte order to the network order. @@ -80,32 +80,32 @@ * @param hostValue Value in the host's host byte order. * @param networkValue Value in network byte order is written here. */ - virtual void hostToNetwork(duint64 const &hostValue, duint64 &networkValue) const = 0; + virtual void hostToNetwork(duint64 hostValue, duint64 &networkValue) const = 0; // The signed variants. - void hostToNetwork(dint16 const &hostValue, dint16 &networkValue) const; - void hostToNetwork(dint32 const &hostValue, dint32 &networkValue) const; - void hostToNetwork(dint64 const &hostValue, dint64 &networkValue) const; - void networkToHost(dint16 const &networkValue, dint16 &hostValue) const; - void networkToHost(dint32 const &networkValue, dint32 &hostValue) const; - void networkToHost(dint64 const &networkValue, dint64 &hostValue) const; + void hostToNetwork(dint16 hostValue, dint16 &networkValue) const; + void hostToNetwork(dint32 hostValue, dint32 &networkValue) const; + void hostToNetwork(dint64 hostValue, dint64 &networkValue) const; + void networkToHost(dint16 networkValue, dint16 &hostValue) const; + void networkToHost(dint32 networkValue, dint32 &hostValue) const; + void networkToHost(dint64 networkValue, dint64 &hostValue) const; // Floating point. - void hostToNetwork(dfloat const &hostValue, dfloat &networkValue) const; - void hostToNetwork(ddouble const &hostValue, ddouble &networkValue) const; - void networkToHost(dfloat const &networkValue, dfloat &hostValue) const; - void networkToHost(ddouble const &networkValue, ddouble &hostValue) const; + void hostToNetwork(dfloat hostValue, dfloat &networkValue) const; + void hostToNetwork(ddouble hostValue, ddouble &networkValue) const; + void networkToHost(dfloat networkValue, dfloat &hostValue) const; + void networkToHost(ddouble networkValue, ddouble &hostValue) const; // Convenience. template - T toNetwork(T const &hostValue) const { + T toNetwork(T hostValue) const { T networkValue; hostToNetwork(hostValue, networkValue); return networkValue; } template - T toHost(T const &networkValue) const { + T toHost(T networkValue) const { T hostValue; networkToHost(networkValue, hostValue); return hostValue; @@ -123,12 +123,12 @@ using ByteOrder::networkToHost; using ByteOrder::hostToNetwork; - void networkToHost(duint16 const &networkValue, duint16 &hostValue) const; - void networkToHost(duint32 const &networkValue, duint32 &hostValue) const; - void networkToHost(duint64 const &networkValue, duint64 &hostValue) const; - void hostToNetwork(duint16 const &hostValue, duint16 &networkValue) const; - void hostToNetwork(duint32 const &hostValue, duint32 &networkValue) const; - void hostToNetwork(duint64 const &hostValue, duint64 &networkValue) const; + void networkToHost(duint16 networkValue, duint16 &hostValue) const; + void networkToHost(duint32 networkValue, duint32 &hostValue) const; + void networkToHost(duint64 networkValue, duint64 &hostValue) const; + void hostToNetwork(duint16 hostValue, duint16 &networkValue) const; + void hostToNetwork(duint32 hostValue, duint32 &networkValue) const; + void hostToNetwork(duint64 hostValue, duint64 &networkValue) const; }; /// Network byte order is big endian. @@ -145,27 +145,27 @@ using ByteOrder::networkToHost; using ByteOrder::hostToNetwork; - void networkToHost(duint16 const &networkValue, duint16 &hostValue) const; - void networkToHost(duint32 const &networkValue, duint32 &hostValue) const; - void networkToHost(duint64 const &networkValue, duint64 &hostValue) const; - void hostToNetwork(duint16 const &hostValue, duint16 &networkValue) const; - void hostToNetwork(duint32 const &hostValue, duint32 &networkValue) const; - void hostToNetwork(duint64 const &hostValue, duint64 &networkValue) const; + void networkToHost(duint16 networkValue, duint16 &hostValue) const; + void networkToHost(duint32 networkValue, duint32 &hostValue) const; + void networkToHost(duint64 networkValue, duint64 &hostValue) const; + void hostToNetwork(duint16 hostValue, duint16 &networkValue) const; + void hostToNetwork(duint32 hostValue, duint32 &networkValue) const; + void hostToNetwork(duint64 hostValue, duint64 &networkValue) const; }; // Swaps the bytes of a 16-bit unsigned integer. -inline duint16 swap16(duint16 const &n) { +inline duint16 swap16(duint16 n) { return duint16((n & 0xff) << 8) | duint16((n & 0xff00) >> 8); } /// Swaps the bytes of a 32-bit unsigned integer. -inline duint32 swap32(duint32 const &n) { +inline duint32 swap32(duint32 n) { return ( ((n & 0xff) << 24) | ((n & 0xff00) << 8) | ((n & 0xff0000) >> 8) | ((n & 0xff000000) >> 24)); } /// Swaps the bytes in a 64-bit unsigned integer. -duint64 swap64(duint64 const &n); +duint64 swap64(duint64 n); /// Globally available big-endian byte order converter. DENG2_PUBLIC extern BigEndianByteOrder bigEndianByteOrder; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/conditionaltrigger.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/conditionaltrigger.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/conditionaltrigger.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/conditionaltrigger.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,70 @@ +/** @file conditionaltrigger.h Conditional trigger configurable via a Variable. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_CONDITIONALTRIGGER_H +#define LIBDENG2_CONDITIONALTRIGGER_H + +#include "../Variable" + +namespace de { + +/** + * Conditional trigger that calls a method + */ +class DENG2_PUBLIC ConditionalTrigger +{ +public: + ConditionalTrigger(); + + virtual ~ConditionalTrigger(); + + bool isValid() const; + + /** + * Sets the variable that defines the condition for the trigger. The variable's + * value can be a Text value or an Array with multiple Text values. If any of the + * values is a single asterisk ("*"), the trigger will be activated with any input. + * + * @param variable Variable for configuring the conditional trigger. + */ + void setCondition(Variable const &variable); + + Variable const &condition() const; + + /** + * Checks if a trigger will cause activation, and if so, call the appropriate + * callback methods. + * + * @param trigger Trigger to check. + * @return @c true if the trigger was activated, otherwise @c false. + */ + bool tryTrigger(String const &trigger); + + /** + * Called when the trigger is activated. + * @param trigger Trigger that caused activation. + */ + virtual void handleTriggered(String const &trigger) = 0; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBDENG2_CONDITIONALTRIGGER_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/dictionaryvalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/dictionaryvalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/dictionaryvalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/dictionaryvalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -98,6 +98,9 @@ */ ArrayValue *contentsAsArray(ContentSelection selection) const; + inline const Value &operator[](const Value &index) const { return element(index); } + inline Value & operator[](const Value &index) { return element(index); } + // Implementations of pure virtual methods. Text typeId() const; Value *duplicate() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/fifo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/fifo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/fifo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/fifo.h 2018-12-11 07:08:23.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #ifndef LIBDENG2_FIFO_H @@ -75,12 +75,12 @@ /** * Takes the oldest object in the buffer. * - * @return The oldest object in the buffer, or NULL if the buffer is empty. + * @return The oldest object in the buffer, or nullptr if the buffer is empty. * Caller gets ownership of the returned object. */ Type *take() { DENG2_GUARD(this); - if (_objects.empty()) return NULL; + if (_objects.empty()) return nullptr; Type *last = _objects.back(); _objects.pop_back(); return last; @@ -89,12 +89,12 @@ /** * Returns the oldest object in the buffer. * - * @return The oldest object in the buffer, or NULL if the buffer is empty. + * @return The oldest object in the buffer, or nullptr if the buffer is empty. * The object is not removed from the buffer. */ Type* tail() const { DENG2_GUARD(this); - if (_objects.empty()) return NULL; + if (_objects.empty()) return nullptr; return _objects.back(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/gzip.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/gzip.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/gzip.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/gzip.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,31 @@ +/** @file gzip.h Process gzip data with zlib. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_GZIP_H +#define DENG2_GZIP_H + +#include "../libcore.h" +#include "../Block" + +namespace de { + +DENG2_PUBLIC Block gDecompress(Block const &gzData); + +} // namespace de + +#endif // DENG2_GZIP_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/info.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/info.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/info.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/info.h 2018-12-11 07:08:23.000000000 +0000 @@ -20,9 +20,10 @@ #ifndef LIBDENG2_INFO_H #define LIBDENG2_INFO_H -#include "../String" #include "../NativePath" +#include "../Record" #include "../SourceLineTable" +#include "../String" #include #include @@ -246,6 +247,12 @@ */ void moveContents(BlockElement &destination); + /** + * Converts the contents of the block into a Record. + * @return Record with block elements. + */ + Record asRecord() const; + private: Info &_info; String _blockType; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/nonevalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/nonevalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/nonevalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/nonevalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -43,6 +43,9 @@ // Implements ISerializable. void operator >> (Writer &to) const; void operator << (Reader &from); + +public: + static const NoneValue &none(); }; } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/numbervalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/numbervalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/numbervalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/numbervalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -54,9 +54,11 @@ }; enum SemanticHint { - Boolean = 0x1, ///< The number is intended to be a boolean value. - Hex = 0x2, ///< The number is intended to be a hexadecimal value. - Generic = 0 ///< Generic number. + Boolean = 0x1, ///< The number is intended to be a boolean value. + Hex = 0x2, ///< The number is intended to be a hexadecimal value. + Int = 0x4, + UInt = 0x8, + Generic = 0 ///< Generic number. }; Q_DECLARE_FLAGS(SemanticHints, SemanticHint) @@ -64,9 +66,9 @@ explicit NumberValue(Number initialValue = 0, SemanticHints semantic = Generic); explicit NumberValue(dint64 initialInteger); explicit NumberValue(duint64 initialUnsignedInteger); - explicit NumberValue(dint32 initialInteger, SemanticHints semantic = Generic); - explicit NumberValue(duint32 initialUnsignedInteger, SemanticHints semantic = Generic); - explicit NumberValue(unsigned long initialUnsignedInteger, SemanticHints semantic = Generic); + explicit NumberValue(dint32 initialInteger, SemanticHints semantic = Int); + explicit NumberValue(duint32 initialUnsignedInteger, SemanticHints semantic = UInt); + explicit NumberValue(unsigned long initialUnsignedInteger, SemanticHints semantic = UInt); explicit NumberValue(bool initialBoolean); void setSemanticHints(SemanticHints hints); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/pathtree.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/pathtree.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/pathtree.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/pathtree.h 2018-12-11 07:08:23.000000000 +0000 @@ -235,6 +235,8 @@ */ Path path(QChar sep = '/') const; + DENG2_CAST_METHODS() + friend class PathTree; friend struct PathTree::Impl; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/record.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/record.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/record.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/record.h 2018-12-11 07:08:23.000000000 +0000 @@ -244,6 +244,8 @@ */ Variable *remove(String const &variableName); + Variable *tryRemove(String const &variableName); + /** * Adds a new variable to the record with a NoneValue. If there is an existing * variable with the given name, the old variable is deleted first. @@ -252,7 +254,7 @@ * * @return The new variable. */ - Variable &add(String const &variableName); + Variable &add(String const &variableName, Variable::Flags variableFlag = Variable::DefaultMode); /** * Adds a number variable to the record. The variable is set up to only accept @@ -263,7 +265,7 @@ * * @return The number variable. */ - Variable &addNumber(String const &variableName, Value::Number const &number); + Variable &addNumber(String const &variableName, Value::Number number); /** * Adds a number variable to the record with a Boolean semantic hint. The variable is @@ -392,7 +394,10 @@ Variable &set(String const &name, Value::Text const &value); /// @copydoc set() - Variable &set(String const &name, Value::Number const &value); + Variable &set(String const &name, Value::Number value); + + /// @copydoc set() + Variable &set(String const &name, const NumberValue &value); /// @copydoc set() Variable &set(String const &name, dint32 value); @@ -409,6 +414,15 @@ /// @copydoc set() Variable &set(String const &name, unsigned long value); + /// @copydoc set() + Variable &set(String const &name, Time const &value); + + /// @copydoc set() + Variable &set(String const &name, Block const &value); + + /// @copydoc set() + Variable &set(const String &name, const Record &value); + /** * Sets the value of a variable, creating the variable if it doesn't exist. * @@ -417,6 +431,10 @@ */ Variable &set(String const &name, ArrayValue *value); + Variable &set(String const &name, Value *value); + + Variable &set(String const &name, const Value &value); + /** * Appends a word to the value of the variable. * @@ -429,6 +447,8 @@ Variable &appendUniqueWord(String const &name, String const &word, String const &separator = " "); + Variable &appendMultipleUniqueWords(String const &name, String const &words, String const &separator = " "); + Variable &appendToArray(String const &name, Value *value); /** @@ -460,6 +480,10 @@ */ Variable const &operator [] (String const &name) const; + Variable *tryFind(String const &name); + + Variable const *tryFind(String const &name) const; + inline Variable &member(String const &name) { return (*this)[name]; } @@ -486,6 +510,10 @@ */ Record const &subrecord(String const &name) const; + dsize size() const; + + inline bool isEmpty() const { return size() == 0; } + /** * Returns a non-modifiable map of the members. */ @@ -595,6 +623,8 @@ */ Record const &parentRecordForMember(String const &name) const; + String asInfo() const; + // Implements ISerializable. void operator >> (Writer &to) const; void operator << (Reader &from); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/recordvalue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/recordvalue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/recordvalue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/recordvalue.h 2018-12-11 07:08:23.000000000 +0000 @@ -129,6 +129,9 @@ RecordValue *duplicateUnowned() const; + static RecordValue *takeRecord(Record *record); + static RecordValue *takeRecord(Record &&record); + public: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/string.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/string.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/string.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/string.h 2018-12-11 07:08:23.000000000 +0000 @@ -77,6 +77,8 @@ typedef dint size_type; + enum CaseSensitivity { CaseInsensitive, CaseSensitive }; + public: static size_type const npos; @@ -122,11 +124,30 @@ /// Returns the last character of the string. QChar last() const; - bool beginsWith(QString const &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { - return startsWith(s, cs); + bool beginsWith(QString const &s, CaseSensitivity cs = CaseSensitive) const { + return startsWith(s, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool beginsWith(QChar c, CaseSensitivity cs = CaseSensitive) const { + return startsWith(c, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool beginsWith(QLatin1String ls, CaseSensitivity cs = CaseSensitive) const { + return startsWith(ls, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool beginsWith(char const *ls, CaseSensitivity cs = CaseSensitive) const { + return beginsWith(QLatin1String(ls), cs); + } + + bool endsWith(QString const &s, CaseSensitivity cs = CaseSensitive) const { + return QString::endsWith(s, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool endsWith(QChar c, CaseSensitivity cs = CaseSensitive) const { + return QString::endsWith(c, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); + } + bool endsWith(QLatin1String ls, CaseSensitivity cs = CaseSensitive) const { + return QString::endsWith(ls, cs == CaseSensitive? Qt::CaseSensitive : Qt::CaseInsensitive); } - bool beginsWith(QChar const &c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const { - return startsWith(c, cs); + bool endsWith(char const *ls, CaseSensitivity cs = CaseSensitive) const { + return endsWith(QLatin1String(ls), cs); } String substr(int position, int n = -1) const { @@ -147,6 +168,8 @@ */ String concatenatePath(String const &path, QChar dirChar = '/') const; + String concatenateRelativePath(String const &path, QChar dirChar = '/') const; + /** * Does a path concatenation on this string and the argument. Note that if * @a path is an absolute path (starts with '/'), the result of the @@ -186,6 +209,12 @@ /// @return Copy of the string without whitespace. String rightStrip() const; + /// Replaces all sequences of whitespace with single space characters. + String normalizeWhitespace() const; + + /// Returns a copy of the string with matches removed. + String removed(QRegularExpression const &expr) const; + /// Returns a lower-case version of the string. String lower() const; @@ -255,7 +284,7 @@ * * @return Number of characters the two strings have in common from the left. */ - int commonPrefixLength(String const &str, Qt::CaseSensitivity sensitivity = Qt::CaseSensitive) const; + int commonPrefixLength(String const &str, CaseSensitivity sensitivity = CaseSensitive) const; /** * Converts the string to UTF-8 and returns it as a byte block. @@ -300,6 +329,20 @@ dint toInt(bool *ok = 0, int base = 10, IntConversionFlags flags = AllowOnlyWhitespace) const; /** + * Converts the string to a 32-bit unsigned integer. The behavior is the same as + * QString::toUInt(), with the exception that the default is to autodetect the + * base of the number. + * + * @param ok @c true is returned via this pointer if the conversion was + * successful. + * @param base Base for the number. + * + * @return 32-bit unsigned integer parsed from the string (@c *ok set to true). + * @c 0 if the conversion fails (@c *ok set to @c false). + */ + duint32 toUInt32(bool *ok = 0, int base = 0) const; + + /** * Adds a prefix to each line in the text. * * @param prefix Prefix text. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/time.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/time.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/time.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/time.h 2018-12-11 07:08:23.000000000 +0000 @@ -54,15 +54,15 @@ /** * Difference between two points in time. @ingroup types */ - class DENG2_PUBLIC Delta : public ISerializable + class DENG2_PUBLIC Span : public ISerializable { public: /** - * Constructs a time delta. + * Constructs a time span. * - * @param seconds Length of the delta. + * @param seconds Length of the time span. */ - Delta(ddouble seconds = 0) : _seconds(seconds) {} + Span(ddouble seconds = 0) : _seconds(seconds) {} /** * Conversion to the numeric type (floating-point seconds). @@ -81,30 +81,30 @@ return fequal(_seconds, d); } - inline Delta operator + (ddouble const &d) const { + inline Span operator + (ddouble const &d) const { return _seconds + d; } - inline Delta &operator += (ddouble const &d) { + inline Span &operator += (ddouble const &d) { _seconds += d; return *this; } - inline Delta operator - (ddouble const &d) const { + inline Span operator - (ddouble const &d) const { return _seconds - d; } - inline Delta &operator -= (ddouble const &d) { + inline Span &operator -= (ddouble const &d) { _seconds -= d; return *this; } - inline Delta &operator *= (ddouble const &d) { + inline Span &operator *= (ddouble const &d) { _seconds *= d; return *this; } - inline Delta &operator /= (ddouble const &d) { + inline Span &operator /= (ddouble const &d) { _seconds /= d; return *this; } @@ -112,7 +112,7 @@ duint64 asMicroSeconds() const; /** - * Convert the delta to milliseconds. + * Convert the time span to milliseconds. * * @return Milliseconds. */ @@ -124,15 +124,15 @@ ddouble asDays() const; - static Delta fromMilliSeconds(duint64 milliseconds) { - return Delta(milliseconds/1000.0); + static Span fromMilliSeconds(duint64 milliseconds) { + return Span(milliseconds/1000.0); } /** * Determines the amount of time passed since the beginning of the native * process (i.e., since creation of the high performance timer). */ - static Delta sinceStartOfProcess(); + static Span sinceStartOfProcess(); /** * Blocks the thread. @@ -156,6 +156,7 @@ ISODateOnly, CompilerDateTime, // Oct 7 2013 03:18:36 (__DATE__ __TIME__) HumanDate, ///< human-entered date (only with Time::fromText) + UnixLsStyleDateTime, }; public: @@ -165,7 +166,7 @@ Time(); Time(Time const &other); - + Time(Time &&moved); Time(QDateTime const &t); @@ -175,7 +176,7 @@ * * @param highPerformanceDelta Elapsed time since the high performance timer was started. */ - Time(Delta const &highPerformanceDelta); + Time(Span const &highPerformanceDelta); static Time invalidTime(); @@ -198,72 +199,72 @@ inline bool operator != (Time const &t) const { return !(*this == t); } /** - * Add a delta to the point of time. + * Add a time span to the point of time. * - * @param delta Delta to add. + * @param span Time span to add. * * @return Modified time. */ - Time operator + (Delta const &delta) const; + Time operator + (Span const &span) const; /** - * Subtract a delta from the point of time. + * Subtract a time span from the point of time. * - * @param delta Delta to subtract. + * @param span Time span to subtract. * * @return Modified time. */ - inline Time operator - (Delta const &delta) const { return *this + (-delta); } + inline Time operator - (Span const &span) const { return *this + (-span); } /** * Modify point of time. * - * @param delta Delta to add. + * @param span Time span to add. * * @return Reference to this Time. */ - Time &operator += (Delta const &delta); + Time &operator += (Span const &span); /** * Modify point of time. * - * @param delta Delta to subtract. + * @param span Time span to subtract. * * @return Reference to this Time. */ - inline Time &operator -= (Delta const &delta) { return *this += -delta; } + inline Time &operator -= (Span const &span) { return *this += -span; } /** * Difference between two times. * * @param earlierTime Time at some point before this time. */ - Delta operator - (Time const &earlierTime) const; + Span operator - (Time const &earlierTime) const; /** * Difference between this time and the current point of time. * Returns positive deltas if current time is past this time. * - * @return Delta. + * @return Span. */ - inline Delta since() const { return deltaTo(Time()); } + inline Span since() const { return deltaTo(Time()); } /** * Difference between current time and this time. * Returns positive deltas if current time is before this time. * - * @return Delta. + * @return Span. */ - inline Delta until() const { return Time().deltaTo(*this); } + inline Span until() const { return Time().deltaTo(*this); } /** * Difference to a later point in time. * * @param laterTime Time. * - * @return Delta. + * @return Span. */ - inline Delta deltaTo(Time const &laterTime) const { return laterTime - *this; } + inline Span deltaTo(Time const &laterTime) const { return laterTime - *this; } /** * Makes a text representation of the time (default is ISO format, e.g., @@ -301,7 +302,7 @@ */ dint asBuildNumber() const; - Delta highPerformanceTime() const; + Span highPerformanceTime() const; // Implements ISerializable. void operator >> (Writer &to) const; @@ -324,7 +325,7 @@ DENG2_PUBLIC QTextStream &operator << (QTextStream &os, Time const &t); -typedef Time::Delta TimeDelta; +typedef Time::Span TimeSpan; } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/value.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/value.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/value.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/value.h 2018-12-11 07:08:23.000000000 +0000 @@ -109,17 +109,18 @@ int asInt() const; /** + * Convert the value to a list of strings using asText(). + * @return List of text strings. + */ + StringList asStringList() const; + + /** * Convert the value to into a text string. All values have * to implement this. */ virtual Text asText() const = 0; template - bool is() const { - return dynamic_cast(this) != 0; - } - - template ValueType &as() { ValueType *t = dynamic_cast(this); if (!t) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/variable.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/variable.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/variable.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/variable.h 2018-12-11 07:08:23.000000000 +0000 @@ -116,7 +116,7 @@ * a NoneValue will be created for the variable. * @param varMode Mode flags. */ - Variable(String const &name = String(), Value *initial = 0, + Variable(String const &name = String(), Value *initial = nullptr, Flags const &varMode = DefaultMode); /** @@ -149,6 +149,13 @@ /** * Sets the value of the variable. + * + * @param textValue Text string. A new TextValue is created. + */ + Variable &operator = (String const &textValue); + + /** + * Sets the value of the variable. * * @param v New value. Variable takes a copy of this. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/waitablefifo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/waitablefifo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/waitablefifo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/waitablefifo.h 2018-12-11 07:08:23.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #ifndef LIBDENG2_WAITABLEFIFO_H @@ -42,10 +42,17 @@ post(); } - Type *take() { - wait(); + Type *take(TimeSpan const &timeOut = 0.0) { + wait(timeOut); return FIFO::take(); } + + Type *tryTake(TimeSpan const &timeOut = 0.0) { + if (tryWait(timeOut)) { + return FIFO::take(); + } + return nullptr; + } }; } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/writer.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/writer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/data/writer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/data/writer.h 2018-12-11 07:08:23.000000000 +0000 @@ -197,7 +197,7 @@ * Writes a fixed-size sequence of bytes to the destination buffer. * The size of the sequence is @em NOT included in the written data. * When reading, the reader must know the size beforehand - * (Reader::readPresetSize()). + * (Reader::readBytesFixedSize()). * * @param array Array to write. * @@ -208,6 +208,15 @@ /// Writes a writable object into the destination buffer. Writer &operator << (IWritable const &writable); + /** + * Begins or ends a span of data. The length of the span is written at the beginning + * (BeginSpan) as an uint32. Nothing is written at the end (EndSpan), however the + * writer is temporarily rewound for updating the length of the span. + * + * @param op BeginSpan or EndSpan. + * + * @return Reference to the Writer. + */ Writer &operator << (InlineOperation op); /** @@ -230,6 +239,17 @@ return *this; } + template + Writer &writeMultiple(Type const &value) { + return *this << value; + } + + template + Writer &writeMultiple(Type const &value, Args... args) { + *this << value; + return writeMultiple(args...); + } + /** * Returns the destination byte array used by the writer. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/directoryfeed.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/directoryfeed.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/directoryfeed.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/directoryfeed.h 2018-12-11 07:08:23.000000000 +0000 @@ -71,7 +71,13 @@ */ DirectoryFeed(NativePath const &nativePath, Flags const &mode = DefaultFlags); - virtual ~DirectoryFeed(); + /** + * Sets the file name pattern that determines which files are populated by the feed. + * By default, the pattern includes all files. + * + * @param namePattern File name pattern. + */ + void setNamePattern(const String &namePattern); String description() const; @@ -105,12 +111,19 @@ */ static File::Status fileStatus(NativePath const &nativePath); + static void setFileModifiedTime(NativePath const &nativePath, Time const &modifiedAt); + /** - * Creates and interprets a single native file and adds it to a folder. The created - * file is not governed by any feed and will not be pruned during folder pruning. + * Creates and interprets a single native file and adds it to a folder. + * + * The intended use of this method is to provide access to specific single native files + * anywhere in the native file system. The caller must prepare an empty or reusable folder + * where the new file object will be placed. A new DirectoryFeed will populate and prune + * the file. * * @param nativePath Native path of the source file. - * @param parentFolder Folder where to place the interpreted file. + * @param parentFolder Folder where to place the interpreted file. The existing contents + * (both files and feeds) of this folder will be cleared beforehand. * * @return Reference to the interpreted file. */ @@ -121,8 +134,7 @@ void populateFile(Folder const &folder, String const &entryName, PopulatedFiles &populated); private: - NativePath const _nativePath; - Flags _mode; + DENG2_PRIVATE(d) }; Q_DECLARE_OPERATORS_FOR_FLAGS(DirectoryFeed::Flags) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/file.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/file.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/file.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/file.h 2018-12-11 07:08:23.000000000 +0000 @@ -91,6 +91,13 @@ }; Q_DECLARE_FLAGS(Flags, Flag) + /// Type of file. + enum class Type + { + File, + Folder + }; + /** * The file object is about to be deleted. This may be, e.g., due to pruning or * because the parent is being deleted. @@ -105,15 +112,8 @@ class Status { public: - /// Type of file. - enum Type { - FILE = 0, - FOLDER = 1 - }; - - public: Status(dsize s = 0, Time const &modTime = Time::invalidTime()) - : size(s), modifiedAt(modTime), _type(FILE) {} + : size(s), modifiedAt(modTime), _type(Type::File) {} Status(Type t, dsize s = 0, Time const &modTime = Time::invalidTime()) : size(s), modifiedAt(modTime), _type(t) {} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/filesystem.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/filesystem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/filesystem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/filesystem.h 2018-12-11 07:08:23.000000000 +0000 @@ -50,6 +50,11 @@ * drive, one must call de::FileSystem::refresh() for the changes to be reflected * in the de::FileSystem index and tree. * + * Refreshing the file system can be done either synchronously or asynchrously. + * If the async mode is used, the user must be careful because files may + * disappear during pruning and population of folders. de::FileSystem provides + * a busy level that allows monitoring whether asynchronous tasks are ongoing. + * * ZIP (PK3) archives are visible in the libcore file system as Folder and * File instances just like regular native files are. This allows one to deploy * a large collection of resources as an archive and treat it at runtime just @@ -116,6 +121,12 @@ static FileSystem &get(); + enum BusyStatus { Idle, Busy }; + + /// File system busy level has become idle or is no longer idle. + /// Always called in the main thread. + DENG2_DEFINE_AUDIENCE2(Busy, void fileSystemBusyStatusChanged(BusyStatus)) + public: /** * Constructs a new file system. The file system needs to be manually @@ -140,14 +151,26 @@ void printIndex(); + /** + * Returns the root folder of the file system. + */ Folder &root(); - Folder const &root() const; + /** + * Returns the root folder of the file system. + */ + const Folder &root() const; + + /** + * Returns the root folder of the file system. + */ + static Folder &rootFolder(); /** - * Refresh the file system. Populates all folders with files from the feeds. + * Refresh the file system asynchronously. Populates all folders with files from + * the feeds. */ - void refresh(); + void refreshAsync(); enum FolderCreationBehavior { DontInheritFeeds = 0, ///< Subfolder will not have any feeds created for them. @@ -324,6 +347,28 @@ */ void deindex(File &file); + void timeChanged(Clock const &); + + void changeBusyLevel(int increment); + int busyLevel() const; + +public: + static void waitForIdle(); + + template + static T &locate(String const &path) { + return get().root().locate(path); + } + + template + static T *tryLocate(String const &path) { + return get().root().tryLocate(path); + } + + static inline bool exists(const String &path) { + return get().root().tryLocate(path) != nullptr; + } + enum CopyBehavior { PlainFileCopy = 0, @@ -342,24 +387,11 @@ * @param destinationPath Destination path. * @param behavior Copy behavior: which members to copy. */ - File ©Serialized(String const &sourcePath, String const &destinationPath, - CopyBehaviors behavior = DefaultCopyBehavior); - - String accessNativeLocation(NativePath const &nativePath, - File::Flags flags = File::ReadOnly); - - void timeChanged(Clock const &); + static File ©Serialized(String const &sourcePath, String const &destinationPath, + CopyBehaviors behavior = DefaultCopyBehavior); -public: - template - static T &locate(String const &path) { - return FileSystem::get().root().locate(path); - } - - template - static T *tryLocate(String const &path) { - return FileSystem::get().root().tryLocate(path); - } + static String accessNativeLocation(NativePath const &nativePath, + File::Flags flags = File::ReadOnly); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/folder.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/folder.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/folder.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/folder.h 2018-12-11 07:08:23.000000000 +0000 @@ -28,6 +28,7 @@ namespace de { +struct AsyncTask; class Feed; /** @@ -73,7 +74,9 @@ PopulateFullTree = 0x1, ///< The full tree is populated. PopulateOnlyThisFolder = 0x2, ///< Do not descend into subfolders while populating. PopulateAsync = 0x4, ///< Do not block until complete. - PopulateAsyncFullTree = PopulateAsync | PopulateFullTree + PopulateAsyncFullTree = PopulateAsync | PopulateFullTree, + + PopulateCalledRecursively = 0x1000, // internal use }; Q_DECLARE_FLAGS(PopulationBehaviors, PopulationBehavior) @@ -165,7 +168,18 @@ void destroyFile(String const &name); /** - * Removes all files in the folder. The files will be delted. If the files + * Removes a file from a folder. The file will be deleted. If it has an + * origin feed, the feed will be asked to remove the file as well, which + * means it will be removed in the source data as well as the file tree. + * + * @param name Name of path of file to remove, relative to this folder. + * + * @return @c true, if the file was deleted. @c false, if it did not exist. + */ + bool tryDestroyFile(String const &name); + + /** + * Removes all files in the folder. The files will be deleted. If the files * have origin feeds, the feed will be asked to remove the files as well. * The folder remains locked during the entire operation. */ @@ -244,7 +258,18 @@ template Type *tryLocate(String const &path) const { - return dynamic_cast(tryLocateFile(path)); + File *f = tryLocateFile(path); + if (!f) return nullptr; + if (auto *casted = dynamic_cast(f)) { + return casted; + } + if (&f->target() != f) { + if (auto *casted = dynamic_cast(&f->target())) { + // Link target also accepted, if type matches. + return casted; + } + } + return nullptr; } /** @@ -266,6 +291,11 @@ if (Type *casted = dynamic_cast(found)) { return *casted; } + if (found != &found->target()) { + if (Type *casted = dynamic_cast(&found->target())) { + return *casted; + } + } /// @throw NotFoundError Found file could not be cast to the /// requested type. throw NotFoundError("Folder::locate", @@ -333,9 +363,29 @@ Node const *tryGetChild(String const &name) const; public: - static void waitForPopulation(); + static Folder &root(); + + enum WaitBehavior { + OnlyInBackground, + BlockingMainThread, + }; + static void waitForPopulation(WaitBehavior waitBehavior = OnlyInBackground); + + /** + * When all folder population tasks are finished, performs a callback in the main + * thread. Does not block the main thread. If nothing is currently being populated, + * the callback is called immediately before the method returns. + * + * @param func Callback to be called in the main thread. + * + * @return Task handle. Can be ignored or added to an AsyncScope. + */ + static AsyncTask *afterPopulation(std::function func); + static bool isPopulatingAsync(); + static void checkDefaultSettings(); + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/idownloadable.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/idownloadable.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/idownloadable.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/idownloadable.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,50 @@ +/** @file idownloadable.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef IDOWNLOADABLE_H +#define IDOWNLOADABLE_H + +#include "../Asset" + +namespace de { + +/** + * Interface for downloadable objects. + * @ingroup fs + */ +class DENG2_PUBLIC IDownloadable +{ +public: + virtual ~IDownloadable() {} + + virtual Asset &asset() = 0; + + virtual Asset const &asset() const = 0; + + virtual dsize downloadSize() const = 0; + + virtual void download() = 0; + + virtual void cancelDownload() = 0; + + DENG2_DEFINE_AUDIENCE(Download, void downloadProgress(IDownloadable &, dsize remainingBytes)) +}; + +} // namespace de + +#endif // IDOWNLOADABLE_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/libraryfile.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/libraryfile.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/libraryfile.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/libraryfile.h 2018-12-11 07:08:23.000000000 +0000 @@ -55,6 +55,8 @@ * @param source Library file. Ownership transferred to LibraryFile. */ LibraryFile(File *source); + + LibraryFile(NativePath const &nativePath); /** * When the LibraryFile is deleted the library is gets unloaded. @@ -68,7 +70,7 @@ * * @return @c true, if the library has been loaded. */ - bool loaded() const { return _library != 0; } + bool loaded() const; /** * Provides access to the library. Automatically attempts to load the @@ -114,9 +116,9 @@ }; private: - Library *_library; + DENG2_PRIVATE(d) }; - + } // namespace de #endif /* LIBDENG2_LIBRARYFILE_H */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/Link doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/Link --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/Link 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/Link 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,2 @@ +#include "remote/link.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/linkfile.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/linkfile.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/linkfile.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/linkfile.h 2018-12-11 07:08:23.000000000 +0000 @@ -49,6 +49,8 @@ */ void setTarget(File const &file); + void setTarget(File const *fileOrNull); + /** * Returns the file's target. This is used for indirection when descending into * subfolders, to implement symbolic links. @@ -75,6 +77,9 @@ String describe() const; + // Stream access: + IIStream const &operator >> (IByteArray &bytes) const override; + // filesys::Node overrides: Node const *tryFollowPath(PathRef const &path) const; Node const *tryGetChild(String const &name) const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/NativeLink doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/NativeLink --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/NativeLink 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/NativeLink 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,2 @@ +#include "remote/nativelink.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/nativepath.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/nativepath.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/nativepath.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/nativepath.h 2018-12-11 07:08:23.000000000 +0000 @@ -157,6 +157,9 @@ bool isReadable() const; + inline void create() { createPath(*this); } + inline bool destroy() { return destroyPath(*this); } + /** * Returns the current native working path. */ @@ -185,7 +188,9 @@ * * @param nativePath Native directory to create. */ - static void createPath(NativePath const &nativePath); + static void createPath(const NativePath &nativePath); + + static bool destroyPath(const NativePath &nativePath); /** * Returns the native path separator character. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/packagefeed.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/packagefeed.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/packagefeed.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/packagefeed.h 2018-12-11 07:08:23.000000000 +0000 @@ -23,6 +23,7 @@ namespace de { +class Package; class PackageLoader; /** @@ -30,10 +31,17 @@ * * @ingroup fs */ -class PackageFeed : public Feed +class DENG2_PUBLIC PackageFeed : public Feed { public: - PackageFeed(PackageLoader &loader); + enum LinkMode { LinkIdentifier, LinkVersionedIdentifier }; + + typedef std::function Filter; + +public: + PackageFeed(PackageLoader &loader, LinkMode linkMode = LinkIdentifier); + + void setFilter(Filter filter); PackageLoader &loader(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/package.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/package.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/package.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/package.h 2018-12-11 07:08:23.000000000 +0000 @@ -95,21 +95,23 @@ virtual ~Package(); /** - * Returns the ".pack" file of the Package. In practice, this may be a ZIP folder, - * an regular folder, or a link to a DataBundle. You should use sourceFile() to - * access the file where the package's contents are stored in. + * Returns the ".pack" file of the Package. In practice, this may be a ZIP folder, an + * regular folder, or a link to a DataBundle. You should use sourceFile() to access + * the file in which the package's contents are actually stored. * * @return Package file. */ File const &file() const; /** - * Returns the original source file of the package, where the package's - * contents are being sourced from. This is usually the file referenced - * by the "path" member in the package metadata. + * Returns the original source file of the package, where the package's contents are + * being sourced from. This is usually the file referenced by the "path" member in + * the package metadata. */ File const &sourceFile() const; + bool sourceFileExists() const; + /** * Returns the package's root folder. */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/packageloader.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/packageloader.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/packageloader.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/packageloader.h 2018-12-11 07:08:23.000000000 +0000 @@ -153,9 +153,10 @@ void sortInPackageOrder(FileSystem::FoundFiles &filesToSort) const; /** - * Loads all the packages specified on the command line (using the @c -pkg option). + * Lists all the packages specified on the command line (using the @c -pkg option) + * so they can be loaded. The order matches the order of the command line parameters. */ - void loadFromCommandLine(); + StringList loadedFromCommandLine() const; /** * Looks up all the packages in the file system index. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/Query doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/Query --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/Query 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/Query 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,2 @@ +#include "remote/query.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/link.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/link.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/link.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/link.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,124 @@ +/** @file remote/link.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_FILESYS_LINK_H +#define DENG2_FILESYS_LINK_H + +#include "../../DictionaryValue" +#include "../../IdentifiedPacket" +#include "../../String" +#include "../Query" + +namespace de { + +class AsyncScope; +class File; +class Folder; + +namespace filesys { + +/** + * Base class for an active connection to a remote repository. Specialized subclasses + * handle specific types of repositories. One link instance is shared by all RemoteFeed + * instances accessing the same repository. + * + * @ingroup fs + */ +class DENG2_PUBLIC Link +{ +public: + enum State + { + Deinitialized, Initializing, Ready + }; + + typedef std::function Constructor; + +public: + virtual ~Link(); + + virtual void setLocalRoot(String const &rootPath); + + Folder &localRoot() const; + + String address() const; + + State state() const; + + /** + * Uses locally available indexes to determine which remote paths for a set of + * packages. + * + * @param packageIds Packages to locate. The identifiers may include versions. + * + * @return Paths for located packages. May contain fewer entries than was provided + * via @a packageIds -- empty if nothing was found. + */ + virtual PackagePaths locatePackages(StringList const &packageIds) const = 0; + + /** + * Returns a list of the categories in the repository. These can be used as tags + * for filtering. + * + * @return Category tags. + */ + virtual StringList categoryTags() const; + + /** + * Iterates the full list of all packages available in the repository. Note this + * may be large set of packages. + */ + virtual LoopResult forPackageIds(std::function func) const = 0; + + QueryId sendQuery(Query query); + + virtual File *populateRemotePath(String const &packageId, RepositoryPath const &path) const; + +protected: + Link(String const &address); + + AsyncScope &scope(); + + Query *findQuery(QueryId id); + + void cancelAllQueries(); + + void cleanupQueries(); + + //void packagePathsReceived(QueryId id, PackagePaths const &remotePaths); + + void metadataReceived(QueryId id, DictionaryValue const &metadata); + + void chunkReceived(QueryId id, duint64 startOffset, Block const &chunk, duint64 fileSize); + + virtual void wasConnected(); + + virtual void wasDisconnected(); + + virtual void handleError(QString errorMessage); + + virtual void transmit(Query const &query) = 0; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace filesys +} // namespace de + +#endif // DENG2_FILESYS_LINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/nativelink.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/nativelink.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/nativelink.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/nativelink.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,56 @@ +/** @file remote/nativelink.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_FILESYS_NATIVELINK_H +#define DENG2_FILESYS_NATIVELINK_H + +#include "link.h" + +namespace de { +namespace filesys { + +/** + * Link to a native Doomsday remote repository (see RemoteFeedUser on server). + */ +class DENG2_PUBLIC NativeLink : public Link +{ +public: + static String const URL_SCHEME; + + static Link *construct(String const &address); + + void setLocalRoot(String const &rootPath) override; + + PackagePaths locatePackages(StringList const &packageIds) const override; + + LoopResult forPackageIds(std::function func) const override; + +protected: + NativeLink(String const &address); + + void wasConnected() override; + void transmit(Query const &query) override; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace filesys +} // namespace de + +#endif // DENG2_FILESYS_NATIVELINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/query.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/query.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/query.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/query.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,85 @@ +/** @file remote/query.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_FILESYS_QUERY_H +#define DENG2_FILESYS_QUERY_H + +#include "../../AsyncCallback" +#include "../../DictionaryValue" +#include "../../IdentifiedPacket" + +namespace de { +namespace filesys { + +class Link; + +using QueryId = IdentifiedPacket::Id; + +struct DENG2_PUBLIC RepositoryPath +{ + Link const *link = nullptr; + String localPath; + String remotePath; + + RepositoryPath() = default; + + RepositoryPath(Link const &link, String const &localPath, String const &remotePath) + : link(&link) + , localPath(localPath) + , remotePath(remotePath) + {} +}; + +typedef QHash PackagePaths; + +typedef std::function FileMetadata; +typedef std::function FileContents; + +template +using Request = std::shared_ptr>; + +/** + * Query about information stored in the remote repository. The callbacks will + * be called when a reply is received. + */ +struct DENG2_PUBLIC Query +{ + // Query parameters: + QueryId id; + String path; + StringList packageIds; + + // Callbacks: + Request fileMetadata; + Request fileContents; + + // Internal status: + duint64 receivedBytes = 0; + duint64 fileSize = 0; + +public: + Query(Request req, String path); + Query(Request req, String path); + bool isValid() const; + void cancel(); +}; + +} // namespace filesys +} // namespace de + +#endif // DENG2_FILESYS_QUERY_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeed.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeed.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeed.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeed.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,51 @@ +/** @file remotefeed.h Feed for remote files. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_REMOTEFEED_H +#define LIBDENG2_REMOTEFEED_H + +#include "../../Feed" +#include "../../Address" + +namespace de { + +/** + * Feed that communicates with a remote backend and populates local placeholders for + * remote file data. + */ +class DENG2_PUBLIC RemoteFeed : public Feed +{ +public: + RemoteFeed(String const &repository, String const &remotePath = String("/")); + + String repository() const; + + String description() const; + PopulatedFiles populate(Folder const &folder); + bool prune(File &file) const; + +protected: + RemoteFeed(RemoteFeed const &parentFeed, String const &remotePath); + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBDENG2_REMOTEFEED_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedprotocol.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedprotocol.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedprotocol.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedprotocol.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,136 @@ +/** @file remotefeedprotocol.h Message protocol for remote feeds. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_REMOTEFEEDPROTOCOL_H +#define LIBDENG2_REMOTEFEEDPROTOCOL_H + +#include "../../DictionaryValue" +#include "../../File" +#include "../../IdentifiedPacket" +#include "../../Protocol" + +namespace de { + +/** + * Packet for requesting information about remote files. @ingroup fs + */ +class DENG2_PUBLIC RemoteFeedQueryPacket : public IdentifiedPacket +{ +public: + enum Query { ListFiles, FileContents }; + +public: + RemoteFeedQueryPacket(); + + void setQuery(Query query); + void setPath(String const &path); + + Query query() const; + String path() const; + + // Implements ISerializable. + void operator >> (Writer &to) const; + void operator << (Reader &from); + + static Packet *fromBlock(Block const &block); + +private: + Query _query; + String _path; +}; + +/** + * Packet that contains information about a set of files. Used as a response + * to the ListFiles query. @ingroup fs + */ +class DENG2_PUBLIC RemoteFeedMetadataPacket : public IdentifiedPacket +{ +public: + RemoteFeedMetadataPacket(); + + void addFile(File const &file, String const &prefix = String()); + void addFolder(Folder const &folder, String prefix = String()); + + DictionaryValue const &metadata() const; + + static File::Type toFileType(int value); + + // Implements ISerializable. + void operator >> (Writer &to) const; + void operator << (Reader &from); + + static Packet *fromBlock(Block const &block); + +private: + DictionaryValue _metadata; +}; + +/** + * Packet that contains a portion of a file. Used as a response to the FileContents + * query. @ingroup fs + */ +class DENG2_PUBLIC RemoteFeedFileContentsPacket : public IdentifiedPacket +{ +public: + RemoteFeedFileContentsPacket(); + + void setData(Block const &data); + void setStartOffset(dsize offset); + void setFileSize(dsize size); + + Block const &data() const; + dsize startOffset() const; + dsize fileSize() const; + + // Implements ISerializable. + void operator >> (Writer &to) const; + void operator << (Reader &from); + + static Packet *fromBlock(Block const &block); + +private: + dsize _startOffset; + dsize _fileSize; + Block _data; +}; + +/** + * Network message protocol for remote feeds. + */ +class DENG2_PUBLIC RemoteFeedProtocol : public Protocol +{ +public: + DENG2_ERROR(TypeError); + + enum PacketType + { + Unknown, + Query, ///< Query for file metadata or contents. + Metadata, ///< Response containing metadata. + FileContents, + }; + +public: + RemoteFeedProtocol(); + + static PacketType recognize(Packet const &packet); +}; + +} // namespace de + +#endif // LIBDENG2_REMOTEFEEDPROTOCOL_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedrelay.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedrelay.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedrelay.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefeedrelay.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,97 @@ +/** @file remotefeedrelay.h Manages one or more connections to remote feed repositories. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_REMOTEFEEDRELAY_H +#define LIBDENG2_REMOTEFEEDRELAY_H + +#include "../../RemoteFeed" +#include "../../Record" +#include "../../DictionaryValue" +#include "../../AsyncCallback" +#include "../Query" +#include "../Link" + +#include +#include + +namespace de { +namespace filesys { + +/** + * Connects to one or more remote file repositories and provides metadata and file + * contents over a network connection. + */ +class DENG2_PUBLIC RemoteFeedRelay +{ +public: + static RemoteFeedRelay &get(); + + enum Status { Disconnected, Connected }; + + DENG2_DEFINE_AUDIENCE2(Status, void remoteRepositoryStatusChanged(String const &address, Status)) + +public: + RemoteFeedRelay(); + + /** + * Defines a new type of remote repository link. The defined links are each + * offered a remote repository address, and the first one to create a Link instance + * based on the address will be used to communicate with the repository. + * + * @param linkConstructor Constructor method. + */ + void defineLink(Link::Constructor linkConstructor); + + void addRepository(String const &address, String const &localRootPath); + + void removeRepository(String const &address); + + Link *repository(String const &address) const; + + StringList repositories() const; + + bool isConnected(String const &address) const; + + /** + * Queries all the connected repositories for a set of packages. The local paths + * representing the remote packages are returned. + * + * @param packageIds Packages to find. + * + * @return Hash of [packageId -> local path]. + */ + PackagePaths locatePackages(StringList const &packageIds) const; + + Request fetchFileList(String const &repository, + String folderPath, + FileMetadata metadataReceived); + + Request fetchFileContents(String const &repository, + String filePath, + FileContents contentsReceived); + + QNetworkAccessManager &network(); + +private: + DENG2_PRIVATE(d) +}; + +} // namespace filesys +} // namespace de + +#endif // LIBDENG2_REMOTEFEEDRELAY_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefile.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefile.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefile.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/remotefile.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,73 @@ +/** @file remotefile.h Remote file. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_REMOTEFILE_H +#define LIBDENG2_REMOTEFILE_H + +#include "../../Asset" +#include "../../LinkFile" +#include "../../IDownloadable" + +namespace de { + +/** + * File that represents file/data on a remote backend and manages the making of a + * local copy of the data. + * + * RemoteFile provides status information as an Asset. + */ +class DENG2_PUBLIC RemoteFile : public LinkFile, public Asset, public IDownloadable +{ +public: + /// Data of the file has not yet been fetched. @ingroup errors + DENG2_ERROR(UnfetchedError); + + static String const CACHE_PATH; + +public: + RemoteFile(String const &name, String const &remotePath, Block const &remoteMetaId, + String const &repositoryAddress = String()); + + String describe() const override; + Block metaId() const override; + + /** + * Initiates downloading of the file contents from the remote backend. + */ + void download() override; + + void cancelDownload() override; + + Asset &asset() override; + + Asset const &asset() const override; + + dsize downloadSize() const override; + + void deleteCache(); + + // File streaming. + IIStream const &operator >> (IByteArray &bytes) const override; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBDENG2_REMOTEFILE_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/webhostedlink.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/webhostedlink.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/remote/webhostedlink.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/remote/webhostedlink.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,73 @@ +/** @file remote/webhostedlink.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_FILESYS_WEBHOSTEDLINK_H +#define DENG2_FILESYS_WEBHOSTEDLINK_H + +#include "../Link" +#include "../../PathTree" + +namespace de { +namespace filesys { + +/** + * Repository of files hosted on a web server as a file tree. Assumed to come + * with a Unix-style "ls-laR.gz" directory tree index (e.g., an idgames mirror). + */ +class DENG2_PUBLIC WebHostedLink : public Link +{ +public: + struct DENG2_PUBLIC FileEntry : public PathTree::Node + { + duint64 size = 0; + Time modTime; + + FileEntry(PathTree::NodeArgs const &args) : Node(args) {} + FileEntry() = delete; + + Block metaId(Link const &link) const; + }; + + using FileTree = PathTreeT; + +public: + WebHostedLink(String const &address, String const &indexPath); + + PackagePaths locatePackages(StringList const &packageIds) const override; + +protected: + virtual void setFileTree(FileTree *tree); + + FileTree const &fileTree() const; + + FileEntry const *findFile(Path const &path) const; + + virtual void parseRepositoryIndex(QByteArray data) = 0; + + virtual String findPackagePath(String const &packageId) const = 0; + + void transmit(Query const &query) override; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace filesys +} // namespace de + +#endif // DENG2_FILESYS_WEBHOSTEDLINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/staticlibraryfeed.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/staticlibraryfeed.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/staticlibraryfeed.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/staticlibraryfeed.h 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,41 @@ +/** @file staticlibraryfeed.h + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef DENG2_STATICLIBRARYFEED_H +#define DENG2_STATICLIBRARYFEED_H + +#include "../Feed" + +namespace de { + +/** + * Feed for populating LibraryFiles representing imported static libraries. + */ +class StaticLibraryFeed : public Feed +{ +public: + StaticLibraryFeed(); + + String description() const; + PopulatedFiles populate(Folder const &folder); + bool prune(File &file) const; +}; + +} // namespace de + +#endif // DENG2_STATICLIBRARYFEED_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/WebHostedLink doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/WebHostedLink --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/filesys/WebHostedLink 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/filesys/WebHostedLink 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,2 @@ +#include "remote/webhostedlink.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/IDownloadable doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/IDownloadable --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/IDownloadable 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/IDownloadable 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,3 @@ +#include "filesys/idownloadable.h" + + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/ISizeRule doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/ISizeRule --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/ISizeRule 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/ISizeRule 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1,2 @@ +#include "widgets/isizerule.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/libcore.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/libcore.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/libcore.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/libcore.h 2018-12-11 07:08:24.000000000 +0000 @@ -159,6 +159,12 @@ # define DENG2_NORETURN __attribute__((__noreturn__)) #endif +#if defined (DENG_IOS) +# define DENG2_VISIBLE_SYMBOL __attribute__((visibility("default"))) +#else +# define DENG2_VISIBLE_SYMBOL +#endif + #ifndef NDEBUG # define DENG2_DEBUG DENG2_EXTERN_C DENG2_PUBLIC void LogBuffer_Flush(void); @@ -194,6 +200,8 @@ out = ""; \ for (i = 0; i < frames; ++i) { out.append(strs[i]); out.append('\n'); } \ free(strs); } +# else +# define DENG2_PRINT_BACKTRACE() # endif #endif @@ -233,6 +241,9 @@ #define DENG2_ESC(StringLiteral) "\x1b" StringLiteral #define _E(Code) DENG2_ESC(#Code) +#define DENG2_OFFSET_PTR(type, member) \ + reinterpret_cast(offsetof(type, member)) + /** * Macro for defining an opaque type in the C wrapper API. */ @@ -455,12 +466,14 @@ template inline X_ &expectedAs(T_ *ptr) { if (auto *t = maybeAs(ptr)) return *t; + DENG2_ASSERT(false); throw CastError(QString("Cannot cast %1 to %2").arg(DENG2_TYPE_NAME(T_)).arg(DENG2_TYPE_NAME(X_))); } template inline X_ const &expectedAs(T_ const *ptr) { if (auto const *t = maybeAs(ptr)) return *t; + DENG2_ASSERT(false); throw CastError(QString("Cannot cast %1 to %2").arg(DENG2_TYPE_NAME(T_)).arg(DENG2_TYPE_NAME(X_))); } @@ -574,6 +587,12 @@ return forcedCast.target; } +template +inline ToType functionAssign(ToType &dest, FromType src) +{ + return dest = de::function_cast(src); +} + /** * Clears a region of memory. Size of the region is the size of Type. * @param t Reference to the memory. @@ -616,6 +635,19 @@ return out; } +template > +inline OutContainer map(const InContainer &input, Func func) { + OutContainer out; + Inserter ins(out); + for (const auto &i : input) { + *ins++ = func(i); + } + return out; +} + template inline ContainerType filter(ContainerType const &c, std::function func) { @@ -723,7 +755,9 @@ DENG2_PROTOCOL_2_0_0 = 3, - DENG2_PROTOCOL_LATEST = DENG2_PROTOCOL_2_0_0 + DENG2_PROTOCOL_2_1_0 = 3, + + DENG2_PROTOCOL_LATEST = DENG2_PROTOCOL_2_1_0 }; //@{ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/math.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/math.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/math.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/math.h 2018-12-11 07:08:24.000000000 +0000 @@ -39,14 +39,14 @@ */ //#undef PI -ddouble const PI = 3.1415926535897932384626433832795028841971693993751; -dfloat const PIf = dfloat(PI); -ddouble const EPSILON = 1.0e-7; -dfloat const FLOAT_EPSILON = 1.0e-5f; +const ddouble PI = 3.1415926535897932384626433832795028841971693993751; +const dfloat PIf = dfloat(PI); +const ddouble EPSILON = 1.0e-7; +const dfloat FLOAT_EPSILON = 1.0e-5f; /// Absolute value. template -inline Type abs(Type const &a) { +inline Type abs(Type a) { if (a < Type(0)) { return -a; } @@ -54,54 +54,54 @@ } // Special case, this is never negative. -inline duint abs(duint const &a) { +inline duint abs(duint a) { return a; } template -inline Type sign(Type const &a) { +inline Type sign(Type a) { if (a < 0) return Type(-1); else return Type(1); } /// Minimum of two values. template -inline Type const &min(Type const &a, Type const &b) { +inline Type min(Type a, Type b) { return (a < b? a : b); } /// Minimum of three values. template -inline Type const &min(Type const &a, Type const &b, Type const &c) { +inline Type min(Type a, Type b, Type c) { return min(a, min(b, c)); } /// Maximum of two values. template -inline Type const &max(Type const &a, Type const &b) { +inline Type max(Type a, Type b) { return (a > b? a : b); } /// Maximum of three values. template -inline Type const &max(Type const &a, Type const &b, Type const &c) { +inline Type max(Type a, Type b, Type c) { return max(a, max(b, c)); } /// Clamp value within range. template -inline Type clamp(Type const &low, Type const &value, Type const &high) { +inline Type clamp(Type low, Type value, Type high) { return min(max(value, low), high); } /// Clamp value within @a lowHighLimit and @a -lowHighLimit. template -inline Type clamp(Type const &value, Type const &lowHighLimit) { +inline Type clamp(Type value, Type lowHighLimit) { return clamp(-lowHighLimit, value, lowHighLimit); } /// Wrap value within range [low, high). template -Type wrap(Type value, Type const &low, Type const &high) { +Type wrap(Type value, Type low, Type high) { DENG2_ASSERT(high > low); Type const range = high - low; while (value < low) value += range; @@ -110,42 +110,44 @@ } template -inline Type squared(Type const &value) { return value * value; } +inline Type squared(Type value) { return value * value; } template -inline Type cubed(Type const &value) { return value * value * value; } +inline Type cubed(Type value) { return value * value * value; } template -inline Type round(dfloat const &value) { +inline Type round(dfloat value) { return Type(std::floor(value + 0.5f)); } -inline dint roundi(dfloat const &value) { return round(value); } -inline dfloat roundf(dfloat const &value) { return round(value); } +inline dint roundi(dfloat value) { return round(value); } +inline dfloat roundf(dfloat value) { return round(value); } template -inline Type round(ddouble const &value) { +inline Type round(ddouble value) { return Type(std::floor(value + 0.5)); } -inline dint32 floor(dfloat const &value) { +inline dint64 roundi(ddouble value) { return round(value); } + +inline dint32 floor(dfloat value) { return dint32(std::floor(value)); } -inline dint64 floor(ddouble const &value) { +inline dint64 floor(ddouble value) { return dint64(std::floor(value)); } -inline dint32 ceil(dfloat const &value) { +inline dint32 ceil(dfloat value) { return dint32(std::ceil(value)); } -inline dint64 ceil(ddouble const &value) { +inline dint64 ceil(ddouble value) { return dint64(std::ceil(value)); } template -inline Type fract(Type const &value) { +inline Type fract(Type value) { return value - std::floor(value); } @@ -174,25 +176,25 @@ } template -inline Type degreeToRadian(Type const °ree) { - return degree / Type(180) * PI; +inline Type degreeToRadian(Type degree) { + return degree * PI / Type(180); } template -inline Type radianToDegree(Type const &radian) { - return radian / PI * Type(180); +inline Type radianToDegree(Type radian) { + return radian * Type(180) / PI; } /// General comparison function. template -inline dint cmp(Type const &a, Type const &b) { +inline dint cmp(Type a, Type b) { if (a < b) return -1; if (a > b) return 1; return 0; } template -IntType ceilPow2(IntType const &num) { +IntType ceilPow2(IntType num) { IntType cumul; for (cumul = 1; num > cumul; cumul <<= 1) {} return cumul; @@ -206,21 +208,26 @@ * @param pos Normalized interpolation point [0..1]. */ template -inline Type lerp(Type const &start, Type const &end, float pos) { +inline Type lerp(Type start, Type end, float pos) { return end * pos + (start * (1.f - pos)); } /** - * @return Random floating-point value in the range [0, 1]. + * @return Random floating-point value in the range [0, 1). + */ +DENG2_PUBLIC float randf(); + +/** + * @return Random unsigned integer in the range [0, 4294967295]. */ -inline float frand() { return float(qrand()) / float(RAND_MAX); } +DENG2_PUBLIC duint32 randui32(); /** @} */ /** * Calculates the CRC32 checksum of the contents of byte array @a bytes. */ -DENG2_PUBLIC duint32 crc32(IByteArray const &bytes); +DENG2_PUBLIC duint32 crc32(const IByteArray &bytes); } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/address.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/address.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/address.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/address.h 2018-12-11 07:08:24.000000000 +0000 @@ -53,9 +53,9 @@ Address(Address const &other); - Address &operator = (Address const &other); + Address &operator=(Address const &other); - bool operator < (Address const &other) const; + bool operator<(Address const &other) const; /** * Checks two addresses for equality. @@ -64,7 +64,7 @@ * * @return @c true if the addresses are equal. */ - bool operator == (Address const &other) const; + bool operator==(Address const &other) const; bool isNull() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/beacon.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/beacon.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/beacon.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/beacon.h 2018-12-11 07:08:24.000000000 +0000 @@ -75,7 +75,7 @@ * is zero or negative, discovery will not end. * @param interval Interval between query broadcasts. */ - void discover(TimeDelta const &timeOut, TimeDelta const &interval = TimeDelta(1.0)); + void discover(TimeSpan const &timeOut, TimeSpan const &interval = TimeSpan(1.0)); QList
foundHosts() const; Block messageFromHost(Address const &host) const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/identifiedpacket.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/identifiedpacket.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/identifiedpacket.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/identifiedpacket.h 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #ifndef LIBDENG2_IDENTIFIEDPACKET_H @@ -44,6 +44,8 @@ */ IdentifiedPacket(Type const &type, Id i = 0); + void setId(Id id); + /// Returns the id of the packet. Id id() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/packet.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/packet.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/packet.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/packet.h 2018-12-11 07:08:24.000000000 +0000 @@ -25,6 +25,8 @@ #include "../String" #include "../Reader" +#include + namespace de { class String; @@ -38,13 +40,17 @@ class DENG2_PUBLIC Packet : public ISerializable { public: + DENG2_CAST_METHODS() + /// While deserializing, an invalid type identifier was encountered. @ingroup errors DENG2_SUB_ERROR(DeserializationError, InvalidTypeError); + typedef std::array Type; + /// Length of a type identifier. static dint const TYPE_SIZE = 4; - typedef String Type; + static Type typeFromString(char const *fourcc); public: /** @@ -52,7 +58,7 @@ * * @param type Type identifier of the packet. */ - Packet(Type const &type); + explicit Packet(Type const &type); virtual ~Packet() {} @@ -88,7 +94,7 @@ /** * Sets the type identifier. * - * @param t Type identifier. Must be exactly TYPE_SIZE characters long. + * @param t Type identifier. */ void setType(Type const &t); @@ -100,10 +106,10 @@ * @param from Reader. * @param type Packet identifier. */ - static bool checkType(Reader &from, String const &type); + static bool checkType(Reader &from, Type const &type); template - static PacketType *constructFromBlock(Block const &block, char const *packetTypeIdentifier) + static PacketType *constructFromBlock(Block const &block, Type const &packetTypeIdentifier) { Reader from(block); if (checkType(from, packetTypeIdentifier)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/socket.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/socket.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/net/socket.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/net/socket.h 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #ifndef LIBDENG2_SOCKET_H @@ -42,6 +42,10 @@ * * ListenSocket constructs Socket instances for incoming connections. * + * Note that Socket instances must always be used in the same thread as ListenSocket. + * Socket uses a background thread for compressing large messages before sending. This + * means they may be sent out-of-order with regards to all other messages. + * * @ingroup net */ class DENG2_PUBLIC Socket : public QObject, public Transmitter @@ -83,7 +87,7 @@ * @param address Address to connect to. * @param timeOut Maximum time to wait for connection. */ - Socket(Address const &address, TimeDelta const &timeOut); + Socket(Address const &address, TimeSpan const &timeOut); virtual ~Socket(); @@ -93,7 +97,7 @@ * * @param address Address to connect to. */ - void connect(Address const &address); + void open(Address const &address); /** * Opens a connection to a host and returns immediately. If the IP address @@ -107,7 +111,7 @@ * optional port appended (e.g., "myhost.com:13209"). * @param defaultPort Port number to use if not specified in the first argument. */ - void connectToDomain(String const &domainNameWithOptionalPort, duint16 defaultPort = 0); + void open(String const &domainNameWithOptionalPort, duint16 defaultPort = 0); /** * Returns the currently active channel. @@ -121,6 +125,19 @@ */ void setChannel(duint number); + /** + * Specifies whether all sent messages need to be written out in the order they have + * been sent. The default is to retain order. + * + * If the messaging protocol in use does not require messages to be ordered, setting + * this to @c false allows Socket to compress large messages in a background thread + * and send them when ready, instead of blocking. + * + * @param retainOrder @c true to keep send order, @c false to allow order to be + * unpredictable. + */ + void setRetainOrder(bool retainOrder); + // Implements Transmitter. /** * Sends the given data over the socket. Copies the data into @@ -201,12 +218,19 @@ */ void setQuiet(bool noLogOutput); + // Statistics: + static void resetCounters(); + static duint64 sentUncompressedBytes(); + static duint64 sentBytes(); + static double outputBytesPerSecond(); + signals: void addressResolved(); void connected(); void messagesReady(); void disconnected(); void error(QString errorMessage); + void allSent(); public slots: void socketDisconnected(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeed doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeed --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeed 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeed 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "filesys/remote/remotefeed.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeedProtocol doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeedProtocol --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeedProtocol 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeedProtocol 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "filesys/remote/remotefeedprotocol.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeedRelay doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeedRelay --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFeedRelay 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFeedRelay 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "filesys/remote/remotefeedrelay.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFile doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFile --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/RemoteFile 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/RemoteFile 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "filesys/remote/remotefile.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scheduler.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scheduler.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scheduler.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scheduler.h 2018-12-11 07:08:24.000000000 +0000 @@ -1,6 +1,6 @@ -/** @file scheduler.h Script scheduling utility. +/** @file scheduler.h Scheduler for scripts and timelines. * - * @authors Copyright (c) 2015-2017 Jaakko Keränen + * @authors Copyright (c) 2017 Jaakko Keränen * * @par License * LGPL: http://www.gnu.org/licenses/lgpl.html @@ -19,23 +19,12 @@ #ifndef LIBDENG2_SCHEDULER_H #define LIBDENG2_SCHEDULER_H -#include "../libcore.h" -#include "../Time" -#include "../String" +#include "../Timeline" namespace de { -class Script; -class Record; - /** - * Script scheduling utility. - * - * Scheduler owns the parsed scripts, but does not execute them. Use Scheduler::Clock - * to execute scripts. There can be any number of Scheduler::Clock instances operating - * on a single schedule. - * - * @ingroup script + * Scheduler for scripts and timelines. */ class DENG2_PUBLIC Scheduler { @@ -45,62 +34,35 @@ void clear(); /** - * Sets the execution context, i.e., global namespace for the scripts. All - * scripts of the scheduler run in the same context. + * Starts executing a timeline. The timeline object will be deleted when the + * finished. The timeline's context is used for execution. * - * @param context Global namespace. + * @param timeline Timeline object. Scheduler takes ownership. + * @param name Name for the started timeline. If empty, a unique name will + * be generated. + * @return Name of the started timeline. */ - void setContext(Record &context); - - Record *context() const; + String start(Timeline *timeline, String const &name = String()); /** - * Adds a new script to the scheduler. - * - * @param at Point in time when the script is to be executed. - * @param source Script source. This will be parsed before the method returns. - * @param sourcePath Path where the source comes from. + * Starts executing a shared timeline. * - * @return Scheduled Script (owned by Scheduler). + * @param sharedTimeline Timeline object. Scheduler does not take ownership. + * @param context Context where to execute the timeline. + * @param name Name for the started timeline instance. If empty, a unique + * name will be generated. + * @return Name of the started timeline. */ - Script &addScript(TimeDelta at, String const &source, String const &sourcePath = ""); + String start(Timeline const &sharedTimeline, Record *context, String const &name = String()); - void addFromInfo(Record const &timelineRecord); + /** + * Stops a running timeline. + * + * @param name Timeline name. + */ + void stop(String const &name); - class DENG2_PUBLIC Clock - { - public: - Clock(Scheduler const &schedule, Record *context = nullptr); - - /** - * Returns the current time of the clock. - */ - TimeDelta at() const; - - /** - * Rewinds the clock back to zero. - * - * @param toTime Rewind destination time. - */ - void rewind(TimeDelta const &toTime = 0.0); - - /** - * Advances the current time of the clock and executes any scripts whose - * execution time has arrived. - * - * @param elapsed Time elapsed since the previous call. - */ - void advanceTime(TimeDelta const &elapsed); - - /** - * Checks if there are no more scheduled sheduler is out of scheduled scripts. - * @return - */ - bool isFinished() const; - - private: - DENG2_PRIVATE(d) - }; + void advanceTime(TimeSpan const &elapsed); private: DENG2_PRIVATE(d) @@ -109,4 +71,3 @@ } // namespace de #endif // LIBDENG2_SCHEDULER_H - diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptedinfo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptedinfo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptedinfo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptedinfo.h 2018-12-11 07:08:24.000000000 +0000 @@ -201,6 +201,8 @@ static bool isFalse(RecordAccessor const &rec, String const &name, bool defaultValue = true /* assume false if missing */); + static bool isFalse(String const &token); + static bool isTrue(Value const &value); static bool isTrue(RecordAccessor const &rec, String const &name, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptsystem.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptsystem.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptsystem.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/scriptsystem.h 2018-12-11 07:08:24.000000000 +0000 @@ -68,9 +68,20 @@ void removeNativeModule(String const &name); + bool nativeModuleExists(const String &name) const; + Record &nativeModule(String const &name); /** + * Returns a native or an imported module. + * + * @param name Name of the module. + * + * @return Module namespace. + */ + Record &operator[](const String &nativeModuleName); + + /** * Returns a list of the names of all the existing native modules. * * @return List of module names. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/statement.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/statement.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/statement.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/statement.h 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #ifndef LIBDENG2_STATEMENT_H @@ -59,21 +59,20 @@ static Statement *constructFrom(Reader &from); protected: - typedef dbyte SerialId; - - enum SerialIds { - ASSIGN, - CATCH, - EXPRESSION, - FLOW, - FOR, - FUNCTION, - IF, - PRINT, - TRY, - WHILE, - DELETE, - SCOPE + enum class SerialId : dbyte + { + Assign, + Catch, + Expression, + Flow, + For, + Function, + If, + Print, + Try, + While, + Delete, + Scope, }; private: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/timeline.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/timeline.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/scriptsys/timeline.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/scriptsys/timeline.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,115 @@ +/** @file timeline.h Script scheduling utility. + * + * @authors Copyright (c) 2015-2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_TIMELINE_H +#define LIBDENG2_TIMELINE_H + +#include "../libcore.h" +#include "../Time" +#include "../String" + +namespace de { + +class Script; +class Record; + +/** + * Collection of scripts to be run at specified points in time. + * + * Timeline owns the parsed scripts, but does not execute them. Use Timeline::Clock + * to execute scripts. There can be any number of Timeline::Clock instances operating + * on a single timeline. + * + * @ingroup script + */ +class DENG2_PUBLIC Timeline +{ +public: + Timeline(); + + void clear(); + + /** + * Sets the execution context, i.e., global namespace for the scripts. All + * scripts of the timeline run in the same context. + * + * @param context Global namespace. + */ + void setContext(Record &context); + + Record *context() const; + + /** + * Adds a new script to the timeline. + * + * @param at Point in time when the script is to be executed. + * @param source Script source. This will be parsed before the method returns. + * @param sourcePath Path where the source comes from. + * + * @return Scheduled Script (owned by Timeline). + */ + Script &addScript(TimeSpan at, String const &source, String const &sourcePath = ""); + + void addFromInfo(Record const &timelineRecord); + + /** + * Clock for executing a timeline. + */ + class DENG2_PUBLIC Clock + { + public: + Clock(Timeline const &timeline, Record *context = nullptr); + + /** + * Returns the current time of the clock. + */ + TimeSpan at() const; + + /** + * Rewinds the clock back to zero. + * + * @param toTime Rewind destination time. + */ + void rewind(TimeSpan const &toTime = 0.0); + + /** + * Advances the current time of the clock and executes any scripts whose + * execution time has arrived. + * + * @param elapsed Time elapsed since the previous call. + */ + void advanceTime(TimeSpan const &elapsed); + + /** + * Checks if there are no more scheduled sheduler is out of scheduled scripts. + * @return + */ + bool isFinished() const; + + private: + DENG2_PRIVATE(d) + }; + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBDENG2_TIMELINE_H + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/StaticLibraryFeed doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/StaticLibraryFeed --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/StaticLibraryFeed 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/StaticLibraryFeed 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "filesys/staticlibraryfeed.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/Timeline doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/Timeline --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/Timeline 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/Timeline 2018-12-11 07:08:23.000000000 +0000 @@ -0,0 +1 @@ +#include "scriptsys/timeline.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animation.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animation.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animation.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animation.h 2018-12-11 07:08:24.000000000 +0000 @@ -42,6 +42,7 @@ enum Style { Linear, EaseOut, + EaseOutSofter, EaseIn, EaseBoth, Bounce, @@ -57,11 +58,9 @@ Animation &operator = (Animation const &other); void setStyle(Style s); - void setStyle(Style style, float bounce); Style style() const; - float bounce() const; /** @@ -72,9 +71,9 @@ * This includes @a startDelay. * @param startDelay Number of seconds to wait before starting the transition. */ - void setValue(float toValue, TimeDelta transitionSpan = 0, TimeDelta startDelay = 0); + void setValue(float toValue, TimeSpan transitionSpan = 0, TimeSpan startDelay = 0); - void setValue(int toValue, TimeDelta transitionSpan = 0, TimeDelta startDelay = 0); + void setValue(int toValue, TimeSpan transitionSpan = 0, TimeSpan startDelay = 0); /** * Starts a new transition. @@ -85,7 +84,7 @@ * This includes @a startDelay. * @param startDelay Number of seconds to wait before starting the transition. */ - void setValueFrom(float fromValue, float toValue, TimeDelta transitionSpan = 0, TimeDelta startDelay = 0); + void setValueFrom(float fromValue, float toValue, TimeSpan transitionSpan = 0, TimeSpan startDelay = 0); /** * Current value. @@ -112,12 +111,12 @@ /** * Number of seconds remaining in the ongoing transition. */ - TimeDelta remainingTime() const; + TimeSpan remainingTime() const; /** * Number of seconds for the entire transition. */ - TimeDelta transitionTime() const; + TimeSpan transitionTime() const; /** * Move the current value and the target value by @a valueDelta. @@ -177,9 +176,9 @@ */ static void setClock(Clock const *clock); - static Time currentTime(); + static TimeSpan currentTime(); - static Animation range(Style style, float from, float to, TimeDelta span, TimeDelta delay = 0); + static Animation range(Style style, float from, float to, TimeSpan span, TimeSpan delay = 0); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animationrule.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animationrule.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animationrule.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animationrule.h 2018-12-11 07:08:24.000000000 +0000 @@ -47,11 +47,11 @@ * @param transition Transition time to reach the current or future target values. * @param style Animation style. */ - explicit AnimationRule(Rule const &target, TimeDelta transition, Animation::Style style = Animation::EaseOut); + explicit AnimationRule(Rule const &target, TimeSpan transition, Animation::Style style = Animation::EaseOut); - void set(float target, TimeDelta transition = 0, TimeDelta delay = 0); + void set(float target, TimeSpan transition = 0, TimeSpan delay = 0); - void set(Rule const &target, TimeDelta transition = 0, TimeDelta delay = 0); + void set(Rule const &target, TimeSpan transition = 0, TimeSpan delay = 0); /** * Sets the animation style of the rule. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animationvector.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animationvector.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/animationvector.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/animationvector.h 2018-12-11 07:08:24.000000000 +0000 @@ -40,13 +40,13 @@ return *this; } - void setValue(Vector2f const &vector, TimeDelta transitionSpan = 0.0) + void setValue(Vector2f const &vector, TimeSpan transitionSpan = 0.0) { x.setValue(vector.x, transitionSpan); y.setValue(vector.y, transitionSpan); } - void setValueIfDifferentTarget(Vector2f const &vector, TimeDelta transitionSpan = 0.0) + void setValueIfDifferentTarget(Vector2f const &vector, TimeSpan transitionSpan = 0.0) { if (!fequal(x.target(), vector.x)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/indirectrule.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/indirectrule.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/indirectrule.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/indirectrule.h 2018-12-11 07:08:24.000000000 +0000 @@ -49,6 +49,8 @@ void unsetSource(); + bool hasSource() const; + void update(); Rule const &source() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/isizerule.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/isizerule.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/isizerule.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/isizerule.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,64 @@ +/** @file isizerule.h Interface for objects providing size rules. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBDENG2_ISIZERULE_H +#define LIBDENG2_ISIZERULE_H + +#include "../Rule" + +namespace de { + +/** + * Interface for objects providing size rules. + * @ingroup widgets + */ +class DENG2_PUBLIC ISizeRule +{ +public: + virtual ~ISizeRule() {} + + virtual Rule const &width() const = 0; + virtual Rule const &height() const = 0; +}; + +/** + * Pair of rules that implements the ISizeRule interface. + * @ingroup widgets + */ +struct DENG2_PUBLIC RulePair + : public std::pair + , public ISizeRule { + RulePair(const Rule &a, const Rule &b) + : std::pair(&a, &b) + {} + // Implements ISizeRule. + const Rule &width() const override + { + DENG2_ASSERT(first); + return *first; + } + const Rule &height() const override + { + DENG2_ASSERT(second); + return *second; + } +}; + +} // namespace de + +#endif // LIBDENG2_ISIZERULE_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rootwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rootwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rootwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rootwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -39,7 +39,7 @@ * * @ingroup widgets */ -class DENG2_PUBLIC RootWidget : public Widget +class DENG2_PUBLIC RootWidget : public Widget, public Lockable { public: typedef Vector2ui Size; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rulebank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rulebank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rulebank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rulebank.h 2018-12-11 07:08:24.000000000 +0000 @@ -34,7 +34,7 @@ class DENG2_PUBLIC RuleBank : public InfoBank { public: - RuleBank(); + RuleBank(const Rule &dpiRule); /** * Creates a number of rules based on information in an Info document. @@ -53,6 +53,8 @@ */ Rule const &rule(DotPath const &path) const; + const Rule &dpiRule() const; + static DotPath const UNIT; protected: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rulerectangle.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rulerectangle.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/rulerectangle.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/rulerectangle.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,6 +21,7 @@ #define LIBDENG2_RECTANGLERULE_H #include "../AnimationVector" +#include "../ISizeRule" #include "../Rectangle" #include "rules.h" @@ -42,7 +43,7 @@ * * @ingroup widgets */ -class DENG2_PUBLIC RuleRectangle +class DENG2_PUBLIC RuleRectangle : public ISizeRule { public: RuleRectangle(); @@ -52,10 +53,10 @@ Rule const &top() const; Rule const &right() const; Rule const &bottom() const; - Rule const &width() const; - Rule const &height() const; Rule const &midX() const; Rule const &midY() const; + Rule const &width() const override; + Rule const &height() const override; /** * Sets one of the input rules of the rectangle. @@ -71,6 +72,8 @@ RuleRectangle &setSize(Rule const &width, Rule const &height); + RuleRectangle &setSize(ISizeRule const &dimensions); + RuleRectangle &setMidAnchorX(Rule const &middle); /** @@ -120,7 +123,7 @@ * (1, 1) to the bottom right. * @param transition Transition time for the change. */ - void setAnchorPoint(Vector2f const &normalizedPoint, TimeDelta const &transition = 0); + void setAnchorPoint(Vector2f const &normalizedPoint, TimeSpan const &transition = 0); /** * Returns the current rectangle as defined by the input rules. @@ -147,6 +150,8 @@ void setDebugName(String const &name); + bool isFullyDefined() const; + String description() const; private: diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/widget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/widget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/include/de/widgets/widget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/include/de/widgets/widget.h 2018-12-11 07:08:24.000000000 +0000 @@ -22,17 +22,19 @@ /** @defgroup widgets Widget Framework * @ingroup core */ -#include "../String" +#include "../DotPath" #include "../Event" +#include "../IObject" #include "../Id" #include "../Observers" -#include "../DotPath" +#include "../String" #include #include namespace de { +class AssetGroup; class Widget; class RootWidget; @@ -42,7 +44,7 @@ * Base class for widgets. * @ingroup widgets */ -class DENG2_PUBLIC Widget +class DENG2_PUBLIC Widget : public IObject { public: /// Widget that was expected to exist was not found. @ingroup errors @@ -239,10 +241,19 @@ Children children() const; dsize childCount() const; Widget *parent() const; - inline Widget *parentWidget() const { return parent(); } + inline Widget *parentWidget() const { return parent(); } bool isFirstChild() const; bool isLastChild() const; + template + Type *ancestorOfType() const { + for (Widget *w = parent(); w; w = w->parent()) + { + if (auto *t = maybeAs(w)) return t; + } + return nullptr; + } + /** * Calls the given callback on each widget of the tree, starting from this widget. * The callback is not called for this widget. @@ -311,6 +322,11 @@ void notifyTreeReversed(NotifyArgs const &args); virtual bool dispatchEvent(Event const &event, bool (Widget::*memberFunc)(Event const &)); + enum class CollectMode { OnlyVisible, All }; + virtual void collectNotReadyAssets(AssetGroup &collected, + CollectMode collectMode = CollectMode::OnlyVisible); + void waitForAssetsReady(); + // Events. virtual void initialize(); virtual void deinitialize(); @@ -324,6 +340,10 @@ virtual void postDrawChildren(); virtual bool handleEvent(Event const &event); + // Implements IObject. + Record & objectNamespace() override; + const Record &objectNamespace() const override; + public: static void setFocusCycle(WidgetList const &order); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/Info 2018-12-11 07:08:24.000000000 +0000 @@ -1,5 +1,5 @@ title: Doomsday Script Standard Library -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core script diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.de doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,150 +0,0 @@ -# The Doomsday Engine Project -- libcore -# -# Copyright (c) 2012-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 3 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -# License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# MAIN CONFIGURATION FOR LIBDENG2 -# -# This module is the special Config namespace, reserved for the engine's -# configuration variables and routines. The namespace is stored persistently -# (persist.pack/modules/Config). The script is executed only when it has -# been updated or when __version__ has changed. - -# Cleanup: this is a persistent namespace so old stuff may be hanging around. -for name in ['setDefaults', 'updateWithDefaults'] - if name in locals(): del locals()[name] -end -del name - -def setDefaults(d = None) - # Applies the default configuration. - # - d: Record where to set the values. If not specified, the - # Config namespace is used. - if d == None - print "Defaults are set in the main Config namespace." - import Config - d = Config - end - - # User's Doomsday Script import override paths (checked before packages). - d.importPath = [''] - - # Log parameters. - record d.log() - # Log message levels. - file = '/home/doomsday.out' - bufferSize = 1000 - end - - # Default log filtering. - def initFilter(flt, level, dev) - flt.minLevel = level - flt.allowDev = dev - end - import Log - record d.log.filter() - initFilter(record generic, Log.MESSAGE, False) - initFilter(record resource, Log.MESSAGE, False) - initFilter(record map, Log.MESSAGE, False) - initFilter(record script, Log.MESSAGE, False) - initFilter(record gl, Log.MESSAGE, False) - initFilter(record audio, Log.MESSAGE, False) - initFilter(record input, Log.MESSAGE, False) - initFilter(record network, Log.MESSAGE, False) - end - - # File system settings. - record d.fs() - # Optional package contents that are currently selected. - selectedPackages = {} - end - - # Network settings. - d.apiUrl = 'http://api.dengine.net/1/' - - try - # Get the application's default configuration, if we can. - import appconfig - appconfig.setDefaults(d) - catch: pass -end - -def updateWithDefaults() - # Any values not already in Config are copied from defaults. - record defaults - setDefaults(defaults) - import recutil, Config - recutil.copyMissingMembers(defaults, Config) -end - -updateWithDefaults() - -# -# -=- UPGRADING -=- -# -# Check the previous version and decide what to do. -if '__oldversion__' in locals() - # Check for a new build. - if __version__[3] > __oldversion__[3] - oldBuild = __oldversion__[3] - newBuild = __version__[3] - print 'Detected new build:', oldBuild, '=>', newBuild - - # Cleanup: get rid of some old stuff. - try - if newBuild >= 826: del window.main.normalRect - catch: pass - try - if newBuild >= 1101 - del log.level - # Log constants were moved to the Log module. - del log.TRACE - del log.DEBUG - del log.VERBOSE - del log.MESSAGE - del log.INFO - del log.WARNING - del log.ERROR - del log.CRITICAL - # Updater constants also moved to their own module. - del updater.DAILY - del updater.BIWEEKLY - del updater.WEEKLY - del updater.MONTHLY - del updater.AT_STARTUP - del updater.CHANNEL_STABLE - del updater.CHANNEL_UNSTABLE - end - catch: pass - try - if newBuild >= 2116 and oldBuild < 2116 - del audio - updateWithDefaults() - end - catch: pass - - del newBuild - del oldBuild - end - - # Check for a new release. - if __version__[0:2] > __oldversion__[0:2] - print 'Detected new release:', __oldversion__, '=>', __version__ - end - - # The above should be done only once after upgrading. - del __oldversion__ -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.ds doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Config.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,150 @@ +# The Doomsday Engine Project -- libcore +# +# Copyright (c) 2012-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# MAIN CONFIGURATION FOR LIBDENG2 +# +# This module is the special Config namespace, reserved for the engine's +# configuration variables and routines. The namespace is stored persistently +# (persist.pack/modules/Config). The script is executed only when it has +# been updated or when __version__ has changed. + +# Cleanup: this is a persistent namespace so old stuff may be hanging around. +for name in ['setDefaults', 'updateWithDefaults'] + if name in locals(): del locals()[name] +end +del name + +def setDefaults(d = None) + # Applies the default configuration. + # - d: Record where to set the values. If not specified, the + # Config namespace is used. + if d == None + print "Defaults are set in the main Config namespace." + import Config + d = Config + end + + # User's Doomsday Script import override paths (checked before packages). + d.importPath = [''] + + # Log parameters. + record d.log() + # Log message levels. + file = '/home/doomsday.out' + bufferSize = 1000 + end + + # Default log filtering. + def initFilter(flt, level, dev) + flt.minLevel = level + flt.allowDev = dev + end + import Log + record d.log.filter() + initFilter(record generic, Log.MESSAGE, False) + initFilter(record resource, Log.MESSAGE, False) + initFilter(record map, Log.MESSAGE, False) + initFilter(record script, Log.MESSAGE, False) + initFilter(record gl, Log.MESSAGE, False) + initFilter(record audio, Log.MESSAGE, False) + initFilter(record input, Log.MESSAGE, False) + initFilter(record network, Log.MESSAGE, False) + end + + # File system settings. + record d.fs() + # Optional package contents that are currently selected. + selectedPackages = {} + end + + # Network settings. + d.apiUrl = 'http://api.dengine.net/1/' + + try + # Get the application's default configuration, if we can. + import appconfig + appconfig.setDefaults(d) + catch: pass +end + +def updateWithDefaults() + # Any values not already in Config are copied from defaults. + record defaults + setDefaults(defaults) + import recutil, Config + recutil.copyMissingMembers(defaults, Config) +end + +updateWithDefaults() + +# +# -=- UPGRADING -=- +# +# Check the previous version and decide what to do. +if '__oldversion__' in locals() + # Check for a new build. + if __version__[3] > __oldversion__[3] + oldBuild = __oldversion__[3] + newBuild = __version__[3] + print 'Detected new build:', oldBuild, '=>', newBuild + + # Cleanup: get rid of some old stuff. + try + if newBuild >= 826: del window.main.normalRect + catch: pass + try + if newBuild >= 1101 + del log.level + # Log constants were moved to the Log module. + del log.TRACE + del log.DEBUG + del log.VERBOSE + del log.MESSAGE + del log.INFO + del log.WARNING + del log.ERROR + del log.CRITICAL + # Updater constants also moved to their own module. + del updater.DAILY + del updater.BIWEEKLY + del updater.WEEKLY + del updater.MONTHLY + del updater.AT_STARTUP + del updater.CHANNEL_STABLE + del updater.CHANNEL_UNSTABLE + end + catch: pass + try + if newBuild >= 2116 and oldBuild < 2116 + del audio + updateWithDefaults() + end + catch: pass + + del newBuild + del oldBuild + end + + # Check for a new release. + if __version__[0:2] > __oldversion__[0:2] + print 'Detected new release:', __oldversion__, '=>', __version__ + end + + # The above should be done only once after upgrading. + del __oldversion__ +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.de doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,30 +0,0 @@ -# The Doomsday Engine Project -- libcore -# -# Copyright (c) 2014-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 3 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -# License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# LOGGING -# -# This module provides Log related functionality. - -# Log entry level constants. -const XVERBOSE = 1 -const VERBOSE = 2 -const MESSAGE = 3 -const NOTE = 4 -const WARNING = 5 -const ERROR = 6 -const CRITICAL = 7 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.ds doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/Log.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,30 @@ +# The Doomsday Engine Project -- libcore +# +# Copyright (c) 2014-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# LOGGING +# +# This module provides Log related functionality. + +# Log entry level constants. +const XVERBOSE = 1 +const VERBOSE = 2 +const MESSAGE = 3 +const NOTE = 4 +const WARNING = 5 +const ERROR = 6 +const CRITICAL = 7 diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.de doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,42 +0,0 @@ -# The Doomsday Engine Project -- libcore -# -# Copyright (c) 2012-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 3 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -# License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# Utility routines for manipulating Records - -def copyMissingMembers(src, dest) - # Checks through 'src' to see if there are any variables or - # records not present in 'dest', and if those are found, inserts - # the missing members to 'dest'. Private keys in 'src' are ignored. - # - src: Source record. - # - dest: Destination record. - - if typeof(dest) != 'Record': return # Hmm? - srcSub = subrecords(src) - - for name in dir(src) - # Private members should be ignored. - if name[:2] == "__": continue - - if not name in dest - if name in srcSub: dest[name] = Record() - else: dest[name] = src[name] - end - - if name in srcSub: copyMissingMembers(src[name], dest[name]) - end -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.ds doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/recutil.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,37 @@ +# The Doomsday Engine Project -- libcore +# +# Copyright (c) 2012-2018 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# Utility routines for manipulating Records + +def copyMissingMembers(src, dest) + # Checks through 'src' to see if there are any variables or + # records not present in 'dest', and if those are found, inserts + # the missing members to 'dest'. Private keys in 'src' are ignored. + # - src: Source record. + # - dest: Destination record. + if typeof(dest) != 'Record': return # Hmm? + srcSub = subrecords(src) + for name in dir(src) + if name[:2] == "__": continue # Private members should be ignored. + if not name in dest + if name in srcSub: dest[name] = Record() + else: dest[name] = src[name] + end + if name in srcSub: copyMissingMembers(src[name], dest[name]) + end +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/utils.ds doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/utils.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/utils.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/net.dengine.stdlib.pack/modules/utils.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,27 @@ +# The Doomsday Engine Project -- libcore +# +# Copyright (c) 2012-2018 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# Miscellaneous utility routines + +def makeArray(value) + # Converts the 'value' to an Array, unless it already is an array. + # Note that if 'value' is an empty string, an empty array is returned. + if typeof(value) == 'Array': return value + if typeof(value) == 'Text' and value == '': return [] + return [value] +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/async.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/async.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/async.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/async.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,75 @@ +/** @file async.cpp Asynchronous utilities. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/Async" + +namespace de { + +AsyncScope::~AsyncScope() +{ + DENG2_GUARD(_tasks); + foreach (AsyncTask *task, _tasks.value) + { + task->invalidate(); + } +} + +AsyncScope &AsyncScope::operator += (AsyncTask *task) +{ + if (task) + { + { + DENG2_GUARD(_tasks); + _tasks.value.insert(task); + } + + QObject::connect(task, &QObject::destroyed, [this] (QObject *obj) + { + DENG2_GUARD(_tasks); + _tasks.value.remove(static_cast(obj)); + }); + } + return *this; +} + +bool AsyncScope::isAsyncFinished() const +{ + DENG2_GUARD(_tasks); + return _tasks.value.isEmpty(); +} + +void AsyncScope::waitForFinished(TimeSpan timeout) +{ + forever + { + AsyncTask *task = nullptr; + { + DENG2_GUARD(_tasks); + if (!_tasks.value.isEmpty()) + { + auto i = _tasks.value.begin(); + task = *i; + _tasks.value.erase(i); + } + } + if (!task) break; + task->wait(timeout.asMilliSeconds()); + } +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/taskpool.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/taskpool.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/taskpool.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/taskpool.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -42,8 +42,6 @@ DENG2_PIMPL(TaskPool), public Lockable, public Waitable, public TaskPool::IPool { - LoopCallback mainCall; - /// Private instance will be deleted when pool is empty. bool deleteWhenDone = false; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/waitable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/waitable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/concurrency/waitable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/concurrency/waitable.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/Waitable" @@ -24,7 +24,7 @@ Waitable::Waitable(duint initialValue) : _semaphore(initialValue) {} - + Waitable::~Waitable() {} @@ -38,7 +38,16 @@ wait(0.0); } -void Waitable::wait(TimeDelta const &timeOut) const +void Waitable::wait(TimeSpan const &timeOut) const +{ + if (!tryWait(timeOut)) + { + /// @throw WaitError Failed to secure the resource due to an error. + throw WaitError("Waitable::wait", "Timed out"); + } +} + +bool Waitable::tryWait(TimeSpan const &timeOut) const { if (timeOut <= 0.0) { @@ -49,10 +58,10 @@ // Wait until the resource becomes available. if (!_semaphore.tryAcquire(1, int(timeOut.asMilliSeconds()))) { - /// @throw WaitError Failed to secure the resource due to an error. - throw WaitError("Waitable::wait", "Timed out"); + return false; } } + return true; } void Waitable::post() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/app.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/app.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/app.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/app.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -34,6 +34,7 @@ #include "de/Log" #include "de/LogBuffer" #include "de/LogFilter" +#include "de/Loop" #include "de/math.h" #include "de/MetadataBank" #include "de/Module" @@ -42,7 +43,10 @@ #include "de/PackageFeed" #include "de/PackageLoader" #include "de/Record" +#include "de/RemoteFeedRelay" #include "de/ScriptSystem" +#include "de/StaticLibraryFeed" +#include "de/TextValue" #include "de/UnixInfo" #include "de/Version" #include "de/Writer" @@ -59,10 +63,41 @@ static App *singletonApp; +static Value *Function_App_Locate(Context &, Function::ArgumentValues const &args) +{ + std::unique_ptr result(new DictionaryValue); + + String const packageId = args.first()->asText(); + + // Local packages. + if (File const *pkg = PackageLoader::get().select(packageId)) + { + result->add(new TextValue(packageId), RecordValue::takeRecord( + Record::withMembers( + "localPath", pkg->path(), + "description", pkg->description() + ))); + } + + // Remote packages. + auto found = App::remoteFeedRelay().locatePackages(StringList({ packageId })); + for (auto i = found.begin(); i != found.end(); ++i) + { + result->add(new TextValue(i.key()), RecordValue::takeRecord( + Record::withMembers( + "repository", i->link->address(), + "localPath", i->localPath, + "remotePath", i->remotePath + ))); + } + + return result.release(); +} + DENG2_PIMPL(App) , DENG2_OBSERVES(PackageLoader, Activity) { - QThread *mainThread; + QThread *mainThread = nullptr; /// Name of the application (metadata for humans). String appName; @@ -87,10 +122,12 @@ QList systems; ScriptSystem scriptSys; + Record appModule; + Binder binder; + FileSystem fs; std::unique_ptr metaBank; std::unique_ptr basePackFile; - Record appModule; /// Archive where persistent data should be stored. Written to /home/persist.pack. /// The archive is owned by the file system. @@ -98,6 +135,8 @@ std::unique_ptr unixInfo; + filesys::RemoteFeedRelay remoteFeedRelay; + /// The configuration. Path configPath; Config *config; @@ -116,15 +155,18 @@ , cmdLine(args) , unixHomeFolder(".doomsday") , persistentData(0) - , configPath("/packs/net.dengine.stdlib/modules/Config.de") + , configPath("/packs/net.dengine.stdlib/modules/Config.ds") , config(0) , terminateFunc(0) { #ifdef UNIX + { // We wish to use U.S. English formatting for time and numbers (in libc). setlocale(LC_ALL, "en_US.UTF-8"); setlocale(LC_NUMERIC, "C"); + } #endif + // Override the system number formatting. QLocale::setDefault(QLocale("en_US.UTF-8")); @@ -149,7 +191,11 @@ fs.addInterpreter(intrpZipArchive); // Native App module. - scriptSys.addNativeModule("App", appModule); + { + scriptSys.addNativeModule("App", appModule); + binder.init(appModule) + << DENG2_FUNC(App_Locate, "locate", "packageId"); + } } ~Impl() @@ -178,15 +224,21 @@ NativePath defaultNativeModulePath() const { #ifdef WIN32 + { NativePath appDir = appPath.fileNamePath(); return appDir / "..\\modules"; + } #else + { return self().nativeBasePath() / "modules"; + } #endif } void initFileSystem(bool allowPlugins) { + Folder::checkDefaultSettings(); + // Executables. Folder &binFolder = fs.makeFolder("/bin"); @@ -205,14 +257,18 @@ else { #ifdef MACOSX + { NativePath appDir = appPath.fileNamePath(); binFolder.attach(new DirectoryFeed(appDir)); fs.makeFolder("/data").attach(new DirectoryFeed(self().nativeBasePath())); + } #elif WIN32 + { NativePath appDir = appPath.fileNamePath(); fs.makeFolder("/data").attach(new DirectoryFeed(appDir / "..\\data")); - + } #else // UNIX + { if ((self().nativeBasePath() / "data").exists()) { fs.makeFolder("/data").attach(new DirectoryFeed(self().nativeBasePath() / "data")); @@ -221,7 +277,9 @@ { fs.makeFolder("/data").attach(new DirectoryFeed(self().nativeBasePath())); } + } #endif + if (defaultNativeModulePath().exists()) { fs.makeFolder("/modules").attach(new DirectoryFeed(defaultNativeModulePath())); @@ -230,7 +288,11 @@ if (allowPlugins) { +#if !defined (DENG_STATIC_LINK) binFolder.attach(new DirectoryFeed(self().nativePluginBinaryPath())); +#else + binFolder.attach(new StaticLibraryFeed); +#endif } // User's home folder. @@ -246,9 +308,8 @@ // Metadata for files. metaBank.reset(new MetadataBank); - // Populate the file system. - fs.refresh(); - Folder::waitForPopulation(); + // Populate the file system (blocking). + fs.root().populate(Folder::PopulateFullTree); // Ensure known subfolders exist: // - /home/configs is used by de::Profiles. @@ -375,14 +436,16 @@ d->appPath = appFilePath; LOG_NOTE("Application path: ") << d->appPath; - LOG_NOTE("Build: ") << Version::currentBuild().asHumanReadableText(); + LOG_NOTE("Version: ") << Version::currentBuild().asHumanReadableText(); -#ifdef MACOSX - // When the application is started through Finder, we get a special command - // line argument. The working directory needs to be changed. - if (d->cmdLine.count() >= 2 && d->cmdLine.at(1).beginsWith("-psn")) + #if defined (MACOSX) { - DirectoryFeed::changeWorkingDir(d->cmdLine.at(0).fileNamePath() + "/.."); + // When the application is started through Finder, we get a special command + // line argument. The working directory needs to be changed. + if (d->cmdLine.count() >= 2 && d->cmdLine.at(1).beginsWith("-psn")) + { + DirectoryFeed::changeWorkingDir(d->cmdLine.at(0).fileNamePath() + "/.."); + } } #endif } @@ -482,6 +545,7 @@ return DENG2_APP->d->mainThread == QThread::currentThread(); } +#if !defined (DENG_STATIC_LINK) NativePath App::nativePluginBinaryPath() { if (!d->cachedPluginBinaryPath.isEmpty()) return d->cachedPluginBinaryPath; @@ -493,24 +557,36 @@ } NativePath path; -#ifdef WIN32 + + #if defined (WIN32) + { path = d->appPath.fileNamePath() / "plugins"; + return (d->cachedPluginBinaryPath = path); + } #else -# ifdef MACOSX + { + #if defined (MACOSX) + { path = d->appPath.fileNamePath() / "../PlugIns/Doomsday"; -# else - path = DENG_LIBRARY_DIR; + } + #else + { + path = d->appPath.fileNamePath() / DENG_LIBRARY_DIR; if (!path.exists()) { // Try a fallback relative to the executable. path = d->appPath.fileNamePath() / "../lib/doomsday"; + } } -# endif + #endif + // Also check the system config files. d->unixInfo->path("libdir", path); + return (d->cachedPluginBinaryPath = path); + } #endif - return (d->cachedPluginBinaryPath = path); } +#endif NativePath App::nativeHomePath() { @@ -522,16 +598,30 @@ return (d->cachedHomePath = d->cmdLine.at(opt.pos + 1)); } -#ifdef MACOSX - NativePath nativeHome = QDir::homePath(); + NativePath nativeHome; + + #if defined (DENG_IOS) + { + nativeHome = QDir::homePath(); + nativeHome = nativeHome / "Documents/runtime"; + } + #elif defined (MACOSX) + { + nativeHome = QDir::homePath(); nativeHome = nativeHome / "Library/Application Support" / d->appName / "runtime"; -#elif WIN32 - NativePath nativeHome = appDataPath(); + } + #elif defined (WIN32) + { + nativeHome = appDataPath(); nativeHome = nativeHome / "runtime"; + } #else // UNIX - NativePath nativeHome = QDir::homePath(); + { + nativeHome = QDir::homePath(); nativeHome = nativeHome / d->unixHomeFolder / "runtime"; + } #endif + return (d->cachedHomePath = nativeHome); } @@ -588,18 +678,26 @@ NativePath path; #ifdef WIN32 + { path = d->appPath.fileNamePath() / ".."; + } #else -# ifdef MACOSX + { + #ifdef MACOSX + { path = d->appPath.fileNamePath() / "../Resources"; if (!path.exists()) { // Try the built-in base directory (unbundled apps). - path = DENG_BASE_DIR; + path = d->appPath.fileNamePath() / DENG_BASE_DIR; + } + } + #else + { + path = d->appPath.fileNamePath() / DENG_BASE_DIR; } -# else - path = DENG_BASE_DIR; -# endif + #endif + if (!path.exists()) { // Fall back to using the application binary path, which always exists. @@ -610,6 +708,7 @@ } // Also check the system config files. d->unixInfo->path("basedir", path); + } #endif return (d->cachedBasePath = path); } @@ -646,7 +745,11 @@ d->config = new Config(d->configPath); d->scriptSys.addNativeModule("Config", d->config->objectNamespace()); - d->config->read(); + // Whenever the version changes, reset the cached metadata so any updates will be applied. + if (d->config->read() == Config::DifferentVersion) + { + LOG_RES_NOTE("Clearing cached metadata due to version change"); + d->metaBank->clear(); // Immediately after upgrading, OLD_VERSION is also present in the Version module. Version oldVer = d->config->upgradedFromVersion(); @@ -655,7 +758,8 @@ ArrayValue *old = new ArrayValue; *old << NumberValue(oldVer.major) << NumberValue(oldVer.minor) << NumberValue(oldVer.patch) << NumberValue(oldVer.build); - d->scriptSys.nativeModule("Version").addArray("OLD_VERSION", old).setReadOnly(); + d->scriptSys["Version"].addArray("OLD_VERSION", old).setReadOnly(); + } } // Set up the log buffer. @@ -721,7 +825,7 @@ #endif } - LOG_VERBOSE("libcore::App %s subsystems initialized") << Version::currentBuild().asHumanReadableText(); + LOG_VERBOSE("Subsystems initialized"); } void App::addSystem(System &system) @@ -833,6 +937,11 @@ return rootFolder().locate("home"); } +filesys::RemoteFeedRelay &App::remoteFeedRelay() +{ + return DENG2_APP->d->remoteFeedRelay; +} + Config &App::config() { DENG2_ASSERT(DENG2_APP->d->config != 0); @@ -844,6 +953,14 @@ return config()[name]; } +String App::apiUrl() // static +{ + String u = Config::get().gets(QStringLiteral("apiUrl")); + if (!u.startsWith("http")) u = "http://" + u; + if (!u.endsWith("/")) u += "/"; + return u; +} + UnixInfo &App::unixInfo() { return *DENG2_APP->d->unixInfo; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/asset.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/asset.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/asset.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/asset.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -17,6 +17,7 @@ */ #include "de/Asset" +#include "de/Waitable" namespace de { @@ -57,7 +58,7 @@ void Asset::setState(bool assetReady) { - setState(assetReady? Ready : NotReady); + setState(assetReady ? Ready : NotReady); } Asset::State Asset::state() const @@ -70,6 +71,32 @@ return d->state == Ready; } +void Asset::waitForState(State s) const +{ + struct Waiter + : public Waitable + , DENG2_OBSERVES(Asset, StateChange) { + State waitingFor; + Waiter(State wf) + : waitingFor(wf) + {} + void assetStateChanged(Asset &asset) override + { + if (asset.state() == waitingFor) + { + post(); + } + } + }; + + Waiter w(s); + audienceForStateChange() += w; + if (d->state != s) + { + w.wait(); + } +} + //---------------------------------------------------------------------------- DENG2_PIMPL_NOREF(AssetGroup) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/clock.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/clock.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/clock.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/clock.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -58,12 +58,12 @@ } } -void Clock::advanceTime(TimeDelta const &span) +void Clock::advanceTime(TimeSpan const &span) { setTime(d->time + span); } -TimeDelta Clock::elapsed() const +TimeSpan Clock::elapsed() const { return d->time - d->startedAt; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/commandline.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/commandline.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/commandline.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/commandline.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,7 +25,6 @@ #include #include -#include #include #include @@ -458,6 +457,8 @@ } return false; } + +#if defined (DENG_HAVE_QPROCESS) bool CommandLine::execute() const { @@ -513,6 +514,8 @@ LOG_DEBUG("Started process %i \"%s\"") << proc->pid() << at(0); return proc; } + +#endif // DENG_HAVE_QPROCESS CommandLine &CommandLine::get() { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/config.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/config.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/config.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/config.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -79,9 +79,11 @@ setAccessedRecord(objectNamespace()); } -void Config::read() +Config::ReadStatus Config::read() { - if (d->configPath.isEmpty()) return; + ReadStatus readStatus = WasNotRead; + + if (d->configPath.isEmpty()) return readStatus; LOG_AS("Config::read"); @@ -100,6 +102,7 @@ { // If we already have a saved copy of the config, read it. d->refuge.read(); + readStatus = DifferentVersion; LOG_DEBUG("Found serialized Config:\n") << objectNamespace(); @@ -118,6 +121,7 @@ else { // Versions match. + readStatus = SameVersion; LOG_MSG("") << d->refuge.path() << " matches version " << version->asText(); } } @@ -175,6 +179,8 @@ d->config.run(script); d->config.execute(); } + + return readStatus; } void Config::write() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/garbage.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/garbage.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/garbage.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/garbage.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -79,6 +79,11 @@ allocs.clear(); } } + + void forgetAndLeak() + { + allocs.clear(); // Oh well... + } }; struct Garbages : public std::map, public Lockable @@ -109,6 +114,16 @@ i->second->recycle(func); } } + + void forgetAndLeak() + { + DENG2_GUARD(this); + for (iterator i = begin(); i != end(); ++i) + { + i->second->forgetAndLeak(); + } + clear(); + } }; } // namespace internal @@ -193,6 +208,11 @@ g->recycle(); } +void Garbage_ForgetAndLeak(void) +{ + garbages.forgetAndLeak(); +} + void Garbage_RecycleAllWithDestructor(GarbageDestructor destructor) { garbages.recycleWithDestructor(destructor); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/highperformancetimer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/highperformancetimer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/highperformancetimer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/highperformancetimer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -44,9 +44,9 @@ HighPerformanceTimer::HighPerformanceTimer() : d(new Impl) {} -TimeDelta HighPerformanceTimer::elapsed() const +TimeSpan HighPerformanceTimer::elapsed() const { - return TimeDelta(d->milliSeconds() / 1000.0); + return TimeSpan(d->milliSeconds() / 1000.0); } Time HighPerformanceTimer::startedAt() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/library.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/library.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/library.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/library.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,16 +22,50 @@ #include "de/Log" #include "de/LogBuffer" -#if defined(UNIX) && defined(DENG2_QT_4_7_OR_NEWER) && !defined(DENG2_QT_4_8_OR_NEWER) -# define DENG2_USE_DLOPEN -# include -typedef void *Handle; -#else -typedef QLibrary *Handle; +#if !defined (DENG_STATIC_LINK) +# include #endif +#include + namespace de { +#if defined (DENG_STATIC_LINK) + +struct ImportedStaticLibrary +{ + char const *name; + StaticSymbolFunc symbolFunc; +}; +static std::array importedLibraries; + +ImportedStaticLibrary const *findStaticLibrary(char const *name) +{ + for (auto const &imp : importedLibraries) + { + if (!imp.name) break; + if (!qstrcmp(imp.name, name)) + { + return &imp; + } + } + return nullptr; +} + +#endif // DENG_STATIC_LINK + +#if defined (DENG_STATIC_LINK) +typedef ImportedStaticLibrary const *Handle; +#else +# if defined(UNIX) && defined(DENG2_QT_4_7_OR_NEWER) && !defined(DENG2_QT_4_8_OR_NEWER) +# define DENG2_USE_DLOPEN +# include +typedef void *Handle; +# else +typedef QLibrary *Handle; +# endif +#endif + char const *Library::DEFAULT_TYPE = "library/generic"; DENG2_PIMPL(Library) @@ -39,7 +73,7 @@ /// Handle to the shared library. Handle library; - typedef QMap Symbols; + typedef QHash Symbols; Symbols symbols; /// Type identifier for the library (e.g., "deng-plugin/generic"). @@ -49,7 +83,7 @@ Impl(Public *i) : Base(i), library(0), type(DEFAULT_TYPE) {} -#ifdef DENG2_USE_DLOPEN +#if defined (DENG_STATIC_LINK) || defined(DENG2_USE_DLOPEN) NativePath fileName; NativePath nativePath() { return fileName; } bool isLoaded() const { return library != 0; } @@ -67,22 +101,27 @@ LOG_AS("Library"); LOG_TRACE("Loading \"%s\"", nativePath.pretty()); -#ifndef DENG2_USE_DLOPEN +#if defined (DENG_STATIC_LINK) + d->fileName = nativePath; + d->library = findStaticLibrary(nativePath.toUtf8().constData()); +#elif defined (DENG2_USE_DLOPEN) + d->fileName = nativePath; + d->library = dlopen(nativePath.toUtf8().constData(), RTLD_NOW); +#else d->library = new QLibrary(nativePath); d->library->setLoadHints(QLibrary::ResolveAllSymbolsHint); d->library->load(); -#else - d->fileName = nativePath; - d->library = dlopen(nativePath.toUtf8().constData(), RTLD_NOW); #endif if (!d->isLoaded()) { -#ifndef DENG2_USE_DLOPEN +#if defined (DENG_STATIC_LINK) + QString msg = "static library has not been imported"; +#elif defined (DENG2_USE_DLOPEN) + QString msg = dlerror(); +#else QString msg = d->library->errorString(); delete d->library; -#else - QString msg = dlerror(); #endif d->library = 0; @@ -120,11 +159,13 @@ // entries contain pointers to functions that are about to disappear. LogBuffer::get().clear(); -#ifndef DENG2_USE_DLOPEN +#if defined (DENG_STATIC_LINK) + d->library = nullptr; +#elif defined (DENG2_USE_DLOPEN) + dlclose(d->library); +#else d->library->unload(); delete d->library; -#else - dlclose(d->library); #endif } } @@ -149,10 +190,13 @@ return found.value(); } -#ifndef DENG2_USE_DLOPEN - void *ptr = de::function_cast(d->library->resolve(name.toLatin1().constData())); -#else +#if defined (DENG_STATIC_LINK) + void *ptr = d->library->symbolFunc(name.toLatin1().constData()); + qDebug() << d->fileName.toString() << name << ptr; +#elif defined (DENG2_USE_DLOPEN) void *ptr = dlsym(d->library, name.toLatin1().constData()); +#else + void *ptr = de::function_cast(d->library->resolve(name.toLatin1().constData())); #endif if (!ptr) @@ -174,11 +218,42 @@ // First check the symbols cache. if (d->symbols.find(name) != d->symbols.end()) return true; -#ifndef DENG2_USE_DLOPEN - return d->library->resolve(name.toLatin1().constData()) != 0; +#if defined (DENG_STATIC_LINK) + return d->library->symbolFunc(name.toLatin1().constData()) != 0; +#elif defined (DENG2_USE_DLOPEN) + return dlsym(d->library, name.toLatin1().constData()) != 0; #else - return dlsym(d->library, name.toAscii().constData()) != 0; + return d->library->resolve(name.toLatin1().constData()) != 0; #endif } +#if defined (DENG_STATIC_LINK) +void Library::importStaticLibrary(char const *name, StaticSymbolFunc symbolFunc) // static +{ + for (uint i = 0; i < importedLibraries.size(); ++i) + { + auto &impLib = importedLibraries[i]; + if (!impLib.name) + { + impLib.name = name; + impLib.symbolFunc = symbolFunc; + return; + } + } +} + +StringList Library::staticLibraries() // static +{ + StringList names; + for (auto const &lib : importedLibraries) + { + if (lib.name) + { + names << lib.name; + } + } + return names; +} +#endif + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/logbuffer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/logbuffer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/logbuffer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/logbuffer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -39,7 +39,7 @@ namespace de { -TimeDelta const FLUSH_INTERVAL = .2; // seconds +TimeSpan const FLUSH_INTERVAL = .2; // seconds DENG2_PIMPL(LogBuffer) { @@ -262,7 +262,7 @@ d->enableAutoFlush(true); } -void LogBuffer::setAutoFlushInterval(TimeDelta const &interval) +void LogBuffer::setAutoFlushInterval(TimeSpan const &interval) { enableFlushing(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/log.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/log.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/log.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/log.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -32,6 +32,7 @@ #include #include #include +#include namespace de { @@ -170,6 +171,11 @@ _data.stringValue = new String(s.data(), s.size()); } +void LogEntry::Arg::setValue(std::array const &typecode) +{ + setValue(QString::fromLatin1(typecode.data(), 4)); +} + void LogEntry::Arg::setValue(LogEntry::Arg::Base const &arg) { switch (arg.logEntryArgType()) @@ -729,22 +735,22 @@ if (!logsPtr.get()) logsPtr.reset(new internal::Logs); return *logsPtr; }*/ - + static QThreadStorage theLogs; Log &Log::threadLog() { // Each thread has its own log. //QThread *thread = QThread::currentThread(); - + return theLogs.localData(); - + /*if (!theLogs.hasLocalData()) { theLogs.setLocalData(<#de::Log t#>) internal::Logs &logs = theLogs(); DENG2_GUARD(logs); - + auto found = logs.constFind(thread); if (found == logs.constEnd()) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/loop.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/loop.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/loop.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/loop.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -33,7 +33,7 @@ DENG2_PIMPL(Loop) { - TimeDelta interval; + TimeSpan interval; bool running; QTimer *timer; LoopCallback mainCall; @@ -62,12 +62,21 @@ Loop::Loop() : d(new Impl(this)) {} -void Loop::setRate(int freqHz) +void Loop::setRate(double freqHz) { + if (fequal(freqHz, 0.0)) +{ + freqHz = 1000.0; + } d->interval = 1.0 / freqHz; d->timer->setInterval(de::max(1, int(d->interval.asMilliSeconds()))); } +double Loop::rate() const +{ + return 1.0 / d->interval; +} + void Loop::start() { d->running = true; @@ -90,7 +99,7 @@ d->timer->start(); } -void Loop::timer(TimeDelta const &delay, std::function func) +void Loop::timer(TimeSpan const &delay, std::function func) { // The timer will delete itself after it's triggered. internal::CallbackTimer *timer = new internal::CallbackTimer(func, qApp); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/textapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/textapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/textapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/textapp.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -36,7 +36,7 @@ // In text-based apps, we can limit the loop frequency. loop.setRate(35); } - + void loopIteration() override { // Update the clock time. App listens to this clock and will inform @@ -47,9 +47,9 @@ }; TextApp::TextApp(int &argc, char **argv) - : QCoreApplication(argc, argv), - App(applicationFilePath(), arguments()), - d(new Impl(this)) + : QCoreApplication(argc, argv) + , App(applicationFilePath(), arguments()) + , d(new Impl(this)) {} void TextApp::setMetadata(String const &orgName, String const &orgDomain, diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/unixinfo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/unixinfo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/core/unixinfo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/core/unixinfo.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -95,7 +95,7 @@ #ifdef UNIX /** * @note There is only the "paths" and "plugins" config files for now; more - * could be added for different purposes. There could also be .de scripts + * could be added for different purposes. There could also be .ds scripts * for configuration. */ d->paths = new Infos("paths"); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/c_wrapper.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/c_wrapper.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/c_wrapper.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/c_wrapper.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -94,7 +94,7 @@ void App_Timer(unsigned int milliseconds, void (*callback)(void)) { - de::Loop::timer(de::TimeDelta::fromMilliSeconds(milliseconds), callback); + de::Loop::timer(de::TimeSpan::fromMilliSeconds(milliseconds), callback); } void App_FatalError(char const *msgFormat, ...) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/archive.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/archive.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/archive.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/archive.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -164,7 +164,7 @@ Entry const &found = static_cast(d->index->find(path, PathTree::MatchFull)); return File::Status( - found.isLeaf()? File::Status::FILE : File::Status::FOLDER, + found.isLeaf()? File::Type::File : File::Type::Folder, found.size, found.modifiedAt); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/arrayvalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/arrayvalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/arrayvalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/arrayvalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -42,6 +42,14 @@ } } +ArrayValue::ArrayValue(StringList const &strings) +{ + for (String str : strings) + { + _elements.push_back(new TextValue(str)); + } +} + ArrayValue::ArrayValue(std::initializer_list values) : _iteration(0) { for (auto *v : values) @@ -289,6 +297,18 @@ _elements.erase(elem); } +dint ArrayValue::indexOf(const Value &value) const +{ + for (int i = 0; i < _elements.size(); ++i) + { + if (!value.compare(*_elements[i])) + { + return i; + } + } + return -1; +} + ArrayValue &ArrayValue::operator << (Value *value) { add(value); @@ -396,7 +416,7 @@ return element(index); } -String ArrayValue::asTextUsingInfoSyntax() const +String ArrayValue::asInfo() const { StringList values; for (Value const *value : elements()) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/bank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/bank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/bank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/bank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -88,6 +88,11 @@ _items.remove(&data); } + bool contains(ItemType const *data) const { + DENG2_GUARD(this); + return _items.contains(const_cast(data)); + } + virtual void clear() { DENG2_GUARD(this); _items.clear(); @@ -142,8 +147,8 @@ if (data.get()) { - LOG_RES_VERBOSE("Item \"%s\" data cleared from memory (%i bytes)") - << path(bank->d->sepChar) << data->sizeInMemory(); + LOG_XVERBOSE("Item \"%s\" data cleared from memory (%i bytes)", + path(bank->d->sepChar) << data->sizeInMemory()); data->aboutToUnload(); data.reset(); } @@ -162,7 +167,6 @@ /// Load the item into memory from its current cache. void load() { - DENG2_GUARD(this); DENG2_ASSERT(cache != 0); switch (cache->format()) @@ -191,8 +195,8 @@ // us. This may take an unspecified amount of time. QScopedPointer loaded(bank->loadFromSource(*source)); - LOG_RES_XVERBOSE("Loaded \"%s\" from source in %.2f seconds", - path(bank->d->sepChar) << startedAt.since()); + LOG_XVERBOSE("Loaded \"%s\" from source in %.2f seconds", + path(bank->d->sepChar) << startedAt.since()); if (loaded.data()) { @@ -224,15 +228,15 @@ std::unique_ptr blank(bank->newData()); reader >> *blank->asSerializable(); setData(blank.release()); - LOG_RES_XVERBOSE("Deserialized \"%s\" in %.2f seconds", - path(bank->d->sepChar) << startedAt.since()); + LOG_XVERBOSE("Deserialized \"%s\" in %.2f seconds", + path(bank->d->sepChar) << startedAt.since()); return; // Done! } // We cannot use this. } catch (Error const &er) { - LOG_RES_WARNING("Failed to deserialize \"%s\":\n") + LOG_WARNING("Failed to deserialize \"%s\":\n") << path(bank->d->sepChar) << er.asText(); } @@ -280,7 +284,7 @@ // to check later whether the data is still fresh. serial.reset(&containingFolder.createFile(name(), Folder::ReplaceExisting)); - LOG_RES_XVERBOSE("Serializing into %s", serial->description()); + LOG_XVERBOSE("Serializing into %s", serial->description()); Writer(*serial).withHeader() << source->modifiedAt() @@ -401,15 +405,14 @@ DENG2_GUARD(this); - DENG2_ASSERT(item.data.get() != 0); - + DENG2_ASSERT(item.data.get() != nullptr); addBytes(item.data->sizeInMemory()); DataCache::add(item); } void remove(Data &item) { - DENG2_ASSERT(item.data.get() != 0); + DENG2_ASSERT(item.data.get() != nullptr); DENG2_GUARD(this); @@ -471,7 +474,7 @@ } catch (Error const &er) { - LOG_RES_WARNING("Failed to load \"%s\" from source:\n") << _path << er.asText(); + LOG_WARNING("Failed to load \"%s\" from source:\n") << _path << er.asText(); } // Ensure a blocking load completes. item().post(); @@ -483,12 +486,12 @@ { DENG2_ASSERT(_bank.d->serialCache != 0); - LOG_RES_XVERBOSE("Serializing \"%s\"", _path); + LOG_XVERBOSE("Serializing \"%s\"", _path); item().changeCache(*_bank.d->serialCache); } catch (Error const &er) { - LOG_RES_WARNING("Failed to serialize \"%s\" to hot storage:\n") + LOG_WARNING("Failed to serialize \"%s\" to hot storage:\n") << _path << er.asText(); } } @@ -502,7 +505,7 @@ } catch (Error const &er) { - LOG_RES_WARNING("Error when unloading \"%s\":\n") + LOG_WARNING("Error when unloading \"%s\":\n") << _path << er.asText(); } } @@ -567,9 +570,9 @@ { DENG2_ASSERT(serialCache); + FS::waitForIdle(); if (Folder *folder = serialCache->folder()) { - Folder::waitForPopulation(); folder->destroyAllFilesRecursively(); } } @@ -819,7 +822,7 @@ { LOG_AS(d->nameForLog); - QScopedPointer src(source); + std::unique_ptr src(source); // Paths are unique. if (d->items.has(path, PathTree::MatchFull | PathTree::NoBranch)) @@ -833,7 +836,7 @@ DENG2_GUARD(item); item.bank = this; - item.source.reset(src.take()); + item.source.reset(src.release()); d->putInBestCache(item); } @@ -848,6 +851,11 @@ return d->items.has(path); } +Bank::ISource &Bank::source(const DotPath &path) const +{ + return *d->items.find(path, PathTree::MatchFull | PathTree::NoBranch).source.get(); +} + dint Bank::allItems(Names &names) const { names.clear(); @@ -908,13 +916,13 @@ item.reset(); item.unlock(); - LOG_RES_XVERBOSE("Loading \"%s\"...", path); + LOG_XVERBOSE("Loading \"%s\"...", path); Time requestedAt; d->load(path, BeforeQueued); item.wait(); - TimeDelta const waitTime = requestedAt.since(); + TimeSpan const waitTime = requestedAt.since(); item.lock(); if (!item.data.get()) @@ -924,11 +932,11 @@ if (waitTime > 0.0) { - LOG_RES_VERBOSE("\"%s\" loaded (waited %.3f seconds)") << path << waitTime; + LOG_VERBOSE("\"%s\" loaded (waited %.3f seconds)") << path << waitTime; } else { - LOG_RES_VERBOSE("\"%s\" loaded") << path; + LOG_VERBOSE("\"%s\" loaded") << path; } return *item.data; @@ -936,9 +944,11 @@ bool Bank::isLoaded(DotPath const &path) const { - Impl::Data &item = d->items.find(path, PathTree::MatchFull | PathTree::NoBranch); - DENG2_GUARD(item); - return bool(item.data); + if (Impl::Data const *item = d->items.tryFind(path, PathTree::MatchFull | PathTree::NoBranch)) + { + return d->memoryCache.contains(item); + } + return false; } void Bank::unload(DotPath const &path, CacheLevel toLevel, Importance importance) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/blockvalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/blockvalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/blockvalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/blockvalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -36,6 +36,11 @@ return _value; } +Block const &BlockValue::block() const +{ + return _value; +} + BlockValue::operator IByteArray const &() const { return _value; @@ -110,4 +115,4 @@ return "Block"; } -} // namespace de \ No newline at end of file +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/byteorder.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/byteorder.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/byteorder.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/byteorder.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,71 +24,73 @@ DENG2_PUBLIC BigEndianByteOrder bigEndianByteOrder; DENG2_PUBLIC LittleEndianByteOrder littleEndianByteOrder; -void ByteOrder::hostToNetwork(de::dint16 const &hostValue, de::dint16 &networkValue) const +void ByteOrder::hostToNetwork(dint16 hostValue, dint16 &networkValue) const { - hostToNetwork(reinterpret_cast(hostValue), - reinterpret_cast< de::duint16 &>(networkValue)); + hostToNetwork(hostValue, reinterpret_cast(networkValue)); } -void ByteOrder::hostToNetwork(de::dint32 const &hostValue, de::dint32 &networkValue) const +void ByteOrder::hostToNetwork(dint32 hostValue, dint32 &networkValue) const { - hostToNetwork(reinterpret_cast(hostValue), - reinterpret_cast< de::duint32 &>(networkValue)); + hostToNetwork(hostValue, reinterpret_cast(networkValue)); } -void ByteOrder::hostToNetwork(de::dint64 const &hostValue, de::dint64 &networkValue) const +void ByteOrder::hostToNetwork(dint64 hostValue, dint64 &networkValue) const { - hostToNetwork(reinterpret_cast(hostValue), - reinterpret_cast< de::duint64 &>(networkValue)); + hostToNetwork(hostValue, reinterpret_cast(networkValue)); } -void ByteOrder::networkToHost(de::dint16 const &networkValue, de::dint16 &hostValue) const +void ByteOrder::networkToHost(dint16 networkValue, dint16 &hostValue) const { - networkToHost(reinterpret_cast(networkValue), - reinterpret_cast< de::duint16 &>(hostValue)); + networkToHost(networkValue, reinterpret_cast(hostValue)); } -void ByteOrder::networkToHost(de::dint32 const &networkValue, de::dint32 &hostValue) const +void ByteOrder::networkToHost(dint32 networkValue, dint32 &hostValue) const { - networkToHost(reinterpret_cast(networkValue), - reinterpret_cast< de::duint32 &>(hostValue)); + networkToHost(networkValue, reinterpret_cast(hostValue)); } -void ByteOrder::networkToHost(de::dint64 const &networkValue, de::dint64 &hostValue) const +void ByteOrder::networkToHost(dint64 networkValue, dint64 &hostValue) const { - networkToHost(reinterpret_cast(networkValue), - reinterpret_cast< de::duint64 &>(hostValue)); + networkToHost(networkValue, reinterpret_cast(hostValue)); } -void ByteOrder::hostToNetwork(de::dfloat const &hostValue, de::dfloat &networkValue) const +void ByteOrder::hostToNetwork(dfloat hostValue, dfloat &networkValue) const { - DENG2_ASSERT(sizeof(de::dfloat) == sizeof(de::duint32)); - hostToNetwork(reinterpret_cast(hostValue), - reinterpret_cast< de::duint32 &>(networkValue)); + DENG2_ASSERT(sizeof(dfloat) == sizeof(duint32)); + duint32 hv, net; + std::memcpy(&hv, &hostValue, 4); + hostToNetwork(hv, net); + std::memcpy(&networkValue, &net, 4); } -void ByteOrder::hostToNetwork(de::ddouble const &hostValue, de::ddouble &networkValue) const +void ByteOrder::hostToNetwork(ddouble hostValue, ddouble &networkValue) const { - DENG2_ASSERT(sizeof(de::ddouble) == sizeof(de::duint64)); - hostToNetwork(reinterpret_cast(hostValue), - reinterpret_cast< de::duint64 &>(networkValue)); + DENG2_ASSERT(sizeof(ddouble) == sizeof(duint64)); + duint64 hv, net; + std::memcpy(&hv, &hostValue, 8); + hostToNetwork(hv, net); + std::memcpy(&networkValue, &net, 8); } -void ByteOrder::networkToHost(de::dfloat const &networkValue, de::dfloat &hostValue) const +void ByteOrder::networkToHost(dfloat networkValue, dfloat &hostValue) const { - DENG2_ASSERT(sizeof(de::dfloat) == sizeof(de::duint32)); - networkToHost(reinterpret_cast(networkValue), - reinterpret_cast< de::duint32 &>(hostValue)); + DENG2_ASSERT(sizeof(dfloat) == sizeof(duint32)); + duint32 net, hv; + std::memcpy(&net, &networkValue, 4); + networkToHost(net, hv); + std::memcpy(&hostValue, &hv, 4); } -void ByteOrder::networkToHost(de::ddouble const &networkValue, de::ddouble &hostValue) const +void ByteOrder::networkToHost(ddouble networkValue, ddouble &hostValue) const { - DENG2_ASSERT(sizeof(de::ddouble) == sizeof(de::duint64)); - networkToHost(reinterpret_cast(networkValue), - reinterpret_cast< de::duint64 &>(hostValue)); + DENG2_ASSERT(sizeof(ddouble) == sizeof(duint64)); + duint64 net, hv; + std::memcpy(&net, &networkValue, 8); + networkToHost(net, hv); + std::memcpy(&hostValue, &hv, 8); } -void BigEndianByteOrder::networkToHost(de::duint16 const &networkValue, de::duint16 &hostValue) const +void BigEndianByteOrder::networkToHost(duint16 networkValue, duint16 &hostValue) const { #ifdef __BIG_ENDIAN__ hostValue = networkValue; @@ -97,7 +99,7 @@ #endif } -void BigEndianByteOrder::networkToHost(de::duint32 const &networkValue, de::duint32 &hostValue) const +void BigEndianByteOrder::networkToHost(duint32 networkValue, duint32 &hostValue) const { #ifdef __BIG_ENDIAN__ hostValue = networkValue; @@ -106,7 +108,7 @@ #endif } -void BigEndianByteOrder::networkToHost(de::duint64 const &networkValue, de::duint64 &hostValue) const +void BigEndianByteOrder::networkToHost(duint64 networkValue, duint64 &hostValue) const { #ifdef __BIG_ENDIAN__ hostValue = networkValue; @@ -115,7 +117,7 @@ #endif } -void BigEndianByteOrder::hostToNetwork(de::duint16 const &hostValue, de::duint16 &networkValue) const +void BigEndianByteOrder::hostToNetwork(duint16 hostValue, duint16 &networkValue) const { #ifdef __BIG_ENDIAN__ networkValue = hostValue; @@ -124,7 +126,7 @@ #endif } -void BigEndianByteOrder::hostToNetwork(de::duint32 const &hostValue, de::duint32 &networkValue) const +void BigEndianByteOrder::hostToNetwork(duint32 hostValue, duint32 &networkValue) const { #ifdef __BIG_ENDIAN__ networkValue = hostValue; @@ -133,7 +135,7 @@ #endif } -void BigEndianByteOrder::hostToNetwork(de::duint64 const &hostValue, de::duint64 &networkValue) const +void BigEndianByteOrder::hostToNetwork(duint64 hostValue, duint64 &networkValue) const { #ifdef __BIG_ENDIAN__ networkValue = hostValue; @@ -142,7 +144,7 @@ #endif } -void LittleEndianByteOrder::networkToHost(de::duint16 const &networkValue, de::duint16 &hostValue) const +void LittleEndianByteOrder::networkToHost(duint16 networkValue, duint16 &hostValue) const { #ifndef __BIG_ENDIAN__ hostValue = networkValue; @@ -151,7 +153,7 @@ #endif } -void LittleEndianByteOrder::networkToHost(de::duint32 const &networkValue, de::duint32 &hostValue) const +void LittleEndianByteOrder::networkToHost(duint32 networkValue, duint32 &hostValue) const { #ifndef __BIG_ENDIAN__ hostValue = networkValue; @@ -160,7 +162,7 @@ #endif } -void LittleEndianByteOrder::networkToHost(de::duint64 const &networkValue, de::duint64 &hostValue) const +void LittleEndianByteOrder::networkToHost(duint64 networkValue, duint64 &hostValue) const { #ifndef __BIG_ENDIAN__ hostValue = networkValue; @@ -169,7 +171,7 @@ #endif } -void LittleEndianByteOrder::hostToNetwork(de::duint16 const &hostValue, de::duint16 &networkValue) const +void LittleEndianByteOrder::hostToNetwork(duint16 hostValue, duint16 &networkValue) const { #ifndef __BIG_ENDIAN__ networkValue = hostValue; @@ -178,7 +180,7 @@ #endif } -void LittleEndianByteOrder::hostToNetwork(de::duint32 const &hostValue, de::duint32 &networkValue) const +void LittleEndianByteOrder::hostToNetwork(duint32 hostValue, duint32 &networkValue) const { #ifndef __BIG_ENDIAN__ networkValue = hostValue; @@ -187,7 +189,7 @@ #endif } -void LittleEndianByteOrder::hostToNetwork(de::duint64 const &hostValue, de::duint64 &networkValue) const +void LittleEndianByteOrder::hostToNetwork(duint64 hostValue, duint64 &networkValue) const { #ifndef __BIG_ENDIAN__ networkValue = hostValue; @@ -196,9 +198,9 @@ #endif } -de::duint64 swap64(de::duint64 const &n) +duint64 swap64(duint64 n) { - de::duint64 result; + duint64 result; dbyte const *in = reinterpret_cast(&n); dbyte *out = reinterpret_cast(&result); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/conditionaltrigger.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/conditionaltrigger.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/conditionaltrigger.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/conditionaltrigger.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,108 @@ +/** @file conditionaltrigger.cpp Conditional trigger. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/ConditionalTrigger" +#include "de/Value" + +#include + +namespace de { + +DENG2_PIMPL(ConditionalTrigger) +, DENG2_OBSERVES(Variable, Change) +{ + SafePtr condition; + QSet activeTriggers; + bool anyTrigger = false; + + Impl(Public *i) : Base(i) + {} + + void variableValueChanged(Variable &, Value const &) override + { + update(); + } + + void update() + { + anyTrigger = false; + activeTriggers.clear(); + + if (!condition) return; + + // The condition can be a text string or an array of text strings. + StringList const trigs = condition->value().asStringList(); + + for (String const &trig : trigs) + { + if (trig == "*") + { + anyTrigger = true; + activeTriggers.clear(); + break; + } + activeTriggers << trig; + } + } + + bool check(String const &trigger) + { + if (anyTrigger) return true; + return activeTriggers.contains(trigger); + } +}; + +ConditionalTrigger::ConditionalTrigger() + : d(new Impl(this)) +{} + +ConditionalTrigger::~ConditionalTrigger() +{} + +bool ConditionalTrigger::isValid() const +{ + return d->condition; +} + +void ConditionalTrigger::setCondition(Variable const &variable) +{ + if (d->condition) + { + d->condition->audienceForChange() -= d; + } + d->condition.reset(&variable); + variable.audienceForChange() += d; + d->update(); +} + +Variable const &ConditionalTrigger::condition() const +{ + return *d->condition; +} + +bool ConditionalTrigger::tryTrigger(String const &trigger) +{ + if (d->check(trigger)) + { + handleTriggered(trigger); + return true; + } + return false; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/gzip.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/gzip.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/gzip.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/gzip.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,76 @@ +/** @file gzip.cpp Process gzip data with zlib + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/data/gzip.h" + +#include + +namespace de { + +Block gDecompress(Block const &gzData) +{ + Block result(16384); + + z_stream stream = {}; + stream.next_in = const_cast(gzData.data()); + stream.avail_in = uint(gzData.size()); + stream.next_out = result.data(); + stream.avail_out = uint(result.size()); + + if (inflateInit2(&stream, 16 + MAX_WBITS) != Z_OK) + { + return Block(); + } + + int res = 0; + do + { + res = inflate(&stream, 0); + switch (res) + { + case Z_OK: + // Allocate more output space, if needed. + if (stream.avail_out == 0) + { + auto const oldSize = result.size(); + result.resize(result.size() * 2); + stream.next_out = result.data() + oldSize; + stream.avail_out = uint(result.size() - oldSize); + } + continue; + + case Z_STREAM_END: + break; + + default: + qWarning("Error decompressing gzip data: result=%i (%s)", res, stream.msg); + inflateEnd(&stream); + return Block(); + } + } + while (res != Z_STREAM_END); + DENG2_ASSERT(stream.avail_in == 0); + + // Truncate the extra space. + result.resize(result.size() - stream.avail_out); + + inflateEnd(&stream); + return result; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/huffman.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/huffman.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/huffman.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/huffman.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -19,7 +19,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/data/huffman.h" @@ -330,7 +330,7 @@ * Checks if the encoding/decoding buffer can hold the given number of * bytes. If not, reallocates the buffer. */ - void Huff_ResizeBuffer(HuffBuffer *buffer, dsize neededSize) + static void Huff_ResizeBuffer(HuffBuffer *buffer, dsize neededSize) { while (neededSize > buffer->size) { @@ -339,7 +339,7 @@ else buffer->size *= 2; } - buffer->data = (dbyte *) realloc(buffer->data, buffer->size); + buffer->data = reinterpret_cast(realloc(buffer->data, buffer->size)); } /** @@ -364,7 +364,7 @@ zapPtr(buffer); } - dbyte *encode(dbyte const *data, dsize size, dsize *encodedSize) + dbyte *encode(dbyte const *data, dsize size, dsize *encodedSize) const { HuffBuffer huffEnc; dsize i; @@ -429,7 +429,7 @@ return huffEnc.data; } - dbyte *decode(dbyte const *data, dsize size, dsize *decodedSize) + dbyte *decode(dbyte const *data, dsize size, dsize *decodedSize) const { HuffBuffer huffDec; HuffNode *node; @@ -439,7 +439,7 @@ dbyte bit = 3, lastByteBits; if (!data || size == 0) return nullptr; - + zap(huffDec); Huff_ResizeBuffer(&huffDec, 256); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/infobank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/infobank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/infobank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/infobank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -141,9 +141,7 @@ // Already added, from the looks of it. continue; } - add(id, newSourceFromInfo(id)); - delete &rec[VAR_NOT_IN_BANK]; } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/info.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/info.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/info.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/info.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,8 +22,10 @@ #include "de/Folder" #include "de/Log" #include "de/LogBuffer" +#include "de/RecordValue" #include "de/ScriptLex" #include "de/SourceLineTable" +#include #include @@ -806,6 +808,35 @@ _contents.clear(); } +Record Info::BlockElement::asRecord() const +{ + Record rec; + for (auto i = _contents.begin(); i != _contents.end(); ++i) + { + std::unique_ptr var(new Variable(i.key())); + const Element *elem = i.value(); + if (elem->isBlock()) + { + var->set(RecordValue::takeRecord(elem->as().asRecord())); + } + else if (elem->isList()) + { + std::unique_ptr array(new ArrayValue); + for (const auto &value : elem->values()) + { + array->add(new TextValue(value.text)); + } + var->set(array.release()); + } + else + { + var->set(new TextValue(elem->as().value().text)); + } + rec.add(var.release()); + } + return rec; +} + //--------------------------------------------------------------------------------------- Info::Info() : d(new Impl(this)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/json.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/json.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/json.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/json.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -324,7 +324,7 @@ static Block valueToJSON(Value const &value) { - if (value.is()) + if (is(value)) { return "null"; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/nonevalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/nonevalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/nonevalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/nonevalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -75,4 +75,10 @@ return "None"; } -} // namespace de \ No newline at end of file +const NoneValue &NoneValue::none() +{ + static NoneValue n; + return n; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/numbervalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/numbervalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/numbervalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/numbervalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -31,11 +31,11 @@ {} NumberValue::NumberValue(dint64 initialInteger) - : _value(initialInteger), _semantic(Generic) + : _value(initialInteger), _semantic(Int) {} NumberValue::NumberValue(duint64 initialUnsignedInteger) - : _value(initialUnsignedInteger), _semantic(Generic) + : _value(initialUnsignedInteger), _semantic(UInt) {} NumberValue::NumberValue(dint32 initialInteger, SemanticHints semantic) @@ -73,7 +73,7 @@ { Text result; QTextStream s(&result); - if (_semantic.testFlag(Boolean) && (_value == True || _value == False)) + if (_semantic.testFlag(Boolean) && (roundi(_value) == True || roundi(_value) == False)) { s << (isTrue()? "True" : "False"); } @@ -81,6 +81,14 @@ { s << "0x" << QString::number(duint32(_value), 16); } + else if (_semantic.testFlag(Int)) + { + s << QString::number(roundi(_value)); + } + else if (_semantic.testFlag(UInt)) + { + s << QString::number(round(_value)); + } else { s << _value; @@ -90,7 +98,7 @@ bool NumberValue::isTrue() const { - return (_value != 0); + return roundi(_value) != 0; } dint NumberValue::compare(Value const &value) const @@ -171,11 +179,15 @@ // Flags for serialization: static duint8 const SEMANTIC_BOOLEAN = 0x01; static duint8 const SEMANTIC_HEX = 0x02; +static duint8 const SEMANTIC_INT = 0x04; +static duint8 const SEMANTIC_UINT = 0x08; void NumberValue::operator >> (Writer &to) const { duint8 flags = (_semantic.testFlag(Boolean)? SEMANTIC_BOOLEAN : 0) | - (_semantic.testFlag(Hex)? SEMANTIC_HEX : 0); + (_semantic.testFlag(Hex)? SEMANTIC_HEX : 0) | + (_semantic.testFlag(Int)? SEMANTIC_INT : 0) | + (_semantic.testFlag(UInt)? SEMANTIC_UINT : 0); to << SerialId(NUMBER) << flags << _value; } @@ -194,7 +206,9 @@ from >> flags >> _value; _semantic = SemanticHints((flags & SEMANTIC_BOOLEAN? Boolean : 0) | - (flags & SEMANTIC_HEX? Hex : 0)); + (flags & SEMANTIC_HEX? Hex : 0) | + (flags & SEMANTIC_INT? Int : 0) | + (flags & SEMANTIC_UINT? UInt : 0)); } Value::Text NumberValue::typeId() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/profiles.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/profiles.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/profiles.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/profiles.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -404,6 +404,7 @@ if (!owner || owner->rename(*this, newName)) { d->name = newName; + notifyChange(); } return true; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/reader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/reader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/reader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/reader.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -329,7 +329,7 @@ Reader &Reader::operator >> (IByteArray &byteArray) { - duint size = 0; + duint32 size = 0; *this >> size; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/recordaccessor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/recordaccessor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/recordaccessor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/recordaccessor.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -133,21 +133,7 @@ StringList RecordAccessor::getStringList(String const &name, StringList defaultValue) const { if (!accessedRecord().has(name)) return defaultValue; - - StringList str; - Value const &value = get(name); - if (value.is()) - { - for (Value const *val : value.as().elements()) - { - str << val->asText(); - } - } - else - { - str << value.asText(); - } - return str; + return get(name).asStringList(); } Record const &RecordAccessor::subrecord(String const &name) const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/record.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/record.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/record.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/record.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,6 +22,7 @@ #include "de/BlockValue" #include "de/DictionaryValue" #include "de/FunctionValue" +#include "de/Info" #include "de/LogBuffer" #include "de/NumberValue" #include "de/Reader" @@ -556,77 +557,67 @@ return remove((*this)[variableName]); } -Variable &Record::add(String const &name) +Variable *Record::tryRemove(String const &variableName) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name))); + if (has(variableName)) + { + return remove(variableName); + } + return nullptr; } -Variable &Record::addNumber(String const &name, Value::Number const &number) +Variable &Record::add(String const &name, Variable::Flags variableFlags) { return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new NumberValue(number), Variable::AllowNumber)); + .add(new Variable(Impl::memberNameFromPath(name), nullptr, variableFlags)); +} + +Variable &Record::addNumber(String const &name, Value::Number number) +{ + return add(name, Variable::AllowNumber).set(NumberValue(number)); } Variable &Record::addBoolean(String const &name, bool booleanValue) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new NumberValue(booleanValue, NumberValue::Boolean), - Variable::AllowNumber)); + return add(name, Variable::AllowNumber).set(NumberValue(booleanValue, NumberValue::Boolean)); } Variable &Record::addText(String const &name, Value::Text const &text) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new TextValue(text), Variable::AllowText)); + return add(name, Variable::AllowText).set(TextValue(text)); } Variable &Record::addTime(String const &name, Time const &time) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new TimeValue(time), Variable::AllowTime)); + return add(name, Variable::AllowTime).set(TimeValue(time)); } Variable &Record::addArray(String const &name, ArrayValue *array) { // Automatically create an empty array if one is not provided. if (!array) array = new ArrayValue; - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - array, Variable::AllowArray)); + return add(name, Variable::AllowArray).set(array); } Variable &Record::addDictionary(String const &name) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new DictionaryValue, Variable::AllowDictionary)); + return add(name, Variable::AllowDictionary).set(new DictionaryValue); } Variable &Record::addBlock(String const &name) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new BlockValue, Variable::AllowBlock)); + return add(name, Variable::AllowBlock).set(new BlockValue); } Variable &Record::addFunction(const String &name, Function *func) { - return d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new FunctionValue(func), Variable::AllowFunction)); + return add(name, Variable::AllowFunction).set(new FunctionValue(func)); } Record &Record::add(String const &name, Record *subrecord) { std::unique_ptr sub(subrecord); - d->parentRecordByPath(name) - .add(new Variable(Impl::memberNameFromPath(name), - new RecordValue(sub.release(), RecordValue::OwnsRecord))); + add(name).set(RecordValue::takeRecord(sub.release())); return *subrecord; } @@ -691,40 +682,83 @@ return addText(name, value); } -Variable &Record::set(String const &name, Value::Number const &value) +Variable &Record::set(String const &name, Value::Number value) +{ + return set(name, NumberValue(value)); +} + +Variable &Record::set(const String &name, const NumberValue &value) { DENG2_GUARD(d); if (hasMember(name)) { - return (*this)[name].set(NumberValue(value)); + return (*this)[name].set(value); } - return addNumber(name, value); + return add(name, Variable::AllowNumber).set(value); } Variable &Record::set(String const &name, dint32 value) { - return set(name, Value::Number(value)); + return set(name, NumberValue(value)); } Variable &Record::set(String const &name, duint32 value) { - return set(name, Value::Number(value)); + return set(name, NumberValue(value)); } Variable &Record::set(String const &name, dint64 value) { - return set(name, Value::Number(value)); + return set(name, NumberValue(value)); } Variable &Record::set(String const &name, duint64 value) { - return set(name, Value::Number(value)); + return set(name, NumberValue(value)); } Variable &Record::set(String const &name, unsigned long value) { - return set(name, Value::Number(value)); + return set(name, NumberValue(value)); +} + +Variable &Record::set(String const &name, Time const &value) +{ + DENG2_GUARD(d); + + if (hasMember(name)) + { + return (*this)[name].set(TimeValue(value)); + } + return addTime(name, value); +} + +Variable &Record::set(String const &name, Block const &value) +{ + DENG2_GUARD(d); + + if (hasMember(name)) + { + return (*this)[name].set(BlockValue(value)); + } + Variable &var = addBlock(name); + var.value().block() = value; + return var; +} + +Variable &Record::set(const String &name, const Record &value) +{ + DENG2_GUARD(d); + + std::unique_ptr dup(new Record(value)); + if (hasMember(name)) + { + return (*this)[name].set(RecordValue::takeRecord(dup.release())); + } + Variable &var = add(name); + var.set(RecordValue::takeRecord(dup.release())); + return var; } Variable &Record::set(String const &name, ArrayValue *value) @@ -738,6 +772,28 @@ return addArray(name, value); } +Variable &Record::set(const String &name, Value *value) +{ + DENG2_GUARD(d); + + if (hasMember(name)) + { + return (*this)[name].set(value); + } + return add(name).set(value); +} + +Variable &Record::set(const String &name, const Value &value) +{ + DENG2_GUARD(d); + + if (hasMember(name)) + { + return (*this)[name].set(value); + } + return add(name).set(value); +} + Variable &Record::appendWord(String const &name, String const &word, String const &separator) { DENG2_GUARD(d); @@ -760,6 +816,15 @@ return (*this)[name]; } +Variable &Record::appendMultipleUniqueWords(String const &name, String const &words, String const &separator) +{ + foreach (String word, words.split(separator, QString::SkipEmptyParts)) + { + appendUniqueWord(name, word, separator); + } + return (*this)[name]; +} + Variable &Record::appendToArray(String const &name, Value *value) { DENG2_GUARD(d); @@ -770,7 +835,7 @@ } Variable &var = (*this)[name]; - DENG2_ASSERT(var.value().is()); + DENG2_ASSERT(is(var.value())); var.value().add(value); return var; } @@ -816,6 +881,16 @@ throw NotFoundError("Record::operator []", "Variable '" + name + "' not found"); } +Variable *Record::tryFind(String const &name) +{ + return const_cast(d->findMemberByPath(name)); +} + +Variable const *Record::tryFind(String const &name) const +{ + return d->findMemberByPath(name); +} + Record &Record::subrecord(String const &name) { return const_cast((const_cast(this))->subrecord(name)); @@ -838,6 +913,11 @@ throw NotFoundError("Record::subrecord", "Subrecord '" + name + "' not found"); } +dsize Record::size() const +{ + return dsize(d->members.size()); +} + Record::Members const &Record::members() const { return d->members; @@ -906,7 +986,7 @@ } } - return d->forSubrecords([this] (String const &, Record &rec) + return d->forSubrecords([](const String &, Record &rec) { if (rec.anyMembersChanged()) { @@ -1095,6 +1175,45 @@ return (*this)[lastOmitted]; } +String Record::asInfo() const +{ + String out; + QTextStream os(&out); + os.setCodec("UTF-8"); + for (auto i = d->members.constBegin(); i != d->members.constEnd(); ++i) + { + if (out) os << "\n"; + + const Variable &var = *i.value(); + String src = i.key(); + + if (is(var.value())) + { + src += " {\n" + var.valueAsRecord().asInfo(); + src.replace("\n", "\n "); + src += "\n}"; + } + else if (is(var.value())) + { + src += " " + var.value().asInfo(); + } + else + { + String valueText = var.value().asText(); + if (valueText.contains("\n")) + { + src += " = " + Info::quoteString(var.value().asText()); + } + else + { + src += ": " + valueText; + } + } + os << src; + } + return out; +} + QTextStream &operator << (QTextStream &os, Record const &record) { return os << record.asText(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/recordvalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/recordvalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/recordvalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/recordvalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -328,4 +328,14 @@ from >> dereference(); } +RecordValue *RecordValue::takeRecord(Record *record) +{ + return new RecordValue(record, OwnsRecord); +} + +RecordValue *RecordValue::takeRecord(Record &&record) +{ + return new RecordValue(new Record(record), OwnsRecord); +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/string.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/string.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/string.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/string.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -39,7 +39,7 @@ String::String(String const &other) : QString(other) {} -String::String(String &&moved) : QString(moved) +String::String(String &&moved) : QString(std::move(moved)) {} String::String(QString const &text) : QString(text) @@ -166,15 +166,22 @@ // The other path is absolute - use as is. return other; } + return concatenateRelativePath(other, dirChar); +} - String result = *this; +String String::concatenateRelativePath(const String &other, QChar dirChar) const +{ + if (other.isEmpty()) return *this; + + int const startPos = (other.first() == dirChar? 1 : 0); // Do a path combination. Check for a slash. + String result = *this; if (!empty() && last() != dirChar) { result += dirChar; } - result += other; + result += other.substr(startPos); return result; } @@ -213,6 +220,21 @@ return left(beginOfSpace + 1); } +String String::normalizeWhitespace() const +{ + static QRegularExpression const reg("\\s+"); + String s = *this; + s.replace(reg, " "); + return s.strip(); +} + +String String::removed(const QRegularExpression &expr) const +{ + String s = *this; + s.remove(expr); + return s; +} + String String::lower() const { return toLower(); @@ -437,13 +459,13 @@ return leftRef(n).compare(str.leftRef(n), Qt::CaseInsensitive); } -int String::commonPrefixLength(String const &str, Qt::CaseSensitivity sensitivity) const +int String::commonPrefixLength(String const &str, CaseSensitivity sensitivity) const { int count = 0; int len = qMin(str.size(), size()); for (int i = 0; i < len; ++i, ++count) { - if (sensitivity == Qt::CaseSensitive) + if (sensitivity == CaseSensitive) { if (at(i) != str.at(i)) break; } @@ -539,6 +561,11 @@ return token.QString::toInt(ok, base); } +duint32 String::toUInt32(bool *ok, int base) const +{ + return QString::toUInt(ok, base); +} + String String::addLinePrefix(String const &prefix) const { String result; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/textvalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/textvalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/textvalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/textvalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -71,7 +71,7 @@ { // We are able to look for substrings within the text, without applying automatic // type conversions. - if (value.is()) + if (is(value)) { return _value.indexOf(value.asText(), Qt::CaseSensitive) >= 0; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/time.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/time.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/time.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/time.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -31,8 +31,14 @@ namespace de { static String const ISO_FORMAT = "yyyy-MM-dd hh:mm:ss.zzz"; -static HighPerformanceTimer highPerfTimer; -static TimeDelta currentHighPerfDelta; + +static HighPerformanceTimer &highPerfTimer() +{ + static HighPerformanceTimer hpt; + return hpt; +} + +static TimeSpan currentHighPerfDelta; namespace internal { @@ -52,37 +58,37 @@ } // namespace internal -duint64 Time::Delta::asMicroSeconds() const +duint64 Time::Span::asMicroSeconds() const { return duint64(_seconds * 1000000); } -duint64 TimeDelta::asMilliSeconds() const +duint64 TimeSpan::asMilliSeconds() const { return duint64(_seconds * 1000); } -ddouble TimeDelta::asMinutes() const +ddouble TimeSpan::asMinutes() const { return _seconds / 60; } -ddouble TimeDelta::asHours() const +ddouble TimeSpan::asHours() const { return _seconds / 3600; } -ddouble TimeDelta::asDays() const +ddouble TimeSpan::asDays() const { return asHours() / 24; } -Time::Delta Time::Delta::sinceStartOfProcess() +Time::Span Time::Span::sinceStartOfProcess() { - return highPerfTimer.elapsed(); + return highPerfTimer().elapsed(); } -void TimeDelta::sleep() const +void TimeSpan::sleep() const { if (_seconds < 60) { @@ -94,12 +100,12 @@ } } -void TimeDelta::operator >> (Writer &to) const +void TimeSpan::operator >> (Writer &to) const { to << _seconds; } -void TimeDelta::operator << (Reader &from) +void TimeSpan::operator << (Reader &from) { from >> _seconds; } @@ -114,17 +120,17 @@ Flags flags; QDateTime dateTime; - Delta highPerfElapsed; + Span highPerfElapsed; Impl() : flags(DateTime | HighPerformance) , dateTime(QDateTime::currentDateTime()) - , highPerfElapsed(highPerfTimer.elapsed()) + , highPerfElapsed(highPerfTimer().elapsed()) {} Impl(QDateTime const &dt) : flags(DateTime), dateTime(dt) {} - Impl(Delta const &delta) : flags(HighPerformance), highPerfElapsed(delta) {} + Impl(Span const &span) : flags(HighPerformance), highPerfElapsed(span) {} Impl(Impl const &other) : de::IPrivate() @@ -179,19 +185,19 @@ if (flags.testFlag(DateTime)) { // This is DateTime but other is high-perf. - return fequal(highPerfTimer.startedAt().asDateTime().msecsTo(dateTime)/1000.0, + return fequal(highPerfTimer().startedAt().asDateTime().msecsTo(dateTime)/1000.0, other.highPerfElapsed); } if (flags.testFlag(HighPerformance)) { // This is high-perf and the other is DateTime. return fequal(highPerfElapsed, - highPerfTimer.startedAt().asDateTime().msecsTo(other.dateTime)/1000.0); + highPerfTimer().startedAt().asDateTime().msecsTo(other.dateTime)/1000.0); } return false; } - void add(Delta const &delta) + void add(Span const &delta) { if (flags.testFlag(DateTime)) { @@ -203,7 +209,7 @@ } } - Delta delta(Impl const &earlier) const + Span delta(Impl const &earlier) const { if (flags.testFlag(HighPerformance) && earlier.flags.testFlag(HighPerformance)) { @@ -223,7 +229,7 @@ void setDateTimeFromHighPerf() { - dateTime = (highPerfTimer.startedAt() + highPerfElapsed).asDateTime(); + dateTime = (highPerfTimer().startedAt() + highPerfElapsed).asDateTime(); flags |= DateTime; } }; @@ -233,14 +239,14 @@ Time::Time(Time const &other) : d(new Impl(*other.d)) {} - + Time::Time(Time &&moved) : d(std::move(moved.d)) {} Time::Time(QDateTime const &t) : d(new Impl(t)) {} -Time::Time(TimeDelta const &highPerformanceDelta) +Time::Time(TimeSpan const &highPerformanceDelta) : ISerializable(), d(new Impl(highPerformanceDelta)) {} @@ -254,7 +260,7 @@ *d = *other.d; return *this; } - + Time &Time::operator = (Time &&moved) { d = std::move(moved.d); @@ -276,20 +282,20 @@ return d->isEqualTo(*t.d); } -Time Time::operator + (Delta const &delta) const +Time Time::operator + (Span const &span) const { Time result = *this; - result += delta; + result += span; return result; } -Time &Time::operator += (Delta const &delta) +Time &Time::operator += (Span const &span) { - d->add(delta); + d->add(span); return *this; } -TimeDelta Time::operator - (Time const &earlierTime) const +TimeSpan Time::operator - (Time const &earlierTime) const { return d->delta(*earlierTime.d); } @@ -321,22 +327,34 @@ } else if (format == FriendlyFormat) { - return d->dateTime.toString(Qt::TextDate); + // Is it today? + if (d->dateTime.date() == QDateTime::currentDateTime().date()) + { + return d->dateTime.toString("HH:mm"); + } + else if (d->dateTime.date().year() == QDateTime::currentDateTime().date().year()) + { + return d->dateTime.toString("MMM dd HH:mm"); + } + else + { + return d->dateTime.toString("YYYY MMM dd"); + } } else if (format == BuildNumberAndSecondsSinceStart || format == SecondsSinceStart) { - TimeDelta elapsed; + TimeSpan elapsed; if (d->flags.testFlag(Impl::HighPerformance)) { elapsed = d->highPerfElapsed; } else if (d->flags.testFlag(Impl::DateTime)) { - elapsed = highPerfTimer.startedAt().deltaTo(Time(d->dateTime)); + elapsed = highPerfTimer().startedAt().deltaTo(Time(d->dateTime)); } int hours = int(elapsed.asHours()); - TimeDelta sec = elapsed - hours * 3600.0; + TimeSpan sec = elapsed - hours * 3600.0; QString prefix; if (format == BuildNumberAndSecondsSinceStart) { @@ -365,10 +383,31 @@ return ""; } +static int parseMonth(String const &shortName) +{ + static char const *months[] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" + }; + + for (int i = 0; i < 12; ++i) + { + if (shortName == months[i]) + { + return i + 1; + } + } + return 0; +} + Time Time::fromText(String const &text, Time::Format format) { - DENG2_ASSERT(format == ISOFormat || format == ISODateOnly || format == FriendlyFormat || - format == CompilerDateTime || format == HumanDate); + DENG2_ASSERT(format == ISOFormat || + format == ISODateOnly || + format == FriendlyFormat || + format == CompilerDateTime || + format == HumanDate || + format == UnixLsStyleDateTime); if (format == ISOFormat) { @@ -386,28 +425,48 @@ { // Parse the text manually as it is locale-independent. QStringList const parts = text.split(" ", QString::SkipEmptyParts); - DENG2_ASSERT(parts.size() == 4); - char const *months[] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", - "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" - }; - int day = parts[1].toInt(); - int year = parts[2].toInt(); - int month = 0; - for (int i = 0; i < 12; ++i) - { - if (parts[0] == months[i]) - { - month = i + 1; - break; - } - } - QDate date(year, month, day); - QTime time = QTime::fromString(parts[3], "HH:mm:ss"); - return Time(QDateTime(date, time)); + if (parts.size() >= 4) + { + int day = parts[1].toInt(); + int year = parts[2].toInt(); + int month = parseMonth(parts[0]); + QDate date(year, month, day); + QTime time = QTime::fromString(parts[3], "HH:mm:ss"); + return Time(QDateTime(date, time)); + } + } + else if (format == UnixLsStyleDateTime) + { + // Two options: + // Jun 2 2016 + // Jun 2 06:30 + + QStringList const parts = text.split(" ", QString::SkipEmptyParts); + if (parts.size() >= 3) + { + int month = parseMonth(parts[0]); + int day = parts[1].toInt(); + int hour = 0; + int minute = 0; + int year; + if (parts[2].contains(QChar(':'))) + { + year = QDate::currentDate().year(); + hour = parts[2].left(2).toInt(); + minute = parts[2].right(2).toInt(); + return Time(QDateTime(QDate(year, month, day), + QTime(hour, minute, 0))); + } + else + { + year = parts[2].toInt(); + return Time(QDateTime(QDate(year, month, day), QTime(0, 0, 0))); + } + } } else if (format == HumanDate) { + // Note: Check use of indices below. static QStringList const formats({ "M/d/yy", "MM/dd/yy", @@ -419,24 +478,37 @@ "dd.MM.yyyy", "MM.dd.yyyy", // as a fallback... "yyyy-MM-dd", + + // Unix "ls" style: + "MMM d yyyy", + "MMM d hh:mm", }); + String const normText = text.normalizeWhitespace(); for (int i = 0; i < formats.size(); ++i) { String const fmt = formats.at(i); bool const isShortYear = i < 4; - QDate date = QDate::fromString(text, fmt); - if (date.isValid()) + QDateTime dt = QDateTime::fromString(normText, fmt); + if (dt.isValid()) { - if (isShortYear && date.year() < 1980) + if (i == 10) // No year specified. { - date.setDate(date.year() + 100, date.month(), date.day()); // Y2K? + dt.setDate(QDate(QDate::currentDate().year(), + dt.date().month(), + dt.date().day())); } - return Time(QDateTime(date)); + else if (isShortYear && dt.date().year() < 1980) + { + dt.setDate(QDate(dt.date().year() + 100, + dt.date().month(), + dt.date().day())); // Y2K? + } + return Time(dt); } } - return Time(QDateTime::fromString(text, Qt::TextDate)); + return Time(QDateTime::fromString(normText, Qt::TextDate)); } - return Time(); + return Time::invalidTime(); } QDateTime &de::Time::asDateTime() @@ -449,7 +521,7 @@ { if (!d->hasDateTime() && d->flags.testFlag(Impl::HighPerformance)) { - d->dateTime = (highPerfTimer.startedAt() + d->highPerfElapsed).asDateTime(); + d->dateTime = (highPerfTimer().startedAt() + d->highPerfElapsed).asDateTime(); d->flags |= Impl::DateTime; } return d->dateTime; @@ -491,8 +563,8 @@ if (from.version() >= DENG2_PROTOCOL_1_11_0_Time_high_performance) { /* - * Starting from build 926, Time can optionally contain a - * high-performance delta component. + * Starting from build 926, Time can optionally contain a high-performance delta + * component. */ duint8 flags; @@ -522,7 +594,7 @@ { // If both are present, the high-performance time should be synced // with current high-perf timer. - if (d->dateTime < highPerfTimer.startedAt().asDateTime()) + if (d->dateTime < highPerfTimer().startedAt().asDateTime()) { // Current high-performance timer was started after this time; // we can't represent the time as high performance delta. @@ -530,7 +602,7 @@ } else { - d->highPerfElapsed = highPerfTimer.startedAt().deltaTo(d->dateTime); + d->highPerfElapsed = highPerfTimer().startedAt().deltaTo(d->dateTime); } } } @@ -546,7 +618,7 @@ } } -TimeDelta Time::highPerformanceTime() const +TimeSpan Time::highPerformanceTime() const { DENG2_ASSERT(d->flags & Impl::HighPerformance); return d->highPerfElapsed; @@ -559,7 +631,7 @@ void Time::updateCurrentHighPerformanceTime() // static { - currentHighPerfDelta = highPerfTimer.elapsed(); + currentHighPerfDelta = highPerfTimer().elapsed(); } QTextStream &operator << (QTextStream &os, Time const &t) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/timevalue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/timevalue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/timevalue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/timevalue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -57,12 +57,12 @@ void TimeValue::sum(Value const &value) { - _time += TimeDelta(value.asNumber()); + _time += TimeSpan(value.asNumber()); } void TimeValue::subtract(Value const &subtrahend) { - _time -= TimeDelta(subtrahend.asNumber()); + _time -= TimeSpan(subtrahend.asNumber()); } void TimeValue::operator >> (Writer &to) const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/value.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/value.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/value.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/value.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -61,7 +61,29 @@ int Value::asInt() const { - return round(asNumber()); + const double num = asNumber(); + if (num > std::numeric_limits::max()) + { + return std::numeric_limits::max(); + } + return round(num); +} + +StringList Value::asStringList() const +{ + StringList str; + if (is(this)) + { + for (Value const *val : as().elements()) + { + str << val->asText(); + } + } + else + { + str << asText(); + } + return str; } Record *Value::memberScope() const diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/variable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/variable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/variable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/variable.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -78,7 +78,10 @@ v.reset(new NoneValue); } verifyName(d->name); - verifyValid(*v); + if (initial) + { + verifyValid(*v); + } d->value = v.release(); } @@ -103,6 +106,12 @@ return *this; } +Variable &Variable::operator = (String const &textValue) +{ + set(new TextValue(textValue)); + return *this; +} + Variable &Variable::set(Value *v) { DENG2_ASSERT(v != 0); @@ -233,13 +242,13 @@ bool Variable::isValid(Value const &v) const { /// @todo Make sure this actually works and add func, record, ref. - if ((dynamic_cast(&v) && !d->flags.testFlag(AllowNone)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowNumber)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowText)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowArray)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowDictionary)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowBlock)) || - (dynamic_cast(&v) && !d->flags.testFlag(AllowTime))) + if ((!d->flags.testFlag(AllowNone) && dynamic_cast(&v) ) || + (!d->flags.testFlag(AllowNumber) && dynamic_cast(&v) ) || + (!d->flags.testFlag(AllowText) && dynamic_cast(&v) ) || + (!d->flags.testFlag(AllowArray) && dynamic_cast(&v) ) || + (!d->flags.testFlag(AllowDictionary) && dynamic_cast(&v)) || + (!d->flags.testFlag(AllowBlock) && dynamic_cast(&v) ) || + (!d->flags.testFlag(AllowTime) && dynamic_cast(&v) ) ) { return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/ziparchive.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/ziparchive.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/data/ziparchive.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/data/ziparchive.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -376,7 +376,8 @@ DOSDate lastModDate(header.lastModDate); DOSTime lastModTime(header.lastModTime); entry->modifiedAt = QDateTime(QDate(lastModDate.year + 1980, lastModDate.month, lastModDate.dayOfMonth), - QTime(lastModTime.hours, lastModTime.minutes, lastModTime.seconds)); + QTime(lastModTime.hours, lastModTime.minutes, lastModTime.seconds), + Qt::UTC); // buildpackage.py sets UTC for .packs if (readingFromOriginal) { @@ -752,7 +753,7 @@ bool ZipArchive::recognize(File const &file) { - if (file.status().type() == File::Status::FILE) + if (file.status().type() == File::Type::File) { // For now, just check the name. return recognizeZipExtension(file.extension().lower()); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/assetobserver.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/assetobserver.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/assetobserver.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/assetobserver.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -21,18 +21,18 @@ #include "de/FileSystem" #include "de/LinkFile" #include "de/Loop" -#include +#include namespace de { namespace filesys { - -static QString const PREFIX = "asset"; + +static const std::string PREFIX = "asset"; DENG2_PIMPL(AssetObserver) , DENG2_OBSERVES(FileIndex, Addition) , DENG2_OBSERVES(FileIndex, Removal) { - QRegExp pattern; + const std::regex pattern; LoopCallback mainCall; static FileIndex const &linkIndex() { @@ -40,13 +40,13 @@ } static String assetIdentifier(File const &link) { - DENG2_ASSERT(link.name().beginsWith(PREFIX + ".")); + DENG2_ASSERT(link.name().beginsWith(String::fromStdString(PREFIX + "."))); return link.name().mid(6); } Impl(Public *i, String const ®ex) : Base(i) - , pattern(PREFIX + "\\." + regex, Qt::CaseInsensitive) + , pattern(PREFIX + "\\." + regex.toStdString(), std::regex::icase) { // We will observe available model assets. linkIndex().audienceForAddition() += this; @@ -56,7 +56,7 @@ void fileAdded(File const &link, FileIndex const &) { // Only matching assets cause notifications. - if (!pattern.exactMatch(link.name())) return; + if (!std::regex_match(link.name().toStdString(), pattern)) return; String const ident = assetIdentifier(link); mainCall.enqueue([this, ident] () @@ -71,7 +71,7 @@ void fileRemoved(File const &link, FileIndex const &) { // Only matching assets cause notifications. - if (!pattern.exactMatch(link.name())) return; + if (!std::regex_match(link.name().toStdString(), pattern)) return; DENG2_FOR_PUBLIC_AUDIENCE2(Availability, i) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/directoryfeed.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/directoryfeed.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/directoryfeed.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/directoryfeed.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -27,46 +27,74 @@ #include #include -using namespace de; +namespace de { + +static String const fileStatusSuffix = ".doomsday_file_status"; + +DENG2_PIMPL_NOREF(DirectoryFeed) +{ + NativePath nativePath; + Flags mode; + String namePattern; +}; DirectoryFeed::DirectoryFeed(NativePath const &nativePath, Flags const &mode) - : _nativePath(nativePath), _mode(mode) {} + : d(new Impl) +{ + d->nativePath = nativePath; + d->mode = mode; +} -DirectoryFeed::~DirectoryFeed() -{} +void DirectoryFeed::setNamePattern(const String &namePattern) +{ + d->namePattern = namePattern; +} String DirectoryFeed::description() const { - return "directory \"" + _nativePath.pretty() + "\""; + String desc; + if (d->namePattern) + { + desc = "files matching \"" + d->namePattern + "\" in "; + } + desc += "directory \"" + d->nativePath.pretty() + "\""; + return desc; } -NativePath const &DirectoryFeed::nativePath() const +const NativePath &DirectoryFeed::nativePath() const { - return _nativePath; + return d->nativePath; } Feed::PopulatedFiles DirectoryFeed::populate(Folder const &folder) { - if (_mode & AllowWrite) + if (d->mode & AllowWrite) { // Automatically enable modifying the Folder. const_cast(folder).setMode(File::Write); } - if (_mode.testFlag(CreateIfMissing) && !NativePath::exists(_nativePath)) + if (d->mode.testFlag(CreateIfMissing) && !NativePath::exists(d->nativePath)) { - NativePath::createPath(_nativePath); + NativePath::createPath(d->nativePath); } - QDir dir(_nativePath); + QDir dir(d->nativePath); if (!dir.isReadable()) { /// @throw NotFoundError The native directory was not accessible. - throw NotFoundError("DirectoryFeed::populate", "Path '" + _nativePath + "' inaccessible"); + throw NotFoundError("DirectoryFeed::populate", "Path '" + d->nativePath + "' inaccessible"); } QStringList nameFilters; - nameFilters << "*"; + if (d->namePattern) + { + nameFilters << d->namePattern; + } + else + { + nameFilters << "*"; + } QDir::Filters dirFlags = QDir::Files | QDir::NoDotAndDotDot; - if (_mode.testFlag(PopulateNativeSubfolders)) + if (d->mode.testFlag(PopulateNativeSubfolders)) { dirFlags |= QDir::Dirs; } @@ -79,7 +107,10 @@ } else { - populateFile(folder, entry.fileName(), populated); + if (!entry.fileName().endsWith(fileStatusSuffix)) // ignore meta files + { + populateFile(folder, entry.fileName(), populated); + } } } return populated; @@ -106,7 +137,7 @@ subFolder = &folder.locate(entryName); } - if (_mode & AllowWrite) + if (d->mode & AllowWrite) { subFolder->setMode(File::Write); } @@ -128,24 +159,21 @@ return; } - NativePath const entryPath = _nativePath / entryName; + NativePath const entryPath = d->nativePath / entryName; // Open the native file. std::unique_ptr nativeFile(new NativeFile(entryName, entryPath)); nativeFile->setStatus(fileStatus(entryPath)); - if (_mode & AllowWrite) + if (d->mode & AllowWrite) { nativeFile->setMode(File::Write); } File *file = folder.fileSystem().interpret(nativeFile.release()); - //folder.add(file); // We will decide on pruning this. file->setOriginFeed(this); - // Include files in the main index. - //folder.fileSystem().index(*file); populated << file; } catch (StatusError const &er) @@ -164,7 +192,7 @@ /// Rules for pruning: /// - A file sourced by NativeFile will be pruned if it's out of sync with the hard /// drive version (size, time of last modification). - if (NativeFile *nativeFile = maybeAs(file)) + if (NativeFile *nativeFile = maybeAs(file.source())) { try { @@ -189,9 +217,9 @@ if (subFolder->feeds().size() == 1) { DirectoryFeed *dirFeed = maybeAs(subFolder->feeds().front()); - if (dirFeed && !NativePath::exists(dirFeed->_nativePath)) + if (dirFeed && !dirFeed->d->nativePath.exists()) { - LOG_RES_NOTE("Pruning \"%s\": no longer exists") << _nativePath; + LOG_RES_NOTE("Pruning %s: no longer exists") << dirFeed->description(); //d->nativePath; return true; } } @@ -203,7 +231,7 @@ File *DirectoryFeed::createFile(String const &name) { - NativePath newPath = _nativePath / name; + NativePath newPath = d->nativePath / name; /*if (NativePath::exists(newPath)) { /// @throw AlreadyExistsError The file @a name already exists in the native directory. @@ -217,15 +245,14 @@ void DirectoryFeed::destroyFile(String const &name) { - NativePath path = _nativePath / name; + NativePath path = d->nativePath / name; - if (!NativePath::exists(path)) + if (!path.exists()) { // The file doesn't exist in the native file system, we can ignore this. return; } - - if (!QDir::current().remove(path)) + if (!path.destroy()) { /// @throw RemoveError The file @a name exists but could not be removed. throw RemoveError("DirectoryFeed::destroyFile", "Cannot remove \"" + name + @@ -235,12 +262,12 @@ Feed *DirectoryFeed::newSubFeed(String const &name) { - NativePath subPath = _nativePath / name; - if (_mode.testFlag(CreateIfMissing) || (subPath.exists() && subPath.isReadable())) + NativePath subPath = d->nativePath / name; + if (d->mode.testFlag(CreateIfMissing) || (subPath.exists() && subPath.isReadable())) { - return new DirectoryFeed(subPath, _mode); + return new DirectoryFeed(subPath, d->mode); } - return 0; + return nullptr; } void DirectoryFeed::changeWorkingDir(NativePath const &nativePath) @@ -256,7 +283,6 @@ File::Status DirectoryFeed::fileStatus(NativePath const &nativePath) { QFileInfo info(nativePath); - if (!info.exists()) { /// @throw StatusError Determining the file status was not possible. @@ -264,17 +290,53 @@ } // Get file status information. - return File::Status(info.isDir()? File::Status::FOLDER : File::Status::FILE, - dsize(info.size()), - info.lastModified()); + File::Status st { info.isDir()? File::Type::Folder : File::Type::File, + dsize(info.size()), + info.lastModified() }; + + // Check for overridden status. + String const overrideName = nativePath + fileStatusSuffix; + if (QFileInfo().exists(overrideName)) + { + QFile f(overrideName); + if (f.open(QFile::ReadOnly)) + { + st.modifiedAt = Time::fromText(String::fromUtf8(f.readAll()), Time::ISOFormat); + } + } + return st; +} + +void DirectoryFeed::setFileModifiedTime(NativePath const &nativePath, Time const &modifiedAt) +{ + String const overrideName = nativePath + fileStatusSuffix; + if (!modifiedAt.isValid()) + { + QFile::remove(overrideName); + return; + } + QFile f(overrideName); + if (f.open(QFile::WriteOnly | QFile::Truncate)) + { + f.write(modifiedAt.asText(Time::ISOFormat).toUtf8()); + } } File &DirectoryFeed::manuallyPopulateSingleFile(NativePath const &nativePath, - Folder &parentFolder) + Folder &parentFolder) // static { - Folder *parent = &parentFolder; + const bool isExisting = nativePath.exists(); + Folder * parent = &parentFolder; - File::Status const status = fileStatus(nativePath); + File::Status status; + if (isExisting) + { + status = fileStatus(nativePath); + } + else + { + status.modifiedAt = Time(); // file being created now + } // If we're populating a .pack, the possible container .packs must be included as // parent folders (in structure only, not all their contents). Otherwise the .pack @@ -300,20 +362,33 @@ } } - if (status.type() == File::Status::FILE) + const String newFilePath = parent->path() / nativePath.fileName(); + + if (status.type() == File::Type::File) { - auto *source = new NativeFile(nativePath.fileName(), nativePath); - source->setStatus(status); - File *file = FileSystem::get().interpret(source); - parent->add(file); - FileSystem::get().index(*file); - return *file; + parent->clear(); + parent->clearFeeds(); + + auto *feed = new DirectoryFeed(nativePath.fileNamePath()); + feed->setNamePattern(nativePath.fileName()); + parent->attach(feed); + if (isExisting) + { + parent->populate(); + } + else + { + parent->replaceFile(nativePath.fileName()); + } + return FS::locate(newFilePath); } else { - return FS::get().makeFolderWithFeed(parent->path() / nativePath.fileName(), + return FS::get().makeFolderWithFeed(newFilePath, new DirectoryFeed(nativePath), Folder::PopulateFullTree, FS::DontInheritFeeds | FS::PopulateNewFolder); } } + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/file.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/file.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/file.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/file.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -159,7 +159,11 @@ // feed itself (would be redundant). if (originFeed() && (verbosity >= 2 || !is(originFeed()))) { - desc += " from " + originFeed()->description(); + String const feedDesc = originFeed()->description(); + if (!desc.contains(feedDesc)) // A bit of a kludge; don't repeat the feed description. + { + desc += " from " + feedDesc; + } } #ifdef DENG2_DEBUG @@ -425,7 +429,7 @@ txt += flags + QString("%1 %2 %3") .arg(f->size(), 9) - .arg(f->status().modifiedAt.asText()) + .arg(f->status().modifiedAt.asText(), 23) .arg(f->name()); // Link target. @@ -452,11 +456,7 @@ Block File::metaId() const { auto const &st = target().status(); - - Block data; - Writer writer(data); - writer << path() << duint64(st.size) << st.modifiedAt; - return data.md5Hash(); + return md5Hash(path(), duint64(st.size), st.modifiedAt); } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/fileindex.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/fileindex.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/fileindex.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/fileindex.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -98,7 +98,7 @@ for (Index::const_iterator i = range.first; i != range.second; ++i) { File *file = i->second; - if (file->path().fileNamePath().endsWith(dir, Qt::CaseInsensitive)) + if (file->path().fileNamePath().endsWith(dir, String::CaseInsensitive)) { found.push_back(file); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/filesystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/filesystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/filesystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/filesystem.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -23,14 +23,19 @@ #include "de/ArchiveFeed" #include "de/ArchiveFolder" #include "de/DirectoryFeed" +#include "de/DictionaryValue" #include "de/Guard" #include "de/LibraryFile" #include "de/Log" #include "de/LogBuffer" +#include "de/Loop" #include "de/NativePath" +#include "de/ScriptSystem" +#include "de/TextValue" #include "de/ZipArchive" #include +#include namespace de { @@ -38,6 +43,12 @@ DENG2_PIMPL_NOREF(FileSystem) { + std::mutex busyMutex; + int busyLevel = 0; + std::condition_variable busyFinished; + + Record fsModule; + QList interpreters; /// The main index to all files in the file system. @@ -56,6 +67,8 @@ Impl() { root.reset(new Folder); + + ScriptSystem::get().addNativeModule("FS", fsModule); } ~Impl() @@ -63,7 +76,7 @@ root.reset(); DENG2_GUARD(typeIndex); - qDeleteAll(typeIndex.value.values()); + qDeleteAll(typeIndex.value); typeIndex.value.clear(); } @@ -77,8 +90,12 @@ } return *idx; } + + DENG2_PIMPL_AUDIENCE(Busy) }; +DENG2_AUDIENCE_METHOD(FileSystem, Busy) + FileSystem::FileSystem() : d(new Impl) {} @@ -87,23 +104,14 @@ d->interpreters.prepend(&interpreter); } -void FileSystem::refresh() +void FileSystem::refreshAsync() { - if (Folder::isPopulatingAsync()) + // We may need to wait until a previous population is complete. + Folder::afterPopulation([this] () { - qDebug() << "FileSystem has to wait for previous population to finish..."; - } - - // Wait for a previous refresh to finish. - Folder::waitForPopulation(); - - LOG_AS("FS::refresh"); - - //Time startedAt; - d->root->populate(Folder::PopulateAsyncFullTree); - - /*LOGDEV_RES_VERBOSE("Completed in %.2f seconds") << startedAt.since(); - printIndex();*/ + LOG_AS("FS::refresh"); + d->root->populate(Folder::PopulateAsyncFullTree); + }); } Folder &FileSystem::makeFolder(String const &path, FolderCreationBehaviors behavior) @@ -300,12 +308,14 @@ } File &FileSystem::copySerialized(String const &sourcePath, String const &destinationPath, - CopyBehaviors behavior) + CopyBehaviors behavior) // static { + auto &fs = get(); + Block contents; - *root().locate(sourcePath).source() >> contents; + *fs.root().locate(sourcePath).source() >> contents; - File *dest = &root().replaceFile(destinationPath); + File *dest = &fs.root().replaceFile(destinationPath); *dest << contents; dest->flush(); @@ -329,6 +339,61 @@ // perform time-based processing (indexing/pruning/refreshing) } +void FileSystem::changeBusyLevel(int increment) +{ + using namespace std; + + bool notify = false; + BusyStatus bs = Idle; + { + lock_guard g(d->busyMutex); + const int oldLevel = d->busyLevel; + d->busyLevel += increment; + if (d->busyLevel == 0) + { + notify = true; + bs = Idle; + d->busyFinished.notify_all(); + } + else if (oldLevel == 0) + { + notify = true; + bs = Busy; + } + } + if (notify) + { + Loop::mainCall([this, bs]() { + lock_guard g(d->busyMutex); + // Only notify if the busy level is still up to date. + if ((bs == Busy && d->busyLevel > 0) || + (bs == Idle && d->busyLevel == 0)) + { + DENG2_FOR_AUDIENCE2(Busy, i) { i->fileSystemBusyStatusChanged(bs); } + } + }); + } +} + +int FileSystem::busyLevel() const +{ + std::lock_guard lk(d->busyMutex); + return d->busyLevel; +} + +void FileSystem::waitForIdle() // static +{ + using namespace std; + + auto &fs = get(); + unique_lock lk(fs.d->busyMutex); + if (fs.d->busyLevel > 0) + { + LOG_MSG("Waiting until file system is ready"); + fs.d->busyFinished.wait(lk); + } +} + FileIndex const &FileSystem::indexFor(String const &typeName) const { return d->getTypeIndex(typeName); @@ -362,24 +427,53 @@ } } -String FileSystem::accessNativeLocation(NativePath const &nativePath, File::Flags flags) +String FileSystem::accessNativeLocation(NativePath const &nativePath, File::Flags flags) // static { - static String const folders = "/sys/folders"; + static const String SYS_NATIVE = "/sys/native"; + static const String VAR_MAPPING = "accessNames"; - makeFolder(folders); + auto &fs = get(); - String const path = folders / nativePath.fileNamePath().fileName(); - if (!root().has(path)) + Folder &sysNative = fs.makeFolder(SYS_NATIVE); + if (!sysNative.objectNamespace().hasMember(VAR_MAPPING)) + { + sysNative.objectNamespace().addDictionary(VAR_MAPPING); + } + +// String accessPath = SYS_NATIVE; + + // The accessed paths are kept in a dictionary so we'll know when the same path is + // reaccessed and needs to be replaced. + DictionaryValue &mapping = sysNative[VAR_MAPPING].value(); + const TextValue key(nativePath); + if (!mapping.contains(key)) + { + // Generate a unique access path. + String name; + do + { + name = String("%1").arg(Rangei(0, 65536).random(), 4, 16, QChar('0')); + } while (sysNative.has(name)); + mapping.setElement(key, new TextValue(name)); + } + + File &f = DirectoryFeed::manuallyPopulateSingleFile( + nativePath, fs.makeFolder(sysNative.path() / mapping[key].asText())); + f.setMode(flags); + return f.path(); + + /* String const path = folders / nativePath.fileNamePath().fileName(); + if (!fs.root().has(path)) { DirectoryFeed::Flags feedFlags = DirectoryFeed::OnlyThisFolder; if (flags.testFlag(File::Write)) feedFlags |= DirectoryFeed::AllowWrite; - makeFolderWithFeed(path, - new DirectoryFeed(nativePath.fileNamePath(), feedFlags), - Folder::PopulateOnlyThisFolder, - FS::DontInheritFeeds | FS::PopulateNewFolder) + fs.makeFolderWithFeed(path, + new DirectoryFeed(nativePath.fileNamePath(), feedFlags), + Folder::PopulateOnlyThisFolder, + FS::DontInheritFeeds | FS::PopulateNewFolder) .setMode(flags); - } - return path / nativePath.fileName(); + }*/ + //return path / nativePath.fileName(); } Folder &FileSystem::root() @@ -392,6 +486,11 @@ return *d->root; } +Folder &FileSystem::rootFolder() // static +{ + return get().root(); +} + FileSystem &FileSystem::get() // static { return App::fileSystem(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/folder.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/folder.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/folder.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/folder.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -19,36 +19,40 @@ #include "de/Folder" +#include "de/App" +#include "de/Async" #include "de/DirectoryFeed" #include "de/FS" #include "de/Feed" #include "de/Guard" #include "de/LogBuffer" #include "de/NumberValue" +#include "de/ScriptedInfo" #include "de/ScriptSystem" #include "de/Task" #include "de/TaskPool" +#include "de/UnixInfo" namespace de { FolderPopulationAudience audienceForFolderPopulation; // public -namespace internal +namespace internal { + +static TaskPool populateTasks; +static bool enableBackgroundPopulation = true; + +/// Forwards internal folder population notifications to the public audience. +struct PopulationNotifier : DENG2_OBSERVES(TaskPool, Done) { - static TaskPool populateTasks; + PopulationNotifier() { populateTasks.audienceForDone() += this; } + void taskPoolDone(TaskPool &) { notify(); } + void notify() { DENG2_FOR_AUDIENCE(FolderPopulation, i) i->folderPopulationFinished(); } +}; - /// Forwards internal folder population notifications to the public audience. - struct PopulationNotifier : DENG2_OBSERVES(TaskPool, Done) - { - PopulationNotifier() { - populateTasks.audienceForDone() += this; - } - void taskPoolDone(TaskPool &) { - DENG2_FOR_AUDIENCE(FolderPopulation, i) i->folderPopulationFinished(); - } - }; - static PopulationNotifier populationNotifier; -} +static PopulationNotifier populationNotifier; + +} // namespace internal DENG2_PIMPL(Folder) { @@ -106,7 +110,7 @@ Folder::Folder(String const &name) : File(name), d(new Impl(this)) { - setStatus(Status::FOLDER); + setStatus(Type::Folder); objectNamespace().addSuperRecord(ScriptSystem::builtInClass(QStringLiteral("Folder"))); } @@ -207,6 +211,8 @@ void Folder::populate(PopulationBehaviors behavior) { + fileSystem().changeBusyLevel(+1); + LOG_AS("Folder"); { DENG2_GUARD(this); @@ -262,8 +268,7 @@ } } - auto populationTask = [this, behavior] () - { + auto populationTask = [this, behavior]() { Feed::PopulatedFiles newFiles; // Populate with new/updated ones. @@ -277,13 +282,14 @@ DENG2_GUARD(this); for (File *i : newFiles) { - if (!i) continue; - - std::unique_ptr file(i); - if (!d->contents.contains(i->name().toLower())) + if (i) { - d->add(file.release()); - fileSystem().index(*i); + std::unique_ptr file(i); + if (!d->contents.contains(i->name().toLower())) + { + d->add(file.release()); + fileSystem().index(*i); + } } } newFiles.clear(); @@ -294,25 +300,41 @@ // Call populate on subfolders. for (Folder *folder : d->subfolders()) { - folder->populate(behavior); + folder->populate(behavior | PopulateCalledRecursively); } } + + fileSystem().changeBusyLevel(-1); }; - if (behavior & PopulateAsync) + if (internal::enableBackgroundPopulation) { - internal::populateTasks.start(populationTask, TaskPool::MediumPriority); + if (behavior & PopulateAsync) + { + internal::populateTasks.start(populationTask, TaskPool::MediumPriority); + } + else + { + populationTask(); + } } else { + // Only synchronous population is enabled. populationTask(); + + // Each population gets an individual notification since they're done synchronously. + // However, only notify once a full hierarchy of populations has finished. + if (!(behavior & PopulateCalledRecursively)) + { + internal::populationNotifier.notify(); + } } } Folder::Contents Folder::contents() const { DENG2_GUARD(this); - return d->contents; } @@ -402,6 +424,23 @@ d->destroy(removePath, &locate(removePath)); } +bool Folder::tryDestroyFile(String const &removePath) +{ + try + { + if (has(removePath)) + { + destroyFile(removePath); + return true; + } + } + catch (Error const &) + { + // This shouldn't happen. + } + return false; +} + void Folder::destroyAllFiles() { DENG2_GUARD(this); @@ -490,9 +529,46 @@ return nullptr; } -void Folder::waitForPopulation() +Folder &Folder::root() +{ + return FS::get().root(); +} + +void Folder::waitForPopulation(WaitBehavior waitBehavior) +{ + if (waitBehavior == OnlyInBackground && App::inMainThread()) + { + DENG2_ASSERT(!App::inMainThread()); + throw Error("Folder::waitForPopulation", "Not allowed to block the main thread"); + } + Time startedAt; + { + internal::populateTasks.waitForDone(); + } + const auto elapsed = startedAt.since(); + if (elapsed > .01) + { + LOG_MSG("Waited for %.3f seconds for file system to be ready") << elapsed; + } +} + +AsyncTask *Folder::afterPopulation(std::function func) { - internal::populateTasks.waitForDone(); + if (!isPopulatingAsync()) + { + func(); + return nullptr; + } + + return async([] () + { + waitForPopulation(); + return 0; + }, + [func] (int) + { + func(); + }); } bool Folder::isPopulatingAsync() @@ -500,6 +576,15 @@ return !internal::populateTasks.isDone(); } +void Folder::checkDefaultSettings() +{ + String mtEnabled; + if (App::app().unixInfo().defaults("fs:multithreaded", mtEnabled)) + { + internal::enableBackgroundPopulation = !ScriptedInfo::isFalse(mtEnabled); + } +} + filesys::Node const *Folder::tryFollowPath(PathRef const &path) const { // Absolute paths refer to the file system root. @@ -573,7 +658,8 @@ String Folder::contentsAsText() const { QList files; - forContents([&files] (String, File &f) { + forContents([&files] (String, File &f) + { files << &f; return LoopContinue; }); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/libraryfile.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/libraryfile.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/libraryfile.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/libraryfile.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -20,26 +20,41 @@ #include "de/LibraryFile" #include "de/Library" #include "de/NativeFile" +#include "de/NativePath" #include "de/LogBuffer" #include using namespace de; +DENG2_PIMPL_NOREF(LibraryFile) +{ + Library *library = nullptr; + NativePath nativePath; +}; + LibraryFile::LibraryFile(File *source) - : File(source->name()), _library(0) + : File(source->name()) + , d(new Impl) { DENG2_ASSERT(source != 0); setSource(source); // takes ownership } +LibraryFile::LibraryFile(NativePath const &nativePath) + : File(nativePath.fileName()) + , d(new Impl) +{ + d->nativePath = nativePath; +} + LibraryFile::~LibraryFile() { DENG2_FOR_AUDIENCE2(Deletion, i) i->fileBeingDeleted(*this); audienceForDeletion().clear(); deindex(); - delete _library; + delete d->library; } String LibraryFile::describe() const @@ -49,14 +64,26 @@ return desc; } +bool LibraryFile::loaded() const +{ + return d->library != 0; +} + Library &LibraryFile::library() { - if (_library) + if (d->library) { - return *_library; + return *d->library; } - /// @todo A method for File for making a NativeFile out of any File. + if (!d->nativePath.isEmpty()) + { + d->library = new Library(d->nativePath); + } + else + { + /// @todo A mechanism to make a NativeFile out of any File via caching? + NativeFile *native = maybeAs(source()); if (!native) { @@ -64,15 +91,15 @@ /// from native files. Other kinds of files would require a temporary native file. throw UnsupportedSourceError("LibraryFile::library", source()->description() + ": can only load from NativeFile"); + } + d->library = new Library(native->nativePath()); } - - _library = new Library(native->nativePath()); - return *_library; + return *d->library; } Library const &LibraryFile::library() const { - if (_library) return *_library; + if (d->library) return *d->library; /// @throw NotLoadedError Library is presently not loaded. throw NotLoadedError("LibraryFile::library", "Library is not loaded: " + description()); @@ -80,10 +107,10 @@ void LibraryFile::clear() { - if (_library) + if (d->library) { - delete _library; - _library = 0; + delete d->library; + d->library = nullptr; } } @@ -95,35 +122,42 @@ bool LibraryFile::recognize(File const &file) { -#ifdef MACOSX - // On macOS, plugins are in the .bundle format. The LibraryFile will point - // to the actual binary inside the bundle. Libraries must be loaded from - // native files. - if (NativeFile const *native = maybeAs(file)) - { - // Check if this in the executable folder with a matching bundle name. - if (native->nativePath().fileNamePath().toString().endsWith( - file.name() + ".bundle/Contents/MacOS")) + #if defined (DENG_APPLE) + { + // On macOS/iOS, plugins are in the .bundle format. The LibraryFile will point + // to the actual binary inside the bundle. Libraries must be loaded from + // native files. + if (NativeFile const *native = maybeAs(file)) { - // (name).bundle/Contents/MacOS/(name) - return true; + // Check if this in the executable folder with a matching bundle name. + if (native->nativePath().fileNamePath().toString() + .endsWith(file.name() + ".bundle/Contents/MacOS")) + { + return true; + } } } -#else + #else // not Apple + { // Check the extension first. if (QLibrary::isLibrary(file.name())) { #if defined(UNIX) + { // Only actual .so files should be considered. if (!file.name().endsWith(".so")) // just checks the file name { return false; } + } #endif + // Looks like a library. return true; } + } #endif + return false; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/linkfile.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/linkfile.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/linkfile.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/linkfile.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -84,6 +84,13 @@ d->target.reset(&file); } +void LinkFile::setTarget(File const *fileOrNull) +{ + DENG2_GUARD(this); + + d->target.reset(fileOrNull); +} + bool LinkFile::isBroken() const { return &target() == this; @@ -101,6 +108,19 @@ return "broken link"; } +IIStream const &LinkFile::operator >> (IByteArray &bytes) const +{ + if (!isBroken()) + { + target() >> bytes; + return *this; + } + else + { + return File::operator >> (bytes); + } +} + filesys::Node const *LinkFile::tryFollowPath(PathRef const &path) const { if (Folder const *folder = targetFolder()) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/nativepath.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/nativepath.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/nativepath.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/nativepath.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -295,18 +295,34 @@ NativePath parentPath = nativePath.fileNamePath(); if (!parentPath.isEmpty() && !exists(parentPath)) { - createPath(parentPath); + parentPath.create(); } QDir::current().mkdir(nativePath); - if (!exists(nativePath)) + if (!nativePath.exists()) { /// @throw CreateDirError Failed to create directory @a nativePath. throw CreateDirError("NativePath::createPath", "Could not create: " + nativePath); } } +bool NativePath::destroyPath(const NativePath &nativePath) +{ + if (!nativePath.isEmpty()) + { + if (nativePath.isDirectory()) + { + return QDir::current().rmdir(nativePath); + } + else + { + return QDir::current().remove(nativePath); + } + } + return true; +} + QChar NativePath::separator() { return DIR_SEPARATOR; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/package.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/package.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/package.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/package.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -40,11 +40,13 @@ String const Package::VAR_TITLE ("title"); String const Package::VAR_VERSION ("version"); +static String const PACKAGE_VERSION ("package.version"); static String const PACKAGE_ORDER ("package.__order__"); static String const PACKAGE_IMPORT_PATH("package.importPath"); static String const PACKAGE_REQUIRES ("package.requires"); static String const PACKAGE_RECOMMENDS ("package.recommends"); static String const PACKAGE_EXTRAS ("package.extras"); +static String const PACKAGE_PATH ("package.path"); static String const PACKAGE_TAGS ("package.tags"); static String const VAR_ID ("ID"); @@ -68,9 +70,8 @@ } DENG2_PIMPL(Package) -, DENG2_OBSERVES(File, Deletion) { - File const *file; + SafePtr file; Version version; // version of the loaded package Impl(Public *i, File const *f) @@ -79,8 +80,6 @@ { if (file) { - file->audienceForDeletion() += this; - // Check the file name first, then metadata. version = split(versionedIdentifierForFile(*file)).second; if (!version.isValid()) @@ -90,16 +89,11 @@ } } - void fileBeingDeleted(File const &) - { - file = 0; - } - void verifyFile() const { if (!file) { - throw SourceError("Package::verify", "Package's source file missing"); + throw SourceError("Package::verifyFile", "Package's source file missing"); } } @@ -143,19 +137,28 @@ File const &Package::sourceFile() const { - return App::rootFolder().locate(objectNamespace().gets("package.path")); + return FS::locate(objectNamespace().gets(PACKAGE_PATH)); +} + +bool Package::sourceFileExists() const +{ + return d->file && FS::tryLocate(objectNamespace().gets(PACKAGE_PATH)); } Folder const &Package::root() const { d->verifyFile(); - return expectedAs(d->file); + if (const Folder *f = maybeAs(&d->file->target())) + { + return *f; + } + return *sourceFile().parent(); } Record &Package::objectNamespace() { d->verifyFile(); - return const_cast(d->file)->objectNamespace(); + return const_cast(d->file.get())->objectNamespace(); } Record const &Package::objectNamespace() const @@ -236,7 +239,8 @@ if (Folder *folder = maybeAs(packageFile)) { - File *initializerScript = folder->tryLocateFile(QStringLiteral("__init__.de")); + File *initializerScript = folder->tryLocateFile(QStringLiteral("__init__.ds")); + if (!initializerScript) initializerScript = folder->tryLocateFile(QStringLiteral("__init__.de")); // old extension File *metadataInfo = folder->tryLocateFile(QStringLiteral("Info.dei")); if (!metadataInfo) metadataInfo = folder->tryLocateFile(QStringLiteral("Info")); // alternate name Time parsedAt = Time::invalidTime(); @@ -455,6 +459,12 @@ String Package::identifierForFile(File const &file) { + // The ID may be specified in the metadata. + if (auto const *pkgId = file.objectNamespace().tryFind(VAR_PACKAGE_ID)) + { + return pkgId->value().asText(); + } + // Form the prefix if there are enclosing packs as parents. String prefix; Folder const *parent = file.parent(); @@ -475,6 +485,11 @@ { return String("%1_%2").arg(id).arg(id_ver.second.fullNumber()); } + // The version may be specified in metadata. + if (auto const *pkgVer = file.objectNamespace().tryFind(PACKAGE_VERSION)) + { + return String("%1_%2").arg(id).arg(Version(pkgVer->value().asText()).fullNumber()); + } return id; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/packagefeed.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/packagefeed.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/packagefeed.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/packagefeed.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,12 +24,16 @@ namespace de { +static String const VAR_LINK_PACKAGE_ID("link.package"); + DENG2_PIMPL(PackageFeed) { PackageLoader &loader; + LinkMode linkMode; + Filter filter; - Impl(Public *i, PackageLoader &ldr) - : Base(i), loader(ldr) + Impl(Public *i, PackageLoader &ldr, LinkMode lm) + : Base(i), loader(ldr), linkMode(lm) {} File *linkToPackage(Package &pkg, String const &linkName, Folder const &folder) @@ -38,12 +42,27 @@ if (folder.has(linkName)) return nullptr; // Already there, keep the existing link. + // Packages can be optionally filtered from the feed. + if (filter && !filter(pkg)) return nullptr; + // Create a link to the loaded package's file. - LinkFile *link = LinkFile::newLinkToFile(pkg.file(), linkName); + String name; + if (linkMode == LinkIdentifier) + { + name = linkName; + } + else + { + name = Package::versionedIdentifierForFile(pkg.file()); + } + LinkFile *link = LinkFile::newLinkToFile(pkg.file(), name); // We will decide on pruning this. link->setOriginFeed(thisPublic); + // Identifier also in metadata. + link->objectNamespace().addText(VAR_LINK_PACKAGE_ID, pkg.identifier()); + return link; } @@ -72,9 +91,15 @@ } }; -PackageFeed::PackageFeed(PackageLoader &loader) : d(new Impl(this, loader)) +PackageFeed::PackageFeed(PackageLoader &loader, LinkMode linkMode) + : d(new Impl(this, loader, linkMode)) {} +void PackageFeed::setFilter(Filter filter) +{ + d->filter = filter; +} + PackageLoader &PackageFeed::loader() { return d->loader; @@ -94,13 +119,20 @@ { if (LinkFile const *link = maybeAs(file)) { - if (Folder const *pkg = maybeAs(link->target())) + // Links to unloaded packages should be pruned. + if (!d->loader.isLoaded(link->objectNamespace().gets(VAR_LINK_PACKAGE_ID))) + return true; + + //if (Folder const *pkg = maybeAs(link->target())) { // Links to unloaded packages should be pruned. - if (!d->loader.isLoaded(*pkg)) return true; + //if (!d->loader.isLoaded(*pkg)) return true; + +// qDebug() << "Link:" << link->description() << link->status().modifiedAt.asText(); +// qDebug() << " tgt:" << link->target().description() << link->target().status().modifiedAt.asText(); // Package has been modified, should be pruned. - if (link->status() != pkg->status()) return true; + if (link->status() != link->target().status()) return true; } } return false; // Don't prune. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/packageloader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/packageloader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/packageloader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/packageloader.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -32,13 +32,14 @@ #include "de/Version" #include -#include +#include namespace de { static String const VAR_PACKAGE_VERSION("package.version"); DENG2_PIMPL(PackageLoader) +, DENG2_OBSERVES(File, Deletion) // loaded package source file is deleted? { LoadedPackages loaded; ///< Identifiers are unversioned; only one version can be loaded at a time. int loadCounter; @@ -59,10 +60,21 @@ */ Package *tryFindLoaded(File const &file) const { + #if 0 + { + qDebug() << "tryFindLoaded:" << Package::identifierForFile(file) << file.description(); + for (auto i = loaded.begin(); i != loaded.end(); ++i) + { + qDebug() << " currently loaded:" << i.key() << "file:" << i.value()->file().path() << "source:" << i.value()->sourceFile().path(); + } + } + #endif + LoadedPackages::const_iterator found = loaded.constFind(Package::identifierForFile(file)); if (found != loaded.constEnd()) { - if (&found.value()->file() == &file) + auto const &pkg = *found.value(); + if (&pkg.file() == &file || &pkg.sourceFile() == &file) { return found.value(); } @@ -165,9 +177,21 @@ } // Each must have a version specified. - DENG2_FOR_EACH_CONST(FS::FoundFiles, i, found) { - checkPackage(**i); + FS::FoundFiles checked; + DENG2_FOR_EACH_CONST(FS::FoundFiles, i, found) + { + try + { + checkPackage(**i); + checked.push_back(*i); + } + catch (const Error &) + { + // Packages with errors cannot be selected. + } + } + found = std::move(checked); } // If the identifier includes a version, only accept that specific version. @@ -228,6 +252,7 @@ loaded.insert(packageId, pkg); pkg->setOrder(loadCounter++); pkg->didLoad(); + source.audienceForDeletion() += this; return *pkg; } @@ -239,12 +264,23 @@ Package *pkg = found.value(); pkg->aboutToUnload(); + if (pkg->sourceFileExists()) + { + pkg->sourceFile().audienceForDeletion() -= this; + } delete pkg; - loaded.remove(identifier); return true; } + void fileBeingDeleted(const File &file) override + { + const String pkgId = Package::identifierForFile(file); + LOG_RES_WARNING("Unloading package \"%s\": source file has been modified or deleted") + << pkgId; + unload(pkgId); + } + void listPackagesInIndex(FileIndex const &index, StringList &list) { foreach (File *indexedFile, index.files()) @@ -288,6 +324,10 @@ LOG_RES_WARNING("\"%s\": Package has a syntax error: %s") << fileName << er.asText(); } + catch (const Error &er) + { + LOG_RES_WARNING("\"%s\": %s") << fileName << er.asText(); + } /// @todo Store the errors so that the UI can show a list of /// problematic packages. -jk @@ -313,16 +353,25 @@ DictionaryValue const &selPkgs = Config::get("fs.selectedPackages") .value(); - Record const &meta = Package::metadata(packageFile); + const Record &meta = Package::metadata(packageFile); + const String idVer = Package::versionedIdentifierForFile(packageFile); - // Helper function to determine if a particular pacakge is marked for loading. - auto isPackageSelected = [meta, &selPkgs] (TextValue const &id, bool byDefault) -> bool { - TextValue const key(meta.gets("ID")); + // Helper function to determine if a particular package is marked for loading. + auto isPackageSelected = [&idVer, &selPkgs] (TextValue const &id, bool byDefault) -> bool { + TextValue const key(idVer); if (selPkgs.contains(key)) { auto const &sels = selPkgs.element(key).as(); if (sels.contains(id)) { return sels.element(id).isTrue(); } + else + { + //LOG_MSG("'%s' not in selectedPackages of '%s'") << id << idVer; + } + } + else + { + //LOG_MSG("'%s' not in fs.selectedPackages") << idVer; } return byDefault; }; @@ -517,7 +566,7 @@ Version const pkgVersion(meta.gets("version")); if (idType == Versioned && pkgVersion.isValid()) // nonzero { - ids << String("%1_%2").arg(meta.gets("ID")).arg(meta.gets("version")); + ids << String("%1_%2").arg(meta.gets("ID")).arg(pkgVersion.fullNumber()); } else { @@ -567,11 +616,11 @@ } } -void PackageLoader::loadFromCommandLine() +StringList PackageLoader::loadedFromCommandLine() const { + StringList pkgs; CommandLine &args = App::commandLine(); - - for (int p = 0; p < args.count(); ) + for (duint p = 0; p < duint(args.count()); ) { // Find all the -pkg options. if (!args.matches("-pkg", args.at(p))) @@ -579,13 +628,13 @@ ++p; continue; } - // Load all the specified packages (by identifier, not by path). - while (++p != args.count() && !args.isOption(p)) + while (++p != duint(args.count()) && !args.isOption(p)) { - load(args.at(p)); + pkgs << args.at(p); } } + return pkgs; } StringList PackageLoader::findAllPackages() const @@ -628,7 +677,7 @@ PackageLoader::IdentifierList::IdentifierList(String const &spaceSeparatedIds) { - static QRegExp anySpace("\\s"); + static const QRegularExpression anySpace("\\s"); for (auto const &qs : spaceSeparatedIds.split(anySpace, String::SkipEmptyParts)) { ids.append(qs); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/link.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/link.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/link.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/link.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,311 @@ +/** @file remote/link.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/filesys/Link" +#include "de/RemoteFeedRelay" +#include "de/FileSystem" + +#include +#include +#include +#include + +namespace de { +namespace filesys { + +DENG2_PIMPL(Link), public AsyncScope +{ + String localRootPath; + State state = Initializing; + String address; + QueryId nextQueryId = 1; + QList deferredQueries; + QHash pendingQueries; + + Impl(Public *i) : Base(i) + {} + + ~Impl() + { + cancelAllQueries(); + } + + void cancelAllQueries() + { + for (auto i = deferredQueries.begin(); i != deferredQueries.end(); ++i) + { + i->cancel(); + } + for (auto i = pendingQueries.begin(); i != pendingQueries.end(); ++i) + { + i.value().cancel(); + } + } + + /// Remove all invalid/cancelled queries. + void cleanup() + { + QMutableHashIterator iter(pendingQueries); + while (iter.hasNext()) + { + iter.next(); + if (!iter.value().isValid()) + { + iter.remove(); + } + } + } + + void sendQuery(Query query) + { + try + { + query.id = nextQueryId++; + if (state == Ready) + { + self().transmit(query); + pendingQueries.insert(query.id, query); + cleanup(); + } + else + { + deferredQueries.append(query); + } + } + catch (Error const &er) + { + LOG_NET_ERROR("Error sending file repository query: %s") + << er.asText(); + } + } + + void sendDeferredQueries() + { + foreach (Query const &query, deferredQueries) + { + if (query.isValid()) + { + pendingQueries.insert(query.id, query); + self().transmit(query); + } + } + deferredQueries.clear(); + } + + void notifyStatus(RemoteFeedRelay::Status status) + { + using Relay = RemoteFeedRelay; + DENG2_FOR_EACH_OBSERVER(Relay::StatusAudience, i, + Relay::get().audienceForStatus()) + { + i->remoteRepositoryStatusChanged(address, status); + } + } +}; + +Link::Link(String const &address) + : d(new Impl(this)) +{ + d->address = address; +} + +Link::~Link() +{ + d->cancelAllQueries(); + + if (d->state != Deinitialized) + { + // Normally, the local folder will be deleted when the link is disconnected. + if (auto *folder = FS::tryLocate(d->localRootPath)) + { + delete folder; + } + } +} + +void Link::setLocalRoot(String const &rootPath) +{ + d->localRootPath = rootPath; + // Create the folder right away. + localRoot(); +} + +Folder &Link::localRoot() const +{ + return FS::get().makeFolder(d->localRootPath, FS::DontInheritFeeds); +} + +String Link::address() const +{ + return d->address; +} + +Link::State Link::state() const +{ + return d->state; +} + +StringList Link::categoryTags() const +{ + return StringList(); +} + +void Link::wasConnected() +{ + DENG2_ASSERT_IN_MAIN_THREAD(); + d->state = Ready; + d->sendDeferredQueries(); + d->notifyStatus(RemoteFeedRelay::Connected); +} + +void Link::wasDisconnected() +{ + DENG2_ASSERT_IN_MAIN_THREAD(); + d->state = Deinitialized; + d->cancelAllQueries(); + d->cleanup(); + d->notifyStatus(RemoteFeedRelay::Disconnected); + + // Remove the local root folder. + if (Folder *root = FS::tryLocate(d->localRootPath)) + { + trash(root); + } +} + +void Link::handleError(QString errorMessage) +{ + LOG_NET_ERROR("Error accessing remote file repository \"%s\": %s " DENG2_CHAR_MDASH + " files from repository may not be available") + << d->address + << errorMessage; +} + +AsyncScope &Link::scope() +{ + return *d; +} + +void Link::cancelAllQueries() +{ + d->cancelAllQueries(); +} + +void Link::cleanupQueries() +{ + d->cleanup(); +} + +Query *Link::findQuery(QueryId id) +{ + auto found = d->pendingQueries.find(id); + if (found != d->pendingQueries.end()) + { + return &found.value(); + } + return nullptr; +} + +QueryId Link::sendQuery(Query query) +{ + try + { + query.id = d->nextQueryId++; + if (d->state == Ready) + { + d->pendingQueries.insert(query.id, query); + transmit(query); + d->cleanup(); + } + else + { + d->deferredQueries.append(query); + } + return query.id; + } + catch (Error const &er) + { + LOG_NET_ERROR("Error sending file repository query: %s") << er.asText(); + return 0; + } +} + +File *Link::populateRemotePath(String const &, RepositoryPath const &path) const +{ + // By default we assume the remote files are all populated while connecting. + return FS::tryLocate(path.localPath); +} + +//void Link::packagePathsReceived(QueryId id, PackagePaths const &remotePaths) +//{ +// if (auto *query = findQuery(id)) +// { +// if (query->remotePaths) +// { +// query->remotePaths->call(id, remotePaths); +// } +// d->pendingQueries.remove(id); +// } +//} + +void Link::metadataReceived(QueryId id, DictionaryValue const &metadata) +{ + if (auto *query = findQuery(id)) + { + if (query->fileMetadata) + { + query->fileMetadata->call(metadata); + } + d->pendingQueries.remove(id); + } +} + +void Link::chunkReceived(QueryId id, duint64 startOffset, Block const &chunk, duint64 fileSize) +{ + if (auto *query = findQuery(id)) + { + // Get rid of cancelled queries. + if (!query->isValid()) + { + d->pendingQueries.remove(id); + return; + } + + // Before the first chunk, notify about the total size. + if (!query->fileSize) + { + query->fileContents->call(0, Block(), fileSize); + } + + query->fileSize = fileSize; + query->receivedBytes += chunk.size(); + + // Notify about progress and provide the data chunk to the requestor. + query->fileContents->call(startOffset, chunk, + fileSize - query->receivedBytes); + + if (fileSize == query->receivedBytes) + { + // Transfer complete. + d->pendingQueries.remove(id); + } + } +} + +} // namespace filesys +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/nativelink.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/nativelink.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/nativelink.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/nativelink.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,168 @@ +/** @file remote/nativelink.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/filesys/NativeLink" + +#include "de/App" +#include "de/FileSystem" +#include "de/Loop" +#include "de/Message" +#include "de/RemoteFeed" +#include "de/RemoteFeedProtocol" +#include "de/Socket" + +namespace de { +namespace filesys { + +String const NativeLink::URL_SCHEME("doomsday:"); + +static String const PATH_SERVER_REPOSITORY_ROOT("/sys/server/public"); // serverside folder + +DENG2_PIMPL(NativeLink) +{ + RemoteFeedProtocol protocol; + Socket socket; + + Impl(Public *i) : Base(i) {} + + void receiveMessages() + { + while (socket.hasIncoming()) + { + try + { + DENG2_ASSERT_IN_MAIN_THREAD(); + + std::unique_ptr response(socket.receive()); + std::unique_ptr packet (protocol.interpret(*response)); + + if (!packet) continue; + + switch (protocol.recognize(*packet)) + { + case RemoteFeedProtocol::Metadata: { + auto const &md = packet->as(); + self().metadataReceived(md.id(), md.metadata()); + break; } + + case RemoteFeedProtocol::FileContents: { + auto const &fc = packet->as(); + self().chunkReceived(fc.id(), fc.startOffset(), fc.data(), fc.fileSize()); + break; } + + default: + break; + } + } + catch (Error const &er) + { + LOG_NET_ERROR("Error when handling remote feed response: %s") + << er.asText(); + } + } + self().cleanupQueries(); + } +}; + +NativeLink::NativeLink(String const &address) + : Link(address) + , d(new Impl(this)) +{ + DENG2_ASSERT(address.startsWith(URL_SCHEME)); + + QObject::connect(&d->socket, &Socket::connected, [this] () { wasConnected(); }); + QObject::connect(&d->socket, &Socket::disconnected, [this] () { wasDisconnected(); }); + QObject::connect(&d->socket, &Socket::error, [this] (QString msg) { handleError(msg); }); + + QObject::connect(&d->socket, &Socket::messagesReady, [this] () { d->receiveMessages(); }); + + d->socket.open(address.mid(URL_SCHEME.size())); +} + +Link *NativeLink::construct(String const &address) +{ + if (address.startsWith(URL_SCHEME)) + { + return new NativeLink(address); + } + return nullptr; +} + +void NativeLink::setLocalRoot(String const &rootPath) +{ + Link::setLocalRoot(rootPath); + + auto &root = localRoot(); + root.attach(new RemoteFeed(address(), PATH_SERVER_REPOSITORY_ROOT)); + root.populate(Folder::PopulateAsyncFullTree); +} + +PackagePaths NativeLink::locatePackages(StringList const &packageIds) const +{ + PackagePaths remotePaths; + foreach (String pkg, packageIds) + { + // Available packages have been populated as remote files. + if (File *rem = FS::tryLocate("/remote/server"/pkg)) + { + // Remote path not needed because local folders are fully populated with + // remote files. + remotePaths.insert(pkg, RepositoryPath(*this, rem->path(), "")); + } + } + return remotePaths; +} + +LoopResult filesys::NativeLink::forPackageIds(std::function func) const +{ + return FS::locate("/remote/server").forContents([&func] (String name, File &) -> LoopResult + { + if (auto result = func(name)) + { + return result; + } + return LoopContinue; + }); +} + +void NativeLink::wasConnected() +{ + d->socket << ByteRefArray("RemoteFeed", 10); + Link::wasConnected(); +} + +void NativeLink::transmit(Query const &query) +{ + DENG2_ASSERT(query.isValid()); + + RemoteFeedQueryPacket packet; + packet.setId(query.id); + packet.setPath(query.path); + if (query.fileMetadata) + { + packet.setQuery(RemoteFeedQueryPacket::ListFiles); + } + else if (query.fileContents) + { + packet.setQuery(RemoteFeedQueryPacket::FileContents); + } + d->socket.sendPacket(packet); +} + +} // namespace filesys +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/query.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/query.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/query.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/query.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,46 @@ +/** @file remote/query.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/filesys/Query" + +namespace de { +namespace filesys { + +Query::Query(Request req, String path) + : path(path), fileMetadata(req) +{} + +Query::Query(Request req, String path) + : path(path), fileContents(req) +{} + +bool Query::isValid() const +{ + if (fileMetadata) return fileMetadata->isValid(); + if (fileContents) return fileContents->isValid(); + return false; +} + +void Query::cancel() +{ + if (fileMetadata) fileMetadata->cancel(); + if (fileContents) fileContents->cancel(); +} + +} // namespace filesys +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeed.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeed.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeed.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeed.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,162 @@ +/** @file remotefeed.cpp Feed for remote files. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/RemoteFeed" + +#include "de/BlockValue" +#include "de/Folder" +#include "de/Path" +#include "de/RecordValue" +#include "de/RemoteFeedProtocol" +#include "de/RemoteFeedRelay" +#include "de/RemoteFile" +#include "de/Socket" +#include "de/TimeValue" +#include "de/Waitable" +#include "de/charsymbols.h" + +namespace de { + +static TimeSpan const POPULATE_TIMEOUT = 15.0; + +DENG2_PIMPL(RemoteFeed) +, DENG2_OBSERVES(filesys::RemoteFeedRelay, Status) +{ + String repository; + Path remotePath; + std::unique_ptr fileMetadata; + SafePtr pendingPopulation; + + Impl(Public *i) : Base(i) + {} + + PopulatedFiles populate() + { + PopulatedFiles populated; + for (auto i : fileMetadata->elements()) + { + String const path = remotePath / i.first.value->asText(); + + if (RecordValue const *meta = maybeAs(i.second)) + { + Record const &md = *meta->record(); + + File::Type const fileType = RemoteFeedMetadataPacket::toFileType(md.geti("type", 0)); + dsize const fileSize = md.getui("size", 0); + Time const modTime = md.getAs("modifiedAt").time(); + + File *file = nullptr; + if (fileType == File::Type::File) + { + file = new RemoteFile(path.fileName(), path, md.getAs("metaId").block()); + } + else + { + Folder *subfolder = new Folder(path.fileName()); + // Make a subfeed of this feed. + subfolder->attach(new RemoteFeed(*thisPublic, path)); + file = subfolder; + } + if (md.has("package")) + { + file->objectNamespace().add("package", new Record(md.subrecord("package"))); + } + file->setStatus(File::Status(fileType, fileSize, modTime)); + file->setOriginFeed(thisPublic); + + populated << file; + } + } + return populated; + } + + void remoteRepositoryStatusChanged(String const &address, filesys::RemoteFeedRelay::Status status) override + { + if (repository == address && status == filesys::RemoteFeedRelay::Connected) + { + if (pendingPopulation) + { + // There is a pending population request, let's do it now. + pendingPopulation->populate(Folder::PopulateAsyncFullTree); + pendingPopulation.reset(); + } + filesys::RemoteFeedRelay::get().audienceForStatus() -= this; + } + } +}; + +RemoteFeed::RemoteFeed(String const &repository, String const &remotePath) + : d(new Impl(this)) +{ + d->repository = repository; + d->remotePath = remotePath; +} + +RemoteFeed::RemoteFeed(RemoteFeed const &parentFeed, String const &remotePath) + : d(new Impl(this)) +{ + d->repository = parentFeed.d->repository; + d->remotePath = remotePath; +} + +String RemoteFeed::repository() const +{ + return d->repository; +} + +String RemoteFeed::description() const +{ + return String("remote repository \"%1\"") + .arg(d->repository / d->remotePath); +} + +Feed::PopulatedFiles RemoteFeed::populate(Folder const &folder) +{ + LOG_AS("RemoteFeed"); + auto &relay = filesys::RemoteFeedRelay::get(); + PopulatedFiles files; + if (!relay.isConnected(d->repository)) + { + //qDebug() << "Population deferred:" << folder.path(); + d->pendingPopulation.reset(const_cast(&folder)); + relay.audienceForStatus() += d; + return files; + } + auto request = relay.fetchFileList + (d->repository, + d->remotePath, + [this, /*&folder,*/ &files] + (DictionaryValue const &fileMetadata) + { + //qDebug() << "Received file listing of" << d->remotePath; + //qDebug() << fileList.asText(); + + // Make a copy of the listed metadata. + d->fileMetadata.reset(static_cast(fileMetadata.duplicate())); + files = d->populate(); + }); + request->wait(POPULATE_TIMEOUT); + return files; +} + +bool RemoteFeed::prune(File &) const +{ + return false; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedprotocol.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedprotocol.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedprotocol.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedprotocol.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,236 @@ +/** @file remotefeedprotocol.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/RemoteFeedProtocol" +#include "de/BlockValue" +#include "de/TextValue" +#include "de/RecordValue" +#include "de/Folder" + +namespace de { + +// RemoteFeedQueryPacket ---------------------------------------------------------------- + +static Packet::Type const QUERY_PACKET_TYPE = Packet::typeFromString("RFQu"); + +RemoteFeedQueryPacket::RemoteFeedQueryPacket() + : IdentifiedPacket(QUERY_PACKET_TYPE) +{} + +void RemoteFeedQueryPacket::setQuery(Query query) +{ + _query = query; +} + +void RemoteFeedQueryPacket::setPath(String const &path) +{ + _path = path; +} + +RemoteFeedQueryPacket::Query RemoteFeedQueryPacket::query() const +{ + return _query; +} + +String RemoteFeedQueryPacket::path() const +{ + return _path; +} + +void RemoteFeedQueryPacket::operator >> (Writer &to) const +{ + IdentifiedPacket::operator >> (to); + to << duint8(_query) << _path; +} + +void RemoteFeedQueryPacket::operator << (Reader &from) +{ + IdentifiedPacket::operator << (from); + from.readAs(_query) >> _path; +} + +Packet *RemoteFeedQueryPacket::fromBlock(Block const &block) +{ + return constructFromBlock(block, QUERY_PACKET_TYPE); +} + +// RemoteFeedMetadataPacket ------------------------------------------------------------- + +static Packet::Type const METADATA_PACKET_TYPE = Packet::typeFromString("RFMt"); + +RemoteFeedMetadataPacket::RemoteFeedMetadataPacket() + : IdentifiedPacket(METADATA_PACKET_TYPE) +{} + +void RemoteFeedMetadataPacket::addFile(File const &file, String const &prefix) +{ + auto const &ns = file.target().objectNamespace(); + auto const status = file.target().status(); + + std::unique_ptr fileMeta(new Record); + + fileMeta->addTime ("modifiedAt", status.modifiedAt); + fileMeta->addNumber("type", status.type() == File::Type::File? 0 : 1); + if (status.type() == File::Type::Folder) + { + fileMeta->addNumber("size", file.target().as().contents().size()); + } + else + { + fileMeta->addNumber("size", status.size); + fileMeta->addBlock ("metaId").value().block() = file.metaId(); + } + if (ns.hasSubrecord("package")) + { + fileMeta->add("package", new Record(ns.getr("package").dereference(), + Record::IgnoreDoubleUnderscoreMembers)); + } +// if (ns.hasSubrecord("link")) +// { +// fileMeta->add("link", new Record(ns.getr("link").dereference())); +// } + + _metadata.add(new TextValue(prefix / file.name()), + new RecordValue(fileMeta.release(), RecordValue::OwnsRecord)); +} + +void RemoteFeedMetadataPacket::addFolder(Folder const &folder, String prefix) +{ + folder.forContents([this, prefix] (String, File &file) + { + // Each file's metadata is included. + addFile(file, prefix); + return LoopContinue; + }); +} + +DictionaryValue const &RemoteFeedMetadataPacket::metadata() const +{ + return _metadata; +} + +File::Type RemoteFeedMetadataPacket::toFileType(int value) +{ + return (value == 0? File::Type::File : File::Type::Folder); +} + +void RemoteFeedMetadataPacket::operator >> (Writer &to) const +{ + IdentifiedPacket::operator >> (to); + to << _metadata; +} + +void RemoteFeedMetadataPacket::operator << (Reader &from) +{ + IdentifiedPacket::operator << (from); + from >> _metadata; +} + +Packet *RemoteFeedMetadataPacket::fromBlock(Block const &block) +{ + return constructFromBlock(block, METADATA_PACKET_TYPE); +} + +// RemoteFeedFileContentsPacket --------------------------------------------------------- + +static Packet::Type const FILE_CONTENTS_PACKET_TYPE = Packet::typeFromString("RFCo"); + +RemoteFeedFileContentsPacket::RemoteFeedFileContentsPacket() + : IdentifiedPacket(FILE_CONTENTS_PACKET_TYPE) + , _startOffset(0) +{} + +void RemoteFeedFileContentsPacket::setData(Block const &data) +{ + _data = data; +} + +void RemoteFeedFileContentsPacket::setStartOffset(dsize offset) +{ + _startOffset = offset; +} + +void RemoteFeedFileContentsPacket::setFileSize(dsize size) +{ + _fileSize = size; +} + +Block const &RemoteFeedFileContentsPacket::data() const +{ + return _data; +} + +dsize RemoteFeedFileContentsPacket::startOffset() const +{ + return _startOffset; +} + +dsize RemoteFeedFileContentsPacket::fileSize() const +{ + return _fileSize; +} + +void RemoteFeedFileContentsPacket::operator >> (Writer &to) const +{ + IdentifiedPacket::operator >> (to); + to << duint64(_fileSize) << duint64(_startOffset) << _data; +} + +void RemoteFeedFileContentsPacket::operator << (Reader &from) +{ + IdentifiedPacket::operator << (from); + from.readAs(_fileSize) + .readAs(_startOffset) + >> _data; +} + +Packet *RemoteFeedFileContentsPacket::fromBlock(Block const &block) +{ + return constructFromBlock(block, FILE_CONTENTS_PACKET_TYPE); +} + +// RemoteFeedProtocol ------------------------------------------------------------------- + +RemoteFeedProtocol::RemoteFeedProtocol() +{ + define(RemoteFeedQueryPacket::fromBlock); + define(RemoteFeedMetadataPacket::fromBlock); + define(RemoteFeedFileContentsPacket::fromBlock); +} + +RemoteFeedProtocol::PacketType RemoteFeedProtocol::recognize(Packet const &packet) +{ + if (packet.type() == QUERY_PACKET_TYPE) + { + DENG2_ASSERT(is(&packet)); + return Query; + } + if (packet.type() == METADATA_PACKET_TYPE) + { + DENG2_ASSERT(is(&packet)); + return Metadata; + } + if (packet.type() == FILE_CONTENTS_PACKET_TYPE) + { + DENG2_ASSERT(is(&packet)); + return FileContents; + } + return Unknown; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedrelay.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedrelay.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedrelay.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefeedrelay.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,203 @@ +/** @file remotefeedrelay.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/RemoteFeedRelay" + +#include "de/App" +#include "de/Async" +#include "de/Date" +#include "de/DictionaryValue" +#include "de/filesys/Link" +#include "de/filesys/NativeLink" +#include "de/Loop" +#include "de/Message" +#include "de/RemoteFeedProtocol" +#include "de/Version" +#include "de/charsymbols.h" + +#include +#include +#include +#include +#include + +#include + +namespace de { +namespace filesys { + +DENG2_PIMPL(RemoteFeedRelay) +{ + std::unique_ptr network; + QList linkConstructors; + QHash repositories; // owned + + Impl(Public *i) : Base(i) + { + network.reset(new QNetworkAccessManager); + + auto *cache = new QNetworkDiskCache; + String const dir = NativePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) + / "RemoteFiles"; + cache->setCacheDirectory(dir); + network->setCache(cache); + } + + ~Impl() + { + qDeleteAll(repositories.values()); + } + + DENG2_PIMPL_AUDIENCE(Status) +}; + +DENG2_AUDIENCE_METHOD(RemoteFeedRelay, Status) + +RemoteFeedRelay &RemoteFeedRelay::get() +{ + return App::remoteFeedRelay(); +} + +RemoteFeedRelay::RemoteFeedRelay() + : d(new Impl(this)) +{ + // Built-in constructors. + defineLink(NativeLink::construct); +} + +void RemoteFeedRelay::defineLink(filesys::Link::Constructor linkConstructor) +{ + d->linkConstructors.push_front(linkConstructor); +} + +void RemoteFeedRelay::addRepository(String const &address, + String const &localRootPath) +{ + for (auto constructor : d->linkConstructors) + { + if (auto *link = constructor(address)) + { + d->repositories.insert(address, link); + link->setLocalRoot(localRootPath); + return; + } + } +} + +void RemoteFeedRelay::removeRepository(String const &address) +{ + if (auto *repo = d->repositories.take(address)) + { + delete repo; + } +} + +Link *RemoteFeedRelay::repository(String const &address) const +{ + auto found = d->repositories.constFind(address); + if (found != d->repositories.constEnd()) + { + return found.value(); + } + return nullptr; +} + +StringList RemoteFeedRelay::repositories() const +{ + StringList repos; + foreach (String a, d->repositories.keys()) + { + repos << a; + } + return repos; +} + +bool RemoteFeedRelay::isConnected(String const &address) const +{ + if (auto *repo = repository(address)) + { + return repo->state() == Link::Ready; + } + return false; +} + +PackagePaths RemoteFeedRelay::locatePackages(StringList const &packageIds) const +{ + PackagePaths located; + foreach (auto *repo, d->repositories) + { + if (repo->state() == Link::Ready) + { + auto const paths = repo->locatePackages(packageIds); + for (auto i = paths.begin(); i != paths.end(); ++i) + { + if (!located.contains(i.key())) + { + located.insert(i.key(), i.value()); + } + } + } + } + return located; +} + +Request +RemoteFeedRelay::fetchFileList(String const &repository, String folderPath, FileMetadata metadataReceived) +{ + DENG2_ASSERT(d->repositories.contains(repository)); + + Waitable done; + Request request; + Loop::mainCall([&] () + { + // The repository sockets are handled in the main thread. + auto *repo = d->repositories[repository]; + request.reset(new Request::element_type(metadataReceived)); + repo->sendQuery(Query(request, folderPath)); + done.post(); + }); + done.wait(); + return request; +} + +Request +RemoteFeedRelay::fetchFileContents(String const &repository, String filePath, FileContents contentsReceived) +{ + DENG2_ASSERT(d->repositories.contains(repository)); + + Waitable done; + Request request; + Loop::mainCall([&] () + { + // The repository sockets are handled in the main thread. + auto *repo = d->repositories[repository]; + request.reset(new Request::element_type(contentsReceived)); + repo->sendQuery(Query(request, filePath)); + done.post(); + }); + done.wait(); + return request; +} + +QNetworkAccessManager &RemoteFeedRelay::network() +{ + return *d->network; +} + +} // namespace filesys +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefile.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefile.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/remotefile.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,277 @@ +/** @file remotefile.cpp Remote file. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/RemoteFile" + +#include "de/App" +#include "de/DirectoryFeed" +#include "de/FileSystem" +#include "de/RecordValue" +#include "de/RemoteFeedRelay" +#include "de/ScriptSystem" +#include "de/TextValue" +#include "de/TimeValue" + +namespace de { + +using namespace de::filesys; + +String const RemoteFile::CACHE_PATH = "/home/cache/remote"; + +DENG2_PIMPL(RemoteFile) +{ + String remotePath; + Block remoteMetaId; + String repositoryAddress; // If empty, use feed's repository. + Block buffer; + Request fetching; + + Impl(Public *i) : Base(i) {} + + ~Impl() + { + if (fetching) + { + fetching->cancel(); + } + } + + String cachePath() const + { + String const hex = remoteMetaId.asHexadecimalText(); + String path = CACHE_PATH / hex.right(1); + String original = self().objectNamespace().gets("package.path", remotePath); + return path / hex + "_" + original.fileName(); + } + + void findCachedFile(bool requireExists = true) + { + if (!self().isBroken()) return; + + if (self().state() == NotReady) + { + throw UnfetchedError("RemoteFile::operator >>", + self().description() + " not downloaded"); + } + if (self().isBroken()) + { + self().setTarget(FS::tryLocate(cachePath())); + } + if (requireExists && self().isBroken()) + { + throw InputError("RemoteFile::operator >>", + self().description() + " has no locally cached data"); + } + } + + void setTarget(File const &cachedFile) + { + self().setTarget(cachedFile); + + auto &ns = self().objectNamespace(); + if (ns.has("package.path")) + { + ns["package.path"] = self().target().path(); + } + } + + bool checkExistingCache() + { + if (File const *cached = FS::tryLocate(cachePath())) + { + if (cached->status() == self().status()) + { + // Seems to match (including part of the meta hash). + LOG_RES_MSG("Using local cached copy of %s") << cached->description(); + setTarget(*cached); + return true; + } + } + return false; + } + + String repository() const + { + if (repositoryAddress) + { + return repositoryAddress; + } + DENG2_ASSERT(is(self().originFeed())); + return self().originFeed()->as().repository(); + } +}; + +RemoteFile::RemoteFile(String const &name, String const &remotePath, Block const &remoteMetaId, + String const &repositoryAddress) + : LinkFile(name) + , d(new Impl(this)) +{ + objectNamespace().addSuperRecord(ScriptSystem::builtInClass(QStringLiteral("RemoteFile"))); + d->repositoryAddress = repositoryAddress; + d->remotePath = remotePath; + d->remoteMetaId = remoteMetaId; + + qDebug() << "RemoteFile remotePath:" << remotePath; + + setState(NotReady); +} + +void RemoteFile::download() +{ + if (state() != NotReady) return; + + setState(Recovering); + + if (d->checkExistingCache()) + { + DENG2_FOR_AUDIENCE(Download, i) + { + i->downloadProgress(*this, 0); + } + setState(Ready); + return; + } + + LOG_NET_MSG("Requesting download of \"%s\"") << name(); + + d->fetching = filesys::RemoteFeedRelay::get().fetchFileContents + (d->repository(), + d->remotePath, + [this] (duint64 startOffset, Block const &chunk, duint64 remainingBytes) + { + DENG2_ASSERT_IN_MAIN_THREAD(); + DENG2_FOR_AUDIENCE(Download, i) + { + i->downloadProgress(*this, remainingBytes); + } + + // Keep received data in a buffer. + if (d->buffer.size() < remainingBytes) + { + d->buffer.resize(remainingBytes); + } + + d->buffer.set(startOffset, chunk.data(), chunk.size()); + + // When fully transferred, the file can be cached locally and interpreted. + if (remainingBytes == 0) + { + LOG_NET_MSG("\"%s\" downloaded (%i bytes)") << name() << d->buffer.size(); + + d->fetching = nullptr; + + String const fn = d->cachePath(); + Folder &cacheFolder = FS::get().makeFolder(fn.fileNamePath()); + File &data = cacheFolder.replaceFile(fn); + data << d->buffer; + d->buffer.clear(); + data.flush(); + + // Override the last modified time. + { + auto st = data.status(); + st.modifiedAt = status().modifiedAt; + data.setStatus(st); + + // Remember this for later as well. + DirectoryFeed::setFileModifiedTime(data.correspondingNativePath(), + st.modifiedAt); + } + + setTarget(data.reinterpret()); + if (objectNamespace().has("package.path")) + { + objectNamespace()["package.path"] = target().path(); + } + + setState(Ready); + + // Now this RemoteFile can become the source of an interpreted file, + // which replaces the RemoteFile within the parent folder. + } + }); +} + +void RemoteFile::cancelDownload() +{ + if (d->fetching) + { + d->fetching->cancel(); + d->fetching = nullptr; + d->buffer.clear(); + setState(NotReady); + } +} + +void RemoteFile::deleteCache() +{ + setState(NotReady); + FS::get().root().tryDestroyFile(d->cachePath()); +} + +IIStream const &RemoteFile::operator >> (IByteArray &bytes) const +{ + if (state() != Ready) + { + throw UnfetchedError("RemoteFile::operator >>", + description() + " not downloaded"); + } + DENG2_ASSERT(!isBroken()); + return LinkFile::operator >> (bytes); +} + +String RemoteFile::describe() const +{ + if (isReady()) + { + return String("\"%1\"").arg(name()); + } + String targetDesc; + if (!isBroken()) + { + targetDesc = " cached in " + target().description(); + } + return String("remote file \"%1\" (%2)") + .arg(name()) + .arg( state() == NotReady ? "not ready" + : state() == Recovering ? "downloading" + : "ready") + + targetDesc; +} + +Block RemoteFile::metaId() const +{ + return d->remoteMetaId; +} + +Asset &RemoteFile::asset() +{ + return *this; +} + +Asset const &RemoteFile::asset() const +{ + return *this; +} + +dsize RemoteFile::downloadSize() const +{ + return size(); +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/webhostedlink.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/webhostedlink.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/remote/webhostedlink.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/remote/webhostedlink.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,219 @@ +/** @file + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/filesys/WebHostedLink" + +#include "de/Async" +#include "de/Folder" +#include "de/PathTree" +#include "de/RecordValue" +#include "de/RemoteFeedRelay" +#include "de/TextValue" + +#include +#include +#include + +namespace de { +namespace filesys { + +DENG2_PIMPL(WebHostedLink), public Lockable +{ + QSet pendingRequests; + std::shared_ptr fileTree; + + Impl(Public *i) : Base(i) + {} + + ~Impl() + {} + + Block metaIdForFileEntry(FileEntry const &entry) const + { + if (entry.isBranch()) return Block(); // not applicable + return md5Hash(self().address(), entry.path(), entry.size, entry.modTime); + } + + void handleFileListQueryAsync(Query query) + { + QueryId const id = query.id; + String const queryPath = query.path; + self().scope() += async([this, queryPath] () -> std::shared_ptr + { + DENG2_GUARD(this); + if (auto const *dir = fileTree->tryFind + (queryPath, FileTree::MatchFull | FileTree::NoLeaf)) + { + std::shared_ptr list(new DictionaryValue); + + static String const VAR_TYPE ("type"); + static String const VAR_MODIFIED_AT("modifiedAt"); + static String const VAR_SIZE ("size"); + static String const VAR_META_ID ("metaId"); + + auto addMeta = [this] + (DictionaryValue &list, PathTree::Nodes const &nodes) + { + for (auto i = nodes.begin(); i != nodes.end(); ++i) + { + auto const &entry = i.value()->as(); + list.add(new TextValue(entry.name()), + RecordValue::takeRecord( + Record::withMembers( + VAR_TYPE, entry.isLeaf()? 0 : 1, + VAR_SIZE, entry.size, + VAR_MODIFIED_AT, entry.modTime, + VAR_META_ID, metaIdForFileEntry(entry) + ))); + } + }; + + addMeta(*list.get(), dir->children().branches); + addMeta(*list.get(), dir->children().leaves); + + return list; + } + return nullptr; + }, + [this, id] (std::shared_ptr list) + { + self().metadataReceived(id, list? *list : DictionaryValue()); + }); + } + + void receiveFileContents(QueryId id, QNetworkReply *reply) + { + if (reply->error() == QNetworkReply::NoError) + { + //qDebug() << "Content-Length:" << reply->header(QNetworkRequest::ContentLengthHeader); + dsize const contentLength = reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); + + //qDebug() << "pos:" << pos << contentLength << reply->url(); + + // Ths is the complete downloaded file. + QByteArray const data = reply->readAll(); + + Query const *query = self().findQuery(id); + self().chunkReceived(id, query->receivedBytes, data, + contentLength? contentLength : dsize(data.size())); + } + else + { + LOG_NET_WARNING(reply->errorString()); + + /// @todo Abort query with error. + } + } +}; + +WebHostedLink::WebHostedLink(String const &address, String const &indexPath) + : Link(address) + , d(new Impl(this)) +{ + // Fetch the repository index. + { + QNetworkRequest req(QUrl(address / indexPath)); + req.setRawHeader("User-Agent", Version::currentBuild().userAgent().toLatin1()); + + QNetworkReply *reply = filesys::RemoteFeedRelay::get().network().get(req); + QObject::connect(reply, &QNetworkReply::finished, [this, reply] () + { + reply->deleteLater(); + if (reply->error() == QNetworkReply::NoError) + { + parseRepositoryIndex(reply->readAll()); + } + else + { + handleError(reply->errorString()); + wasDisconnected(); + } + }); + } +} + +void WebHostedLink::setFileTree(FileTree *tree) +{ + DENG2_GUARD(d); + d->fileTree.reset(tree); +} + +WebHostedLink::FileTree const &WebHostedLink::fileTree() const +{ + return *d->fileTree; +} + +WebHostedLink::FileEntry const *WebHostedLink::findFile(Path const &path) const +{ + DENG2_GUARD(d); + return d->fileTree->tryFind(path, PathTree::MatchFull); +} + +filesys::PackagePaths WebHostedLink::locatePackages(StringList const &packageIds) const +{ + PackagePaths remotePaths; + foreach (String packageId, packageIds) + { + if (String remotePath = findPackagePath(packageId)) + { + remotePaths.insert(packageId, + RepositoryPath(*this, localRoot().path()/packageId, remotePath)); + } + } + return remotePaths; +} + +void WebHostedLink::transmit(Query const &query) +{ + // We can answer population queries instantly because an index was + // downloaded when the connection was opened. + if (query.fileMetadata) + { + d->handleFileListQueryAsync(query); + return; + } + + DENG2_ASSERT(query.fileContents); + + String url = address(); + QNetworkRequest req(url.concatenateRelativePath(query.path)); + qDebug() << req.url().toString(); + req.setRawHeader("User-Agent", Version::currentBuild().userAgent().toLatin1()); + + QNetworkReply *reply = RemoteFeedRelay::get().network().get(req); + d->pendingRequests.insert(reply); + + auto const id = query.id; + QObject::connect(reply, &QNetworkReply::readyRead, [this, id, reply] () + { + d->receiveFileContents(id, reply); + }); + QObject::connect(reply, &QNetworkReply::finished, [this, id, reply] () + { + d->pendingRequests.remove(reply); + reply->deleteLater(); + }); +} + +Block WebHostedLink::FileEntry::metaId(Link const &link) const +{ + return md5Hash(link.address(), path(), size, modTime); +} + +} // namespace filesys +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/staticlibraryfeed.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/staticlibraryfeed.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/filesys/staticlibraryfeed.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/filesys/staticlibraryfeed.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,58 @@ +/** @file staticlibraryfeed.cpp + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/filesys/staticlibraryfeed.h" +#include "de/Folder" +#include "de/Library" +#include "de/LibraryFile" +#include "de/String" + +namespace de { + +StaticLibraryFeed::StaticLibraryFeed() +{} + +String StaticLibraryFeed::description() const +{ + return "imported static libraries"; +} + +Feed::PopulatedFiles StaticLibraryFeed::populate(Folder const &folder) +{ + PopulatedFiles files; +#if defined (DENG_STATIC_LINK) + for (String name : Library::staticLibraries()) + { + if (!folder.has(name)) + { + files << new LibraryFile(NativePath(name)); + } + } +#else + DENG2_UNUSED(folder); +#endif + return files; +} + +bool StaticLibraryFeed::prune(File &) const +{ + // Static libraries are built-in, so nothing will change... + return false; +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/math.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/math.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/math.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/math.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -20,8 +20,29 @@ #include "de/IByteArray" #include "de/Reader" +#include +#include + +#include + namespace de { +float randf() +{ + using namespace std; + + static minstd_rand rng( + uint32_t((chrono::high_resolution_clock::now().time_since_epoch().count() & 0xffffffff) ^ + QCoreApplication::applicationPid())); + + return float(double(rng() - rng.min()) / double(rng.max() - rng.min() + 1)); +} + +duint32 randui32() +{ + return duint32(randf() * 0x10000) | (duint32(randf() * 0x10000) << 16); +} + duint32 crc32(IByteArray const &data) { /* ====================================================================== */ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/address.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/address.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/address.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/address.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -28,10 +28,18 @@ DENG2_PIMPL_NOREF(Address) { - QHostAddress host; - duint16 port; + std::shared_ptr host; + duint16 port = 0; + String textRepr; - Impl() : port(0) {} + enum Special { Undefined, LocalHost, RemoteHost }; + Special special = Undefined; + + void clearCached() + { + textRepr.clear(); + special = Impl::Undefined; + } }; Address::Address() : d(new Impl) @@ -43,62 +51,69 @@ if (QLatin1String(address) == "localhost") // special case { - d->host = QHostAddress(QHostAddress::LocalHostIPv6); + d->host.reset(new QHostAddress(QHostAddress::LocalHostIPv6)); + d->special = Impl::LocalHost; } else { - d->host = QHostAddress(QHostAddress(address).toIPv6Address()); + d->host.reset(new QHostAddress(QHostAddress(address).toIPv6Address())); } } Address::Address(QHostAddress const &host, duint16 port) : d(new Impl) { - d->host = QHostAddress(host.toIPv6Address()); + d->host.reset(new QHostAddress(host.toIPv6Address())); d->port = port; } -Address::Address(Address const &other) : LogEntry::Arg::Base(), d(new Impl) -{ - d->host = other.d->host; - d->port = other.d->port; -} +Address::Address(Address const &other) + : d(new Impl(*other.d)) +{} -Address &Address::operator = (Address const &other) +Address &Address::operator=(Address const &other) { - d->host = other.d->host; - d->port = other.d->port; + d->host = other.d->host; + d->port = other.d->port; + d->textRepr = other.d->textRepr; + d->special = other.d->special; return *this; } -bool Address::operator < (Address const &other) const +bool Address::operator<(Address const &other) const { return asText() < other.asText(); } -bool Address::operator == (Address const &other) const +bool Address::operator==(Address const &other) const { - if (d->port != other.d->port) return false; - return (isLocal() && other.isLocal()) || (d->host == other.d->host); +// if (d->port != other.d->port) return false; +// return (isLocal() && other.isLocal()) || (d->host == other.d->host); + return asText() == other.asText(); } bool Address::isNull() const { - return d->host.isNull(); + return d->host->isNull(); } QHostAddress const &Address::host() const { - return d->host; + return *d->host; } void Address::setHost(QHostAddress const &host) { - d->host = QHostAddress(host.toIPv6Address()); + d->clearCached(); + d->host.reset(new QHostAddress(host.toIPv6Address())); } bool Address::isLocal() const { - return isHostLocal(d->host); + if (d->special == Impl::Undefined) + { + d->special = isHostLocal(*d->host) ? Impl::LocalHost : Impl::RemoteHost; + } + return (d->special == Impl::LocalHost); } duint16 Address::port() const @@ -108,22 +123,26 @@ void Address::setPort(duint16 p) { + d->clearCached(); d->port = p; } bool Address::matches(Address const &other, duint32 mask) { - return (d->host.toIPv4Address() & mask) == (other.d->host.toIPv4Address() & mask); + return (d->host->toIPv4Address() & mask) == (other.d->host->toIPv4Address() & mask); } String Address::asText() const { - String result = (isLocal()? String("localhost") : d->host.toString()); - if (d->port) + if (!d->textRepr) { - result += ":" + QString::number(d->port); + d->textRepr = (isLocal()? String("localhost") : d->host->toString()); + if (d->port) + { + d->textRepr += ":" + QString::number(d->port); + } } - return result; + return d->textRepr; } Address Address::parse(String const &addressWithOptionalPort, duint16 defaultPort) // static @@ -160,7 +179,7 @@ return Address(str.toLatin1(), port); } -QTextStream &operator << (QTextStream &os, Address const &address) +QTextStream &operator<<(QTextStream &os, Address const &address) { os << address.asText(); return os; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/beacon.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/beacon.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/beacon.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/beacon.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -107,7 +107,7 @@ d->socket = 0; } -void Beacon::discover(TimeDelta const &timeOut, TimeDelta const &interval) +void Beacon::discover(TimeSpan const &timeOut, TimeSpan const &interval) { if (d->timer) return; // Already discovering. @@ -120,7 +120,7 @@ int tries = 10; forever { - if (d->socket->bind(d->port + 1 + qrand() % 0x4000, QUdpSocket::DontShareAddress)) + if (d->socket->bind(d->port + Rangeui16(1, 0x4000).random(), QUdpSocket::DontShareAddress)) { // Got a port open successfully. break; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/blockpacket.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/blockpacket.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/blockpacket.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/blockpacket.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,7 +22,7 @@ namespace de { -static const char* BLOCK_PACKET_TYPE = "BLCK"; +static Packet::Type const BLOCK_PACKET_TYPE = Packet::typeFromString("BLCK"); BlockPacket::BlockPacket() : Packet(BLOCK_PACKET_TYPE) {} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/identifiedpacket.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/identifiedpacket.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/identifiedpacket.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/identifiedpacket.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/IdentifiedPacket" @@ -29,6 +29,11 @@ : Packet(type), _id(i) {} +void IdentifiedPacket::setId(Id id) +{ + _id = id; +} + void IdentifiedPacket::operator >> (Writer &to) const { Packet::operator >> (to); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/packet.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/packet.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/packet.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/packet.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,18 +14,27 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/Packet" -#include "de/Writer" + +#include "de/ByteRefArray" #include "de/Reader" #include "de/String" +#include "de/Writer" #include namespace de { +Packet::Type Packet::typeFromString(char const *fourcc) +{ + Type type; + std::memcpy(type.data(), fourcc, 4); + return type; +} + Packet::Packet(Type const &t) { setType(t); @@ -33,25 +42,23 @@ void Packet::setType(Type const &t) { - DENG2_ASSERT(t.size() == TYPE_SIZE); _type = t; } void Packet::operator >> (Writer &to) const { - QByteArray bytes = _type.toLatin1(); - to << bytes[0] << bytes[1] << bytes[2] << bytes[3]; + to.writeBytes(ByteRefArray(_type.data(), 4)); } void Packet::operator << (Reader &from) { - char ident[5]; - from >> ident[0] >> ident[1] >> ident[2] >> ident[3]; - ident[4] = 0; - + Type ident; + ByteRefArray ref(ident.data(), 4); + from.readBytesFixedSize(ref); + // Having been constructed as a specific type, the identifier is already // set and cannot change. Let's check if it's the correct one. - if (_type.compareWithCase(ident)) + if (_type != ident) { throw InvalidTypeError("Packet::operator <<", "Invalid ID"); } @@ -60,14 +67,14 @@ void Packet::execute() const {} -bool Packet::checkType(Reader &from, String const &type) +bool Packet::checkType(Reader &from, Type const &type) { - char ident[5]; from.mark(); - from >> ident[0] >> ident[1] >> ident[2] >> ident[3]; - ident[4] = 0; + Type ident; + ByteRefArray ref(ident.data(), 4); + from.readBytesFixedSize(ref); from.rewind(); - return !type.compareWithCase(ident); + return type == ident; } -} // namespace de \ No newline at end of file +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/protocol.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/protocol.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/protocol.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/protocol.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/Protocol" @@ -43,13 +43,12 @@ { foreach (Constructor constructor, _constructors) { - Packet *p = constructor(block); - if (p) + if (Packet *p = constructor(block)) { return p; } } - return 0; + return nullptr; } /* @@ -57,7 +56,7 @@ { LOG_AS("Protocol::syncCommand"); LOG_DEBUG("Sending: '%s' with args:\n%s") << command.command() << command.arguments(); - + to << command; QScopedPointer rep(to.receivePacket()); @@ -65,7 +64,7 @@ if (rep->label() == "failure") { /// @throw FailureError The response to @a command was FAILURE. - throw FailureError("Protocol::decree", "Command '" + command.command() + + throw FailureError("Protocol::decree", "Command '" + command.command() + "' failed: " + rep->valueAsText("message")); } else if (rep->label() == "deny") @@ -93,11 +92,11 @@ case OK: label = "ok"; break; - + case FAILURE: label = "failure"; break; - + case DENY: label = "deny"; break; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/recordpacket.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/recordpacket.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/recordpacket.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/recordpacket.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/RecordPacket" @@ -25,7 +25,7 @@ namespace de { -static const char* RECORD_PACKET_TYPE = "RECO"; +static Packet::Type const RECORD_PACKET_TYPE = Packet::typeFromString("RECO"); RecordPacket::RecordPacket(String const &name, Id i) : IdentifiedPacket(RECORD_PACKET_TYPE, i), _name(name), _record(0) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/socket.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/socket.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/net/socket.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/net/socket.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -67,26 +67,39 @@ */ #include "de/Socket" +#include "de/Async" #include "de/Message" #include "de/Writer" #include "de/Reader" #include "de/data/huffman.h" +#include + namespace de { +struct Counters +{ + duint64 sentUncompressedBytes = 0; + duint64 sentBytes = 0; + duint64 sentPeriodBytes = 0; + double outputBytesPerSecond = 0; + Time periodStartedAt; +}; +static LockableT counters; +static TimeSpan const sendPeriodDuration = 5; + /// Maximum number of channels. static duint const MAX_CHANNELS = 2; static int const MAX_SIZE_SMALL = 127; // bytes static int const MAX_SIZE_MEDIUM = 4095; // bytes +static int const MAX_SIZE_BIG = 10*MAX_SIZE_MEDIUM; static int const MAX_SIZE_LARGE = DENG2_SOCKET_MAX_PAYLOAD_SIZE; /// Threshold for input data size: messages smaller than this are first compressed /// with Doomsday's Huffman codes. If the result is smaller than the deflated data, /// the Huffman coded payload is used (unless it doesn't fit in a medium-sized packet). -#define MAX_HUFFMAN_INPUT_SIZE 4096 // bytes - -#define DEFAULT_TRANSMISSION_SIZE 4096 +static int const MAX_HUFFMAN_INPUT_SIZE = 4096; // bytes #define TRMF_CONTINUE 0x80 #define TRMF_DEFLATED 0x40 @@ -184,40 +197,30 @@ DENG2_PIMPL_NOREF(Socket) { - Address target; - bool quiet; + Address peer; + bool quiet = false; + bool retainOrder = true; - enum ReceptionState { - ReceivingHeader, - ReceivingPayload - }; - ReceptionState receptionState; + enum ReceptionState { ReceivingHeader, ReceivingPayload }; + ReceptionState receptionState = ReceivingHeader; Block receivedBytes; MessageHeader incomingHeader; /// Number of the active channel. /// @todo Channel is not used at the moment. - duint activeChannel; + duint activeChannel = 0; /// Pointer to the internal socket data. - QTcpSocket *socket; + QTcpSocket *socket = nullptr; /// Buffer for incoming received messages. QList receivedMessages; /// Number of bytes waiting to be written to the socket. - dint64 bytesToBeWritten; + dint64 bytesToBeWritten = 0; /// Number of bytes written to the socket so far. - dint64 totalBytesWritten; - - Impl() : - quiet(false), - receptionState(ReceivingHeader), - activeChannel(0), - socket(0), - bytesToBeWritten(0), - totalBytesWritten(0) {} + dint64 totalBytesWritten = 0; ~Impl() { @@ -225,11 +228,9 @@ foreach (Message *msg, receivedMessages) delete msg; } - void serializeAndSendMessage(IByteArray const &packet) + void serializeMessage(MessageHeader &header, Block &payload) { - Block payload(packet); Block huffData; - MessageHeader header; // Let's find the appropriate compression method of the payload. First see // if the encoded contents are under 128 bytes as Huffman codes. @@ -253,7 +254,7 @@ if (!header.size) // Try deflate. { - int const level = (payload.size() < 10*MAX_SIZE_MEDIUM? 1 /*fast*/ : 9 /*best*/); + int const level = 1; //(payload.size() < MAX_SIZE_BIG? 1 /*fast*/ : 9 /*best*/); Block const deflated = payload.compressed(level); if (!deflated.size()) @@ -282,6 +283,13 @@ payload = deflated; } } + } + + void sendMessage(MessageHeader const &header, + Block const &payload) + { + DENG2_ASSERT(socket != nullptr); + DENG2_ASSERT(QThread::currentThread() == socket->thread()); // Write the message header. Block dest; @@ -289,11 +297,62 @@ socket->write(dest); // Update totals (for statistics). - dsize total = dest.size() + payload.size(); - bytesToBeWritten += total; + dsize const total = dest.size() + payload.size(); + bytesToBeWritten += total; totalBytesWritten += total; socket->write(payload); + + // Update total counters, too. + { + DENG2_GUARD(counters); + counters.value.sentPeriodBytes += total; + counters.value.sentBytes += total; + // Update Bps counter. + if (!counters.value.periodStartedAt.isValid() + || counters.value.periodStartedAt.since() > sendPeriodDuration) + { + counters.value.outputBytesPerSecond = double(counters.value.sentPeriodBytes) + / sendPeriodDuration; + counters.value.sentPeriodBytes = 0; + counters.value.periodStartedAt = Time::currentHighPerformanceTime(); + } + } + } + + void serializeAndSendMessage(IByteArray const &packet) + { + Block payload = packet; + { + DENG2_GUARD(counters); + counters.value.sentUncompressedBytes += payload.size(); + } + + if (!retainOrder && packet.size() >= MAX_SIZE_BIG) + { + async([this, payload] () + { + // Prepare for sending in a background thread, since it may take a moment. + MessageHeader header; + Block msgData = payload; + serializeMessage(header, msgData); + return std::make_pair(header, msgData); + }, + [this] (std::pair msg) + { + if (socket) + { + // Write to socket in main thread. + sendMessage(msg.first, msg.second); + } + }); + } + else + { + MessageHeader header; + serializeMessage(header, payload); + sendMessage(header, payload); + } } /** @@ -310,7 +369,6 @@ // A message must be at least two bytes long (header + payload). return; } - try { Reader reader(receivedBytes); @@ -378,7 +436,7 @@ QObject::connect(d->socket, SIGNAL(connected()), this, SIGNAL(connected())); } -Socket::Socket(Address const &address, TimeDelta const &timeOut) : d(new Impl) // blocking +Socket::Socket(Address const &address, TimeSpan const &timeOut) : d(new Impl) // blocking { LOG_AS("Socket"); @@ -387,7 +445,7 @@ // Now that the signals have been set... d->socket->connectToHost(address.host(), address.port()); - if (!d->socket->waitForConnected(timeOut.asMilliSeconds())) + if (!d->socket->waitForConnected(int(timeOut.asMilliSeconds()))) { QString msg = d->socket->errorString(); delete d->socket; @@ -400,13 +458,13 @@ LOG_NET_NOTE("Connection opened to %s") << address.asText(); - d->target = address; + d->peer = address; DENG2_ASSERT(d->socket->isOpen() && d->socket->isWritable() && d->socket->state() == QAbstractSocket::ConnectedState); } -void Socket::connect(Address const &address) // non-blocking +void Socket::open(Address const &address) // non-blocking { DENG2_ASSERT(d->socket); DENG2_ASSERT(d->socket->state() == QAbstractSocket::UnconnectedState); @@ -415,11 +473,11 @@ if (!d->quiet) LOG_NET_MSG("Opening connection to %s") << address.asText(); d->socket->connectToHost(address.host(), address.port()); - d->target = address; + d->peer = address; } -void Socket::connectToDomain(String const &domainNameWithOptionalPort, - duint16 defaultPort) // non-blocking +void Socket::open(String const &domainNameWithOptionalPort, + duint16 defaultPort) // non-blocking { String str = domainNameWithOptionalPort; duint16 port = defaultPort; @@ -432,7 +490,7 @@ } if (str == "localhost") { - connect(Address(str.toLatin1(), port)); + open(Address(str.toLatin1(), port)); return; } @@ -440,11 +498,11 @@ if (!host.isNull()) { // Looks like a regular IP address. - connect(Address(str.toLatin1(), port)); + open(Address(str.toLatin1(), port)); return; } - d->target.setPort(port); + d->peer.setPort(port); // Looks like we will need to look this up. QHostInfo::lookupHost(str, this, SLOT(hostResolved(QHostInfo))); @@ -454,7 +512,7 @@ { DENG2_ASSERT(!isOpen()); - connect(d->target); + open(d->peer); } Socket::Socket(QTcpSocket *existingSocket) : d(new Impl) @@ -523,6 +581,30 @@ d->quiet = noLogOutput; } +void Socket::resetCounters() +{ + DENG2_GUARD(counters); + counters.value = Counters(); +} + +duint64 Socket::sentUncompressedBytes() +{ + DENG2_GUARD(counters); + return counters.value.sentUncompressedBytes; +} + +duint64 Socket::sentBytes() +{ + DENG2_GUARD(counters); + return counters.value.sentBytes; +} + +double Socket::outputBytesPerSecond() +{ + DENG2_GUARD(counters); + return counters.value.outputBytesPerSecond; +} + duint Socket::channel() const { return d->activeChannel; @@ -534,6 +616,11 @@ d->activeChannel = min(number, MAX_CHANNELS - 1); } +void Socket::setRetainOrder(bool retainOrder) +{ + d->retainOrder = retainOrder; +} + void Socket::send(IByteArray const &packet) { send(packet, d->activeChannel); @@ -553,6 +640,9 @@ throw DisconnectedError("Socket::send", "Socket is unavailable"); } + // Sockets must be used only in their own thread. + DENG2_ASSERT(thread() == QThread::currentThread()); + d->serializeAndSendMessage(packet); } @@ -560,7 +650,7 @@ { if (!d->socket) return; - int available = d->socket->bytesAvailable(); + auto available = d->socket->bytesAvailable(); if (available > 0) { d->receivedBytes += d->socket->read(d->socket->bytesAvailable()); @@ -585,7 +675,7 @@ else { // Now we know where to connect. - connect(Address(info.addresses().first(), d->target.port())); + open(Address(info.addresses().first(), d->peer.port())); emit addressResolved(); } @@ -595,7 +685,7 @@ { if (d->receivedMessages.isEmpty()) { - return 0; + return nullptr; } return d->receivedMessages.takeFirst(); } @@ -604,7 +694,7 @@ { if (d->receivedMessages.isEmpty()) { - return 0; + return nullptr; } return d->receivedMessages.first(); } @@ -624,7 +714,7 @@ { return Address(d->socket->peerAddress(), d->socket->peerPort()); } - return d->target; + return d->peer; } bool Socket::isOpen() const @@ -661,13 +751,18 @@ dsize Socket::bytesBuffered() const { - return d->bytesToBeWritten; + return dsize(d->bytesToBeWritten); } void Socket::bytesWereWritten(qint64 bytes) { d->bytesToBeWritten -= bytes; DENG2_ASSERT(d->bytesToBeWritten >= 0); + + if (d->bytesToBeWritten == 0) + { + emit allSent(); + } } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/assignstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/assignstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/assignstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/assignstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -104,14 +104,14 @@ void AssignStatement::operator >> (Writer &to) const { - to << SerialId(ASSIGN) << duint8(_indexCount) << _args; + to << dbyte(SerialId::Assign) << duint8(_indexCount) << _args; } void AssignStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != ASSIGN) + from.readAs(id); + if (id != SerialId::Assign) { /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_core.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_core.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_core.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_core.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -28,6 +28,7 @@ #include "de/Path" #include "de/Record" #include "de/RecordValue" +#include "de/RemoteFile" #include "de/TextValue" #include "de/TimeValue" @@ -94,7 +95,7 @@ //--------------------------------------------------------------------------------------- -static File const &fileInstance(Context &ctx) +static File &fileInstance(Context &ctx) { // The record is expected to have a path (e.g., File info record). File *file = ctx.selfInstance().get(Record::VAR_NATIVE_SELF) @@ -106,70 +107,94 @@ return *file; } +static File const &constFileInstance(Context &ctx) +{ + return fileInstance(ctx); +} + static Value *Function_File_Name(Context &ctx, Function::ArgumentValues const &) { - return new TextValue(fileInstance(ctx).name()); + return new TextValue(constFileInstance(ctx).name()); } static Value *Function_File_Path(Context &ctx, Function::ArgumentValues const &) { - return new TextValue(fileInstance(ctx).path()); + return new TextValue(constFileInstance(ctx).path()); } static Value *Function_File_Type(Context &ctx, Function::ArgumentValues const &) { - return new TextValue(fileInstance(ctx).status().type() == File::Status::FILE? "file" : "folder"); + return new TextValue(constFileInstance(ctx).status().type() == File::Type::File? "file" : "folder"); } static Value *Function_File_Size(Context &ctx, Function::ArgumentValues const &) { - return new NumberValue(fileInstance(ctx).size()); + return new NumberValue(constFileInstance(ctx).size()); } static Value *Function_File_ModifiedAt(Context &ctx, Function::ArgumentValues const &) { - return new TimeValue(fileInstance(ctx).status().modifiedAt); + return new TimeValue(constFileInstance(ctx).status().modifiedAt); } static Value *Function_File_Description(Context &ctx, Function::ArgumentValues const &) { - return new TextValue(fileInstance(ctx).description()); + return new TextValue(constFileInstance(ctx).description()); } static Value *Function_File_Locate(Context &ctx, Function::ArgumentValues const &args) { Path const relativePath = args.at(0)->asText(); - - if (File const *found = maybeAs(fileInstance(ctx).tryFollowPath(relativePath))) + if (File const *found = maybeAs(constFileInstance(ctx).tryFollowPath(relativePath))) { return new RecordValue(found->objectNamespace()); } // Wasn't there, result is None. - return 0; + return nullptr; } static Value *Function_File_Read(Context &ctx, Function::ArgumentValues const &) { QScopedPointer data(new BlockValue); - fileInstance(ctx) >> *data; + constFileInstance(ctx) >> *data; return data.take(); } static Value *Function_File_ReadUtf8(Context &ctx, Function::ArgumentValues const &) { Block raw; - fileInstance(ctx) >> raw; + constFileInstance(ctx) >> raw; return new TextValue(String::fromUtf8(raw)); } +static Value *Function_File_Replace(Context &ctx, Function::ArgumentValues const &args) +{ + Folder &parentFolder = fileInstance(ctx).as(); + File &created = parentFolder.replaceFile(args.at(0)->asText()); + return new RecordValue(created.objectNamespace()); +} + +static Value *Function_File_Write(Context &ctx, Function::ArgumentValues const &args) +{ + BlockValue const &data = args.at(0)->as(); + fileInstance(ctx) << data.block(); + return nullptr; +} + +static Value *Function_File_Flush(Context &ctx, Function::ArgumentValues const &) +{ + fileInstance(ctx).flush(); + return nullptr; +} + static Value *Function_File_MetaId(Context &ctx, Function::ArgumentValues const &) { - return new TextValue(fileInstance(ctx).metaId().asHexadecimalText()); + return new TextValue(constFileInstance(ctx).metaId().asHexadecimalText()); } static Value *Function_Folder_List(Context &ctx, Function::ArgumentValues const &) { - Folder const &folder = fileInstance(ctx).as(); + Folder const &folder = constFileInstance(ctx).as(); std::unique_ptr array(new ArrayValue); foreach (String name, folder.contents().keys()) { @@ -180,10 +205,24 @@ static Value *Function_Folder_ContentSize(Context &ctx, Function::ArgumentValues const &) { - Folder const &folder = fileInstance(ctx).as(); + Folder const &folder = constFileInstance(ctx).as(); return new NumberValue(folder.contents().size()); } +static Value *Function_Folder_Contents(Context &ctx, Function::ArgumentValues const &) +{ + Folder const &folder = constFileInstance(ctx).as(); + LOG_SCR_MSG(_E(m) "%s") << folder.contentsAsText(); + return nullptr; +} + +static Value *Function_RemoteFile_Download(Context &ctx, Function::ArgumentValues const &) +{ + RemoteFile &rf = fileInstance(ctx).as(); + rf.download(); + return nullptr; +} + //--------------------------------------------------------------------------------------- static Animation &animationInstance(Context &ctx) @@ -232,6 +271,8 @@ void initCoreModule(Binder &binder, Record &coreModule) { + // The Core module contains classes that match native classes as closely as possible. + // Dictionary { @@ -271,12 +312,15 @@ << DENG2_FUNC_NOARG(File_Path, "path") << DENG2_FUNC_NOARG(File_Type, "type") << DENG2_FUNC_NOARG(File_Size, "size") + << DENG2_FUNC_NOARG(File_MetaId, "metaId") << DENG2_FUNC_NOARG(File_ModifiedAt, "modifiedAt") << DENG2_FUNC_NOARG(File_Description, "description") << DENG2_FUNC (File_Locate, "locate", "relativePath") << DENG2_FUNC_NOARG(File_Read, "read") << DENG2_FUNC_NOARG(File_ReadUtf8, "readUtf8") - << DENG2_FUNC_NOARG(File_MetaId, "metaId"); + << DENG2_FUNC (File_Replace, "replace", "relativePath") + << DENG2_FUNC (File_Write, "write", "data") + << DENG2_FUNC_NOARG(File_Flush, "flush"); } // Folder @@ -284,9 +328,17 @@ Record &folder = coreModule.addSubrecord("Folder").setFlags(Record::WontBeDeleted); binder.init(folder) << DENG2_FUNC_NOARG(Folder_List, "list") + << DENG2_FUNC_NOARG(Folder_Contents, "contents") << DENG2_FUNC_NOARG(Folder_ContentSize, "contentSize"); } + // RemoteFile + { + Record &remoteFile = coreModule.addSubrecord("RemoteFile").setFlags(Record::WontBeDeleted); + binder.init(remoteFile) + << DENG2_FUNC_NOARG(RemoteFile_Download, "download"); + } + // Animation { Function::Defaults setValueArgs; @@ -305,6 +357,8 @@ << DENG2_FUNC_DEFS (Animation_SetValueFrom, "setValueFrom", "fromValue" << "toValue" << "span" << "delay", setValueFromArgs); } + + } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_math.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_math.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_math.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/bindings_math.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,7 +25,7 @@ static Value *Function_Math_Random(Context &, Function::ArgumentValues const &) { - return new NumberValue(frand()); + return new NumberValue(randf()); } static Value *Function_Math_RandInt(Context &, Function::ArgumentValues const &args) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/catchstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/catchstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/catchstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/catchstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/CatchStatement" @@ -57,10 +57,10 @@ // Not specified, so catches all. return true; } - + NameExpression const *name = dynamic_cast(&_args->at(0)); DENG2_ASSERT(name != NULL); - + return (name->identifier() == "Error" || // Generic catch-all. name->identifier() == err.name() || // Exact match. String(err.name()).endsWith("_" + name->identifier())); // Sub-error match. @@ -74,23 +74,23 @@ RefValue &ref = context.evaluator().evaluateTo(&_args->at(1)); ref.assign(new TextValue(err.asText())); } - + // Begin the catch compound. context.start(_compound.firstStatement(), next()); } void CatchStatement::operator >> (Writer &to) const { - to << SerialId(CATCH) << duint8(flags) << *_args << _compound; + to << dbyte(SerialId::Catch) << duint8(flags) << *_args << _compound; } void CatchStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != CATCH) + from.readAs(id); + if (id != SerialId::Catch) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("CatchStatement::operator <<", "Invalid ID"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/deletestatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/deletestatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/deletestatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/deletestatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/DeleteStatement" @@ -60,16 +60,16 @@ void DeleteStatement::operator >> (Writer &to) const { - to << SerialId(DELETE) << *_targets; + to << dbyte(SerialId::Delete) << *_targets; } void DeleteStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != DELETE) + from.readAs(id); + if (id != SerialId::Delete) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("DeleteStatement::operator <<", "Invalid ID"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/expressionstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/expressionstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/expressionstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/expressionstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/ExpressionStatement" @@ -43,16 +43,16 @@ void ExpressionStatement::operator >> (Writer &to) const { - to << SerialId(EXPRESSION) << *_expression; + to << dbyte(SerialId::Expression) << *_expression; } void ExpressionStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != EXPRESSION) + from.readAs(id); + if (id != SerialId::Expression) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("ExpressionStatement::operator <<", "Invalid ID"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/flowstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/flowstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/flowstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/flowstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/FlowStatement" @@ -30,33 +30,33 @@ #define HAS_ARG 0x80 #define TYPE_MASK 0x7f - + FlowStatement::FlowStatement() : _type(PASS), _arg(0) {} - -FlowStatement::FlowStatement(Type type, Expression *countArgument) - : _type(type), _arg(countArgument) + +FlowStatement::FlowStatement(Type type, Expression *countArgument) + : _type(type), _arg(countArgument) {} - + FlowStatement::~FlowStatement() { delete _arg; } - + void FlowStatement::execute(Context &context) const { Evaluator &eval = context.evaluator(); - + switch (_type) { case PASS: context.proceed(); break; - + case CONTINUE: context.jumpContinue(); break; - + case BREAK: if (_arg) { @@ -65,9 +65,9 @@ else { context.jumpBreak(); - } + } break; - + case RETURN: if (_arg) { @@ -79,23 +79,23 @@ context.process().finish(); } break; - + case THROW: if (_arg) { throw Error("thrown in script", eval.evaluate(_arg).asText()); - } + } else { /// @todo Rethrow the current error. context.proceed(); - } + } } } void FlowStatement::operator >> (Writer &to) const { - to << SerialId(FLOW); + to << dbyte(SerialId::Flow); duint8 header = duint8(_type); if (_arg) { @@ -111,10 +111,10 @@ void FlowStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != FLOW) + from.readAs(id); + if (id != SerialId::Flow) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("FlowStatement::operator <<", "Invalid ID"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/forstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/forstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/forstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/forstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -69,14 +69,14 @@ void ForStatement::operator >> (Writer &to) const { - to << SerialId(FOR) << *_iterator << *_iteration << _compound; + to << dbyte(SerialId::For) << *_iterator << *_iteration << _compound; } void ForStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != FOR) + from.readAs(id); + if (id != SerialId::For) { /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/functionstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/functionstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/functionstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/functionstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -85,14 +85,14 @@ void FunctionStatement::operator >> (Writer &to) const { - to << SerialId(FUNCTION) << *_identifier << *_function << _defaults; + to << dbyte(SerialId::Function) << *_identifier << *_function << _defaults; } void FunctionStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != FUNCTION) + from.readAs(id); + if (id != SerialId::Function) { /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/ifstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/ifstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/ifstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/ifstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/IfStatement" @@ -80,8 +80,8 @@ void IfStatement::operator >> (Writer &to) const { - to << SerialId(IF); - + to << dbyte(SerialId::If); + // Branches. to << duint16(_branches.size()); for (Branches::const_iterator i = _branches.begin(); i != _branches.end(); ++i) @@ -96,15 +96,15 @@ void IfStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != IF) + from.readAs(id); + if (id != SerialId::If) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("IfStatement::operator <<", "Invalid ID"); } clear(); - + // Branches. duint16 count; from >> count; @@ -114,6 +114,6 @@ setBranchCondition(Expression::constructFrom(from)); from >> branchCompound(); } - + from >> _elseCompound; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/lex.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/lex.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/lex.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/lex.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -98,7 +98,7 @@ // Skip over the line. duint p = _state.pos; - while (p < inputSize && _input->at(++p) != '\n') {} + while (p < inputSize - 1 && _input->at(++p) != '\n') {} _nextPos = p + 1; return (p < inputSize? '\n' : 0); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/parser.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/parser.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/parser.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/parser.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -289,7 +289,7 @@ dint startAt = 1; Expression::Flags flags = Expression::Import | - Expression::NotInScope | + //Expression::NotInScope | Expression::LocalOnly; if (_statementRange.size() >= 3 && _statementRange.token(1).equals(ScriptLex::RECORD)) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/printstatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/printstatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/printstatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/printstatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -62,22 +62,22 @@ } os << (*i)->asText(); } - + LOG_SCR_MSG(_E(m)) << msg; - + context.proceed(); } void PrintStatement::operator >> (Writer &to) const { - to << SerialId(PRINT) << *_arg; + to << dbyte(SerialId::Print) << *_arg; } void PrintStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != PRINT) + from.readAs(id); + if (id != SerialId::Print) { /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/process.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/process.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/process.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/process.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -147,7 +147,7 @@ }; /// If execution continues for longer than this, a HangError is thrown. -static TimeDelta const MAX_EXECUTION_TIME = 10; +static TimeSpan const MAX_EXECUTION_TIME = 10; Process::Process(Record *externalGlobalNamespace) : d(new Impl(this)) { @@ -387,7 +387,7 @@ for (; b != argValues.end() && a != function.arguments().end(); ++b, ++a) { // Records must only be passed as unowned references. - DENG2_ASSERT(!(*b)->is() || !(*b)->as().hasOwnership()); + DENG2_ASSERT(!is(*b) || !(*b)->as().hasOwnership()); context().names().add(new Variable(*a, (*b)->duplicate())); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scheduler.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scheduler.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scheduler.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scheduler.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -1,6 +1,6 @@ -/** @file scheduler.cpp Script scheduling utility. +/** @file scheduler.cpp Scheduler for scripts and timelines. * - * @authors Copyright (c) 2015-2017 Jaakko Keränen + * @authors Copyright (c) 2017 Jaakko Keränen * * @par License * LGPL: http://www.gnu.org/licenses/lgpl.html @@ -17,188 +17,117 @@ */ #include "de/Scheduler" -#include "de/ScriptedInfo" -#include "de/Record" -#include "de/Script" -#include "de/Process" -#include -#include +#include namespace de { -DENG2_PIMPL(Scheduler) -, DENG2_OBSERVES(Record, Deletion) +DENG2_PIMPL_NOREF(Scheduler) { - Record *context = nullptr; + struct RunningTimeline + { + Timeline const *timeline = nullptr; + std::unique_ptr clock; + bool isOwned = false; - struct Event { - TimeDelta at; - Script script; - - Event(TimeDelta at, String const &source, String const &sourcePath) - : at(at) - , script(source) + ~RunningTimeline() { - script.setPath(sourcePath); // where the source comes from + if (isOwned) delete timeline; } - - struct Compare { - bool operator () (Event const *a, Event const *b) { return a->at > b->at; } - }; }; - typedef std::priority_queue, Event::Compare> Events; - Events events; - Impl(Public *i) : Base(i) - {} + QHash running; + duint64 counter = 0; ~Impl() { - setContext(nullptr); clear(); } void clear() { - while (!events.empty()) - { - delete events.top(); - events.pop(); - } - } - - void setContext(Record *rec) - { - if (context) context->audienceForDeletion() -= this; - context = rec; - if (context) context->audienceForDeletion() += this; + qDeleteAll(running); + running.clear(); } - void recordBeingDeleted(Record &record) + String internalName(String const &publicName) { - if (context == &record) + if (publicName.isEmpty()) { - context = nullptr; + // Choose a name automatically. + return QString("__TL%1__").arg(counter++, 0, 16); } + return publicName; } -}; - -Scheduler::Scheduler() - : d(new Impl(this)) -{} - -void Scheduler::clear() -{ - d->clear(); -} - -void Scheduler::setContext(Record &context) -{ - d->setContext(&context); -} - -Script &Scheduler::addScript(TimeDelta at, String const &source, String const &sourcePath) -{ - auto *ev = new Impl::Event(at, source, sourcePath); - d->events.push(ev); - return ev->script; -} -void Scheduler::addFromInfo(Record const &timelineRecord) -{ - auto scripts = ScriptedInfo::subrecordsOfType(ScriptedInfo::SCRIPT, timelineRecord); - for (String key : ScriptedInfo::sortRecordsBySource(scripts)) + String start(RunningTimeline *run, String const &name) { - auto const &def = *scripts[key]; - try - { - addScript(def.getd("at", 0.0), - def.gets(ScriptedInfo::SCRIPT), - ScriptedInfo::sourceLocation(def)); - } - catch (Error const &er) - { - LOG_RES_ERROR("%s: Error in timeline script: %s") - << ScriptedInfo::sourceLocation(def) - << er.asText(); - } + String const intName = internalName(name); + stop(intName); + running.insert(intName, run); + return intName; } -} - -//---------------------------------------------------------------------------- - -DENG2_PIMPL_NOREF(Scheduler::Clock) -{ - typedef Scheduler::Impl::Event Event; - typedef Scheduler::Impl::Events Events; // Events not owned - - Record *context = nullptr; - Scheduler const *scheduler = nullptr; - TimeDelta at = 0.0; - Events events; - void rewind(TimeDelta const &toTime) + void stop(String const &intName) { - at = toTime; - - // Restore events into the queue. - events = scheduler->d->events; - while (!events.empty()) + if (running.contains(intName)) { - if (events.top()->at < at) - { - events.pop(); - } - else break; + delete running[intName]; + running.remove(intName); } } - void advanceTime(TimeDelta const &elapsed) + void advanceTime(TimeSpan const &elapsed) { - at += elapsed; - - while (!events.empty()) + QMutableHashIterator iter(running); + while (iter.hasNext()) { - Event const *ev = events.top(); - if (ev->at > at) break; - - events.pop(); - - // Execute the script in the specified context. - Process process(context? context : scheduler->d->context); - process.run(ev->script); - process.execute(); + RunningTimeline *rt = iter.next().value(); + rt->clock->advanceTime(elapsed); + if (rt->clock->isFinished()) + { + delete rt; + iter.remove(); + } } } }; -Scheduler::Clock::Clock(Scheduler const &schedule, Record *context) +Scheduler::Scheduler() : d(new Impl) +{} + +void Scheduler::clear() { - d->scheduler = &schedule; - d->context = context; - d->rewind(0.0); + d->clear(); } -TimeDelta Scheduler::Clock::at() const +String Scheduler::start(Timeline *timeline, String const &name) { - return d->at; + auto *run = new Impl::RunningTimeline; + run->isOwned = true; + run->timeline = timeline; + run->clock.reset(new Timeline::Clock(*timeline, timeline->context())); + return d->start(run, name); } -void Scheduler::Clock::rewind(TimeDelta const &toTime) +String Scheduler::start(Timeline const &sharedTimeline, Record *context, String const &name) { - d->rewind(toTime); + auto *run = new Impl::RunningTimeline; + run->isOwned = false; + run->timeline = &sharedTimeline; + run->clock.reset(new Timeline::Clock(sharedTimeline, context)); + return d->start(run, name); } -void Scheduler::Clock::advanceTime(TimeDelta const &elapsed) +void Scheduler::stop(String const &name) { - d->advanceTime(elapsed); + d->stop(name); } -bool Scheduler::Clock::isFinished() const +void Scheduler::advanceTime(TimeSpan const &elapsed) { - return d->events.empty(); + d->advanceTime(elapsed); } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scopestatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scopestatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scopestatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scopestatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -75,14 +75,14 @@ void ScopeStatement::operator >> (Writer &to) const { - to << SerialId(SCOPE) << *d->identifier << *d->superRecords << d->compound; + to << dbyte(SerialId::Scope) << *d->identifier << *d->superRecords << d->compound; } void ScopeStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != SCOPE) + from.readAs(id); + if (id != SerialId::Scope) { /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scriptedinfo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scriptedinfo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scriptedinfo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scriptedinfo.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -605,8 +605,8 @@ // Text values are interpreted a bit more loosely. String const value = textValue->asText(); if (!value.compareWithoutCase("true") || - !value.compareWithoutCase("yes") || - !value.compareWithoutCase("on")) + !value.compareWithoutCase("yes") || + !value.compareWithoutCase("on")) { return true; } @@ -638,19 +638,23 @@ return defaultValue; } +bool ScriptedInfo::isFalse(String const &token) // static +{ + // Text values are interpreted a bit more loosely. + if (!token.compareWithoutCase("false") || + !token.compareWithoutCase("no") || + !token.compareWithoutCase("off")) + { + return true; + } + return false; +} + bool ScriptedInfo::isFalse(Value const &value) // static { if (TextValue const *textValue = maybeAs(value)) { - // Text values are interpreted a bit more loosely. - String const value = textValue->asText(); - if (!value.compareWithoutCase("false") || - !value.compareWithoutCase("no") || - !value.compareWithoutCase("off")) - { - return true; - } - return false; + return isFalse(textValue->asText()); } return !value.isTrue(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scriptsystem.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scriptsystem.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/scriptsystem.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/scriptsystem.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -91,7 +91,7 @@ ~Impl() { - qDeleteAll(modules.values()); + qDeleteAll(modules); } static Value *Function_ImportPath(Context &, Function::ArgumentValues const &) @@ -216,6 +216,30 @@ return *foundNative.value(); } +Record &ScriptSystem::operator[](const String &name) +{ + if (nativeModuleExists(name)) + { + return nativeModule(name); + } + // Imported modules. + { + const auto &mods = d->modules; + auto found = mods.find(name); + if (found != mods.end()) + { + return found.value()->names(); + } + } + throw NotFoundError("ScriptSystem::operator[]", "Module not found: " + name); +} + +bool ScriptSystem::nativeModuleExists(const String &name) const +{ + DENG2_GUARD_FOR(d->nativeModules, G); + return d->nativeModules.value.contains(name); +} + StringList ScriptSystem::nativeModules() const { DENG2_GUARD_FOR(d->nativeModules, G); @@ -255,7 +279,7 @@ } else if (dir == "*") { - App::fileSystem().findAll(name + ".de", matching); + App::fileSystem().findAll(name + ".ds", matching); if (matching.empty()) { continue; @@ -271,7 +295,7 @@ } if (!found) { - found = App::rootFolder().tryLocateFile(p + ".de"); + found = App::rootFolder().tryLocateFile(p + ".ds"); } if (found) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/statement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/statement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/statement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/statement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -44,57 +44,57 @@ { SerialId id; reader.mark(); - reader >> id; + reader.readAs(id); reader.rewind(); std::unique_ptr result; switch (id) { - case ASSIGN: + case SerialId::Assign: result.reset(new AssignStatement); break; - case CATCH: + case SerialId::Catch: result.reset(new CatchStatement); break; - case DELETE: + case SerialId::Delete: result.reset(new DeleteStatement); break; - case EXPRESSION: + case SerialId::Expression: result.reset(new ExpressionStatement); break; - case FLOW: + case SerialId::Flow: result.reset(new FlowStatement); break; - case FOR: + case SerialId::For: result.reset(new ForStatement); break; - case FUNCTION: + case SerialId::Function: result.reset(new FunctionStatement); break; - case IF: + case SerialId::If: result.reset(new IfStatement); break; - case PRINT: + case SerialId::Print: result.reset(new PrintStatement); break; - case TRY: + case SerialId::Try: result.reset(new TryStatement); break; - case WHILE: + case SerialId::While: result.reset(new WhileStatement); break; - case SCOPE: + case SerialId::Scope: result.reset(new ScopeStatement); break; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/timeline.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/timeline.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/timeline.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/timeline.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,209 @@ +/** @file scheduler.cpp Script scheduling utility. + * + * @authors Copyright (c) 2015-2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/Timeline" +#include "de/ScriptedInfo" +#include "de/Record" +#include "de/Script" +#include "de/Process" + +#include +#include + +namespace de { + +DENG2_PIMPL(Timeline) +, DENG2_OBSERVES(Record, Deletion) +{ + Record *context = nullptr; + + struct Event { + TimeSpan at; + Script script; + + Event(TimeSpan at, String const &source, String const &sourcePath) + : at(at) + , script(source) + { + script.setPath(sourcePath); // where the source comes from + } + + struct Compare { + bool operator () (Event const *a, Event const *b) { return a->at > b->at; } + }; + }; + typedef std::priority_queue, Event::Compare> Events; + Events events; + + Impl(Public *i) : Base(i) + {} + + ~Impl() + { + setContext(nullptr); + clear(); + } + + void clear() + { + while (!events.empty()) + { + delete events.top(); + events.pop(); + } + } + + void setContext(Record *rec) + { + if (context) context->audienceForDeletion() -= this; + context = rec; + if (context) context->audienceForDeletion() += this; + } + + void recordBeingDeleted(Record &record) + { + if (context == &record) + { + context = nullptr; + } + } +}; + +Timeline::Timeline() + : d(new Impl(this)) +{} + +void Timeline::clear() +{ + d->clear(); +} + +void Timeline::setContext(Record &context) +{ + d->setContext(&context); +} + +Record *Timeline::context() const +{ + return d->context; +} + +Script &Timeline::addScript(TimeSpan at, String const &source, String const &sourcePath) +{ + auto *ev = new Impl::Event(at, source, sourcePath); + d->events.push(ev); + return ev->script; +} + +void Timeline::addFromInfo(Record const &timelineRecord) +{ + auto scripts = ScriptedInfo::subrecordsOfType(ScriptedInfo::SCRIPT, timelineRecord); + for (String key : ScriptedInfo::sortRecordsBySource(scripts)) + { + auto const &def = *scripts[key]; + try + { + addScript(def.getd("at", 0.0), + def.gets(ScriptedInfo::SCRIPT), + ScriptedInfo::sourceLocation(def)); + } + catch (Error const &er) + { + LOG_RES_ERROR("%s: Error in timeline script: %s") + << ScriptedInfo::sourceLocation(def) + << er.asText(); + } + } +} + +//---------------------------------------------------------------------------- + +DENG2_PIMPL_NOREF(Timeline::Clock) +{ + typedef Timeline::Impl::Event Event; + typedef Timeline::Impl::Events Events; // Events not owned + + Record *context = nullptr; + Timeline const *scheduler = nullptr; + TimeSpan at = 0.0; + Events events; + + void rewind(TimeSpan const &toTime) + { + at = toTime; + + // Restore events into the queue. + events = scheduler->d->events; + while (!events.empty()) + { + if (events.top()->at < at) + { + events.pop(); + } + else break; + } + } + + void advanceTime(TimeSpan const &elapsed) + { + at += elapsed; + + while (!events.empty()) + { + Event const *ev = events.top(); + if (ev->at > at) break; + + events.pop(); + + // Execute the script in the specified context. + Process process(context? context : scheduler->d->context); + process.run(ev->script); + process.execute(); + } + } +}; + +Timeline::Clock::Clock(Timeline const &schedule, Record *context) + : d(new Impl) +{ + d->scheduler = &schedule; + d->context = context; + d->rewind(0.0); +} + +TimeSpan Timeline::Clock::at() const +{ + return d->at; +} + +void Timeline::Clock::rewind(TimeSpan const &toTime) +{ + d->rewind(toTime); +} + +void Timeline::Clock::advanceTime(TimeSpan const &elapsed) +{ + d->advanceTime(elapsed); +} + +bool Timeline::Clock::isFinished() const +{ + return d->events.empty(); +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/trystatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/trystatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/trystatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/trystatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,7 +14,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/TryStatement" @@ -31,16 +31,16 @@ void TryStatement::operator >> (Writer &to) const { - to << SerialId(TRY) << _compound; + to << dbyte(SerialId::Try) << _compound; } void TryStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != TRY) + from.readAs(id); + if (id != SerialId::Try) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("TryStatement::operator <<", "Invalid ID"); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/whilestatement.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/whilestatement.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/scriptsys/whilestatement.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/scriptsys/whilestatement.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -14,9 +14,9 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ - + #include "de/WhileStatement" #include "de/Expression" #include "de/Evaluator" @@ -49,22 +49,22 @@ void WhileStatement::operator >> (Writer &to) const { - to << SerialId(WHILE) << *_loopCondition << _compound; + to << dbyte(SerialId::While) << *_loopCondition << _compound; } void WhileStatement::operator << (Reader &from) { SerialId id; - from >> id; - if (id != WHILE) + from.readAs(id); + if (id != SerialId::While) { - /// @throw DeserializationError The identifier that species the type of the + /// @throw DeserializationError The identifier that species the type of the /// serialized statement was invalid. throw DeserializationError("WhileStatement::operator <<", "Invalid ID"); } delete _loopCondition; _loopCondition = 0; _loopCondition = Expression::constructFrom(from); - + from >> _compound; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/version.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/version.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/version.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/version.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -36,6 +36,13 @@ , build(0) {} +Version::Version(int major, int minor, int patch, int buildNumber) + : major(major) + , minor(minor) + , patch(patch) + , build(buildNumber) +{} + Version Version::currentBuild() { Version v; @@ -72,13 +79,6 @@ !label.isEmpty() || !gitDescription.isEmpty(); } -String Version::base() const -{ - String v = compactNumber(); - if (!label.isEmpty()) v += String("-%1").arg(label); - return v; -} - String Version::compactNumber() const { if (patch != 0) @@ -99,8 +99,21 @@ String Version::asHumanReadableText() const { - if (!build) return base(); - return base() + String(" [#%1]").arg(build); + String v = compactNumber(); + if (label || build) + { + v += " ("; + v += label.toLower(); + if (build) + { + v += String::format("%sbuild %d)", label ? " " : "", build); + } + else + { + v += ")"; + } + } + return v; } void Version::parseVersionString(String const &version) @@ -151,12 +164,19 @@ return !(*this < other || *this == other); } +String Version::userAgent() const +{ + return String("Doomsday Engine %1 (%2)").arg(fullNumber()).arg(operatingSystem()); +} + String Version::operatingSystem() { -#if defined(WIN32) +#if defined (WIN32) return "windows"; -#elif defined(MACOSX) +#elif defined (MACOSX) return "macx"; +#elif defined (DENG_IOS) + return "ios"; #else return "unix"; #endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/animation.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/animation.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/animation.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/animation.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -29,17 +29,23 @@ namespace internal { -static inline float easeOut(TimeDelta t) +static inline float easeOut(TimeSpan t) { return t * (2 - t); } -static inline float easeIn(TimeDelta t) +static inline float easeOutSofter(TimeSpan t) +{ + const float a = -std::pow(t - 1.0, 4) + 1; + return (easeOut(t) + a) / 2.0f; +} + +static inline float easeIn(TimeSpan t) { return t * t; } -static inline float easeBoth(TimeDelta t) +static inline float easeBoth(TimeSpan t) { if (t < .5) { @@ -80,10 +86,10 @@ { float value; float target; - TimeDelta startDelay; - Time setTime; - Time targetTime; - Time pauseTime; + TimeSpan startDelay; + TimeSpan setTime; + TimeSpan targetTime; + TimeSpan pauseTime; Style style; float spring; mutable AnimationFlags flags; @@ -92,8 +98,8 @@ : value(val) , target(val) , startDelay(0) - , setTime (Animation::currentTime()) - , targetTime(Animation::currentTime()) + , setTime (theTime.now) + , targetTime(theTime.now) , style(s) , spring(DEFAULT_SPRING) {} @@ -103,13 +109,13 @@ * @param now Point of time at which to evaluate. * @return Value of the animation when the frame time is @a now. */ - float valueAt(TimeDelta const &now) const + float valueAt(TimeSpan const &now) const { - TimeDelta span = targetTime - setTime; + TimeSpan span = targetTime - setTime; float s2 = 0; - TimeDelta peak = 0; - TimeDelta peak2 = 0; + TimeSpan peak = 0; + TimeSpan peak2 = 0; // Spring values. if (style == Bounce || style == FixedBounce) @@ -119,7 +125,7 @@ peak2 = 2.f/3; } - if (now >= targetTime.highPerformanceTime() || span <= 0) + if (now >= targetTime || span <= 0) { flags |= Finished; return target; @@ -127,14 +133,17 @@ else { span -= startDelay; - TimeDelta const elapsed = now - setTime.highPerformanceTime() - startDelay; - TimeDelta const t = clamp(0.0, elapsed/span, 1.0); + TimeSpan const elapsed = now - setTime - startDelay; + TimeSpan const t = clamp(0.0, elapsed/span, 1.0); float const delta = target - value; switch (style) { case EaseOut: return value + easeOut(t) * delta; + case EaseOutSofter: + return value + easeOutSofter(t) * delta; + case EaseIn: return value + easeIn(t) * delta; @@ -173,16 +182,16 @@ void checkDone() { - if (!(flags & Finished) && theTime.now >= targetTime.highPerformanceTime()) + if (!(flags & Finished) && currentTime() >= targetTime) { flags |= Finished; } } - Time currentTime() const + double currentTime() const { if (flags & Paused) return pauseTime; - return Animation::currentTime(); + return theTime.now; //Animation::currentTime(); } }; @@ -225,11 +234,11 @@ return d->spring; } -void Animation::setValue(float v, TimeDelta transitionSpan, TimeDelta startDelay) +void Animation::setValue(float v, TimeSpan transitionSpan, TimeSpan startDelay) { resume(); - Time const now = d->currentTime(); + TimeSpan const now = d->currentTime(); if (transitionSpan <= 0) { @@ -239,7 +248,7 @@ } else { - d->value = d->valueAt(now.highPerformanceTime()); + d->value = d->valueAt(now); d->target = v; d->setTime = now; d->targetTime = d->setTime + transitionSpan; @@ -248,12 +257,12 @@ d->startDelay = startDelay; } -void Animation::setValue(int v, TimeDelta transitionSpan, TimeDelta startDelay) +void Animation::setValue(int v, TimeSpan transitionSpan, TimeSpan startDelay) { setValue(float(v), transitionSpan, startDelay); } -void Animation::setValueFrom(float fromValue, float toValue, TimeDelta transitionSpan, TimeDelta startDelay) +void Animation::setValueFrom(float fromValue, float toValue, TimeSpan transitionSpan, TimeSpan startDelay) { setValue(fromValue); setValue(toValue, transitionSpan, startDelay); @@ -263,7 +272,7 @@ { if (d->flags & Paused) { - return d->valueAt(d->pauseTime.highPerformanceTime()); + return d->valueAt(d->pauseTime); } if (d->flags & Finished) { @@ -276,10 +285,6 @@ { d->checkDone(); if (d->flags & Finished) return true; - if (d->flags & Paused) - { - return d->pauseTime >= d->targetTime; - } return false; } @@ -293,9 +298,9 @@ d->target = newTarget; } -TimeDelta Animation::remainingTime() const +TimeSpan Animation::remainingTime() const { - Time const now = d->currentTime(); + TimeSpan const now = d->currentTime(); if (now >= d->targetTime) { return 0; @@ -303,7 +308,7 @@ return d->targetTime - now; } -TimeDelta Animation::transitionTime() const +TimeSpan Animation::transitionTime() const { return d->targetTime - d->setTime; } @@ -328,7 +333,7 @@ d->flags &= ~Paused; - TimeDelta const delta = d->currentTime() - d->pauseTime; + TimeSpan const delta = d->currentTime() - d->pauseTime; d->setTime += delta; d->targetTime += delta; } @@ -340,7 +345,7 @@ String Animation::asText() const { - return String("Animation(%1 -> %2, ETA:%3 s)").arg(d->value).arg(d->target).arg(remainingTime()); + return String("Animation(%1 -> %2, ETA:%3 s; curr: %4)").arg(d->value).arg(d->target).arg(remainingTime()).arg(value()); } Clock const &Animation::clock() @@ -355,7 +360,7 @@ void Animation::operator >> (Writer &to) const { - Time const now = currentTime(); + TimeSpan const now = currentTime(); to << d->value << d->target; // Write times relative to current frame time. @@ -366,12 +371,12 @@ void Animation::operator << (Reader &from) { - Time const now = currentTime(); + TimeSpan const now = currentTime(); from >> d->value >> d->target; // Times are relative to current frame time. - TimeDelta relSet, relTarget; + TimeSpan relSet, relTarget; from >> relSet >> relTarget; d->setTime = now + relSet; @@ -385,25 +390,25 @@ from >> d->spring; } - + void Animation::setClock(Clock const *clock) { if (_clock) _clock->audienceForPriorityTimeChange -= theTime; _clock = clock; if (clock) clock->audienceForPriorityTimeChange += theTime; } - -Time Animation::currentTime() // static + +TimeSpan Animation::currentTime() // static { DENG2_ASSERT(_clock != 0); if (!_clock) { throw ClockMissingError("Animation::clock", "Animation has no clock"); } - return Time(theTime.now); + return TimeSpan(theTime.now); } -Animation Animation::range(Style style, float from, float to, TimeDelta span, TimeDelta delay) +Animation Animation::range(Style style, float from, float to, TimeSpan span, TimeSpan delay) { Animation anim(from, style); anim.setValue(to, span, delay); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/animationrule.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/animationrule.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/animationrule.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/animationrule.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -30,7 +30,7 @@ , _behavior(Singleshot) {} -AnimationRule::AnimationRule(Rule const &target, TimeDelta transition, Animation::Style style) +AnimationRule::AnimationRule(Rule const &target, TimeSpan transition, Animation::Style style) : Rule(target.value()) , _animation(target.value(), style) , _targetRule(0) @@ -44,18 +44,16 @@ independentOf(_targetRule); } -void AnimationRule::set(float target, TimeDelta transition, TimeDelta delay) +void AnimationRule::set(float target, TimeSpan transition, TimeSpan delay) { independentOf(_targetRule); _targetRule = 0; - _animation.clock().audienceForPriorityTimeChange += this; - _animation.setValue(target, transition, delay); invalidate(); } -void AnimationRule::set(Rule const &target, TimeDelta transition, TimeDelta delay) +void AnimationRule::set(Rule const &target, TimeSpan transition, TimeSpan delay) { set(target.value(), transition, delay); @@ -107,12 +105,14 @@ String AnimationRule::description() const { - String desc = "Scalar(" + _animation.asText(); + DENG2_ASSERT(!isValid() || fequal(value(), _animation)); + + String desc = _animation.asText(); if (_targetRule) { - desc += "; target: " + _targetRule->description(); + desc += "=>" + _targetRule->description(); } - return desc + ")"; + return desc; } void AnimationRule::update() @@ -129,7 +129,7 @@ // Start a new animation with the previously used transition time. if (!fequal(_animation.target(), _targetRule->value())) { - TimeDelta span = _animation.transitionTime(); + TimeSpan span = _animation.transitionTime(); if (_behavior.testFlag(DontAnimateFromZero) && fequal(_animation.target(), 0)) { span = 0; @@ -141,16 +141,16 @@ } setValue(_animation); -} - -void AnimationRule::timeChanged(Clock const &clock) -{ - invalidate(); if (_animation.done()) { - clock.audienceForPriorityTimeChange -= this; + _animation.clock().audienceForPriorityTimeChange -= this; } } +void AnimationRule::timeChanged(const Clock &) +{ + invalidate(); +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/constantrule.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/constantrule.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/constantrule.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/constantrule.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -44,7 +44,7 @@ String ConstantRule::description() const { - return String("Constant(%1)").arg(cachedValue()); + return String::format("%g", cachedValue()); } ConstantRule const &ConstantRule::zero() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/indirectrule.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/indirectrule.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/indirectrule.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/indirectrule.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -20,7 +20,7 @@ namespace de { -IndirectRule::IndirectRule() : _source(0) +IndirectRule::IndirectRule() : _source(nullptr) {} IndirectRule::~IndirectRule() @@ -32,26 +32,29 @@ { unsetSource(); dependsOn(_source = &rule); - invalidate(); } void IndirectRule::unsetSource() { independentOf(_source); - _source = 0; - + _source = nullptr; invalidate(); } +bool IndirectRule::hasSource() const +{ + return _source != nullptr; +} + void IndirectRule::update() { - setValue(_source? _source->value() : 0); + setValue(_source ? _source->value() : 0.f); } Rule const &IndirectRule::source() const { - DENG2_ASSERT(_source != 0); + DENG2_ASSERT(_source); return *_source; } @@ -63,7 +66,7 @@ } else { - return String("(null)"); + return String("[0]"); } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rootwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rootwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rootwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rootwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -97,6 +97,10 @@ void RootWidget::setViewSize(Size const &size) { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif + d->viewRect->setInput(Rule::Right, Constu(size.x)); d->viewRect->setInput(Rule::Bottom, Constu(size.y)); @@ -139,23 +143,35 @@ void RootWidget::initialize() { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif notifyTree(&Widget::initialize); } void RootWidget::update() { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif notifyTree(&Widget::update); } void RootWidget::draw() { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif notifyTree(notifyArgsForDraw()); - Rule::markRulesValid(); // All done for this frame. } bool RootWidget::processEvent(Event const &event) { +#if defined (DENG_MOBILE) + DENG2_GUARD(this); +#endif + // Focus is only for the keyboard. if (event.isKey() && focus()) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rulebank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rulebank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rulebank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rulebank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -18,40 +18,52 @@ #include "de/RuleBank" #include +#include #include namespace de { -DotPath const RuleBank::UNIT("unit"); +const DotPath RuleBank::UNIT("unit"); DENG2_PIMPL_NOREF(RuleBank) { + const Rule *dpiRule = nullptr; + struct RuleSource : public ISource { - InfoBank &bank; + RuleBank &bank; String id; - RuleSource(InfoBank &b, String const &ruleId) : bank(b), id(ruleId) {} + RuleSource(RuleBank &b, String const &ruleId) : bank(b), id(ruleId) {} Time modifiedAt() const { return bank.sourceModifiedAt(); } - Rule *load() const + const Rule &load() const { Record const &def = bank[id]; - return refless(new ConstantRule(def["constant"].value().asNumber())); + return *bank.d->dpiRule * float(def["constant"].value().asNumber()); } }; struct RuleData : public IData { - Rule *rule; + const Rule *rule; - RuleData(Rule *r) : rule(holdRef(r)) {} + RuleData(const Rule &r) : rule(holdRef(r)) {} ~RuleData() { releaseRef(rule); } }; + + ~Impl() + { + releaseRef(dpiRule); + } }; -RuleBank::RuleBank() : InfoBank("RuleBank", DisableHotStorage), d(new Impl) -{} +RuleBank::RuleBank(const Rule &dpiRule) + : InfoBank("RuleBank", DisableHotStorage) + , d(new Impl) +{ + d->dpiRule = holdRef(dpiRule); +} void RuleBank::addFromInfo(File const &file) { @@ -66,6 +78,11 @@ return *static_cast(data(path)).rule; } +const Rule &RuleBank::dpiRule() const +{ + return *d->dpiRule; +} + Bank::ISource *RuleBank::newSourceFromInfo(String const &id) { return new Impl::RuleSource(*this, id); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rulerectangle.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rulerectangle.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/rulerectangle.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/rulerectangle.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -339,6 +339,11 @@ return *this; } +RuleRectangle &RuleRectangle::setSize(ISizeRule const &dimensions) +{ + return setSize(dimensions.width(), dimensions.height()); +} + RuleRectangle &RuleRectangle::setMidAnchorX(Rule const &middle) { setInput(Rule::AnchorX, middle); @@ -365,7 +370,7 @@ return *d->ruleRef(inputRule); } -void RuleRectangle::setAnchorPoint(Vector2f const &normalizedPoint, TimeDelta const &transition) +void RuleRectangle::setAnchorPoint(Vector2f const &normalizedPoint, TimeSpan const &transition) { d->normalizedAnchorX()->set(normalizedPoint.x, transition); d->normalizedAnchorY()->set(normalizedPoint.y, transition); @@ -404,13 +409,25 @@ d->debugName = name; } +bool RuleRectangle::isFullyDefined() const +{ + for (const auto *out : d->outputRules) + { + if (!out->hasSource()) + { + return false; + } + } + return true; +} + String RuleRectangle::description() const { String desc = QString("RuleRectangle '%1'").arg(d->debugName); for (int i = 0; i < int(Rule::MAX_SEMANTICS); ++i) { - desc += String("\n - ") + + desc += String("\n INPUT ") + (i == Rule::Left? "Left" : i == Rule::Top? "Top" : i == Rule::Right? "Right" : @@ -421,13 +438,26 @@ if (d->inputRules[i]) { + desc += String::format("(%g) ", d->inputRules[i]->value()); desc += d->inputRules[i]->description(); } else { - desc += "(null)"; + desc += "(not set)"; } } + for (int i = 0; i < Impl::MAX_OUTPUT_RULES; ++i) + { + desc += String::format("\n OUTPUT %s: ", + i == Impl::OutLeft ? "Left" + : i == Impl::OutTop ? "Top" + : i == Impl::OutRight ? "Right" + : i == Impl::OutBottom ? "Bottom" + : i == Impl::OutWidth ? "Width" + : "Height"); + desc += String::format("(%g) ", d->outputRules[i]->value()); + desc += d->outputRules[i]->description(); + } return desc; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/widget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/widget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libcore/src/widgets/widget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libcore/src/widgets/widget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -19,6 +19,8 @@ #include "de/Widget" #include "de/RootWidget" +#include "de/Asset" +#include "de/LogBuffer" #include #include @@ -29,6 +31,7 @@ Id id; String name; Widget *parent = nullptr; + std::unique_ptr names; // IObject RootWidget *manualRoot = nullptr; Behaviors behavior; String focusNext; @@ -755,6 +758,39 @@ return false; } +void Widget::waitForAssetsReady() +{ + AssetGroup assets; + collectNotReadyAssets(assets, CollectMode::OnlyVisible); + if (!assets.isEmpty()) + { + assets.waitForState(Asset::Ready); + } +} + +void Widget::collectNotReadyAssets(AssetGroup &collected, CollectMode collectMode) +{ + if (collectMode == CollectMode::OnlyVisible && behavior().testFlag(Hidden)) + { + return; + } + if (auto *assetGroup = maybeAs(this)) + { + if (!assetGroup->assets().isReady()) + { + collected += *assetGroup; + LOGDEV_XVERBOSE("Found " _E(m) "NotReady" _E(.) " asset %s (%p)", path() << this); + } + } + else + { + foreach (Widget *child, children()) + { + child->collectNotReadyAssets(collected, collectMode); + } + } +} + Widget::Children Widget::children() const { return d->children; @@ -801,6 +837,20 @@ return false; } +Record &Widget::objectNamespace() +{ + if (!d->names) + { + d->names.reset(new Record); + } + return *d->names; +} + +const Record &Widget::objectNamespace() const +{ + return const_cast(this)->objectNamespace(); +} + void Widget::setFocusCycle(WidgetList const &order) { for (int i = 0; i < order.size(); ++i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/CMakeLists.txt 2018-12-11 07:08:24.000000000 +0000 @@ -66,7 +66,7 @@ endif () if (APPLE) - # Don't change display modes on macOS. We'll instead resize the + # Don't change display modes on macOS/iOS. We'll instead resize the # frame buffer and scale up. set (DENG_ENABLE_DISPLAYMODE_DEFAULT OFF) else () @@ -76,6 +76,13 @@ ${DENG_ENABLE_DISPLAYMODE_DEFAULT} ) +# OpenGL API selection. +set (DENG_OPENGL_API "3.3" CACHE STRING "OpenGL API selection (3.3, GLES3, GLES2)") + +if (IOS) + set (DENG_OPENGL_API "GLES3" CACHE STRING "OpenGL API selection" FORCE) +endif () + # Dependencies. find_package (DengCore) find_package (Assimp REQUIRED) @@ -87,6 +94,18 @@ # Definitions. add_definitions (-D__LIBGUI__=1) +if (DENG_OPENGL_API STREQUAL "3.3") + add_definitions (-DDENG_OPENGL=330) + message (STATUS "Using OpenGL 3.3") +elseif (DENG_OPENGL_API STREQUAL "GLES3") + add_definitions (-DDENG_OPENGL_ES=30) + message (STATUS "Using OpenGL ES 3.0") +elseif (DENG_OPENGL_API STREQUAL "GLES2") + add_definitions (-DDENG_OPENGL_ES=20) + message (STATUS "Using OpenGL ES 2.0") +else () + message (FATAL_ERROR "Invalid value for OpenGL API: ${DENG_OPENGL_API}") +endif () # Source and header files. file (GLOB_RECURSE HEADERS include/de/*) @@ -105,6 +124,10 @@ list (APPEND SOURCES src/displaymode_${DENG_PLATFORM_SUFFIX}) endif () +# Ignore mobile-only sources. +list_remove_matches (HEADERS ".*_qml.*") +list_remove_matches (SOURCES ".*_qml.*") + deng_add_library (libgui ${SOURCES} ${HEADERS}) target_link_libraries (libgui @@ -121,7 +144,9 @@ target_link_libraries (libgui PUBLIC ${assimpLibs}) endif () -if (APPLE) +if (IOS) + link_framework (libgui PRIVATE OpenGLES) +elseif (APPLE) link_framework (libgui PRIVATE Cocoa) link_framework (libgui PRIVATE OpenGL) endif () diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/audio/waveform.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/audio/waveform.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/audio/waveform.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/audio/waveform.h 2018-12-11 07:08:24.000000000 +0000 @@ -96,7 +96,7 @@ * Playing duration of the audio waveform, assuming sample count and sample rate * are known. */ - TimeDelta duration() const; + TimeSpan duration() const; private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/GLWindow doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/GLWindow --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/GLWindow 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/GLWindow 2018-12-11 07:08:24.000000000 +0000 @@ -1 +1,6 @@ -#include "gui/glwindow.h" +#if defined (DENG_MOBILE) +# include "gui/glwindow_qml.h" +#else +# include "gui/glwindow.h" +#endif + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glbuffer.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glbuffer.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glbuffer.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glbuffer.h 2018-12-11 07:08:24.000000000 +0000 @@ -286,6 +286,8 @@ void setIndices(gl::Primitive primitive, Indices const &indices, gl::Usage usage); + void setData(void const *data, dsize dataSize, gl::Usage usage); + void setData(dsize startOffset, void const *data, dsize dataSize); void setUninitializedData(dsize dataSize, gl::Usage usage); @@ -301,6 +303,8 @@ void drawWithIndices(GLBuffer const &indexBuffer) const; + void drawWithIndices(gl::Primitive primitive, Index const *indices, dsize count) const; + /** * Draws the buffer with instancing. One instance of the buffer is drawn per * each element in the provided @a instanceAttribs buffer. @@ -321,6 +325,8 @@ void setFormat(internal::AttribSpecs const &format); + GLuint glName() const; + static duint drawCount(); static void resetDrawCount(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/gldrawqueue.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/gldrawqueue.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/gldrawqueue.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/gldrawqueue.h 2018-12-11 07:08:24.000000000 +0000 @@ -47,6 +47,8 @@ public: GLDrawQueue(); + void beginFrame(); + void setProgram(GLProgram &program, Block const &batchUniformName = Block(), GLUniform::Type batchUniformType = GLUniform::Float); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glinfo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glinfo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glinfo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glinfo.h 2018-12-11 07:08:24.000000000 +0000 @@ -20,21 +20,21 @@ #define LIBGUI_GLINFO_H #include +#include // checking for render thread +#include #include "../gui/libgui.h" #include "de/graphics/opengl.h" #define LIBGUI_GL de::GLInfo::api() #ifndef NDEBUG -# define LIBGUI_ASSERT_GL_OK() {GLuint _er = GL_NO_ERROR; do { \ - _er = LIBGUI_GL.glGetError(); if (_er != GL_NO_ERROR) { \ - LogBuffer_Flush(); qWarning(__FILE__":%i: OpenGL error: 0x%x (%s)", __LINE__, _er, \ - LIBGUI_GL_ERROR_STR(_er)); LIBGUI_ASSERT_GL(0!="OpenGL operation failed"); \ - }} while (_er != GL_NO_ERROR);} +# define LIBGUI_ASSERT_GL_OK() de::GLInfo::checkError(__FILE__, __LINE__) #else # define LIBGUI_ASSERT_GL_OK() #endif +#define LIBGUI_ASSERT_GL_CONTEXT_ACTIVE() DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr) + namespace de { /** @@ -50,28 +50,30 @@ /// Extension availability bits. struct Extensions { - duint32 ARB_draw_instanced : 1; - duint32 ARB_instanced_arrays : 1; - duint32 ARB_texture_env_combine : 1; - duint32 ARB_texture_non_power_of_two : 1; - - duint32 EXT_blend_subtract : 1; - duint32 EXT_framebuffer_blit : 1; - duint32 EXT_framebuffer_multisample : 1; - duint32 EXT_framebuffer_object : 1; - duint32 EXT_packed_depth_stencil : 1; + //duint32 ARB_draw_instanced : 1; + //duint32 ARB_instanced_arrays : 1; + //duint32 ARB_texture_env_combine : 1; + //duint32 ARB_texture_non_power_of_two : 1; + + //duint32 EXT_blend_subtract : 1; + //duint32 EXT_framebuffer_blit : 1; + //duint32 EXT_framebuffer_multisample : 1; + //duint32 EXT_framebuffer_object : 1; + //duint32 EXT_packed_depth_stencil : 1; duint32 EXT_texture_compression_s3tc : 1; duint32 EXT_texture_filter_anisotropic : 1; - duint32 EXT_timer_query : 1; + //duint32 EXT_timer_query : 1; // Vendor-specific extensions: - duint32 ATI_texture_env_combine3 : 1; + //duint32 ATI_texture_env_combine3 : 1; duint32 NV_framebuffer_multisample_coverage : 1; - duint32 NV_texture_env_combine4 : 1; - duint32 SGIS_generate_mipmap : 1; + //duint32 NV_texture_env_combine4 : 1; + //duint32 SGIS_generate_mipmap : 1; + + duint32 KHR_debug : 1; #ifdef WIN32 - duint32 Windows_ARB_multisample : 1; + //duint32 Windows_ARB_multisample : 1; duint32 Windows_EXT_swap_control : 1; #endif @@ -85,9 +87,11 @@ /// Implementation limits. struct Limits { - int maxTexFilterAniso; - int maxTexSize; ///< Texels. - int maxTexUnits; + int maxTexFilterAniso = 0; + int maxTexSize = 0; ///< Texels. + int maxTexUnits = 0; + Rangef smoothLineWidth; + float smoothLineWidthGranularity = 0.f; }; GLInfo(); @@ -108,15 +112,20 @@ static QOpenGLFunctions_Doomsday &api(); // Extensions: - static QOpenGLExtension_ARB_draw_instanced *ARB_draw_instanced(); - static QOpenGLExtension_ARB_instanced_arrays *ARB_instanced_arrays(); - static QOpenGLExtension_EXT_framebuffer_blit *EXT_framebuffer_blit(); - static QOpenGLExtension_EXT_framebuffer_multisample *EXT_framebuffer_multisample(); - static QOpenGLExtension_EXT_framebuffer_object *EXT_framebuffer_object(); + //static QOpenGLExtension_ARB_draw_instanced *ARB_draw_instanced(); + //static QOpenGLExtension_ARB_instanced_arrays *ARB_instanced_arrays(); + //static QOpenGLExtension_EXT_framebuffer_blit *EXT_framebuffer_blit(); + //static QOpenGLExtension_EXT_framebuffer_multisample *EXT_framebuffer_multisample(); + //static QOpenGLExtension_EXT_framebuffer_object *EXT_framebuffer_object(); +#if defined (DENG_OPENGL) static QOpenGLExtension_NV_framebuffer_multisample_coverage *NV_framebuffer_multisample_coverage(); +#endif static void setSwapInterval(int interval); +// static void setLineWidth(float lineWidth); + + static void checkError(char const *file, int line); private: DENG2_PRIVATE(d) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glprogram.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glprogram.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glprogram.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glprogram.h 2018-12-11 07:08:24.000000000 +0000 @@ -119,6 +119,8 @@ */ int attributeLocation(internal::AttribSpec::Semantic semantic) const; + bool validate() const; + private: DENG2_PRIVATE(d) }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glshaderbank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glshaderbank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glshaderbank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glshaderbank.h 2018-12-11 07:08:24.000000000 +0000 @@ -61,6 +61,14 @@ */ GLProgram &build(GLProgram &program, DotPath const &path) const; + /** + * Sets additional preprocessor symbols to insert to compiled shaders. + * These are in addition to any defines in the shader definition itself. + * + * @param preDefines Preprocessor defines. + */ + void setPreprocessorDefines(const DictionaryValue &preDefines); + protected: ISource *newSourceFromInfo(String const &id); IData *loadFromSource(ISource &source); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glshader.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glshader.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glshader.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glshader.h 2018-12-11 07:08:24.000000000 +0000 @@ -63,7 +63,7 @@ void compile(Type shaderType, IByteArray const &source); - void recompile(); +// void recompile(); /** * Prefixes a piece of shader source code to another shader source. This takes diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glstate.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glstate.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/glstate.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/glstate.h 2018-12-11 07:08:24.000000000 +0000 @@ -108,7 +108,8 @@ GLState(); GLState(GLState const &other); - GLState &operator = (GLState const &other); + GLState &operator=(GLState const &other); + bool operator==(const GLState &); GLState &setCull(gl::Cull mode); GLState &setDepthTest(bool enable); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/gluniform.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/gluniform.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/gluniform.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/gluniform.h 2018-12-11 07:08:24.000000000 +0000 @@ -63,7 +63,9 @@ Mat4, Sampler2D, SamplerCube, + IntArray, FloatArray, + Vec2Array, Vec3Array, Vec4Array, Mat4Array @@ -109,14 +111,19 @@ GLUniform &operator = (GLTexture const *texture); GLUniform &set(duint elementIndex, dfloat value); + GLUniform &set(duint elementIndex, dint value); + GLUniform &set(duint elementIndex, Vector2f const &vec); GLUniform &set(duint elementIndex, Vector3f const &vec); GLUniform &set(duint elementIndex, Vector4f const &vec); GLUniform &set(duint elementIndex, Matrix4f const &mat); GLUniform &setUsedElementCount(duint elementCount); + GLUniform &set(dint const *intArray, dsize count); GLUniform &set(float const *floatArray, dsize count); + GLUniform &set(Vector2f const *vectorArray, dsize count); GLUniform &set(Vector4f const *vectorArray, dsize count); + GLUniform &set(Matrix4f const *mat4Array, dsize count); operator dint() const { return toInt(); } operator duint() const { return toUInt(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/imagebank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/imagebank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/imagebank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/imagebank.h 2018-12-11 07:08:24.000000000 +0000 @@ -50,7 +50,7 @@ void add(DotPath const &path, String const &imageFilePath); void addFromInfo(File const &file); - Image const &image(DotPath const &path) const; + const Image &image(DotPath const &path) const; protected: ISource *newSourceFromInfo(String const &id); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/image.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/image.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/image.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/image.h 2018-12-11 07:08:24.000000000 +0000 @@ -90,14 +90,16 @@ Image &operator = (Image const &other); Image &operator = (QImage const &other); + inline explicit operator bool() const { return !isNull(); } + Format format() const; QImage::Format qtFormat() const; Size size() const; Rectanglei rect() const; - duint width() const { return size().x; } - duint height() const { return size().y; } + inline duint width() const { return size().x; } + inline duint height() const { return size().y; } /** * Number of bits per pixel. @@ -141,6 +143,16 @@ GLPixelFormat glFormat() const; + /** + * Returns the ratio of how many points there are for each image pixel. + * This can be used to scale the image appropriately for the UI. + * + * @return Points per image pixel. + */ + float pointRatio() const; + + void setPointRatio(float pointsPerPixel); + // Drawing/editing methods. Image subImage(Rectanglei const &subArea) const; void resize(Size const &size); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/modeldrawable.h 2018-12-11 07:08:24.000000000 +0000 @@ -247,7 +247,7 @@ * * @param elapsed Duration of elapsed time. */ - virtual void advanceTime(TimeDelta const &elapsed); + virtual void advanceTime(TimeSpan const &elapsed); /** * Returns the time to be used when drawing the model. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/opengl.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/opengl.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/opengl.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/opengl.h 2018-12-11 07:08:24.000000000 +0000 @@ -25,23 +25,38 @@ # error "glDeleteTextures defined as a macro! (would be undefined by Qt)" #endif -#include -#include - -#define QOpenGLFunctions_Doomsday QOpenGLFunctions_2_1 +/* + * OpenGL API selection + */ +#if (DENG_OPENGL == 330) +# include +# include +# define QOpenGLFunctions_Doomsday QOpenGLFunctions_3_3_Core +# ifndef GL_VERSION_3_3 +# error "OpenGL 3.3 (or newer) headers not found" +# endif +# define DENG_HAVE_TIMER_QUERY + +#elif (DENG_OPENGL_ES == 30) +# include +# include +# define QOpenGLFunctions_Doomsday QOpenGLExtraFunctions + +#elif (DENG_OPENGL_ES == 20) +# include +# include +# define QOpenGLFunctions_Doomsday QOpenGLFunctions +#endif // Defined in GLES2. #ifndef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS # define GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS 0x8CD9 #endif -/* - * The LIBGUI_GLES2 macro is defined when the OpenGL ES 2.0 API is in use. - */ -//#define LIBGUI_GLES2 - -#ifndef GL_VERSION_2_1 -# error "OpenGL 2.1 (or newer) headers not found" +#if !defined (DENG_OPENGL_ES) || DENG_OPENGL_ES > 20 +# define DENG_HAVE_VAOS +# define DENG_HAVE_INSTANCES +# define DENG_HAVE_BLIT_FRAMEBUFFER #endif #endif // LIBGUI_SYSTEM_OPENGL_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/packageiconbank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/packageiconbank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/packageiconbank.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/packageiconbank.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,69 @@ +/** @file packageiconbank.h Bank for package icons. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBGUI_PACKAGEICONBANK_H +#define LIBGUI_PACKAGEICONBANK_H + +#include "../TextureBank" +#include + +namespace de { + +/** + * Bank for package icons. + * + * Before use, PackageIconBank must be told which atlas the icons are stored. + * + * Loaded icons are resized to a size suitable for use in package lists before they + * are allocated on the UI atlas. + */ +class LIBGUI_PUBLIC PackageIconBank : public TextureBank +{ +public: + typedef Vector2ui Size; + + PackageIconBank(); + + /** + * Sets the display size for icons (in pixels). Icon images are resized to this + * size before allocating on the atlas. + * + * @param iconDisplaySize Display size for icons. + */ + void setDisplaySize(Size const &displaySize); + + bool packageContainsIcon(const File &packageFile) const; + + /** + * Returns the ID of a package icon, if one is loaded and available in the atlas. + * If the icon is not yet available, loading it is requested. The caller can use + * the Bank's Load notification to observe when the icon is available. + * + * @param packageFile Package whose icon to fetch. + * + * @return Allocation ID, or Id::None. + */ + Id packageIcon(const File &packageFile); + +private: + DENG2_PRIVATE(d) +}; + +} // namespace de + +#endif // LIBGUI_PACKAGEICONBANK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/texturebank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/texturebank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/graphics/texturebank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/graphics/texturebank.h 2018-12-11 07:08:24.000000000 +0000 @@ -51,7 +51,8 @@ }; public: - TextureBank(); + TextureBank(char const *nameForLog = "TextureBank", + Flags const &flags = DefaultFlags); /** * Sets the atlas where the images are to be allocated from. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/glwindow.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/glwindow.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/glwindow.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/glwindow.h 2018-12-11 07:08:24.000000000 +0000 @@ -26,6 +26,11 @@ #include #include #include + +#if defined (DENG_MOBILE) +# error "glwindow.h is for desktop platforms (use glwindow_qml.h instead)" +#endif + #include #ifdef WIN32 @@ -48,7 +53,7 @@ typedef Vector2ui Size; /** - * Notified when the canvas's GL state needs to be initialized. The OpenGL + * Notified when the window's GL state needs to be initialized. The OpenGL * context and drawing surface are not ready before this occurs. This gets * called immediately before drawing the contents of the WindowEventHandler for the * first time (during a paint event). @@ -56,12 +61,17 @@ DENG2_DEFINE_AUDIENCE2(Init, void windowInit(GLWindow &)) /** - * Notified when a canvas's size has changed. + * Notified when a window size has changed. */ DENG2_DEFINE_AUDIENCE2(Resize, void windowResized(GLWindow &)) /** - * Notified when the contents of the canvas have been swapped to the window front + * Notified when the window pixel ratio has changed. + */ + DENG2_DEFINE_AUDIENCE2(PixelRatio, void windowPixelRatioChanged(GLWindow &)) + + /** + * Notified when the contents of the window have been swapped to the window front * buffer and are thus visible to the user. */ DENG2_DEFINE_AUDIENCE2(Swap, void windowSwapped(GLWindow &)) @@ -78,6 +88,7 @@ bool isHidden() const; float frameRate() const; + uint frameCount() const; /** * Determines the current top left corner (origin) of the window. @@ -86,6 +97,7 @@ Size pointSize() const; Size pixelSize() const; + double pixelRatio() const; int pointWidth() const; int pointHeight() const; @@ -96,7 +108,7 @@ int height() const = delete; /** - * Returns a render target that renders to this canvas. + * Returns a render target that renders to this window. * * @return GL render target. */ @@ -131,7 +143,7 @@ bool grabToFile(NativePath const &path) const; /** - * Grabs the contents of the canvas framebuffer. + * Grabs the contents of the window framebuffer. * * @param outputSize If specified, the contents will be scaled to this size before * the image is returned. @@ -141,7 +153,7 @@ QImage grabImage(QSize const &outputSize = QSize()) const; /** - * Grabs a portion of the contents of the canvas framebuffer. + * Grabs a portion of the contents of the window framebuffer. * * @param area Portion to grab. * @param outputSize If specified, the contents will be scaled to this size before diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/glwindow_qml.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/glwindow_qml.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/glwindow_qml.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/glwindow_qml.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,280 @@ +/** @file glwindow_ios.h Top-level OpenGL window (QML item). + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBGUI_GLWINDOW_IOS_H +#define LIBGUI_GLWINDOW_IOS_H + +#if !defined (DENG_MOBILE) +# error "glwindow_qml.h is only for mobile platforms" +#endif + +#include "../WindowEventHandler" +#include "../GLTextureFramebuffer" + +#include +#include +#include + +#include + +namespace de { + +/** + * Top-level UI item that paints onto the OpenGL drawing surface. @ingroup gui + */ +class LIBGUI_PUBLIC GLWindow : public QObject, public Asset +{ + Q_OBJECT + +public: + typedef Vector2ui Size; + + /** + * Notified when the canvas's GL state needs to be initialized. The OpenGL + * context and drawing surface are not ready before this occurs. This gets + * called immediately before drawing the contents of the WindowEventHandler for the + * first time (during a paint event). + */ + DENG2_DEFINE_AUDIENCE2(Init, void windowInit(GLWindow &)) + + /** + * Notified when a canvas's size has changed. + */ + DENG2_DEFINE_AUDIENCE2(Resize, void windowResized(GLWindow &)) + + /** + * Notified when the contents of the canvas have been swapped to the window front + * buffer and are thus visible to the user. + */ + DENG2_DEFINE_AUDIENCE2(Swap, void windowSwapped(GLWindow &)) + + DENG2_CAST_METHODS() + +public: + GLWindow(); + + void setWindow(QQuickWindow *window); + void setOpenGLContext(QOpenGLContext *context); + + void setTitle(QString const &title); + QSurfaceFormat format() const; + double devicePixelRatio() const; + void makeCurrent(); + void doneCurrent(); + Rectanglei windowRect() const; + Size fullscreenSize() const; + void hide(); + void update(); + + bool isGLReady() const; + bool isFullScreen() const; + bool isMaximized() const; + bool isMinimized() const; + bool isVisible() const; + bool isHidden() const; + + float frameRate() const; + uint frameCount() const; + + /** + * Determines the current top left corner (origin) of the window. + */ + inline Vector2i pos() const { return Vector2i(); } + + Size pointSize() const; + Size pixelSize() const; + + int pointWidth() const; + int pointHeight() const; + int pixelWidth() const; + int pixelHeight() const; + + int width() const = delete; + int height() const = delete; + + /** + * Returns a render target that renders to this canvas. + * + * @return GL render target. + */ + GLFramebuffer &framebuffer() const; + + WindowEventHandler &eventHandler() const; + + /** + * Determines if a WindowEventHandler instance is owned by this window. + * + * @param handler WindowEventHandler instance. + * + * @return @c true or @c false. + */ + bool ownsEventHandler(WindowEventHandler *handler) const; + + enum GrabMode + { + GrabNormal, + GrabHalfSized + }; + + /** + * Grabs the contents of the window and saves it into a native image file. + * + * @param path Name of the file to save. May include a file extension + * that indicates which format to use (e.g, "screenshot.jpg"). + * If omitted, defaults to PNG. + * + * @return @c true if successful, otherwise @c false. + */ + bool grabToFile(NativePath const &path) const; + + /** + * Grabs the contents of the canvas framebuffer. + * + * @param outputSize If specified, the contents will be scaled to this size before + * the image is returned. + * + * @return Framebuffer contents (no alpha channel). + */ + QImage grabImage(QSize const &outputSize = QSize()) const; + + /** + * Grabs a portion of the contents of the canvas framebuffer. + * + * @param area Portion to grab. + * @param outputSize If specified, the contents will be scaled to this size before + * the image is returned. + * + * @return Framebuffer contents (no alpha channel). + */ + QImage grabImage(QRect const &area, QSize const &outputSize = QSize()) const; + + /** + * Activates the window's GL context so that OpenGL API calls can be made. + * The GL context is automatically active during the drawing of the window's + * contents; at other times it needs to be manually activated. + */ + void glActivate(); + + /** + * Dectivates the window's GL context after OpenGL API calls have been done. + * The GL context is automatically deactived after the drawing of the window's + * contents; at other times it needs to be manually deactivated. + */ + void glDone(); + + /** + * Returns a handle to the native window instance. (Platform-specific.) + */ + void *nativeHandle() const; + + void initializeGL(); + void resizeGL(int w, int h); + + virtual void draw() = 0; + +public: + static bool mainExists(); + static GLWindow &main(); + static void glActiveMain(); + static void setMain(GLWindow *window); + +protected: + virtual void windowAboutToClose(); + + /* + // Native events. + void resizeEvent (QResizeEvent *ev) override; + void focusInEvent (QFocusEvent *ev) override; + void focusOutEvent (QFocusEvent *ev) override; + void keyPressEvent (QKeyEvent *ev) override; + void keyReleaseEvent (QKeyEvent *ev) override; + void mousePressEvent (QMouseEvent *ev) override; + void mouseReleaseEvent (QMouseEvent *ev) override; + void mouseDoubleClickEvent (QMouseEvent *ev) override; + void mouseMoveEvent (QMouseEvent *ev) override; + void wheelEvent (QWheelEvent *ev) override; + + bool event(QEvent *) override; + */ + +signals: + void textEntryRequest(); + void textEntryDismiss(); + void userEnteredText(QString); + void userFinishedTextEntry(); + void rootDimensionsChanged(QRect); + +public slots: + void paintGL(); + void frameWasSwapped(); + +private: + DENG2_PRIVATE(d) +}; + +/** + * Performs OpenGL rendering primarily in the Qt render thread. + */ +class GLQuickItem : public QQuickItem +{ + Q_OBJECT + +public: + GLQuickItem(); + + virtual GLWindow *makeWindowRenderer() = 0; + +signals: + void textEntryRequest(); + void textEntryDismiss(); + +public slots: + void sync(); + void cleanup(); + + void dimensionsChanged(); + void userEnteredText(QString text); + void userFinishedTextEntry(); + + void onTouchPressed(QVariantList touchPoints); + void onTouchUpdated(QVariantList touchPoints); + void onTouchReleased(QVariantList touchPoints); + +private slots: + void handleWindowChanged(QQuickWindow *win); + +private: + DENG2_PRIVATE(d) +}; + +/** + * Template for instantiating a particular type of renderer in a GLQuickItem. + */ +template +class GLQuickItemT : public GLQuickItem +{ +public: + GLWindow *makeWindowRenderer() override + { + return new RendererType; + } +}; + +} // namespace de + +#endif // LIBGUI_GLWINDOW_IOS_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/guiapp.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/guiapp.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/guiapp.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/guiapp.h 2018-12-11 07:08:24.000000000 +0000 @@ -20,7 +20,6 @@ #define LIBGUI_GUIAPP_H #include "libgui.h" -#include #include #include @@ -29,6 +28,16 @@ */ #define DENG2_GUI_APP (static_cast(qApp)) +#define DENG2_ASSERT_IN_RENDER_THREAD() DENG2_ASSERT(de::GuiApp::inRenderThread()) + +#if defined (DENG_MOBILE) +#include +# define LIBGUI_GUIAPP_BASECLASS QGuiApplication +#else +#include +# define LIBGUI_GUIAPP_BASECLASS QApplication +#endif + namespace de { /** @@ -39,8 +48,9 @@ * * @ingroup gui */ -class LIBGUI_PUBLIC GuiApp : public QApplication, public App, - DENG2_OBSERVES(Loop, Iteration) +class LIBGUI_PUBLIC GuiApp : public LIBGUI_GUIAPP_BASECLASS + , public App + , DENG2_OBSERVES(Loop, Iteration) { Q_OBJECT @@ -68,6 +78,14 @@ GuiLoop &loop(); + /** + * Determines if the currently executing thread is the rendering thread. + * This may be the same thread as the main thread. + */ + static bool inRenderThread(); + + static void setRenderThread(QThread *thread); + protected: NativePath appDataPath() const; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/libgui.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/libgui.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/libgui.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/libgui.h 2018-12-11 07:08:24.000000000 +0000 @@ -63,8 +63,6 @@ error == GL_INVALID_ENUM? "GL_INVALID_ENUM" : \ error == GL_INVALID_VALUE? "GL_INVALID_VALUE" : \ error == GL_INVALID_OPERATION? "GL_INVALID_OPERATION" : \ - error == GL_STACK_OVERFLOW? "GL_STACK_OVERFLOW" : \ - error == GL_STACK_UNDERFLOW? "GL_STACK_UNDERFLOW" : \ error == GL_OUT_OF_MEMORY? "GL_OUT_OF_MEMORY" : \ error == GL_INVALID_FRAMEBUFFER_OPERATION? "GL_INVALID_FRAMEBUFFER_OPERATION" : \ "?") diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/persistentglwindow.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/persistentglwindow.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/gui/persistentglwindow.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/gui/persistentglwindow.h 2018-12-11 07:08:24.000000000 +0000 @@ -1,4 +1,4 @@ -/** @file persistentcanvaswindow.h Canvas window with persistent state. +/** @file persistentglwindow.h Canvas window with persistent state. * * @authors Copyright © 2003-2017 Jaakko Keränen * @authors Copyright © 2005-2013 Daniel Swanson @@ -17,8 +17,10 @@ * http://www.gnu.org/licenses */ -#ifndef LIBGUI_PERSISTENTCANVASWINDOW_H -#define LIBGUI_PERSISTENTCANVASWINDOW_H +#ifndef LIBGUI_PERSISTENTGLWINDOW_H +#define LIBGUI_PERSISTENTGLWINDOW_H + +#if !defined (DENG_MOBILE) #include #include @@ -71,6 +73,7 @@ FullscreenWidth, FullscreenHeight, ColorDepthBits, + RefreshRate, // milli-Hz // Other FullSceneAntialias, @@ -118,6 +121,8 @@ int colorDepthBits() const; + float refreshRate() const; + void show(bool yes = true); /** @@ -165,6 +170,7 @@ protected slots: void performQueuedTasks(); + void windowVisibilityChanged(); /** * Forms the name of a Config variable for this window. Subclasses are @@ -183,4 +189,6 @@ } // namespace de -#endif // LIBGUI_PERSISTENTCANVASWINDOW_H +#endif + +#endif // LIBGUI_PERSISTENTGLWINDOW_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/PackageIconBank doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/PackageIconBank --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/PackageIconBank 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/PackageIconBank 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1 @@ +#include "graphics/packageiconbank.h" diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/text/fontbank.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/text/fontbank.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/text/fontbank.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/text/fontbank.h 2018-12-11 07:08:24.000000000 +0000 @@ -58,6 +58,8 @@ */ void setFontSizeFactor(float sizeFactor); + void reload(); + protected: virtual ISource *newSourceFromInfo(String const &id); virtual IData *loadFromSource(ISource &source); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/text/font.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/text/font.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/include/de/text/font.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/include/de/text/font.h 2018-12-11 07:08:24.000000000 +0000 @@ -117,7 +117,8 @@ DimmedColor = 2, AccentColor = 3, DimAccentColor = 4, - AltAccentColor = 5 + AltAccentColor = 5, + MaxColors }; /** @@ -275,6 +276,8 @@ //QFont toQFont() const; + void initialize(const QFont &font); + /** * Determines the size of the given line of text, i.e., how large an area * is covered by the glyphs. (0,0) is at the baseline, left edge of the diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/Info doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/Info --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/Info 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/Info 2018-12-11 07:08:24.000000000 +0000 @@ -1,5 +1,5 @@ title: Doomsday Script Standard Library: GUI -version: 2.0.0 +version: 2.1 license: GPL 3+ tags: core script gui diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.de doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,133 +0,0 @@ -# The Doomsday Engine Project -# -# Copyright (c) 2013-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 3 of the License, or (at -# your option) any later version. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY -# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public -# License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, see . - -#---------------------------------------------------------------------------- -# Graphical user interface - -import Version - -def setDefaults(d) - # Applies the default configuration settings. - # - d: Record where to set the values. - try - import DisplayMode - - # The default audio and video subsystems. - d.video = 'opengl' - - # Generic user interface settings. - record d.ui() - scaleFactor = 1.0 # Overall factor (both rules and fonts). - showAnnotations = True - end - - # Window manager defaults. - record d.window() - fsaa = False # Remove this (should be window-specific). - - # Configure the main window. - record main() - showFps = False - center = True - fsaa = False - vsync = True - end - end - - # The default window parameters depend on the original display mode. - mode = DisplayMode.originalMode() - - # By default the fullscreen resolution is the desktop resolution. - mainWin = d.window.main - mainWin.fullSize = [mode['width'], mode['height']] - - # In windowed mode mode, leave some space on the sides so that - # the first switch to windowed mode does not place the window in an - # inconvenient location. The reduction is done proportionally. - offx = mode['width'] * 0.15 - offy = mode['height'] * 0.15 - mainWin.rect = [offx, offy, mode['width'] - 2*offx, mode['height'] - 2*offy] - mainWin.colorDepth = mode['depth'] - - if Version.OS == 'windows' or Version.OS == 'macx' - mainWin.fullscreen = True - mainWin.maximize = False - else - mainWin.fullscreen = False - mainWin.maximize = True - end - - catch NotFoundError - # DisplayMode isn't available on the server. - end -end - -def scale(value, factor) - # Scales a value by 'factor'. If 'value' is a text string, the - # suffixes "pt" and "px" (point, pixel) are retained in the result. - # - src: Value to scale. Number or Text, may have "pt" or "px" - # as suffix. - # - factor: Scale factor (Number). - - unit = '' - p = Text(value) - amount = p - if p[-2:] == 'pt' or p[-2:] == 'px' - unit = p[-2:] - amount = p[:-2] - end - return Text(floor(Number(amount) * factor)) + unit -end - -def colorMix(a, b, amount) - # Returns a color where vectors 'a' and 'b' are interpolated by - # 'amount'. If 'amount' is 0, the result is 'a'; if 'amount' is 1, - # the result is 'b'. - if len(a) < 4: a += [1.0] - if len(b) < 4: b += [1.0] - - for i in [0, 1, 2, 3] - a[i] = Number(a[i]) - b[i] = Number(b[i]) - end - - inv = 1.0 - amount - return [a[0] * inv + b[0] * amount, - a[1] * inv + b[1] * amount, - a[2] * inv + b[2] * amount, - a[3] * inv + b[3] * amount] -end - -def colorAlpha(colorVector, alpha) - # Returns a new color with the alpha value changed to 'alpha'. - v = colorVector - if len(v) >= 4: v[3] = alpha - elsif len(v) == 3: v += [alpha] - return v -end - -def dpiScaledImagePath(path) - # Returns a version of 'path' where "@2x" is appended to the end - # if DPI_FACTOR is 2 (approximately). - import DisplayMode - p = Text(path) - if DisplayMode.DPI_FACTOR > 1.5 - return (p.fileNameAndPathWithoutExtension() + "@2x" + - p.fileNameExtension()) - end - return p -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.ds doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/net.dengine.stdlib.gui.pack/modules/gui.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,135 @@ +# The Doomsday Engine Project +# +# Copyright (c) 2013-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 3 of the License, or (at +# your option) any later version. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUTANY WARRANTY; without even the implied warranty of MERCHANTABILITY +# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public +# License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, see . + +#---------------------------------------------------------------------------- +# Graphical user interface + +import Version + +def setDefaults(d) + # Applies the default configuration settings. + # - d: Record where to set the values. + try + import DisplayMode + + # The default audio and video subsystems. + d.video = 'opengl' + + # Generic user interface settings. + record d.ui() + scaleFactor = 1.0 # Overall factor (both rules and fonts). + showAnnotations = True + translucency = True + end + + # Window manager defaults. + record d.window() + fsaa = False # Remove this (should be window-specific). + + # Configure the main window. + record main() + showFps = False + center = True + fsaa = False + vsync = True + refreshRate = 0.0 # match desktop rate + end + end + + # The default window parameters depend on the original display mode. + mode = DisplayMode.originalMode() + + # By default the fullscreen resolution is the desktop resolution. + mainWin = d.window.main + mainWin.fullSize = [mode['width'], mode['height']] + + # In windowed mode mode, leave some space on the sides so that + # the first switch to windowed mode does not place the window in an + # inconvenient location. The reduction is done proportionally. + offx = mode['width'] * 0.15 + offy = mode['height'] * 0.15 + mainWin.rect = [offx, offy, mode['width'] - 2*offx, mode['height'] - 2*offy] + mainWin.colorDepth = mode['depth'] + + if Version.OS in ['windows', 'macx', 'ios'] + mainWin.fullscreen = True + mainWin.maximize = False + else + mainWin.fullscreen = False + mainWin.maximize = True + end + + catch NotFoundError + # DisplayMode isn't available on the server. + end +end + +def scale(value, factor) + # Scales a value by 'factor'. If 'value' is a text string, the + # suffixes "pt" and "px" (point, pixel) are retained in the result. + # - src: Value to scale. Number or Text, may have "pt" or "px" + # as suffix. + # - factor: Scale factor (Number). + + unit = '' + p = Text(value) + amount = p + if p[-2:] == 'pt' or p[-2:] == 'px' + unit = p[-2:] + amount = p[:-2] + end + return Text(floor(Number(amount) * factor)) + unit +end + +def colorMix(a, b, amount) + # Returns a color where vectors 'a' and 'b' are interpolated by + # 'amount'. If 'amount' is 0, the result is 'a'; if 'amount' is 1, + # the result is 'b'. + if len(a) < 4: a += [1.0] + if len(b) < 4: b += [1.0] + + for i in [0, 1, 2, 3] + a[i] = Number(a[i]) + b[i] = Number(b[i]) + end + + inv = 1.0 - amount + return [a[0] * inv + b[0] * amount, + a[1] * inv + b[1] * amount, + a[2] * inv + b[2] * amount, + a[3] * inv + b[3] * amount] +end + +def colorAlpha(colorVector, alpha) + # Returns a new color with the alpha value changed to 'alpha'. + v = colorVector + if len(v) >= 4: v[3] = alpha + elsif len(v) == 3: v += [alpha] + return v +end + +def dpiScaledImagePath(path) + # Returns a version of 'path' where "@2x" is appended to the end + # if PIXEL_RATIO is 2 (approximately). + import DisplayMode + p = Text(path) + if DisplayMode.PIXEL_RATIO > 1.5 + return (p.fileNameAndPathWithoutExtension() + "@2x" + + p.fileNameExtension()) + end + return p +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/audio/sound.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/audio/sound.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/audio/sound.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/audio/sound.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,14 +22,14 @@ DENG2_PIMPL(Sound) { - dfloat volume; - dfloat pan; - dfloat frequency; - Vector3f position; - Vector3f velocity; + dfloat volume; + dfloat pan; + dfloat frequency; + Vector3f position; + Vector3f velocity; Positioning positioning; - dfloat minDistance; - dfloat spread; + dfloat minDistance; + dfloat spread; Impl(Public *i) : Base(i) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/audio/waveform.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/audio/waveform.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/audio/waveform.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/audio/waveform.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -26,7 +26,7 @@ struct WAVChunk : public IReadable { - Block id; + Block id; duint32 size; WAVChunk() : id(4), size(0) {} @@ -247,7 +247,7 @@ return d->sampleRate; } -TimeDelta Waveform::duration() const +TimeSpan Waveform::duration() const { return d->sampleRate * d->sampleCount; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/displaymode.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/displaymode.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/displaymode.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/displaymode.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -220,7 +220,7 @@ // Script bindings. binder.initNew() << DENG2_FUNC_NOARG(DisplayMode_OriginalMode, "originalMode"); de::App::scriptSystem().addNativeModule("DisplayMode", binder.module()); - binder.module().addNumber("DPI_FACTOR", 1.0); + binder.module().addNumber("PIXEL_RATIO", 1.0); inited = true; return true; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/displaymode_dummy.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/displaymode_dummy.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/displaymode_dummy.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/displaymode_dummy.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -20,6 +20,8 @@ #include "de/gui/displaymode_native.h" #include +#include +#include void DisplayMode_Native_Init(void) { @@ -42,7 +44,12 @@ void DisplayMode_Native_GetCurrentMode(DisplayMode *mode) { - DENG2_UNUSED(mode); + const auto *scr = QGuiApplication::primaryScreen(); + + mode->width = scr->geometry().width(); + mode->height = scr->geometry().height(); + mode->depth = scr->depth(); + mode->refreshRate = scr->refreshRate(); } int DisplayMode_Native_Change(DisplayMode const *mode, int shouldCapture) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/glwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/glwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/glwindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/glwindow.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -21,10 +21,10 @@ #include "de/GLWindow" #include "de/GuiApp" -#include #include #include #include +#include #include #include @@ -40,21 +40,23 @@ DENG2_PIMPL(GLWindow) { - LoopCallback mainCall; - GLFramebuffer backing; // Represents QOpenGLWindow's framebuffer. - WindowEventHandler *handler = nullptr; ///< Event handler. - bool readyPending = false; - bool readyNotified = false; - Size currentSize; - Size pendingSize; - - unsigned int frameCount = 0; - float fps = 0; - - QOpenGLTimerQuery *timerQuery = nullptr; - bool timerQueryPending = false; - QElapsedTimer gpuTimeRecordingStartedAt; - QVector recordedGpuTimes; + LoopCallback mainCall; + GLFramebuffer backing; // Represents QOpenGLWindow's framebuffer. + WindowEventHandler *handler = nullptr; ///< Event handler. + bool readyPending = false; + bool readyNotified = false; + Size currentSize; + double pixelRatio = 0.0; + + uint frameCount = 0; + float fps = 0; + +#if defined(DENG_HAVE_TIMER_QUERY) + bool timerQueryPending = false; + QOpenGLTimerQuery *timerQuery = nullptr; + QElapsedTimer gpuTimeRecordingStartedAt; + QVector recordedGpuTimes; +#endif Impl(Public *i) : Base(i) {} @@ -82,6 +84,7 @@ self().setState(NotReady); readyNotified = false; readyPending = false; +#if defined (DENG_HAVE_TIMER_QUERY) if (timerQuery) { if (timerQueryPending) timerQuery->waitForResult(); @@ -89,6 +92,7 @@ timerQuery = nullptr; timerQueryPending = false; } +#endif GLInfo::glDeinit(); } @@ -105,11 +109,17 @@ // Print some information. QSurfaceFormat const fmt = self().format(); +#if defined (DENG_OPENGL) LOG_GL_NOTE("OpenGL %i.%i supported%s") - << fmt.majorVersion() << fmt.minorVersion() + << fmt.majorVersion() + << fmt.minorVersion() << (fmt.majorVersion() > 2? (fmt.profile() == QSurfaceFormat::CompatibilityProfile? " (Compatibility)" : " (Core)") : ""); +#else + LOG_GL_NOTE("OpenGL ES %i.%i supported") + << fmt.majorVersion() << fmt.minorVersion(); +#endif // Everybody can perform GL init now. DENG2_FOR_PUBLIC_AUDIENCE2(Init, i) i->windowInit(self()); @@ -122,16 +132,17 @@ mainCall.enqueue([this] () { self().update(); }); } +#if defined (DENG_HAVE_TIMER_QUERY) bool timerQueryReady() const { - if (!GLInfo::extensions().EXT_timer_query) return false; + //if (!GLInfo::extensions().EXT_timer_query) return false; return timerQuery && !timerQueryPending; } void checkTimerQueryResult() { // Measure how long it takes to render a frame on average. - if (GLInfo::extensions().EXT_timer_query && + if (//GLInfo::extensions().EXT_timer_query && timerQueryPending && timerQuery->isResultAvailable()) { @@ -147,7 +158,7 @@ // a second to find out a reasonable value. if (gpuTimeRecordingStartedAt.elapsed() > 1000) { - TimeDelta average = 0; + TimeSpan average = 0; for (auto dt : recordedGpuTimes) average += dt; average = average / recordedGpuTimes.size(); recordedGpuTimes.clear(); @@ -159,6 +170,7 @@ } } } +#endif void updateFrameRateStatistics() { @@ -170,37 +182,88 @@ frameCount++; // Count the frames every other second. - TimeDelta elapsed = nowTime - lastFpsTime; + TimeSpan elapsed = nowTime - lastFpsTime; if (elapsed > 2.5) { - fps = frameCount / elapsed; + fps = float(frameCount / elapsed); lastFpsTime = nowTime; frameCount = 0; } } + void submitResize(const Size &pixelSize) + { + //qDebug() << "resize event:" << pixelSize.asText(); + //qDebug() << "pixel ratio:" << pixelRatio; + + // Only react if this is actually a resize. + if (currentSize != pixelSize) + { + currentSize = pixelSize; + + if (readyNotified) + { + self().makeCurrent(); + } + + DENG2_FOR_PUBLIC_AUDIENCE2(Resize, i) i->windowResized(self()); + + if (readyNotified) + { + self().doneCurrent(); + } + } + } + DENG2_PIMPL_AUDIENCE(Init) DENG2_PIMPL_AUDIENCE(Resize) + DENG2_PIMPL_AUDIENCE(PixelRatio) DENG2_PIMPL_AUDIENCE(Swap) }; DENG2_AUDIENCE_METHOD(GLWindow, Init) DENG2_AUDIENCE_METHOD(GLWindow, Resize) +DENG2_AUDIENCE_METHOD(GLWindow, PixelRatio) DENG2_AUDIENCE_METHOD(GLWindow, Swap) GLWindow::GLWindow() - : QOpenGLWindow() - , d(new Impl(this)) + : d(new Impl(this)) { -#ifdef MACOSX +#if defined (MACOSX) setFlags(flags() | Qt::WindowFullscreenButtonHint); #endif +#if defined (DENG_MOBILE) + setFocusPolicy(Qt::StrongFocus); +#endif + connect(this, SIGNAL(frameSwapped()), this, SLOT(frameWasSwapped())); // Create the drawing canvas for this window. d->handler = new WindowEventHandler(this); + + d->pixelRatio = devicePixelRatio(); + + connect(this, &QWindow::screenChanged, [this](QScreen *scr) { + //qDebug() << "window screen changed:" << scr << scr->devicePixelRatio(); + if (!fequal(d->pixelRatio, scr->devicePixelRatio())) + { + d->pixelRatio = scr->devicePixelRatio(); + d->submitResize(pointSize() * d->pixelRatio); + DENG2_FOR_AUDIENCE2(PixelRatio, i) + { + i->windowPixelRatioChanged(*this); + } + } + }); +} + +#if defined (DENG_MOBILE) +void GLWindow::setTitle(QString const &title) +{ + setWindowTitle(title); } +#endif bool GLWindow::isGLReady() const { @@ -209,22 +272,38 @@ bool GLWindow::isMaximized() const { +#if defined (DENG_MOBILE) + return false; +#else return visibility() == QWindow::Maximized; +#endif } bool GLWindow::isMinimized() const { +#if defined (DENG_MOBILE) + return false; +#else return visibility() == QWindow::Minimized; +#endif } bool GLWindow::isFullScreen() const { +#if defined (DENG_MOBILE) + return true; +#else return visibility() == QWindow::FullScreen; +#endif } bool GLWindow::isHidden() const { +#if defined (DENG_MOBILE) + return false; +#else return visibility() == QWindow::Hidden; +#endif } GLFramebuffer &GLWindow::framebuffer() const @@ -237,6 +316,11 @@ return d->fps; } +uint GLWindow::frameCount() const +{ + return d->frameCount; +} + GLWindow::Size GLWindow::pointSize() const { return Size(duint(de::max(0, QOpenGLWindow::width())), @@ -248,6 +332,11 @@ return d->currentSize; } +double GLWindow::pixelRatio() const +{ + return d->pixelRatio; +} + int GLWindow::pointWidth() const { return pointSize().x; @@ -335,6 +424,7 @@ return QApplication::sendEvent(&canvas(), &keyEvent); } #endif*/ + if (ev->type() == QEvent::Close) { windowAboutToClose(); @@ -349,7 +439,7 @@ QImage GLWindow::grabImage(QSize const &outputSize) const { - return grabImage(QRect(QPoint(0, 0), geometry().size() * qApp->devicePixelRatio()), outputSize); + return grabImage(QRect(QPoint(0, 0), QSize(pixelWidth(), pixelHeight())), outputSize); } QImage GLWindow::grabImage(QRect const &area, QSize const &outputSize) const @@ -406,7 +496,7 @@ if (!d->readyPending) { d->readyPending = true; - d->mainCall.enqueue([this] () { d->notifyReady(); }); + d->mainCall.enqueue([this]() { d->notifyReady(); }); } LIBGUI_GL.glClear(GL_COLOR_BUFFER_BIT); return; @@ -414,7 +504,8 @@ DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr); - if (GLInfo::extensions().EXT_timer_query) + //if (GLInfo::extensions().EXT_timer_query) +#if defined (DENG_HAVE_TIMER_QUERY) { d->checkTimerQueryResult(); @@ -432,24 +523,26 @@ d->timerQuery->begin(); } } +#endif GLBuffer::resetDrawCount(); LIBGUI_ASSERT_GL_OK(); // Make sure any changes to the state stack are in effect. - GLState::current().apply(); GLState::current().target().glBind(); draw(); LIBGUI_ASSERT_GL_OK(); +#if defined (DENG_HAVE_TIMER_QUERY) if (d->timerQueryReady()) { d->timerQuery->end(); d->timerQueryPending = true; } +#endif } void GLWindow::windowAboutToClose() @@ -457,25 +550,7 @@ void GLWindow::resizeEvent(QResizeEvent *ev) { - d->pendingSize = Size(ev->size().width(), ev->size().height()) * qApp->devicePixelRatio(); - - // Only react if this is actually a resize. - if (d->currentSize != d->pendingSize) - { - d->currentSize = d->pendingSize; - - if (d->readyNotified) - { - makeCurrent(); - } - - DENG2_FOR_AUDIENCE2(Resize, i) i->windowResized(*this); - - if (d->readyNotified) - { - doneCurrent(); - } - } + d->submitResize(Size(ev->size().width(), ev->size().height()) * devicePixelRatio()); } void GLWindow::frameWasSwapped() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/glwindow_qml.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/glwindow_qml.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/glwindow_qml.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/glwindow_qml.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,720 @@ +/** @file glwindow.cpp Top-level OpenGL window (QML item). + * @ingroup base + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/GLWindow" +#include "de/GuiApp" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#if !defined (DENG_MOBILE) +# error "glwindow_qml.cpp is only for mobile platforms" +#endif + +namespace de { + +static GLWindow *mainWindow = nullptr; + +DENG2_PIMPL(GLWindow) +{ + QQuickWindow *qtWindow = nullptr; + QOpenGLContext *mainContext = nullptr; + GLFramebuffer backing; // Represents QOpenGLWindow's framebuffer. + WindowEventHandler *handler = nullptr; ///< Event handler. + bool readyNotified = false; + Size currentSize; + Size pendingSize; + + unsigned int frameCount = 0; + float fps = 0; + + Impl(Public *i) : Base(i) {} + + ~Impl() + { + glDeinit(); + } + + void glInit() + { + GLInfo::glInit(); + self().Asset::setState(Ready); + } + + void glDeinit() + { + self().Asset::setState(NotReady); + readyNotified = false; + GLInfo::glDeinit(); + } + + void notifyReady() + { + if (readyNotified) return; + readyNotified = true; + + DENG2_ASSERT_IN_MAIN_THREAD(); + DENG2_ASSERT(QOpenGLContext::currentContext() == mainContext); + + // Print some information. + QSurfaceFormat const fmt = qtWindow->format(); + +#if defined (DENG_OPENGL) + LOG_GL_NOTE("OpenGL %i.%i supported%s") + << fmt.majorVersion() + << fmt.minorVersion() + << (fmt.majorVersion() > 2? + (fmt.profile() == QSurfaceFormat::CompatibilityProfile? " (Compatibility)" + : " (Core)") : ""); +#else + LOG_GL_NOTE("OpenGL ES %i.%i supported") + << fmt.majorVersion() << fmt.minorVersion(); +#endif + + // Everybody can perform GL init now. + DENG2_FOR_PUBLIC_AUDIENCE2(Init, i) i->windowInit(self()); + } + + void updateFrameRateStatistics() + { + static Time lastFpsTime; + + Time const nowTime = Clock::appTime(); + + // Increment the (local) frame counter. + frameCount++; + + // Count the frames every other second. + TimeDelta elapsed = nowTime - lastFpsTime; + if (elapsed > 2.5) + { + fps = frameCount / elapsed; + lastFpsTime = nowTime; + frameCount = 0; + } + } + + DENG2_PIMPL_AUDIENCE(Init) + DENG2_PIMPL_AUDIENCE(Resize) + DENG2_PIMPL_AUDIENCE(Swap) +}; + +DENG2_AUDIENCE_METHOD(GLWindow, Init) +DENG2_AUDIENCE_METHOD(GLWindow, Resize) +DENG2_AUDIENCE_METHOD(GLWindow, Swap) + +GLWindow::GLWindow() + : d(new Impl(this)) +{ + // Create the drawing canvas for this window. + d->handler = new WindowEventHandler(this); +} + +void GLWindow::setTitle(QString const &title) +{ + //setWindowTitle(title); +} + +QSurfaceFormat GLWindow::format() const +{ + DENG2_ASSERT(d->qtWindow); + return d->qtWindow->format(); +} + +double GLWindow::devicePixelRatio() const +{ + DENG2_ASSERT(d->qtWindow); + return d->qtWindow->devicePixelRatio(); +} + +void GLWindow::makeCurrent() +{ + //DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr); + if (App::inMainThread()) + { + DENG2_ASSERT(!QOpenGLContext::currentContext() || QOpenGLContext::currentContext() == d->mainContext); + d->mainContext->makeCurrent(d->qtWindow); + } + else + { + //d->qtWindow->openglContext()->makeCurrent(d->qtWindow); + } +} + +void GLWindow::doneCurrent() +{ +} + +void GLWindow::setWindow(QQuickWindow *window) +{ + d->qtWindow = window; +} + +void GLWindow::setOpenGLContext(QOpenGLContext *context) +{ + d->mainContext = context; +} + +void GLWindow::update() +{ + if (d->qtWindow) d->qtWindow->update(); +} + +Rectanglei GLWindow::windowRect() const +{ + Size const size = pointSize(); + return Rectanglei(0, 0, size.x, size.y); +} + +GLWindow::Size GLWindow::fullscreenSize() const +{ + return pointSize(); +} + +void GLWindow::hide() +{ + +} + +bool GLWindow::isGLReady() const +{ + return d->readyNotified; +} + +bool GLWindow::isMaximized() const +{ + return false; +} + +bool GLWindow::isMinimized() const +{ + return false; +} + +bool GLWindow::isFullScreen() const +{ + return true; +} + +bool GLWindow::isHidden() const +{ + return false; +} + +bool GLWindow::isVisible() const +{ + return true; +} + +GLFramebuffer &GLWindow::framebuffer() const +{ + return d->backing; +} + +float GLWindow::frameRate() const +{ + return d->fps; +} + +uint GLWindow::frameCount() const +{ + return d->frameCount; +} + +GLWindow::Size GLWindow::pointSize() const +{ + if (!d->qtWindow) return Size(); + return Size(duint(de::max(0, d->qtWindow->width())), + duint(de::max(0, d->qtWindow->height()))); +} + +GLWindow::Size GLWindow::pixelSize() const +{ + return d->currentSize; +} + +int GLWindow::pointWidth() const +{ + return pointSize().x; +} + +int GLWindow::pointHeight() const +{ + return pointSize().y; +} + +int GLWindow::pixelWidth() const +{ + return pixelSize().x; +} + +int GLWindow::pixelHeight() const +{ + return pixelSize().y; +} + +WindowEventHandler &GLWindow::eventHandler() const +{ + DENG2_ASSERT(d->handler != 0); + return *d->handler; +} + +bool GLWindow::ownsEventHandler(WindowEventHandler *handler) const +{ + if (!handler) return false; + return d->handler == handler; +} + + /* +void GLWindow::focusInEvent(QFocusEvent *ev) +{ + d->handler->focusInEvent(ev); +} + +void GLWindow::focusOutEvent(QFocusEvent *ev) +{ + d->handler->focusOutEvent(ev); +} + +void GLWindow::keyPressEvent(QKeyEvent *ev) +{ + d->handler->keyPressEvent(ev); +} + +void GLWindow::keyReleaseEvent(QKeyEvent *ev) +{ + d->handler->keyReleaseEvent(ev); +} + +void GLWindow::mousePressEvent(QMouseEvent *ev) +{ + d->handler->mousePressEvent(ev); +} + +void GLWindow::mouseReleaseEvent(QMouseEvent *ev) +{ + d->handler->mouseReleaseEvent(ev); +} + +void GLWindow::mouseDoubleClickEvent(QMouseEvent *ev) +{ + d->handler->mouseDoubleClickEvent(ev); +} + +void GLWindow::mouseMoveEvent(QMouseEvent *ev) +{ + d->handler->mouseMoveEvent(ev); +} + +void GLWindow::wheelEvent(QWheelEvent *ev) +{ + d->handler->wheelEvent(ev); +} + +bool GLWindow::event(QEvent *ev) +{ + if (ev->type() == QEvent::Close) + { + windowAboutToClose(); + } + return LIBGUI_GLWINDOW_BASECLASS::event(ev); +} + */ + +bool GLWindow::grabToFile(NativePath const &path) const +{ + return grabImage().save(path.toString()); +} + +QImage GLWindow::grabImage(QSize const &outputSize) const +{ + Size const size = pixelSize(); + return grabImage(QRect(QPoint(0, 0), QSize(size.x, size.y)), outputSize); +} + +QImage GLWindow::grabImage(QRect const &area, QSize const &outputSize) const +{ +#if 0 + // We will be grabbing the visible, latest complete frame. + //LIBGUI_GL.glReadBuffer(GL_FRONT); + QImage grabbed = const_cast(this)->grabFramebuffer(); // no alpha + if (area.size() != grabbed.size()) + { + // Just take a portion of the full image. + grabbed = grabbed.copy(area); + } + //LIBGUI_GL.glReadBuffer(GL_BACK); + if (outputSize.isValid()) + { + grabbed = grabbed.scaled(outputSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + } + return grabbed; +#endif + return QImage(); +} + +void GLWindow::glActivate() +{ + if (isGLReady()) + { + makeCurrent(); + } +} + +void GLWindow::glDone() +{ + //doneCurrent(); +} + +void *GLWindow::nativeHandle() const +{ +#if 0 + return reinterpret_cast(winId()); +#endif + return nullptr; +} + +void GLWindow::initializeGL() +{ + LOG_AS("GLWindow"); + LOGDEV_GL_NOTE("Initializing OpenGL window"); + + DENG2_ASSERT_IN_MAIN_THREAD(); + makeCurrent(); + + d->glInit(); + d->notifyReady(); +} + +void GLWindow::paintGL() +{ + DENG2_ASSERT_IN_RENDER_THREAD(); + DENG2_ASSERT(d->qtWindow != nullptr); + DENG2_ASSERT(QOpenGLContext::currentContext() == d->qtWindow->openglContext()); + + GLFramebuffer::setDefaultFramebuffer(QOpenGLContext::currentContext()->defaultFramebufferObject()); + + // Do not proceed with painting until after the application has completed + // GL initialization. This is done via timer callback because we don't + // want to perform a long-running operation during a paint event. + + /*if (!d->readyNotified) + { + if (!d->readyPending) + { + d->readyPending = true; + d->mainCall.enqueue([this] () { d->notifyReady(); }); + } + LIBGUI_GL.glClear(GL_COLOR_BUFFER_BIT); + return; + }*/ + + GLBuffer::resetDrawCount(); + + LIBGUI_ASSERT_GL_OK(); + + GLState::considerNativeStateUndefined(); + GLState::current().apply(); + + // Make sure any changes to the state stack are in effect. + GLState::current().target().glBind(); + + draw(); + + LIBGUI_ASSERT_GL_OK(); + + d->qtWindow->resetOpenGLState(); +} + +void GLWindow::windowAboutToClose() +{} + +void GLWindow::resizeGL(int w, int h) +{ + DENG2_ASSERT_IN_MAIN_THREAD(); + + d->pendingSize = Size(w, h); + + // Only react if this is actually a resize. + if (d->currentSize != d->pendingSize) + { + d->currentSize = d->pendingSize; + + if (d->readyNotified) + { + makeCurrent(); + } + + DENG2_FOR_AUDIENCE2(Resize, i) i->windowResized(*this); + + if (d->readyNotified) + { + doneCurrent(); + } + } +} + +void GLWindow::frameWasSwapped() +{ + Loop::mainCall([this] () + { + makeCurrent(); + DENG2_FOR_AUDIENCE2(Swap, i) + { + i->windowSwapped(*this); + } + d->updateFrameRateStatistics(); + }); +} + +bool GLWindow::mainExists() // static +{ + return mainWindow != 0; +} + +GLWindow &GLWindow::main() // static +{ + DENG2_ASSERT(mainWindow != 0); + return *mainWindow; +} + +void GLWindow::glActiveMain() +{ + if (mainExists()) main().glActivate(); +} + +void GLWindow::setMain(GLWindow *window) // static +{ + mainWindow = window; + GuiLoop::get().setWindow(window); +} + +//---------------------------------------------------------------------------------------- + +DENG2_PIMPL_NOREF(GLQuickItem) +{ + QQuickWindow *qtWindow = nullptr; + GLWindow *renderer = nullptr; + bool initPending = false; + int touchId = 0; +}; + +GLQuickItem::GLQuickItem() + : d(new Impl) +{ + connect(this, &QQuickItem::windowChanged, this, &GLQuickItem::handleWindowChanged); +} + +void GLQuickItem::handleWindowChanged(QQuickWindow *win) +{ + d->qtWindow = win; + + if (win) + { + connect(win, &QQuickWindow::beforeSynchronizing, this, &GLQuickItem::sync, Qt::DirectConnection); + connect(win, &QQuickWindow::sceneGraphInvalidated, this, &GLQuickItem::cleanup, Qt::DirectConnection); + + win->setClearBeforeRendering(false); + + if (d->renderer) + { + d->renderer->setWindow(win); + } + } +} + +void GLQuickItem::sync() +{ + DENG2_ASSERT(d->qtWindow); + + if (!d->renderer && !d->initPending) + { + d->initPending = true; + GuiApp::setRenderThread(QThread::currentThread()); + + QOpenGLContext *renderContext = QOpenGLContext::currentContext(); + + Loop::mainCall([this, renderContext] () + { + LOG_AS("GLWindow"); + LOGDEV_GL_NOTE("Initializing OpenGL window"); + + DENG2_ASSERT_IN_MAIN_THREAD(); + + // Create a shared OpenGL context for the main thread. + QOpenGLContext *mainContext = new QOpenGLContext; + mainContext->setShareContext(renderContext); + mainContext->create(); + + auto *renderer = makeWindowRenderer(); + renderer->setOpenGLContext(mainContext); + renderer->setWindow(d->qtWindow); + renderer->initializeGL(); + + connect(renderer, &GLWindow::textEntryRequest, this, &GLQuickItem::textEntryRequest); + connect(renderer, &GLWindow::textEntryDismiss, this, &GLQuickItem::textEntryDismiss); + + d->renderer = renderer; + }); + } + + if (d->renderer) + { + if (d->initPending) + { + d->initPending = false; + + // Painting may commence. + connect(d->qtWindow, &QQuickWindow::beforeRendering, d->renderer, &GLWindow::paintGL, Qt::DirectConnection); + connect(d->qtWindow, &QQuickWindow::frameSwapped, d->renderer, &GLWindow::frameWasSwapped, Qt::DirectConnection); + } + + QSize const winSize = d->qtWindow->size() * d->qtWindow->devicePixelRatio(); + Loop::mainCall([this, winSize] () + { + d->renderer->resizeGL(winSize.width(), winSize.height()); + }); + } +} + +void GLQuickItem::cleanup() +{ + delete d->renderer; + d->renderer = nullptr; + d->initPending = false; +} + +void GLQuickItem::dimensionsChanged() +{ + if (d->renderer && d->qtWindow) + { + auto const ratio = d->qtWindow->devicePixelRatio(); + + QRect newRect = QRect(0, 0, width() * ratio, height() * ratio); + qDebug() << "dimensions" << newRect; + + // Just resize the root widget, the window hasn't changed. + emit d->renderer->rootDimensionsChanged(newRect); + } +} + +void GLQuickItem::userEnteredText(QString text) +{ + if (d->renderer) + { + qDebug() << "user entered:" << text; + emit d->renderer->userEnteredText(text); + } +} + +void GLQuickItem::userFinishedTextEntry() +{ + if (d->renderer) + { + qDebug() << "user Done"; + + auto &handler = d->renderer->eventHandler(); +// QKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, const QString& text = QString(), +// bool autorep = false, ushort count = 1); + + // Simulate the press of the Enter key. + + QKeyEvent pressed (QEvent::KeyPress, Qt::Key_Enter, Qt::NoModifier, "\n"); + QKeyEvent released(QEvent::KeyRelease, Qt::Key_Enter, Qt::NoModifier); + + handler.keyPressEvent(&pressed); + handler.keyReleaseEvent(&released); + + emit d->renderer->userFinishedTextEntry(); + } +} + +void GLQuickItem::onTouchPressed(QVariantList touchPoints) +{ + if (!d->renderer) return; + + //qDebug() << "GLQuickItem: onTouchPressed" << touchPoints; + foreach (QVariant item, touchPoints) + { + QObject *obj = item.value(); + int id = obj->property("pointId").toInt(); + if (id == 0) + { + QMouseEvent event(QEvent::MouseButtonPress, + QPointF(obj->property("x").toDouble(), + obj->property("y").toDouble()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + d->renderer->eventHandler().mousePressEvent(&event); + } + } +} + +void GLQuickItem::onTouchUpdated(QVariantList touchPoints) +{ + if (!d->renderer) return; + + foreach (QVariant item, touchPoints) + { + QObject *obj = item.value(); + if (obj->property("pointId").toInt() == 0) + { + QMouseEvent event(QEvent::MouseMove, + QPointF(obj->property("x").toDouble(), + obj->property("y").toDouble()), + Qt::LeftButton, + Qt::LeftButton, + Qt::NoModifier); + d->renderer->eventHandler().mouseMoveEvent(&event); + } + } +} + +void GLQuickItem::onTouchReleased(QVariantList touchPoints) +{ + if (!d->renderer) return; + + foreach (QVariant item, touchPoints) + { + QObject *obj = item.value(); + if (obj->property("pointId").toInt() == 0) + { + QMouseEvent event(QEvent::MouseButtonRelease, + QPointF(obj->property("x").toDouble(), + obj->property("y").toDouble()), + Qt::LeftButton, + Qt::NoButton, + Qt::NoModifier); + d->renderer->eventHandler().mouseReleaseEvent(&event); + } + } +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/drawable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/drawable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/drawable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/drawable.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,10 +24,10 @@ DENG2_PIMPL(Drawable) { - typedef QMap Buffers; + typedef QMap Buffers; typedef QMap Programs; - typedef QMap States; - typedef QMap Names; + typedef QMap States; + typedef QMap Names; struct BufferConfig { GLProgram const *program; @@ -38,14 +38,14 @@ }; typedef QMap BufferConfigs; - Buffers buffers; - Programs programs; - States states; - Names bufferNames; - Names programNames; - Names stateNames; + Buffers buffers; + Programs programs; + States states; + Names bufferNames; + Names programNames; + Names stateNames; BufferConfigs configs; - GLProgram defaultProgram; + GLProgram defaultProgram; Impl(Public *i) : Base(i) { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glbuffer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glbuffer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glbuffer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glbuffer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -127,21 +127,46 @@ DENG2_PIMPL(GLBuffer) { - GLuint name; - GLuint idxName; - dsize count; - dsize idxCount; - DrawRanges defaultRange; ///< All vertices. - Primitive prim; - AttribSpecs specs { nullptr, 0 }; + GLuint vao = 0; + GLProgram const *vaoBoundProgram = nullptr; + GLuint name = 0; + GLuint idxName = 0; + dsize count = 0; + dsize idxCount = 0; + DrawRanges defaultRange; ///< All vertices. + Primitive prim = Points; + AttribSpecs specs{nullptr, 0}; - Impl(Public *i) : Base(i), name(0), idxName(0), count(0), idxCount(0), prim(Points) + Impl(Public *i) : Base(i) {} ~Impl() { release(); releaseIndices(); + releaseArray(); + } + + void allocArray() + { +#if defined (DENG_HAVE_VAOS) + if (!vao) + { + LIBGUI_GL.glGenVertexArrays(1, &vao); + } +#endif + } + + void releaseArray() + { +#if defined (DENG_HAVE_VAOS) + if (vao) + { + LIBGUI_GL.glDeleteVertexArrays(1, &vao); + vao = 0; + vaoBoundProgram = nullptr; + } +#endif } void alloc() @@ -167,6 +192,7 @@ LIBGUI_GL.glDeleteBuffers(1, &name); name = 0; count = 0; + vaoBoundProgram = nullptr; } } @@ -212,10 +238,12 @@ { DENG2_ASSERT(!part || spec.type == GL_FLOAT); - LIBGUI_GL.glEnableVertexAttribArray(index + part); + auto &GL = LIBGUI_GL; + + GL.glEnableVertexAttribArray(index + part); LIBGUI_ASSERT_GL_OK(); - LIBGUI_GL.glVertexAttribPointer(index + part, + GL.glVertexAttribPointer(index + part, min(4, spec.size), spec.type, spec.normalized, @@ -223,23 +251,47 @@ (void const *) dintptr(spec.startOffset + part * 4 * sizeof(float))); LIBGUI_ASSERT_GL_OK(); - if (GLInfo::ARB_instanced_arrays()) - { - GLInfo::ARB_instanced_arrays()->glVertexAttribDivisorARB(index + part, divisor); - LIBGUI_ASSERT_GL_OK(); - } +#if defined (DENG_HAVE_INSTANCES) + GL.glVertexAttribDivisor(index + part, divisor); + LIBGUI_ASSERT_GL_OK(); +#else + DENG2_UNUSED(divisor); +#endif } - void enableArrays(bool enable, int divisor = 0) const + void enableArrays(bool enable, int divisor = 0, GLuint vaoName = 0) { + auto &GL = LIBGUI_GL; + + if (!enable) + { +#if defined (DENG_HAVE_VAOS) + GL.glBindVertexArray(0); +#endif + return; + } + DENG2_ASSERT(GLProgram::programInUse()); DENG2_ASSERT(specs.first != 0); // must have a spec +#if defined (DENG_HAVE_VAOS) + DENG2_ASSERT(vaoName || vao); +#else + DENG2_UNUSED(vaoName); +#endif + +#if defined (DENG_HAVE_VAOS) + GL.glBindVertexArray(vaoName? vaoName : vao); +#endif + GL.glBindBuffer(GL_ARRAY_BUFFER, name); + + // Arrays are updated for a particular program. + vaoBoundProgram = GLProgram::programInUse(); for (duint i = 0; i < specs.second; ++i) { AttribSpec const &spec = specs.first[i]; - int index = GLProgram::programInUse()->attributeLocation(spec.semantic); + int index = vaoBoundProgram->attributeLocation(spec.semantic); if (index < 0) continue; // Not used. if (spec.size == 16) @@ -251,7 +303,7 @@ setAttribPointer(index, spec, divisor, part); else { - LIBGUI_GL.glDisableVertexAttribArray(index + part); + GL.glDisableVertexAttribArray(index + part); LIBGUI_ASSERT_GL_OK(); } } @@ -262,11 +314,39 @@ setAttribPointer(index, spec, divisor); else { - LIBGUI_GL.glDisableVertexAttribArray(index); + GL.glDisableVertexAttribArray(index); LIBGUI_ASSERT_GL_OK(); } } } + + GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + } + + void bindArray(bool doBind) + { +#if defined (DENG_HAVE_VAOS) + if (doBind) + { + DENG2_ASSERT(vao != 0); + DENG2_ASSERT(GLProgram::programInUse()); + if (vaoBoundProgram != GLProgram::programInUse()) + { + enableArrays(true); + } + else + { + // Just bind it, the setup is already good. + LIBGUI_GL.glBindVertexArray(vao); + } + } + else + { + LIBGUI_GL.glBindVertexArray(0); + } +#else + enableArrays(doBind); +#endif } }; @@ -278,6 +358,7 @@ setState(NotReady); d->release(); d->releaseIndices(); + d->releaseArray(); } void GLBuffer::setVertices(dsize count, void const *data, dsize dataSize, Usage usage) @@ -295,6 +376,7 @@ if (data) { + d->allocArray(); d->alloc(); if (dataSize && count) @@ -325,11 +407,13 @@ if (indices && count) { + d->allocArray(); d->allocIndices(); auto &GL = LIBGUI_GL; GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d->idxName); - GL.glBufferData(GL_ELEMENT_ARRAY_BUFFER, count * sizeof(Index), indices, Impl::glUsage(usage)); + GL.glBufferData(GL_ELEMENT_ARRAY_BUFFER, GLsizeiptr(count * sizeof(Index)), + indices, Impl::glUsage(usage)); GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else @@ -343,6 +427,23 @@ setIndices(primitive, indices.size(), indices.constData(), usage); } +void GLBuffer::setData(void const *data, dsize dataSize, gl::Usage usage) +{ + if (data && dataSize) + { + d->alloc(); + + auto &GL = LIBGUI_GL; + GL.glBindBuffer(GL_ARRAY_BUFFER, d->name); + GL.glBufferData(GL_ARRAY_BUFFER, GLsizeiptr(dataSize), data, Impl::glUsage(usage)); + GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + } + else + { + d->release(); + } +} + void GLBuffer::setData(dsize startOffset, void const *data, dsize dataSize) { DENG2_ASSERT(isReady()); @@ -361,6 +462,7 @@ d->count = 0; d->defaultRange.clear(); + d->allocArray(); d->alloc(); LIBGUI_GL.glBindBuffer(GL_ARRAY_BUFFER, d->name); @@ -379,13 +481,12 @@ auto &GL = LIBGUI_GL; - GL.glBindBuffer(GL_ARRAY_BUFFER, d->name); - d->enableArrays(true); - GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + d->bindArray(true); if (d->idxName) { GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d->idxName); + DENG2_ASSERT(GLProgram::programInUse()->validate()); for (Rangeui const &range : (ranges? *ranges : d->defaultRange)) { GL.glDrawElements(Impl::glPrimitive(d->prim), @@ -397,6 +498,7 @@ } else { + DENG2_ASSERT(GLProgram::programInUse()->validate()); for (Rangeui const &range : (ranges? *ranges : d->defaultRange)) { GL.glDrawArrays(Impl::glPrimitive(d->prim), range.start, range.size()); @@ -409,7 +511,7 @@ DENG2_ASSERT(GLDrawQueue_queuedElems == 0); #endif - d->enableArrays(false); + d->bindArray(false); } void GLBuffer::drawWithIndices(GLBuffer const &indexBuffer) const @@ -421,9 +523,9 @@ auto &GL = LIBGUI_GL; - GL.glBindBuffer(GL_ARRAY_BUFFER, d->name); - d->enableArrays(true); - GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + d->bindArray(true); + + DENG2_ASSERT(GLProgram::programInUse()->validate()); GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffer.d->idxName); GL.glDrawElements(Impl::glPrimitive(indexBuffer.d->prim), @@ -434,29 +536,41 @@ ++drawCounter; - d->enableArrays(false); + d->bindArray(false); +} + +void GLBuffer::drawWithIndices(gl::Primitive primitive, Index const *indices, dsize count) const +{ + if (!isReady() || !indices || !count || !GLProgram::programInUse()) return; + + GLState::current().target().markAsChanged(); + + auto &GL = LIBGUI_GL; + + d->bindArray(true); + DENG2_ASSERT(GLProgram::programInUse()->validate()); + GL.glDrawElements(Impl::glPrimitive(primitive), GLsizei(count), GL_UNSIGNED_SHORT, indices); + LIBGUI_ASSERT_GL_OK(); + ++drawCounter; + + d->bindArray(false); } void GLBuffer::drawInstanced(GLBuffer const &instanceAttribs, duint first, dint count) const { - if (!GLInfo::extensions().ARB_draw_instanced || - !GLInfo::extensions().ARB_instanced_arrays) return; +#if defined (DENG_HAVE_INSTANCES) if (!isReady() || !instanceAttribs.isReady() || !GLProgram::programInUse()) return; - if (!GLInfo::ARB_draw_instanced() || !GLInfo::ARB_instanced_arrays()) return; - // Mark the current target changed. GLState::current().target().markAsChanged(); - LIBGUI_GL.glBindBuffer(GL_ARRAY_BUFFER, d->name); + auto &GL = LIBGUI_GL; + d->enableArrays(true); - // Set up the instance data. - LIBGUI_GL.glBindBuffer(GL_ARRAY_BUFFER, instanceAttribs.d->name); - instanceAttribs.d->enableArrays(true, 1 /* per instance */); - - LIBGUI_GL.glBindBuffer(GL_ARRAY_BUFFER, 0); + // Set up the instance data, using this buffer's VAO. + instanceAttribs.d->enableArrays(true, 1 /* per instance */, d->vao); if (d->idxName) { @@ -465,12 +579,13 @@ DENG2_ASSERT(count >= 0); - LIBGUI_GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d->idxName); - GLInfo::ARB_draw_instanced()->glDrawElementsInstancedARB(Impl::glPrimitive(d->prim), count, GL_UNSIGNED_SHORT, - (void const *) dintptr(first * 2), - instanceAttribs.count()); + GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, d->idxName); + DENG2_ASSERT(GLProgram::programInUse()->validate()); + GL.glDrawElementsInstanced(Impl::glPrimitive(d->prim), count, GL_UNSIGNED_SHORT, + reinterpret_cast(dintptr(first * 2)), + GLsizei(instanceAttribs.count())); LIBGUI_ASSERT_GL_OK(); - LIBGUI_GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + GL.glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); } else { @@ -478,14 +593,24 @@ if (first + count > d->count) count = d->count - first; DENG2_ASSERT(count >= 0); + DENG2_ASSERT(GLProgram::programInUse()->validate()); - GLInfo::ARB_draw_instanced()->glDrawArraysInstancedARB(Impl::glPrimitive(d->prim), first, count, - instanceAttribs.count()); + GL.glDrawArraysInstanced(Impl::glPrimitive(d->prim), first, count, + GLsizei(instanceAttribs.count())); LIBGUI_ASSERT_GL_OK(); } d->enableArrays(false); instanceAttribs.d->enableArrays(false); + +#else + + // Instanced drawing is not available. + DENG2_UNUSED(instanceAttribs); + DENG2_UNUSED(first); + DENG2_UNUSED(count); + +#endif } dsize GLBuffer::count() const @@ -498,6 +623,11 @@ d->specs = format; } +GLuint GLBuffer::glName() const +{ + return d->name; +} + duint GLBuffer::drawCount() // static { return drawCounter; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gldrawqueue.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gldrawqueue.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gldrawqueue.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gldrawqueue.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -33,10 +33,11 @@ DENG2_PIMPL_NOREF(GLDrawQueue) { - GLProgram *currentProgram = nullptr; - GLBuffer const *currentBuffer = nullptr; + GLProgram * currentProgram = nullptr; + GLBuffer const * currentBuffer = nullptr; GLBuffer::Indices indices; - GLBuffer indexBuffer; + QList indexBuffers; + int indexBufferPos = 0; dsize batchIndex = 0; @@ -51,6 +52,22 @@ float defaultSaturation = 1.f; GLUniform uBatchSaturation { "uSaturation", GLUniform::FloatArray, GLShader::MAX_BATCH_UNIFORMS }; + ~Impl() + { + qDeleteAll(indexBuffers); + } + + GLBuffer &nextIndexBuffer() + { + if (indexBufferPos == indexBuffers.size()) + { + // Allocate a new one. + indexBuffers << new GLBuffer; + } + indexBufferPos++; + return *indexBuffers.last(); + } + void unsetProgram() { if (currentProgram) @@ -192,7 +209,8 @@ /*qDebug() << "[GLDrawQueue] Flushing" << d->indices.size() << "elements" << "consisting of" << batchCount << "batches";*/ - d->indexBuffer.setIndices(gl::TriangleStrip, d->indices, gl::Dynamic); + GLBuffer &indexBuffer = d->nextIndexBuffer(); + indexBuffer.setIndices(gl::TriangleStrip, d->indices, gl::Stream); d->indices.clear(); if (d->uBatchColors) @@ -203,8 +221,10 @@ } d->currentProgram->beginUse(); - d->currentBuffer ->drawWithIndices(d->indexBuffer); + d->currentBuffer ->drawWithIndices(indexBuffer); d->currentProgram->endUse(); + + d->indices.clear(); } d->currentBuffer = nullptr; d->batchIndex = 0; @@ -213,5 +233,10 @@ d->restoreBatchValues(); } +void GLDrawQueue::beginFrame() +{ + d->indexBufferPos = 0; +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glframebuffer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glframebuffer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glframebuffer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glframebuffer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -78,16 +78,16 @@ GL_DEPTH_STENCIL_ATTACHMENT; } - GLuint fbo; - GLuint renderBufs[MAX_ATTACHMENTS]; - GLTexture *bufTextures[MAX_ATTACHMENTS]; - Flags flags; - Flags textureAttachment; ///< Where to attach @a texture. - GLTexture *texture; - Vector2ui size; - Vector4f clearColor; + GLuint fbo; + GLuint renderBufs[MAX_ATTACHMENTS]; + GLTexture * bufTextures[MAX_ATTACHMENTS]; + Flags flags; + Flags textureAttachment; ///< Where to attach @a texture. + GLTexture * texture; + Vector2ui size; + Vector4f clearColor; Rectangleui activeRect; ///< Initially null. - int sampleCount; + int sampleCount; Impl(Public *i) : Base(i) @@ -183,8 +183,8 @@ { if (isDefault() || fbo) return; - GLInfo::EXT_framebuffer_object()->glGenFramebuffersEXT(1, &fbo); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + LIBGUI_GL.glGenFramebuffers(1, &fbo); + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); LIBGUI_ASSERT_GL_OK(); LOG_GL_XVERBOSE("Creating FBO %i", fbo); @@ -197,7 +197,7 @@ LOG_GL_XVERBOSE("FBO %i: glTex %i (level %i) => attachment %i", fbo << tex.glName() << level << attachmentToId(attachment)); - GLInfo::EXT_framebuffer_object()->glFramebufferTexture2DEXT(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex.glName(), level); + LIBGUI_GL.glFramebufferTexture2D(GL_FRAMEBUFFER, attachment, GL_TEXTURE_2D, tex.glName(), level); LIBGUI_ASSERT_GL_OK(); bufTextures[attachmentToId(attachment)] = &tex; @@ -207,10 +207,11 @@ { DENG2_ASSERT(size != Vector2ui(0, 0)); - GLInfo::EXT_framebuffer_object()->glGenRenderbuffersEXT(1, &renderBufs[id]); - GLInfo::EXT_framebuffer_object()->glBindRenderbufferEXT(GL_RENDERBUFFER, renderBufs[id]); + LIBGUI_GL.glGenRenderbuffers(1, &renderBufs[id]); + LIBGUI_GL.glBindRenderbuffer(GL_RENDERBUFFER, renderBufs[id]); LIBGUI_ASSERT_GL_OK(); +#if !defined(DENG_OPENGL_ES) if (sampleCount > 1) { if (GLInfo::extensions().NV_framebuffer_multisample_coverage) @@ -230,18 +231,19 @@ << attachmentToId(attachment); //DENG2_ASSERT(GLInfo::extensions().EXT_framebuffer_multisample); - GLInfo::EXT_framebuffer_multisample()->glRenderbufferStorageMultisampleEXT( + LIBGUI_GL.glRenderbufferStorageMultisample( GL_RENDERBUFFER, sampleCount, type, size.x, size.y); LIBGUI_ASSERT_GL_OK(); } } else +#endif { - GLInfo::EXT_framebuffer_object()->glRenderbufferStorageEXT(GL_RENDERBUFFER, type, size.x, size.y); + LIBGUI_GL.glRenderbufferStorage(GL_RENDERBUFFER, type, size.x, size.y); LIBGUI_ASSERT_GL_OK(); } - GLInfo::EXT_framebuffer_object()->glFramebufferRenderbufferEXT( + LIBGUI_GL.glFramebufferRenderbuffer( GL_FRAMEBUFFER, attachment, GL_RENDERBUFFER, renderBufs[id]); LIBGUI_ASSERT_GL_OK(); } @@ -287,7 +289,7 @@ allocDepthStencilRenderBuffers(); - GLInfo::EXT_framebuffer_object()->glBindRenderbufferEXT(GL_RENDERBUFFER, 0); + LIBGUI_GL.glBindRenderbuffer(GL_RENDERBUFFER, 0); } void allocDepthStencilRenderBuffers() @@ -307,17 +309,19 @@ LOG_GL_VERBOSE("FBO %i: depth renderbuffer %s") << fbo << size.asText(); attachRenderbuffer(DepthBuffer, GL_DEPTH_COMPONENT, GL_DEPTH_ATTACHMENT); } +#if defined (DENG_OPENGL) if (flags.testFlag(Stencil) && !textureAttachment.testFlag(Stencil)) { LOG_GL_VERBOSE("FBO %i: stencil renderbuffer %s") << fbo << size.asText(); attachRenderbuffer(StencilBuffer, GL_STENCIL_INDEX, GL_STENCIL_ATTACHMENT); } +#endif } } void releaseRenderBuffers() { - GLInfo::EXT_framebuffer_object()->glDeleteRenderbuffersEXT(MAX_ATTACHMENTS, renderBufs); + LIBGUI_GL.glDeleteRenderbuffers(MAX_ATTACHMENTS, renderBufs); zap(renderBufs); zap(bufTextures); } @@ -328,7 +332,7 @@ if (fbo) { releaseRenderBuffers(); - GLInfo::EXT_framebuffer_object()->glDeleteFramebuffersEXT(1, &fbo); + LIBGUI_GL.glDeleteFramebuffers(1, &fbo); fbo = 0; } zap(bufTextures); @@ -349,7 +353,7 @@ { if (renderBufs[id]) { - GLInfo::EXT_framebuffer_object()->glDeleteRenderbuffersEXT(1, &renderBufs[id]); + LIBGUI_GL.glDeleteRenderbuffers(1, &renderBufs[id]); renderBufs[id] = 0; } } @@ -367,7 +371,7 @@ DENG2_ASSERT(self().isReady()); // must already be inited DENG2_ASSERT(bufTextures[attachmentToId(attachment)] != 0); // must have an attachment already - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); attachTexture(newTexture, attachment); validate(); @@ -378,7 +382,7 @@ DENG2_ASSERT(self().isReady()); // must already be inited if (attachment == DepthStencil) // this supported only { - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); allocDepthStencilRenderBuffers(); @@ -394,8 +398,8 @@ renderBufs[id] = renderBufId; - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); - GLInfo::EXT_framebuffer_object()->glFramebufferRenderbufferEXT( + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + LIBGUI_GL.glFramebufferRenderbuffer( GL_FRAMEBUFFER, flagsToGLAttachment(attachment), GL_RENDERBUFFER, renderBufs[id]); @@ -415,9 +419,8 @@ DENG2_ASSERT(fbo != 0); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); - GLenum status = GLInfo::EXT_framebuffer_object()->glCheckFramebufferStatusEXT(GL_FRAMEBUFFER); - + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); + GLenum status = LIBGUI_GL.glCheckFramebufferStatus(GL_FRAMEBUFFER); if (status != GL_FRAMEBUFFER_COMPLETE) { releaseAndReset(); @@ -500,7 +503,11 @@ d->flags = flags; d->size = size; +#if defined (DENG_OPENGL_ES) + DENG2_UNUSED(sampleCount); +#else d->sampleCount = (sampleCount > 1? sampleCount : 0); +#endif d->allocFBO(); d->allocRenderBuffers(); @@ -584,7 +591,7 @@ GLuint const fbo = (d->fbo? d->fbo : defaultFramebuffer); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, fbo); + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, fbo); LIBGUI_ASSERT_GL_OK(); } @@ -592,7 +599,7 @@ { LIBGUI_ASSERT_GL_OK(); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, defaultFramebuffer); // both read and write FBOs + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, defaultFramebuffer); // both read and write FBOs LIBGUI_ASSERT_GL_OK(); } @@ -607,13 +614,13 @@ // Read the contents of the color attachment. Size imgSize = size(); QImage img(QSize(imgSize.x, imgSize.y), QImage::Format_ARGB32); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, d->fbo); + LIBGUI_GL.glBindFramebuffer(GL_READ_FRAMEBUFFER, d->fbo); LIBGUI_GL.glPixelStorei(GL_PACK_ALIGNMENT, 4); LIBGUI_GL.glReadPixels(0, 0, imgSize.x, imgSize.y, GL_BGRA, GL_UNSIGNED_BYTE, (GLvoid *) img.constBits()); // Restore the stack's target. GLState::current().target().glBind(); - return img; + return img.mirrored(false, true); } return QImage(); } @@ -648,7 +655,7 @@ // The default target resizes itself automatically with the canvas. if (d->size == size || d->isDefault()) return; - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, d->fbo); + LIBGUI_GL.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo); if (d->texture) { d->texture->setUndefinedImage(size, d->texture->imageFormat()); @@ -691,23 +698,17 @@ { LIBGUI_ASSERT_GL_OK(); - auto *fb_obj = GLInfo::EXT_framebuffer_object(); - auto *fb_blit = GLInfo::EXT_framebuffer_blit(); - - if (!fb_obj || !fb_blit) - { - return; - } - - fb_obj->glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, dest.glName()); + LIBGUI_GL.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dest.glName()); LIBGUI_ASSERT_GL_OK(); - fb_obj->glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, glName()); +#if defined (DENG_HAVE_BLIT_FRAMEBUFFER) + + LIBGUI_GL.glBindFramebuffer(GL_READ_FRAMEBUFFER, glName()); LIBGUI_ASSERT_GL_OK(); Flags common = d->flags & dest.flags() & attachments; - fb_blit->glBlitFramebufferEXT( + LIBGUI_GL.glBlitFramebuffer( 0, 0, size().x, size().y, 0, 0, dest.size().x, dest.size().y, (common.testFlag(Color)? GL_COLOR_BUFFER_BIT : 0) | @@ -719,6 +720,14 @@ //GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, 0); //LIBGUI_ASSERT_GL_OK(); +#else + + qDebug() << "need to implement glBlitFramebuffer:" << glName() << "->" << dest.glName(); + qDebug() << "\t- from texture:" << attachedTexture(Color); + qDebug() << "\t- to texture:" << dest.attachedTexture(Color); + +#endif + dest.markAsChanged(); GLState::current().target().glBind(); @@ -730,10 +739,12 @@ //qDebug() << "Blitting from" << glName() << "to" << defaultFramebuffer << size().asText(); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, glName()); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, defaultFramebuffer); +#if defined (DENG_HAVE_BLIT_FRAMEBUFFER) + + LIBGUI_GL.glBindFramebuffer(GL_READ_FRAMEBUFFER, glName()); + LIBGUI_GL.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, defaultFramebuffer); - GLInfo::EXT_framebuffer_blit()->glBlitFramebufferEXT( + LIBGUI_GL.glBlitFramebuffer( 0, 0, size().x, size().y, 0, 0, size().x, size().y, GL_COLOR_BUFFER_BIT, @@ -741,6 +752,13 @@ LIBGUI_ASSERT_GL_OK(); +#else + + qDebug() << "need to implement glBlitFramebuffer:" << glName() << "-> 0"; + qDebug() << "\t- texture:" << attachedTexture(Color); + +#endif + GLState::current().target().glBind(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glinfo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glinfo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glinfo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glinfo.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -27,6 +27,11 @@ #include #include +#ifdef DENG2_DEBUG +# define DENG_ENABLE_OPENGL_DEBUG_LOGGER +# include +#endif + #if defined (MACOSX) # include #endif @@ -50,12 +55,14 @@ Extensions ext; Limits lim; - std::unique_ptr ARB_draw_instanced; - std::unique_ptr ARB_instanced_arrays; - std::unique_ptr EXT_framebuffer_blit; - std::unique_ptr EXT_framebuffer_multisample; - std::unique_ptr EXT_framebuffer_object; + //std::unique_ptr ARB_draw_instanced; + //std::unique_ptr ARB_instanced_arrays; + //std::unique_ptr EXT_framebuffer_blit; + //std::unique_ptr EXT_framebuffer_multisample; + //std::unique_ptr EXT_framebuffer_object; +#if defined (DENG_OPENGL) std::unique_ptr NV_framebuffer_multisample_coverage; +#endif #ifdef WIN32 BOOL (APIENTRY *wglSwapIntervalEXT)(int interval) = nullptr; @@ -67,11 +74,13 @@ PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA = nullptr; #endif +#ifdef DENG_ENABLE_OPENGL_DEBUG_LOGGER + QOpenGLDebugLogger *logger = nullptr; +#endif Impl() { zap(ext); - zap(lim); } /** @@ -155,65 +164,190 @@ if (inited) return; - if (!initializeOpenGLFunctions()) + #if defined (DENG_OPENGL_ES) { - throw InitError("GLInfo::init", "Failed to initialize OpenGL"); + initializeOpenGLFunctions(); + + static OpenGLFeature const requiredFeatures[] = + { + Multitexture, + Shaders, + Buffers, + Framebuffers, + BlendEquationSeparate, + BlendSubtract, + NPOTTextures, + NPOTTextureRepeat, + }; + for (auto const &feature : requiredFeatures) + { + if (!openGLFeatures().testFlag(feature)) + { + qDebug() << "OpenGL feature reported as not available:" << feature; + //throw InitError("GLInfo::init", "Required OpenGL feature missing: " + + // String("%1").arg(feature)); + } + } } + #else + { + if (!initializeOpenGLFunctions()) + { + throw InitError("GLInfo::init", "Failed to initialize OpenGL"); + } + } + #endif + + inited = true; // Extensions. - ext.ARB_draw_instanced = query("GL_ARB_draw_instanced"); - ext.ARB_instanced_arrays = query("GL_ARB_instanced_arrays"); - ext.ARB_texture_env_combine = query("GL_ARB_texture_env_combine") || query("GL_EXT_texture_env_combine"); - ext.ARB_texture_non_power_of_two = query("GL_ARB_texture_non_power_of_two"); - - ext.EXT_blend_subtract = query("GL_EXT_blend_subtract"); - ext.EXT_framebuffer_blit = query("GL_EXT_framebuffer_blit"); - ext.EXT_framebuffer_multisample = query("GL_EXT_framebuffer_multisample"); - ext.EXT_framebuffer_object = query("GL_EXT_framebuffer_object"); - ext.EXT_packed_depth_stencil = query("GL_EXT_packed_depth_stencil"); + //ext.ARB_draw_instanced = query("GL_ARB_draw_instanced"); + //ext.ARB_instanced_arrays = query("GL_ARB_instanced_arrays"); + //ext.ARB_texture_env_combine = query("GL_ARB_texture_env_combine") || query("GL_EXT_texture_env_combine"); + //ext.ARB_texture_non_power_of_two = query("GL_ARB_texture_non_power_of_two"); + + //ext.EXT_blend_subtract = query("GL_EXT_blend_subtract"); + //ext.EXT_framebuffer_blit = query("GL_EXT_framebuffer_blit"); + //ext.EXT_framebuffer_multisample = query("GL_EXT_framebuffer_multisample"); + //ext.EXT_framebuffer_object = query("GL_EXT_framebuffer_object"); + //ext.EXT_packed_depth_stencil = query("GL_EXT_packed_depth_stencil"); ext.EXT_texture_compression_s3tc = query("GL_EXT_texture_compression_s3tc"); ext.EXT_texture_filter_anisotropic = query("GL_EXT_texture_filter_anisotropic"); - ext.EXT_timer_query = query("GL_EXT_timer_query"); + //ext.EXT_timer_query = query("GL_EXT_timer_query"); - ext.ATI_texture_env_combine3 = query("GL_ATI_texture_env_combine3"); + //ext.ATI_texture_env_combine3 = query("GL_ATI_texture_env_combine3"); ext.NV_framebuffer_multisample_coverage = query("GL_NV_framebuffer_multisample_coverage"); - ext.NV_texture_env_combine4 = query("GL_NV_texture_env_combine4"); - ext.SGIS_generate_mipmap = query("GL_SGIS_generate_mipmap"); + //ext.NV_texture_env_combine4 = query("GL_NV_texture_env_combine4"); + //ext.SGIS_generate_mipmap = query("GL_SGIS_generate_mipmap"); -#ifdef WIN32 - ext.Windows_ARB_multisample = query("WGL_ARB_multisample"); - ext.Windows_EXT_swap_control = query("WGL_EXT_swap_control"); + ext.KHR_debug = query("GL_KHR_debug"); - if (ext.Windows_EXT_swap_control) + #ifdef WIN32 { - wglSwapIntervalEXT = de::function_cast - (QOpenGLContext::currentContext()->getProcAddress("wglSwapIntervalEXT")); - } -#endif - -#ifdef DENG_X11 - ext.X11_EXT_swap_control = query("GLX_EXT_swap_control"); - ext.X11_SGI_swap_control = query("GLX_SGI_swap_control"); - ext.X11_MESA_swap_control = query("GLX_MESA_swap_control"); + //ext.Windows_ARB_multisample = query("WGL_ARB_multisample"); + ext.Windows_EXT_swap_control = query("WGL_EXT_swap_control"); - if (ext.X11_EXT_swap_control) - { - glXSwapIntervalEXT = de::function_cast - (glXGetProcAddress(reinterpret_cast("glXSwapIntervalEXT"))); + if (ext.Windows_EXT_swap_control) + { + wglSwapIntervalEXT = de::function_cast + (QOpenGLContext::currentContext()->getProcAddress("wglSwapIntervalEXT")); + } } - if (ext.X11_SGI_swap_control) + #endif + + #ifdef DENG_X11 { - glXSwapIntervalSGI = de::function_cast - (glXGetProcAddress(reinterpret_cast("glXSwapIntervalSGI"))); + ext.X11_EXT_swap_control = query("GLX_EXT_swap_control"); + ext.X11_SGI_swap_control = query("GLX_SGI_swap_control"); + ext.X11_MESA_swap_control = query("GLX_MESA_swap_control"); + + if (ext.X11_EXT_swap_control) + { + glXSwapIntervalEXT = de::function_cast + (glXGetProcAddress(reinterpret_cast("glXSwapIntervalEXT"))); + } + if (ext.X11_SGI_swap_control) + { + glXSwapIntervalSGI = de::function_cast + (glXGetProcAddress(reinterpret_cast("glXSwapIntervalSGI"))); + } + if (ext.X11_MESA_swap_control) + { + glXSwapIntervalMESA = de::function_cast + (glXGetProcAddress(reinterpret_cast("glXSwapIntervalMESA"))); + } } - if (ext.X11_MESA_swap_control) + #endif + + #ifdef DENG_ENABLE_OPENGL_DEBUG_LOGGER { - glXSwapIntervalMESA = de::function_cast - (glXGetProcAddress(reinterpret_cast("glXSwapIntervalMESA"))); + logger = new QOpenGLDebugLogger(&GLWindow::main()); + if (!ext.KHR_debug) + { + qDebug() << "[GLInfo] GL_KHR_debug is not available"; + } + else if (!logger->initialize()) + { + qWarning() << "[GLInfo] Failed to initialize debug logger!"; + } + else + { + QObject::connect(logger, &QOpenGLDebugLogger::messageLogged, + [] (QOpenGLDebugMessage const &debugMessage) + { + if (debugMessage.severity() == QOpenGLDebugMessage::NotificationSeverity) + { + // Too verbose. + return; + } + + char const *mType = "--"; + char const *mSeverity = "--"; + + switch (debugMessage.type()) + { + case QOpenGLDebugMessage::ErrorType: + mType = "ERROR"; + break; + case QOpenGLDebugMessage::DeprecatedBehaviorType: + mType = "Deprecated"; + break; + case QOpenGLDebugMessage::UndefinedBehaviorType: + mType = "Undefined"; + break; + case QOpenGLDebugMessage::PortabilityType: + mType = "Portability"; + break; + case QOpenGLDebugMessage::PerformanceType: + mType = "Performance"; + break; + case QOpenGLDebugMessage::OtherType: + mType = "Other"; + break; + case QOpenGLDebugMessage::MarkerType: + mType = "Marker"; + break; + case QOpenGLDebugMessage::GroupPushType: + mType = "Group Push"; + break; + case QOpenGLDebugMessage::GroupPopType: + mType = "Group Pop"; + break; + default: + break; + } + + switch (debugMessage.severity()) + { + case QOpenGLDebugMessage::HighSeverity: + mType = " HIGH "; + break; + case QOpenGLDebugMessage::MediumSeverity: + mType = "MEDIUM"; + break; + case QOpenGLDebugMessage::LowSeverity: + mType = " low "; + break; + case QOpenGLDebugMessage::NotificationSeverity: + mType = " note "; + break; + default: + break; + } + + qDebug("[OpenGL] %04x %s (%s): %s", + debugMessage.id(), + mType, + mSeverity, + debugMessage.message().toLatin1().constData()); + }); + logger->startLogging(QOpenGLDebugLogger::SynchronousLogging); + } } -#endif + #endif + /* if (ext.ARB_draw_instanced) { ARB_draw_instanced.reset(new QOpenGLExtension_ARB_draw_instanced); @@ -238,16 +372,29 @@ { EXT_framebuffer_object.reset(new QOpenGLExtension_EXT_framebuffer_object); EXT_framebuffer_object->initializeOpenGLFunctions(); - } - if (ext.NV_framebuffer_multisample_coverage) + }*/ + + #if defined (DENG_OPENGL) { - NV_framebuffer_multisample_coverage.reset(new QOpenGLExtension_NV_framebuffer_multisample_coverage); - NV_framebuffer_multisample_coverage->initializeOpenGLFunctions(); + if (ext.NV_framebuffer_multisample_coverage) + { + NV_framebuffer_multisample_coverage.reset(new QOpenGLExtension_NV_framebuffer_multisample_coverage); + NV_framebuffer_multisample_coverage->initializeOpenGLFunctions(); + } } + #endif // Limits. - glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *) &lim.maxTexSize); - glGetIntegerv(GL_MAX_TEXTURE_UNITS, (GLint *) &lim.maxTexUnits); + glGetIntegerv(GL_MAX_TEXTURE_SIZE, reinterpret_cast(&lim.maxTexSize)); + glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, reinterpret_cast(&lim.maxTexUnits)); // at least 16 + #if defined (DENG_OPENGL) + { + glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, &lim.smoothLineWidth.start); + glGetFloatv(GL_SMOOTH_LINE_WIDTH_GRANULARITY, &lim.smoothLineWidthGranularity); + } + #endif + + LIBGUI_ASSERT_GL_OK(); if (ext.EXT_texture_filter_anisotropic) { @@ -276,7 +423,7 @@ LOGDEV_GL_MSG(" - samples: %i") << form.samples(); LOGDEV_GL_MSG(" - swap behavior: %i") << form.swapBehavior(); - inited = true; + LIBGUI_ASSERT_GL_OK(); } }; @@ -285,11 +432,21 @@ void GLInfo::glInit() { + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); + info.d->init(); } void GLInfo::glDeinit() { + #ifdef DENG_ENABLE_OPENGL_DEBUG_LOGGER + { + if (info.d->logger) + { + info.d->logger->stopLogging(); + } + } + #endif info.d.reset(); } @@ -300,6 +457,7 @@ return *info.d; } +/* QOpenGLExtension_ARB_draw_instanced *GLInfo::ARB_draw_instanced() { DENG2_ASSERT(info.d->inited); @@ -329,25 +487,28 @@ DENG2_ASSERT(info.d->inited); return info.d->EXT_framebuffer_object.get(); } +*/ +#if defined (DENG_OPENGL) QOpenGLExtension_NV_framebuffer_multisample_coverage *GLInfo::NV_framebuffer_multisample_coverage() { DENG2_ASSERT(info.d->inited); return info.d->NV_framebuffer_multisample_coverage.get(); } +#endif void GLInfo::setSwapInterval(int interval) { DENG2_ASSERT(info.d->inited); -#if defined (WIN32) - if (extensions().Windows_EXT_swap_control) + #if defined (WIN32) { - info.d->wglSwapIntervalEXT(interval); + if (extensions().Windows_EXT_swap_control) + { + info.d->wglSwapIntervalEXT(interval); + } } -#endif - -#if defined (MACOSX) + #elif defined (MACOSX) { CGLContextObj context = CGLGetCurrentContext(); DENG2_ASSERT(context != nullptr); @@ -357,25 +518,43 @@ CGLSetParameter(context, kCGLCPSwapInterval, params); } } -#endif - -#if defined (DENG_X11) - if (extensions().X11_SGI_swap_control) + #elif defined (DENG_X11) { - info.d->glXSwapIntervalSGI(interval); + if (extensions().X11_SGI_swap_control) + { + info.d->glXSwapIntervalSGI(interval); + } + else if (extensions().X11_MESA_swap_control) + { + info.d->glXSwapIntervalMESA(uint(interval)); + } + else if (extensions().X11_EXT_swap_control) + { + info.d->glXSwapIntervalEXT(QX11Info::display(), + GLWindow::main().winId(), + interval); + } } - else if (extensions().X11_MESA_swap_control) + #endif +} + +#if 0 +void GLInfo::setLineWidth(float lineWidth) +{ + #if defined (DENG_OPENGL) { - info.d->glXSwapIntervalMESA(uint(interval)); + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); + DENG2_ASSERT(info.d->inited); + info.d->glLineWidth(info.d->lim.smoothLineWidth.clamp(lineWidth)); + LIBGUI_ASSERT_GL_OK(); } - else if (extensions().X11_EXT_swap_control) + #else { - info.d->glXSwapIntervalEXT(QX11Info::display(), - GLWindow::main().winId(), - interval); + DENG2_UNUSED(lineWidth); } -#endif + #endif } +#endif GLInfo::Extensions const &GLInfo::extensions() { @@ -391,8 +570,24 @@ bool GLInfo::isFramebufferMultisamplingSupported() { - return extensions().EXT_framebuffer_multisample && - extensions().EXT_framebuffer_blit; + return true; +} + +void GLInfo::checkError(char const *file, int line) +{ + GLuint error = GL_NO_ERROR; + do + { + error = LIBGUI_GL.glGetError(); + if (error != GL_NO_ERROR) + { + LogBuffer_Flush(); + qWarning("%s:%i: OpenGL error: 0x%x (%s)", file, line, error, + LIBGUI_GL_ERROR_STR(error)); + LIBGUI_ASSERT_GL(0!="OpenGL operation failed"); + } + } + while (error != GL_NO_ERROR); } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glprogram.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glprogram.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glprogram.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glprogram.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -50,17 +50,17 @@ /// in each stack is the active one at any given time. QHash> stacks; - Uniforms allBound; - Uniforms active; ///< Currently active bindings. - Uniforms changed; + Uniforms allBound; + Uniforms active; ///< Currently active bindings. + Uniforms changed; UniformList textures; - bool texturesChanged; - int attribLocation[AttribSpec::NUM_SEMANTICS]; ///< Where each attribute is bound. + bool texturesChanged; + int attribLocation[AttribSpec::NUM_SEMANTICS]; ///< Where each attribute is bound. - GLuint name; + GLuint name; Shaders shaders; - bool inUse; - bool needRebuild; + bool inUse; + bool needRebuild; Impl(Public *i) : Base(i) @@ -201,6 +201,17 @@ } } + Block getInfoLog() const + { + dint32 logSize; + dint32 count; + LIBGUI_GL.glGetProgramiv(name, GL_INFO_LOG_LENGTH, &logSize); + + Block log{Block::Size(logSize)}; + LIBGUI_GL.glGetProgramInfoLog(name, logSize, &count, reinterpret_cast(log.data())); + return log; + } + void link() { DENG2_ASSERT(name != 0); @@ -212,14 +223,7 @@ LIBGUI_GL.glGetProgramiv(name, GL_LINK_STATUS, &ok); if (!ok) { - dint32 logSize; - dint32 count; - LIBGUI_GL.glGetProgramiv(name, GL_INFO_LOG_LENGTH, &logSize); - - Block log(logSize); - LIBGUI_GL.glGetProgramInfoLog(name, logSize, &count, reinterpret_cast(log.data())); - - throw LinkerError("GLProgram::link", "Linking failed:\n" + log); + throw LinkerError("GLProgram::link", "Linking failed:\n" + getInfoLog()); } } @@ -453,10 +457,10 @@ void GLProgram::beginUse() const { LIBGUI_ASSERT_GL_OK(); - DENG2_ASSERT_IN_MAIN_THREAD(); - DENG2_ASSERT(QOpenGLContext::currentContext() != nullptr); + DENG2_ASSERT_IN_RENDER_THREAD(); DENG2_ASSERT(isReady()); DENG2_ASSERT(!d->inUse); + LIBGUI_ASSERT_GL_CONTEXT_ACTIVE(); if (d->needRebuild) { @@ -482,6 +486,7 @@ void GLProgram::endUse() const { + DENG2_ASSERT_IN_RENDER_THREAD(); DENG2_ASSERT(d->inUse); d->inUse = false; @@ -517,4 +522,19 @@ return d->attribLocation[semantic]; } +bool GLProgram::validate() const +{ + LIBGUI_GL.glValidateProgram(d->name); + + int valid; + LIBGUI_GL.glGetProgramiv(d->name, GL_VALIDATE_STATUS, &valid); + if (valid == GL_FALSE) + { + qDebug() << "GLProgram" << d->name << this << "is not validated:"; + qDebug() << d->getInfoLog().constData(); + return false; + } + return true; +} + } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glshaderbank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glshaderbank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glshaderbank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glshaderbank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,14 +25,36 @@ #include #include #include +#include #include #include #include +#include #include namespace de { +static String processIncludes(String source, String const &sourceFolderPath) +{ + QRegularExpression const re("#include\\s+['\"]([^\"']+)['\"]"); + forever + { + auto found = re.match(source); + if (!found.hasMatch()) break; // No more includes. + + String incFilePath = sourceFolderPath / found.captured(1); + String incSource = String::fromUtf8(Block(App::rootFolder().locate(incFilePath))); + incSource = processIncludes(incSource, incFilePath.fileNamePath()); + + Rangei const capRange(found.capturedStart(), found.capturedEnd()); + source = source.substr(0, capRange.start) + + incSource + + source.substr(capRange.end); + } + return source; +} + DENG2_PIMPL(GLShaderBank) { struct Source : public ISource @@ -72,10 +94,17 @@ void insertDefinition(String const ¯oName, String const &content) { convertToSourceText(); - Block combo = GLShader::prefixToSource(source.toLatin1(), - Block(String("#define %1 %2\n").arg(macroName).arg(content).toLatin1())); + Block combo = GLShader::prefixToSource( + source.toLatin1(), + Block(String("#define %1 %2\n").arg(macroName).arg(content).toLatin1())); source = String::fromLatin1(combo); } + + void insertIncludes(GLShaderBank const &bank, Record const &def) + { + convertToSourceText(); + source = processIncludes(source, bank.absolutePathInContext(def, ".").fileNamePath()); + } }; GLShaderBank &bank; @@ -112,7 +141,8 @@ return bank.d->findShader(src.source, type); } // The program will hold the only ref to this shader. - return refless(new GLShader(type, src.source.toLatin1())); + return refless( + new GLShader(type, bank.d->prependPredefines(Block(src.source.toLatin1())))); } }; @@ -137,6 +167,7 @@ typedef QMap Shaders; // path -> shader Shaders shaders; + std::unique_ptr preDefines; Impl(Public *i) : Base(i) {} @@ -156,6 +187,25 @@ shaders.clear(); } + Block prependPredefines(const IByteArray &source) const + { + Block sourceText = source; + if (preDefines) + { + Block predefs; + for (auto i : preDefines->elements()) + { + predefs += String::format("#define %s %s\n", + i.first.value->asText().toLatin1().constData(), + i.second->asText().toLatin1().constData()) + .toLatin1(); + } + predefs += "#line 1\n"; + sourceText = predefs + sourceText; + } + return sourceText; + } + GLShader *findShader(String const &path, GLShader::Type type) { /// @todo Should check the modification time of the file to determine @@ -167,7 +217,8 @@ } // We don't have this one yet, load and compile it now. - GLShader *shader = new GLShader(type, App::rootFolder().locate(path)); + GLShader *shader = + new GLShader(type, prependPredefines(FS::locate(path))); shaders.insert(path, shader); return shader; } @@ -218,6 +269,11 @@ return program; } +void GLShaderBank::setPreprocessorDefines(const DictionaryValue &preDefines) +{ + d->preDefines.reset(static_cast(preDefines.duplicate())); +} + Bank::ISource *GLShaderBank::newSourceFromInfo(String const &id) { typedef Impl::Source Source; @@ -276,9 +332,14 @@ } } + // Handle #include directives in the source. + vtx .insertIncludes(*this, def); + frag.insertIncludes(*this, def); + + // Preprocessor defines (built-in and from the Info). if (def.has("defines")) { - DictionaryValue const &dict = def.getdt("defines"); + const DictionaryValue &dict = def.getdt("defines"); for (auto i : dict.elements()) { String const macroName = i.first.value->asText(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glshader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glshader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glshader.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glshader.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -30,8 +30,8 @@ DENG2_PIMPL(GLShader) { GLuint name; - Type type; - Block compiledSource; + Type type; +// Block compiledSource; Impl(Public *i) : Base(i), name(0), type(Vertex) {} @@ -114,51 +114,96 @@ return src; } -void GLShader::compile(Type shaderType, IByteArray const &source) +void GLShader::compile(Type shaderType, IByteArray const &shaderSource) { - static QByteArray const DEFAULT_VERSION("#version 120\n"); - -#ifndef LIBGUI_GLES2 +#if defined (DENG_OPENGL) + static const Block DEFAULT_VERSION("#version 330\n"); // With non-ES OpenGL, ignore the precision attributes. - static QByteArray const PREFIX("#ifndef GL_ES\n#define lowp\n#define mediump\n#define highp\n#endif\n"); + static const Block PREFIX("#ifndef GL_ES\n" + "# define lowp\n" + "# define mediump\n" + "# define highp\n" + "#endif\n"); +#else + int const glesVer = DENG_OPENGL_ES; + static Block const DEFAULT_VERSION(glesVer == 30? "#version 300 es\n" : "#version 100\n"); + static Block const PREFIX("\n"); #endif DENG2_ASSERT(shaderType == Vertex || shaderType == Fragment); - setState(NotReady); + Block preamble; + Block source = shaderSource; + + if (!source.contains("#version")) + { + preamble = DEFAULT_VERSION; + } + preamble += PREFIX; - // Keep a copy of the source for possible recompilation. - d->compiledSource = source; +// Keep a copy of the source for possible recompilation. +// d->compiledSource = src; + setState(NotReady); d->type = shaderType; d->alloc(); // Additional predefined symbols for the shader. - QByteArray predefs; +// Block predefs; if (shaderType == Vertex) { - predefs = QByteArray("#define DENG_VERTEX_SHADER\n"); + preamble += "#define DENG_VERTEX_SHADER\n"; + +#if defined (DENG_OPENGL) || (defined (DENG_OPENGL_ES) && DENG_OPENGL_ES == 30) + preamble += "#define DENG_VAR out\n" + "#define DENG_ATTRIB in\n"; +#else + preamble += "#define DENG_VAR varying\n" + "#define DENG_ATTRIB attribute\n"; +#endif } else { - predefs = QByteArray("#define DENG_FRAGMENT_SHADER\n"); + preamble += "#define DENG_FRAGMENT_SHADER\n"; + +#if defined (DENG_OPENGL_ES) + // Precision qualifiers required in fragment shaders. + preamble += "precision highp float;\n" + "precision highp int;\n"; +#endif + +#if defined (DENG_OPENGL) || (defined (DENG_OPENGL_ES) && DENG_OPENGL_ES == 30) + preamble += "#define DENG_VAR in\n" + "out vec4 out_FragColor;\n"; +#else + preamble += "#define DENG_VAR varying\n" + "#define out_FragColor gl_FragColor\n"; +#endif } - predefs += "#define DENG_MAX_BATCH_UNIFORMS " + QByteArray::number(MAX_BATCH_UNIFORMS) + "\n"; + preamble += String::format("#define DENG_MAX_BATCH_UNIFORMS %d\n", MAX_BATCH_UNIFORMS).toLatin1(); + +#if defined (DENG_OPENGL) || (defined (DENG_OPENGL_ES) && DENG_OPENGL_ES == 30) + preamble += "#define DENG_LAYOUT_LOC(x) layout(location = x)\n"; +#else + preamble += "#define DENG_LAYOUT_LOC(x)\n"; +#endif + + preamble += "#line 1\n"; // Prepare the shader source. This would be the time to substitute any // remaining symbols in the shader source. - Block src = prefixToSource(source, PREFIX + predefs); + //Block src = prefixToSource(source, PREFIX + predefs); // If version has not been specified, use the default one. - if (!src.contains("#version")) - { - src = DEFAULT_VERSION + src; - } - - char const *srcPtr = src.constData(); - LIBGUI_GL.glShaderSource(d->name, 1, &srcPtr, 0); +// if (!src.contains("#version")) +// { +// src = DEFAULT_VERSION + src; +// } + const char *srcPtr[] = {preamble.constData(), source.constData()}; + LIBGUI_GL.glShaderSource(d->name, 2, srcPtr, 0); LIBGUI_GL.glCompileShader(d->name); + LIBGUI_ASSERT_GL_OK(); // Check the compilation status. GLint status; @@ -169,7 +214,7 @@ dint32 count = 0; LIBGUI_GL.glGetShaderiv(d->name, GL_INFO_LOG_LENGTH, &logSize); - Block log(logSize); + Block log{Block::Size(logSize)}; LIBGUI_GL.glGetShaderInfoLog(d->name, logSize, &count, reinterpret_cast(log.data())); throw CompilerError("GLShader::compile", @@ -180,11 +225,11 @@ setState(Ready); } -void GLShader::recompile() -{ - d->release(); - compile(d->type, d->compiledSource); - DENG2_ASSERT(isReady()); -} +//void GLShader::recompile() +//{ +// d->release(); +// compile(d->type, d->compiledSource); +// DENG2_ASSERT(isReady()); +//} } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glstate.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glstate.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glstate.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glstate.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -21,10 +21,12 @@ */ #include "de/GLState" -#include "de/PersistentGLWindow" +#include "de/GLFramebuffer" +#include "de/GLWindow" #include "de/graphics/opengl.h" #include #include +#include namespace de { @@ -139,7 +141,7 @@ DENG2_PIMPL(GLState) { - BitField props; + BitField props; GLFramebuffer *target; Impl(Public *i) @@ -246,14 +248,21 @@ break; case internal::AlphaTest: - if (self().alphaTest()) + /*if (self().alphaTest()) LIBGUI_GL.glEnable(GL_ALPHA_TEST); else - LIBGUI_GL.glDisable(GL_ALPHA_TEST); + LIBGUI_GL.glDisable(GL_ALPHA_TEST);*/ + + // TODO: use a shared GLUniform available to all shaders that need it + + //qDebug() << "[GLState] Alpha test:" << (self().alphaTest()? "enabled" : "disabled"); break; case internal::AlphaLimit: - LIBGUI_GL.glAlphaFunc(GL_GREATER, self().alphaLimit()); + //LIBGUI_GL.glAlphaFunc(GL_GREATER, self().alphaLimit()); + + // TODO: use a shared GLUniform available to all shaders that need it + break; case internal::Blend: @@ -392,12 +401,17 @@ GLState::GLState(GLState const &other) : d(new Impl(this, *other.d)) {} -GLState &GLState::operator = (GLState const &other) +GLState &GLState::operator=(GLState const &other) { d.reset(new Impl(this, *other.d)); return *this; } +bool GLState::operator==(const GLState &other) +{ + return d->target == other.d->target && d->props == other.d->props; +} + GLState &GLState::setCull(gl::Cull mode) { d->props.set(internal::CullMode, duint(mode)); @@ -655,9 +669,9 @@ DENG2_ASSERT(GLDrawQueue_queuedElems == 0); #endif -/*#ifdef LIBGUI_USE_GLENTRYPOINTS - if (!glBindFramebuffer) return; -#endif*/ + // Actual OpenGL state shouldn't be changed outside the render thread. + // The main thread can still manipulate shared OpenGL objects, though. + DENG2_ASSERT_IN_RENDER_THREAD(); bool forceViewportAndScissor = false; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glsubbuffer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glsubbuffer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/glsubbuffer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/glsubbuffer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,18 +22,17 @@ DENG2_PIMPL_NOREF(GLSubBuffer) { - GLBuffer *host = nullptr; - Rangeui16 hostRange; - dsize size = 0; + GLBuffer * host = nullptr; + Rangeui16 hostRange; + dsize size = 0; internal::AttribSpecs format; - int batchIndexOffset = -1; + int batchIndexOffset = -1; }; GLSubBuffer::GLSubBuffer(Rangeui16 const &hostRange, GLBuffer &hostBuffer) : d(new Impl) { - //d->reservedSize = reservedSize; - d->host = &hostBuffer; + d->host = &hostBuffer; d->hostRange = hostRange; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gltexture.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gltexture.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gltexture.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gltexture.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -39,17 +39,17 @@ DENG2_PIMPL(GLTexture) { - Size size; + Size size; Image::Format format; - GLuint name; - GLenum texTarget; - Filter minFilter; - Filter magFilter; - MipFilter mipFilter; - Wraps wrap; - dfloat maxAnisotropy; - dfloat maxLevel; - TextureFlags flags; + GLuint name; + GLenum texTarget; + Filter minFilter; + Filter magFilter; + MipFilter mipFilter; + Wraps wrap; + dfloat maxAnisotropy; + dfloat maxLevel; + TextureFlags flags; Impl(Public *i) : Base(i) @@ -508,7 +508,7 @@ if (d->name) { d->glBind(); - GLInfo::EXT_framebuffer_object()->glGenerateMipmapEXT(d->texTarget); LIBGUI_ASSERT_GL_OK(); + LIBGUI_GL.glGenerateMipmap(d->texTarget); LIBGUI_ASSERT_GL_OK(); d->glUnbind(); d->flags |= MipmapAvailable; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gltextureframebuffer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gltextureframebuffer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gltextureframebuffer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gltextureframebuffer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -32,12 +32,12 @@ , DENG2_OBSERVES(DefaultSampleCount, Change) { Image::Format colorFormat; - Size size; - int _samples; ///< don't touch directly (0 == default) - GLTexture color; - GLTexture depthStencil; + Size size; + int _samples; ///< don't touch directly (0 == default) + GLTexture color; + GLTexture depthStencil; GLFramebuffer resolvedFbo; - Asset texFboState; + Asset texFboState; Impl(Public *i) : Base(i) @@ -245,14 +245,7 @@ LOG_AS("GLFramebuffer"); - // Check for some integral OpenGL functionality. - if (!GLInfo::extensions().EXT_packed_depth_stencil) - { - LOG_GL_WARNING("GL_EXT_packed_depth_stencil is missing, some features may be unavailable"); - } - d->texFboState.setState(Ready); - d->reconfigure(); } @@ -339,29 +332,6 @@ return GLFramebuffer::attachedTexture(attachment); } -/*void GLTextureFramebuffer::clear(GLFramebuffer::Flags const &attachments) -{ - d->framebuf.clear(attachments); -}*/ - -/*void GLTextureFramebuffer::blit(GLFramebuffer const &target) const -{ - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, glName()); - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, target.glName()); - - GLInfo::EXT_framebuffer_blit()->glBlitFramebufferEXT( - 0, 0, size().x, size().y, - 0, 0, target.size().x, target.size().y, - GL_COLOR_BUFFER_BIT, GL_LINEAR); - - GLInfo::EXT_framebuffer_object()->glBindFramebufferEXT(GL_FRAMEBUFFER, 0); -}*/ - -/*void GLTextureFramebuffer::swapBuffers(Canvas &canvas, gl::SwapBufferMode swapMode) -{ - d->swapBuffers(canvas, swapMode); -}*/ - /*void GLTextureFramebuffer::drawBuffer(float opacity) { d->uColor = Vector4f(1, 1, 1, opacity); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gluniform.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gluniform.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/gluniform.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/gluniform.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -35,7 +35,9 @@ dint int32; duint uint32; dfloat float32; + dint *ints; dfloat *floats; + Vector2f *vec2array; Vector3f *vec3array; Vector4f *vector; Matrix3f *mat3; @@ -54,10 +56,12 @@ { name.append('\0'); - DENG2_ASSERT(elemCount == 1 || (elemCount > 1 && (type == FloatArray || + DENG2_ASSERT(elemCount == 1 || (elemCount > 1 && (type == IntArray || + type == FloatArray || type == Mat4Array || type == Vec4Array || - type == Vec3Array ))); + type == Vec3Array || + type == Vec2Array))); // Allocate the value type. zap(value); switch (type) @@ -68,10 +72,18 @@ value.vector = new Vector4f; break; + case IntArray: + value.ints = new int[elemCount]; + break; + case FloatArray: value.floats = new float[elemCount]; break; + case Vec2Array: + value.vec2array = new Vector2f[elemCount]; + break; + case Vec3Array: value.vec3array = new Vector3f[elemCount]; break; @@ -109,10 +121,18 @@ delete value.vector; break; + case IntArray: + delete [] value.ints; + break; + case FloatArray: delete [] value.floats; break; + case Vec2Array: + delete [] value.vec2array; + break; + case Vec3Array: delete [] value.vec3array; break; @@ -403,6 +423,17 @@ return *this; } +GLUniform &GLUniform::set(const int *intArray, dsize count) +{ + DENG2_ASSERT(d->type == IntArray); + DENG2_ASSERT(count <= d->elemCount); + + memcpy(d->value.ints, intArray, sizeof(int) * count); + d->usedElemCount = duint16(count); + d->markAsChanged(); + return *this; +} + GLUniform &GLUniform::set(float const *floatArray, dsize count) { DENG2_ASSERT(d->type == FloatArray); @@ -425,6 +456,17 @@ return *this; } +GLUniform &GLUniform::set(const Matrix4f *mat4Array, dsize count) +{ + DENG2_ASSERT(d->type == Mat4Array); + DENG2_ASSERT(count <= d->elemCount); + + memcpy(d->value.mat4, mat4Array, sizeof(Matrix4f) * count); + d->usedElemCount = duint16(count); + d->markAsChanged(); + return *this; +} + GLUniform &GLUniform::setUsedElementCount(duint elementCount) { DENG2_ASSERT(elementCount <= d->elemCount); @@ -531,6 +573,8 @@ void GLUniform::applyInProgram(GLProgram &program) const { + LIBGUI_ASSERT_GL_OK(); + int loc = program.glUniformLocation(d->name.constData()); if (loc < 0) { @@ -544,59 +588,69 @@ { case Int: LIBGUI_GL.glUniform1i(loc, d->value.int32); - LIBGUI_ASSERT_GL_OK(); + break; + + case IntArray: + LIBGUI_GL.glUniform1iv(loc, d->usedElemCount, d->value.ints); break; case UInt: - LIBGUI_GL.glUniform1i(loc, d->value.uint32); - LIBGUI_ASSERT_GL_OK(); + LIBGUI_GL.glUniform1ui(loc, d->value.uint32); break; case Float: LIBGUI_GL.glUniform1f(loc, d->value.float32); - LIBGUI_ASSERT_GL_OK(); break; case FloatArray: LIBGUI_GL.glUniform1fv(loc, d->usedElemCount, d->value.floats); - LIBGUI_ASSERT_GL_OK(); break; case Vec2: LIBGUI_GL.glUniform2f(loc, d->value.vector->x, d->value.vector->y); - LIBGUI_ASSERT_GL_OK(); + break; + + case Vec2Array: + LIBGUI_GL.glUniform2fv(loc, d->usedElemCount, &d->value.vec2array->x); break; case Vec3: LIBGUI_GL.glUniform3f(loc, d->value.vector->x, d->value.vector->y, d->value.vector->z); - LIBGUI_ASSERT_GL_OK(); break; case Vec3Array: LIBGUI_GL.glUniform3fv(loc, d->usedElemCount, &d->value.vec3array->x); // sequentially laid out - LIBGUI_ASSERT_GL_OK(); break; case Vec4: case Vec4Array: LIBGUI_GL.glUniform4fv(loc, d->usedElemCount, &d->value.vector->x); // sequentially laid out - LIBGUI_ASSERT_GL_OK(); break; case Mat3: LIBGUI_GL.glUniformMatrix3fv(loc, 1, GL_FALSE, d->value.mat3->values()); - LIBGUI_ASSERT_GL_OK(); break; case Mat4: case Mat4Array: LIBGUI_GL.glUniformMatrix4fv(loc, d->usedElemCount, GL_FALSE, d->value.mat4->values()); // sequentially laid out - LIBGUI_ASSERT_GL_OK(); break; - default: + case Sampler2D: + case SamplerCube: + // Not set here. GLProgram sets the sampler values according to where textures are bound. break; } + +#if defined (DENG2_DEBUG) + { + GLenum err = LIBGUI_GL.glGetError(); + if (err != GL_NO_ERROR) + { + qDebug() << "[GLUniform] Failure with uniform:" << d->name << "loc:" << loc; + } + } +#endif } } // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/heightmap.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/heightmap.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/heightmap.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/heightmap.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,10 +24,10 @@ DENG2_PIMPL_NOREF(HeightMap) { - QImage heightImage; - QImage normalImage; + QImage heightImage; + QImage normalImage; Vector2f mapSize; - float heightRange = 1.f; + float heightRange = 1.f; Vector2f pixelCoordf(Vector2f const &worldPos) const { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/imagebank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/imagebank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/imagebank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/imagebank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -18,7 +18,8 @@ #include "de/ImageBank" #include "de/App" -#include "de/Folder" +#include "de/FileSystem" +#include "de/ImageFile" #include @@ -29,8 +30,12 @@ struct ImageSource : public ISource { String filePath; + float pointRatio; - ImageSource(String const &path) : filePath(path) {} + ImageSource(String const &path, float pointRatio) + : filePath(path) + , pointRatio(pointRatio) + {} Time modifiedAt() const { @@ -39,9 +44,12 @@ Image load() const { - Block imageData; - App::rootFolder().locate(filePath) >> imageData; - return Image::fromData(imageData); + Image img = FS::locate(filePath).image(); + if (pointRatio > 0) + { + img.setPointRatio(pointRatio); + } + return img; } }; @@ -59,7 +67,7 @@ duint sizeInMemory() const { - return image.byteCount(); + return duint(image.byteCount()); } }; }; @@ -69,7 +77,7 @@ void ImageBank::add(DotPath const &path, String const &imageFilePath) { - Bank::add(path, new Impl::ImageSource(imageFilePath)); + Bank::add(path, new Impl::ImageSource(imageFilePath, 0.f)); } void ImageBank::addFromInfo(File const &file) @@ -87,7 +95,8 @@ Bank::ISource *ImageBank::newSourceFromInfo(String const &id) { Record const &def = info()[id]; - return new Impl::ImageSource(absolutePathInContext(def, def["path"])); + return new Impl::ImageSource(absolutePathInContext(def, def["path"]), + def.getf("pointRatio", 0.f)); } Bank::IData *ImageBank::loadFromSource(ISource &source) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/image.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/image.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/image.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/image.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -46,14 +46,14 @@ struct Header : public IReadable { - dbyte magic; - dbyte version; - dbyte encoding; - dbyte bitsPerPixel; + dbyte magic; + dbyte version; + dbyte encoding; + dbyte bitsPerPixel; duint16 xMin, yMin; duint16 xMax, yMax; duint16 hRes, vRes; - dbyte colorPlanes; + dbyte colorPlanes; duint16 bytesPerLine; duint16 paletteType; @@ -338,6 +338,7 @@ QImage image; Block pixels; ByteRefArray refPixels; + float pointRatio = 1.f; Impl(Public *i, QImage const &img = QImage()) : Base(i), format(UseQImageFormat), image(img) @@ -345,13 +346,14 @@ size = Size(img.width(), img.height()); } - Impl(Public *i, Impl const &other) - : Base (i), - format (other.format), - size (other.size), - image (other.image), - pixels (other.pixels), - refPixels(other.refPixels) + Impl(Public * i, Impl const &other) + : Base(i) + , format(other.format) + , size(other.size) + , image(other.image) + , pixels(other.pixels) + , refPixels(other.refPixels) + , pointRatio(other.pointRatio) {} Impl(Public *i, Size const &imgSize, Format imgFormat, IByteArray const &imgPixels) @@ -367,7 +369,7 @@ {} Image::Image(Image const &other) - : de::ISerializable(), d(new Impl(this, *other.d)) + : d(new Impl(this, *other.d)) {} Image::Image(QImage const &image) : d(new Impl(this, image)) @@ -381,7 +383,7 @@ : d(new Impl(this, size, format, refPixels)) {} -Image &Image::operator = (Image const &other) +Image &Image::operator=(Image const &other) { d.reset(new Impl(this, *other.d)); return *this; @@ -452,7 +454,7 @@ { return d->image.bytesPerLine(); } - return depth()/8 * d->size.x; + return depth() / 8 * d->size.x; } int Image::byteCount() const @@ -465,7 +467,7 @@ { return d->pixels.size(); } - return depth()/8 * d->size.x * d->size.y; + return depth() / 8 * d->size.x * d->size.y; } void const *Image::bits() const @@ -587,6 +589,16 @@ return glFormat(d->format); } +float Image::pointRatio() const +{ + return d->pointRatio; +} + +void Image::setPointRatio(float pointsPerPixel) +{ + d->pointRatio = pointsPerPixel; +} + Image Image::subImage(Rectanglei const &subArea) const { IMAGE_ASSERT_EDITABLE(d); @@ -601,8 +613,10 @@ DENG2_ASSERT(d->image.format() != QImage::Format_Invalid); QImage resized(QSize(size.x, size.y), d->image.format()); + resized.fill(0); + QPainter painter(&resized); - painter.drawImage(QPoint(0, 0), d->image); + painter.drawImage(QRect(QPoint(0, 0), resized.size()), d->image); d->image = resized; d->size = size; } @@ -669,12 +683,10 @@ duint16 r = (*ptr & 0xff0000) >> 16; duint16 a = (*ptr & 0xff000000) >> 24; - QColor const mult((color.x + 1) * r >> 8, - (color.y + 1) * g >> 8, - (color.z + 1) * b >> 8, - (color.w + 1) * a >> 8); - - *ptr++ = mult.rgba(); + *ptr++ = qRgba((color.x + 1) * r >> 8, + (color.y + 1) * g >> 8, + (color.z + 1) * b >> 8, + (color.w + 1) * a >> 8); } } return copy; @@ -814,8 +826,12 @@ return GLPixelFormat(GL_RGB, GL_UNSIGNED_BYTE, 1); case QImage::Format_RGB32: +#if defined (DENG_OPENGL) /// @todo Is GL_BGR in any GL standard spec? Check for EXT_bgra. return GLPixelFormat(GL_BGR, GL_UNSIGNED_BYTE, 4); +#else + return GLPixelFormat(GL_BGRA8_EXT, GL_UNSIGNED_BYTE, 4); +#endif case QImage::Format_ARGB32: /// @todo Is GL_BGRA in any GL standard spec? Check for EXT_bgra. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/imagefile.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/imagefile.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/imagefile.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/imagefile.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -40,7 +40,7 @@ ~Impl() { - qDeleteAll(filtered.values()); + qDeleteAll(filtered); } ImageFile *makeOrGetFiltered(BuiltInFilter filter) @@ -169,7 +169,12 @@ } else { - return Image::fromData(*source(), extension()); + Image img = Image::fromData(*source(), extension()); + if (source()->name().contains("@2x.", Qt::CaseInsensitive)) + { + img.setPointRatio(.5f); + } + return img; } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/modeldrawable.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -718,7 +718,9 @@ animNameToIndex.clear(); for (duint i = 0; i < scene->mNumAnimations; ++i) { - LOG_GL_VERBOSE("Animation #%i name:%s") << i << scene->mAnimations[i]->mName.C_Str(); + LOG_GL_VERBOSE("Animation #%i name:%s tps:%f") + << i << scene->mAnimations[i]->mName.C_Str() + << scene->mAnimations[i]->mTicksPerSecond; String const name = scene->mAnimations[i]->mName.C_Str(); if (!name.isEmpty()) @@ -1897,7 +1899,7 @@ d->anims.clear(); } -void ModelDrawable::Animator::advanceTime(TimeDelta const &) +void ModelDrawable::Animator::advanceTime(TimeSpan const &) { // overridden } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/packageiconbank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/packageiconbank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/packageiconbank.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/packageiconbank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,124 @@ +/** @file packageiconbank.cpp Bank for package icons. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * LGPL: http://www.gnu.org/licenses/lgpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 3 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser + * General Public License for more details. You should have received a copy of + * the GNU Lesser General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/PackageIconBank" +#include +#include + +namespace de { + +DENG2_PIMPL_NOREF(PackageIconBank) +{ + class PackageImageSource : public TextureBank::ImageSource + { + public: + PackageImageSource(Path const &packagePath, + Size const &displaySize) + : ImageSource(packagePath) + , _displaySize(displaySize) + { + DENG2_ASSERT(packagePath.lastSegment().toStringRef().endsWith(".pack")); + } + + Image load() const override + { + const String iconPath = sourcePath() / QStringLiteral("icon"); + + Image img; + if (ImageFile const *file = FS::tryLocate(iconPath + ".jpg")) + { + img = file->image(); + } + else if (ImageFile const *file = FS::tryLocate(iconPath + ".png")) + { + img = file->image(); + } + if (!img.isNull()) + { + // Cut to square aspect first. + if (img.height() > img.width()) + { + duint const off = img.height() - img.width(); + img = img.subImage(Rectanglei(0, off/2, img.width(), img.width())); + } + else if (img.width() > img.height()) + { + duint const off = img.width() - img.height(); + img = img.subImage(Rectanglei(off/2, 0, img.height(), img.height())); + } + + if (img.width() > _displaySize.x) + { + // Resize to display size. + img.resize(_displaySize); + } + } + img.setPointRatio(1.f); + return img; + } + + private: + Size _displaySize; + }; + + Size displaySize; + + static bool doesPackageHaveIcon(const Path &packagePath) + { + return FS::exists(packagePath / "icon.jpg") || + FS::exists(packagePath / "icon.png"); + } +}; + +PackageIconBank::PackageIconBank() + : TextureBank("PackageIconBank", BackgroundThread | DisableHotStorage) + , d(new Impl) +{ + setSeparator('/'); // expect package paths as keys +} + +void PackageIconBank::setDisplaySize(Size const &displaySize) +{ + d->displaySize = displaySize; +} + +Id PackageIconBank::packageIcon(File const &packageFile) +{ + const Path packagePath = packageFile.path(); + if (!has(packagePath)) + { + add(packagePath, new Impl::PackageImageSource(packagePath, d->displaySize)); + } + if (isLoaded(packagePath)) + { + // Already have it. + return TextureBank::texture(packagePath); + } + LOG_AS("PackageIconBank"); + LOG_RES_VERBOSE("Loading icon from \"%s\"") << packagePath.toString(); + // Every new request goes to the front of the queue. + load(packagePath, BeforeQueued); + return Id::None; +} + +bool PackageIconBank::packageContainsIcon(const de::File &packageFile) const +{ + return Impl::doesPackageHaveIcon(packageFile.path()); +} + +} // namespace de diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/rowatlasallocator.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/rowatlasallocator.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/rowatlasallocator.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/rowatlasallocator.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -71,11 +71,11 @@ { Slot *next = nullptr; Slot *prev = nullptr; - Row *row; + Row * row; - Id id { Id::None }; ///< Id of allocation here, or Id::None if free. - int x = 0; ///< Left edge of the slot. - duint width = 0; ///< Width of the slot. + Id id{Id::None}; ///< Id of allocation here, or Id::None if free. + int x = 0; ///< Left edge of the slot. + duint width = 0; ///< Width of the slot. dsize usedArea = 0; Slot(Row *owner) : row(owner) {} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/texturebank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/texturebank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/graphics/texturebank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/graphics/texturebank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -42,19 +42,43 @@ struct TextureData : public IData { Impl *d; - Id id { Id::None }; + Id _id { Id::None }; + std::unique_ptr pendingImage; TextureData(Image const &image, Impl *owner) : d(owner) { - id = d->atlas->alloc(image); + if (image) + { + if (d->atlas) + { + _id = d->atlas->alloc(image); + } + else + { + pendingImage.reset(new Image(image)); + } + } /// @todo Reduce size if doesn't fit? Can be expanded when requested for use. } ~TextureData() { - d->pathForAtlasId.remove(id); - d->atlas->release(id); + if (_id) + { + d->pathForAtlasId.remove(_id); + d->atlas->release(_id); + } + } + + Id const &id() + { + if (pendingImage && d->atlas) + { + _id = d->atlas->alloc(*pendingImage); + pendingImage.reset(); + } + return _id; } }; @@ -70,7 +94,8 @@ } }; -TextureBank::TextureBank() : Bank("TextureBank"), d(new Impl(this)) +TextureBank::TextureBank(char const *nameForLog, Flags const &flags) + : Bank(nameForLog, flags), d(new Impl(this)) {} void TextureBank::setAtlas(IAtlas *atlas) @@ -85,7 +110,7 @@ Id const &TextureBank::texture(DotPath const &id) { - return data(id).as().id; + return data(id).as().id(); } Path TextureBank::sourcePathForAtlasId(Id const &id) const @@ -101,7 +126,10 @@ Bank::IData *TextureBank::loadFromSource(ISource &source) { auto *data = new Impl::TextureData(source.as().load(), d); - d->pathForAtlasId.insert(data->id, source.as().sourcePath()); + if (auto const &texId = data->id()) + { + d->pathForAtlasId.insert(texId, source.as().sourcePath()); + } return data; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/guiapp.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/guiapp.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/guiapp.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/guiapp.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,6 +24,7 @@ #include #include +#include #ifdef DENG2_QT_5_0_OR_NEWER # include @@ -36,29 +37,42 @@ DENG2_PIMPL(GuiApp) { GuiLoop loop; + QThread *renderThread; Impl(Public *i) : Base(i) { + loop.setRate(120); loop.audienceForIteration() += self(); + + // The default render thread is the main thread. + renderThread = QThread::currentThread(); } }; void GuiApp::setDefaultOpenGLFormat() // static { QSurfaceFormat fmt; +#if defined (DENG_OPENGL_ES) + fmt.setRenderableType(QSurfaceFormat::OpenGLES); + fmt.setVersion(DENG_OPENGL_ES / 10, DENG_OPENGL_ES % 10); +#else fmt.setRenderableType(QSurfaceFormat::OpenGL); - fmt.setProfile(QSurfaceFormat::CompatibilityProfile); - fmt.setVersion(2, 1); + fmt.setProfile(QSurfaceFormat::CoreProfile); + fmt.setVersion(3, 3); +#endif fmt.setDepthBufferSize(24); fmt.setStencilBufferSize(8); fmt.setSwapBehavior(QSurfaceFormat::DoubleBuffer); +#if defined (DENG2_DEBUG) + fmt.setOption(QSurfaceFormat::DebugContext, true); +#endif QSurfaceFormat::setDefaultFormat(fmt); } GuiApp::GuiApp(int &argc, char **argv) - : QApplication(argc, argv), - App(applicationFilePath(), arguments()), - d(new Impl(this)) + : LIBGUI_GUIAPP_BASECLASS(argc, argv) + , App(applicationFilePath(), arguments()) + , d(new Impl(this)) { static ImageFile::Interpreter intrpImageFile; fileSystem().addInterpreter(intrpImageFile); @@ -83,7 +97,7 @@ { try { - return QApplication::notify(receiver, event); + return LIBGUI_GUIAPP_BASECLASS::notify(receiver, event); } catch (std::exception const &error) { @@ -106,7 +120,7 @@ LOGDEV_NOTE("Starting GuiApp event loop..."); d->loop.start(); - int code = QApplication::exec(); + int code = LIBGUI_GUIAPP_BASECLASS::exec(); LOGDEV_NOTE("GuiApp event loop exited with code %i") << code; return code; @@ -117,7 +131,7 @@ LOGDEV_MSG("Stopping GuiApp event loop"); d->loop.stop(); - return QApplication::exit(code); + return LIBGUI_GUIAPP_BASECLASS::exit(code); } GuiLoop &GuiApp::loop() @@ -125,6 +139,20 @@ return d->loop; } +bool GuiApp::inRenderThread() +{ + if (!App::appExists()) + { + return false; + } + return DENG2_GUI_APP->d->renderThread == QThread::currentThread(); +} + +void GuiApp::setRenderThread(QThread *thread) +{ + DENG2_GUI_APP->d->renderThread = thread; +} + void GuiApp::loopIteration() { // Update the clock time. de::App listens to this clock and will inform diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/input/keyevent.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/input/keyevent.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/input/keyevent.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/input/keyevent.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -27,7 +27,7 @@ #include #include -#if defined(UNIX) && !defined(MACOSX) +#if defined (DENG_X11) # include # include # include @@ -48,7 +48,7 @@ # endif #endif -#ifdef WIN32 +#if defined (WIN32) static int win32Keymap[256]; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/persistentglwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/persistentglwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/persistentglwindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/persistentglwindow.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,6 +22,8 @@ * http://www.gnu.org/licenses */ +#if !defined (DENG_MOBILE) + #include "de/PersistentGLWindow" #include "de/GuiApp" #include "de/DisplayMode" @@ -34,6 +36,7 @@ #include #include +#include #include #include #include @@ -46,11 +49,16 @@ int const PersistentGLWindow::MIN_HEIGHT = 240; static int const BREAK_CENTERING_THRESHOLD = 5; - static QRect desktopRect() { + //return QApplication::desktop()->screenGeometry(); + /// @todo Multimonitor? This checks the default screen. - return QApplication::desktop()->screenGeometry(); +#if defined (DENG2_QT_5_6_OR_NEWER) + return QGuiApplication::primaryScreen()->geometry(); +#else + return QGuiApplication::screens().at(0)->geometry(); +#endif } static QRect centeredQRect(Vector2ui const &size) @@ -103,11 +111,11 @@ String winId; Rectanglei windowRect; ///< Window geometry in windowed mode. Size fullSize; ///< Dimensions in a fullscreen mode. - int colorDepthBits; - Flags flags; + int colorDepthBits = 0; + float refreshRate = 0.f; + Flags flags { None }; - State(String const &id) - : winId(id), colorDepthBits(0), flags(None) + State(String const &id) : winId(id) {} bool operator == (State const &other) const @@ -116,7 +124,8 @@ windowRect == other.windowRect && fullSize == other.fullSize && colorDepthBits == other.colorDepthBits && - flags == other.flags); + flags == other.flags && + refreshRate == other.refreshRate); } bool operator != (State const &other) const @@ -195,10 +204,11 @@ << NumberValue(fullSize.y); config.set(configName("fullSize"), array); - config.set(configName("center"), isCentered()); - config.set(configName("maximize"), isMaximized()); - config.set(configName("fullscreen"), isFullscreen()); - config.set(configName("colorDepth"), colorDepthBits); + config.set(configName("center"), isCentered()); + config.set(configName("maximize"), isMaximized()); + config.set(configName("fullscreen"), isFullscreen()); + config.set(configName("colorDepth"), colorDepthBits); + config.set(configName("refreshRate"), refreshRate); // FSAA and vsync are saved as part of the Config. //config.set(configName("fsaa"), isAntialiased()); @@ -225,7 +235,8 @@ fullSize = Size(fs.at(0).asNumber(), fs.at(1).asNumber()); } - colorDepthBits = config.geti(configName("colorDepth")); + colorDepthBits = config.geti(configName("colorDepth")); + refreshRate = config.getf(configName("refreshRate")); setFlag(Centered, config.getb(configName("center"))); setFlag(Maximized, config.getb(configName("maximize"))); setFlag(Fullscreen, config.getb(configName("fullscreen"))); @@ -250,7 +261,7 @@ { if (isFullscreen()) { - return DisplayMode_FindClosest(fullSize.x, fullSize.y, colorDepthBits, 0); + return DisplayMode_FindClosest(fullSize.x, fullSize.y, colorDepthBits, refreshRate); } return DisplayMode_OriginalMode(); } @@ -304,6 +315,10 @@ DENG2_ASSERT(colorDepthBits >= 8 && colorDepthBits <= 32); break; + case PersistentGLWindow::RefreshRate: + refreshRate = float(de::max(0, attribs[i])) / 1000.f; + break; + case PersistentGLWindow::FullSceneAntialias: setFlag(State::FSAA, attribs[i]); break; @@ -375,6 +390,12 @@ attribs << PersistentGLWindow::ColorDepthBits << de::clamp(8, cmdLine.at(arg+1).toInt(), 32); } + if (int arg = cmdLine.check("-refreshrate", 1)) + { + attribs << PersistentGLWindow::RefreshRate + << int(cmdLine.at(arg + 1).toFloat() * 1000); + } + if (int arg = cmdLine.check("-xpos", 1)) { attribs << PersistentGLWindow::Left << cmdLine.at(arg+ 1 ).toInt() @@ -449,11 +470,11 @@ Type type; Rectanglei rect; - TimeDelta delay; ///< How long to wait before doing this. + TimeSpan delay; ///< How long to wait before doing this. - Task(Type t, TimeDelta defer = 0) + Task(Type t, TimeSpan defer = 0) : type(t), delay(defer) {} - Task(Rectanglei const &r, TimeDelta defer = 0) + Task(Rectanglei const &r, TimeSpan defer = 0) : type(SetGeometry), rect(r), delay(defer) {} }; @@ -524,6 +545,7 @@ return false; // Illegal value. break; + case RefreshRate: case Centered: case Maximized: break; @@ -558,10 +580,11 @@ State mod = state; mod.applyAttributes(attribs); - LOGDEV_GL_MSG("windowRect:%s fullSize:%s depth:%i flags:%x") + LOGDEV_GL_MSG("windowRect:%s fullSize:%s depth:%i refresh:%.1f flags:%x") << mod.windowRect.asText() << mod.fullSize.asText() << mod.colorDepthBits + << mod.refreshRate << mod.flags; // Apply them. @@ -588,7 +611,7 @@ // If the display mode needs to change, we will have to defer the rest // of the state changes so that everything catches up after the change. - TimeDelta defer = 0; + TimeSpan defer = 0; DisplayMode const *newMode = newState.displayMode(); bool modeChanged = false; @@ -606,6 +629,7 @@ modeChanged = DisplayMode_Change(newMode, newState.shouldCaptureScreen()); state.colorDepthBits = newMode->depth; + state.refreshRate = newMode->refreshRate; // Wait a while after the mode change to let changes settle in. #ifdef MACOSX @@ -772,11 +796,12 @@ st.windowRect = self().windowRect(); st.fullSize = state.fullSize; st.colorDepthBits = DisplayMode_Current()->depth; + st.refreshRate = DisplayMode_Current()->refreshRate; st.flags = (self().isMaximized()? State::Maximized : State::None) | (self().isFullScreen()? State::Fullscreen : State::None) | - (state.isCentered()? State::Centered : State::None); + (state.isCentered()? State::Centered : State::None); return st; } @@ -791,6 +816,7 @@ { try { + connect(this, SIGNAL(visibilityChanged(QWindow::Visibility)), this, SLOT(windowVisibilityChanged())); restoreFromConfig(); } catch (Error const &er) @@ -863,6 +889,11 @@ return d->state.colorDepthBits; } +float PersistentGLWindow::refreshRate() const +{ + return d->state.refreshRate; +} + void PersistentGLWindow::show(bool yes) { if (yes) @@ -920,6 +951,19 @@ d->checkQueue(); } +void PersistentGLWindow::windowVisibilityChanged() +{ + if (d->queue.isEmpty()) + { + d->state = d->widgetState(); + } + + DENG2_FOR_AUDIENCE2(AttributeChange, i) + { + i->windowAttributesChanged(*this); + } +} + String PersistentGLWindow::configName(String const &key) const { return d->state.configName(key); @@ -976,3 +1020,5 @@ } } // namespace de + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/coretextnativefont_macx.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/coretextnativefont_macx.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/coretextnativefont_macx.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/coretextnativefont_macx.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -344,7 +344,8 @@ // Text color. Vector4d const fg = foreground.zyxw().toVector4f() / 255.f; - CGColorRef fgColor = CGColorCreate(fontCache.colorspace(), &fg.x); + CGFloat fgValues[4] = { fg.x, fg.y, fg.z, fg.w }; + CGColorRef fgColor = CGColorCreate(fontCache.colorspace(), fgValues); // Ensure the color is used by recreating the attributed line string. d->cache.release(); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/fontbank.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/fontbank.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/fontbank.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/fontbank.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,22 +25,27 @@ namespace de { +static const String BLOCK_FONT = "font"; + DENG2_PIMPL(FontBank) { struct FontSource : public ISource { FontBank &bank; - String id; + String id; + + FontSource(FontBank &b, String const &fontId) + : bank(b) + , id(fontId) + {} - FontSource(FontBank &b, String const &fontId) : bank(b), id(fontId) {} Time modifiedAt() const { return bank.sourceModifiedAt(); } - Font *load() const + void initParams(QFont &font) const { - Record const &def = bank[id]; + const Record &def = bank[id]; - // Font family. - QFont font(def["family"]); + font.setFamily(def["family"]); // Size. String size = def["size"]; @@ -68,8 +73,21 @@ font.setCapitalization(caps == "uppercase"? QFont::AllUppercase : caps == "lowercase"? QFont::AllLowercase : QFont::MixedCase); + } + + Font *load() const + { + QFont params; + initParams(params); + return new Font(params); + } - return new Font(font); + void reload(Font &font) + { + // Only the size can change when reloading. + QFont params; + initParams(params); + font.initialize(params); } }; @@ -77,11 +95,15 @@ { Font *font; // owned - FontData(Font *f = 0) : font(f) {} + FontData(Font *f = nullptr) + : font(f) + {} + ~FontData() { delete font; } }; - float fontSizeFactor; + SafePtr sourceFile; + float fontSizeFactor; Impl(Public *i) : Base(i) @@ -89,17 +111,20 @@ {} }; -FontBank::FontBank() : InfoBank("FontBank", DisableHotStorage), d(new Impl(this)) +FontBank::FontBank() + : InfoBank("FontBank", DisableHotStorage) + , d(new Impl(this)) {} -void FontBank::addFromInfo(File const &file) +void FontBank::addFromInfo(const File &file) { LOG_AS("FontBank"); + d->sourceFile.reset(&file); parse(file); - addFromInfoBlocks("font"); + addFromInfoBlocks(BLOCK_FONT); } -Font const &FontBank::font(DotPath const &path) const +Font const &FontBank::font(const DotPath &path) const { return *data(path).as().font; } @@ -107,8 +132,30 @@ void FontBank::setFontSizeFactor(float sizeFactor) { // The overall UI scalefactor affects fonts. - d->fontSizeFactor = clamp(.1f, sizeFactor, 20.f) * - Config::get().getf("ui.scaleFactor", 1.f); + d->fontSizeFactor = clamp(.1f, sizeFactor, 20.f); + +#if defined (WIN32) + /* + * On Windows, fonts are automatically scaled by the operating system according + * to the display scaling factor (pixel ratio). Therefore, defaultstyle.pack + * does not scale fonts on Windows based on PIXEL_RATIO, and we need to apply + * the user's UI scaling here. + */ + d->fontSizeFactor *= Config::get().getf("ui.scaleFactor", 1.f); +#endif +} + +void FontBank::reload() +{ + if (d->sourceFile) + { + objectNamespace().clear(); + parse(*d->sourceFile); + for (const String &id : info().allBlocksOfType(BLOCK_FONT)) + { + source(id).as().reload(*data(id).as().font); + } + } } Bank::ISource *FontBank::newSourceFromInfo(String const &id) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/font.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/font.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/text/font.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/text/font.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,7 +25,7 @@ #include #include -#if defined(MACOSX) && defined(MACOS_10_7) +#if defined (DENG_IOS) || (defined(MACOSX) && defined(MACOS_10_7)) # include "../src/text/coretextnativefont_macx.h" namespace de { typedef CoreTextNativeFont PlatformFont; } #else @@ -54,7 +54,7 @@ spec.transform = font.transform(); } - bool operator == (FontParams const &other) const + bool operator==(FontParams const &other) const { return fequal(size, other.size) && spec == other.spec @@ -80,7 +80,7 @@ QHash fontMods; ~ThreadFonts() { - qDeleteAll(fontMods.values()); + qDeleteAll(fontMods); } }; } @@ -148,10 +148,19 @@ internal::ThreadFonts &getThreadFonts() { auto &hash = fontsForThread.localData(); - if (!hash.contains(thisPublic)) + auto found = hash.find(thisPublic); + if (found != hash.end()) { - hash[thisPublic].font = PlatformFont(referenceFont); + auto &tf = found.value(); + if (fequal(tf.font.size(), float(referenceFont.pointSizeF()))) + { + return tf; + } + // Size has changed, re-initialize the font. + qDeleteAll(tf.fontMods); + tf.fontMods.clear(); } + hash[thisPublic].font = PlatformFont(referenceFont); return hash[thisPublic]; } @@ -268,6 +277,12 @@ Font::Font(QFont const &font) : d(new Impl(this, font)) {} +void Font::initialize(const QFont &font) +{ + d->referenceFont = font; + d->updateMetrics(); +} + Rectanglei Font::measure(String const &textLine) const { return measure(textLine, RichFormat::fromPlainText(textLine)); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/windoweventhandler.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/windoweventhandler.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libgui/src/windoweventhandler.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libgui/src/windoweventhandler.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -32,13 +31,13 @@ DENG2_PIMPL(WindowEventHandler) { GLWindow *window; - bool mouseGrabbed = false; - QPoint prevMousePos; - QTime prevWheelAt; - QPoint wheelAngleAccum; - int wheelDir[2]; -#ifdef WIN32 - bool altIsDown = false; + bool mouseGrabbed = false; + QPoint prevMousePos; + QTime prevWheelAt; + QPoint wheelAngleAccum; + int wheelDir[2]; +#if defined(WIN32) + bool altIsDown = false; #endif Impl(Public *i, GLWindow *parentWindow) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/concurrency.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/concurrency.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/concurrency.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/concurrency.h 2018-12-11 07:08:24.000000000 +0000 @@ -97,11 +97,7 @@ * @def DENG_ASSERT_IN_MAIN_THREAD * In a debug build, this asserts that the current code is executing in the main thread. */ -#ifdef _DEBUG -# define DENG_ASSERT_IN_MAIN_THREAD() { DENG_ASSERT(Sys_InMainThread()); } -#else -# define DENG_ASSERT_IN_MAIN_THREAD() -#endif +#define DENG_ASSERT_IN_MAIN_THREAD() DENG2_ASSERT_IN_MAIN_THREAD() /** * Starts a new thread. @@ -161,12 +157,6 @@ void Sem_V(sem_t semaphore); #endif -/* - * Private functions. - */ - -void Sys_MarkAsMainThread(void); - /// @} #ifdef __cplusplus diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/liblegacy.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/liblegacy.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/liblegacy.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/liblegacy.h 2018-12-11 07:08:24.000000000 +0000 @@ -77,6 +77,18 @@ # define DENG_NORETURN __attribute__((__noreturn__)) #endif +#if defined (DENG_IOS) +# define DENG_VISIBLE_SYMBOL __attribute__((visibility("default"))) +#else +# define DENG_VISIBLE_SYMBOL +#endif + +#if defined (DENG_STATIC_LINK) +# define DENG_ENTRYPOINT static +#else +# define DENG_ENTRYPOINT DENG_EXTERN_C +#endif + #if !defined(_MSC_VER) #endif @@ -142,6 +154,10 @@ #define FEQUAL(x, y) (INRANGE_OF(x, y, FLOATEPSILON)) +#define IS_ZERO(x) FEQUAL(x, 0) + +#define NON_ZERO(x) (!IS_ZERO(x)) + #define ROUND(x) ((int) (((x) < 0.0f)? ((x) - 0.5f) : ((x) + 0.5f))) #ifdef ABS diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/point.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/point.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/point.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/point.h 2018-12-11 07:08:24.000000000 +0000 @@ -43,10 +43,10 @@ }; int xy[2]; }; -#ifdef __cplusplus - Point2Raw_s(int x_ = 0, int y_ = 0) : x(x_), y(y_) {} - Point2Raw_s(Point2Raw_s const &other) : x(other.x), y(other.y) {} -#endif +//#ifdef __cplusplus +// Point2Raw_s(int x_ = 0, int y_ = 0) : x(x_), y(y_) {} +// Point2Raw_s(Point2Raw_s const &other) : x(other.x), y(other.y) {} +//#endif } Point2Raw; struct point2_s; // The Point2f instance (opaque). diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/rect.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/rect.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/rect.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/rect.h 2018-12-11 07:08:24.000000000 +0000 @@ -39,10 +39,6 @@ typedef struct RectRaw_s { Point2Raw origin; Size2Raw size; -#ifdef __cplusplus - RectRaw_s(int x = 0, int y = 0, int width = 0, int height = 0) - : origin(x, y), size(width, height) {} -#endif } RectRaw; /** diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/size.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/size.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/size.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/size.h 2018-12-11 07:08:24.000000000 +0000 @@ -43,9 +43,9 @@ }; int widthHeight[2]; }; -#ifdef __cplusplus - Size2Raw_s(int w = 0, int h = 0) : width(w), height(h) {} -#endif +//#ifdef __cplusplus +// Size2Raw_s(int w = 0, int h = 0) : width(w), height(h) {} +//#endif } Size2Raw; struct size2_s; // The Size2 instance (opaque). diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/strutil.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/strutil.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/include/de/strutil.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/include/de/strutil.h 2018-12-11 07:08:24.000000000 +0000 @@ -74,9 +74,9 @@ // String Utilities -DENG_PUBLIC char* M_SkipWhite(char* str); +DENG_PUBLIC char *M_SkipWhite(const char *str); -DENG_PUBLIC char* M_FindWhite(char* str); +DENG_PUBLIC char *M_FindWhite(const char *str); DENG_PUBLIC void M_StripLeft(char* str); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/binangle.c doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/binangle.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/binangle.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/binangle.c 2018-12-11 07:08:24.000000000 +0000 @@ -20,7 +20,7 @@ * 02110-1301 USA */ -#include "binangle.h" +#include "de/binangle.h" #include // Define this to use the lookup table implementation diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/concurrency.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/concurrency.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/concurrency.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/concurrency.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,13 +25,12 @@ #include #include #include +#include #include #include #include #include -static uint mainThreadId = 0; ///< ID of the main thread. - CallbackThread::CallbackThread(systhreadfunc_t func, void *param) : _callback(func), _parm(param), _returnValue(0), _exitStatus(DENG_THREAD_STOPPED_NORMALLY), @@ -111,20 +110,20 @@ _terminationFunc = func; } -void Sys_MarkAsMainThread(void) +/*void Sys_MarkAsMainThread(void) { // This is the main thread. mainThreadId = Sys_CurrentThreadId(); -} +}*/ dd_bool Sys_InMainThread(void) { - return mainThreadId == Sys_CurrentThreadId(); + return de::App::inMainThread(); } void Thread_Sleep(int milliseconds) { - de::TimeDelta::fromMilliSeconds(milliseconds).sleep(); + de::TimeSpan::fromMilliSeconds(milliseconds).sleep(); } thread_t Sys_StartThread(systhreadfunc_t startpos, void *parm, void (*terminationFunc)(systhreadexitstatus_t)) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/liblegacy.c doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/liblegacy.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/liblegacy.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/liblegacy.c 2018-12-11 07:08:24.000000000 +0000 @@ -35,7 +35,6 @@ bamsInit(); Timer_Init(); Z_Init(); - Sys_MarkAsMainThread(); } void Libdeng_Shutdown(void) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/mathutil.c doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/mathutil.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/mathutil.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/mathutil.c 2018-12-11 07:08:24.000000000 +0000 @@ -2079,11 +2079,11 @@ slopetype_t M_SlopeTypeXY(double dx, double dy) { - if (FEQUAL(dx, 0)) + if (IS_ZERO(dx)) { return ST_VERTICAL; } - else if (FEQUAL(dy, 0)) + else if (IS_ZERO(dy)) { return ST_HORIZONTAL; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/strutil.c doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/strutil.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/strutil.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/strutil.c 2018-12-11 07:08:24.000000000 +0000 @@ -87,18 +87,18 @@ } #endif // UNIX -char* M_SkipWhite(char* str) +char *M_SkipWhite(const char *str) { while (*str && DENG_ISSPACE(*str)) str++; - return str; + return (char *) str; } -char* M_FindWhite(char* str) +char *M_FindWhite(const char *str) { while (*str && !DENG_ISSPACE(*str)) str++; - return str; + return (char *) str; } void M_StripLeft(char* str) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/timer.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/timer.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/liblegacy/src/timer.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/liblegacy/src/timer.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -125,7 +125,7 @@ #endif de::Time::updateCurrentHighPerformanceTime(); - de::TimeDelta const delta = de::Time::currentHighPerformanceTime() - startedAt; + de::TimeSpan const delta = de::Time::currentHighPerformanceTime() - startedAt; return (unsigned int) delta.asMilliSeconds(); } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/CMakeLists.txt 2018-12-11 07:08:24.000000000 +0000 @@ -17,7 +17,7 @@ deng_merge_sources (libshell src/*.cpp) deng_add_library (libshell ${SOURCES} ${HEADERS}) -target_link_libraries (libshell Deng::libcore) +target_link_libraries (libshell PUBLIC Deng::libcore) deng_deploy_library (libshell DengShell) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/abstractlineeditor.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/abstractlineeditor.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/abstractlineeditor.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/abstractlineeditor.h 2018-12-11 07:08:24.000000000 +0000 @@ -25,8 +25,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { class Lexicon; @@ -54,14 +53,14 @@ * * @param promptText Text for the prompt. */ - void setPrompt(String const &promptText); + void setPrompt(String const &promptText); String prompt() const; - void setText(String const &lineText); + void setText(String const &lineText); String text() const; void setCursor(int index); - int cursor() const; + int cursor() const; /** * Determines the position of a specific character on the wrapped lines. @@ -72,10 +71,10 @@ Vector2i lineCursorPos() const { return linePos(cursor()); } - bool isSuggestingCompletion() const; - Rangei completionRange() const; + bool isSuggestingCompletion() const; + Rangei completionRange() const; QStringList suggestedCompletions() const; - void acceptCompletion(); + void acceptCompletion(); /** * Defines the terms and rules for auto-completion. @@ -86,10 +85,7 @@ Lexicon const &lexicon() const; - enum EchoMode { - NormalEchoMode, - PasswordEchoMode - }; + enum EchoMode { NormalEchoMode, PasswordEchoMode }; /** * Determines how the entered text should be shown to the user. @@ -100,13 +96,7 @@ EchoMode echoMode() const; - enum KeyModifier { - Unmodified = 0, - Shift = 0x1, - Control = 0x2, - Alt = 0x4, - Meta = 0x8 - }; + enum KeyModifier { Unmodified = 0, Shift = 0x1, Control = 0x2, Alt = 0x4, Meta = 0x8 }; Q_DECLARE_FLAGS(KeyModifiers, KeyModifier) virtual bool handleControlKey(int qtKey, KeyModifiers const &mods = Unmodified); @@ -127,15 +117,12 @@ // Notifications: virtual void numberOfLinesChanged(int lineCount) = 0; - virtual void cursorMoved() = 0; - virtual void contentChanged() = 0; + virtual void cursorMoved() = 0; + virtual void contentChanged() = 0; virtual void autoCompletionBegan(String const &wordBase); virtual void autoCompletionEnded(bool accepted); - enum LineWrapUpdateBehavior { - RewrapNow, - WrapUnlessWrappedAlready - }; + enum LineWrapUpdateBehavior { RewrapNow, WrapUnlessWrappedAlready }; /// Request rewrapping the text. void updateLineWraps(LineWrapUpdateBehavior behavior); @@ -146,7 +133,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractLineEditor::KeyModifiers) -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_ABSTRACTLINEEDITOR_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/abstractlink.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/abstractlink.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/abstractlink.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/abstractlink.h 2018-12-11 07:08:24.000000000 +0000 @@ -26,8 +26,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Abstract network connection to a server. @@ -36,17 +35,14 @@ * * @ingroup shell */ -class LIBSHELL_PUBLIC AbstractLink : public QObject, public Transmitter +class LIBSHELL_PUBLIC AbstractLink + : public QObject + , public Transmitter { Q_OBJECT public: - enum Status - { - Disconnected, - Connecting, - Connected - }; + enum Status { Disconnected, Connecting, Connected }; public: AbstractLink(); @@ -57,7 +53,7 @@ * @param domain Domain/IP address of the server. * @param timeout Keep trying until this much time has passed. */ - virtual void connectDomain(String const &domain, TimeDelta const &timeout = 0); + virtual void connectDomain(String const &domain, TimeSpan const &timeout = 0); /** * Opens a connection to a server over the network. @@ -128,7 +124,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_ABSTRACTLINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/action.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/action.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/action.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/action.h 2018-12-11 07:08:24.000000000 +0000 @@ -23,15 +23,16 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Maps a key event to a signal. * * @ingroup textUi */ -class Action : public QObject, public de::Action +class Action + : public QObject + , public de::Action { Q_OBJECT @@ -66,13 +67,12 @@ ~Action(); private: - KeyEvent _event; - String _label; - QObject *_target; + KeyEvent _event; + String _label; + QObject * _target; char const *_slot; }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_ACTION_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/choicewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/choicewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/choicewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/choicewidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -22,8 +22,7 @@ #include "LabelWidget" #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Widget for selecting an item from multiple choices. @@ -73,7 +72,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_CHOICEWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/commandlinewidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/commandlinewidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/commandlinewidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/commandlinewidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,8 +21,7 @@ #include "LineEditWidget" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Text editor with a history. @@ -47,7 +46,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_COMMANDLINEWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/dialogwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/dialogwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/dialogwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/dialogwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,8 +21,7 @@ #include "TextWidget" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Base class for modal dialogs. @@ -79,7 +78,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace shell +}} // namespace de::shell #endif // LIBSHELL_DIALOGWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/doomsdayinfo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/doomsdayinfo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/doomsdayinfo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/doomsdayinfo.h 2018-12-11 07:08:24.000000000 +0000 @@ -24,8 +24,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Information about Doomsday Engine and its plugins. @@ -35,42 +34,34 @@ class LIBSHELL_PUBLIC DoomsdayInfo { public: - struct Game - { + struct Game { String title; String option; ///< Mode identifier. }; - enum OptionType - { - Toggle, - Choice, - Text - }; + enum OptionType { Toggle, Choice, Text }; - struct LIBSHELL_PUBLIC GameOption - { - struct LIBSHELL_PUBLIC Value - { + struct LIBSHELL_PUBLIC GameOption { + struct LIBSHELL_PUBLIC Value { String value; String label; String ruleSemantic; // for determining if the option is set Value(String const &value = String(), String const &label = String(), String const &ruleSemantic = String()) - : value(value), label(label), ruleSemantic(ruleSemantic) {} + : value(value) + , label(label) + , ruleSemantic(ruleSemantic) + {} }; - OptionType type; - String title; - String command; // e.g., "setmap %1" - Value defaultValue; + OptionType type; + String title; + String command; // e.g., "setmap %1" + Value defaultValue; QList allowedValues; - GameOption(OptionType type, - String title, - String command, - Value defaultValue = Value(), + GameOption(OptionType type, String title, String command, Value defaultValue = Value(), QList allowedValues = QList()); }; @@ -88,7 +79,6 @@ static NativePath defaultServerRuntimeFolder(); }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_DOOMSDAYINFO_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/editorhistory.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/editorhistory.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/editorhistory.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/editorhistory.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,8 +21,7 @@ #include "ITextEditor" -namespace de { -namespace shell { +namespace de { namespace shell { /** * History buffer for a text editor. Remembers past entries entered into the @@ -35,7 +34,7 @@ public: EditorHistory(ITextEditor *editor = 0); - void setEditor(ITextEditor &editor); + void setEditor(ITextEditor &editor); ITextEditor &editor(); /** @@ -66,11 +65,19 @@ */ bool handleControlKey(int qtKey); + /** + * Returns the history contents. + * + * @param maxCount Maximum number of history entries. 0 for unlimited. + */ + StringList fullHistory(int maxCount = 0) const; + + void setFullHistory(StringList history); + private: DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_ABSTRACTCOMMANDLINEEDITOR_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/inputdialog.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/inputdialog.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/inputdialog.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/inputdialog.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,8 +21,7 @@ #include "DialogWidget" -namespace de { -namespace shell { +namespace de { namespace shell { class LabelWidget; class LineEditWidget; @@ -38,9 +37,9 @@ public: InputDialog(de::String const &name = de::String()); - LabelWidget &label(); + LabelWidget & label(); LineEditWidget &lineEdit(); - MenuWidget &menu(); + MenuWidget & menu(); /** * Sets the width of the dialog. The default width is 50. @@ -73,7 +72,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_INPUTDIALOG_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/itexteditor.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/itexteditor.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/itexteditor.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/itexteditor.h 2018-12-11 07:08:24.000000000 +0000 @@ -21,8 +21,7 @@ #include "libshell.h" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Interface for a text editor: text content and a cursor position. @@ -35,13 +34,12 @@ virtual ~ITextEditor() {} virtual void setText(String const &text) = 0; - virtual void setCursor(int pos) = 0; + virtual void setCursor(int pos) = 0; - virtual String text() const = 0; - virtual int cursor() const = 0; + virtual String text() const = 0; + virtual int cursor() const = 0; }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_ITEXTEDITOR_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/keyevent.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/keyevent.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/keyevent.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/keyevent.h 2018-12-11 07:08:24.000000000 +0000 @@ -24,8 +24,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Key press event generated when the user presses a key on the keyboard. @@ -35,36 +34,38 @@ class LIBSHELL_PUBLIC KeyEvent : public Event { public: - enum Modifier - { - None = 0x0, - Control = 0x1 - }; + enum Modifier { None = 0x0, Control = 0x1 }; Q_DECLARE_FLAGS(Modifiers, Modifier) public: - KeyEvent(String const &keyText) : Event(KeyPress), _text(keyText), _code(0) {} - KeyEvent(int keyCode, Modifiers mods = None) : Event(KeyPress), _code(keyCode), _modifiers(mods) {} + KeyEvent(String const &keyText) + : Event(KeyPress) + , _text(keyText) + , _code(0) + {} + KeyEvent(int keyCode, Modifiers mods = None) + : Event(KeyPress) + , _code(keyCode) + , _modifiers(mods) + {} - String text() const { return _text; } - int key() const { return _code; } + String text() const { return _text; } + int key() const { return _code; } Modifiers modifiers() const { return _modifiers; } - bool operator == (KeyEvent const &other) const { - return _text == other._text && - _code == other._code && - _modifiers == other._modifiers; + bool operator==(KeyEvent const &other) const + { + return _text == other._text && _code == other._code && _modifiers == other._modifiers; } private: - String _text; ///< Text to be inserted by the event. - int _code; ///< Qt key code. - Modifiers _modifiers; ///< Modifiers in effect. + String _text; ///< Text to be inserted by the event. + int _code; ///< Qt key code. + Modifiers _modifiers; ///< Modifiers in effect. }; Q_DECLARE_OPERATORS_FOR_FLAGS(KeyEvent::Modifiers) -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_KEYEVENT_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/labelwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/labelwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/labelwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/labelwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -22,8 +22,7 @@ #include "TextWidget" #include "TextCanvas" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Widget for showing a text label. @@ -57,7 +56,8 @@ * @param text Text to show. * @param attribs Attributes for the text. */ - void setLabel(String const &text, TextCanvas::Char::Attribs attribs = TextCanvas::Char::DefaultAttributes); + void setLabel(String const & text, + TextCanvas::Char::Attribs attribs = TextCanvas::Char::DefaultAttributes); void setAttribs(TextCanvas::Char::Attribs const &attribs); @@ -85,7 +85,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_LABELWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/lexicon.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/lexicon.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/lexicon.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/lexicon.h 2018-12-11 07:08:24.000000000 +0000 @@ -23,8 +23,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Lexicon containing terms and grammatical rules. By default, the lexicon is @@ -40,7 +39,7 @@ public: Lexicon(); Lexicon(Lexicon const &other); - Lexicon &operator = (Lexicon const &other); + Lexicon &operator=(Lexicon const &other); Terms terms() const; @@ -60,7 +59,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_LEXICON_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/lineeditwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/lineeditwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/lineeditwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/lineeditwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -23,8 +23,7 @@ #include "TextWidget" #include "AbstractLineEditor" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Widget for word-wrapped text editing. @@ -34,7 +33,9 @@ * * @ingroup textUi */ -class LIBSHELL_PUBLIC LineEditWidget : public TextWidget, public AbstractLineEditor +class LIBSHELL_PUBLIC LineEditWidget + : public TextWidget + , public AbstractLineEditor { Q_OBJECT @@ -68,7 +69,7 @@ void enterPressed(de::String text); protected: - virtual int maximumWidth() const; + virtual int maximumWidth() const; virtual void numberOfLinesChanged(int lineCount); virtual void cursorMoved(); virtual void contentChanged(); @@ -77,7 +78,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_LINEEDITWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/link.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/link.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/link.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/link.h 2018-12-11 07:08:24.000000000 +0000 @@ -28,8 +28,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Network connection to a server using the shell protocol. @@ -49,7 +48,7 @@ * @param domain Domain/IP address of the server. * @param timeout Keep trying until this much time has passed. */ - Link(String const &domain, TimeDelta const &timeout = 0); + Link(String const &domain, TimeSpan const &timeout = 0); /** * Opens a connection to a server over the network. @@ -78,13 +77,12 @@ protected: Packet *interpret(Message const &msg); - void initiateCommunications(); + void initiateCommunications(); private: DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_LINK_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/localserver.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/localserver.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/localserver.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/localserver.h 2018-12-11 07:08:24.000000000 +0000 @@ -19,13 +19,14 @@ #ifndef LIBSHELL_LOCALSERVER_H #define LIBSHELL_LOCALSERVER_H -#include "Link" -#include -#include -#include +#if !defined(DENG_MOBILE) -namespace de { -namespace shell { +# include "Link" +# include +# include +# include + +namespace de { namespace shell { /** * Utility for starting and stopping local servers. @@ -50,8 +51,7 @@ void setApplicationPath(NativePath const &path); - void start(duint16 port, - String const &gameMode, + void start(duint16 port, String const &gameMode, QStringList additionalOptions = QStringList(), NativePath const &runtimePath = ""); @@ -80,7 +80,8 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell + +# endif // !DENG_MOBILE #endif // LIBSHELL_LOCALSERVER_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/logwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/logwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/logwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/logwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -22,8 +22,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Text-based log widget. @@ -91,7 +90,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LOGWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/menuwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/menuwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/menuwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/menuwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -23,8 +23,7 @@ #include "Action" #include "TextCanvas" -namespace de { -namespace shell { +namespace de { namespace shell { /** * Menu with Action instances as items. @@ -43,17 +42,12 @@ Q_OBJECT public: - enum Preset - { - Popup, ///< Menu initially hidden, will popup on demand. - AlwaysOpen ///< Menu initially shown, stays open. + enum Preset { + Popup, ///< Menu initially hidden, will popup on demand. + AlwaysOpen ///< Menu initially shown, stays open. }; - enum BorderStyle - { - NoBorder, - LineBorder - }; + enum BorderStyle { NoBorder, LineBorder }; public: MenuWidget(Preset preset, String const &name = String()); @@ -130,7 +124,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_MENUWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/monospacelinewrapping.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/monospacelinewrapping.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/monospacelinewrapping.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/monospacelinewrapping.h 2018-12-11 07:08:24.000000000 +0000 @@ -22,8 +22,7 @@ #include "libshell.h" #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Line wrapper that assumes that all characters are the same width. Width is @@ -52,16 +51,15 @@ void wrapTextToWidth(String const &text, int maxWidth); WrappedLine line(int index) const { return _lines[index]; } - int width() const; - int height() const; - int rangeWidth(Rangei const &range) const; - int indexAtWidth(Rangei const &range, int width) const; + int width() const; + int height() const; + int rangeWidth(Rangei const &range) const; + int indexAtWidth(Rangei const &range, int width) const; private: QList _lines; }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_MONOSPACELINEWRAPPING_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/PackageDownloader doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/PackageDownloader --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/PackageDownloader 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/PackageDownloader 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,2 @@ +#include "packagedownloader.h" + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/packagedownloader.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/packagedownloader.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/packagedownloader.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/packagedownloader.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,89 @@ +/** @file packagedownloader.h Utility for downloading packages from a remote repository. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#ifndef LIBSHELL_PACKAGEDOWNLOADER_H +#define LIBSHELL_PACKAGEDOWNLOADER_H + +#include +#include +#include +#include "ServerInfo" + +namespace de { namespace shell { + +/** + * Utility for downloading packages from remote repositories. + * @ingroup network + */ +class LIBSHELL_PUBLIC PackageDownloader +{ +public: + PackageDownloader(); + + typedef std::function MountCallback; + + /** + * Mount a server's remote file repository. + * + * @param serverInfo Server information. + * @param afterConnected Callback to call when the repository is connected and ready for use. + */ + void mountServerRepository(ServerInfo const &serverInfo, MountCallback afterConnected); + + void unmountServerRepository(); + + /** + * Start downloading files for a set of packages. A notification callback is done + * after the operation is complete (successfully or not). + * + * @param packageIds Packages to download from the remote repository. + * @param callback Called when the downloads are finished or cancelled. + */ + void download(StringList packageIds, std::function callback); + + de::String fileRepository() const; + + /** + * Cancel the ongoing downloads. + */ + void cancel(); + + bool isCancelled() const; + + /** + * Determines whether downloads are currently active. + */ + bool isActive() const; + +public: + /** + * Notified when file downloads are progressing. The ranges describe the remaining + * and total amounts. For example, `bytes.start` is the number of total bytes + * remaining to download. `bytes.size()` is the number of bytes downloaded so far. + * `bytes.end` is the total number of bytes overall. + */ + DENG2_DEFINE_AUDIENCE2(Status, + void downloadStatusUpdate(Rangei64 const &bytes, Rangei const &files)) + +private: + DENG2_PRIVATE(d) +}; + +}} // namespace de::shell + +#endif // LIBSHELL_PACKAGEDOWNLOADER_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/protocol.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/protocol.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/protocol.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/protocol.h 2018-12-11 07:08:24.000000000 +0000 @@ -26,8 +26,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Password challenge. @@ -70,8 +69,8 @@ void execute() const; // Implements ISerializable. - void operator >> (Writer &to) const; - void operator << (Reader &from); + void operator>>(Writer &to) const; + void operator<<(Reader &from); static Packet *fromBlock(Block const &block); @@ -86,21 +85,18 @@ class LIBSHELL_PUBLIC PlayerInfoPacket : public Packet { public: - struct Player - { - int number; - Vector2i position; - String name; + struct Player { + int number; + Vector2i position; + String name; Vector3ub color; - Player(int num = 0, - Vector2i const &pos = Vector2i(), - String const &plrName = "", + Player(int num = 0, Vector2i const &pos = Vector2i(), String const &plrName = "", Vector3ub const &plrColor = Vector3ub()) - : number(num), - position(pos), - name(plrName), - color(plrColor) + : number(num) + , position(pos) + , name(plrName) + , color(plrColor) {} }; @@ -118,8 +114,8 @@ Players players() const; // Implements ISerializable. - void operator >> (Writer &to) const; - void operator << (Reader &from); + void operator>>(Writer &to) const; + void operator<<(Reader &from); static Packet *fromBlock(Block const &block); @@ -137,13 +133,11 @@ class LIBSHELL_PUBLIC MapOutlinePacket : public Packet { public: - enum LineType - { + enum LineType { OneSidedLine = 0, TwoSidedLine = 1, }; - struct Line - { + struct Line { Vector2i start; Vector2i end; LineType type; @@ -168,8 +162,8 @@ Line const &line(int index) const; // Implements ISerializable. - void operator >> (Writer &to) const; - void operator << (Reader &from); + void operator>>(Writer &to) const; + void operator<<(Reader &from); static Packet *fromBlock(Block const &block); @@ -186,8 +180,7 @@ /// Type of provided packet is incorrect. @ingroup errors DENG2_ERROR(TypeError); - enum PacketType - { + enum PacketType { Unknown, PasswordChallenge, Command, ///< Console command (only to server). @@ -245,13 +238,10 @@ * * @return Packet. Caller gets ownership. */ - RecordPacket *newGameState(String const &mode, - String const &rules, - String const &mapId, + RecordPacket *newGameState(String const &mode, String const &rules, String const &mapId, String const &mapTitle); }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_PROTOCOL_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/serverfinder.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/serverfinder.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/serverfinder.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/serverfinder.h 2018-12-11 07:08:24.000000000 +0000 @@ -25,8 +25,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Looks up servers via beacon. @ingroup shell @@ -51,8 +50,8 @@ QList
foundServers() const; String name(Address const &server) const; - int playerCount(Address const &server) const; - int maxPlayers(Address const &server) const; + int playerCount(Address const &server) const; + int maxPlayers(Address const &server) const; /** * Returns the message sent by a server's beacon. @@ -74,7 +73,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_SERVERFINDER_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/serverinfo.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/serverinfo.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/serverinfo.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/serverinfo.h 2018-12-11 07:08:24.000000000 +0000 @@ -24,52 +24,48 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Information about a multiplayer server. @ingroup network */ -class LIBSHELL_PUBLIC ServerInfo : public Record +class LIBSHELL_PUBLIC ServerInfo { public: - enum Flag - { - AllowJoin = 0x1, - DefaultFlags = AllowJoin - }; + enum Flag { AllowJoin = 0x1, DefaultFlags = AllowJoin }; Q_DECLARE_FLAGS(Flags, Flag) ServerInfo(); ServerInfo(ServerInfo const &other); - ServerInfo(ServerInfo &&moved); ServerInfo(Record const &rec); - ServerInfo &operator = (ServerInfo const &other); - ServerInfo &operator = (ServerInfo &&moved); + ServerInfo &operator=(ServerInfo const &other); Version version() const; - int compatibilityVersion() const; + int compatibilityVersion() const; - Address address() const; - String domainName() const; - duint16 port() const; - String name() const; - String description() const; - String pluginDescription() const; + Address address() const; + String domainName() const; + duint16 port() const; + duint32 serverId() const; + String name() const; + String description() const; + String pluginDescription() const; StringList packages() const; - String gameId() const; - String gameConfig() const; - String map() const; + String gameId() const; + String gameConfig() const; + String map() const; StringList players() const; - int playerCount() const; - int maxPlayers() const; - Flags flags() const; - - String asStyledText() const; - Block asJSON() const; - Record strippedForBroadcast() const; + int playerCount() const; + int maxPlayers() const; + Flags flags() const; + + String asStyledText() const; + Block asJSON() const; + const Record &asRecord() const; + Record strippedForBroadcast() const; ServerInfo &setCompatibilityVersion(int compatVersion); + ServerInfo &setServerId(duint32 sid); ServerInfo &setAddress(Address const &address); ServerInfo &setDomainName(String const &domain); ServerInfo &setName(String const &name); @@ -84,36 +80,18 @@ ServerInfo &setMaxPlayers(int count); ServerInfo &setFlags(Flags const &flags); - //duint32 iwadDirectoryCRC32() const; - - //int version; - //char name[64]; - //char description[80]; - //int numPlayers, maxPlayers; - //char canJoin; - //char address[64]; - //int port; - //unsigned short ping; ///< Milliseconds. - //char plugin[32]; ///< Game plugin and version. - //char gameIdentityKey[17]; - //char gameConfig[40]; - //char map[20]; - //char clientNames[128]; - //unsigned int loadedFilesCRC; - //char iwad[32]; ///< Obsolete. - //char pwads[128]; - //int data[3]; - /** * Prints server/host information into the console. The header line is * printed if 'info' is NULL. */ void printToLog(int indexNumber, bool includeHeader = false) const; + +private: + DENG2_PRIVATE(d) }; Q_DECLARE_OPERATORS_FOR_FLAGS(ServerInfo::Flags) -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // SERVERINFO_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textcanvas.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textcanvas.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textcanvas.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textcanvas.h 2018-12-11 07:08:24.000000000 +0000 @@ -25,20 +25,13 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Flags for specifying alignment. * @ingroup textUi */ -enum AlignmentFlag -{ - AlignTop = 0x1, - AlignBottom = 0x2, - AlignLeft = 0x4, - AlignRight = 0x8 -}; +enum AlignmentFlag { AlignTop = 0x1, AlignBottom = 0x2, AlignLeft = 0x4, AlignRight = 0x8 }; Q_DECLARE_FLAGS(Alignment, AlignmentFlag) Q_DECLARE_OPERATORS_FOR_FLAGS(Alignment) @@ -56,35 +49,34 @@ { public: typedef Vector2ui Size; - typedef Vector2i Coord; + typedef Vector2i Coord; - struct Char - { - enum Attrib - { + struct Char { + enum Attrib { Bold = 0x1, Underline = 0x2, Reverse = 0x4, Blink = 0x8, - Dirty = 0x80000000, + Dirty = 0x80000000, DefaultAttributes = 0, - VisualAttributes = Bold | Underline | Reverse | Blink + VisualAttributes = Bold | Underline | Reverse | Blink }; Q_DECLARE_FLAGS(Attribs, Attrib) - QChar ch; + QChar ch; Attribs attribs; public: Char(QChar const &c = QChar(' '), Attribs const &at = DefaultAttributes) - : ch(c), attribs(at) + : ch(c) + , attribs(at) { attribs |= Dirty; } - bool operator < (Char const &other) const + bool operator<(Char const &other) const { if (ch.unicode() == other.ch.unicode()) { @@ -93,19 +85,19 @@ return ch.unicode() < other.ch.unicode(); } - bool operator == (Char const &other) const + bool operator==(Char const &other) const { return (ch.unicode() == other.ch.unicode() && (attribs & VisualAttributes) == (other.attribs & VisualAttributes)); } - Char &operator = (Char const &other) + Char &operator=(Char const &other) { bool changed = false; if (ch != other.ch) { - ch = other.ch; + ch = other.ch; changed = true; } if ((attribs & VisualAttributes) != (other.attribs & VisualAttributes)) @@ -122,19 +114,16 @@ return *this; } - bool isDirty() const - { - return attribs.testFlag(Dirty); - } + bool isDirty() const { return attribs.testFlag(Dirty); } }; public: TextCanvas(Size const &size = Size(1, 1)); virtual ~TextCanvas(); - Size size() const; - int width() const; - int height() const; + Size size() const; + int width() const; + int height() const; Rectanglei rect() const; virtual void resize(Size const &newSize); @@ -170,8 +159,7 @@ void put(Coord const &pos, Char const &ch); void drawText(Coord const &pos, String const &text, - Char::Attribs const &attribs = Char::DefaultAttributes, - int richOffset = 0); + Char::Attribs const &attribs = Char::DefaultAttributes, int richOffset = 0); /** * Draws line wrapped text. Use de::shell::wordWrapText() to determine @@ -184,14 +172,15 @@ * @param lineAlignment Alignment for lines. */ void drawWrappedText(Coord const &pos, String const &text, ILineWrapping const &wraps, - Char::Attribs const &attribs = Char::DefaultAttributes, - Alignment lineAlignment = AlignLeft); + Char::Attribs const &attribs = Char::DefaultAttributes, + Alignment lineAlignment = AlignLeft); void clearRichFormat(); void setRichFormatRange(Char::Attribs const &attribs, Rangei const &range); - void drawLineRect(Rectanglei const &rect, Char::Attribs const &attribs = Char::DefaultAttributes); + void drawLineRect(Rectanglei const & rect, + Char::Attribs const &attribs = Char::DefaultAttributes); /** * Draws the contents of a canvas onto this canvas. @@ -223,7 +212,6 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(TextCanvas::Char::Attribs) -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_TEXTCANVAS_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textrootwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textrootwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textrootwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textrootwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -23,8 +23,7 @@ #include #include "TextCanvas" -namespace de { -namespace shell { +namespace de { namespace shell { class TextWidget; @@ -68,10 +67,9 @@ private: TextCanvas *_canvas; - bool _drawRequest; + bool _drawRequest; }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_TEXTROOTWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textwidget.h doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textwidget.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/include/de/shell/textwidget.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/include/de/shell/textwidget.h 2018-12-11 07:08:24.000000000 +0000 @@ -26,8 +26,7 @@ #include #include "TextCanvas" -namespace de { -namespace shell { +namespace de { namespace shell { class TextRootWidget; class Action; @@ -46,7 +45,9 @@ * * @ingroup textUi */ -class LIBSHELL_PUBLIC TextWidget : public QObject, public Widget +class LIBSHELL_PUBLIC TextWidget + : public QObject + , public Widget { Q_OBJECT @@ -128,7 +129,6 @@ DENG2_PRIVATE(d) }; -} // namespace shell -} // namespace de +}} // namespace de::shell #endif // LIBSHELL_TEXTWIDGET_H diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/abstractlineeditor.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/abstractlineeditor.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/abstractlineeditor.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/abstractlineeditor.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -24,16 +24,16 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(AbstractLineEditor) { - String prompt; - String text; - int cursor; ///< Index in range [0...text.size()] - Lexicon lexicon; + String prompt; + String text; + int cursor; ///< Index in range [0...text.size()] + Lexicon lexicon; EchoMode echoMode; + QScopedPointer wraps; struct Completion { @@ -48,10 +48,10 @@ return Rangei(pos, pos + size); } }; - Completion completion; + Completion completion; QStringList suggestions; - bool suggesting; - bool completionNotified; + bool suggesting; + bool completionNotified; Impl(Public *i, ILineWrapping *lineWraps) : Base(i), @@ -308,15 +308,15 @@ QStringList completionsForBase(String base, String &commonPrefix) const { - Qt::CaseSensitivity const sensitivity = - lexicon.isCaseSensitive()? Qt::CaseSensitive : Qt::CaseInsensitive; + String::CaseSensitivity const sensitivity = + lexicon.isCaseSensitive()? String::CaseSensitive : String::CaseInsensitive; bool first = true; QStringList sugs; foreach (String term, lexicon.terms()) { - if (term.startsWith(base, sensitivity) && term.size() > base.size()) + if (term.beginsWith(base, sensitivity) && term.size() > base.size()) { sugs << term; @@ -686,5 +686,4 @@ d->updateWraps(); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/abstractlink.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/abstractlink.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/abstractlink.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/abstractlink.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -17,25 +17,26 @@ */ #include "de/shell/AbstractLink" +#include +#include #include +#include #include #include -#include -#include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(AbstractLink) { - String tryingToConnectToHost; - Time startedTryingAt; - TimeDelta timeout; - Address peerAddress; + String tryingToConnectToHost; + Time startedTryingAt; + TimeSpan timeout; + Address peerAddress; + Status status; + Time connectedAt; + std::unique_ptr socket; - Status status; - Time connectedAt; Impl(Public *i) : Base(i), @@ -55,7 +56,7 @@ AbstractLink::AbstractLink() : d(new Impl(this)) {} -void AbstractLink::connectDomain(String const &domain, TimeDelta const &timeout) +void AbstractLink::connectDomain(String const &domain, TimeSpan const &timeout) { disconnect(); @@ -69,7 +70,7 @@ // Fallback to default port. d->tryingToConnectToHost = domain; d->socket->setQuiet(true); // we'll be retrying a few times - d->socket->connectToDomain(d->tryingToConnectToHost, DEFAULT_PORT); + d->socket->open(d->tryingToConnectToHost, DEFAULT_PORT); d->status = Connecting; d->startedTryingAt = Time(); @@ -90,7 +91,7 @@ // Fallback to default port. if (!d->peerAddress.port()) d->peerAddress.setPort(DEFAULT_PORT); - d->socket->connect(d->peerAddress); + d->socket->open(d->peerAddress); d->status = Connecting; d->startedTryingAt = Time(); @@ -211,5 +212,4 @@ d->connectedAt = Time::invalidTime(); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/action.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/action.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/action.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/action.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,13 +13,12 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/Action" -namespace de { -namespace shell { +namespace de { namespace shell { Action::Action(String const &label) : _event(KeyEvent("")), _label(label), _target(0), _slot(0) {} @@ -80,5 +79,4 @@ emit triggered(); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/choicewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/choicewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/choicewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/choicewidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -20,15 +20,14 @@ #include "de/shell/MenuWidget" #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(ChoiceWidget) { - Items items; - int selection; + Items items; + int selection; MenuWidget *menu; - String prompt; + String prompt; Impl(Public &i) : Base(i), selection(0) {} @@ -190,5 +189,4 @@ add(d->menu); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/commandlinewidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/commandlinewidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/commandlinewidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/commandlinewidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/CommandLineWidget" @@ -24,8 +24,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(CommandLineWidget) { @@ -71,5 +70,4 @@ LOG_MSG(" %s") << suggestedCompletions().join(", "); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/dialogwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/dialogwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/dialogwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/dialogwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/DialogWidget" @@ -21,8 +21,7 @@ #include "de/shell/KeyEvent" #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(DialogWidget) { @@ -114,5 +113,4 @@ } } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/doomsdayinfo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/doomsdayinfo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/doomsdayinfo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/doomsdayinfo.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,8 +25,7 @@ #include "de/shell/DoomsdayInfo" #include -namespace de { -namespace shell { +namespace de { namespace shell { static struct { @@ -159,5 +158,4 @@ , allowedValues(allowedValues) {} -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/editorhistory.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/editorhistory.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/editorhistory.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/editorhistory.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,14 +13,13 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/EditorHistory" #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(EditorHistory) { @@ -33,7 +32,7 @@ { String text; String original; ///< For undoing editing in history. - int cursor; ///< Index in range [0...text.size()] + int cursor; ///< Index in range [0...text.size()] Command() : cursor(0) {} }; @@ -49,6 +48,25 @@ ~Impl() {} + void restore(StringList contents) + { + history.clear(); + if (contents.isEmpty()) + { + history.append(Command()); + historyPos = 0; + return; + } + foreach (String line, contents) + { + Command cmd; + cmd.text = cmd.original = line; + cmd.cursor = cmd.text.size(); + history.append(cmd); + } + historyPos = history.size() - 1; + } + Command &command() { DENG2_ASSERT(historyPos >= 0 && historyPos < history.size()); @@ -181,5 +199,23 @@ return false; } -} // namespace shell -} // namespace de +StringList EditorHistory::fullHistory(int maxCount) const +{ + StringList lines; + foreach (auto const &cmd, d->history) + { + lines << cmd.original; + if (maxCount > 0 && lines.count() == maxCount) + { + break; + } + } + return lines; +} + +void EditorHistory::setFullHistory(StringList history) +{ + d->restore(history); +} + +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/inputdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/inputdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/inputdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/inputdialog.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/InputDialog" @@ -22,16 +22,15 @@ #include "de/shell/MenuWidget" #include "de/shell/TextRootWidget" -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(InputDialog) { - LabelWidget *label; + LabelWidget * label; LineEditWidget *edit; - MenuWidget *menu; - String userText; - int result; + MenuWidget * menu; + String userText; + int result; Impl() : label(0), edit(0), menu(0), result(0) {} @@ -168,5 +167,4 @@ return d->result; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/labelwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/labelwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/labelwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/labelwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/LabelWidget" @@ -21,18 +21,17 @@ #include "de/shell/MonospaceLineWrapping" #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(LabelWidget) { - TextCanvas::Char background; - String label; - MonospaceLineWrapping wraps; + TextCanvas::Char background; + String label; + MonospaceLineWrapping wraps; TextCanvas::Char::Attribs attribs; - Alignment align; - bool vertExpand; - ConstantRule *height; + Alignment align; + bool vertExpand; + ConstantRule * height; Impl() : align(0), vertExpand(false) { @@ -148,5 +147,4 @@ targetCanvas().draw(buf, pos.topLeft); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/lexicon.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/lexicon.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/lexicon.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/lexicon.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,19 +13,18 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/Lexicon" -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(Lexicon) { - Terms terms; + Terms terms; String extraChars; - bool caseSensitive; + bool caseSensitive; Impl() : caseSensitive(false) {} }; @@ -79,5 +78,4 @@ return d->caseSensitive; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/libshell.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/libshell.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/libshell.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/libshell.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,14 +13,12 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/libshell.h" #include -namespace de { -namespace shell { +namespace de { namespace shell { -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/lineeditwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/lineeditwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/lineeditwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/lineeditwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/LineEditWidget" @@ -27,8 +27,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(LineEditWidget) { @@ -180,5 +179,4 @@ redraw(); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/link.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/link.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/link.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/link.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -1,4 +1,4 @@ -/** @file link.h Network connection to a server. +/** @file link.cpp Network connection to a server. * * @authors Copyright © 2013-2017 Jaakko Keränen * @@ -24,22 +24,21 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(Link) { - String connectDomain; - TimeDelta connectTimeout; - Address connectAddress; + String connectDomain; + TimeSpan connectTimeout; + Address connectAddress; - Protocol protocol; + Protocol protocol; Impl(Public *i) : Base(i) {} }; -Link::Link(String const &domain, TimeDelta const &timeout) : d(new Impl(this)) +Link::Link(String const &domain, TimeSpan const &timeout) : d(new Impl(this)) { d->connectDomain = domain; d->connectTimeout = timeout; @@ -87,5 +86,4 @@ *this << ByteRefArray("Shell", 5); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/localserver.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/localserver.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/localserver.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/localserver.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -23,19 +23,20 @@ #include #include -namespace de { -namespace shell { +#if !defined (DENG_MOBILE) + +namespace de { namespace shell { static String const ERROR_LOG_NAME = "doomsday-errors.out"; DENG2_PIMPL_NOREF(LocalServer) { - Link *link = nullptr; + Link * link = nullptr; NativePath appPath; // where to find the server - duint16 port = 0; - String name; + duint16 port = 0; + String name; NativePath userDir; - QProcess *proc = nullptr; // not deleted until stopped + QProcess * proc = nullptr; // not deleted until stopped ~Impl() { @@ -190,5 +191,6 @@ return d->userDir / ERROR_LOG_NAME; } -} // namespace shell -} // namespace de +}} // namespace de::shell + +#endif diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/logwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/logwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/logwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/logwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/LogWidget" @@ -24,8 +24,7 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { /** * Log sink for incoming entries (local and remote). Rather than formatting the @@ -293,5 +292,4 @@ redraw(); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/menuwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/menuwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/menuwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/menuwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,7 +13,7 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/MenuWidget" @@ -21,20 +21,19 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL(MenuWidget) { - ConstantRule *width; - ConstantRule *height; + ConstantRule * width; + ConstantRule * height; TextCanvas::Char::Attribs borderAttr; TextCanvas::Char::Attribs backgroundAttr; TextCanvas::Char::Attribs selectionAttr; - BorderStyle borderStyle; - Vector2i cursorPos; ///< Visual position. - bool closable; - bool cycleCursor; + BorderStyle borderStyle; + Vector2i cursorPos; ///< Visual position. + bool closable; + bool cycleCursor; struct Item { @@ -460,5 +459,4 @@ return false; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/monospacelinewrapping.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/monospacelinewrapping.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/monospacelinewrapping.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/monospacelinewrapping.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,14 +13,13 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/MonospaceLineWrapping" #include -namespace de { -namespace shell { +namespace de { namespace shell { MonospaceLineWrapping::MonospaceLineWrapping() { @@ -121,5 +120,4 @@ return range.end; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/packagedownloader.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/packagedownloader.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/packagedownloader.cpp 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/packagedownloader.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,348 @@ +/** @file packagedownloader.cpp Utility for downloading packages from a remote repository. + * + * @authors Copyright (c) 2017 Jaakko Keränen + * + * @par License + * GPL: http://www.gnu.org/licenses/gpl.html + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses + */ + +#include "de/shell/PackageDownloader" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace de { namespace shell { + +static String const PATH_REMOTE_PACKS = "/remote/packs"; +static String const PATH_REMOTE_SERVER = "/remote/server"; // local folder for RemoteFeed + +DENG2_PIMPL(PackageDownloader) +, DENG2_OBSERVES(filesys::RemoteFeedRelay, Status) +, DENG2_OBSERVES(Asset, StateChange) +, DENG2_OBSERVES(RemoteFile, Download) +, DENG2_OBSERVES(Deletable, Deletion) +{ + String fileRepository; + MountCallback afterConnected; + bool isCancelled = false; + dint64 totalBytes = 0; + int numDownloads = 0; + AssetGroup downloads; + QHash downloadBytes; + std::function postDownloadCallback; + LoopCallback deferred; + + Impl(Public *i) : Base(i) {} + + void remoteRepositoryStatusChanged(String const &address, + filesys::RemoteFeedRelay::Status) override + { + if (address == fileRepository) + { + // When NativeLink is connected, any pending folder populations will be + // started. We'll defer this callback so that NativeLink gets to react + // first to the status change notification. + + deferred.enqueue([this] () + { + auto *relay = &filesys::RemoteFeedRelay::get(); + relay->audienceForStatus() -= this; + + // Populate remote folders before notifying so everything is ready to go. + Folder::afterPopulation([this, relay] () + { + if (afterConnected) + { + afterConnected(relay->repository(fileRepository)); + } + }); + }); + } + } + + void downloadFile(File &file) + { + if (auto *folder = maybeAs(file)) + { + folder->forContents([this] (String, File &f) + { + downloadFile(f); + return LoopContinue; + }); + } + if (auto *dl = maybeAs(file)) + { + LOG_NET_VERBOSE("Downloading from server: %s") << file.description(); + + downloads.insert(dl->asset()); + dl->audienceForDownload += this; + file.Deletable::audienceForDeletion += this; + downloadBytes.insert(dl, Rangei64(dint64(dl->downloadSize()), + dint64(dl->downloadSize()))); + numDownloads++; + totalBytes += dl->downloadSize(); + isCancelled = false; + + dl->download(); + } + } + + void downloadProgress(IDownloadable &dl, dsize remainingBytes) override + { + DENG2_ASSERT_IN_MAIN_THREAD(); + + auto found = downloadBytes.find(&dl); + if (found == downloadBytes.end()) return; + + found.value().start = dint64(remainingBytes); + + if (remainingBytes == 0) + { + dl.audienceForDownload -= this; + maybeAs(dl)->Deletable::audienceForDeletion -= this; + downloadBytes.erase(found); + } + + // Update total for the UI popup. + { + dint64 totalRemaining = 0; + foreach (auto bytes, downloadBytes) + { + totalRemaining += bytes.start; + } + + DENG2_FOR_PUBLIC_AUDIENCE2(Status, i) + { + i->downloadStatusUpdate(Rangei64(totalRemaining, totalBytes), + Rangei(downloadBytes.size(), numDownloads)); + } + } + } + + void objectWasDeleted(Deletable *del) override + { + DENG2_ASSERT_IN_MAIN_THREAD(); + downloadBytes.remove(static_cast(del)); + } + + void assetStateChanged(Asset &) override + { + if (downloads.isReady()) + { + LOG_NET_VERBOSE(isCancelled? "Remote file downloads cancelled" + : "All downloads of remote files finished"); + Loop::mainCall([this] () + { + DENG2_ASSERT(downloadBytes.isEmpty()); + if (postDownloadCallback) postDownloadCallback(); + }); + } + } + + void finishDownloads() + { + // Final status update. + DENG2_FOR_PUBLIC_AUDIENCE2(Status, i) + { + i->downloadStatusUpdate(Rangei64(0, totalBytes), Rangei(0, numDownloads)); + } + numDownloads = 0; + totalBytes = 0; + downloads.clear(); + } + + void clearDownloads() + { + for (auto i = downloadBytes.begin(); i != downloadBytes.end(); ++i) + { + auto *dl = i.key(); + + // Ongoing (partial) downloads will be cancelled. + dl->cancelDownload(); + + dl->audienceForDownload -= this; + maybeAs(dl)->Deletable::audienceForDeletion -= this; + } + numDownloads = 0; + totalBytes = 0; + downloadBytes.clear(); + downloads.clear(); + } + + /** + * Makes remote packages available for loading locally. + * + * Once remote files have been downloaded, PackageLoader still needs to be made aware + * that the packages are available. This is done via link files that have the ".pack" + * extension and thus are treated as loadable packages. + * + * @param ids Identifiers of remote packages that have been downloaded and are now + * being prepared for loading. + */ + void linkRemotePackages(filesys::PackagePaths const &pkgPaths) + { + Folder &remotePacks = FS::get().makeFolder(PATH_REMOTE_PACKS); + for (auto i = pkgPaths.begin(); i != pkgPaths.end(); ++i) + { + LOG_RES_VERBOSE("Registering remote package \"%s\"") << i.key(); + if (auto *file = FS::tryLocate(i.value().localPath)) + { + LOGDEV_RES_VERBOSE("Cached metadata:\n") << file->objectNamespace().asText(); + + auto *pack = LinkFile::newLinkToFile(*file, file->name() + ".pack"); + Record &meta = pack->objectNamespace(); + meta.add("package", new Record(file->objectNamespace().subrecord("package"))); + meta.set("package.path", file->path()); + remotePacks.add(pack); + FS::get().index(*pack); + + LOG_RES_VERBOSE("\"%s\" linked as ") << i.key() << pack->path(); + } + } + } + + void unlinkRemotePackages() + { + // Unload all server packages. Note that the entire folder will be destroyed, too. + if (std::unique_ptr remotePacks { FS::tryLocate(PATH_REMOTE_PACKS) }) + { + remotePacks->forContents([] (String, File &file) + { + LOG_RES_VERBOSE("Unloading remote package: ") << file.description(); + PackageLoader::get().unload(Package::identifierForFile(file)); + return LoopContinue; + }); + } + } + + DENG2_PIMPL_AUDIENCE(Status) +}; + +DENG2_AUDIENCE_METHOD(PackageDownloader, Status) + +PackageDownloader::PackageDownloader() + : d(new Impl(this)) +{} + +String PackageDownloader::fileRepository() const +{ + return d->fileRepository; +} + +void PackageDownloader::cancel() +{ + d->isCancelled = true; + DENG2_FOR_AUDIENCE2(Status, i) + { + i->downloadStatusUpdate(Rangei64(), Rangei()); + } + d->clearDownloads(); +} + +bool PackageDownloader::isCancelled() const +{ + return d->isCancelled; +} + +bool PackageDownloader::isActive() const +{ + return !d->downloads.isEmpty() && !d->downloads.isReady(); +} + +void PackageDownloader::mountServerRepository(shell::ServerInfo const &info, + MountCallback afterConnected) +{ + // The remote repository feature was added in 2.1. Trying to send a RemoteFeed + // request to an older server would just result in us getting immediately + // disconnected. + + if (info.version() > Version(2, 1, 0, 2484)) + { + auto &relay = filesys::RemoteFeedRelay::get(); + + d->fileRepository = filesys::NativeLink::URL_SCHEME + info.address().asText(); + d->isCancelled = false; + relay.addRepository(d->fileRepository, PATH_REMOTE_SERVER); + + // Notify after repository is available. + d->afterConnected = afterConnected; + relay.audienceForStatus() += d; + } + else if (afterConnected) + { + afterConnected(nullptr); + } +} + +void PackageDownloader::unmountServerRepository() +{ + d->clearDownloads(); + d->unlinkRemotePackages(); + filesys::RemoteFeedRelay::get().removeRepository(d->fileRepository); + d->fileRepository.clear(); + d->isCancelled = false; + + if (Folder *remoteFiles = FS::tryLocate(PATH_REMOTE_SERVER)) + { + trash(remoteFiles); + } +} + +void PackageDownloader::download(StringList packageIds, std::function callback) +{ + d->downloads.clear(); + + auto const pkgPaths = filesys::RemoteFeedRelay::get().locatePackages(packageIds); + + // The set of found packages may not contain all the requested packages. + StringList const foundIds = pkgPaths.keys(); + for (auto found = pkgPaths.begin(); found != pkgPaths.end(); ++found) + { + if (File *file = found.value().link->populateRemotePath(found.key(), found.value())) + { + d->downloadFile(*file); + } + } + + auto finished = [this, pkgPaths, callback] () + { + // Let's finalize the downloads so we can load all the packages. + d->downloads.audienceForStateChange() -= d; + d->finishDownloads(); + d->linkRemotePackages(pkgPaths); + + callback(); + }; + + // If nothing needs to be downloaded, let's just continue right away. + if (d->downloads.isReady()) + { + d->postDownloadCallback = nullptr; + finished(); + } + else + { + d->postDownloadCallback = finished; + d->downloads.audienceForStateChange() += d; + } +} + +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/protocol.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/protocol.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/protocol.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/protocol.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -25,16 +25,15 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { -static String const PT_COMMAND = "shell.command"; -static String const PT_LEXICON = "shell.lexicon"; +static String const PT_COMMAND = "shell.command"; +static String const PT_LEXICON = "shell.lexicon"; static String const PT_GAME_STATE = "shell.game.state"; // ChallengePacket ----------------------------------------------------------- -static char const *CHALLENGE_PACKET_TYPE = "Psw?"; +static Packet::Type const CHALLENGE_PACKET_TYPE = Packet::typeFromString("Psw?"); ChallengePacket::ChallengePacket() : Packet(CHALLENGE_PACKET_TYPE) {} @@ -46,7 +45,7 @@ // LogEntryPacket ------------------------------------------------------------ -static char const *LOG_ENTRY_PACKET_TYPE = "LgEn"; +static Packet::Type const LOG_ENTRY_PACKET_TYPE = Packet::typeFromString("LgEn"); LogEntryPacket::LogEntryPacket() : Packet(LOG_ENTRY_PACKET_TYPE) {} @@ -108,7 +107,7 @@ // PlayerInfoPacket ---------------------------------------------------------- -static char const *PLAYER_INFO_PACKET_TYPE = "PlrI"; +static Packet::Type const PLAYER_INFO_PACKET_TYPE = Packet::typeFromString("PlrI"); DENG2_PIMPL_NOREF(PlayerInfoPacket) { @@ -174,7 +173,7 @@ // MapOutlinePacket ---------------------------------------------------------- -static char const *MAP_OUTLINE_PACKET_TYPE = "MpOL"; +static Packet::Type const MAP_OUTLINE_PACKET_TYPE = Packet::typeFromString("MpOL"); DENG2_PIMPL_NOREF(MapOutlinePacket) { @@ -257,31 +256,30 @@ { if (packet->type() == CHALLENGE_PACKET_TYPE) { - DENG2_ASSERT(dynamic_cast(packet) != 0); + DENG2_ASSERT(is(packet)); return PasswordChallenge; } if (packet->type() == LOG_ENTRY_PACKET_TYPE) { - DENG2_ASSERT(dynamic_cast(packet) != 0); + DENG2_ASSERT(is(packet)); return LogEntries; } if (packet->type() == MAP_OUTLINE_PACKET_TYPE) { - DENG2_ASSERT(dynamic_cast(packet) != 0); + DENG2_ASSERT(is(packet)); return MapOutline; } if (packet->type() == PLAYER_INFO_PACKET_TYPE) { - DENG2_ASSERT(dynamic_cast(packet) != 0); + DENG2_ASSERT(is(packet)); return PlayerInfo; } // One of the generic-format packets? - RecordPacket const *rec = dynamic_cast(packet); - if (rec) + if (RecordPacket const *rec = maybeAs(packet)) { if (rec->name() == PT_COMMAND) { @@ -368,5 +366,4 @@ return gs; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/serverfinder.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/serverfinder.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/serverfinder.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/serverfinder.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -28,39 +28,24 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { -static TimeDelta MSG_EXPIRATION_SECS = 4; +static TimeSpan MSG_EXPIRATION_SECS = 4; DENG2_PIMPL_NOREF(ServerFinder) { Beacon beacon; struct Found { - shell::ServerInfo *message; + shell::ServerInfo message; Time at; - Found() : message(0), at(Time()) {} + Found() : at(Time()) {} }; QMap servers; Impl() : beacon(DEFAULT_PORT) {} - ~Impl() - { - clearServers(); - } - - void clearServers() - { - foreach (Found const &found, servers.values()) - { - delete found.message; - } - servers.clear(); - } - bool removeExpired() { bool changed = false; @@ -71,7 +56,6 @@ Found &found = iter.next().value(); if (found.at.since() > MSG_EXPIRATION_SECS) { - delete found.message; iter.remove(); changed = true; } @@ -106,7 +90,7 @@ void ServerFinder::clear() { - d->clearServers(); + d->servers.clear(); } QList
ServerFinder::foundServers() const @@ -138,7 +122,7 @@ throw NotFoundError("ServerFinder::messageFromServer", "No message from server " + addr.asText()); } - return *d->servers[addr].message; + return d->servers[addr].message; } void ServerFinder::found(Address host, Block block) @@ -151,8 +135,10 @@ LOG_TRACE("Received a server message from %s with %i bytes", host << block.size()); - shell::ServerInfo receivedInfo; - Reader(block).withHeader() >> receivedInfo; + Record info; + Reader(block).withHeader() >> info; + + ServerInfo receivedInfo(info); receivedInfo.setAddress(host); Address const from = receivedInfo.address(); // port validated @@ -161,12 +147,12 @@ Impl::Found found; if (d->servers.contains(from)) { - *d->servers[from].message = receivedInfo; + d->servers[from].message = receivedInfo; d->servers[from].at = Time(); } else { - found.message = new shell::ServerInfo(receivedInfo); + found.message = receivedInfo; d->servers.insert(from, found); } @@ -179,7 +165,6 @@ // Remove the message that failed to deserialize. if (d->servers.contains(host)) { - delete d->servers[host].message; d->servers.remove(host); } } @@ -194,5 +179,4 @@ QTimer::singleShot(1000, this, SLOT(expire())); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/serverinfo.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/serverinfo.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/serverinfo.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/serverinfo.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -22,9 +22,9 @@ #include #include -namespace de { -namespace shell { +namespace de { namespace shell { +static String const VAR_SERVER_ID ("sid"); static String const VAR_VERSION ("ver"); static String const VAR_COMPATIBILITY_VERSION ("cver"); static String const VAR_HOST ("host"); @@ -42,140 +42,165 @@ static String const VAR_MAX_PLAYERS ("pmax"); static String const VAR_FLAGS ("flags"); -void checkValid(ServerInfo &info) +DENG2_PIMPL(ServerInfo) { - if (!info.has(VAR_PLAYERS)) info.addArray(VAR_PLAYERS); - if (info.has(VAR_HOST)) + std::shared_ptr info; + + Impl(Public *i) : Base(i) + {} + + void detach() { - if (info.address().port() != info.port()) + if (info.use_count() > 1) { - info.setAddress(Address(info.address().host(), info.port())); + // Duplicate our own copy of it. + info.reset(new Record(*info)); + DENG2_ASSERT(info.use_count() == 1); } } -} + + void checkValid() + { + if (!info->has(VAR_PLAYERS)) info->addArray(VAR_PLAYERS); + if (info->has(VAR_HOST)) + { + if (self().address().port() != self().port()) + { + self().setAddress(Address(self().address().host(), self().port())); + } + } + } +}; ServerInfo::ServerInfo() + : d(new Impl(this)) { - set(VAR_VERSION, Version::currentBuild().fullNumber()); - addArray(VAR_PLAYERS); + d->info.reset(new Record); + d->info->set(VAR_VERSION, Version::currentBuild().fullNumber()); + d->info->addArray(VAR_PLAYERS); } ServerInfo::ServerInfo(ServerInfo const &other) - : Record(other) + : d(new Impl(this)) { - checkValid(*this); + d->info = other.d->info; } ServerInfo::ServerInfo(Record const &rec) - : Record(rec) -{ - checkValid(*this); -} - -ServerInfo::ServerInfo(ServerInfo &&moved) - : Record(moved) -{ - checkValid(*this); -} - -ServerInfo &ServerInfo::operator = (ServerInfo const &other) + : d(new Impl(this)) { - Record::operator = (other); - checkValid(*this); - return *this; + d->info.reset(new Record(rec)); + d->checkValid(); } -ServerInfo &ServerInfo::operator = (ServerInfo &&moved) +ServerInfo &ServerInfo::operator=(ServerInfo const &other) { - Record::operator = (moved); - checkValid(*this); + d->info = other.d->info; return *this; } Version ServerInfo::version() const { - return Version(gets(VAR_VERSION)); + return Version(d->info->gets(VAR_VERSION)); } int ServerInfo::compatibilityVersion() const { - return geti(VAR_COMPATIBILITY_VERSION); + return d->info->geti(VAR_COMPATIBILITY_VERSION); } ServerInfo &ServerInfo::setCompatibilityVersion(int compatVersion) { - set(VAR_COMPATIBILITY_VERSION, compatVersion); + d->detach(); + d->info->set(VAR_COMPATIBILITY_VERSION, compatVersion); + return *this; +} + +ServerInfo &ServerInfo::setServerId(duint32 sid) +{ + d->detach(); + d->info->set(VAR_SERVER_ID, sid); return *this; } Address ServerInfo::address() const { - if (has(VAR_HOST)) + if (d->info->has(VAR_HOST)) { - return Address::parse(gets(VAR_HOST)); + return Address::parse(d->info->gets(VAR_HOST)); } return Address(); } String ServerInfo::domainName() const { - return gets(VAR_DOMAIN, ""); + return d->info->gets(VAR_DOMAIN, ""); } ServerInfo &ServerInfo::setAddress(Address const &address) { - set(VAR_HOST, address.asText()); - set(VAR_PORT, address.port()? address.port() : shell::DEFAULT_PORT); - checkValid(*this); + d->detach(); + d->info->set(VAR_HOST, address.asText()); + d->info->set(VAR_PORT, address.port() ? address.port() : shell::DEFAULT_PORT); + d->checkValid(); return *this; } duint16 ServerInfo::port() const { - return duint16(geti(VAR_PORT, shell::DEFAULT_PORT)); + return duint16(d->info->geti(VAR_PORT, shell::DEFAULT_PORT)); +} + +duint32 ServerInfo::serverId() const +{ + return d->info->getui(VAR_SERVER_ID, 0); } String ServerInfo::name() const { - return gets(VAR_NAME, ""); + return d->info->gets(VAR_NAME, ""); } ServerInfo &ServerInfo::setName(String const &name) { - set(VAR_NAME, name); + d->detach(); + d->info->set(VAR_NAME, name); return *this; } String ServerInfo::description() const { - return gets(VAR_DESCRIPTION, ""); + return d->info->gets(VAR_DESCRIPTION, ""); } ServerInfo &ServerInfo::setDescription(const String &description) { - set(VAR_DESCRIPTION, description); + d->detach(); + d->info->set(VAR_DESCRIPTION, description); return *this; } String ServerInfo::pluginDescription() const { - return gets(VAR_PLUGIN, ""); + return d->info->gets(VAR_PLUGIN, ""); } ServerInfo &ServerInfo::setPluginDescription(String const &pluginDescription) { - set(VAR_PLUGIN, pluginDescription); + d->detach(); + d->info->set(VAR_PLUGIN, pluginDescription); return *this; } StringList ServerInfo::packages() const { - return getStringList(VAR_PACKAGES); + return d->info->getStringList(VAR_PACKAGES); } ServerInfo &ServerInfo::setPackages(StringList packages) { - ArrayValue &pkgs = addArray(VAR_PACKAGES).value(); + d->detach(); + ArrayValue &pkgs = d->info->addArray(VAR_PACKAGES).value(); for (String const &p : packages) { pkgs << TextValue(p); @@ -185,64 +210,69 @@ String ServerInfo::gameId() const { - return gets(VAR_GAME_ID, ""); + return d->info->gets(VAR_GAME_ID, ""); } ServerInfo &ServerInfo::setGameId(String const &gameId) { - set(VAR_GAME_ID, gameId); + d->detach(); + d->info->set(VAR_GAME_ID, gameId); return *this; } String ServerInfo::gameConfig() const { - return gets(VAR_GAME_CONFIG, ""); + return d->info->gets(VAR_GAME_CONFIG, ""); } ServerInfo &ServerInfo::setGameConfig(String const &gameConfig) { - set(VAR_GAME_CONFIG, gameConfig); + d->detach(); + d->info->set(VAR_GAME_CONFIG, gameConfig); return *this; } String ServerInfo::map() const { - return gets(VAR_MAP, ""); + return d->info->gets(VAR_MAP, ""); } ServerInfo &ServerInfo::setMap(String const &map) { - set(VAR_MAP, map); + d->detach(); + d->info->set(VAR_MAP, map); return *this; } StringList ServerInfo::players() const { - return getStringList(VAR_PLAYERS); + return d->info->getStringList(VAR_PLAYERS); } int ServerInfo::playerCount() const { - return geti(VAR_PLAYER_COUNT, 0); + return d->info->geti(VAR_PLAYER_COUNT, 0); } ServerInfo &ServerInfo::addPlayer(String const &playerName) { - ArrayValue &players = member(VAR_PLAYERS).value(); + d->detach(); + ArrayValue &players = d->info->member(VAR_PLAYERS).value(); players.add(playerName); - set(VAR_PLAYER_COUNT, players.size()); + d->info->set(VAR_PLAYER_COUNT, players.size()); return *this; } ServerInfo &ServerInfo::removePlayer(String const &playerName) { - ArrayValue &players = member(VAR_PLAYERS).value(); + d->detach(); + ArrayValue &players = d->info->member(VAR_PLAYERS).value(); for (int i = 0; i < int(players.size()); ++i) { if (players.at(i).asText() == playerName) { players.remove(i); - set(VAR_PLAYER_COUNT, players.size()); + d->info->set(VAR_PLAYER_COUNT, players.size()); break; } } @@ -251,18 +281,19 @@ int ServerInfo::maxPlayers() const { - return geti(VAR_MAX_PLAYERS); + return d->info->geti(VAR_MAX_PLAYERS); } ServerInfo &ServerInfo::setMaxPlayers(int count) { - set(VAR_MAX_PLAYERS, count); + d->detach(); + d->info->set(VAR_MAX_PLAYERS, count); return *this; } ServerInfo::Flags ServerInfo::flags() const { - return Flags(geti(VAR_FLAGS, DefaultFlags)); + return Flags(d->info->geti(VAR_FLAGS, DefaultFlags)); } String ServerInfo::asStyledText() const @@ -297,28 +328,35 @@ Block ServerInfo::asJSON() const { - return composeJSON(*this); + return composeJSON(*d->info); +} + +const Record &ServerInfo::asRecord() const +{ + return *d->info; } Record ServerInfo::strippedForBroadcast() const { - Record stripped(*this); - if (stripped.has(VAR_HOST)) stripped.remove(VAR_HOST); // address in network msg - if (stripped.has(VAR_PLUGIN)) stripped.remove(VAR_PLUGIN); // gameId+version is enough - if (stripped.has(VAR_PLAYERS)) stripped.remove(VAR_PLAYERS); // count is enough - if (stripped.has(VAR_PACKAGES)) stripped.remove(VAR_PACKAGES); // queried before connecting + Record stripped(*d->info); + delete stripped.tryRemove(VAR_HOST); // address in network msg + delete stripped.tryRemove(VAR_PLUGIN); // gameId+version is enough + delete stripped.tryRemove(VAR_PLAYERS); // count is enough + delete stripped.tryRemove(VAR_PACKAGES); // queried before connecting return stripped; } ServerInfo &ServerInfo::setDomainName(String const &domain) { - set(VAR_DOMAIN, domain); + d->detach(); + d->info->set(VAR_DOMAIN, domain); return *this; } ServerInfo &ServerInfo::setFlags(Flags const &flags) { - set(VAR_FLAGS, duint32(flags)); + d->detach(); + d->info->set(VAR_FLAGS, duint32(flags)); return *this; } @@ -345,6 +383,8 @@ LOG_NET_MSG(" %s %-40s") << map() << description(); LOG_NET_MSG(" %s %s") << gameId() << gameConfig(); + LOG_NET_MSG(" Instance ID: %08x") << serverId(); + // Optional: PWADs in use. LOG_NET_MSG(" Packages: " _E(>) "%s") << String::join(packages(), "\n"); @@ -355,5 +395,4 @@ } } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textcanvas.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textcanvas.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textcanvas.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textcanvas.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,25 +13,23 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/TextCanvas" #include #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(TextCanvas) { - Size size; + Size size; QList lines; - struct RichFormat - { + struct RichFormat { Char::Attribs attrib; - Rangei range; + Rangei range; }; QList richFormats; @@ -210,7 +208,7 @@ { Impl::RichFormat rf; rf.attrib = attribs; - rf.range = range; + rf.range = range; d->richFormats.append(rf); } @@ -298,8 +296,6 @@ d->markAllAsDirty(false); } -void TextCanvas::setCursorPosition(Vector2i const &) -{} +void TextCanvas::setCursorPosition(Vector2i const &) {} -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textrootwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textrootwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textrootwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textrootwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -13,14 +13,13 @@ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy of * the GNU Lesser General Public License along with this program; if not, see: - * http://www.gnu.org/licenses + * http://www.gnu.org/licenses */ #include "de/shell/TextRootWidget" #include "de/shell/TextWidget" -namespace de { -namespace shell { +namespace de { namespace shell { TextRootWidget::TextRootWidget(TextCanvas *cv) : RootWidget(), _canvas(cv), _drawRequest(false) { @@ -72,5 +71,4 @@ _drawRequest = false; } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textwidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textwidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk/libshell/src/textwidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk/libshell/src/textwidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -21,13 +21,12 @@ #include "de/shell/Action" #include -namespace de { -namespace shell { +namespace de { namespace shell { DENG2_PIMPL_NOREF(TextWidget) { - TextCanvas *canvas; - RuleRectangle *rule; + TextCanvas * canvas; + RuleRectangle * rule; QList actions; Impl() : canvas(0), rule(new RuleRectangle) @@ -178,5 +177,4 @@ return Widget::handleEvent(event); } -} // namespace shell -} // namespace de +}} // namespace de::shell diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/sdk.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk.doxy 2018-12-11 07:08:23.000000000 +0000 @@ -2,7 +2,7 @@ @INCLUDE = doomsday.doxy PROJECT_NAME = "Doomsday SDK" -PROJECT_NUMBER = 2.0 +PROJECT_NUMBER = 2.1 PROJECT_BRIEF = "Core engine library and supporting libraries" PROJECT_LOGO = doc/apidoc-logo.png OUTPUT_DIRECTORY = apidoc/sdk/ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/sdk-qch.doxy doomsday-stable-2.1.0.2900+xenial/doomsday/sdk-qch.doxy --- doomsday-stable-2.0.3.2464+xenial/doomsday/sdk-qch.doxy 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/sdk-qch.doxy 2018-12-11 07:08:23.000000000 +0000 @@ -6,7 +6,7 @@ GENERATE_QHP = YES QCH_FILE = "doomsday.qch" QHP_NAMESPACE = "net.dengine.sdk.200" -QHP_VIRTUAL_FOLDER = "doomsday-2.0.0" +QHP_VIRTUAL_FOLDER = "doomsday-2.1.0" QHG_LOCATION = "../build/scripts/qhelp.py" # Dynamic HTML doesn't work inside Qt Creator diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/fonts.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/fonts.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/fonts.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/fonts.dei 2018-12-11 07:08:24.000000000 +0000 @@ -60,14 +60,14 @@ font default { family: Helvetica Neue - size $: gui.scale('16pt', DisplayMode.DPI_FACTOR) + size $: gui.scale('16pt', DisplayMode.PIXEL_RATIO) weight: normal style: normal } font monospace inherits default { family: Menlo - size $: gui.scale('13pt', DisplayMode.DPI_FACTOR) + size $: gui.scale('13pt', DisplayMode.PIXEL_RATIO) } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/rules.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/rules.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/rules.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/defaultstyle.pack/rules.dei 2018-12-11 07:08:24.000000000 +0000 @@ -1,8 +1,7 @@ # Length rules for the default UI style script { - import DisplayMode - UNIT = 4.0 * DisplayMode.DPI_FACTOR + UNIT = 4.0 } rule unit { constant $= UNIT } @@ -36,6 +35,10 @@ rule editor { constant $= UNIT * 20 } } +group choice { + rule item.width.max { constant $= UNIT * 100 } +} + group dialog { rule gap { constant $= UNIT * 2 } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.de doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,15 +0,0 @@ -# Config for test_appfw - -import gui - -def setDefaults(d) - # Applies the apps's defaults. - # - d: Record where to set the values. - gui.setDefaults(d) - - # Use a windowed mode instead of going to fullscreen. - d.window.main.fullscreen = False - d.window.main.maximize = False - - # TODO: Other default values set here. -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.ds doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/appconfig.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,15 @@ +# Config for test_appfw + +import gui + +def setDefaults(d) + # Applies the apps's defaults. + # - d: Record where to set the values. + gui.setDefaults(d) + + # Use a windowed mode instead of going to fullscreen. + d.window.main.fullscreen = False + d.window.main.maximize = False + + # TODO: Other default values set here. +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.de doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,2 +0,0 @@ -# test_appfw bootstrap -print "Running bootstrap..." diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.ds doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/modules/bootstrap.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,2 @@ +# test_appfw bootstrap +print "Running bootstrap..." diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/fx-blur.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/fx-blur.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/fx-blur.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/fx-blur.dei 2018-12-11 07:08:24.000000000 +0000 @@ -6,12 +6,12 @@ uniform highp vec4 uColor; uniform highp vec4 uWindow; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec2 aUV; + DENG_ATTRIB highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -25,21 +25,21 @@ fragment = " uniform sampler2D uTex; uniform highp vec2 uBlurStep; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { highp vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.05; - sum += texture2D(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.154; - sum += texture2D(uTex, vUV) * 0.165; - sum += texture2D(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.154; - sum += texture2D(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.05; - gl_FragColor = sum; - gl_FragColor.a = 1.0; + sum += texture(uTex, vec2(vUV.s - 4.0 * uBlurStep.s, vUV.t)) * 0.05; + sum += texture(uTex, vec2(vUV.s - 3.0 * uBlurStep.s, vUV.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s - 2.0 * uBlurStep.s, vUV.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s - uBlurStep.s, vUV.t)) * 0.154; + sum += texture(uTex, vUV) * 0.165; + sum += texture(uTex, vec2(vUV.s + uBlurStep.s, vUV.t)) * 0.154; + sum += texture(uTex, vec2(vUV.s + 2.0 * uBlurStep.s, vUV.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s + 3.0 * uBlurStep.s, vUV.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s + 4.0 * uBlurStep.s, vUV.t)) * 0.05; + out_FragColor = sum; + out_FragColor.a = 1.0; }" } @@ -49,20 +49,20 @@ fragment = " uniform sampler2D uTex; uniform highp vec2 uBlurStep; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { highp vec4 sum = vec4(0.0); - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.05; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.154; - sum += texture2D(uTex, vUV) * 0.165; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.154; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.123; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.09; - sum += texture2D(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.05; - gl_FragColor = sum * vColor; + sum += texture(uTex, vec2(vUV.s, vUV.t - 4.0 * uBlurStep.t)) * 0.05; + sum += texture(uTex, vec2(vUV.s, vUV.t - 3.0 * uBlurStep.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s, vUV.t - 2.0 * uBlurStep.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s, vUV.t - uBlurStep.t )) * 0.154; + sum += texture(uTex, vUV) * 0.165; + sum += texture(uTex, vec2(vUV.s, vUV.t + uBlurStep.t )) * 0.154; + sum += texture(uTex, vec2(vUV.s, vUV.t + 2.0 * uBlurStep.t)) * 0.123; + sum += texture(uTex, vec2(vUV.s, vUV.t + 3.0 * uBlurStep.t)) * 0.09; + sum += texture(uTex, vec2(vUV.s, vUV.t + 4.0 * uBlurStep.t)) * 0.05; + out_FragColor = sum * vColor; }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/generic.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/generic.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/generic.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/generic.dei 2018-12-11 07:08:24.000000000 +0000 @@ -8,19 +8,19 @@ vertex = " uniform highp mat4 uMvpMatrix; uniform highp vec4 uColor; - attribute highp vec4 aVertex; - attribute highp vec4 aColor; - varying highp vec4 vColor; + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec4 aColor; + DENG_VAR highp vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; vColor = uColor * aColor; }" fragment = " - varying highp vec4 vColor; + DENG_VAR highp vec4 vColor; void main(void) { - gl_FragColor = vColor; + out_FragColor = vColor; }" } @@ -28,9 +28,9 @@ { vertex = " uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - varying highp vec2 vUV; + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec2 aUV; + DENG_VAR highp vec2 vUV; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -38,10 +38,10 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; + DENG_VAR highp vec2 vUV; void main(void) { - gl_FragColor = texture2D(uTex, vUV); + out_FragColor = texture(uTex, vUV); }" } @@ -53,11 +53,11 @@ { vertex = " uniform highp mat4 uMvpMatrix; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec2 aUV; + DENG_ATTRIB highp vec4 aColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -66,11 +66,11 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { - gl_FragColor = vColor * texture2D(uTex, vUV); + out_FragColor = vColor * texture(uTex, vUV); }" } @@ -82,11 +82,11 @@ vertex = " uniform highp mat4 uMvpMatrix; uniform highp vec4 uColor; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec2 aUV; + DENG_ATTRIB highp vec4 aColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -95,11 +95,11 @@ }" fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; void main(void) { - gl_FragColor = vColor * texture2D(uTex, vUV); + out_FragColor = vColor * texture(uTex, vUV); }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/ui.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/ui.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/ui.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/net.dengine.test.appfw.pack/shaders/ui.dei 2018-12-11 07:08:24.000000000 +0000 @@ -7,15 +7,15 @@ uniform highp float uSaturation[DENG_MAX_BATCH_UNIFORMS]; uniform highp vec4 uScissorRect[DENG_MAX_BATCH_UNIFORMS]; - attribute highp vec4 aVertex; - attribute highp vec2 aUV; - attribute highp vec4 aColor; - attribute highp float aIndex; // uColor + DENG_ATTRIB highp vec4 aVertex; + DENG_ATTRIB highp vec2 aUV; + DENG_ATTRIB highp vec4 aColor; + DENG_ATTRIB highp float aIndex; // uColor - varying highp vec2 vUV; - varying highp vec4 vColor; - varying highp vec4 vScissor; - varying highp float vSaturation; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; + DENG_VAR highp vec4 vScissor; + DENG_VAR highp float vSaturation; void main(void) { gl_Position = uMvpMatrix * aVertex; @@ -30,10 +30,10 @@ fragment = " uniform sampler2D uTex; - varying highp vec2 vUV; - varying highp vec4 vColor; - varying highp vec4 vScissor; - varying highp float vSaturation; + DENG_VAR highp vec2 vUV; + DENG_VAR highp vec4 vColor; + DENG_VAR highp vec4 vScissor; + DENG_VAR highp float vSaturation; void main(void) { // Check the scissor first. @@ -41,17 +41,17 @@ gl_FragCoord.y < vScissor.y || gl_FragCoord.y > vScissor.w) { discard; } - gl_FragColor = texture2D(uTex, vUV); + out_FragColor = texture(uTex, vUV); // Optionally adjust color saturation. if (vSaturation < 1.0) { - highp vec4 hsv = rgbToHsv(gl_FragColor); + highp vec4 hsv = rgbToHsv(out_FragColor); hsv.y *= vSaturation; - gl_FragColor = hsvToRgb(hsv); + out_FragColor = hsvToRgb(hsv); } // Final vertex color. - gl_FragColor *= vColor; + out_FragColor *= vColor; }" } } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/src/main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/src/main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/src/main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/src/main.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -26,6 +26,7 @@ int main(int argc, char **argv) { + TestApp::setDefaultOpenGLFormat(); TestApp app(argc, argv); try { diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/src/mainwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/src/mainwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_appfw/src/mainwindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_appfw/src/mainwindow.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -99,7 +99,7 @@ .setInput(Rule::Right, root.viewRule().midX()) .setInput(Rule::Top, root.viewRule().top()) .setInput(Rule::Width, root.viewRule().width()/3) - .setInput(Rule::Height, Const(label->toDevicePixels(300))); + .setInput(Rule::Height, Const(GuiWidget::pointsToPixels(300))); compositor->add(label); LabelWidget *label2 = new LabelWidget; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_archive/main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_archive/main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_archive/main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_archive/main.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -121,7 +121,7 @@ LOG_MSG("Before flushing:\n") << app.homeFolder().contentsAsText(); - TimeDelta(0.5).sleep(); // make the time difference clearer + TimeSpan(0.5).sleep(); // make the time difference clearer // Changes were made to the archive via files. The archive won't be // written back to its source file until the ArchiveFolder instance @@ -130,10 +130,10 @@ LOG_MSG("After flushing:\n") << app.homeFolder().contentsAsText(); - App::fileSystem().copySerialized(updated.path(), "home/copied.zip", FS::PlainFileCopy); + FS::copySerialized(updated.path(), "home/copied.zip", FS::PlainFileCopy); LOG_MSG("Plain copy: ") << App::rootFolder().locate("home/copied.zip").description(); - App::fileSystem().copySerialized(updated.path(), "home/copied.zip"); + FS::copySerialized(updated.path(), "home/copied.zip"); LOG_MSG("Normal copy: ") << App::rootFolder().locate("home/copied.zip").description(); } catch (Error const &err) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_glsandbox/testwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_glsandbox/testwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_glsandbox/testwindow.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_glsandbox/testwindow.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -189,12 +189,12 @@ "uniform highp vec4 uColor;\n" "uniform highp float uTime;\n" - "attribute highp vec4 aVertex;\n" - "attribute highp vec2 aUV;\n" - "attribute highp vec4 aColor;\n" + "in highp vec4 aVertex;\n" + "in highp vec2 aUV;\n" + "in highp vec4 aColor;\n" - "varying highp vec2 vUV;\n" - "varying highp vec4 vColor;\n" + "out highp vec2 vUV;\n" + "out highp vec4 vColor;\n" "void main(void) {\n" " gl_Position = uMvpMatrix * aVertex;\n" @@ -205,13 +205,13 @@ ByteRefArray::fromCStr( "uniform sampler2D uTex;\n" - "varying highp vec2 vUV;\n" - "varying highp vec4 vColor;\n" + "in highp vec2 vUV;\n" + "in highp vec4 vColor;\n" "void main(void) {\n" - " highp vec4 color = texture2D(uTex, vUV);\n" + " highp vec4 color = texture(uTex, vUV);\n" " if (color.a < 0.05) discard;\n" - " gl_FragColor = color * vColor;\n" + " out_FragColor = color * vColor;\n" "}")) << uMvpMatrix << uColor << uTime @@ -234,18 +234,18 @@ atlasOb.program().build( ByteRefArray::fromCStr( "uniform highp mat4 uMvpMatrix;\n" - "attribute highp vec4 aVertex;\n" - "attribute highp vec2 aUV;\n" - "varying highp vec2 vUV;\n" + "in highp vec4 aVertex;\n" + "in highp vec2 aUV;\n" + "out highp vec2 vUV;\n" "void main(void) {\n" " gl_Position = uMvpMatrix * aVertex;\n" " vUV = aUV;\n" "}\n"), ByteRefArray::fromCStr( "uniform sampler2D uTex;\n" - "varying highp vec2 vUV;\n" + "in highp vec2 vUV;\n" "void main(void) {\n" - " gl_FragColor = texture2D(uTex, vUV);\n" + " out_FragColor = texture(uTex, vUV);\n" "}\n")) << uMvpMatrix // note: uniforms shared between programs << uTex; @@ -258,17 +258,17 @@ "uniform highp vec4 uColor;\n" "uniform highp mat4 uBoneMatrices[64];\n" - "attribute highp vec4 aVertex;\n" - "attribute highp vec3 aNormal;\n" - "attribute highp vec2 aUV;\n" - "attribute highp vec4 aBounds;\n" - "attribute highp vec4 aColor;\n" - "attribute highp vec4 aBoneIDs;\n" - "attribute highp vec4 aBoneWeights;\n" - - "varying highp vec2 vUV;\n" - "varying highp vec4 vColor;\n" - "varying highp vec3 vNormal;\n" + "in highp vec4 aVertex;\n" + "in highp vec3 aNormal;\n" + "in highp vec2 aUV;\n" + "in highp vec4 aBounds;\n" + "in highp vec4 aColor;\n" + "in highp vec4 aBoneIDs;\n" + "in highp vec4 aBoneWeights;\n" + + "out highp vec2 vUV;\n" + "out highp vec4 vColor;\n" + "out highp vec3 vNormal;\n" "void main(void) {\n" " highp mat4 bone =\n" @@ -284,10 +284,10 @@ "}\n"), ByteRefArray::fromCStr( "uniform sampler2D uTex;\n" - "varying highp vec2 vUV;\n" - "varying highp vec3 vNormal;\n" + "in highp vec2 vUV;\n" + "in highp vec3 vNormal;\n" "void main(void) {\n" - " gl_FragColor = texture2D(uTex, vUV) * " + " out_FragColor = texture(uTex, vUV) * " "vec4(vec3((vNormal.x + 1.0) / 2.0), 1.0);" "}\n")) << uMvpMatrix diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_info/test_info.dei doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_info/test_info.dei --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_info/test_info.dei 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_info/test_info.dei 2018-12-11 07:08:24.000000000 +0000 @@ -55,7 +55,7 @@ type2 example-block inherits first-block {} group font { - condition: Version.OS == 'macx' + #condition: Version.OS == 'macx' preferences < font.default, $" 'font'+'.'+'title' " > diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/CMakeLists.txt 2018-12-11 07:08:24.000000000 +0000 @@ -4,4 +4,4 @@ deng_test (test_script main.cpp) -install (FILES kitchen_sink.de sections.de DESTINATION ${DENG_INSTALL_DATA_DIR}) +install (FILES kitchen_sink.ds sections.ds DESTINATION ${DENG_INSTALL_DATA_DIR}) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/kitchen_sink.de doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/kitchen_sink.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/kitchen_sink.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/kitchen_sink.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,817 +0,0 @@ -# The Doomsday Engine Project -# -# Copyright (c) 2009-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -# ================ -# THE KITCHEN SINK -# ================ -# This script tests *all* features of the Doomsday Script Language. -# Behold its power and glory. - -import sections - -# --------------------------------------------------------------------------- -sections.begin('BASIC EXPRESSIONS') - -sections.subsection('Basic types (number, text, array, dictionary, time).') -print 5, 5.5, -3.141592657 -print 0x100, 0X123 -print 'Using underscores for readability:', 0x0012_3456 -print "Hello", 'World' -print """I can span -newlines.""" -print [1, 2, 3] -print [1, [2, 3], 4] -print {'a': 'b', 1: ['b', {5:6, 6:7}], ['array', 'as', 'key']: 'oh my'} -print 'The time is now:', Time() - -sections.subsection('Constants: True, False, None, Pi.') -print True, False, None, Pi - -sections.subsection('Built-in functions: len(), dictkeys(), dictvalues().') -print 'len("abcd") =', len("abcd") -print 'len([1, 2, 3, 4]) =', len([1, 2, 3, 4]) -print 'len({1:2, 3:5, 8:13}) =', len({1:2, 3:5, 8:13}) -print 'dictkeys({1:2, 3:5, 8:13}) =', dictkeys({1:2, 3:5, 8:13}) -print 'dictvalues({1:2, 3:5, 8:13}) =', dictvalues({1:2, 3:5, 8:13}) - -sections.subsection('Built-in functions: Text(), Number(), Time(), timedelta().') -print Text(123), Number("123") -print "Beginning of March 2011:", Time("2011-03-01") -print Time("2000-01-02 03:04:05.678") -print 'Invalid time:', Time("123-123"), Time("") -print 'Thousand seconds later:', timedelta(Time(), Time() + 1000) - -sections.subsection('Built-in functions: serialize() and deserialize().') -a = [1, 'One', {1:'One'}] -print 'a =', a -b = serialize(a) -print 'serialize(a) =', b -print 'deserialize(serialize(a)) =', deserialize(b) -del a, b - -sections.subsection('Built-in function: eval().') -a = eval(""" 'arg' + 'ument' """) -eval("""print "Printed from eval(): %s" % a""") - -# --------------------------------------------------------------------------- -sections.begin('OPERATOR EXPRESSIONS') - -sections.subsection('Operators: +') -print 'Numbers:', 1 + 1, -.5 + .5 -print 'Larger than 32-bit:', 0xffffffffff + 0xffffffffff -print 'Text:', 'Hello' + 'World' -print 'Array:', [1, 2, 3] + ['a', 'b', 'c'] -print 'Dictionary:', {1:2, 3:4} + {'a':'b', 'c':'d'} -print 'Time:', Time() + 3600 - -sections.subsection('Operators: -') -print 'Numbers:', 1 - 1, -.5 - .5 -print 'Larger than 32-bit:', 0xffffffffff - 0xffffffffff -print 'Dictionary:', {'a':'A', 'b':'B'} - 'a' -print 'Time:', Time() - 3600, timedelta(Time(), Time() - 3600) - -sections.subsection('Operators: *') -print 'Numbers:', 1 * 2, 2.5 * 4, (2 + 6) * 45 -print 'Text:', 'Word' * 3, 'Longword' * 3.5 - -sections.subsection('Operators: /') -print 'Numbers:', 2 / 2, 10 / 4, 1 / 0 -print 'Path concatenation:', 'folder' / 'filename.ext', 'folder/' / 'filename.ext' - -sections.subsection('Operators: %') -print 'Numbers:', 7 % 3 -print 'String formatting:', \ - '%s with "%3i" arguments. Hex %x, capital hex %X, float %f, precision %.10f.' % [ - 'Formatted', 2, 240, 240, Pi, Pi] -print 'More formatting: Width and precision: "%10.5f"' % Pi - -sections.subsection('Operators: +=, -=, *=, /=, %=') -a = 1 -print 'a =', a -print 'a =', a += 3 -print 'a =', a -= 3 -print 'a =', a *= 100 -print 'a =', a /= 10 -print 'a =', a %= 3 -print 'a =', a -path = '/some/path/' -print 'path =', path -print 'path =', path /= 'filename.ext' - -sections.subsection('Operators: []') -transports = ['planes', 'trains', 'automobiles', 'bicycles'] -print transports[2] -xlat = {'hi': 'hello', 'globe': 'world'} -print xlat['hi'], xlat['globe'] -matrix = [[1, 2], [3, 4]] -print 'Two level indexing:', matrix[0][1], matrix[1][1] -matrix2 = [matrix, matrix] -print 'Three level indexing:', matrix2[1][1][0], 'from', matrix2 - -sections.subsection('Operators: slice.') -fullArray = [1, 2, 3, 4, 5, 6, 7] -print 'Full:', fullArray -print 'Sliced:', fullArray[2:4], fullArray[3:], fullArray[:3] -print 'Nega-sliced:', fullArray[-4:-2] -print 'Reversing:', fullArray[::-1] -print 'Reverse slice:', fullArray[4:2:-1] -print 'Stepping:', fullArray[::2], fullArray[1:6:2] - -print 'Text can be sliced as well...' -fullString = "abcdefg" -print 'Full:', fullString -print 'Sliced:', fullString[2:4], fullString[3:], fullString[:3] -print 'Nega-sliced:', fullString[-4:-2] -print 'Reversing:', fullString[::-1] -print 'Reverse slice:', fullString[4:2:-1] -print 'Stepping:', fullString[::2], fullString[1:6:2] - -sections.subsection('Operators: not.') -print not True -print not False -print not 'Is this true?' - -sections.subsection('Operators: and/or.') -print True and True -print True and False -print True or True -print True or False -print False or False -print "'and' has higher precedence than 'or':", True and False or True - -print 'and/or have early termination:' -def returnValue(a) - print '- called with', a - return a -end -print 'True and True:' -if returnValue(True) and returnValue(True): pass -print 'False and True:' -if returnValue(False) and returnValue(True): pass -print 'False or True:' -if returnValue(False) or returnValue(True): pass -print 'True or True:' -if returnValue(True) or returnValue(True): pass - -sections.subsection('Operators: comparisons.') -print 'Numbers:', 1 > 3, 1 < 3, 2 >= 2, 4 >= 2, 2 <= 2, 4 <= 2 -print 'Text:', "hello" > "world", "hello" < "world", 'hello' == 'hello' -print 'True/False:', True == True, True != False -print 'Arrays:', [1, 0] == [1, 0], [1, 0] < [1, 1], [1, 0] > [1, 1], [2, 0] > [1, 0], [2, 0] < [1, 0] - -sections.subsection('Operators: in.') -print 'transports =', transports -if 'bicycles' in transports: print "Got a bicycle." -if not 'jet' in transports: print "No jet." - -# --------------------------------------------------------------------------- -sections.begin('STATEMENTS & COMPOUNDS') - -sections.subsection('Separating statements with semicolon.') -print 'Statement 1.'; print 'Statement 2.' - -sections.subsection('if/elsif/else statements.') -if True -end -if True - if True - if True - if True - end - end - end -end -if True - print 'Regular compound.' -else - print "You won't see this." -end -if True: print "One statement compound." -else: print "Not printed." -if True - print "Compound A" - if False - print "Compound B" - else: print "Compound C" -end -if False: print "Lots of useless stuff here" -elsif True - print "From the elsif" -end - -if False - print 'a)' -elsif False - print 'b)' -elsif True > False - print 'c)' -end -print 'After the a), b), c)' - -if True: print 'Everything on one line.'; else: print 'Goes unseen.' -if False; print 'Goes unseen again.'; else; print 'And with semicolons (requires "end").'; end - -sections.subsection('Assign statement.') -print 'Assigning 10 to i...' -i = 10 -print '...and i ==', i -i = 'abc' -print "Now i ==", i - -sections.subsection('Assign statement: assigning into elements.') -array = [1, 2, 3, 4] -originalArray = array # by value -print array -array[1] = 100 -print array -array[1] = ['a', 'b', 'c'] -print array -array[1][1] = 'Bee' -print array -array[1] = {1:2, 'Three':4} -print array -array[1][4] = 'Four' -print array -array[2] = array[1] -print array -array[2]['Three'] = '300' -print array -print originalArray - -sections.subsection('Assign statement: weak assignment with ?=.') -print "'z' in locals():", 'z' in locals() -z ?= 3 -print "'z' in locals():", 'z' in locals() -print 'z =', z -print 'Trying weak assignment: z ?= 10' -z ?= 10 -print 'z =', z - -sections.subsection('Assign statement: const assignment to make read-only variables.') -z = 1 -print 'z =', z -const z = 10 -print 'z has been consted to', z -try - z = 10 - print 'It is allowed to reassign the same value...' - z = 5 -catch ReadOnlyError - print 'Have to delete z before its value can change.' -end -del z -z = 2 -print 'Now z =', 2 - -sections.subsection('Delete statement: deleting identifiers.') -def funky() - i = 1 - k = 2 - print locals() - del i - print 'After deletion:' - print locals() -end -funky() -del funky - -sections.subsection('while statement.') -i = 5 -while i > 0 - print 'Still looping because %i > 0' % i - i -= 1 -end - -sections.subsection('break statement.') -while True - print "I won't stay here." - break - print "Jumped over me." -end -print "Out of the while." -while False: print "Never going in." -while True - while True - print "Uh-oh, now I'm in trouble!" - break 2 - end -end -print "Guess again!" - -sections.subsection('for statement.') -for i in ['planes', 'trains', 'automobiles'] - print "I would like:", i -end -print 'Value of i after the "for" loop is', i - -sections.subsection('continue statement.') -i = 3 -while i > 0 - print 'i =', i - i -= 1 - if i == 1: continue - print 'Bottom of loop.' -end -for i in ['planes', 'trains', 'automobiles'] - if i == 'trains': continue - print i, 'are cool!' -end - -sections.subsection('pass statement: no operation.') -if True: print "'Tis true."; else: pass - -# --------------------------------------------------------------------------- -sections.begin('EXCEPTIONS') - -sections.subsection('Simple try/catch.') -try: print 'Nothing thrown yet.' -catch: print 'Skipped.' - -try: throw "OMG!" -catch: print 'Whoa there.' - -try - throw "OMG!" -catch - print 'Not so fast!' -end - -try: throw "OMG!" -catch Error - print 'Hold your horses.' -end - -try - throw "OMG!" -catch Error: print "Whatcha tryin' to pull?" - -sections.subsection('Minimal catch.') -try: throw 'OMG!' -catch: pass - -sections.subsection('Assigning exception message to local variable.') -try: throw "OMG!" -catch Error, er - print 'Caught:', er -end -try: throw "OMG!" -catch Error, er: print 'Caught:', er - -sections.subsection('Nesting try/catch statements.') -try - try - try - throw 'Deep.' - catch BogusError - end - catch BogusError - end -catch Error, er: print 'Got it:', er -try - try - try - throw 'Deep 2.' - catch BogusError - end - catch BogusError: pass - try - catch Error, er - print 'Should *not* be caught here.' - end -catch Error, er - print 'Should be caught here:', er -end - -sections.subsection('Throwing exception in a function.') -def erroneous() - throw "I can't handle the truth!" -end -try - print "Calling erroneous()" - erroneous() - try - print 'This will be skipped!' - catch - print 'I am on the wrong catch level.' - end -catch - print 'Fumbled it...' -end - -sections.subsection('Catching a specific type of exception.') -try - record temp - reference = temp - del temp - print reference -catch NullError, er - print 'Oh noes:', er -end - -sections.subsection('Multiple catch statements.') -try - throw 'For the 2nd catch.' -catch NullError: print 'Got NullError' -catch Error, er: print er -catch: print 'Never here.' - -sections.subsection('Exception thrown in another module.') -try - sections.throwError() -catch Error, er - print 'Got error from another module:', er -end - -sections.subsection('Exception thrown in recursive call.') -def recursive(i) - print i - if i == 10: throw 'Reached 10!' - recursive(i + 1) -end -try - recursive(1) -catch Error, er - print er -end - -sections.subsection('Exception from trying to change a read-only variable.') -const SOME_CONSTANT = 3.1415 -print 'SOME_CONSTANT =', SOME_CONSTANT -try - SOME_CONSTANT = 3 -catch ReadOnlyError, er - print 'Cannot do it.', er -end -try - const SOME_CONSTANT = 3 -catch ReadOnlyError, er - print 'Will not work either:', er -end - -# --------------------------------------------------------------------------- -sections.begin('RECORDS') - -sections.subsection('Creating a record with a statement.') -record myrec -print len(myrec) -print "Alternative way using Record()." -del myrec -myrec = Record() -print len(myrec) - -sections.subsection('Creating a record using an expression.') -del myrec -(record myrec).expressionCreated = True -myrec.(record subexp).alsoExpCreated = True -print myrec -del myrec.subexp - -sections.subsection('Creating variables into a record.') -myrec.newMember = 100 -print len(myrec) -print 'myrec.newMember =', myrec.newMember -print "Here's the record:" -print myrec - -sections.subsection('Creating a subrecord.') -record myrec.subrec -print len(myrec), len(myrec.subrec) -const myrec.subrec.something = 200 -try - myrec.subrec.something = 201 - print 'THIS IS AN ERROR -- EXCEPTION SHOULD HAVE BEEN THROWN! --' -catch ReadOnlyError, er - print 'Cannot change const member.' - print er -end -print 'myrec.subrec.something =', myrec.subrec.something -print "Here's the record:" -print myrec - -sections.subsection('Checking whether members exist in record.') -print 'subrec' in myrec, 'newMember' in myrec, 'not-there' in myrec.subrec - -sections.subsection('Built-in functions: members(), subrecords().') -print 'members of myrec:', members(myrec) -print 'subrecords of myrec:', subrecords(myrec) - -sections.subsection('Alternative ways to access members and subrecords.') -print myrec['newMember'] -print myrec['subrec'] -print myrec['subrec']['something'] -print members(myrec)['newMember'] - -sections.subsection('Creating new members using [].') -myrec['assignedElement'] = 3000 -print myrec - -sections.subsection('Copying members using recutil.') -import recutil -record copyTarget -recutil.copyMissingMembers(myrec, copyTarget) -print "Copied:\n", copyTarget -del recutil - -sections.subsection('Having two variables reference the same record.') -reference = myrec -print len(reference) -reference.otherMember = 150 -print "Here's the record:" -print myrec -reference.memberViaRef = 'added via ref' -print "Added a member via a reference:" -print reference - -sections.subsection('Accessing members through a record reference.') -record other -other.refd = reference -print 'The other is:' -print other -other.refd.newMember = 300 -print 'myrec after modifications:' -print myrec - -sections.subsection('Making a copy of a record.') -def recCopyTest() - print "Record() can be used to make a copy of a record." - reference = Record(myrec) - print reference - print "Now we can modify the new record without affecting myrec." - reference.superGreat = 'wow' - del reference.subrec - print reference - print "Original:" - print myrec - print "Locals:" - print locals() -end -recCopyTest() - -sections.subsection('Deleting members from record.') -print 'Before deleting:' -print myrec -del myrec.subrec.something -print 'After deleting:' -print myrec -print "subrec isn't gone, though: len(myrec.subrec) =", len(myrec.subrec) - -sections.subsection('Deleting a record pointed to by two variables.') -record soonDeleted -reference = soonDeleted -del soonDeleted -try: print reference -catch Error, er: print "Can't print reference:", er -del reference - -sections.subsection('Serializing records.') -print 'serialize(myrec) =', serialize(myrec) -print 'deserialize(serialize(myrec)) =' -print deserialize(serialize(myrec)) - -# --------------------------------------------------------------------------- -sections.begin('FUNCTIONS') - -sections.subsection('Defining a function (empty body).') -def func1(): return -func1() -def func1b() -end -func1b() - -sections.subsection('Returning values from the function.') -def func2(): return 'World' -print 'Hello', func2() -def func2b(a) - if a - return "It is true!" - else - return "Nay, it is false." - end -end -print func2b(1), func2b(''), func2b(True), func2b(False) - -sections.subsection('Returning a record from a function.') -def recFunc() - record a - a.value = "recFunc" - return a -end - -try: print recFunc() -catch NullError - print "Records are passed by reference; the returned record went out of scope." -end - -del recFunc -def recFunc() - record a - a.value = "recFunc" - return Record(a) -end -print "Let's try again, making a copy for the return value." -print recFunc() -del recFunc - -sections.subsection('Passing arguments.') -a = 'At process scope.' -def func3(a, b, c) - print 'The arguments were:', a, b, c - return b -end -print 'returned:', func3(1, 2, 3) -print a - -sections.subsection('Passing record as argument.') -myrec.passed = 'Original' -print 'myrec.passed =', myrec.passed -def recArg(r) - r.passed = 'Changed' -end -recArg(myrec) -print 'myrec.passed =', myrec.passed - -sections.subsection('Default values to function arguments.') -def func4(a, b='default', c=100) - print 'Given:', a, b, c -end -func4(1) -func4(1, 2) -func4([1,2], c='world', b='hello') -print 'func4 =', func4 - -sections.subsection('Defining function in a record.') -def myrec.func5(a, b) - return a + b -end -print myrec.func5("The record is\n", Text(myrec)) - -sections.subsection('Defining a function within a function.') -def func6() - print 'Inside func6.' - print 'func2() =', func2() - def func2(): return 'Shadows the global level.' - print 'func2() =', func2() -end -func6() -print 'func2() =', func2() - -sections.subsection("Accessing function's locals within a subfunction.") -def func7() - a = 100 - print 'Inside func7: a =', a - def func() - print 'Inside func: a =', a - end - func() -end -func7() - -sections.subsection('Reference to function.') -reference = func2 -print 'func2() =', func2() -print 'reference() =', reference() -print 'reference =', reference - -sections.subsection('Callback function as argument.') -def doCallback(a, b, cb) - print cb(a, b) -end -doCallback(10, 15, myrec.func5) - -sections.subsection('Returning a local function from a function.') -a = 'Process scope.' -def testfun() - a = 'testfun() scope.' - def returningFunc() - print 'I come from another place.', a - end - returningFunc() # 'a' found in local namespace - return returningFunc -end -testfun()() # 'a' found in global namespace! (testfun()'s local scope does not exist here) -ar = [testfun] -ar[0]()() - -# --------------------------------------------------------------------------- -sections.begin('SCOPES') - -sections.subsection('Global assignment with :=.') -a = 1 -print 'a =', a -def normalAssign() - a = 2 - print 'in normalAssign(), a =', a -end -normalAssign() -print 'a =', a -def globalAssign() - a := 2 - print 'in globalAssign(), a =', a -end -globalAssign() -print 'a =', a - -sections.subsection('Exporting variable from a function.') -def exporting() - abc = 'Value from exporting()' - export abc -end -abc = 'Value in global namespace' -print 'Before: abc =', abc -exporting() -print 'After: abc =', abc - -sections.subsection('Exporting a record.') -def exporting2() - record bunny - bunny.ear = 'value' - export bunny -end -exporting2() -print 'bunny =', bunny - -sections.subsection('Exporting while assigning.') -del abc -def exporting3() - export abc = 'Value from exporting3()' -end -exporting3() -print 'abc =', abc - -sections.subsection('Built-in function locals() returns the local namespace as a record.') -print 'At global level:' -print locals() -print -print 'Within a function:' -def func8() - justMe = "Function's local namespace." - print locals() -end -func8() - -sections.subsection('Importing modules: built-in module Config.') -import Config -print "Here's the Config:" -print Config - -sections.subsection('Serializing namespaces.') -sns = serialize(locals()) -print 'sns =', sns -print 'That deserializes into:' -dsns = deserialize(sns) -print dsns -print 'Calling deserialized function...' -print dsns.func3(1, 2, 3) -print 'Calling deserialized function that throws an exception...' -try: dsns.erroneous(); catch: print 'Caught.' -del dsns - -sections.subsection('Serializing record references.') -def recordRefTest() - record hello - hello.entry = 'World' - - record hello.subrec - hello.subrec.another = 123 - - hello.recref = hello.subrec - - print 'Original record:' - print hello - - hello.subrec.another = 456 - print 'Modified:' - print hello - - print 'After serialization:' - print deserialize(serialize(hello)) -end -recordRefTest() - -sections.subsection('Importing modules: import record.') -print 'Getting rid of the imported sections module (which is just a reference).' -print "Note that this has no effect on sections's own namespace." -del sections -print 'import record sections' -import record sections -print 'The sections namespace has become a local record.' -print locals() - -# --------------------------------------------------------------------------- -sections.begin('SCRIPT RETURN VALUE') - -sections.subsection('Returning value from the script: the final expression.') -"I am the return value." diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/kitchen_sink.ds doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/kitchen_sink.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/kitchen_sink.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/kitchen_sink.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,817 @@ +# The Doomsday Engine Project +# +# Copyright (c) 2009-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +# ================ +# THE KITCHEN SINK +# ================ +# This script tests *all* features of the Doomsday Script Language. +# Behold its power and glory. + +import sections + +# --------------------------------------------------------------------------- +sections.begin('BASIC EXPRESSIONS') + +sections.subsection('Basic types (number, text, array, dictionary, time).') +print 5, 5.5, -3.141592657 +print 0x100, 0X123 +print 'Using underscores for readability:', 0x0012_3456 +print "Hello", 'World' +print """I can span +newlines.""" +print [1, 2, 3] +print [1, [2, 3], 4] +print {'a': 'b', 1: ['b', {5:6, 6:7}], ['array', 'as', 'key']: 'oh my'} +print 'The time is now:', Time() + +sections.subsection('Constants: True, False, None, Pi.') +print True, False, None, Pi + +sections.subsection('Built-in functions: len(), dictkeys(), dictvalues().') +print 'len("abcd") =', len("abcd") +print 'len([1, 2, 3, 4]) =', len([1, 2, 3, 4]) +print 'len({1:2, 3:5, 8:13}) =', len({1:2, 3:5, 8:13}) +print 'dictkeys({1:2, 3:5, 8:13}) =', dictkeys({1:2, 3:5, 8:13}) +print 'dictvalues({1:2, 3:5, 8:13}) =', dictvalues({1:2, 3:5, 8:13}) + +sections.subsection('Built-in functions: Text(), Number(), Time(), timedelta().') +print Text(123), Number("123") +print "Beginning of March 2011:", Time("2011-03-01") +print Time("2000-01-02 03:04:05.678") +print 'Invalid time:', Time("123-123"), Time("") +print 'Thousand seconds later:', timedelta(Time(), Time() + 1000) + +sections.subsection('Built-in functions: serialize() and deserialize().') +a = [1, 'One', {1:'One'}] +print 'a =', a +b = serialize(a) +print 'serialize(a) =', b +print 'deserialize(serialize(a)) =', deserialize(b) +del a, b + +sections.subsection('Built-in function: eval().') +a = eval(""" 'arg' + 'ument' """) +eval("""print "Printed from eval(): %s" % a""") + +# --------------------------------------------------------------------------- +sections.begin('OPERATOR EXPRESSIONS') + +sections.subsection('Operators: +') +print 'Numbers:', 1 + 1, -.5 + .5 +print 'Larger than 32-bit:', 0xffffffffff + 0xffffffffff +print 'Text:', 'Hello' + 'World' +print 'Array:', [1, 2, 3] + ['a', 'b', 'c'] +print 'Dictionary:', {1:2, 3:4} + {'a':'b', 'c':'d'} +print 'Time:', Time() + 3600 + +sections.subsection('Operators: -') +print 'Numbers:', 1 - 1, -.5 - .5 +print 'Larger than 32-bit:', 0xffffffffff - 0xffffffffff +print 'Dictionary:', {'a':'A', 'b':'B'} - 'a' +print 'Time:', Time() - 3600, timedelta(Time(), Time() - 3600) + +sections.subsection('Operators: *') +print 'Numbers:', 1 * 2, 2.5 * 4, (2 + 6) * 45 +print 'Text:', 'Word' * 3, 'Longword' * 3.5 + +sections.subsection('Operators: /') +print 'Numbers:', 2 / 2, 10 / 4, 1 / 0 +print 'Path concatenation:', 'folder' / 'filename.ext', 'folder/' / 'filename.ext' + +sections.subsection('Operators: %') +print 'Numbers:', 7 % 3 +print 'String formatting:', \ + '%s with "%3i" arguments. Hex %x, capital hex %X, float %f, precision %.10f.' % [ + 'Formatted', 2, 240, 240, Pi, Pi] +print 'More formatting: Width and precision: "%10.5f"' % Pi + +sections.subsection('Operators: +=, -=, *=, /=, %=') +a = 1 +print 'a =', a +print 'a =', a += 3 +print 'a =', a -= 3 +print 'a =', a *= 100 +print 'a =', a /= 10 +print 'a =', a %= 3 +print 'a =', a +path = '/some/path/' +print 'path =', path +print 'path =', path /= 'filename.ext' + +sections.subsection('Operators: []') +transports = ['planes', 'trains', 'automobiles', 'bicycles'] +print transports[2] +xlat = {'hi': 'hello', 'globe': 'world'} +print xlat['hi'], xlat['globe'] +matrix = [[1, 2], [3, 4]] +print 'Two level indexing:', matrix[0][1], matrix[1][1] +matrix2 = [matrix, matrix] +print 'Three level indexing:', matrix2[1][1][0], 'from', matrix2 + +sections.subsection('Operators: slice.') +fullArray = [1, 2, 3, 4, 5, 6, 7] +print 'Full:', fullArray +print 'Sliced:', fullArray[2:4], fullArray[3:], fullArray[:3] +print 'Nega-sliced:', fullArray[-4:-2] +print 'Reversing:', fullArray[::-1] +print 'Reverse slice:', fullArray[4:2:-1] +print 'Stepping:', fullArray[::2], fullArray[1:6:2] + +print 'Text can be sliced as well...' +fullString = "abcdefg" +print 'Full:', fullString +print 'Sliced:', fullString[2:4], fullString[3:], fullString[:3] +print 'Nega-sliced:', fullString[-4:-2] +print 'Reversing:', fullString[::-1] +print 'Reverse slice:', fullString[4:2:-1] +print 'Stepping:', fullString[::2], fullString[1:6:2] + +sections.subsection('Operators: not.') +print not True +print not False +print not 'Is this true?' + +sections.subsection('Operators: and/or.') +print True and True +print True and False +print True or True +print True or False +print False or False +print "'and' has higher precedence than 'or':", True and False or True + +print 'and/or have early termination:' +def returnValue(a) + print '- called with', a + return a +end +print 'True and True:' +if returnValue(True) and returnValue(True): pass +print 'False and True:' +if returnValue(False) and returnValue(True): pass +print 'False or True:' +if returnValue(False) or returnValue(True): pass +print 'True or True:' +if returnValue(True) or returnValue(True): pass + +sections.subsection('Operators: comparisons.') +print 'Numbers:', 1 > 3, 1 < 3, 2 >= 2, 4 >= 2, 2 <= 2, 4 <= 2 +print 'Text:', "hello" > "world", "hello" < "world", 'hello' == 'hello' +print 'True/False:', True == True, True != False +print 'Arrays:', [1, 0] == [1, 0], [1, 0] < [1, 1], [1, 0] > [1, 1], [2, 0] > [1, 0], [2, 0] < [1, 0] + +sections.subsection('Operators: in.') +print 'transports =', transports +if 'bicycles' in transports: print "Got a bicycle." +if not 'jet' in transports: print "No jet." + +# --------------------------------------------------------------------------- +sections.begin('STATEMENTS & COMPOUNDS') + +sections.subsection('Separating statements with semicolon.') +print 'Statement 1.'; print 'Statement 2.' + +sections.subsection('if/elsif/else statements.') +if True +end +if True + if True + if True + if True + end + end + end +end +if True + print 'Regular compound.' +else + print "You won't see this." +end +if True: print "One statement compound." +else: print "Not printed." +if True + print "Compound A" + if False + print "Compound B" + else: print "Compound C" +end +if False: print "Lots of useless stuff here" +elsif True + print "From the elsif" +end + +if False + print 'a)' +elsif False + print 'b)' +elsif True > False + print 'c)' +end +print 'After the a), b), c)' + +if True: print 'Everything on one line.'; else: print 'Goes unseen.' +if False; print 'Goes unseen again.'; else; print 'And with semicolons (requires "end").'; end + +sections.subsection('Assign statement.') +print 'Assigning 10 to i...' +i = 10 +print '...and i ==', i +i = 'abc' +print "Now i ==", i + +sections.subsection('Assign statement: assigning into elements.') +array = [1, 2, 3, 4] +originalArray = array # by value +print array +array[1] = 100 +print array +array[1] = ['a', 'b', 'c'] +print array +array[1][1] = 'Bee' +print array +array[1] = {1:2, 'Three':4} +print array +array[1][4] = 'Four' +print array +array[2] = array[1] +print array +array[2]['Three'] = '300' +print array +print originalArray + +sections.subsection('Assign statement: weak assignment with ?=.') +print "'z' in locals():", 'z' in locals() +z ?= 3 +print "'z' in locals():", 'z' in locals() +print 'z =', z +print 'Trying weak assignment: z ?= 10' +z ?= 10 +print 'z =', z + +sections.subsection('Assign statement: const assignment to make read-only variables.') +z = 1 +print 'z =', z +const z = 10 +print 'z has been consted to', z +try + z = 10 + print 'It is allowed to reassign the same value...' + z = 5 +catch ReadOnlyError + print 'Have to delete z before its value can change.' +end +del z +z = 2 +print 'Now z =', 2 + +sections.subsection('Delete statement: deleting identifiers.') +def funky() + i = 1 + k = 2 + print locals() + del i + print 'After deletion:' + print locals() +end +funky() +del funky + +sections.subsection('while statement.') +i = 5 +while i > 0 + print 'Still looping because %i > 0' % i + i -= 1 +end + +sections.subsection('break statement.') +while True + print "I won't stay here." + break + print "Jumped over me." +end +print "Out of the while." +while False: print "Never going in." +while True + while True + print "Uh-oh, now I'm in trouble!" + break 2 + end +end +print "Guess again!" + +sections.subsection('for statement.') +for i in ['planes', 'trains', 'automobiles'] + print "I would like:", i +end +print 'Value of i after the "for" loop is', i + +sections.subsection('continue statement.') +i = 3 +while i > 0 + print 'i =', i + i -= 1 + if i == 1: continue + print 'Bottom of loop.' +end +for i in ['planes', 'trains', 'automobiles'] + if i == 'trains': continue + print i, 'are cool!' +end + +sections.subsection('pass statement: no operation.') +if True: print "'Tis true."; else: pass + +# --------------------------------------------------------------------------- +sections.begin('EXCEPTIONS') + +sections.subsection('Simple try/catch.') +try: print 'Nothing thrown yet.' +catch: print 'Skipped.' + +try: throw "OMG!" +catch: print 'Whoa there.' + +try + throw "OMG!" +catch + print 'Not so fast!' +end + +try: throw "OMG!" +catch Error + print 'Hold your horses.' +end + +try + throw "OMG!" +catch Error: print "Whatcha tryin' to pull?" + +sections.subsection('Minimal catch.') +try: throw 'OMG!' +catch: pass + +sections.subsection('Assigning exception message to local variable.') +try: throw "OMG!" +catch Error, er + print 'Caught:', er +end +try: throw "OMG!" +catch Error, er: print 'Caught:', er + +sections.subsection('Nesting try/catch statements.') +try + try + try + throw 'Deep.' + catch BogusError + end + catch BogusError + end +catch Error, er: print 'Got it:', er +try + try + try + throw 'Deep 2.' + catch BogusError + end + catch BogusError: pass + try + catch Error, er + print 'Should *not* be caught here.' + end +catch Error, er + print 'Should be caught here:', er +end + +sections.subsection('Throwing exception in a function.') +def erroneous() + throw "I can't handle the truth!" +end +try + print "Calling erroneous()" + erroneous() + try + print 'This will be skipped!' + catch + print 'I am on the wrong catch level.' + end +catch + print 'Fumbled it...' +end + +sections.subsection('Catching a specific type of exception.') +try + record temp + reference = temp + del temp + print reference +catch NullError, er + print 'Oh noes:', er +end + +sections.subsection('Multiple catch statements.') +try + throw 'For the 2nd catch.' +catch NullError: print 'Got NullError' +catch Error, er: print er +catch: print 'Never here.' + +sections.subsection('Exception thrown in another module.') +try + sections.throwError() +catch Error, er + print 'Got error from another module:', er +end + +sections.subsection('Exception thrown in recursive call.') +def recursive(i) + print i + if i == 10: throw 'Reached 10!' + recursive(i + 1) +end +try + recursive(1) +catch Error, er + print er +end + +sections.subsection('Exception from trying to change a read-only variable.') +const SOME_CONSTANT = 3.1415 +print 'SOME_CONSTANT =', SOME_CONSTANT +try + SOME_CONSTANT = 3 +catch ReadOnlyError, er + print 'Cannot do it.', er +end +try + const SOME_CONSTANT = 3 +catch ReadOnlyError, er + print 'Will not work either:', er +end + +# --------------------------------------------------------------------------- +sections.begin('RECORDS') + +sections.subsection('Creating a record with a statement.') +record myrec +print len(myrec) +print "Alternative way using Record()." +del myrec +myrec = Record() +print len(myrec) + +sections.subsection('Creating a record using an expression.') +del myrec +(record myrec).expressionCreated = True +myrec.(record subexp).alsoExpCreated = True +print myrec +del myrec.subexp + +sections.subsection('Creating variables into a record.') +myrec.newMember = 100 +print len(myrec) +print 'myrec.newMember =', myrec.newMember +print "Here's the record:" +print myrec + +sections.subsection('Creating a subrecord.') +record myrec.subrec +print len(myrec), len(myrec.subrec) +const myrec.subrec.something = 200 +try + myrec.subrec.something = 201 + print 'THIS IS AN ERROR -- EXCEPTION SHOULD HAVE BEEN THROWN! --' +catch ReadOnlyError, er + print 'Cannot change const member.' + print er +end +print 'myrec.subrec.something =', myrec.subrec.something +print "Here's the record:" +print myrec + +sections.subsection('Checking whether members exist in record.') +print 'subrec' in myrec, 'newMember' in myrec, 'not-there' in myrec.subrec + +sections.subsection('Built-in functions: members(), subrecords().') +print 'members of myrec:', members(myrec) +print 'subrecords of myrec:', subrecords(myrec) + +sections.subsection('Alternative ways to access members and subrecords.') +print myrec['newMember'] +print myrec['subrec'] +print myrec['subrec']['something'] +print members(myrec)['newMember'] + +sections.subsection('Creating new members using [].') +myrec['assignedElement'] = 3000 +print myrec + +sections.subsection('Copying members using recutil.') +import recutil +record copyTarget +recutil.copyMissingMembers(myrec, copyTarget) +print "Copied:\n", copyTarget +del recutil + +sections.subsection('Having two variables reference the same record.') +reference = myrec +print len(reference) +reference.otherMember = 150 +print "Here's the record:" +print myrec +reference.memberViaRef = 'added via ref' +print "Added a member via a reference:" +print reference + +sections.subsection('Accessing members through a record reference.') +record other +other.refd = reference +print 'The other is:' +print other +other.refd.newMember = 300 +print 'myrec after modifications:' +print myrec + +sections.subsection('Making a copy of a record.') +def recCopyTest() + print "Record() can be used to make a copy of a record." + reference = Record(myrec) + print reference + print "Now we can modify the new record without affecting myrec." + reference.superGreat = 'wow' + del reference.subrec + print reference + print "Original:" + print myrec + print "Locals:" + print locals() +end +recCopyTest() + +sections.subsection('Deleting members from record.') +print 'Before deleting:' +print myrec +del myrec.subrec.something +print 'After deleting:' +print myrec +print "subrec isn't gone, though: len(myrec.subrec) =", len(myrec.subrec) + +sections.subsection('Deleting a record pointed to by two variables.') +record soonDeleted +reference = soonDeleted +del soonDeleted +try: print reference +catch Error, er: print "Can't print reference:", er +del reference + +sections.subsection('Serializing records.') +print 'serialize(myrec) =', serialize(myrec) +print 'deserialize(serialize(myrec)) =' +print deserialize(serialize(myrec)) + +# --------------------------------------------------------------------------- +sections.begin('FUNCTIONS') + +sections.subsection('Defining a function (empty body).') +def func1(): return +func1() +def func1b() +end +func1b() + +sections.subsection('Returning values from the function.') +def func2(): return 'World' +print 'Hello', func2() +def func2b(a) + if a + return "It is true!" + else + return "Nay, it is false." + end +end +print func2b(1), func2b(''), func2b(True), func2b(False) + +sections.subsection('Returning a record from a function.') +def recFunc() + record a + a.value = "recFunc" + return a +end + +try: print recFunc() +catch NullError + print "Records are passed by reference; the returned record went out of scope." +end + +del recFunc +def recFunc() + record a + a.value = "recFunc" + return Record(a) +end +print "Let's try again, making a copy for the return value." +print recFunc() +del recFunc + +sections.subsection('Passing arguments.') +a = 'At process scope.' +def func3(a, b, c) + print 'The arguments were:', a, b, c + return b +end +print 'returned:', func3(1, 2, 3) +print a + +sections.subsection('Passing record as argument.') +myrec.passed = 'Original' +print 'myrec.passed =', myrec.passed +def recArg(r) + r.passed = 'Changed' +end +recArg(myrec) +print 'myrec.passed =', myrec.passed + +sections.subsection('Default values to function arguments.') +def func4(a, b='default', c=100) + print 'Given:', a, b, c +end +func4(1) +func4(1, 2) +func4([1,2], c='world', b='hello') +print 'func4 =', func4 + +sections.subsection('Defining function in a record.') +def myrec.func5(a, b) + return a + b +end +print myrec.func5("The record is\n", Text(myrec)) + +sections.subsection('Defining a function within a function.') +def func6() + print 'Inside func6.' + print 'func2() =', func2() + def func2(): return 'Shadows the global level.' + print 'func2() =', func2() +end +func6() +print 'func2() =', func2() + +sections.subsection("Accessing function's locals within a subfunction.") +def func7() + a = 100 + print 'Inside func7: a =', a + def func() + print 'Inside func: a =', a + end + func() +end +func7() + +sections.subsection('Reference to function.') +reference = func2 +print 'func2() =', func2() +print 'reference() =', reference() +print 'reference =', reference + +sections.subsection('Callback function as argument.') +def doCallback(a, b, cb) + print cb(a, b) +end +doCallback(10, 15, myrec.func5) + +sections.subsection('Returning a local function from a function.') +a = 'Process scope.' +def testfun() + a = 'testfun() scope.' + def returningFunc() + print 'I come from another place.', a + end + returningFunc() # 'a' found in local namespace + return returningFunc +end +testfun()() # 'a' found in global namespace! (testfun()'s local scope does not exist here) +ar = [testfun] +ar[0]()() + +# --------------------------------------------------------------------------- +sections.begin('SCOPES') + +sections.subsection('Global assignment with :=.') +a = 1 +print 'a =', a +def normalAssign() + a = 2 + print 'in normalAssign(), a =', a +end +normalAssign() +print 'a =', a +def globalAssign() + a := 2 + print 'in globalAssign(), a =', a +end +globalAssign() +print 'a =', a + +sections.subsection('Exporting variable from a function.') +def exporting() + abc = 'Value from exporting()' + export abc +end +abc = 'Value in global namespace' +print 'Before: abc =', abc +exporting() +print 'After: abc =', abc + +sections.subsection('Exporting a record.') +def exporting2() + record bunny + bunny.ear = 'value' + export bunny +end +exporting2() +print 'bunny =', bunny + +sections.subsection('Exporting while assigning.') +del abc +def exporting3() + export abc = 'Value from exporting3()' +end +exporting3() +print 'abc =', abc + +sections.subsection('Built-in function locals() returns the local namespace as a record.') +print 'At global level:' +print locals() +print +print 'Within a function:' +def func8() + justMe = "Function's local namespace." + print locals() +end +func8() + +sections.subsection('Importing modules: built-in module Config.') +import Config +print "Here's the Config:" +print Config + +sections.subsection('Serializing namespaces.') +sns = serialize(locals()) +print 'sns =', sns +print 'That deserializes into:' +dsns = deserialize(sns) +print dsns +print 'Calling deserialized function...' +print dsns.func3(1, 2, 3) +print 'Calling deserialized function that throws an exception...' +try: dsns.erroneous(); catch: print 'Caught.' +del dsns + +sections.subsection('Serializing record references.') +def recordRefTest() + record hello + hello.entry = 'World' + + record hello.subrec + hello.subrec.another = 123 + + hello.recref = hello.subrec + + print 'Original record:' + print hello + + hello.subrec.another = 456 + print 'Modified:' + print hello + + print 'After serialization:' + print deserialize(serialize(hello)) +end +recordRefTest() + +sections.subsection('Importing modules: import record.') +print 'Getting rid of the imported sections module (which is just a reference).' +print "Note that this has no effect on sections's own namespace." +del sections +print 'import record sections' +import record sections +print 'The sections namespace has become a local record.' +print locals() + +# --------------------------------------------------------------------------- +sections.begin('SCRIPT RETURN VALUE') + +sections.subsection('Returning value from the script: the final expression.') +"I am the return value." diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/main.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/main.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/main.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/main.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -33,7 +33,7 @@ TextApp app(argc, argv); app.initSubsystems(App::DisablePlugins); - Script testScript(app.fileSystem().find("kitchen_sink.de")); + Script testScript(app.fileSystem().find("kitchen_sink.ds")); #if 0 Script testScript("def returnValue(a): return a\n" "returnValue(True) and returnValue(True)\n"); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/sections.de doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/sections.de --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/sections.de 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/sections.de 1970-01-01 00:00:00.000000000 +0000 @@ -1,39 +0,0 @@ -# The Doomsday Engine Project -# -# Copyright (c) 2009-2017 Jaakko Keränen -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, see . - -# Module for printing and numbering sections. - -secNum = 0 -subSecNum = 0 - -def printSection(msg): print "\n" + "=" * 78 + "\nSECTION %i: %s" % [secNum, msg] - -def printSubsection(msg): print "\n" + "_" * 78 + "\n%i.%i: %s\n" % [secNum, subSecNum, msg] - -def begin(msg) - secNum += 1 - subSecNum := 0 - printSection(msg) -end - -def subsection(msg) - subSecNum += 1 - printSubsection(msg) -end - -def throwError() - throw 'Thrown from the sections module.' -end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/sections.ds doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/sections.ds --- doomsday-stable-2.0.3.2464+xenial/doomsday/tests/test_script/sections.ds 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tests/test_script/sections.ds 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,39 @@ +# The Doomsday Engine Project +# +# Copyright (c) 2009-2017 Jaakko Keränen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +# Module for printing and numbering sections. + +secNum = 0 +subSecNum = 0 + +def printSection(msg): print "\n" + "=" * 78 + "\nSECTION %i: %s" % [secNum, msg] + +def printSubsection(msg): print "\n" + "_" * 78 + "\n%i.%i: %s\n" % [secNum, subSecNum, msg] + +def begin(msg) + secNum += 1 + subSecNum := 0 + printSection(msg) +end + +def subsection(msg) + subSecNum += 1 + printSubsection(msg) +end + +def throwError() + throw 'Thrown from the sections module.' +end diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/amethyst/lib/amestd.ame doomsday-stable-2.1.0.2900+xenial/doomsday/tools/amethyst/lib/amestd.ame --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/amethyst/lib/amestd.ame 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/amethyst/lib/amestd.ame 2018-12-11 07:08:24.000000000 +0000 @@ -1,8 +1,8 @@ -$* +$* Amethyst Standard Library ------------------------- - The following output languages are defined by the library: + The following output languages are defined by the library: - TXT: plain text - HTML: HTML/CSS formatted text - RTF: rich text format @@ -13,8 +13,8 @@ Note: For everything to work properly, @begin must be called at the beginning of the document. - - TITLE (title of the document) must be defined prior to + + TITLE (title of the document) must be defined prior to @require{amestd}. *$ @@ -43,7 +43,7 @@ @ifdef{TXT}{ __ @glue{@arg} @glue{__} } - @else{ + @else{ @strong{@arg} } } @@ -157,7 +157,7 @@ } @ifdef{WIKI}{ $ Mediawiki has its own page header. - } + } @ifdef{DOKUWIKI}{ ====== @TITLE ====== } @@ -190,9 +190,9 @@ @large{@strong{@TITLE}} @br } @ifdef{VERSION}{ - @strong{@VERSION} @tag{\@apply{@n}{.}} + @strong{@VERSION} @tag{\@apply{@n}{.}} } - @ifdef{AUTHOR}{ + @ifdef{AUTHOR}{ by @ifdef{LINK}{@link{@AUTHOR}{@LINK}}@else{@AUTHOR} @br } @ifdef{EMAIL}{ @mailto{@EMAIL} @br } @@ -201,10 +201,10 @@ } @ifdef{HELP}{ $ Doomsday Help does not use a header. - } + } } -$ Specify an author with contact information. (Manual page only.) +$ Specify an author with contact information. (Manual page only.) @macro{man_author}{ @ifdef{MAN}{ .An @dquote{@arg{1}} Aq @sp @nsp{@arg{2}} @br @@ -273,12 +273,12 @@ @macro{wikilink}{[[@glue{@arg{2}}@glue{|}@glue{@arg{1}}]]} } @else{@ifdef{HTML}{ - @macro{wikilink}{@link{@arg{1}}{@tag{http://wiki.dengine.net/w/@glue{@arg{2}}}}} + @macro{wikilink}{@link{@arg{1}}{@tag{https://manual.dengine.net/@glue{@arg{2}}}}} @macro{wikiterm}{@wikilink{@arg}{@arg}} } @else{ @macro{wikiterm}{@arg} - @macro{wikilink}{@link{@arg{1}}{http://wiki.dengine.net/w/@arg{2}}} + @macro{wikilink}{@link{@arg{1}}{https://manual.dengine.net/@arg{2}}} }}} @ifdef{TXT}{ $ Omit the hyperlinks in TXT files. diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/md2tool/md2tool.c doomsday-stable-2.1.0.2900+xenial/doomsday/tools/md2tool/md2tool.c --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/md2tool/md2tool.c 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/md2tool/md2tool.c 2018-12-11 07:08:24.000000000 +0000 @@ -276,14 +276,18 @@ // Allocates and loads in the given data. //=========================================================================== void *Load(FILE *file, int offset, int len) -{ - void *ptr = malloc(len); - fseek(file, offset, SEEK_SET); - if (!fread(ptr, len, 1, file)) +{ + if (len > 0) { - DoError(MTERR_READ_FAILED); + void *ptr = malloc(len); + fseek(file, offset, SEEK_SET); + if (fread(ptr, len, 1, file) == 0) + { + DoError(MTERR_READ_FAILED); + } + return ptr; } - return ptr; + return NULL; } //=========================================================================== diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/md2tool/md2tool.h doomsday-stable-2.1.0.2900+xenial/doomsday/tools/md2tool/md2tool.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/md2tool/md2tool.h 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/md2tool/md2tool.h 2018-12-11 07:08:24.000000000 +0000 @@ -8,7 +8,7 @@ #ifndef __MD2TOOL_H__ -#define MD2TOOL_VERSION "1.2.0" +#define MD2TOOL_VERSION "1.2.1" #define PI 3.14159265f enum { VX, VY, VZ }; diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/savegametool/src/packageformatter.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tools/savegametool/src/packageformatter.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/savegametool/src/packageformatter.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/savegametool/src/packageformatter.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -50,7 +50,7 @@ << "\n# Source version: " + String::number(oldSaveVersion); // Write metadata. - os << "\n\n" + metadata.asTextWithInfoSyntax() + "\n"; + os << "\n\n" + metadata.asInfo() + "\n"; return info; } diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/CMakeLists.txt doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/CMakeLists.txt --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/CMakeLists.txt 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/CMakeLists.txt 2018-12-11 07:08:24.000000000 +0000 @@ -30,8 +30,11 @@ deng_add_application (shell ${SOURCES} EXTRA_RESOURCES ${MAC_RES}) if (APPLE OR WIN32) - set_property (TARGET shell PROPERTY OUTPUT_NAME "Doomsday Shell") set (MACOSX_BUNDLE_BUNDLE_EXECUTABLE "Doomsday Shell") + set_target_properties (shell PROPERTIES + OUTPUT_NAME "Doomsday Shell" + MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_LIST_DIR}/res/macx/Info.plist + ) else () set_property (TARGET shell PROPERTY OUTPUT_NAME "doomsday-shell") endif () Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/res/macx/English.lproj/InfoPlist.strings and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/res/macx/English.lproj/InfoPlist.strings differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/res/macx/Info.plist doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/res/macx/Info.plist --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/res/macx/Info.plist 2017-10-01 00:40:14.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/res/macx/Info.plist 2018-12-11 07:08:24.000000000 +0000 @@ -24,5 +24,7 @@ True NSPrincipalClass NSApplication + NSRequiresAquaSystemAppearance + YES diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/src/aboutdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/src/aboutdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/src/aboutdialog.cpp 2017-10-01 00:40:14.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/src/aboutdialog.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -31,7 +31,7 @@ "The Shell is a utility for controlling and monitoring " "Doomsday servers.") .arg(SHELL_VERSION) - .arg("2013-2017 Deng Team")); + .arg("2013-2018 Deng Team")); connect(txt, SIGNAL(linkActivated(QString)), &GuiShellApp::app(), SLOT(openWebAddress(QString))); diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/src/linkwindow.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/src/linkwindow.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell/src/linkwindow.cpp 2017-10-01 00:40:14.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell/src/linkwindow.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -528,7 +528,7 @@ { if (d->link) { - TimeDelta elapsed = d->link->connectedAt().since(); + TimeSpan elapsed = d->link->connectedAt().since(); String time = String("%1:%2:%3") .arg(int(elapsed.asHours())) .arg(int(elapsed.asMinutes()) % 60, 2, 10, QLatin1Char('0')) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell-text/src/aboutdialog.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell-text/src/aboutdialog.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell-text/src/aboutdialog.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell-text/src/aboutdialog.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -29,7 +29,7 @@ "The Shell is a utility for controlling and monitoring " "Doomsday servers using a text-based (curses) user interface.") .arg(SHELL_VERSION) - .arg("2013-2017 Deng Team")); + .arg("2013-2018 Deng Team")); label->setExpandsToFitLines(true); label->rule() diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell-text/src/statuswidget.cpp doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell-text/src/statuswidget.cpp --- doomsday-stable-2.0.3.2464+xenial/doomsday/tools/shell-text/src/statuswidget.cpp 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/tools/shell-text/src/statuswidget.cpp 2018-12-11 07:08:24.000000000 +0000 @@ -97,7 +97,7 @@ if (!d->rules.isEmpty()) msg += " (" + d->rules + ")"; buf.drawText(Vector2i(1, 0), msg); - TimeDelta elapsed = d->link->connectedAt().since(); + TimeSpan elapsed = d->link->connectedAt().since(); String time = String("| %1:%2:%3") .arg(int(elapsed.asHours())) .arg(int(elapsed.asMinutes()) % 60, 2, 10, QLatin1Char('0')) diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Assimp/revision.h doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Assimp/revision.h --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Assimp/revision.h 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Assimp/revision.h 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,7 @@ +#ifndef ASSIMP_REVISION_H_INC +#define ASSIMP_REVISION_H_INC + +#define GitVersion 0x0 +#define GitBranch "master" + +#endif // ASSIMP_REVISION_H_INC Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x-1.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x-1.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@2x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-20~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x-1.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x-1.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-29~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x-1.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x-1.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-40~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x-1.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-60@2x-1.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x-1.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-60@3x-1.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-76@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-76~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-76~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-83.5@2x~ipad.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-Small@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-Small@3x.png differ Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-Small-40@3x.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/AppIcon-Small-40@3x.png differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/Contents.json doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/Contents.json --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/AppIcon.appiconset/Contents.json 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,110 @@ +{ + "images" : [ + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20@2x.png", + "scale" : "2x" + }, + { + "size" : "20x20", + "idiom" : "iphone", + "filename" : "AppIcon-20@3x.png", + "scale" : "3x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-29@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "iphone", + "filename" : "AppIcon-Small@3x.png", + "scale" : "3x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-40@2x-1.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "iphone", + "filename" : "AppIcon-Small-40@3x.png", + "scale" : "3x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60@2x-1.png", + "scale" : "2x" + }, + { + "size" : "60x60", + "idiom" : "iphone", + "filename" : "AppIcon-60@3x-1.png", + "scale" : "3x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20~ipad.png", + "scale" : "1x" + }, + { + "size" : "20x20", + "idiom" : "ipad", + "filename" : "AppIcon-20@2x-1.png", + "scale" : "2x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29~ipad.png", + "scale" : "1x" + }, + { + "size" : "29x29", + "idiom" : "ipad", + "filename" : "AppIcon-29@2x~ipad.png", + "scale" : "2x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40~ipad.png", + "scale" : "1x" + }, + { + "size" : "40x40", + "idiom" : "ipad", + "filename" : "AppIcon-40@2x~ipad.png", + "scale" : "2x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76~ipad.png", + "scale" : "1x" + }, + { + "size" : "76x76", + "idiom" : "ipad", + "filename" : "AppIcon-76@2x~ipad.png", + "scale" : "2x" + }, + { + "size" : "83.5x83.5", + "idiom" : "ipad", + "filename" : "AppIcon-83.5@2x~ipad.png", + "scale" : "2x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file Binary files /tmp/tmpB8Mrft/GoKu4eM1s1/doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/ColorMap.png and /tmp/tmpB8Mrft/NeaUWJdyz_/doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/ColorMap.png differ diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/Contents.json doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/Contents.json --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/ColorMap.imageset/Contents.json 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,21 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "ColorMap.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/Contents.json doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/Contents.json --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Assets.xcassets/Contents.json 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Assets.xcassets/Contents.json 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Base.lproj/LaunchScreen.storyboard doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Base.lproj/LaunchScreen.storyboard --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Base.lproj/LaunchScreen.storyboard 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Base.lproj/LaunchScreen.storyboard 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Info.plist doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Info.plist --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday/Info.plist 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday/Info.plist 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,50 @@ + + + + + CFBundleDevelopmentRegion + en + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + $DENG_VERSION + CFBundleVersion + 1 + LSApplicationCategoryType + public.app-category.action-games + LSRequiresIPhoneOS + + UILaunchStoryboardName + LaunchScreen + UIRequiredDeviceCapabilities + + armv7 + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationPortrait + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + UIInterfaceOrientationPortraitUpsideDown + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationPortrait + UIInterfaceOrientationPortraitUpsideDown + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + + diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday.xcodeproj/project.pbxproj doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday.xcodeproj/project.pbxproj --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday.xcodeproj/project.pbxproj 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday.xcodeproj/project.pbxproj 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,8825 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + 063575801EBF39FA0074E6D4 /* abstractlineeditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575681EBF39FA0074E6D4 /* abstractlineeditor.cpp */; }; + 063575811EBF39FA0074E6D4 /* abstractlink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575691EBF39FA0074E6D4 /* abstractlink.cpp */; }; + 063575821EBF39FA0074E6D4 /* action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756A1EBF39FA0074E6D4 /* action.cpp */; }; + 063575831EBF39FA0074E6D4 /* choicewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756B1EBF39FA0074E6D4 /* choicewidget.cpp */; }; + 063575841EBF39FA0074E6D4 /* commandlinewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756C1EBF39FA0074E6D4 /* commandlinewidget.cpp */; }; + 063575851EBF39FA0074E6D4 /* dialogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756D1EBF39FA0074E6D4 /* dialogwidget.cpp */; }; + 063575861EBF39FA0074E6D4 /* doomsdayinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756E1EBF39FA0074E6D4 /* doomsdayinfo.cpp */; }; + 063575871EBF39FA0074E6D4 /* editorhistory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635756F1EBF39FA0074E6D4 /* editorhistory.cpp */; }; + 063575881EBF39FA0074E6D4 /* inputdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575701EBF39FA0074E6D4 /* inputdialog.cpp */; }; + 063575891EBF39FA0074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575711EBF39FA0074E6D4 /* labelwidget.cpp */; }; + 0635758A1EBF39FA0074E6D4 /* lexicon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575721EBF39FA0074E6D4 /* lexicon.cpp */; }; + 0635758B1EBF39FA0074E6D4 /* libshell.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575731EBF39FA0074E6D4 /* libshell.cpp */; }; + 0635758C1EBF39FA0074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575741EBF39FA0074E6D4 /* lineeditwidget.cpp */; }; + 0635758D1EBF39FA0074E6D4 /* link.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575751EBF39FA0074E6D4 /* link.cpp */; }; + 0635758E1EBF39FA0074E6D4 /* localserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575761EBF39FA0074E6D4 /* localserver.cpp */; }; + 0635758F1EBF39FA0074E6D4 /* logwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575771EBF39FA0074E6D4 /* logwidget.cpp */; }; + 063575901EBF39FA0074E6D4 /* menuwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575781EBF39FA0074E6D4 /* menuwidget.cpp */; }; + 063575911EBF39FA0074E6D4 /* monospacelinewrapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575791EBF39FA0074E6D4 /* monospacelinewrapping.cpp */; }; + 063575921EBF39FA0074E6D4 /* protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757A1EBF39FA0074E6D4 /* protocol.cpp */; }; + 063575931EBF39FA0074E6D4 /* serverfinder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757B1EBF39FA0074E6D4 /* serverfinder.cpp */; }; + 063575941EBF39FA0074E6D4 /* serverinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757C1EBF39FA0074E6D4 /* serverinfo.cpp */; }; + 063575951EBF39FA0074E6D4 /* textcanvas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757D1EBF39FA0074E6D4 /* textcanvas.cpp */; }; + 063575961EBF39FA0074E6D4 /* textrootwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757E1EBF39FA0074E6D4 /* textrootwidget.cpp */; }; + 063575971EBF39FA0074E6D4 /* textwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635757F1EBF39FA0074E6D4 /* textwidget.cpp */; }; + 063575ED1EBF3B430074E6D4 /* aabox.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D31EBF3B430074E6D4 /* aabox.c */; }; + 063575EE1EBF3B430074E6D4 /* animator.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D41EBF3B430074E6D4 /* animator.c */; }; + 063575EF1EBF3B430074E6D4 /* binangle.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D51EBF3B430074E6D4 /* binangle.c */; }; + 063575F01EBF3B430074E6D4 /* findfile_unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D61EBF3B430074E6D4 /* findfile_unix.c */; }; + 063575F11EBF3B430074E6D4 /* fixedpoint.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D71EBF3B430074E6D4 /* fixedpoint.c */; }; + 063575F21EBF3B430074E6D4 /* liblegacy.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D81EBF3B430074E6D4 /* liblegacy.c */; }; + 063575F31EBF3B430074E6D4 /* mathutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575D91EBF3B430074E6D4 /* mathutil.c */; }; + 063575F41EBF3B430074E6D4 /* memory.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DA1EBF3B430074E6D4 /* memory.c */; }; + 063575F51EBF3B430074E6D4 /* memoryblockset.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DB1EBF3B430074E6D4 /* memoryblockset.c */; }; + 063575F61EBF3B430074E6D4 /* memoryzone.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DC1EBF3B430074E6D4 /* memoryzone.c */; }; + 063575F71EBF3B430074E6D4 /* nodepile.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DD1EBF3B430074E6D4 /* nodepile.c */; }; + 063575F81EBF3B430074E6D4 /* point.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DE1EBF3B430074E6D4 /* point.c */; }; + 063575F91EBF3B430074E6D4 /* reader1.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575DF1EBF3B430074E6D4 /* reader1.c */; }; + 063575FA1EBF3B430074E6D4 /* rect.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E01EBF3B430074E6D4 /* rect.c */; }; + 063575FB1EBF3B430074E6D4 /* size.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E11EBF3B430074E6D4 /* size.c */; }; + 063575FC1EBF3B430074E6D4 /* stack.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E21EBF3B430074E6D4 /* stack.c */; }; + 063575FD1EBF3B430074E6D4 /* str.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E31EBF3B430074E6D4 /* str.c */; }; + 063575FE1EBF3B430074E6D4 /* strutil.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E41EBF3B430074E6D4 /* strutil.c */; }; + 063575FF1EBF3B430074E6D4 /* texgamma.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E51EBF3B430074E6D4 /* texgamma.c */; }; + 063576001EBF3B430074E6D4 /* vector1.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E61EBF3B430074E6D4 /* vector1.c */; }; + 063576011EBF3B430074E6D4 /* writer1.c in Sources */ = {isa = PBXBuildFile; fileRef = 063575E71EBF3B430074E6D4 /* writer1.c */; }; + 063576021EBF3B430074E6D4 /* concurrency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575E81EBF3B430074E6D4 /* concurrency.cpp */; }; + 063576041EBF3B430074E6D4 /* smoother.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575EA1EBF3B430074E6D4 /* smoother.cpp */; }; + 063576051EBF3B430074E6D4 /* stringarray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575EB1EBF3B430074E6D4 /* stringarray.cpp */; }; + 063576061EBF3B430074E6D4 /* timer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063575EC1EBF3B430074E6D4 /* timer.cpp */; }; + 063576AE1EBF3CFC0074E6D4 /* sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576271EBF3C970074E6D4 /* sound.cpp */; }; + 063576AF1EBF3CFC0074E6D4 /* waveform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576281EBF3C970074E6D4 /* waveform.cpp */; }; + 063576B01EBF3CFC0074E6D4 /* waveformbank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576291EBF3C970074E6D4 /* waveformbank.cpp */; }; + 063576B11EBF3CFC0074E6D4 /* atlas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635762B1EBF3C970074E6D4 /* atlas.cpp */; }; + 063576B21EBF3CFC0074E6D4 /* atlastexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635762C1EBF3C970074E6D4 /* atlastexture.cpp */; }; + 063576B31EBF3CFC0074E6D4 /* colorbank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635762D1EBF3C970074E6D4 /* colorbank.cpp */; }; + 063576B41EBF3CFC0074E6D4 /* drawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635762E1EBF3C970074E6D4 /* drawable.cpp */; }; + 063576B51EBF3CFC0074E6D4 /* glatlasbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635762F1EBF3C970074E6D4 /* glatlasbuffer.cpp */; }; + 063576B61EBF3CFC0074E6D4 /* glbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576301EBF3C970074E6D4 /* glbuffer.cpp */; }; + 063576B71EBF3CFC0074E6D4 /* gldrawqueue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576311EBF3C970074E6D4 /* gldrawqueue.cpp */; }; + 063576B81EBF3CFC0074E6D4 /* glframebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576321EBF3C970074E6D4 /* glframebuffer.cpp */; }; + 063576BA1EBF3CFC0074E6D4 /* glinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576341EBF3C970074E6D4 /* glinfo.cpp */; }; + 063576BB1EBF3CFC0074E6D4 /* glprogram.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576351EBF3C970074E6D4 /* glprogram.cpp */; }; + 063576BC1EBF3CFC0074E6D4 /* glshader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576361EBF3C970074E6D4 /* glshader.cpp */; }; + 063576BD1EBF3CFC0074E6D4 /* glshaderbank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576371EBF3C970074E6D4 /* glshaderbank.cpp */; }; + 063576BE1EBF3CFC0074E6D4 /* glstate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576381EBF3C970074E6D4 /* glstate.cpp */; }; + 063576BF1EBF3CFC0074E6D4 /* glsubbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576391EBF3C970074E6D4 /* glsubbuffer.cpp */; }; + 063576C01EBF3CFC0074E6D4 /* gltexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763A1EBF3C970074E6D4 /* gltexture.cpp */; }; + 063576C11EBF3CFC0074E6D4 /* gltextureframebuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763B1EBF3C970074E6D4 /* gltextureframebuffer.cpp */; }; + 063576C21EBF3CFC0074E6D4 /* gluniform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763C1EBF3C970074E6D4 /* gluniform.cpp */; }; + 063576C31EBF3CFC0074E6D4 /* heightmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763D1EBF3C970074E6D4 /* heightmap.cpp */; }; + 063576C41EBF3CFC0074E6D4 /* image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763E1EBF3C970074E6D4 /* image.cpp */; }; + 063576C51EBF3CFC0074E6D4 /* imagebank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635763F1EBF3C970074E6D4 /* imagebank.cpp */; }; + 063576C61EBF3CFC0074E6D4 /* imagefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576401EBF3C970074E6D4 /* imagefile.cpp */; }; + 063576C71EBF3CFC0074E6D4 /* kdtreeatlasallocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576411EBF3C970074E6D4 /* kdtreeatlasallocator.cpp */; }; + 063576C81EBF3CFC0074E6D4 /* modelbank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576421EBF3C970074E6D4 /* modelbank.cpp */; }; + 063576C91EBF3CFC0074E6D4 /* modeldrawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576431EBF3C970074E6D4 /* modeldrawable.cpp */; }; + 063576CA1EBF3CFC0074E6D4 /* multiatlas.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576441EBF3C970074E6D4 /* multiatlas.cpp */; }; + 063576CB1EBF3CFC0074E6D4 /* rowatlasallocator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576451EBF3C970074E6D4 /* rowatlasallocator.cpp */; }; + 063576CC1EBF3CFC0074E6D4 /* texturebank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576461EBF3C970074E6D4 /* texturebank.cpp */; }; + 063576CD1EBF3CFC0074E6D4 /* keyevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576491EBF3C970074E6D4 /* keyevent.cpp */; }; + 063576CE1EBF3CFC0074E6D4 /* keyeventsource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635764A1EBF3C970074E6D4 /* keyeventsource.cpp */; }; + 063576CF1EBF3CFC0074E6D4 /* mouseevent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635764B1EBF3C970074E6D4 /* mouseevent.cpp */; }; + 063576D01EBF3CFC0074E6D4 /* mouseeventsource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635764C1EBF3C970074E6D4 /* mouseeventsource.cpp */; }; + 063576D11EBF3CFC0074E6D4 /* coretextnativefont_macx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635764E1EBF3C970074E6D4 /* coretextnativefont_macx.cpp */; }; + 063576D31EBF3CFC0074E6D4 /* font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576501EBF3C970074E6D4 /* font.cpp */; }; + 063576D41EBF3CFC0074E6D4 /* font_richformat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576511EBF3C970074E6D4 /* font_richformat.cpp */; }; + 063576D51EBF3CFC0074E6D4 /* fontbank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576521EBF3C970074E6D4 /* fontbank.cpp */; }; + 063576D61EBF3CFC0074E6D4 /* nativefont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576531EBF3C970074E6D4 /* nativefont.cpp */; }; + 063576D91EBF3CFC0074E6D4 /* displaymode_dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576561EBF3C970074E6D4 /* displaymode_dummy.cpp */; }; + 063576DA1EBF3CFC0074E6D4 /* displaymode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576571EBF3C970074E6D4 /* displaymode.cpp */; }; + 063576DB1EBF3CFC0074E6D4 /* glwindow_qml.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576581EBF3C970074E6D4 /* glwindow_qml.cpp */; }; + 063576DC1EBF3CFC0074E6D4 /* guiapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063576591EBF3C970074E6D4 /* guiapp.cpp */; }; + 063576DD1EBF3CFC0074E6D4 /* guiloop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635765A1EBF3C970074E6D4 /* guiloop.cpp */; }; + 063576DE1EBF3CFC0074E6D4 /* persistentglwindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635765B1EBF3C970074E6D4 /* persistentglwindow.cpp */; }; + 063576DF1EBF3CFC0074E6D4 /* windoweventhandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635765C1EBF3C970074E6D4 /* windoweventhandler.cpp */; }; + 063577171EBF3E1E0074E6D4 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610871EBF04C500180814 /* OpenGLES.framework */; }; + 063577181EBF3E990074E6D4 /* libdeng_gui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 063576AD1EBF3CD20074E6D4 /* libdeng_gui.a */; }; + 063577191EBF3E990074E6D4 /* libdeng_legacy.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 063575D21EBF3AD50074E6D4 /* libdeng_legacy.a */; }; + 0635771A1EBF3E990074E6D4 /* libdeng_shell.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0635752C1EBF39880074E6D4 /* libdeng_shell.a */; }; + 063578071EBF43470074E6D4 /* directorylistdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577281EBF42C10074E6D4 /* directorylistdialog.cpp */; }; + 063578081EBF43470074E6D4 /* inputdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577291EBF42C10074E6D4 /* inputdialog.cpp */; }; + 063578091EBF43470074E6D4 /* messagedialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635772A1EBF42C10074E6D4 /* messagedialog.cpp */; }; + 0635780A1EBF43470074E6D4 /* oculusrift.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635772C1EBF42C10074E6D4 /* oculusrift.cpp */; }; + 0635780B1EBF43470074E6D4 /* vrconfig.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635772D1EBF42C10074E6D4 /* vrconfig.cpp */; }; + 0635780C1EBF43470074E6D4 /* auxbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635772F1EBF42C10074E6D4 /* auxbuttonwidget.cpp */; }; + 0635780D1EBF43470074E6D4 /* blurwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577301EBF42C10074E6D4 /* blurwidget.cpp */; }; + 0635780E1EBF43470074E6D4 /* buttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577311EBF42C10074E6D4 /* buttonwidget.cpp */; }; + 0635780F1EBF43470074E6D4 /* choicewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577321EBF42C10074E6D4 /* choicewidget.cpp */; }; + 063578101EBF43470074E6D4 /* commandwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577331EBF42C10074E6D4 /* commandwidget.cpp */; }; + 063578111EBF43470074E6D4 /* compositorwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577341EBF42C10074E6D4 /* compositorwidget.cpp */; }; + 063578121EBF43470074E6D4 /* dialogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577351EBF42C10074E6D4 /* dialogwidget.cpp */; }; + 063578131EBF43470074E6D4 /* directoryarraywidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577361EBF42C10074E6D4 /* directoryarraywidget.cpp */; }; + 063578141EBF43470074E6D4 /* documentpopupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577371EBF42C10074E6D4 /* documentpopupwidget.cpp */; }; + 063578151EBF43470074E6D4 /* documentwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577381EBF42C10074E6D4 /* documentwidget.cpp */; }; + 063578161EBF43470074E6D4 /* fadetoblackwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577391EBF42C10074E6D4 /* fadetoblackwidget.cpp */; }; + 063578171EBF43470074E6D4 /* focuswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773A1EBF42C10074E6D4 /* focuswidget.cpp */; }; + 063578181EBF43470074E6D4 /* foldpanelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773B1EBF42C10074E6D4 /* foldpanelwidget.cpp */; }; + 063578191EBF43470074E6D4 /* gridpopupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773C1EBF42C10074E6D4 /* gridpopupwidget.cpp */; }; + 0635781A1EBF43470074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773D1EBF42C10074E6D4 /* labelwidget.cpp */; }; + 0635781B1EBF43470074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773E1EBF42C10074E6D4 /* lineeditwidget.cpp */; }; + 0635781C1EBF43470074E6D4 /* logwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635773F1EBF42C10074E6D4 /* logwidget.cpp */; }; + 0635781D1EBF43470074E6D4 /* menuwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577401EBF42C10074E6D4 /* menuwidget.cpp */; }; + 0635781E1EBF43470074E6D4 /* notificationareawidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577411EBF42C10074E6D4 /* notificationareawidget.cpp */; }; + 0635781F1EBF43470074E6D4 /* panelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577421EBF42C10074E6D4 /* panelwidget.cpp */; }; + 063578201EBF43470074E6D4 /* popupbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577431EBF42C10074E6D4 /* popupbuttonwidget.cpp */; }; + 063578211EBF43470074E6D4 /* popupmenuwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577441EBF42C10074E6D4 /* popupmenuwidget.cpp */; }; + 063578221EBF43470074E6D4 /* popupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577451EBF42C10074E6D4 /* popupwidget.cpp */; }; + 063578231EBF43470074E6D4 /* progresswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577461EBF42C10074E6D4 /* progresswidget.cpp */; }; + 063578241EBF43470074E6D4 /* relaywidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577471EBF42C10074E6D4 /* relaywidget.cpp */; }; + 063578251EBF43470074E6D4 /* scriptcommandwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577481EBF42C10074E6D4 /* scriptcommandwidget.cpp */; }; + 063578261EBF43470074E6D4 /* scrollareawidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577491EBF42C10074E6D4 /* scrollareawidget.cpp */; }; + 063578271EBF43470074E6D4 /* sliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774A1EBF42C10074E6D4 /* sliderwidget.cpp */; }; + 063578281EBF43470074E6D4 /* tabwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774B1EBF42C10074E6D4 /* tabwidget.cpp */; }; + 063578291EBF43470074E6D4 /* togglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774C1EBF42C10074E6D4 /* togglewidget.cpp */; }; + 0635782A1EBF43470074E6D4 /* variablearraywidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774D1EBF42C10074E6D4 /* variablearraywidget.cpp */; }; + 0635782B1EBF43470074E6D4 /* variablechoicewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774E1EBF42C10074E6D4 /* variablechoicewidget.cpp */; }; + 0635782C1EBF43470074E6D4 /* variablelineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635774F1EBF42C10074E6D4 /* variablelineeditwidget.cpp */; }; + 0635782D1EBF43470074E6D4 /* variablesliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577501EBF42C10074E6D4 /* variablesliderwidget.cpp */; }; + 0635782E1EBF43470074E6D4 /* variabletogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577511EBF42C10074E6D4 /* variabletogglewidget.cpp */; }; + 0635782F1EBF43470074E6D4 /* baseguiapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577521EBF42C10074E6D4 /* baseguiapp.cpp */; }; + 063578301EBF43470074E6D4 /* basewindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577531EBF42C10074E6D4 /* basewindow.cpp */; }; + 063578311EBF43470074E6D4 /* callbackaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577541EBF42C10074E6D4 /* callbackaction.cpp */; }; + 063578321EBF43470074E6D4 /* childwidgetorganizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577551EBF42C10074E6D4 /* childwidgetorganizer.cpp */; }; + 063578331EBF43470074E6D4 /* data.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577561EBF42C10074E6D4 /* data.cpp */; }; + 063578341EBF43470074E6D4 /* dialogcontentstylist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577571EBF42C10074E6D4 /* dialogcontentstylist.cpp */; }; + 063578351EBF43470074E6D4 /* filtereddata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577581EBF42C10074E6D4 /* filtereddata.cpp */; }; + 063578361EBF43470074E6D4 /* fontlinewrapping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577591EBF42C10074E6D4 /* fontlinewrapping.cpp */; }; + 063578371EBF43470074E6D4 /* gltextcomposer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775A1EBF42C10074E6D4 /* gltextcomposer.cpp */; }; + 063578381EBF43470074E6D4 /* gridlayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775B1EBF42C10074E6D4 /* gridlayout.cpp */; }; + 063578391EBF43470074E6D4 /* guirootwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775C1EBF42C10074E6D4 /* guirootwidget.cpp */; }; + 0635783A1EBF43470074E6D4 /* guiwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775D1EBF42C10074E6D4 /* guiwidget.cpp */; }; + 0635783B1EBF43470074E6D4 /* imageitem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775E1EBF42C10074E6D4 /* imageitem.cpp */; }; + 0635783C1EBF43470074E6D4 /* item.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635775F1EBF42C10074E6D4 /* item.cpp */; }; + 0635783D1EBF43470074E6D4 /* listdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577601EBF42C10074E6D4 /* listdata.cpp */; }; + 0635783E1EBF43470074E6D4 /* margins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577611EBF42C10074E6D4 /* margins.cpp */; }; + 0635783F1EBF43470074E6D4 /* painter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577621EBF42C10074E6D4 /* painter.cpp */; }; + 063578401EBF43470074E6D4 /* persistentstate.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577631EBF42C10074E6D4 /* persistentstate.cpp */; }; + 063578411EBF43470074E6D4 /* proceduralimage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577641EBF42C10074E6D4 /* proceduralimage.cpp */; }; + 063578421EBF43470074E6D4 /* sequentiallayout.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577651EBF42C10074E6D4 /* sequentiallayout.cpp */; }; + 063578431EBF43470074E6D4 /* signalaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577661EBF42C10074E6D4 /* signalaction.cpp */; }; + 063578441EBF43470074E6D4 /* style.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577671EBF42C10074E6D4 /* style.cpp */; }; + 063578451EBF43470074E6D4 /* textdrawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577681EBF42C10074E6D4 /* textdrawable.cpp */; }; + 063578461EBF43470074E6D4 /* untrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063577691EBF42C10074E6D4 /* untrapper.cpp */; }; + 063578471EBF43470074E6D4 /* vrwindowtransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635776A1EBF42C10074E6D4 /* vrwindowtransform.cpp */; }; + 063578481EBF43470074E6D4 /* windowsystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635776B1EBF42C10074E6D4 /* windowsystem.cpp */; }; + 063578491EBF43470074E6D4 /* windowtransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635776C1EBF42C10074E6D4 /* windowtransform.cpp */; }; + 0635796B1EBF440D0074E6D4 /* library.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578961EBF43DE0074E6D4 /* library.cpp */; }; + 0635796C1EBF440D0074E6D4 /* alias.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578981EBF43DE0074E6D4 /* alias.cpp */; }; + 0635796D1EBF440D0074E6D4 /* cmd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578991EBF43DE0074E6D4 /* cmd.cpp */; }; + 0635796E1EBF440D0074E6D4 /* exec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635789A1EBF43DE0074E6D4 /* exec.cpp */; }; + 0635796F1EBF440D0074E6D4 /* knownword.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635789B1EBF43DE0074E6D4 /* knownword.cpp */; }; + 063579701EBF440D0074E6D4 /* var.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635789C1EBF43DE0074E6D4 /* var.cpp */; }; + 063579711EBF440D0074E6D4 /* decoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635789E1EBF43DE0074E6D4 /* decoration.cpp */; }; + 063579721EBF440D0074E6D4 /* ded.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635789F1EBF43DE0074E6D4 /* ded.cpp */; }; + 063579731EBF440D0074E6D4 /* dedfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A01EBF43DE0074E6D4 /* dedfile.cpp */; }; + 063579741EBF440D0074E6D4 /* dedparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A11EBF43DE0074E6D4 /* dedparser.cpp */; }; + 063579751EBF440D0074E6D4 /* dedregister.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A21EBF43DE0074E6D4 /* dedregister.cpp */; }; + 063579761EBF440D0074E6D4 /* definition.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A31EBF43DE0074E6D4 /* definition.cpp */; }; + 063579771EBF440D0074E6D4 /* episode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A41EBF43DE0074E6D4 /* episode.cpp */; }; + 063579781EBF440D0074E6D4 /* finale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A51EBF43DE0074E6D4 /* finale.cpp */; }; + 063579791EBF440D0074E6D4 /* mapgraphnode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A61EBF43DE0074E6D4 /* mapgraphnode.cpp */; }; + 0635797A1EBF440D0074E6D4 /* mapinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A71EBF43DE0074E6D4 /* mapinfo.cpp */; }; + 0635797B1EBF440D0074E6D4 /* material.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A81EBF43DE0074E6D4 /* material.cpp */; }; + 0635797C1EBF440D0074E6D4 /* model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578A91EBF43DE0074E6D4 /* model.cpp */; }; + 0635797D1EBF440D0074E6D4 /* music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578AA1EBF43DE0074E6D4 /* music.cpp */; }; + 0635797E1EBF440D0074E6D4 /* sky.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578AB1EBF43DE0074E6D4 /* sky.cpp */; }; + 0635797F1EBF440D0074E6D4 /* sprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578AC1EBF43DE0074E6D4 /* sprite.cpp */; }; + 063579801EBF440D0074E6D4 /* state.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578AD1EBF43DE0074E6D4 /* state.cpp */; }; + 063579811EBF440D0074E6D4 /* thing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578AE1EBF43DE0074E6D4 /* thing.cpp */; }; + 063579821EBF440D0074E6D4 /* datafile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B01EBF43DE0074E6D4 /* datafile.cpp */; }; + 063579831EBF440D0074E6D4 /* datafolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B11EBF43DE0074E6D4 /* datafolder.cpp */; }; + 063579841EBF440D0074E6D4 /* file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B21EBF43DE0074E6D4 /* file.cpp */; }; + 063579851EBF440D0074E6D4 /* filehandle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B31EBF43DE0074E6D4 /* filehandle.cpp */; }; + 063579861EBF440D0074E6D4 /* fileid.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B41EBF43DE0074E6D4 /* fileid.cpp */; }; + 063579871EBF440D0074E6D4 /* filetype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B51EBF43DE0074E6D4 /* filetype.cpp */; }; + 063579881EBF440D0074E6D4 /* fs_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B61EBF43DE0074E6D4 /* fs_main.cpp */; }; + 063579891EBF440D0074E6D4 /* fs_scheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B71EBF43DE0074E6D4 /* fs_scheme.cpp */; }; + 0635798A1EBF440D0074E6D4 /* fs_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578B81EBF43DE0074E6D4 /* fs_util.cpp */; }; + 0635798B1EBF440D0074E6D4 /* lumpcache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BA1EBF43DE0074E6D4 /* lumpcache.cpp */; }; + 0635798C1EBF440D0074E6D4 /* lumpindex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BB1EBF43DE0074E6D4 /* lumpindex.cpp */; }; + 0635798D1EBF440D0074E6D4 /* readfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BC1EBF43DE0074E6D4 /* readfile.cpp */; }; + 0635798E1EBF440D0074E6D4 /* searchpath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BD1EBF43DE0074E6D4 /* searchpath.cpp */; }; + 0635798F1EBF440D0074E6D4 /* virtualmappings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BE1EBF43DE0074E6D4 /* virtualmappings.cpp */; }; + 063579901EBF440D0074E6D4 /* wad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578BF1EBF43DE0074E6D4 /* wad.cpp */; }; + 063579911EBF440D0074E6D4 /* zip.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C01EBF43DE0074E6D4 /* zip.cpp */; }; + 063579921EBF440D0074E6D4 /* animgroup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C21EBF43DE0074E6D4 /* animgroup.cpp */; }; + 063579931EBF440D0074E6D4 /* animgroups.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C31EBF43DE0074E6D4 /* animgroups.cpp */; }; + 063579941EBF440D0074E6D4 /* bundlelinkfeed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C41EBF43DE0074E6D4 /* bundlelinkfeed.cpp */; }; + 063579951EBF440D0074E6D4 /* bundles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C51EBF43DE0074E6D4 /* bundles.cpp */; }; + 063579961EBF440D0074E6D4 /* colorpalette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C61EBF43DE0074E6D4 /* colorpalette.cpp */; }; + 063579971EBF440D0074E6D4 /* colorpalettes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C71EBF43DE0074E6D4 /* colorpalettes.cpp */; }; + 063579981EBF440D0074E6D4 /* composite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C81EBF43DE0074E6D4 /* composite.cpp */; }; + 063579991EBF440D0074E6D4 /* databundle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578C91EBF43DE0074E6D4 /* databundle.cpp */; }; + 0635799A1EBF440D0074E6D4 /* doomsdaypackage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CA1EBF43DE0074E6D4 /* doomsdaypackage.cpp */; }; + 0635799B1EBF440D0074E6D4 /* lumpcatalog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CB1EBF43DE0074E6D4 /* lumpcatalog.cpp */; }; + 0635799C1EBF440D0074E6D4 /* lumpdirectory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CC1EBF43DE0074E6D4 /* lumpdirectory.cpp */; }; + 0635799D1EBF440D0074E6D4 /* m_decomp64.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CD1EBF43DE0074E6D4 /* m_decomp64.cpp */; }; + 0635799E1EBF440D0074E6D4 /* manifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CE1EBF43DE0074E6D4 /* manifest.cpp */; }; + 0635799F1EBF440D0074E6D4 /* mapmanifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578CF1EBF43DE0074E6D4 /* mapmanifest.cpp */; }; + 063579A01EBF440D0074E6D4 /* mapmanifests.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D01EBF43DE0074E6D4 /* mapmanifests.cpp */; }; + 063579A11EBF440D0074E6D4 /* patch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D11EBF43DE0074E6D4 /* patch.cpp */; }; + 063579A21EBF440D0074E6D4 /* patchname.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D21EBF43DE0074E6D4 /* patchname.cpp */; }; + 063579A31EBF440D0074E6D4 /* pcx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D31EBF43DE0074E6D4 /* pcx.cpp */; }; + 063579A41EBF440D0074E6D4 /* resourceclass.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D41EBF43DE0074E6D4 /* resourceclass.cpp */; }; + 063579A51EBF440D0074E6D4 /* resources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D51EBF43DE0074E6D4 /* resources.cpp */; }; + 063579A61EBF440D0074E6D4 /* sprites.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D61EBF43DE0074E6D4 /* sprites.cpp */; }; + 063579A71EBF440D0074E6D4 /* texture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D71EBF43DE0074E6D4 /* texture.cpp */; }; + 063579A81EBF440D0074E6D4 /* texturemanifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D81EBF43DE0074E6D4 /* texturemanifest.cpp */; }; + 063579A91EBF440D0074E6D4 /* textures.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578D91EBF43DE0074E6D4 /* textures.cpp */; }; + 063579AA1EBF440D0074E6D4 /* texturescheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578DA1EBF43DE0074E6D4 /* texturescheme.cpp */; }; + 063579AB1EBF440D0074E6D4 /* tga.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578DB1EBF43DE0074E6D4 /* tga.cpp */; }; + 063579AC1EBF440D0074E6D4 /* wav.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578DC1EBF43DE0074E6D4 /* wav.cpp */; }; + 063579AD1EBF440D0074E6D4 /* actions.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578DE1EBF43DE0074E6D4 /* actions.cpp */; }; + 063579AE1EBF440D0074E6D4 /* bspnode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578DF1EBF43DE0074E6D4 /* bspnode.cpp */; }; + 063579AF1EBF440D0074E6D4 /* detailtexturemateriallayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E01EBF43DE0074E6D4 /* detailtexturemateriallayer.cpp */; }; + 063579B01EBF440D0074E6D4 /* dmuargs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E11EBF43DE0074E6D4 /* dmuargs.cpp */; }; + 063579B11EBF440D0074E6D4 /* entitydatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E21EBF43DE0074E6D4 /* entitydatabase.cpp */; }; + 063579B21EBF440D0074E6D4 /* entitydef.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E31EBF43DE0074E6D4 /* entitydef.cpp */; }; + 063579B31EBF440D0074E6D4 /* map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E41EBF43DE0074E6D4 /* map.cpp */; }; + 063579B41EBF440D0074E6D4 /* mapelement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E51EBF43DE0074E6D4 /* mapelement.cpp */; }; + 063579B51EBF440D0074E6D4 /* material.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E61EBF43DE0074E6D4 /* material.cpp */; }; + 063579B61EBF440D0074E6D4 /* materialarchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E71EBF43DE0074E6D4 /* materialarchive.cpp */; }; + 063579B71EBF440D0074E6D4 /* materialmanifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E81EBF43DE0074E6D4 /* materialmanifest.cpp */; }; + 063579B81EBF440D0074E6D4 /* materials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578E91EBF43DE0074E6D4 /* materials.cpp */; }; + 063579B91EBF440D0074E6D4 /* materialscheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578EA1EBF43DE0074E6D4 /* materialscheme.cpp */; }; + 063579BA1EBF440D0074E6D4 /* mobjthinkerdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578EB1EBF43DE0074E6D4 /* mobjthinkerdata.cpp */; }; + 063579BB1EBF440D0074E6D4 /* propertyvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578EC1EBF43DE0074E6D4 /* propertyvalue.cpp */; }; + 063579BC1EBF440D0074E6D4 /* shinetexturemateriallayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578ED1EBF43DE0074E6D4 /* shinetexturemateriallayer.cpp */; }; + 063579BD1EBF440D0074E6D4 /* texturemateriallayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578EE1EBF43DE0074E6D4 /* texturemateriallayer.cpp */; }; + 063579BE1EBF440D0074E6D4 /* thinker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578EF1EBF43DE0074E6D4 /* thinker.cpp */; }; + 063579BF1EBF440D0074E6D4 /* thinkerdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F01EBF43DE0074E6D4 /* thinkerdata.cpp */; }; + 063579C01EBF440D0074E6D4 /* world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F11EBF43DE0074E6D4 /* world.cpp */; }; + 063579C11EBF440D0074E6D4 /* xg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F21EBF43DE0074E6D4 /* xg.cpp */; }; + 063579C21EBF440D0074E6D4 /* abstractsession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F31EBF43DE0074E6D4 /* abstractsession.cpp */; }; + 063579C31EBF440D0074E6D4 /* busymode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F41EBF43DE0074E6D4 /* busymode.cpp */; }; + 063579C41EBF440D0074E6D4 /* doomsdayapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F51EBF43DE0074E6D4 /* doomsdayapp.cpp */; }; + 063579C51EBF440D0074E6D4 /* dualstring.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F61EBF43DE0074E6D4 /* dualstring.cpp */; }; + 063579C61EBF440D0074E6D4 /* game_init.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F71EBF43DE0074E6D4 /* game_init.cpp */; }; + 063579C71EBF440D0074E6D4 /* game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F81EBF43DE0074E6D4 /* game.cpp */; }; + 063579C81EBF440D0074E6D4 /* gameprofiles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578F91EBF43DE0074E6D4 /* gameprofiles.cpp */; }; + 063579C91EBF440D0074E6D4 /* games.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FA1EBF43DE0074E6D4 /* games.cpp */; }; + 063579CA1EBF440D0074E6D4 /* gamestatefolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FB1EBF43DE0074E6D4 /* gamestatefolder.cpp */; }; + 063579CB1EBF440D0074E6D4 /* help.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FC1EBF43DE0074E6D4 /* help.cpp */; }; + 063579CC1EBF440D0074E6D4 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FD1EBF43DE0074E6D4 /* player.cpp */; }; + 063579CD1EBF440D0074E6D4 /* players.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FE1EBF43DE0074E6D4 /* players.cpp */; }; + 063579CE1EBF440D0074E6D4 /* plugins.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063578FF1EBF43DE0074E6D4 /* plugins.cpp */; }; + 063579CF1EBF440D0074E6D4 /* savegames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063579001EBF43DE0074E6D4 /* savegames.cpp */; }; + 063579D01EBF440D0074E6D4 /* uri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063579011EBF43DE0074E6D4 /* uri.cpp */; }; + 063579D11EBF440D0074E6D4 /* urivalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063579021EBF43DE0074E6D4 /* urivalue.cpp */; }; + 063579D21EBF5E2E0074E6D4 /* c_wrapper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD92A1EBF151100B808B2 /* c_wrapper.cpp */; }; + 063579D31EBF5E2E0074E6D4 /* charsymbols.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD92B1EBF151100B808B2 /* charsymbols.cpp */; }; + 063579D41EBF5E2E0074E6D4 /* guard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD92D1EBF151100B808B2 /* guard.cpp */; }; + 063579D51EBF5E2E0074E6D4 /* lockable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD92E1EBF151100B808B2 /* lockable.cpp */; }; + 063579D61EBF5E2E0074E6D4 /* readwritelockable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD92F1EBF151100B808B2 /* readwritelockable.cpp */; }; + 063579D71EBF5E2E0074E6D4 /* task.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9301EBF151100B808B2 /* task.cpp */; }; + 063579D81EBF5E2E0074E6D4 /* taskpool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9311EBF151100B808B2 /* taskpool.cpp */; }; + 063579D91EBF5E2E0074E6D4 /* waitable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9321EBF151100B808B2 /* waitable.cpp */; }; + 063579DA1EBF5E2E0074E6D4 /* app.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9341EBF151100B808B2 /* app.cpp */; }; + 063579DB1EBF5E2E0074E6D4 /* asset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9351EBF151100B808B2 /* asset.cpp */; }; + 063579DC1EBF5E2E0074E6D4 /* callbacktimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9361EBF151100B808B2 /* callbacktimer.cpp */; }; + 063579DE1EBF5E2E0074E6D4 /* clock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9381EBF151100B808B2 /* clock.cpp */; }; + 063579DF1EBF5E2E0074E6D4 /* commandline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9391EBF151100B808B2 /* commandline.cpp */; }; + 063579E01EBF5E2E0074E6D4 /* config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93A1EBF151100B808B2 /* config.cpp */; }; + 063579E11EBF5E2E0074E6D4 /* debuglogsink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93B1EBF151100B808B2 /* debuglogsink.cpp */; }; + 063579E21EBF5E2E0074E6D4 /* filelogsink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93C1EBF151100B808B2 /* filelogsink.cpp */; }; + 063579E31EBF5E2E0074E6D4 /* garbage.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93D1EBF151100B808B2 /* garbage.cpp */; }; + 063579E41EBF5E2E0074E6D4 /* highperformancetimer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93E1EBF151100B808B2 /* highperformancetimer.cpp */; }; + 063579E51EBF5E2E0074E6D4 /* id.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD93F1EBF151100B808B2 /* id.cpp */; }; + 063579E61EBF5E2E0074E6D4 /* library.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9401EBF151100B808B2 /* library.cpp */; }; + 063579E71EBF5E2E0074E6D4 /* log.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9411EBF151100B808B2 /* log.cpp */; }; + 063579E81EBF5E2E0074E6D4 /* logbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9421EBF151100B808B2 /* logbuffer.cpp */; }; + 063579E91EBF5E2E0074E6D4 /* logfilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9431EBF151100B808B2 /* logfilter.cpp */; }; + 063579EA1EBF5E2E0074E6D4 /* logsink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9441EBF151100B808B2 /* logsink.cpp */; }; + 063579EC1EBF5E2E0074E6D4 /* loop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9461EBF151100B808B2 /* loop.cpp */; }; + 063579ED1EBF5E2E0074E6D4 /* memorylogsink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9471EBF151100B808B2 /* memorylogsink.cpp */; }; + 063579EE1EBF5E2E0074E6D4 /* monospacelogsinkformatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9481EBF151100B808B2 /* monospacelogsinkformatter.cpp */; }; + 063579EF1EBF5E2E0074E6D4 /* system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9491EBF151100B808B2 /* system.cpp */; }; + 063579F01EBF5E2E0074E6D4 /* textapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD94A1EBF151100B808B2 /* textapp.cpp */; }; + 063579F11EBF5E2E0074E6D4 /* textstreamlogsink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD94B1EBF151100B808B2 /* textstreamlogsink.cpp */; }; + 063579F21EBF5E2E0074E6D4 /* unixinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD94C1EBF151100B808B2 /* unixinfo.cpp */; }; + 063579F31EBF5E2E0074E6D4 /* animationvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD94E1EBF151100B808B2 /* animationvalue.cpp */; }; + 063579F41EBF5E2E0074E6D4 /* archive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD94F1EBF151100B808B2 /* archive.cpp */; }; + 063579F51EBF5E2E0074E6D4 /* arrayvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9501EBF151100B808B2 /* arrayvalue.cpp */; }; + 063579F61EBF5E2E0074E6D4 /* bank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9511EBF151100B808B2 /* bank.cpp */; }; + 063579F71EBF5E2E0074E6D4 /* bitfield.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9521EBF151100B808B2 /* bitfield.cpp */; }; + 063579F81EBF5E2E0074E6D4 /* bitfield_elements.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9531EBF151100B808B2 /* bitfield_elements.cpp */; }; + 063579F91EBF5E2E0074E6D4 /* block.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9541EBF151100B808B2 /* block.cpp */; }; + 063579FA1EBF5E2E0074E6D4 /* blockvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9551EBF151100B808B2 /* blockvalue.cpp */; }; + 063579FB1EBF5E2E0074E6D4 /* byteorder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9561EBF151100B808B2 /* byteorder.cpp */; }; + 063579FC1EBF5E2E0074E6D4 /* byterefarray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9571EBF151100B808B2 /* byterefarray.cpp */; }; + 063579FD1EBF5E2E0074E6D4 /* bytesubarray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9581EBF151100B808B2 /* bytesubarray.cpp */; }; + 063579FE1EBF5E2E0074E6D4 /* counted.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9591EBF151100B808B2 /* counted.cpp */; }; + 063579FF1EBF5E2E0074E6D4 /* date.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95A1EBF151100B808B2 /* date.cpp */; }; + 06357A001EBF5E2E0074E6D4 /* deletable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95B1EBF151100B808B2 /* deletable.cpp */; }; + 06357A011EBF5E2E0074E6D4 /* dictionaryvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95C1EBF151100B808B2 /* dictionaryvalue.cpp */; }; + 06357A021EBF5E2E0074E6D4 /* escapeparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95D1EBF151100B808B2 /* escapeparser.cpp */; }; + 06357A031EBF5E2E0074E6D4 /* fixedbytearray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95E1EBF151100B808B2 /* fixedbytearray.cpp */; }; + 06357A041EBF5E2E0074E6D4 /* huffman.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD95F1EBF151100B808B2 /* huffman.cpp */; }; + 06357A051EBF5E2E0074E6D4 /* info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9601EBF151100B808B2 /* info.cpp */; }; + 06357A061EBF5E2E0074E6D4 /* infobank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9611EBF151100B808B2 /* infobank.cpp */; }; + 06357A071EBF5E2E0074E6D4 /* json.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9621EBF151100B808B2 /* json.cpp */; }; + 06357A081EBF5E2E0074E6D4 /* nativepointervalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9631EBF151100B808B2 /* nativepointervalue.cpp */; }; + 06357A091EBF5E2E0074E6D4 /* nonevalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9641EBF151100B808B2 /* nonevalue.cpp */; }; + 06357A0A1EBF5E2E0074E6D4 /* numbervalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9651EBF151100B808B2 /* numbervalue.cpp */; }; + 06357A0B1EBF5E2E0074E6D4 /* observers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9661EBF151100B808B2 /* observers.cpp */; }; + 06357A0C1EBF5E2E0074E6D4 /* path.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9671EBF151100B808B2 /* path.cpp */; }; + 06357A0D1EBF5E2E0074E6D4 /* pathtree.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9681EBF151100B808B2 /* pathtree.cpp */; }; + 06357A0E1EBF5E2E0074E6D4 /* pathtreenode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9691EBF151100B808B2 /* pathtreenode.cpp */; }; + 06357A0F1EBF5E2E0074E6D4 /* pointerset.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96A1EBF151100B808B2 /* pointerset.cpp */; }; + 06357A101EBF5E2E0074E6D4 /* profiles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96B1EBF151100B808B2 /* profiles.cpp */; }; + 06357A111EBF5E2E0074E6D4 /* reader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96C1EBF151100B808B2 /* reader.cpp */; }; + 06357A121EBF5E2E0074E6D4 /* record.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96D1EBF151100B808B2 /* record.cpp */; }; + 06357A131EBF5E2E0074E6D4 /* recordaccessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96E1EBF151100B808B2 /* recordaccessor.cpp */; }; + 06357A141EBF5E2E0074E6D4 /* recordvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD96F1EBF151100B808B2 /* recordvalue.cpp */; }; + 06357A151EBF5E2E0074E6D4 /* refuge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9701EBF151100B808B2 /* refuge.cpp */; }; + 06357A161EBF5E2E0074E6D4 /* refvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9711EBF151100B808B2 /* refvalue.cpp */; }; + 06357A171EBF5E2E0074E6D4 /* sourcelinetable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9721EBF151100B808B2 /* sourcelinetable.cpp */; }; + 06357A181EBF5E2E0074E6D4 /* string.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9731EBF151100B808B2 /* string.cpp */; }; + 06357A191EBF5E2E0074E6D4 /* stringpool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9741EBF151100B808B2 /* stringpool.cpp */; }; + 06357A1A1EBF5E2E0074E6D4 /* textvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9751EBF151100B808B2 /* textvalue.cpp */; }; + 06357A1B1EBF5E2E0074E6D4 /* time.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9761EBF151100B808B2 /* time.cpp */; }; + 06357A1C1EBF5E2E0074E6D4 /* timevalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9771EBF151100B808B2 /* timevalue.cpp */; }; + 06357A1D1EBF5E2E0074E6D4 /* value.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9781EBF151100B808B2 /* value.cpp */; }; + 06357A1E1EBF5E2E0074E6D4 /* variable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9791EBF151100B808B2 /* variable.cpp */; }; + 06357A1F1EBF5E2E0074E6D4 /* writer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD97A1EBF151100B808B2 /* writer.cpp */; }; + 06357A201EBF5E2E0074E6D4 /* ziparchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD97B1EBF151100B808B2 /* ziparchive.cpp */; }; + 06357A211EBF5E2E0074E6D4 /* error.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD97C1EBF151100B808B2 /* error.cpp */; }; + 06357A221EBF5E2E0074E6D4 /* archiveentryfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD97E1EBF151100B808B2 /* archiveentryfile.cpp */; }; + 06357A231EBF5E2E0074E6D4 /* archivefeed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD97F1EBF151100B808B2 /* archivefeed.cpp */; }; + 06357A241EBF5E2E0074E6D4 /* archivefolder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9801EBF151100B808B2 /* archivefolder.cpp */; }; + 06357A251EBF5E2E0074E6D4 /* assetobserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9811EBF151100B808B2 /* assetobserver.cpp */; }; + 06357A261EBF5E2E0074E6D4 /* bytearrayfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9821EBF151100B808B2 /* bytearrayfile.cpp */; }; + 06357A271EBF5E2E0074E6D4 /* directoryfeed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9831EBF151100B808B2 /* directoryfeed.cpp */; }; + 06357A281EBF5E2E0074E6D4 /* feed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9841EBF151100B808B2 /* feed.cpp */; }; + 06357A291EBF5E2E0074E6D4 /* file.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9851EBF151100B808B2 /* file.cpp */; }; + 06357A2A1EBF5E2E0074E6D4 /* fileindex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9861EBF151100B808B2 /* fileindex.cpp */; }; + 06357A2B1EBF5E2E0074E6D4 /* filesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9871EBF151100B808B2 /* filesystem.cpp */; }; + 06357A2C1EBF5E2E0074E6D4 /* folder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9881EBF151100B808B2 /* folder.cpp */; }; + 06357A2D1EBF5E2E0074E6D4 /* libraryfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9891EBF151100B808B2 /* libraryfile.cpp */; }; + 06357A2E1EBF5E2E0074E6D4 /* linkfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98A1EBF151100B808B2 /* linkfile.cpp */; }; + 06357A2F1EBF5E2E0074E6D4 /* metadatabank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98B1EBF151100B808B2 /* metadatabank.cpp */; }; + 06357A301EBF5E2E0074E6D4 /* nativefile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98C1EBF151100B808B2 /* nativefile.cpp */; }; + 06357A311EBF5E2E0074E6D4 /* nativepath.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98D1EBF151100B808B2 /* nativepath.cpp */; }; + 06357A321EBF5E2E0074E6D4 /* node.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98E1EBF151100B808B2 /* node.cpp */; }; + 06357A331EBF5E2E0074E6D4 /* package.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD98F1EBF151100B808B2 /* package.cpp */; }; + 06357A341EBF5E2E0074E6D4 /* packagefeed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9901EBF151100B808B2 /* packagefeed.cpp */; }; + 06357A351EBF5E2E0074E6D4 /* packageloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9911EBF151100B808B2 /* packageloader.cpp */; }; + 06357A361EBF5E2E0074E6D4 /* staticlibraryfeed.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9921EBF151100B808B2 /* staticlibraryfeed.cpp */; }; + 06357A371EBF5E2E0074E6D4 /* math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9931EBF151100B808B2 /* math.cpp */; }; + 06357A381EBF5E2E0074E6D4 /* matrix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9941EBF151100B808B2 /* matrix.cpp */; }; + 06357A391EBF5E2E0074E6D4 /* address.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9961EBF151100B808B2 /* address.cpp */; }; + 06357A3A1EBF5E2E0074E6D4 /* beacon.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9971EBF151100B808B2 /* beacon.cpp */; }; + 06357A3B1EBF5E2E0074E6D4 /* blockpacket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9981EBF151100B808B2 /* blockpacket.cpp */; }; + 06357A3C1EBF5E2E0074E6D4 /* identifiedpacket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9991EBF151100B808B2 /* identifiedpacket.cpp */; }; + 06357A3D1EBF5E2E0074E6D4 /* listensocket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD99A1EBF151100B808B2 /* listensocket.cpp */; }; + 06357A3E1EBF5E2E0074E6D4 /* message.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD99B1EBF151100B808B2 /* message.cpp */; }; + 06357A3F1EBF5E2E0074E6D4 /* networkinterfaces.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD99C1EBF151100B808B2 /* networkinterfaces.cpp */; }; + 06357A411EBF5E2E0074E6D4 /* packet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD99E1EBF151100B808B2 /* packet.cpp */; }; + 06357A421EBF5E2E0074E6D4 /* protocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD99F1EBF151100B808B2 /* protocol.cpp */; }; + 06357A431EBF5E2E0074E6D4 /* recordpacket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A01EBF151100B808B2 /* recordpacket.cpp */; }; + 06357A441EBF5E2E0074E6D4 /* socket.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A11EBF151100B808B2 /* socket.cpp */; }; + 06357A451EBF5E2E0074E6D4 /* transmitter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A21EBF151100B808B2 /* transmitter.cpp */; }; + 06357A461EBF5E2E0074E6D4 /* arrayexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A51EBF151100B808B2 /* arrayexpression.cpp */; }; + 06357A471EBF5E2E0074E6D4 /* assignstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A61EBF151100B808B2 /* assignstatement.cpp */; }; + 06357A481EBF5E2E0074E6D4 /* bindings_core.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A71EBF151100B808B2 /* bindings_core.cpp */; }; + 06357A4A1EBF5E2E0074E6D4 /* bindings_math.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9A91EBF151100B808B2 /* bindings_math.cpp */; }; + 06357A4C1EBF5E2E0074E6D4 /* builtinexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9AB1EBF151100B808B2 /* builtinexpression.cpp */; }; + 06357A4D1EBF5E2E0074E6D4 /* catchstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9AC1EBF151100B808B2 /* catchstatement.cpp */; }; + 06357A4E1EBF5E2E0074E6D4 /* compound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9AD1EBF151100B808B2 /* compound.cpp */; }; + 06357A4F1EBF5E2E0074E6D4 /* constantexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9AE1EBF151100B808B2 /* constantexpression.cpp */; }; + 06357A501EBF5E2E0074E6D4 /* context.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9AF1EBF151100B808B2 /* context.cpp */; }; + 06357A511EBF5E2E0074E6D4 /* deletestatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B01EBF151100B808B2 /* deletestatement.cpp */; }; + 06357A521EBF5E2E0074E6D4 /* dictionaryexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B11EBF151100B808B2 /* dictionaryexpression.cpp */; }; + 06357A531EBF5E2E0074E6D4 /* evaluator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B21EBF151100B808B2 /* evaluator.cpp */; }; + 06357A541EBF5E2E0074E6D4 /* expression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B31EBF151100B808B2 /* expression.cpp */; }; + 06357A551EBF5E2E0074E6D4 /* expressionstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B41EBF151100B808B2 /* expressionstatement.cpp */; }; + 06357A561EBF5E2E0074E6D4 /* flowstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B51EBF151100B808B2 /* flowstatement.cpp */; }; + 06357A571EBF5E2E0074E6D4 /* forstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B61EBF151100B808B2 /* forstatement.cpp */; }; + 06357A581EBF5E2E0074E6D4 /* function.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B71EBF151100B808B2 /* function.cpp */; }; + 06357A591EBF5E2E0074E6D4 /* functionstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B81EBF151100B808B2 /* functionstatement.cpp */; }; + 06357A5A1EBF5E2E0074E6D4 /* functionvalue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9B91EBF151100B808B2 /* functionvalue.cpp */; }; + 06357A5B1EBF5E2E0074E6D4 /* ifstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BA1EBF151100B808B2 /* ifstatement.cpp */; }; + 06357A5C1EBF5E2E0074E6D4 /* lex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BB1EBF151100B808B2 /* lex.cpp */; }; + 06357A5D1EBF5E2E0074E6D4 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BC1EBF151100B808B2 /* module.cpp */; }; + 06357A5E1EBF5E2E0074E6D4 /* nameexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BD1EBF151100B808B2 /* nameexpression.cpp */; }; + 06357A5F1EBF5E2E0074E6D4 /* operator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BE1EBF151100B808B2 /* operator.cpp */; }; + 06357A601EBF5E2E0074E6D4 /* operatorexpression.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9BF1EBF151100B808B2 /* operatorexpression.cpp */; }; + 06357A611EBF5E2E0074E6D4 /* parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C01EBF151100B808B2 /* parser.cpp */; }; + 06357A621EBF5E2E0074E6D4 /* printstatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C11EBF151100B808B2 /* printstatement.cpp */; }; + 06357A631EBF5E2E0074E6D4 /* process.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C21EBF151100B808B2 /* process.cpp */; }; + 06357A641EBF5E2E0074E6D4 /* scheduler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C31EBF151100B808B2 /* scheduler.cpp */; }; + 06357A651EBF5E2E0074E6D4 /* scopestatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C41EBF151100B808B2 /* scopestatement.cpp */; }; + 06357A661EBF5E2E0074E6D4 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C51EBF151100B808B2 /* script.cpp */; }; + 06357A671EBF5E2E0074E6D4 /* scriptedinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C61EBF151100B808B2 /* scriptedinfo.cpp */; }; + 06357A681EBF5E2E0074E6D4 /* scriptlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C71EBF151100B808B2 /* scriptlex.cpp */; }; + 06357A691EBF5E2E0074E6D4 /* scriptsystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C81EBF151100B808B2 /* scriptsystem.cpp */; }; + 06357A6A1EBF5E2E0074E6D4 /* statement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9C91EBF151100B808B2 /* statement.cpp */; }; + 06357A6B1EBF5E2E0074E6D4 /* tokenbuffer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9CA1EBF151100B808B2 /* tokenbuffer.cpp */; }; + 06357A6C1EBF5E2E0074E6D4 /* tokenrange.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9CB1EBF151100B808B2 /* tokenrange.cpp */; }; + 06357A6D1EBF5E2E0074E6D4 /* trystatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9CC1EBF151100B808B2 /* trystatement.cpp */; }; + 06357A6E1EBF5E2E0074E6D4 /* whilestatement.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9CD1EBF151100B808B2 /* whilestatement.cpp */; }; + 06357A6F1EBF5E2E0074E6D4 /* version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9CE1EBF151100B808B2 /* version.cpp */; }; + 06357A701EBF5E2E0074E6D4 /* action.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D01EBF151100B808B2 /* action.cpp */; }; + 06357A711EBF5E2E0074E6D4 /* animation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D11EBF151100B808B2 /* animation.cpp */; }; + 06357A721EBF5E2E0074E6D4 /* animationrule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D21EBF151100B808B2 /* animationrule.cpp */; }; + 06357A731EBF5E2E0074E6D4 /* constantrule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D31EBF151100B808B2 /* constantrule.cpp */; }; + 06357A741EBF5E2E0074E6D4 /* indirectrule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D41EBF151100B808B2 /* indirectrule.cpp */; }; + 06357A751EBF5E2E0074E6D4 /* operatorrule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D51EBF151100B808B2 /* operatorrule.cpp */; }; + 06357A761EBF5E2E0074E6D4 /* rootwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D61EBF151100B808B2 /* rootwidget.cpp */; }; + 06357A771EBF5E2E0074E6D4 /* rule.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D71EBF151100B808B2 /* rule.cpp */; }; + 06357A781EBF5E2E0074E6D4 /* rulebank.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D81EBF151100B808B2 /* rulebank.cpp */; }; + 06357A791EBF5E2E0074E6D4 /* rulerectangle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9D91EBF151100B808B2 /* rulerectangle.cpp */; }; + 06357A7A1EBF5E2E0074E6D4 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9DA1EBF151100B808B2 /* widget.cpp */; }; + 06357A801EBF5F250074E6D4 /* lzss.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357A7F1EBF5F250074E6D4 /* lzss.c */; }; + 06357AF61EBF62860074E6D4 /* libgamefw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357AF21EBF62180074E6D4 /* libgamefw.cpp */; }; + 06357AF71EBF62890074E6D4 /* mapspot.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357AF31EBF62180074E6D4 /* mapspot.cpp */; }; + 06357B091EBF64DE0074E6D4 /* dehreader_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B051EBF64DE0074E6D4 /* dehreader_util.cpp */; }; + 06357B0A1EBF64DE0074E6D4 /* dehreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B061EBF64DE0074E6D4 /* dehreader.cpp */; }; + 06357B0B1EBF64DE0074E6D4 /* importdeh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B071EBF64DE0074E6D4 /* importdeh.cpp */; }; + 06357B0C1EBF64DE0074E6D4 /* info.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B081EBF64DE0074E6D4 /* info.cpp */; }; + 06357B2F1EBF6A660074E6D4 /* importudmf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B2C1EBF6A660074E6D4 /* importudmf.cpp */; }; + 06357B301EBF6A660074E6D4 /* udmflex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B2D1EBF6A660074E6D4 /* udmflex.cpp */; }; + 06357B311EBF6A660074E6D4 /* udmfparser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B2E1EBF6A660074E6D4 /* udmfparser.cpp */; }; + 06357B5B1EBF6F5A0074E6D4 /* ammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B3F1EBF6F5A0074E6D4 /* ammowidget.cpp */; }; + 06357B5C1EBF6F5A0074E6D4 /* armoriconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B401EBF6F5A0074E6D4 /* armoriconwidget.cpp */; }; + 06357B5D1EBF6F5A0074E6D4 /* facewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B411EBF6F5A0074E6D4 /* facewidget.cpp */; }; + 06357B5E1EBF6F5A0074E6D4 /* healthiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B421EBF6F5A0074E6D4 /* healthiconwidget.cpp */; }; + 06357B5F1EBF6F5A0074E6D4 /* maxammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B431EBF6F5A0074E6D4 /* maxammowidget.cpp */; }; + 06357B601EBF6F5A0074E6D4 /* weaponslotwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B441EBF6F5A0074E6D4 /* weaponslotwidget.cpp */; }; + 06357B611EBF6F5A0074E6D4 /* acfnlink.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B451EBF6F5A0074E6D4 /* acfnlink.c */; }; + 06357B621EBF6F5A0074E6D4 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B461EBF6F5A0074E6D4 /* m_random.c */; }; + 06357B631EBF6F5A0074E6D4 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B471EBF6F5A0074E6D4 /* p_enemy.c */; }; + 06357B641EBF6F5A0074E6D4 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B481EBF6F5A0074E6D4 /* p_inter.c */; }; + 06357B651EBF6F5A0074E6D4 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B491EBF6F5A0074E6D4 /* p_maputl.c */; }; + 06357B661EBF6F5A0074E6D4 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4A1EBF6F5A0074E6D4 /* p_mobj.c */; }; + 06357B671EBF6F5A0074E6D4 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4B1EBF6F5A0074E6D4 /* p_pspr.c */; }; + 06357B681EBF6F5A0074E6D4 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4C1EBF6F5A0074E6D4 /* p_setup.c */; }; + 06357B691EBF6F5A0074E6D4 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4D1EBF6F5A0074E6D4 /* p_telept.c */; }; + 06357B6A1EBF6F5A0074E6D4 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4E1EBF6F5A0074E6D4 /* tables.c */; }; + 06357B6B1EBF6F5A0074E6D4 /* bossbrain.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B4F1EBF6F5A0074E6D4 /* bossbrain.cpp */; }; + 06357B6C1EBF6F5A0074E6D4 /* d_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B501EBF6F5A0074E6D4 /* d_api.cpp */; }; + 06357B6D1EBF6F5A0074E6D4 /* d_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B511EBF6F5A0074E6D4 /* d_console.cpp */; }; + 06357B6E1EBF6F5A0074E6D4 /* d_items.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B521EBF6F5A0074E6D4 /* d_items.cpp */; }; + 06357B6F1EBF6F5A0074E6D4 /* d_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B531EBF6F5A0074E6D4 /* d_main.cpp */; }; + 06357B701EBF6F5A0074E6D4 /* d_refresh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B541EBF6F5A0074E6D4 /* d_refresh.cpp */; }; + 06357B711EBF6F5A0074E6D4 /* doomv9mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B551EBF6F5A0074E6D4 /* doomv9mapstatereader.cpp */; }; + 06357B721EBF6F5A0074E6D4 /* intermission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B561EBF6F5A0074E6D4 /* intermission.cpp */; }; + 06357B731EBF6F5A0074E6D4 /* m_cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B571EBF6F5A0074E6D4 /* m_cheat.cpp */; }; + 06357B741EBF6F5A0074E6D4 /* p_lights.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B581EBF6F5A0074E6D4 /* p_lights.cpp */; }; + 06357B751EBF6F5A0074E6D4 /* p_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B591EBF6F5A0074E6D4 /* p_spec.cpp */; }; + 06357B761EBF6F5A0074E6D4 /* st_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B5A1EBF6F5A0074E6D4 /* st_stuff.cpp */; }; + 06357BE21EBF6F760074E6D4 /* interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B781EBF6F750074E6D4 /* interpreter.cpp */; }; + 06357BE31EBF6F760074E6D4 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B791EBF6F750074E6D4 /* module.cpp */; }; + 06357BE41EBF6F760074E6D4 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7A1EBF6F750074E6D4 /* script.cpp */; }; + 06357BE51EBF6F760074E6D4 /* system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7B1EBF6F750074E6D4 /* system.cpp */; }; + 06357BE61EBF6F760074E6D4 /* g_defs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */; }; + 06357BE71EBF6F760074E6D4 /* g_eventsequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */; }; + 06357BE81EBF6F760074E6D4 /* g_game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7F1EBF6F750074E6D4 /* g_game.cpp */; }; + 06357BE91EBF6F760074E6D4 /* g_update.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B801EBF6F750074E6D4 /* g_update.cpp */; }; + 06357BEA1EBF6F760074E6D4 /* gamerules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B811EBF6F750074E6D4 /* gamerules.cpp */; }; + 06357BEB1EBF6F760074E6D4 /* gamesession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B821EBF6F750074E6D4 /* gamesession.cpp */; }; + 06357BEC1EBF6F760074E6D4 /* saveslots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B831EBF6F750074E6D4 /* saveslots.cpp */; }; + 06357BED1EBF6F760074E6D4 /* automapstyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B851EBF6F750074E6D4 /* automapstyle.cpp */; }; + 06357BEE1EBF6F760074E6D4 /* hudwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B861EBF6F750074E6D4 /* hudwidget.cpp */; }; + 06357BEF1EBF6F760074E6D4 /* armorwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B881EBF6F750074E6D4 /* armorwidget.cpp */; }; + 06357BF01EBF6F760074E6D4 /* automapwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B891EBF6F750074E6D4 /* automapwidget.cpp */; }; + 06357BF11EBF6F760074E6D4 /* chainwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */; }; + 06357BF21EBF6F760074E6D4 /* chatwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */; }; + 06357BF31EBF6F760074E6D4 /* flightwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */; }; + 06357BF41EBF6F760074E6D4 /* fragswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */; }; + 06357BF51EBF6F760074E6D4 /* groupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */; }; + 06357BF61EBF6F760074E6D4 /* healthwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */; }; + 06357BF71EBF6F760074E6D4 /* itemswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B901EBF6F750074E6D4 /* itemswidget.cpp */; }; + 06357BF81EBF6F760074E6D4 /* keyslotwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */; }; + 06357BF91EBF6F760074E6D4 /* keyswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B921EBF6F750074E6D4 /* keyswidget.cpp */; }; + 06357BFA1EBF6F760074E6D4 /* killswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B931EBF6F750074E6D4 /* killswidget.cpp */; }; + 06357BFB1EBF6F760074E6D4 /* playerlogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */; }; + 06357BFC1EBF6F760074E6D4 /* readyammoiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */; }; + 06357BFD1EBF6F760074E6D4 /* readyammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */; }; + 06357BFE1EBF6F760074E6D4 /* readyitemwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */; }; + 06357BFF1EBF6F760074E6D4 /* secretswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B981EBF6F750074E6D4 /* secretswidget.cpp */; }; + 06357C001EBF6F760074E6D4 /* page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9A1EBF6F760074E6D4 /* page.cpp */; }; + 06357C011EBF6F760074E6D4 /* buttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */; }; + 06357C021EBF6F760074E6D4 /* coloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */; }; + 06357C031EBF6F760074E6D4 /* cvarcoloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */; }; + 06357C041EBF6F760074E6D4 /* cvarinlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */; }; + 06357C051EBF6F760074E6D4 /* cvarlineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */; }; + 06357C061EBF6F760074E6D4 /* cvarsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */; }; + 06357C071EBF6F760074E6D4 /* cvartextualsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */; }; + 06357C081EBF6F760074E6D4 /* cvartogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */; }; + 06357C091EBF6F760074E6D4 /* inlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */; }; + 06357C0A1EBF6F760074E6D4 /* inputbindingwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */; }; + 06357C0B1EBF6F760074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */; }; + 06357C0C1EBF6F760074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */; }; + 06357C0D1EBF6F760074E6D4 /* listwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA81EBF6F760074E6D4 /* listwidget.cpp */; }; + 06357C0E1EBF6F760074E6D4 /* mobjpreviewwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */; }; + 06357C0F1EBF6F760074E6D4 /* rectwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */; }; + 06357C101EBF6F760074E6D4 /* sliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */; }; + 06357C111EBF6F760074E6D4 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAC1EBF6F760074E6D4 /* widget.cpp */; }; + 06357C121EBF6F760074E6D4 /* d_net.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAE1EBF6F760074E6D4 /* d_net.cpp */; }; + 06357C131EBF6F760074E6D4 /* d_netcl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */; }; + 06357C141EBF6F760074E6D4 /* d_netsv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */; }; + 06357C151EBF6F760074E6D4 /* dmu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */; }; + 06357C161EBF6F760074E6D4 /* mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */; }; + 06357C171EBF6F760074E6D4 /* mapstatewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */; }; + 06357C181EBF6F760074E6D4 /* mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB51EBF6F760074E6D4 /* mobj.cpp */; }; + 06357C191EBF6F760074E6D4 /* p_actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB61EBF6F760074E6D4 /* p_actor.cpp */; }; + 06357C1A1EBF6F760074E6D4 /* p_ceiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */; }; + 06357C1B1EBF6F760074E6D4 /* p_door.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB81EBF6F760074E6D4 /* p_door.cpp */; }; + 06357C1C1EBF6F760074E6D4 /* p_floor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB91EBF6F760074E6D4 /* p_floor.cpp */; }; + 06357C1D1EBF6F760074E6D4 /* p_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBA1EBF6F760074E6D4 /* p_map.cpp */; }; + 06357C1E1EBF6F760074E6D4 /* p_mapsetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */; }; + 06357C1F1EBF6F760074E6D4 /* p_mapspec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */; }; + 06357C201EBF6F760074E6D4 /* p_plat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */; }; + 06357C211EBF6F760074E6D4 /* p_scroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */; }; + 06357C221EBF6F760074E6D4 /* p_sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */; }; + 06357C231EBF6F760074E6D4 /* p_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC01EBF6F760074E6D4 /* p_start.cpp */; }; + 06357C241EBF6F760074E6D4 /* p_switch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC11EBF6F760074E6D4 /* p_switch.cpp */; }; + 06357C251EBF6F760074E6D4 /* p_tick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC21EBF6F760074E6D4 /* p_tick.cpp */; }; + 06357C261EBF6F760074E6D4 /* p_xgfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */; }; + 06357C271EBF6F760074E6D4 /* p_xgline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */; }; + 06357C281EBF6F760074E6D4 /* p_xgsave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */; }; + 06357C291EBF6F760074E6D4 /* p_xgsec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */; }; + 06357C2A1EBF6F760074E6D4 /* pause.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC71EBF6F760074E6D4 /* pause.cpp */; }; + 06357C2B1EBF6F760074E6D4 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC81EBF6F760074E6D4 /* player.cpp */; }; + 06357C2C1EBF6F760074E6D4 /* polyobjs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */; }; + 06357C2D1EBF6F760074E6D4 /* thingarchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */; }; + 06357C2E1EBF6F760074E6D4 /* thinkerinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */; }; + 06357C2F1EBF6F760074E6D4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCC1EBF6F760074E6D4 /* common.c */; }; + 06357C301EBF6F760074E6D4 /* hu_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */; }; + 06357C311EBF6F760074E6D4 /* p_iterlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */; }; + 06357C321EBF6F760074E6D4 /* p_terraintype.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */; }; + 06357C331EBF6F760074E6D4 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD01EBF6F760074E6D4 /* p_user.c */; }; + 06357C341EBF6F760074E6D4 /* p_view.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD11EBF6F760074E6D4 /* p_view.c */; }; + 06357C351EBF6F760074E6D4 /* r_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD21EBF6F760074E6D4 /* r_common.c */; }; + 06357C361EBF6F760074E6D4 /* x_hair.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD31EBF6F760074E6D4 /* x_hair.c */; }; + 06357C371EBF6F760074E6D4 /* animdefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD41EBF6F760074E6D4 /* animdefs.cpp */; }; + 06357C381EBF6F760074E6D4 /* fi_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */; }; + 06357C391EBF6F760074E6D4 /* g_controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD61EBF6F760074E6D4 /* g_controls.cpp */; }; + 06357C3A1EBF6F760074E6D4 /* gl_drawpatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */; }; + 06357C3B1EBF6F760074E6D4 /* hexlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD81EBF6F760074E6D4 /* hexlex.cpp */; }; + 06357C3C1EBF6F760074E6D4 /* hu_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */; }; + 06357C3D1EBF6F760074E6D4 /* hu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */; }; + 06357C3E1EBF6F760074E6D4 /* hu_menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */; }; + 06357C3F1EBF6F760074E6D4 /* hu_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */; }; + 06357C401EBF6F760074E6D4 /* hu_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */; }; + 06357C411EBF6F760074E6D4 /* m_ctrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */; }; + 06357C421EBF6F760074E6D4 /* p_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */; }; + 06357C431EBF6F760074E6D4 /* p_saveg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */; }; + 06357C441EBF6F760074E6D4 /* p_saveio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */; }; + 06357CD01EBF70D80074E6D4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCC1EBF6F760074E6D4 /* common.c */; }; + 06357CD11EBF70D80074E6D4 /* hu_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */; }; + 06357CD21EBF70D80074E6D4 /* p_iterlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */; }; + 06357CD31EBF70D80074E6D4 /* p_terraintype.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */; }; + 06357CD41EBF70D80074E6D4 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD01EBF6F760074E6D4 /* p_user.c */; }; + 06357CD51EBF70D80074E6D4 /* p_view.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD11EBF6F760074E6D4 /* p_view.c */; }; + 06357CD61EBF70D80074E6D4 /* r_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD21EBF6F760074E6D4 /* r_common.c */; }; + 06357CD71EBF70D80074E6D4 /* x_hair.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD31EBF6F760074E6D4 /* x_hair.c */; }; + 06357CD81EBF70D80074E6D4 /* animdefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD41EBF6F760074E6D4 /* animdefs.cpp */; }; + 06357CD91EBF70D80074E6D4 /* fi_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */; }; + 06357CDA1EBF70D80074E6D4 /* g_controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD61EBF6F760074E6D4 /* g_controls.cpp */; }; + 06357CDB1EBF70D80074E6D4 /* gl_drawpatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */; }; + 06357CDC1EBF70D80074E6D4 /* hexlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD81EBF6F760074E6D4 /* hexlex.cpp */; }; + 06357CDD1EBF70D80074E6D4 /* hu_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */; }; + 06357CDE1EBF70D80074E6D4 /* hu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */; }; + 06357CDF1EBF70D80074E6D4 /* hu_menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */; }; + 06357CE01EBF70D80074E6D4 /* hu_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */; }; + 06357CE11EBF70D80074E6D4 /* hu_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */; }; + 06357CE21EBF70D80074E6D4 /* m_ctrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */; }; + 06357CE31EBF70D80074E6D4 /* p_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */; }; + 06357CE41EBF70D80074E6D4 /* p_saveg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */; }; + 06357CE51EBF70D80074E6D4 /* p_saveio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */; }; + 06357CE61EBF70E00074E6D4 /* dmu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */; }; + 06357CE71EBF70E00074E6D4 /* mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */; }; + 06357CE81EBF70E00074E6D4 /* mapstatewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */; }; + 06357CE91EBF70E10074E6D4 /* mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB51EBF6F760074E6D4 /* mobj.cpp */; }; + 06357CEA1EBF70E10074E6D4 /* p_actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB61EBF6F760074E6D4 /* p_actor.cpp */; }; + 06357CEB1EBF70E10074E6D4 /* p_ceiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */; }; + 06357CEC1EBF70E10074E6D4 /* p_door.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB81EBF6F760074E6D4 /* p_door.cpp */; }; + 06357CED1EBF70E10074E6D4 /* p_floor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB91EBF6F760074E6D4 /* p_floor.cpp */; }; + 06357CEE1EBF70E10074E6D4 /* p_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBA1EBF6F760074E6D4 /* p_map.cpp */; }; + 06357CEF1EBF70E10074E6D4 /* p_mapsetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */; }; + 06357CF01EBF70E10074E6D4 /* p_mapspec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */; }; + 06357CF11EBF70E10074E6D4 /* p_plat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */; }; + 06357CF21EBF70E10074E6D4 /* p_scroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */; }; + 06357CF31EBF70E10074E6D4 /* p_sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */; }; + 06357CF41EBF70E10074E6D4 /* p_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC01EBF6F760074E6D4 /* p_start.cpp */; }; + 06357CF51EBF70E10074E6D4 /* p_switch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC11EBF6F760074E6D4 /* p_switch.cpp */; }; + 06357CF61EBF70E10074E6D4 /* p_tick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC21EBF6F760074E6D4 /* p_tick.cpp */; }; + 06357CF71EBF70E10074E6D4 /* p_xgfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */; }; + 06357CF81EBF70E10074E6D4 /* p_xgline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */; }; + 06357CF91EBF70E10074E6D4 /* p_xgsave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */; }; + 06357CFA1EBF70E10074E6D4 /* p_xgsec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */; }; + 06357CFB1EBF70E10074E6D4 /* pause.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC71EBF6F760074E6D4 /* pause.cpp */; }; + 06357CFC1EBF70E10074E6D4 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC81EBF6F760074E6D4 /* player.cpp */; }; + 06357CFD1EBF70E10074E6D4 /* polyobjs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */; }; + 06357CFE1EBF70E10074E6D4 /* thingarchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */; }; + 06357CFF1EBF70E10074E6D4 /* thinkerinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */; }; + 06357D001EBF70E60074E6D4 /* d_net.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAE1EBF6F760074E6D4 /* d_net.cpp */; }; + 06357D011EBF70E60074E6D4 /* d_netcl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */; }; + 06357D021EBF70E60074E6D4 /* d_netsv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */; }; + 06357D031EBF70EB0074E6D4 /* page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9A1EBF6F760074E6D4 /* page.cpp */; }; + 06357D041EBF70F00074E6D4 /* buttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */; }; + 06357D051EBF70F00074E6D4 /* coloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */; }; + 06357D061EBF70F00074E6D4 /* cvarcoloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */; }; + 06357D071EBF70F00074E6D4 /* cvarinlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */; }; + 06357D081EBF70F00074E6D4 /* cvarlineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */; }; + 06357D091EBF70F00074E6D4 /* cvarsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */; }; + 06357D0A1EBF70F00074E6D4 /* cvartextualsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */; }; + 06357D0B1EBF70F00074E6D4 /* cvartogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */; }; + 06357D0C1EBF70F00074E6D4 /* inlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */; }; + 06357D0D1EBF70F00074E6D4 /* inputbindingwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */; }; + 06357D0E1EBF70F00074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */; }; + 06357D0F1EBF70F00074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */; }; + 06357D101EBF70F00074E6D4 /* listwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA81EBF6F760074E6D4 /* listwidget.cpp */; }; + 06357D111EBF70F00074E6D4 /* mobjpreviewwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */; }; + 06357D121EBF70F00074E6D4 /* rectwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */; }; + 06357D131EBF70F00074E6D4 /* sliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */; }; + 06357D141EBF70F00074E6D4 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAC1EBF6F760074E6D4 /* widget.cpp */; }; + 06357D151EBF70F50074E6D4 /* automapstyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B851EBF6F750074E6D4 /* automapstyle.cpp */; }; + 06357D161EBF70F50074E6D4 /* hudwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B861EBF6F750074E6D4 /* hudwidget.cpp */; }; + 06357D171EBF70FA0074E6D4 /* armorwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B881EBF6F750074E6D4 /* armorwidget.cpp */; }; + 06357D181EBF70FA0074E6D4 /* automapwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B891EBF6F750074E6D4 /* automapwidget.cpp */; }; + 06357D191EBF70FA0074E6D4 /* chainwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */; }; + 06357D1A1EBF70FA0074E6D4 /* chatwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */; }; + 06357D1B1EBF70FA0074E6D4 /* flightwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */; }; + 06357D1C1EBF70FA0074E6D4 /* fragswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */; }; + 06357D1D1EBF70FA0074E6D4 /* groupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */; }; + 06357D1E1EBF70FA0074E6D4 /* healthwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */; }; + 06357D1F1EBF70FA0074E6D4 /* itemswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B901EBF6F750074E6D4 /* itemswidget.cpp */; }; + 06357D201EBF70FA0074E6D4 /* keyslotwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */; }; + 06357D211EBF70FA0074E6D4 /* keyswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B921EBF6F750074E6D4 /* keyswidget.cpp */; }; + 06357D221EBF70FA0074E6D4 /* killswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B931EBF6F750074E6D4 /* killswidget.cpp */; }; + 06357D231EBF70FA0074E6D4 /* playerlogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */; }; + 06357D241EBF70FA0074E6D4 /* readyammoiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */; }; + 06357D251EBF70FA0074E6D4 /* readyammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */; }; + 06357D261EBF70FA0074E6D4 /* readyitemwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */; }; + 06357D271EBF70FA0074E6D4 /* secretswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B981EBF6F750074E6D4 /* secretswidget.cpp */; }; + 06357D281EBF70FE0074E6D4 /* g_defs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */; }; + 06357D291EBF70FE0074E6D4 /* g_eventsequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */; }; + 06357D2A1EBF70FE0074E6D4 /* g_game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7F1EBF6F750074E6D4 /* g_game.cpp */; }; + 06357D2B1EBF70FE0074E6D4 /* g_update.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B801EBF6F750074E6D4 /* g_update.cpp */; }; + 06357D2C1EBF70FE0074E6D4 /* gamerules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B811EBF6F750074E6D4 /* gamerules.cpp */; }; + 06357D2D1EBF70FE0074E6D4 /* gamesession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B821EBF6F750074E6D4 /* gamesession.cpp */; }; + 06357D2E1EBF70FE0074E6D4 /* saveslots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B831EBF6F750074E6D4 /* saveslots.cpp */; }; + 06357D2F1EBF71030074E6D4 /* interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B781EBF6F750074E6D4 /* interpreter.cpp */; }; + 06357D301EBF71030074E6D4 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B791EBF6F750074E6D4 /* module.cpp */; }; + 06357D311EBF71030074E6D4 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7A1EBF6F750074E6D4 /* script.cpp */; }; + 06357D321EBF71030074E6D4 /* system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7B1EBF6F750074E6D4 /* system.cpp */; }; + 06357D4B1EBF71320074E6D4 /* tomeofpowerwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D351EBF71320074E6D4 /* tomeofpowerwidget.cpp */; }; + 06357D4C1EBF71320074E6D4 /* acfnlink.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D361EBF71320074E6D4 /* acfnlink.c */; }; + 06357D4D1EBF71320074E6D4 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D371EBF71320074E6D4 /* m_random.c */; }; + 06357D4E1EBF71330074E6D4 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D381EBF71320074E6D4 /* p_enemy.c */; }; + 06357D4F1EBF71330074E6D4 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D391EBF71320074E6D4 /* p_inter.c */; }; + 06357D501EBF71330074E6D4 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3A1EBF71320074E6D4 /* p_maputl.c */; }; + 06357D511EBF71330074E6D4 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3B1EBF71320074E6D4 /* p_mobj.c */; }; + 06357D521EBF71330074E6D4 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3C1EBF71320074E6D4 /* p_pspr.c */; }; + 06357D531EBF71330074E6D4 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3D1EBF71320074E6D4 /* p_setup.c */; }; + 06357D541EBF71330074E6D4 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3E1EBF71320074E6D4 /* p_telept.c */; }; + 06357D551EBF71330074E6D4 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357D3F1EBF71320074E6D4 /* tables.c */; }; + 06357D561EBF71330074E6D4 /* h_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D401EBF71320074E6D4 /* h_api.cpp */; }; + 06357D571EBF71330074E6D4 /* h_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D411EBF71320074E6D4 /* h_console.cpp */; }; + 06357D581EBF71330074E6D4 /* h_items.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D421EBF71320074E6D4 /* h_items.cpp */; }; + 06357D591EBF71330074E6D4 /* h_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D431EBF71320074E6D4 /* h_main.cpp */; }; + 06357D5A1EBF71330074E6D4 /* h_refresh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D441EBF71320074E6D4 /* h_refresh.cpp */; }; + 06357D5B1EBF71330074E6D4 /* hereticv13mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D451EBF71320074E6D4 /* hereticv13mapstatereader.cpp */; }; + 06357D5C1EBF71330074E6D4 /* intermission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D461EBF71320074E6D4 /* intermission.cpp */; }; + 06357D5D1EBF71330074E6D4 /* m_cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D471EBF71320074E6D4 /* m_cheat.cpp */; }; + 06357D5E1EBF71330074E6D4 /* p_lights.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D481EBF71320074E6D4 /* p_lights.cpp */; }; + 06357D5F1EBF71330074E6D4 /* p_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D491EBF71320074E6D4 /* p_spec.cpp */; }; + 06357D601EBF71330074E6D4 /* st_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357D4A1EBF71320074E6D4 /* st_stuff.cpp */; }; + 06357D631EBF728D0074E6D4 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAC1EBF6F760074E6D4 /* widget.cpp */; }; + 06357D651EBF728D0074E6D4 /* p_sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */; }; + 06357D661EBF728D0074E6D4 /* p_xgsec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */; }; + 06357D671EBF728D0074E6D4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCC1EBF6F760074E6D4 /* common.c */; }; + 06357D681EBF728D0074E6D4 /* keyslotwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */; }; + 06357D691EBF728D0074E6D4 /* g_eventsequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */; }; + 06357D6B1EBF728D0074E6D4 /* hu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */; }; + 06357D6D1EBF728D0074E6D4 /* inputbindingwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */; }; + 06357D6E1EBF728D0074E6D4 /* g_game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7F1EBF6F750074E6D4 /* g_game.cpp */; }; + 06357D6F1EBF728D0074E6D4 /* gamerules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B811EBF6F750074E6D4 /* gamerules.cpp */; }; + 06357D701EBF728D0074E6D4 /* readyammoiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */; }; + 06357D711EBF728D0074E6D4 /* itemswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B901EBF6F750074E6D4 /* itemswidget.cpp */; }; + 06357D721EBF728D0074E6D4 /* p_iterlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */; }; + 06357D731EBF728D0074E6D4 /* p_xgsave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */; }; + 06357D741EBF728D0074E6D4 /* system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7B1EBF6F750074E6D4 /* system.cpp */; }; + 06357D751EBF728D0074E6D4 /* page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9A1EBF6F760074E6D4 /* page.cpp */; }; + 06357D761EBF728D0074E6D4 /* automapstyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B851EBF6F750074E6D4 /* automapstyle.cpp */; }; + 06357D771EBF728D0074E6D4 /* p_terraintype.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */; }; + 06357D781EBF728D0074E6D4 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD01EBF6F760074E6D4 /* p_user.c */; }; + 06357D791EBF728D0074E6D4 /* secretswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B981EBF6F750074E6D4 /* secretswidget.cpp */; }; + 06357D7A1EBF728D0074E6D4 /* g_defs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */; }; + 06357D7B1EBF728D0074E6D4 /* interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B781EBF6F750074E6D4 /* interpreter.cpp */; }; + 06357D7C1EBF728D0074E6D4 /* p_xgline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */; }; + 06357D7D1EBF728D0074E6D4 /* d_netcl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */; }; + 06357D7E1EBF728D0074E6D4 /* mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */; }; + 06357D7F1EBF728D0074E6D4 /* g_update.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B801EBF6F750074E6D4 /* g_update.cpp */; }; + 06357D801EBF728D0074E6D4 /* p_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBA1EBF6F760074E6D4 /* p_map.cpp */; }; + 06357D821EBF728D0074E6D4 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC81EBF6F760074E6D4 /* player.cpp */; }; + 06357D831EBF728D0074E6D4 /* p_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC01EBF6F760074E6D4 /* p_start.cpp */; }; + 06357D841EBF728D0074E6D4 /* cvarlineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */; }; + 06357D851EBF728D0074E6D4 /* hu_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */; }; + 06357D861EBF728D0074E6D4 /* mapstatewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */; }; + 06357D871EBF728D0074E6D4 /* p_scroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */; }; + 06357D881EBF728D0074E6D4 /* p_actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB61EBF6F760074E6D4 /* p_actor.cpp */; }; + 06357D891EBF728D0074E6D4 /* chatwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */; }; + 06357D8A1EBF728D0074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */; }; + 06357D8B1EBF728D0074E6D4 /* hexlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD81EBF6F760074E6D4 /* hexlex.cpp */; }; + 06357D8D1EBF728D0074E6D4 /* p_plat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */; }; + 06357D8E1EBF728D0074E6D4 /* x_hair.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD31EBF6F760074E6D4 /* x_hair.c */; }; + 06357D8F1EBF728D0074E6D4 /* d_netsv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */; }; + 06357D901EBF728D0074E6D4 /* automapwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B891EBF6F750074E6D4 /* automapwidget.cpp */; }; + 06357D911EBF728D0074E6D4 /* m_ctrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */; }; + 06357D921EBF728D0074E6D4 /* groupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */; }; + 06357D931EBF728D0074E6D4 /* pause.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC71EBF6F760074E6D4 /* pause.cpp */; }; + 06357D941EBF728D0074E6D4 /* d_net.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAE1EBF6F760074E6D4 /* d_net.cpp */; }; + 06357D951EBF728D0074E6D4 /* cvartogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */; }; + 06357D961EBF728D0074E6D4 /* p_tick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC21EBF6F760074E6D4 /* p_tick.cpp */; }; + 06357D971EBF728D0074E6D4 /* rectwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */; }; + 06357D9A1EBF728D0074E6D4 /* p_ceiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */; }; + 06357D9B1EBF728D0074E6D4 /* buttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */; }; + 06357D9D1EBF728D0074E6D4 /* fragswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */; }; + 06357D9E1EBF728D0074E6D4 /* killswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B931EBF6F750074E6D4 /* killswidget.cpp */; }; + 06357D9F1EBF728D0074E6D4 /* coloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */; }; + 06357DA01EBF728D0074E6D4 /* p_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */; }; + 06357DA21EBF728D0074E6D4 /* sliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */; }; + 06357DA31EBF728D0074E6D4 /* cvartextualsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */; }; + 06357DA41EBF728D0074E6D4 /* p_mapspec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */; }; + 06357DA51EBF728D0074E6D4 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7A1EBF6F750074E6D4 /* script.cpp */; }; + 06357DA71EBF728D0074E6D4 /* gl_drawpatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */; }; + 06357DA81EBF728D0074E6D4 /* p_floor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB91EBF6F760074E6D4 /* p_floor.cpp */; }; + 06357DA91EBF728D0074E6D4 /* cvarcoloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */; }; + 06357DAB1EBF728D0074E6D4 /* p_door.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB81EBF6F760074E6D4 /* p_door.cpp */; }; + 06357DAC1EBF728D0074E6D4 /* readyitemwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */; }; + 06357DAD1EBF728D0074E6D4 /* readyammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */; }; + 06357DAE1EBF728D0074E6D4 /* flightwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */; }; + 06357DAF1EBF728D0074E6D4 /* armorwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B881EBF6F750074E6D4 /* armorwidget.cpp */; }; + 06357DB01EBF728D0074E6D4 /* hu_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */; }; + 06357DB11EBF728D0074E6D4 /* animdefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD41EBF6F760074E6D4 /* animdefs.cpp */; }; + 06357DB31EBF728D0074E6D4 /* hu_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */; }; + 06357DB41EBF728D0074E6D4 /* p_xgfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */; }; + 06357DB51EBF728D0074E6D4 /* saveslots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B831EBF6F750074E6D4 /* saveslots.cpp */; }; + 06357DB61EBF728D0074E6D4 /* thinkerinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */; }; + 06357DB71EBF728D0074E6D4 /* p_saveg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */; }; + 06357DB81EBF728D0074E6D4 /* healthwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */; }; + 06357DB91EBF728D0074E6D4 /* r_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD21EBF6F760074E6D4 /* r_common.c */; }; + 06357DBA1EBF728D0074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */; }; + 06357DBB1EBF728D0074E6D4 /* fi_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */; }; + 06357DBC1EBF728D0074E6D4 /* cvarinlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */; }; + 06357DBD1EBF728D0074E6D4 /* dmu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */; }; + 06357DBF1EBF728D0074E6D4 /* hu_menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */; }; + 06357DC21EBF728D0074E6D4 /* gamesession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B821EBF6F750074E6D4 /* gamesession.cpp */; }; + 06357DC31EBF728D0074E6D4 /* chainwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */; }; + 06357DC41EBF728D0074E6D4 /* p_view.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD11EBF6F760074E6D4 /* p_view.c */; }; + 06357DC51EBF728D0074E6D4 /* polyobjs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */; }; + 06357DC61EBF728D0074E6D4 /* p_switch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC11EBF6F760074E6D4 /* p_switch.cpp */; }; + 06357DC71EBF728D0074E6D4 /* inlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */; }; + 06357DC81EBF728D0074E6D4 /* thingarchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */; }; + 06357DC91EBF728D0074E6D4 /* mobjpreviewwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */; }; + 06357DCB1EBF728D0074E6D4 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B791EBF6F750074E6D4 /* module.cpp */; }; + 06357DCE1EBF728D0074E6D4 /* p_saveio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */; }; + 06357DCF1EBF728D0074E6D4 /* mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB51EBF6F760074E6D4 /* mobj.cpp */; }; + 06357DD01EBF728D0074E6D4 /* p_mapsetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */; }; + 06357DD11EBF728D0074E6D4 /* hudwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B861EBF6F750074E6D4 /* hudwidget.cpp */; }; + 06357DD21EBF728D0074E6D4 /* hu_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */; }; + 06357DD31EBF728D0074E6D4 /* playerlogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */; }; + 06357DD51EBF728D0074E6D4 /* cvarsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */; }; + 06357DD71EBF728D0074E6D4 /* listwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA81EBF6F760074E6D4 /* listwidget.cpp */; }; + 06357DDA1EBF728D0074E6D4 /* g_controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD61EBF6F760074E6D4 /* g_controls.cpp */; }; + 06357DDB1EBF728D0074E6D4 /* keyswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B921EBF6F750074E6D4 /* keyswidget.cpp */; }; + 06357E2E1EBF73790074E6D4 /* a_action.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF01EBF73460074E6D4 /* a_action.c */; }; + 06357E2F1EBF73790074E6D4 /* acfnlink.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF11EBF73460074E6D4 /* acfnlink.c */; }; + 06357E301EBF73790074E6D4 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF21EBF73460074E6D4 /* m_random.c */; }; + 06357E311EBF73790074E6D4 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF31EBF73460074E6D4 /* p_enemy.c */; }; + 06357E321EBF73790074E6D4 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF41EBF73460074E6D4 /* p_inter.c */; }; + 06357E331EBF73790074E6D4 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF51EBF73460074E6D4 /* p_maputl.c */; }; + 06357E341EBF73790074E6D4 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF61EBF73460074E6D4 /* p_mobj.c */; }; + 06357E351EBF73790074E6D4 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF71EBF73460074E6D4 /* p_pspr.c */; }; + 06357E361EBF73790074E6D4 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF81EBF73460074E6D4 /* p_setup.c */; }; + 06357E371EBF73790074E6D4 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DF91EBF73460074E6D4 /* p_telept.c */; }; + 06357E381EBF73790074E6D4 /* p_things.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFA1EBF73460074E6D4 /* p_things.c */; }; + 06357E391EBF73790074E6D4 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFB1EBF73460074E6D4 /* tables.c */; }; + 06357E3A1EBF73790074E6D4 /* h2_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFC1EBF73460074E6D4 /* h2_main.cpp */; }; + 06357E3B1EBF73790074E6D4 /* hconsole.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFD1EBF73460074E6D4 /* hconsole.cpp */; }; + 06357E3C1EBF73790074E6D4 /* hrefresh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFE1EBF73460074E6D4 /* hrefresh.cpp */; }; + 06357E3D1EBF73790074E6D4 /* intermission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DFF1EBF73460074E6D4 /* intermission.cpp */; }; + 06357E3E1EBF73790074E6D4 /* lightninganimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E001EBF73460074E6D4 /* lightninganimator.cpp */; }; + 06357E3F1EBF73790074E6D4 /* m_cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E011EBF73460074E6D4 /* m_cheat.cpp */; }; + 06357E401EBF73790074E6D4 /* p_lights.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E021EBF73460074E6D4 /* p_lights.cpp */; }; + 06357E411EBF73790074E6D4 /* p_pillar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E031EBF73460074E6D4 /* p_pillar.cpp */; }; + 06357E421EBF73790074E6D4 /* p_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E041EBF73460074E6D4 /* p_spec.cpp */; }; + 06357E431EBF73790074E6D4 /* p_waggle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E051EBF73460074E6D4 /* p_waggle.cpp */; }; + 06357E441EBF73790074E6D4 /* sn_sonix.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E061EBF73460074E6D4 /* sn_sonix.cpp */; }; + 06357E451EBF73790074E6D4 /* st_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E071EBF73460074E6D4 /* st_stuff.cpp */; }; + 06357E461EBF73790074E6D4 /* x_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357E081EBF73460074E6D4 /* x_api.cpp */; }; + 06357E471EBF73800074E6D4 /* armoriconswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE41EBF73460074E6D4 /* armoriconswidget.cpp */; }; + 06357E481EBF73800074E6D4 /* bluemanaiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE51EBF73460074E6D4 /* bluemanaiconwidget.cpp */; }; + 06357E491EBF73800074E6D4 /* bluemanavialwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE61EBF73460074E6D4 /* bluemanavialwidget.cpp */; }; + 06357E4A1EBF73800074E6D4 /* bluemanawidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE71EBF73460074E6D4 /* bluemanawidget.cpp */; }; + 06357E4B1EBF73800074E6D4 /* bootswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE81EBF73460074E6D4 /* bootswidget.cpp */; }; + 06357E4C1EBF73800074E6D4 /* defensewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DE91EBF73460074E6D4 /* defensewidget.cpp */; }; + 06357E4D1EBF73800074E6D4 /* greenmanaiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DEA1EBF73460074E6D4 /* greenmanaiconwidget.cpp */; }; + 06357E4E1EBF73800074E6D4 /* greenmanavialwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DEB1EBF73460074E6D4 /* greenmanavialwidget.cpp */; }; + 06357E4F1EBF73800074E6D4 /* greenmanawidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DEC1EBF73460074E6D4 /* greenmanawidget.cpp */; }; + 06357E501EBF73800074E6D4 /* servantwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DED1EBF73460074E6D4 /* servantwidget.cpp */; }; + 06357E511EBF73800074E6D4 /* weaponpieceswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DEE1EBF73460074E6D4 /* weaponpieceswidget.cpp */; }; + 06357E521EBF73800074E6D4 /* worldtimewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357DEF1EBF73460074E6D4 /* worldtimewidget.cpp */; }; + 06357E5F1EBF73F80074E6D4 /* libdeng_appfw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 063578061EBF42D10074E6D4 /* libdeng_appfw.a */; }; + 06357E601EBF73F80074E6D4 /* libdeng_doomsday.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 063578941EBF43A30074E6D4 /* libdeng_doomsday.a */; }; + 06357E611EBF73F80074E6D4 /* libdeng_gamefw.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357AF01EBF61C70074E6D4 /* libdeng_gamefw.a */; }; + 06357E621EBF73F80074E6D4 /* libdoom.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357B3C1EBF6EBD0074E6D4 /* libdoom.a */; }; + 06357E631EBF73F80074E6D4 /* libheretic.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357CCB1EBF70A20074E6D4 /* libheretic.a */; }; + 06357E641EBF73F80074E6D4 /* libhexen.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357DE11EBF728D0074E6D4 /* libhexen.a */; }; + 06357E651EBF73F80074E6D4 /* libimportdeh.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357B041EBF63770074E6D4 /* libimportdeh.a */; }; + 06357E661EBF73F80074E6D4 /* libimportudmf.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357B291EBF69C00074E6D4 /* libimportudmf.a */; }; + 06357E691EBF76120074E6D4 /* pause.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC71EBF6F760074E6D4 /* pause.cpp */; }; + 06357E6A1EBF76120074E6D4 /* lineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */; }; + 06357E6B1EBF76120074E6D4 /* cvartextualsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */; }; + 06357E6C1EBF76120074E6D4 /* p_xgfile.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */; }; + 06357E6D1EBF76120074E6D4 /* system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7B1EBF6F750074E6D4 /* system.cpp */; }; + 06357E6E1EBF76120074E6D4 /* r_common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD21EBF6F760074E6D4 /* r_common.c */; }; + 06357E6F1EBF76120074E6D4 /* buttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */; }; + 06357E701EBF76120074E6D4 /* p_xgsec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */; }; + 06357E711EBF76120074E6D4 /* groupwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */; }; + 06357E721EBF76120074E6D4 /* g_game.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7F1EBF6F750074E6D4 /* g_game.cpp */; }; + 06357E731EBF76120074E6D4 /* g_defs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */; }; + 06357E741EBF76120074E6D4 /* cvarlineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */; }; + 06357E751EBF76120074E6D4 /* saveslots.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B831EBF6F750074E6D4 /* saveslots.cpp */; }; + 06357E781EBF76120074E6D4 /* d_netsv.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */; }; + 06357E791EBF76120074E6D4 /* cvartogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */; }; + 06357E7A1EBF76120074E6D4 /* p_iterlist.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */; }; + 06357E7B1EBF76120074E6D4 /* fi_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */; }; + 06357E7C1EBF76120074E6D4 /* hu_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */; }; + 06357E7E1EBF76120074E6D4 /* readyitemwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */; }; + 06357E7F1EBF76120074E6D4 /* hu_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */; }; + 06357E801EBF76120074E6D4 /* hu_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */; }; + 06357E811EBF76120074E6D4 /* g_update.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B801EBF6F750074E6D4 /* g_update.cpp */; }; + 06357E821EBF76120074E6D4 /* chatwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */; }; + 06357E831EBF76120074E6D4 /* hu_menu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */; }; + 06357E841EBF76120074E6D4 /* hudwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B861EBF6F750074E6D4 /* hudwidget.cpp */; }; + 06357E851EBF76120074E6D4 /* x_hair.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD31EBF6F760074E6D4 /* x_hair.c */; }; + 06357E861EBF76120074E6D4 /* rectwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */; }; + 06357E871EBF76120074E6D4 /* p_saveio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */; }; + 06357E881EBF76120074E6D4 /* p_scroll.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */; }; + 06357E8A1EBF76120074E6D4 /* p_sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */; }; + 06357E8B1EBF76120074E6D4 /* automapstyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B851EBF6F750074E6D4 /* automapstyle.cpp */; }; + 06357E8C1EBF76120074E6D4 /* automapwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B891EBF6F750074E6D4 /* automapwidget.cpp */; }; + 06357E8E1EBF76120074E6D4 /* keyswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B921EBF6F750074E6D4 /* keyswidget.cpp */; }; + 06357E901EBF76120074E6D4 /* common.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCC1EBF6F760074E6D4 /* common.c */; }; + 06357E911EBF76120074E6D4 /* mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB51EBF6F760074E6D4 /* mobj.cpp */; }; + 06357E921EBF76120074E6D4 /* p_mapsetup.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */; }; + 06357E931EBF76120074E6D4 /* polyobjs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */; }; + 06357E941EBF76120074E6D4 /* fragswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */; }; + 06357E961EBF76120074E6D4 /* gamerules.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B811EBF6F750074E6D4 /* gamerules.cpp */; }; + 06357E981EBF76120074E6D4 /* animdefs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD41EBF6F760074E6D4 /* animdefs.cpp */; }; + 06357E991EBF76120074E6D4 /* cvarinlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */; }; + 06357E9A1EBF76120074E6D4 /* hexlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD81EBF6F760074E6D4 /* hexlex.cpp */; }; + 06357E9B1EBF76120074E6D4 /* hu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */; }; + 06357EA11EBF76120074E6D4 /* secretswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B981EBF6F750074E6D4 /* secretswidget.cpp */; }; + 06357EA31EBF76120074E6D4 /* d_net.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAE1EBF6F760074E6D4 /* d_net.cpp */; }; + 06357EA41EBF76120074E6D4 /* p_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBA1EBF6F760074E6D4 /* p_map.cpp */; }; + 06357EA51EBF76120074E6D4 /* itemswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B901EBF6F750074E6D4 /* itemswidget.cpp */; }; + 06357EA71EBF76120074E6D4 /* sliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */; }; + 06357EA81EBF76120074E6D4 /* p_ceiling.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */; }; + 06357EAA1EBF76120074E6D4 /* interpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B781EBF6F750074E6D4 /* interpreter.cpp */; }; + 06357EAB1EBF76120074E6D4 /* thingarchive.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */; }; + 06357EAC1EBF76120074E6D4 /* mapstatewriter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */; }; + 06357EAD1EBF76120074E6D4 /* listwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA81EBF6F760074E6D4 /* listwidget.cpp */; }; + 06357EAE1EBF76120074E6D4 /* m_ctrl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */; }; + 06357EAF1EBF76120074E6D4 /* p_switch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC11EBF6F760074E6D4 /* p_switch.cpp */; }; + 06357EB01EBF76120074E6D4 /* mapstatereader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */; }; + 06357EB11EBF76120074E6D4 /* p_tick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC21EBF6F760074E6D4 /* p_tick.cpp */; }; + 06357EB21EBF76120074E6D4 /* readyammowidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */; }; + 06357EB41EBF76120074E6D4 /* chainwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */; }; + 06357EB61EBF76120074E6D4 /* g_eventsequence.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */; }; + 06357EB71EBF76120074E6D4 /* cvarcoloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */; }; + 06357EB81EBF76120074E6D4 /* p_xgline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */; }; + 06357EB91EBF76120074E6D4 /* p_floor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB91EBF6F760074E6D4 /* p_floor.cpp */; }; + 06357EBA1EBF76120074E6D4 /* p_door.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB81EBF6F760074E6D4 /* p_door.cpp */; }; + 06357EBB1EBF76120074E6D4 /* inputbindingwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */; }; + 06357EBC1EBF76120074E6D4 /* keyslotwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */; }; + 06357EBE1EBF76120074E6D4 /* p_actor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB61EBF6F760074E6D4 /* p_actor.cpp */; }; + 06357EBF1EBF76120074E6D4 /* thinkerinfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */; }; + 06357EC01EBF76120074E6D4 /* playerlogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */; }; + 06357EC21EBF76120074E6D4 /* script.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B7A1EBF6F750074E6D4 /* script.cpp */; }; + 06357EC31EBF76120074E6D4 /* dmu_lib.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */; }; + 06357EC51EBF76120074E6D4 /* cvarsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */; }; + 06357EC61EBF76120074E6D4 /* p_plat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */; }; + 06357EC71EBF76120074E6D4 /* coloreditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */; }; + 06357EC81EBF76120074E6D4 /* mobjpreviewwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */; }; + 06357EC91EBF76120074E6D4 /* gl_drawpatch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */; }; + 06357ECA1EBF76120074E6D4 /* g_controls.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD61EBF6F760074E6D4 /* g_controls.cpp */; }; + 06357ECB1EBF76120074E6D4 /* page.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B9A1EBF6F760074E6D4 /* page.cpp */; }; + 06357ECC1EBF76120074E6D4 /* hu_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */; }; + 06357ECD1EBF76120074E6D4 /* labelwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */; }; + 06357ECE1EBF76120074E6D4 /* p_xgsave.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */; }; + 06357ECF1EBF76120074E6D4 /* p_start.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC01EBF6F760074E6D4 /* p_start.cpp */; }; + 06357ED01EBF76120074E6D4 /* p_mapspec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */; }; + 06357ED21EBF76120074E6D4 /* armorwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B881EBF6F750074E6D4 /* armorwidget.cpp */; }; + 06357ED31EBF76120074E6D4 /* player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BC81EBF6F760074E6D4 /* player.cpp */; }; + 06357ED41EBF76120074E6D4 /* p_user.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD01EBF6F760074E6D4 /* p_user.c */; }; + 06357ED51EBF76120074E6D4 /* killswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B931EBF6F750074E6D4 /* killswidget.cpp */; }; + 06357ED61EBF76120074E6D4 /* gamesession.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B821EBF6F750074E6D4 /* gamesession.cpp */; }; + 06357ED91EBF76120074E6D4 /* p_view.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BD11EBF6F760074E6D4 /* p_view.c */; }; + 06357EDA1EBF76120074E6D4 /* readyammoiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */; }; + 06357EDB1EBF76120074E6D4 /* inlinelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */; }; + 06357EDC1EBF76120074E6D4 /* p_inventory.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */; }; + 06357EDF1EBF76120074E6D4 /* module.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B791EBF6F750074E6D4 /* module.cpp */; }; + 06357EE01EBF76120074E6D4 /* widget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAC1EBF6F760074E6D4 /* widget.cpp */; }; + 06357EE11EBF76120074E6D4 /* p_saveg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */; }; + 06357EE21EBF76120074E6D4 /* flightwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */; }; + 06357EE31EBF76120074E6D4 /* healthwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */; }; + 06357EE41EBF76120074E6D4 /* d_netcl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */; }; + 06357EE51EBF76120074E6D4 /* p_terraintype.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */; }; + 06357F211EBF76880074E6D4 /* armoriconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF01EBF767C0074E6D4 /* armoriconwidget.cpp */; }; + 06357F221EBF76880074E6D4 /* healthiconwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF11EBF767C0074E6D4 /* healthiconwidget.cpp */; }; + 06357F231EBF769C0074E6D4 /* acfnlink.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF51EBF767C0074E6D4 /* acfnlink.c */; }; + 06357F241EBF769C0074E6D4 /* m_random.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF61EBF767C0074E6D4 /* m_random.c */; }; + 06357F251EBF769C0074E6D4 /* p_enemy.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF71EBF767C0074E6D4 /* p_enemy.c */; }; + 06357F261EBF769C0074E6D4 /* p_inter.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF81EBF767C0074E6D4 /* p_inter.c */; }; + 06357F271EBF769C0074E6D4 /* p_maputl.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EF91EBF767C0074E6D4 /* p_maputl.c */; }; + 06357F281EBF769C0074E6D4 /* p_mobj.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFA1EBF767C0074E6D4 /* p_mobj.c */; }; + 06357F291EBF769C0074E6D4 /* p_pspr.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFB1EBF767C0074E6D4 /* p_pspr.c */; }; + 06357F2A1EBF769C0074E6D4 /* p_setup.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFC1EBF767C0074E6D4 /* p_setup.c */; }; + 06357F2B1EBF769C0074E6D4 /* p_telept.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFD1EBF767C0074E6D4 /* p_telept.c */; }; + 06357F2C1EBF769C0074E6D4 /* tables.c in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFE1EBF767C0074E6D4 /* tables.c */; }; + 06357F2D1EBF769C0074E6D4 /* d_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357EFF1EBF767C0074E6D4 /* d_console.cpp */; }; + 06357F2E1EBF769C0074E6D4 /* d_items.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F001EBF767C0074E6D4 /* d_items.cpp */; }; + 06357F2F1EBF769C0074E6D4 /* d_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F011EBF767C0074E6D4 /* d_main.cpp */; }; + 06357F301EBF769C0074E6D4 /* d_refresh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F021EBF767C0074E6D4 /* d_refresh.cpp */; }; + 06357F311EBF769C0074E6D4 /* d64_api.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F031EBF767C0074E6D4 /* d64_api.cpp */; }; + 06357F321EBF769C0074E6D4 /* intermission.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F041EBF767C0074E6D4 /* intermission.cpp */; }; + 06357F331EBF769C0074E6D4 /* m_cheat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F051EBF767C0074E6D4 /* m_cheat.cpp */; }; + 06357F341EBF769C0074E6D4 /* p_lights.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F061EBF767C0074E6D4 /* p_lights.cpp */; }; + 06357F351EBF769C0074E6D4 /* p_spec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F071EBF767C0074E6D4 /* p_spec.cpp */; }; + 06357F361EBF769C0074E6D4 /* st_stuff.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F081EBF767C0074E6D4 /* st_stuff.cpp */; }; + 06357F481EBF78420074E6D4 /* driver_fmod.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F431EBF78420074E6D4 /* driver_fmod.cpp */; }; + 06357F491EBF78420074E6D4 /* fmod_cd.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F441EBF78420074E6D4 /* fmod_cd.cpp */; }; + 06357F4A1EBF78420074E6D4 /* fmod_music.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F451EBF78420074E6D4 /* fmod_music.cpp */; }; + 06357F4B1EBF78420074E6D4 /* fmod_sfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F461EBF78420074E6D4 /* fmod_sfx.cpp */; }; + 06357F4C1EBF78420074E6D4 /* fmod_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F471EBF78420074E6D4 /* fmod_util.cpp */; }; + 06357F531EBF79FF0074E6D4 /* libaudio_fmod.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357F421EBF77A00074E6D4 /* libaudio_fmod.a */; }; + 06357F541EBF79FF0074E6D4 /* libdoom64.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 06357EED1EBF76120074E6D4 /* libdoom64.a */; }; + 063580741EBF7AE50074E6D4 /* audiodriver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F561EBF7AE50074E6D4 /* audiodriver.cpp */; }; + 063580751EBF7AE50074E6D4 /* audiosystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F581EBF7AE50074E6D4 /* audiosystem.cpp */; }; + 063580771EBF7AE50074E6D4 /* s_cache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5A1EBF7AE50074E6D4 /* s_cache.cpp */; }; + 063580781EBF7AE50074E6D4 /* m_mus2midi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5B1EBF7AE50074E6D4 /* m_mus2midi.cpp */; }; + 063580791EBF7AE50074E6D4 /* s_environ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5C1EBF7AE50074E6D4 /* s_environ.cpp */; }; + 0635807A1EBF7AE50074E6D4 /* sfxchannel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5D1EBF7AE50074E6D4 /* sfxchannel.cpp */; }; + 0635807B1EBF7AE50074E6D4 /* sys_audiod_dummy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5E1EBF7AE50074E6D4 /* sys_audiod_dummy.cpp */; }; + 0635807C1EBF7AE50074E6D4 /* sys_audiod_sdlmixer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F5F1EBF7AE50074E6D4 /* sys_audiod_sdlmixer.cpp */; }; + 0635807D1EBF7AE50074E6D4 /* cl_frame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F611EBF7AE50074E6D4 /* cl_frame.cpp */; }; + 0635807E1EBF7AE50074E6D4 /* cl_infine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F621EBF7AE50074E6D4 /* cl_infine.cpp */; }; + 0635807F1EBF7AE50074E6D4 /* cl_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F631EBF7AE50074E6D4 /* cl_main.cpp */; }; + 063580801EBF7AE50074E6D4 /* cl_mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F641EBF7AE50074E6D4 /* cl_mobj.cpp */; }; + 063580811EBF7AE50074E6D4 /* cl_player.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F651EBF7AE50074E6D4 /* cl_player.cpp */; }; + 063580821EBF7AE50074E6D4 /* cl_sound.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F661EBF7AE50074E6D4 /* cl_sound.cpp */; }; + 063580831EBF7AE50074E6D4 /* cl_world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F671EBF7AE50074E6D4 /* cl_world.cpp */; }; + 063580841EBF7AE50074E6D4 /* cledgeloop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F681EBF7AE50074E6D4 /* cledgeloop.cpp */; }; + 063580851EBF7AE50074E6D4 /* clientsubsector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F691EBF7AE50074E6D4 /* clientsubsector.cpp */; }; + 063580861EBF7AE50074E6D4 /* clplanemover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F6A1EBF7AE50074E6D4 /* clplanemover.cpp */; }; + 063580871EBF7AE50074E6D4 /* clpolymover.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F6B1EBF7AE50074E6D4 /* clpolymover.cpp */; }; + 063580881EBF7AE50074E6D4 /* clskyplane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F6C1EBF7AE50074E6D4 /* clskyplane.cpp */; }; + 063580891EBF7AE50074E6D4 /* dgl_common.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F6E1EBF7AE50074E6D4 /* dgl_common.cpp */; }; + 0635808A1EBF7AE50074E6D4 /* dgl_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F6F1EBF7AE50074E6D4 /* dgl_draw.cpp */; }; + 0635808B1EBF7AE50074E6D4 /* gl_defer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F701EBF7AE50074E6D4 /* gl_defer.cpp */; }; + 0635808C1EBF7AE50074E6D4 /* gl_deferredapi.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F711EBF7AE50074E6D4 /* gl_deferredapi.cpp */; }; + 0635808D1EBF7AE50074E6D4 /* gl_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F721EBF7AE50074E6D4 /* gl_draw.cpp */; }; + 0635808E1EBF7AE50074E6D4 /* gl_drawvectorgraphic.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F731EBF7AE50074E6D4 /* gl_drawvectorgraphic.cpp */; }; + 0635808F1EBF7AE50074E6D4 /* gl_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F741EBF7AE50074E6D4 /* gl_main.cpp */; }; + 063580901EBF7AE50074E6D4 /* gl_tex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F751EBF7AE50074E6D4 /* gl_tex.cpp */; }; + 063580911EBF7AE50074E6D4 /* gl_texmanager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F761EBF7AE50074E6D4 /* gl_texmanager.cpp */; }; + 063580921EBF7AE50074E6D4 /* svg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F771EBF7AE50074E6D4 /* svg.cpp */; }; + 063580931EBF7AE50074E6D4 /* sys_opengl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F781EBF7AE50074E6D4 /* sys_opengl.cpp */; }; + 063580941EBF7AE50074E6D4 /* texturecontent.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F791EBF7AE50074E6D4 /* texturecontent.cpp */; }; + 063580951EBF7AE50074E6D4 /* color.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F7B1EBF7AE50074E6D4 /* color.cpp */; }; + 063580961EBF7AE50074E6D4 /* face.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F7C1EBF7AE50074E6D4 /* face.cpp */; }; + 063580971EBF7AE50074E6D4 /* hedge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F7D1EBF7AE50074E6D4 /* hedge.cpp */; }; + 063580981EBF7AE50074E6D4 /* mesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F7E1EBF7AE50074E6D4 /* mesh.cpp */; }; + 063580991EBF7AE50074E6D4 /* r_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F7F1EBF7AE50074E6D4 /* r_util.cpp */; }; + 0635809A1EBF7AE50074E6D4 /* tab_tables.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F801EBF7AE50074E6D4 /* tab_tables.cpp */; }; + 0635809B1EBF7AE50074E6D4 /* masterserver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F831EBF7AE50074E6D4 /* masterserver.cpp */; }; + 0635809C1EBF7AE50074E6D4 /* monitor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F841EBF7AE50074E6D4 /* monitor.cpp */; }; + 0635809D1EBF7AE50074E6D4 /* net_buf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F851EBF7AE50074E6D4 /* net_buf.cpp */; }; + 0635809E1EBF7AE50074E6D4 /* net_event.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F861EBF7AE50074E6D4 /* net_event.cpp */; }; + 0635809F1EBF7AE50074E6D4 /* net_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F871EBF7AE50074E6D4 /* net_main.cpp */; }; + 063580A01EBF7AE50074E6D4 /* net_msg.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F881EBF7AE50074E6D4 /* net_msg.cpp */; }; + 063580A11EBF7AE50074E6D4 /* net_ping.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F891EBF7AE50074E6D4 /* net_ping.cpp */; }; + 063580A31EBF7AE50074E6D4 /* net_demo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F8B1EBF7AE50074E6D4 /* net_demo.cpp */; }; + 063580A41EBF7AE50074E6D4 /* serverlink.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F8C1EBF7AE50074E6D4 /* serverlink.cpp */; }; + 063580A51EBF7AE50074E6D4 /* sys_network.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F8D1EBF7AE50074E6D4 /* sys_network.cpp */; }; + 063580A61EBF7AE50074E6D4 /* angleclipper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F8F1EBF7AE50074E6D4 /* angleclipper.cpp */; }; + 063580A71EBF7AE50074E6D4 /* api_render.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F901EBF7AE50074E6D4 /* api_render.cpp */; }; + 063580A81EBF7AE50074E6D4 /* billboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F911EBF7AE50074E6D4 /* billboard.cpp */; }; + 063580A91EBF7AE50074E6D4 /* blockmapvisual.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F921EBF7AE50074E6D4 /* blockmapvisual.cpp */; }; + 063580AA1EBF7AE50074E6D4 /* cameralensfx.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F931EBF7AE50074E6D4 /* cameralensfx.cpp */; }; + 063580AB1EBF7AE50074E6D4 /* consoleeffect.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F941EBF7AE50074E6D4 /* consoleeffect.cpp */; }; + 063580AC1EBF7AE50074E6D4 /* decoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F951EBF7AE50074E6D4 /* decoration.cpp */; }; + 063580AD1EBF7AE50074E6D4 /* drawlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F961EBF7AE50074E6D4 /* drawlist.cpp */; }; + 063580AE1EBF7AE50074E6D4 /* drawlists.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F971EBF7AE50074E6D4 /* drawlists.cpp */; }; + 063580AF1EBF7AE50074E6D4 /* environ.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F981EBF7AE50074E6D4 /* environ.cpp */; }; + 063580B01EBF7AE50074E6D4 /* bloom.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9A1EBF7AE50074E6D4 /* bloom.cpp */; }; + 063580B11EBF7AE50074E6D4 /* colorfilter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9B1EBF7AE50074E6D4 /* colorfilter.cpp */; }; + 063580B21EBF7AE50074E6D4 /* lensflares.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9C1EBF7AE50074E6D4 /* lensflares.cpp */; }; + 063580B31EBF7AE50074E6D4 /* vignette.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9D1EBF7AE50074E6D4 /* vignette.cpp */; }; + 063580B41EBF7AE50074E6D4 /* lightdecoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9E1EBF7AE50074E6D4 /* lightdecoration.cpp */; }; + 063580B51EBF7AE50074E6D4 /* lumobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357F9F1EBF7AE50074E6D4 /* lumobj.cpp */; }; + 063580B61EBF7AE50074E6D4 /* model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA01EBF7AE50074E6D4 /* model.cpp */; }; + 063580B71EBF7AE50074E6D4 /* modelloader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA11EBF7AE50074E6D4 /* modelloader.cpp */; }; + 063580B81EBF7AE50074E6D4 /* modelrenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA21EBF7AE50074E6D4 /* modelrenderer.cpp */; }; + 063580B91EBF7AE50074E6D4 /* playerweaponanimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA31EBF7AE50074E6D4 /* playerweaponanimator.cpp */; }; + 063580BA1EBF7AE50074E6D4 /* projectionlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA41EBF7AE50074E6D4 /* projectionlist.cpp */; }; + 063580BB1EBF7AE50074E6D4 /* r_draw.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA51EBF7AE50074E6D4 /* r_draw.cpp */; }; + 063580BC1EBF7AE50074E6D4 /* r_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA61EBF7AE50074E6D4 /* r_main.cpp */; }; + 063580BD1EBF7AE50074E6D4 /* r_things.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA71EBF7AE50074E6D4 /* r_things.cpp */; }; + 063580BE1EBF7AE50074E6D4 /* rend_fakeradio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA81EBF7AE50074E6D4 /* rend_fakeradio.cpp */; }; + 063580BF1EBF7AE50074E6D4 /* rend_font.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FA91EBF7AE50074E6D4 /* rend_font.cpp */; }; + 063580C01EBF7AE50074E6D4 /* rend_halo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAA1EBF7AE50074E6D4 /* rend_halo.cpp */; }; + 063580C11EBF7AE50074E6D4 /* rend_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAB1EBF7AE50074E6D4 /* rend_main.cpp */; }; + 063580C21EBF7AE50074E6D4 /* rend_model.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAC1EBF7AE50074E6D4 /* rend_model.cpp */; }; + 063580C31EBF7AE50074E6D4 /* rend_particle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAD1EBF7AE50074E6D4 /* rend_particle.cpp */; }; + 063580C41EBF7AE50074E6D4 /* rendersystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAE1EBF7AE50074E6D4 /* rendersystem.cpp */; }; + 063580C51EBF7AE50074E6D4 /* rendpoly.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FAF1EBF7AE50074E6D4 /* rendpoly.cpp */; }; + 063580C61EBF7AE50074E6D4 /* shadervar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB01EBF7AE50074E6D4 /* shadervar.cpp */; }; + 063580C71EBF7AE50074E6D4 /* shadowedge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB11EBF7AE50074E6D4 /* shadowedge.cpp */; }; + 063580C81EBF7AE50074E6D4 /* skydrawable.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB21EBF7AE50074E6D4 /* skydrawable.cpp */; }; + 063580C91EBF7AE50074E6D4 /* skyfixedge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB31EBF7AE50074E6D4 /* skyfixedge.cpp */; }; + 063580CA1EBF7AE50074E6D4 /* stateanimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB41EBF7AE50074E6D4 /* stateanimator.cpp */; }; + 063580CB1EBF7AE50074E6D4 /* store.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB51EBF7AE50074E6D4 /* store.cpp */; }; + 063580CC1EBF7AE50074E6D4 /* trianglestripbuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB61EBF7AE50074E6D4 /* trianglestripbuilder.cpp */; }; + 063580CD1EBF7AE50074E6D4 /* vectorlightlist.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB71EBF7AE50074E6D4 /* vectorlightlist.cpp */; }; + 063580CE1EBF7AE50074E6D4 /* viewports.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB81EBF7AE50074E6D4 /* viewports.cpp */; }; + 063580CF1EBF7AE50074E6D4 /* vissprite.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FB91EBF7AE50074E6D4 /* vissprite.cpp */; }; + 063580D01EBF7AE50074E6D4 /* vr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FBA1EBF7AE50074E6D4 /* vr.cpp */; }; + 063580D11EBF7AE50074E6D4 /* walledge.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FBB1EBF7AE50074E6D4 /* walledge.cpp */; }; + 063580D21EBF7AE50074E6D4 /* wallspec.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FBC1EBF7AE50074E6D4 /* wallspec.cpp */; }; + 063580D31EBF7AE50074E6D4 /* abstractfont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FBE1EBF7AE50074E6D4 /* abstractfont.cpp */; }; + 063580D41EBF7AE50074E6D4 /* api_material.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC01EBF7AE50074E6D4 /* api_material.cpp */; }; + 063580D51EBF7AE50074E6D4 /* api_resource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC11EBF7AE50074E6D4 /* api_resource.cpp */; }; + 063580D71EBF7AE50074E6D4 /* bitmapfont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC31EBF7AE50074E6D4 /* bitmapfont.cpp */; }; + 063580D81EBF7AE50074E6D4 /* clientmaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC41EBF7AE50074E6D4 /* clientmaterial.cpp */; }; + 063580D91EBF7AE50074E6D4 /* clientresources.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC51EBF7AE50074E6D4 /* clientresources.cpp */; }; + 063580DA1EBF7AE50074E6D4 /* clienttexture.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC61EBF7AE50074E6D4 /* clienttexture.cpp */; }; + 063580DB1EBF7AE50074E6D4 /* compositebitmapfont.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC71EBF7AE50074E6D4 /* compositebitmapfont.cpp */; }; + 063580DC1EBF7AE50074E6D4 /* fontmanifest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC81EBF7AE50074E6D4 /* fontmanifest.cpp */; }; + 063580DD1EBF7AE50074E6D4 /* fonts.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FC91EBF7AE50074E6D4 /* fonts.cpp */; }; + 063580DE1EBF7AE50074E6D4 /* fontscheme.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCA1EBF7AE50074E6D4 /* fontscheme.cpp */; }; + 063580DF1EBF7AE50074E6D4 /* framemodel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCB1EBF7AE50074E6D4 /* framemodel.cpp */; }; + 063580E01EBF7AE50074E6D4 /* hq2x.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCC1EBF7AE50074E6D4 /* hq2x.cpp */; }; + 063580E11EBF7AE50074E6D4 /* idtech1image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCD1EBF7AE50074E6D4 /* idtech1image.cpp */; }; + 063580E21EBF7AE50074E6D4 /* image.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCE1EBF7AE50074E6D4 /* image.cpp */; }; + 063580E31EBF7AE50074E6D4 /* lightmaterialdecoration.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FCF1EBF7AE50074E6D4 /* lightmaterialdecoration.cpp */; }; + 063580E41EBF7AE50074E6D4 /* materialanimator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD01EBF7AE50074E6D4 /* materialanimator.cpp */; }; + 063580E51EBF7AE50074E6D4 /* texturevariant.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD11EBF7AE50074E6D4 /* texturevariant.cpp */; }; + 063580E61EBF7AE50074E6D4 /* alertmask.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD31EBF7AE50074E6D4 /* alertmask.cpp */; }; + 063580E71EBF7AE50074E6D4 /* axisinputcontrol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD41EBF7AE50074E6D4 /* axisinputcontrol.cpp */; }; + 063580E81EBF7AE50074E6D4 /* b_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD51EBF7AE50074E6D4 /* b_main.cpp */; }; + 063580E91EBF7AE50074E6D4 /* b_util.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD61EBF7AE50074E6D4 /* b_util.cpp */; }; + 063580EA1EBF7AE50074E6D4 /* bindcontext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD71EBF7AE50074E6D4 /* bindcontext.cpp */; }; + 063580EB1EBF7AE50074E6D4 /* binding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD81EBF7AE50074E6D4 /* binding.cpp */; }; + 063580EC1EBF7AE50074E6D4 /* busyvisual.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FD91EBF7AE50074E6D4 /* busyvisual.cpp */; }; + 063580ED1EBF7AE50074E6D4 /* buttoninputcontrol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDA1EBF7AE50074E6D4 /* buttoninputcontrol.cpp */; }; + 063580EE1EBF7AE50074E6D4 /* clientrootwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDB1EBF7AE50074E6D4 /* clientrootwidget.cpp */; }; + 063580EF1EBF7AE50074E6D4 /* clientstyle.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDC1EBF7AE50074E6D4 /* clientstyle.cpp */; }; + 063580F01EBF7AE50074E6D4 /* clientwindow.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDD1EBF7AE50074E6D4 /* clientwindow.cpp */; }; + 063580F11EBF7AE50074E6D4 /* clientwindowsystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDE1EBF7AE50074E6D4 /* clientwindowsystem.cpp */; }; + 063580F21EBF7AE50074E6D4 /* commandaction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FDF1EBF7AE50074E6D4 /* commandaction.cpp */; }; + 063580F31EBF7AE50074E6D4 /* commandbinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE01EBF7AE50074E6D4 /* commandbinding.cpp */; }; + 063580F41EBF7AE50074E6D4 /* controllerpresets.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE11EBF7AE50074E6D4 /* controllerpresets.cpp */; }; + 063580F51EBF7AE50074E6D4 /* aboutdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE31EBF7AE50074E6D4 /* aboutdialog.cpp */; }; + 063580F61EBF7AE50074E6D4 /* alertdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE41EBF7AE50074E6D4 /* alertdialog.cpp */; }; + 063580F71EBF7AE50074E6D4 /* audiosettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE51EBF7AE50074E6D4 /* audiosettingsdialog.cpp */; }; + 063580F81EBF7AE50074E6D4 /* coloradjustmentdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE61EBF7AE50074E6D4 /* coloradjustmentdialog.cpp */; }; + 063580F91EBF7AE50074E6D4 /* createprofiledialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE71EBF7AE50074E6D4 /* createprofiledialog.cpp */; }; + 063580FA1EBF7AE50074E6D4 /* datafilesettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE81EBF7AE50074E6D4 /* datafilesettingsdialog.cpp */; }; + 063580FB1EBF7AE50074E6D4 /* inputsettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FE91EBF7AE50074E6D4 /* inputsettingsdialog.cpp */; }; + 063580FC1EBF7AE50074E6D4 /* logsettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FEA1EBF7AE50074E6D4 /* logsettingsdialog.cpp */; }; + 063580FD1EBF7AE50074E6D4 /* manualconnectiondialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FEB1EBF7AE50074E6D4 /* manualconnectiondialog.cpp */; }; + 063580FE1EBF7AE50074E6D4 /* networksettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FEC1EBF7AE50074E6D4 /* networksettingsdialog.cpp */; }; + 063580FF1EBF7AE50074E6D4 /* packagecompatibilitydialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FED1EBF7AE50074E6D4 /* packagecompatibilitydialog.cpp */; }; + 063581001EBF7AE50074E6D4 /* packageinfodialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FEE1EBF7AE50074E6D4 /* packageinfodialog.cpp */; }; + 063581011EBF7AE50074E6D4 /* packagesdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FEF1EBF7AE50074E6D4 /* packagesdialog.cpp */; }; + 063581021EBF7AE50074E6D4 /* renderersettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF01EBF7AE50074E6D4 /* renderersettingsdialog.cpp */; }; + 063581031EBF7AE50074E6D4 /* serverinfodialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF11EBF7AE50074E6D4 /* serverinfodialog.cpp */; }; + 063581041EBF7AE50074E6D4 /* uisettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF21EBF7AE50074E6D4 /* uisettingsdialog.cpp */; }; + 063581051EBF7AE50074E6D4 /* videosettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF31EBF7AE50074E6D4 /* videosettingsdialog.cpp */; }; + 063581061EBF7AE50074E6D4 /* vrsettingsdialog.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF41EBF7AE50074E6D4 /* vrsettingsdialog.cpp */; }; + 063581071EBF7AE50074E6D4 /* modelasseteditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF61EBF7AE50074E6D4 /* modelasseteditor.cpp */; }; + 063581081EBF7AE50074E6D4 /* rendererappearanceeditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF71EBF7AE50074E6D4 /* rendererappearanceeditor.cpp */; }; + 063581091EBF7AE50074E6D4 /* variablegroupeditor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF81EBF7AE50074E6D4 /* variablegroupeditor.cpp */; }; + 0635810A1EBF7AE50074E6D4 /* hatinputcontrol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FF91EBF7AE50074E6D4 /* hatinputcontrol.cpp */; }; + 0635810B1EBF7AE50074E6D4 /* columnwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FFB1EBF7AE50074E6D4 /* columnwidget.cpp */; }; + 0635810C1EBF7AE50074E6D4 /* gamecolumnwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FFC1EBF7AE50074E6D4 /* gamecolumnwidget.cpp */; }; + 0635810D1EBF7AE50074E6D4 /* gamepanelbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FFD1EBF7AE50074E6D4 /* gamepanelbuttonwidget.cpp */; }; + 0635810E1EBF7AE50074E6D4 /* headerwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FFE1EBF7AE50074E6D4 /* headerwidget.cpp */; }; + 0635810F1EBF7AE50074E6D4 /* homewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 06357FFF1EBF7AE50074E6D4 /* homewidget.cpp */; }; + 063581101EBF7AE50074E6D4 /* multiplayercolumnwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580001EBF7AE50074E6D4 /* multiplayercolumnwidget.cpp */; }; + 063581111EBF7AE50074E6D4 /* multiplayerpanelbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580011EBF7AE50074E6D4 /* multiplayerpanelbuttonwidget.cpp */; }; + 063581121EBF7AE50074E6D4 /* nogamescolumnwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580021EBF7AE50074E6D4 /* nogamescolumnwidget.cpp */; }; + 063581131EBF7AE50074E6D4 /* packagescolumnwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580031EBF7AE50074E6D4 /* packagescolumnwidget.cpp */; }; + 063581141EBF7AE50074E6D4 /* savelistwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580041EBF7AE50074E6D4 /* savelistwidget.cpp */; }; + 063581151EBF7AE50074E6D4 /* impulsebinding.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580051EBF7AE50074E6D4 /* impulsebinding.cpp */; }; + 063581161EBF7AE50074E6D4 /* finale.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580071EBF7AE50074E6D4 /* finale.cpp */; }; + 063581171EBF7AE50074E6D4 /* finaleanimwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580081EBF7AE50074E6D4 /* finaleanimwidget.cpp */; }; + 063581181EBF7AE50074E6D4 /* finaleinterpreter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580091EBF7AE50074E6D4 /* finaleinterpreter.cpp */; }; + 063581191EBF7AE50074E6D4 /* finalepagewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800A1EBF7AE50074E6D4 /* finalepagewidget.cpp */; }; + 0635811A1EBF7AE50074E6D4 /* finaletextwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800B1EBF7AE50074E6D4 /* finaletextwidget.cpp */; }; + 0635811B1EBF7AE50074E6D4 /* finalewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800C1EBF7AE50074E6D4 /* finalewidget.cpp */; }; + 0635811C1EBF7AE50074E6D4 /* infinesystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800D1EBF7AE50074E6D4 /* infinesystem.cpp */; }; + 0635811D1EBF7AE50074E6D4 /* inputdebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800E1EBF7AE50074E6D4 /* inputdebug.cpp */; }; + 0635811E1EBF7AE50074E6D4 /* inputdevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635800F1EBF7AE50074E6D4 /* inputdevice.cpp */; }; + 0635811F1EBF7AE50074E6D4 /* inputsystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580101EBF7AE50074E6D4 /* inputsystem.cpp */; }; + 063581201EBF7AE50074E6D4 /* mouse_qt.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580111EBF7AE50074E6D4 /* mouse_qt.cpp */; }; + 063581211EBF7AE50074E6D4 /* nativemenu.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580121EBF7AE50074E6D4 /* nativemenu.cpp */; }; + 063581221EBF7AE50074E6D4 /* nativeui.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580131EBF7AE50074E6D4 /* nativeui.cpp */; }; + 063581231EBF7AE50074E6D4 /* postprocessing.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580141EBF7AE50074E6D4 /* postprocessing.cpp */; }; + 063581241EBF7AE50074E6D4 /* progress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580151EBF7AE50074E6D4 /* progress.cpp */; }; + 063581251EBF7AE50074E6D4 /* savelistdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580161EBF7AE50074E6D4 /* savelistdata.cpp */; }; + 063581271EBF7AE50074E6D4 /* styledlogsinkformatter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580181EBF7AE50074E6D4 /* styledlogsinkformatter.cpp */; }; + 063581281EBF7AE50074E6D4 /* sys_input.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580191EBF7AE50074E6D4 /* sys_input.cpp */; }; + 063581291EBF7AE50074E6D4 /* ui_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635801A1EBF7AE50074E6D4 /* ui_main.cpp */; }; + 0635812A1EBF7AE50074E6D4 /* viewcompositor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635801B1EBF7AE50074E6D4 /* viewcompositor.cpp */; }; + 0635812B1EBF7AE50074E6D4 /* busywidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635801D1EBF7AE50074E6D4 /* busywidget.cpp */; }; + 0635812C1EBF7AE50074E6D4 /* consolecommandwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635801E1EBF7AE50074E6D4 /* consolecommandwidget.cpp */; }; + 0635812D1EBF7AE50074E6D4 /* consolewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635801F1EBF7AE50074E6D4 /* consolewidget.cpp */; }; + 0635812E1EBF7AE50074E6D4 /* cvarchoicewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580201EBF7AE50074E6D4 /* cvarchoicewidget.cpp */; }; + 0635812F1EBF7AE50074E6D4 /* cvarlineeditwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580211EBF7AE50074E6D4 /* cvarlineeditwidget.cpp */; }; + 063581301EBF7AE50074E6D4 /* cvarnativepathwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580221EBF7AE50074E6D4 /* cvarnativepathwidget.cpp */; }; + 063581311EBF7AE50074E6D4 /* cvarsliderwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580231EBF7AE50074E6D4 /* cvarsliderwidget.cpp */; }; + 063581321EBF7AE50074E6D4 /* cvartogglewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580241EBF7AE50074E6D4 /* cvartogglewidget.cpp */; }; + 063581331EBF7AE50074E6D4 /* gamewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580251EBF7AE50074E6D4 /* gamewidget.cpp */; }; + 063581341EBF7AE50074E6D4 /* homeitemwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580261EBF7AE50074E6D4 /* homeitemwidget.cpp */; }; + 063581351EBF7AE50074E6D4 /* homemenuwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580271EBF7AE50074E6D4 /* homemenuwidget.cpp */; }; + 063581361EBF7AE50074E6D4 /* inputbindingwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580281EBF7AE50074E6D4 /* inputbindingwidget.cpp */; }; + 063581371EBF7AE50074E6D4 /* keygrabberwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580291EBF7AE50074E6D4 /* keygrabberwidget.cpp */; }; + 063581381EBF7AE50074E6D4 /* mapoutlinewidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802A1EBF7AE50074E6D4 /* mapoutlinewidget.cpp */; }; + 063581391EBF7AE50074E6D4 /* multiplayerservermenuwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802B1EBF7AE50074E6D4 /* multiplayerservermenuwidget.cpp */; }; + 0635813A1EBF7AE50074E6D4 /* multiplayerstatuswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802C1EBF7AE50074E6D4 /* multiplayerstatuswidget.cpp */; }; + 0635813B1EBF7AE50074E6D4 /* packagecontentoptionswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802D1EBF7AE50074E6D4 /* packagecontentoptionswidget.cpp */; }; + 0635813C1EBF7AE50074E6D4 /* packagesbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802E1EBF7AE50074E6D4 /* packagesbuttonwidget.cpp */; }; + 0635813D1EBF7AE50074E6D4 /* packagessidebarwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635802F1EBF7AE50074E6D4 /* packagessidebarwidget.cpp */; }; + 0635813E1EBF7AE50074E6D4 /* packageswidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580301EBF7AE50074E6D4 /* packageswidget.cpp */; }; + 0635813F1EBF7AE50074E6D4 /* panelbuttonwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580311EBF7AE50074E6D4 /* panelbuttonwidget.cpp */; }; + 063581401EBF7AE50074E6D4 /* privilegedlogwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580321EBF7AE50074E6D4 /* privilegedlogwidget.cpp */; }; + 063581411EBF7AE50074E6D4 /* profilepickerwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580331EBF7AE50074E6D4 /* profilepickerwidget.cpp */; }; + 063581421EBF7AE50074E6D4 /* sidebarwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580341EBF7AE50074E6D4 /* sidebarwidget.cpp */; }; + 063581431EBF7AE50074E6D4 /* taskbarwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580351EBF7AE50074E6D4 /* taskbarwidget.cpp */; }; + 063581441EBF7AE50074E6D4 /* tutorialwidget.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580361EBF7AE50074E6D4 /* tutorialwidget.cpp */; }; + 063581451EBF7AE50074E6D4 /* zonedebug.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580371EBF7AE50074E6D4 /* zonedebug.cpp */; }; + 063581461EBF7AE50074E6D4 /* dd_uinit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580391EBF7AE50074E6D4 /* dd_uinit.cpp */; }; + 063581471EBF7AE50074E6D4 /* joystick.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635803A1EBF7AE50074E6D4 /* joystick.cpp */; }; + 063581481EBF7AE50074E6D4 /* bindings_world.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635803D1EBF7AE50074E6D4 /* bindings_world.cpp */; }; + 063581491EBF7AE50074E6D4 /* blockmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635803E1EBF7AE50074E6D4 /* blockmap.cpp */; }; + 0635814A1EBF7AE50074E6D4 /* bspleaf.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635803F1EBF7AE50074E6D4 /* bspleaf.cpp */; }; + 0635814B1EBF7AE50074E6D4 /* clientserverworld.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580401EBF7AE50074E6D4 /* clientserverworld.cpp */; }; + 0635814C1EBF7AE50074E6D4 /* convexsubspace.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580411EBF7AE50074E6D4 /* convexsubspace.cpp */; }; + 0635814D1EBF7AE50074E6D4 /* impulseaccumulator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580421EBF7AE50074E6D4 /* impulseaccumulator.cpp */; }; + 0635814E1EBF7AE50074E6D4 /* interceptor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580431EBF7AE50074E6D4 /* interceptor.cpp */; }; + 0635814F1EBF7AE50074E6D4 /* line.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580441EBF7AE50074E6D4 /* line.cpp */; }; + 063581501EBF7AE50074E6D4 /* lineblockmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580451EBF7AE50074E6D4 /* lineblockmap.cpp */; }; + 063581511EBF7AE50074E6D4 /* linesighttest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580461EBF7AE50074E6D4 /* linesighttest.cpp */; }; + 063581521EBF7AE50074E6D4 /* map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580471EBF7AE50074E6D4 /* map.cpp */; }; + 063581531EBF7AE50074E6D4 /* maputil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580481EBF7AE50074E6D4 /* maputil.cpp */; }; + 063581541EBF7AE50074E6D4 /* p_mobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580491EBF7AE50074E6D4 /* p_mobj.cpp */; }; + 063581551EBF7AE50074E6D4 /* p_players.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804A1EBF7AE50074E6D4 /* p_players.cpp */; }; + 063581561EBF7AE50074E6D4 /* p_ticker.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804B1EBF7AE50074E6D4 /* p_ticker.cpp */; }; + 063581571EBF7AE50074E6D4 /* plane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804C1EBF7AE50074E6D4 /* plane.cpp */; }; + 063581581EBF7AE50074E6D4 /* polyobj.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804D1EBF7AE50074E6D4 /* polyobj.cpp */; }; + 063581591EBF7AE50074E6D4 /* polyobjdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804E1EBF7AE50074E6D4 /* polyobjdata.cpp */; }; + 0635815A1EBF7AE50074E6D4 /* reject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635804F1EBF7AE50074E6D4 /* reject.cpp */; }; + 0635815C1EBF7AE50074E6D4 /* sector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580511EBF7AE50074E6D4 /* sector.cpp */; }; + 0635815D1EBF7AE50074E6D4 /* sky.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580521EBF7AE50074E6D4 /* sky.cpp */; }; + 0635815E1EBF7AE50074E6D4 /* subsector.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580531EBF7AE50074E6D4 /* subsector.cpp */; }; + 0635815F1EBF7AE50074E6D4 /* surface.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580541EBF7AE50074E6D4 /* surface.cpp */; }; + 063581601EBF7AE50074E6D4 /* thinkers.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580551EBF7AE50074E6D4 /* thinkers.cpp */; }; + 063581611EBF7AE50074E6D4 /* vertex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580561EBF7AE50074E6D4 /* vertex.cpp */; }; + 063581621EBF7AE50074E6D4 /* convexsubspaceproxy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580581EBF7AE50074E6D4 /* convexsubspaceproxy.cpp */; }; + 063581631EBF7AE50074E6D4 /* hplane.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580591EBF7AE50074E6D4 /* hplane.cpp */; }; + 063581641EBF7AE50074E6D4 /* linesegment.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805A1EBF7AE50074E6D4 /* linesegment.cpp */; }; + 063581651EBF7AE50074E6D4 /* partitioner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805B1EBF7AE50074E6D4 /* partitioner.cpp */; }; + 063581661EBF7AE50074E6D4 /* partitionevaluator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805C1EBF7AE50074E6D4 /* partitionevaluator.cpp */; }; + 063581671EBF7AE50074E6D4 /* superblockmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805D1EBF7AE50074E6D4 /* superblockmap.cpp */; }; + 063581681EBF7AE50074E6D4 /* clientmobjthinkerdata.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805E1EBF7AE50074E6D4 /* clientmobjthinkerdata.cpp */; }; + 063581691EBF7AE50074E6D4 /* contact.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635805F1EBF7AE50074E6D4 /* contact.cpp */; }; + 0635816A1EBF7AE50074E6D4 /* contactspreader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580601EBF7AE50074E6D4 /* contactspreader.cpp */; }; + 0635816B1EBF7AE50074E6D4 /* generator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580611EBF7AE50074E6D4 /* generator.cpp */; }; + 0635816C1EBF7AE50074E6D4 /* mapobject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580621EBF7AE50074E6D4 /* mapobject.cpp */; }; + 0635816D1EBF7AE50074E6D4 /* api_console.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580631EBF7AE50074E6D4 /* api_console.cpp */; }; + 0635816E1EBF7AE50074E6D4 /* api_filesys.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580641EBF7AE50074E6D4 /* api_filesys.cpp */; }; + 0635816F1EBF7AE50074E6D4 /* api_map.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580651EBF7AE50074E6D4 /* api_map.cpp */; }; + 063581701EBF7AE50074E6D4 /* api_mapedit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580661EBF7AE50074E6D4 /* api_mapedit.cpp */; }; + 063581711EBF7AE50074E6D4 /* api_uri.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580671EBF7AE50074E6D4 /* api_uri.cpp */; }; + 063581721EBF7AE50074E6D4 /* busyrunner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580681EBF7AE50074E6D4 /* busyrunner.cpp */; }; + 063581731EBF7AE50074E6D4 /* clientapp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580691EBF7AE50074E6D4 /* clientapp.cpp */; }; + 063581741EBF7AE50074E6D4 /* clientplayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806A1EBF7AE50074E6D4 /* clientplayer.cpp */; }; + 063581751EBF7AE50074E6D4 /* con_config.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806B1EBF7AE50074E6D4 /* con_config.cpp */; }; + 063581761EBF7AE50074E6D4 /* configprofiles.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806C1EBF7AE50074E6D4 /* configprofiles.cpp */; }; + 063581771EBF7AE50074E6D4 /* dd_loop.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806D1EBF7AE50074E6D4 /* dd_loop.cpp */; }; + 063581781EBF7AE50074E6D4 /* dd_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806E1EBF7AE50074E6D4 /* dd_main.cpp */; }; + 063581791EBF7AE50074E6D4 /* dd_pinit.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635806F1EBF7AE50074E6D4 /* dd_pinit.cpp */; }; + 0635817A1EBF7AE50074E6D4 /* def_main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580701EBF7AE50074E6D4 /* def_main.cpp */; }; + 0635817B1EBF7AE50074E6D4 /* localplayer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580711EBF7AE50074E6D4 /* localplayer.cpp */; }; + 0635817C1EBF7AE50074E6D4 /* main_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580721EBF7AE50074E6D4 /* main_client.cpp */; }; + 0635817D1EBF7AE50074E6D4 /* sys_system.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063580731EBF7AE50074E6D4 /* sys_system.cpp */; }; + 0635817F1EBF87040074E6D4 /* libz.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = 0635817E1EBF87040074E6D4 /* libz.tbd */; }; + 0635818A1EBFB5680074E6D4 /* deng_core_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063581891EBFB5680074E6D4 /* deng_core_moc_compilation.cpp */; }; + 0635818C1EBFB5C90074E6D4 /* deng_shell_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635818B1EBFB5C90074E6D4 /* deng_shell_moc_compilation.cpp */; }; + 063581931EBFB6B80074E6D4 /* deng_gui_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063581921EBFB6B80074E6D4 /* deng_gui_moc_compilation.cpp */; }; + 063581951EBFB6D30074E6D4 /* deng_appfw_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063581941EBFB6D30074E6D4 /* deng_appfw_moc_compilation.cpp */; }; + 063581971EBFB6F10074E6D4 /* deng_legacy_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063581961EBFB6F10074E6D4 /* deng_legacy_moc_compilation.cpp */; }; + 063581991EBFB7620074E6D4 /* Doomsday_moc_compilation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063581981EBFB7620074E6D4 /* Doomsday_moc_compilation.cpp */; }; + 0635824B1EBFBA5F0074E6D4 /* libassimp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 063582481EBFBA120074E6D4 /* libassimp.a */; }; + 0635824D1EBFBB960074E6D4 /* Assimp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635824C1EBFBB960074E6D4 /* Assimp.cpp */; }; + 0635824F1EBFBBB40074E6D4 /* DefaultLogger.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635824E1EBFBBB30074E6D4 /* DefaultLogger.cpp */; }; + 063582511EBFBBCC0074E6D4 /* BaseImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582501EBFBBCC0074E6D4 /* BaseImporter.cpp */; }; + 063582531EBFBBDB0074E6D4 /* BaseProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582521EBFBBDB0074E6D4 /* BaseProcess.cpp */; }; + 063582551EBFBBF10074E6D4 /* PostStepRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582541EBFBBF10074E6D4 /* PostStepRegistry.cpp */; }; + 063582571EBFBBFA0074E6D4 /* ImporterRegistry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582561EBFBBFA0074E6D4 /* ImporterRegistry.cpp */; }; + 0635825A1EBFBC1C0074E6D4 /* DefaultIOStream.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582581EBFBC1C0074E6D4 /* DefaultIOStream.cpp */; }; + 0635825B1EBFBC1C0074E6D4 /* DefaultIOSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582591EBFBC1C0074E6D4 /* DefaultIOSystem.cpp */; }; + 0635825D1EBFBC2A0074E6D4 /* Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635825C1EBFBC2A0074E6D4 /* Importer.cpp */; }; + 0635826B1EBFBC8D0074E6D4 /* Bitmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635825E1EBFBC8D0074E6D4 /* Bitmap.cpp */; }; + 0635826C1EBFBC8D0074E6D4 /* RemoveComments.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635825F1EBFBC8D0074E6D4 /* RemoveComments.cpp */; }; + 0635826D1EBFBC8D0074E6D4 /* SceneCombiner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582601EBFBC8D0074E6D4 /* SceneCombiner.cpp */; }; + 0635826E1EBFBC8D0074E6D4 /* ScenePreprocessor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582611EBFBC8D0074E6D4 /* ScenePreprocessor.cpp */; }; + 0635826F1EBFBC8D0074E6D4 /* SGSpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582621EBFBC8D0074E6D4 /* SGSpatialSort.cpp */; }; + 063582701EBFBC8D0074E6D4 /* SkeletonMeshBuilder.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582631EBFBC8D0074E6D4 /* SkeletonMeshBuilder.cpp */; }; + 063582711EBFBC8D0074E6D4 /* SpatialSort.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582641EBFBC8D0074E6D4 /* SpatialSort.cpp */; }; + 063582721EBFBC8D0074E6D4 /* SplitByBoneCountProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582651EBFBC8D0074E6D4 /* SplitByBoneCountProcess.cpp */; }; + 063582731EBFBC8D0074E6D4 /* StandardShapes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582661EBFBC8D0074E6D4 /* StandardShapes.cpp */; }; + 063582741EBFBC8D0074E6D4 /* Subdivision.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582671EBFBC8D0074E6D4 /* Subdivision.cpp */; }; + 063582751EBFBC8D0074E6D4 /* TargetAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582681EBFBC8D0074E6D4 /* TargetAnimation.cpp */; }; + 063582761EBFBC8D0074E6D4 /* Version.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582691EBFBC8D0074E6D4 /* Version.cpp */; }; + 063582771EBFBC8D0074E6D4 /* VertexTriangleAdjacency.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635826A1EBFBC8D0074E6D4 /* VertexTriangleAdjacency.cpp */; }; + 0635827B1EBFBCB50074E6D4 /* 3DSConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582781EBFBCB50074E6D4 /* 3DSConverter.cpp */; }; + 0635827C1EBFBCB50074E6D4 /* 3DSExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582791EBFBCB50074E6D4 /* 3DSExporter.cpp */; }; + 0635827D1EBFBCB50074E6D4 /* 3DSLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635827A1EBFBCB50074E6D4 /* 3DSLoader.cpp */; }; + 063582821EBFBCE10074E6D4 /* ColladaExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635827F1EBFBCE10074E6D4 /* ColladaExporter.cpp */; }; + 063582831EBFBCE10074E6D4 /* ColladaLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582801EBFBCE10074E6D4 /* ColladaLoader.cpp */; }; + 063582841EBFBCE10074E6D4 /* ColladaParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582811EBFBCE10074E6D4 /* ColladaParser.cpp */; }; + 063582891EBFBD0C0074E6D4 /* MD2Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582851EBFBD0C0074E6D4 /* MD2Loader.cpp */; }; + 0635828A1EBFBD0C0074E6D4 /* MD3Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582861EBFBD0C0074E6D4 /* MD3Loader.cpp */; }; + 0635828B1EBFBD0C0074E6D4 /* MD5Loader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582871EBFBD0C0074E6D4 /* MD5Loader.cpp */; }; + 0635828C1EBFBD0C0074E6D4 /* MD5Parser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582881EBFBD0C0074E6D4 /* MD5Parser.cpp */; }; + 0635828F1EBFBD1D0074E6D4 /* MDLLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635828D1EBFBD1D0074E6D4 /* MDLLoader.cpp */; }; + 063582901EBFBD1D0074E6D4 /* MDLMaterialLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635828E1EBFBD1D0074E6D4 /* MDLMaterialLoader.cpp */; }; + 063582951EBFBD2C0074E6D4 /* ObjExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582911EBFBD2C0074E6D4 /* ObjExporter.cpp */; }; + 063582961EBFBD2C0074E6D4 /* ObjFileImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582921EBFBD2C0074E6D4 /* ObjFileImporter.cpp */; }; + 063582971EBFBD2C0074E6D4 /* ObjFileMtlImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582931EBFBD2C0074E6D4 /* ObjFileMtlImporter.cpp */; }; + 063582981EBFBD2C0074E6D4 /* ObjFileParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582941EBFBD2C0074E6D4 /* ObjFileParser.cpp */; }; + 0635829F1EBFBD4D0074E6D4 /* BlenderBMesh.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582991EBFBD4D0074E6D4 /* BlenderBMesh.cpp */; }; + 063582A01EBFBD4D0074E6D4 /* BlenderDNA.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635829A1EBFBD4D0074E6D4 /* BlenderDNA.cpp */; }; + 063582A11EBFBD4D0074E6D4 /* BlenderLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635829B1EBFBD4D0074E6D4 /* BlenderLoader.cpp */; }; + 063582A21EBFBD4D0074E6D4 /* BlenderModifier.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635829C1EBFBD4D0074E6D4 /* BlenderModifier.cpp */; }; + 063582A31EBFBD4D0074E6D4 /* BlenderScene.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635829D1EBFBD4D0074E6D4 /* BlenderScene.cpp */; }; + 063582A41EBFBD4D0074E6D4 /* BlenderTessellator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0635829E1EBFBD4D0074E6D4 /* BlenderTessellator.cpp */; }; + 063582B41EBFBD700074E6D4 /* FBXAnimation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582A51EBFBD700074E6D4 /* FBXAnimation.cpp */; }; + 063582B51EBFBD700074E6D4 /* FBXBinaryTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582A61EBFBD700074E6D4 /* FBXBinaryTokenizer.cpp */; }; + 063582B61EBFBD700074E6D4 /* FBXConverter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582A71EBFBD700074E6D4 /* FBXConverter.cpp */; }; + 063582B71EBFBD700074E6D4 /* FBXDeformer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582A81EBFBD700074E6D4 /* FBXDeformer.cpp */; }; + 063582B81EBFBD700074E6D4 /* FBXDocument.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582A91EBFBD700074E6D4 /* FBXDocument.cpp */; }; + 063582B91EBFBD700074E6D4 /* FBXDocumentUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AA1EBFBD700074E6D4 /* FBXDocumentUtil.cpp */; }; + 063582BA1EBFBD700074E6D4 /* FBXImporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AB1EBFBD700074E6D4 /* FBXImporter.cpp */; }; + 063582BB1EBFBD700074E6D4 /* FBXMaterial.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AC1EBFBD700074E6D4 /* FBXMaterial.cpp */; }; + 063582BC1EBFBD700074E6D4 /* FBXMeshGeometry.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AD1EBFBD700074E6D4 /* FBXMeshGeometry.cpp */; }; + 063582BD1EBFBD700074E6D4 /* FBXModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AE1EBFBD700074E6D4 /* FBXModel.cpp */; }; + 063582BE1EBFBD700074E6D4 /* FBXNodeAttribute.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582AF1EBFBD700074E6D4 /* FBXNodeAttribute.cpp */; }; + 063582BF1EBFBD700074E6D4 /* FBXParser.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582B01EBFBD700074E6D4 /* FBXParser.cpp */; }; + 063582C01EBFBD700074E6D4 /* FBXProperties.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582B11EBFBD700074E6D4 /* FBXProperties.cpp */; }; + 063582C11EBFBD700074E6D4 /* FBXTokenizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582B21EBFBD700074E6D4 /* FBXTokenizer.cpp */; }; + 063582C21EBFBD700074E6D4 /* FBXUtil.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582B31EBFBD700074E6D4 /* FBXUtil.cpp */; }; + 063582C61EBFBD860074E6D4 /* IRRLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582C31EBFBD860074E6D4 /* IRRLoader.cpp */; }; + 063582C71EBFBD860074E6D4 /* IRRMeshLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582C41EBFBD860074E6D4 /* IRRMeshLoader.cpp */; }; + 063582C81EBFBD860074E6D4 /* IRRShared.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582C51EBFBD860074E6D4 /* IRRShared.cpp */; }; + 063582CA1EBFBE4B0074E6D4 /* MaterialSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582C91EBFBE4B0074E6D4 /* MaterialSystem.cpp */; }; + 063582D21EBFBF560074E6D4 /* ComputeUVMappingProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582CB1EBFBF560074E6D4 /* ComputeUVMappingProcess.cpp */; }; + 063582D31EBFBF560074E6D4 /* ConvertToLHProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582CC1EBFBF560074E6D4 /* ConvertToLHProcess.cpp */; }; + 063582D41EBFBF560074E6D4 /* DeboneProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582CD1EBFBF560074E6D4 /* DeboneProcess.cpp */; }; + 063582D51EBFBF560074E6D4 /* FindDegenerates.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582CE1EBFBF560074E6D4 /* FindDegenerates.cpp */; }; + 063582D61EBFBF560074E6D4 /* FindInstancesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582CF1EBFBF560074E6D4 /* FindInstancesProcess.cpp */; }; + 063582D71EBFBF560074E6D4 /* FindInvalidDataProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582D01EBFBF560074E6D4 /* FindInvalidDataProcess.cpp */; }; + 063582D81EBFBF560074E6D4 /* FixNormalsStep.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582D11EBFBF560074E6D4 /* FixNormalsStep.cpp */; }; + 063582EA1EBFBFB80074E6D4 /* GenFaceNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582D91EBFBFB80074E6D4 /* GenFaceNormalsProcess.cpp */; }; + 063582EB1EBFBFB80074E6D4 /* GenVertexNormalsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DA1EBFBFB80074E6D4 /* GenVertexNormalsProcess.cpp */; }; + 063582EC1EBFBFB80074E6D4 /* ImproveCacheLocality.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DB1EBFBFB80074E6D4 /* ImproveCacheLocality.cpp */; }; + 063582ED1EBFBFB80074E6D4 /* JoinVerticesProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DC1EBFBFB80074E6D4 /* JoinVerticesProcess.cpp */; }; + 063582EE1EBFBFB80074E6D4 /* LimitBoneWeightsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DD1EBFBFB80074E6D4 /* LimitBoneWeightsProcess.cpp */; }; + 063582EF1EBFBFB80074E6D4 /* MakeVerboseFormat.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DE1EBFBFB80074E6D4 /* MakeVerboseFormat.cpp */; }; + 063582F01EBFBFB80074E6D4 /* OptimizeGraph.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582DF1EBFBFB80074E6D4 /* OptimizeGraph.cpp */; }; + 063582F11EBFBFB80074E6D4 /* OptimizeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E01EBFBFB80074E6D4 /* OptimizeMeshes.cpp */; }; + 063582F21EBFBFB80074E6D4 /* PretransformVertices.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E11EBFBFB80074E6D4 /* PretransformVertices.cpp */; }; + 063582F31EBFBFB80074E6D4 /* ProcessHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E21EBFBFB80074E6D4 /* ProcessHelper.cpp */; }; + 063582F41EBFBFB80074E6D4 /* RemoveRedundantMaterials.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E31EBFBFB80074E6D4 /* RemoveRedundantMaterials.cpp */; }; + 063582F51EBFBFB80074E6D4 /* RemoveVCProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E41EBFBFB80074E6D4 /* RemoveVCProcess.cpp */; }; + 063582F61EBFBFB80074E6D4 /* SortByPTypeProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E51EBFBFB80074E6D4 /* SortByPTypeProcess.cpp */; }; + 063582F71EBFBFB80074E6D4 /* SplitLargeMeshes.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E61EBFBFB80074E6D4 /* SplitLargeMeshes.cpp */; }; + 063582F81EBFBFB80074E6D4 /* TextureTransform.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E71EBFBFB80074E6D4 /* TextureTransform.cpp */; }; + 063582F91EBFBFB80074E6D4 /* TriangulateProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E81EBFBFB80074E6D4 /* TriangulateProcess.cpp */; }; + 063582FA1EBFBFB80074E6D4 /* ValidateDataStructure.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582E91EBFBFB80074E6D4 /* ValidateDataStructure.cpp */; }; + 063582FC1EBFBFCA0074E6D4 /* CalcTangentsProcess.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582FB1EBFBFCA0074E6D4 /* CalcTangentsProcess.cpp */; }; + 063582FE1EBFC03B0074E6D4 /* StepExporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582FD1EBFC03B0074E6D4 /* StepExporter.cpp */; }; + 063583001EBFC0510074E6D4 /* Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063582FF1EBFC0510074E6D4 /* Exporter.cpp */; }; + 063583021EBFC0670074E6D4 /* AssimpCExport.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063583011EBFC0670074E6D4 /* AssimpCExport.cpp */; }; + 063583041EC036B40074E6D4 /* irrXML.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063583031EC036B40074E6D4 /* irrXML.cpp */; }; + 063583061EC036CC0074E6D4 /* ConvertUTF.c in Sources */ = {isa = PBXBuildFile; fileRef = 063583051EC036CC0074E6D4 /* ConvertUTF.c */; }; + 063583111EC044DF0074E6D4 /* doomsday.pk3 in Resources */ = {isa = PBXBuildFile; fileRef = 063583101EC044DF0074E6D4 /* doomsday.pk3 */; }; + 063583161EC0452B0074E6D4 /* libdoom.pk3 in Resources */ = {isa = PBXBuildFile; fileRef = 063583121EC045220074E6D4 /* libdoom.pk3 */; }; + 063583171EC0452B0074E6D4 /* libdoom64.pk3 in Resources */ = {isa = PBXBuildFile; fileRef = 063583131EC045220074E6D4 /* libdoom64.pk3 */; }; + 063583181EC0452B0074E6D4 /* libheretic.pk3 in Resources */ = {isa = PBXBuildFile; fileRef = 063583141EC045220074E6D4 /* libheretic.pk3 */; }; + 063583191EC0452B0074E6D4 /* libhexen.pk3 in Resources */ = {isa = PBXBuildFile; fileRef = 063583151EC045220074E6D4 /* libhexen.pk3 */; }; + 0635831E1EC069B70074E6D4 /* net.dengine.base.pack in Resources */ = {isa = PBXBuildFile; fileRef = 0635831A1EC069B70074E6D4 /* net.dengine.base.pack */; }; + 0635831F1EC069B70074E6D4 /* net.dengine.client.pack in Resources */ = {isa = PBXBuildFile; fileRef = 0635831B1EC069B70074E6D4 /* net.dengine.client.pack */; }; + 063583201EC069B70074E6D4 /* net.dengine.stdlib.gui.pack in Resources */ = {isa = PBXBuildFile; fileRef = 0635831C1EC069B70074E6D4 /* net.dengine.stdlib.gui.pack */; }; + 063583211EC069B70074E6D4 /* net.dengine.stdlib.pack in Resources */ = {isa = PBXBuildFile; fileRef = 0635831D1EC069B70074E6D4 /* net.dengine.stdlib.pack */; }; + 063583231EC0B7870074E6D4 /* doom1.wad in Resources */ = {isa = PBXBuildFile; fileRef = 063583221EC0B7870074E6D4 /* doom1.wad */; }; + 063671181EC4E7BA00DAF520 /* qrc_client.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 063671171EC4E7BA00DAF520 /* qrc_client.cpp */; }; + 067AD9181EBF14AE00B808B2 /* hexlex.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9131EBF148F00B808B2 /* hexlex.cpp */; }; + 067AD9191EBF14AE00B808B2 /* importidtech1.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9141EBF148F00B808B2 /* importidtech1.cpp */; }; + 067AD91A1EBF14AE00B808B2 /* mapimporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9151EBF148F00B808B2 /* mapimporter.cpp */; }; + 067AD91B1EBF14AE00B808B2 /* mapimporter_loadblockmap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9161EBF148F00B808B2 /* mapimporter_loadblockmap.cpp */; }; + 067AD91C1EBF14AE00B808B2 /* mapinfotranslator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 067AD9171EBF148F00B808B2 /* mapinfotranslator.cpp */; }; + 067ADA941EBF15E600B808B2 /* libdeng_core.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 067AD9291EBF14E000B808B2 /* libdeng_core.a */; }; + 067ADA951EBF15E600B808B2 /* libimportidtech1.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 067AD9091EBF143600B808B2 /* libimportidtech1.a */; }; + 068610631EBF01F700180814 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 068610621EBF01F700180814 /* Assets.xcassets */; }; + 068610781EBF01F700180814 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 068610761EBF01F700180814 /* LaunchScreen.storyboard */; }; + 0686108B1EBF04C500180814 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0686107F1EBF04C500180814 /* AudioToolbox.framework */; }; + 0686108C1EBF04C500180814 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610801EBF04C500180814 /* AVFoundation.framework */; }; + 0686108D1EBF04C500180814 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610811EBF04C500180814 /* CoreFoundation.framework */; }; + 0686108E1EBF04C500180814 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610821EBF04C500180814 /* CoreGraphics.framework */; }; + 0686108F1EBF04C500180814 /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610831EBF04C500180814 /* CoreText.framework */; }; + 068610901EBF04C500180814 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610841EBF04C500180814 /* Foundation.framework */; }; + 068610911EBF04C500180814 /* ImageIO.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610851EBF04C500180814 /* ImageIO.framework */; }; + 068610921EBF04C500180814 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610861EBF04C500180814 /* MobileCoreServices.framework */; }; + 068610931EBF04C500180814 /* OpenGLES.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610871EBF04C500180814 /* OpenGLES.framework */; }; + 068610941EBF04C500180814 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610881EBF04C500180814 /* QuartzCore.framework */; }; + 068610951EBF04C500180814 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 068610891EBF04C500180814 /* Security.framework */; }; + 068610961EBF04C500180814 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0686108A1EBF04C500180814 /* UIKit.framework */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 0635771B1EBF3EB40074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 063574811EBF39880074E6D4; + remoteInfo = deng_shell; + }; + 0635771D1EBF3EB40074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 063575B31EBF3AD50074E6D4; + remoteInfo = deng_legacy; + }; + 0635771F1EBF3EB40074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0635768E1EBF3CD20074E6D4; + remoteInfo = deng_gui; + }; + 06357A7B1EBF5E8B0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 063577E71EBF42D10074E6D4; + remoteInfo = deng_appfw; + }; + 06357A7D1EBF5E8B0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0635784A1EBF43A30074E6D4; + remoteInfo = deng_doomsday; + }; + 06357B111EBF674F0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357A811EBF61C70074E6D4; + remoteInfo = deng_gamefw; + }; + 06357B131EBF674F0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357AF81EBF63770074E6D4; + remoteInfo = importdeh; + }; + 06357B2A1EBF69F00074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357B1D1EBF69C00074E6D4; + remoteInfo = importudmf; + }; + 06357CCC1EBF70AE0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357B321EBF6EBD0074E6D4; + remoteInfo = doom; + }; + 06357CCE1EBF70AE0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357C451EBF70A20074E6D4; + remoteInfo = heretic; + }; + 06357F4D1EBF79EB0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357F371EBF77A00074E6D4; + remoteInfo = audio_fmod; + }; + 06357F4F1EBF79EB0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357D611EBF728D0074E6D4; + remoteInfo = hexen; + }; + 06357F511EBF79EB0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 06357E671EBF76120074E6D4; + remoteInfo = doom64; + }; + 063582491EBFBA350074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 0635819B1EBFBA120074E6D4; + remoteInfo = assimp; + }; + 0635830B1EC03E0C0074E6D4 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 063583071EC03DAD0074E6D4; + remoteInfo = Packages; + }; + 067AD9E11EBF154500B808B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 067AD91D1EBF14E000B808B2; + remoteInfo = deng_core; + }; + 067AD9E31EBF154500B808B2 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 068610501EBF01F700180814 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 067AD9081EBF143600B808B2; + remoteInfo = importidtech1; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXCopyFilesBuildPhase section */ + 063575281EBF39880074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063575CE1EBF3AD50074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063576A91EBF3CD20074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063578021EBF42D10074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063578901EBF43A30074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357AEC1EBF61C70074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B001EBF63770074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B251EBF69C00074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B381EBF6EBD0074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357CC71EBF70A20074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357DDD1EBF728D0074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357EE91EBF76120074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357F3E1EBF77A00074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063582441EBFBA120074E6D4 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD9071EBF143600B808B2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD9251EBF14E000B808B2 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = "include/$(PRODUCT_NAME)"; + dstSubfolderSpec = 16; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + 0635752C1EBF39880074E6D4 /* libdeng_shell.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_shell.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 063575681EBF39FA0074E6D4 /* abstractlineeditor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = abstractlineeditor.cpp; path = ../sdk/libshell/src/abstractlineeditor.cpp; sourceTree = ""; }; + 063575691EBF39FA0074E6D4 /* abstractlink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = abstractlink.cpp; path = ../sdk/libshell/src/abstractlink.cpp; sourceTree = ""; }; + 0635756A1EBF39FA0074E6D4 /* action.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = action.cpp; path = ../sdk/libshell/src/action.cpp; sourceTree = ""; }; + 0635756B1EBF39FA0074E6D4 /* choicewidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = choicewidget.cpp; path = ../sdk/libshell/src/choicewidget.cpp; sourceTree = ""; }; + 0635756C1EBF39FA0074E6D4 /* commandlinewidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = commandlinewidget.cpp; path = ../sdk/libshell/src/commandlinewidget.cpp; sourceTree = ""; }; + 0635756D1EBF39FA0074E6D4 /* dialogwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = dialogwidget.cpp; path = ../sdk/libshell/src/dialogwidget.cpp; sourceTree = ""; }; + 0635756E1EBF39FA0074E6D4 /* doomsdayinfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = doomsdayinfo.cpp; path = ../sdk/libshell/src/doomsdayinfo.cpp; sourceTree = ""; }; + 0635756F1EBF39FA0074E6D4 /* editorhistory.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = editorhistory.cpp; path = ../sdk/libshell/src/editorhistory.cpp; sourceTree = ""; }; + 063575701EBF39FA0074E6D4 /* inputdialog.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = inputdialog.cpp; path = ../sdk/libshell/src/inputdialog.cpp; sourceTree = ""; }; + 063575711EBF39FA0074E6D4 /* labelwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = labelwidget.cpp; path = ../sdk/libshell/src/labelwidget.cpp; sourceTree = ""; }; + 063575721EBF39FA0074E6D4 /* lexicon.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lexicon.cpp; path = ../sdk/libshell/src/lexicon.cpp; sourceTree = ""; }; + 063575731EBF39FA0074E6D4 /* libshell.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = libshell.cpp; path = ../sdk/libshell/src/libshell.cpp; sourceTree = ""; }; + 063575741EBF39FA0074E6D4 /* lineeditwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = lineeditwidget.cpp; path = ../sdk/libshell/src/lineeditwidget.cpp; sourceTree = ""; }; + 063575751EBF39FA0074E6D4 /* link.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = link.cpp; path = ../sdk/libshell/src/link.cpp; sourceTree = ""; }; + 063575761EBF39FA0074E6D4 /* localserver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = localserver.cpp; path = ../sdk/libshell/src/localserver.cpp; sourceTree = ""; }; + 063575771EBF39FA0074E6D4 /* logwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = logwidget.cpp; path = ../sdk/libshell/src/logwidget.cpp; sourceTree = ""; }; + 063575781EBF39FA0074E6D4 /* menuwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = menuwidget.cpp; path = ../sdk/libshell/src/menuwidget.cpp; sourceTree = ""; }; + 063575791EBF39FA0074E6D4 /* monospacelinewrapping.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = monospacelinewrapping.cpp; path = ../sdk/libshell/src/monospacelinewrapping.cpp; sourceTree = ""; }; + 0635757A1EBF39FA0074E6D4 /* protocol.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = protocol.cpp; path = ../sdk/libshell/src/protocol.cpp; sourceTree = ""; }; + 0635757B1EBF39FA0074E6D4 /* serverfinder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = serverfinder.cpp; path = ../sdk/libshell/src/serverfinder.cpp; sourceTree = ""; }; + 0635757C1EBF39FA0074E6D4 /* serverinfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = serverinfo.cpp; path = ../sdk/libshell/src/serverinfo.cpp; sourceTree = ""; }; + 0635757D1EBF39FA0074E6D4 /* textcanvas.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = textcanvas.cpp; path = ../sdk/libshell/src/textcanvas.cpp; sourceTree = ""; }; + 0635757E1EBF39FA0074E6D4 /* textrootwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = textrootwidget.cpp; path = ../sdk/libshell/src/textrootwidget.cpp; sourceTree = ""; }; + 0635757F1EBF39FA0074E6D4 /* textwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = textwidget.cpp; path = ../sdk/libshell/src/textwidget.cpp; sourceTree = ""; }; + 063575991EBF3A1F0074E6D4 /* abstractlineeditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = abstractlineeditor.h; path = ../sdk/libshell/include/de/shell/abstractlineeditor.h; sourceTree = ""; }; + 0635759A1EBF3A1F0074E6D4 /* abstractlink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = abstractlink.h; path = ../sdk/libshell/include/de/shell/abstractlink.h; sourceTree = ""; }; + 0635759B1EBF3A1F0074E6D4 /* action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = action.h; path = ../sdk/libshell/include/de/shell/action.h; sourceTree = ""; }; + 0635759C1EBF3A1F0074E6D4 /* choicewidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = choicewidget.h; path = ../sdk/libshell/include/de/shell/choicewidget.h; sourceTree = ""; }; + 0635759D1EBF3A1F0074E6D4 /* commandlinewidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = commandlinewidget.h; path = ../sdk/libshell/include/de/shell/commandlinewidget.h; sourceTree = ""; }; + 0635759E1EBF3A1F0074E6D4 /* dialogwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = dialogwidget.h; path = ../sdk/libshell/include/de/shell/dialogwidget.h; sourceTree = ""; }; + 0635759F1EBF3A1F0074E6D4 /* doomsdayinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = doomsdayinfo.h; path = ../sdk/libshell/include/de/shell/doomsdayinfo.h; sourceTree = ""; }; + 063575A01EBF3A1F0074E6D4 /* editorhistory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = editorhistory.h; path = ../sdk/libshell/include/de/shell/editorhistory.h; sourceTree = ""; }; + 063575A11EBF3A1F0074E6D4 /* inputdialog.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = inputdialog.h; path = ../sdk/libshell/include/de/shell/inputdialog.h; sourceTree = ""; }; + 063575A21EBF3A1F0074E6D4 /* itexteditor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = itexteditor.h; path = ../sdk/libshell/include/de/shell/itexteditor.h; sourceTree = ""; }; + 063575A31EBF3A1F0074E6D4 /* keyevent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = keyevent.h; path = ../sdk/libshell/include/de/shell/keyevent.h; sourceTree = ""; }; + 063575A41EBF3A1F0074E6D4 /* labelwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = labelwidget.h; path = ../sdk/libshell/include/de/shell/labelwidget.h; sourceTree = ""; }; + 063575A51EBF3A1F0074E6D4 /* lexicon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lexicon.h; path = ../sdk/libshell/include/de/shell/lexicon.h; sourceTree = ""; }; + 063575A61EBF3A1F0074E6D4 /* libshell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libshell.h; path = ../sdk/libshell/include/de/shell/libshell.h; sourceTree = ""; }; + 063575A71EBF3A1F0074E6D4 /* lineeditwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = lineeditwidget.h; path = ../sdk/libshell/include/de/shell/lineeditwidget.h; sourceTree = ""; }; + 063575A81EBF3A1F0074E6D4 /* link.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = link.h; path = ../sdk/libshell/include/de/shell/link.h; sourceTree = ""; }; + 063575A91EBF3A1F0074E6D4 /* localserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = localserver.h; path = ../sdk/libshell/include/de/shell/localserver.h; sourceTree = ""; }; + 063575AA1EBF3A1F0074E6D4 /* logwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = logwidget.h; path = ../sdk/libshell/include/de/shell/logwidget.h; sourceTree = ""; }; + 063575AB1EBF3A1F0074E6D4 /* menuwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = menuwidget.h; path = ../sdk/libshell/include/de/shell/menuwidget.h; sourceTree = ""; }; + 063575AC1EBF3A1F0074E6D4 /* monospacelinewrapping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = monospacelinewrapping.h; path = ../sdk/libshell/include/de/shell/monospacelinewrapping.h; sourceTree = ""; }; + 063575AD1EBF3A1F0074E6D4 /* protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = protocol.h; path = ../sdk/libshell/include/de/shell/protocol.h; sourceTree = ""; }; + 063575AE1EBF3A1F0074E6D4 /* serverfinder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = serverfinder.h; path = ../sdk/libshell/include/de/shell/serverfinder.h; sourceTree = ""; }; + 063575AF1EBF3A1F0074E6D4 /* serverinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = serverinfo.h; path = ../sdk/libshell/include/de/shell/serverinfo.h; sourceTree = ""; }; + 063575B01EBF3A1F0074E6D4 /* textcanvas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textcanvas.h; path = ../sdk/libshell/include/de/shell/textcanvas.h; sourceTree = ""; }; + 063575B11EBF3A1F0074E6D4 /* textrootwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textrootwidget.h; path = ../sdk/libshell/include/de/shell/textrootwidget.h; sourceTree = ""; }; + 063575B21EBF3A1F0074E6D4 /* textwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = textwidget.h; path = ../sdk/libshell/include/de/shell/textwidget.h; sourceTree = ""; }; + 063575D21EBF3AD50074E6D4 /* libdeng_legacy.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_legacy.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 063575D31EBF3B430074E6D4 /* aabox.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = aabox.c; path = ../sdk/liblegacy/src/aabox.c; sourceTree = ""; }; + 063575D41EBF3B430074E6D4 /* animator.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = animator.c; path = ../sdk/liblegacy/src/animator.c; sourceTree = ""; }; + 063575D51EBF3B430074E6D4 /* binangle.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = binangle.c; path = ../sdk/liblegacy/src/binangle.c; sourceTree = ""; }; + 063575D61EBF3B430074E6D4 /* findfile_unix.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = findfile_unix.c; path = ../sdk/liblegacy/src/findfile_unix.c; sourceTree = ""; }; + 063575D71EBF3B430074E6D4 /* fixedpoint.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = fixedpoint.c; path = ../sdk/liblegacy/src/fixedpoint.c; sourceTree = ""; }; + 063575D81EBF3B430074E6D4 /* liblegacy.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = liblegacy.c; path = ../sdk/liblegacy/src/liblegacy.c; sourceTree = ""; }; + 063575D91EBF3B430074E6D4 /* mathutil.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = mathutil.c; path = ../sdk/liblegacy/src/mathutil.c; sourceTree = ""; }; + 063575DA1EBF3B430074E6D4 /* memory.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = memory.c; path = ../sdk/liblegacy/src/memory.c; sourceTree = ""; }; + 063575DB1EBF3B430074E6D4 /* memoryblockset.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = memoryblockset.c; path = ../sdk/liblegacy/src/memoryblockset.c; sourceTree = ""; }; + 063575DC1EBF3B430074E6D4 /* memoryzone.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = memoryzone.c; path = ../sdk/liblegacy/src/memoryzone.c; sourceTree = ""; }; + 063575DD1EBF3B430074E6D4 /* nodepile.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = nodepile.c; path = ../sdk/liblegacy/src/nodepile.c; sourceTree = ""; }; + 063575DE1EBF3B430074E6D4 /* point.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = point.c; path = ../sdk/liblegacy/src/point.c; sourceTree = ""; }; + 063575DF1EBF3B430074E6D4 /* reader1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = reader1.c; path = ../sdk/liblegacy/src/reader1.c; sourceTree = ""; }; + 063575E01EBF3B430074E6D4 /* rect.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = rect.c; path = ../sdk/liblegacy/src/rect.c; sourceTree = ""; }; + 063575E11EBF3B430074E6D4 /* size.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = size.c; path = ../sdk/liblegacy/src/size.c; sourceTree = ""; }; + 063575E21EBF3B430074E6D4 /* stack.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = stack.c; path = ../sdk/liblegacy/src/stack.c; sourceTree = ""; }; + 063575E31EBF3B430074E6D4 /* str.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = str.c; path = ../sdk/liblegacy/src/str.c; sourceTree = ""; }; + 063575E41EBF3B430074E6D4 /* strutil.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = strutil.c; path = ../sdk/liblegacy/src/strutil.c; sourceTree = ""; }; + 063575E51EBF3B430074E6D4 /* texgamma.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = texgamma.c; path = ../sdk/liblegacy/src/texgamma.c; sourceTree = ""; }; + 063575E61EBF3B430074E6D4 /* vector1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = vector1.c; path = ../sdk/liblegacy/src/vector1.c; sourceTree = ""; }; + 063575E71EBF3B430074E6D4 /* writer1.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = writer1.c; path = ../sdk/liblegacy/src/writer1.c; sourceTree = ""; }; + 063575E81EBF3B430074E6D4 /* concurrency.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = concurrency.cpp; path = ../sdk/liblegacy/src/concurrency.cpp; sourceTree = ""; }; + 063575EA1EBF3B430074E6D4 /* smoother.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = smoother.cpp; path = ../sdk/liblegacy/src/smoother.cpp; sourceTree = ""; }; + 063575EB1EBF3B430074E6D4 /* stringarray.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = stringarray.cpp; path = ../sdk/liblegacy/src/stringarray.cpp; sourceTree = ""; }; + 063575EC1EBF3B430074E6D4 /* timer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = timer.cpp; path = ../sdk/liblegacy/src/timer.cpp; sourceTree = ""; }; + 063576081EBF3B6C0074E6D4 /* aabox.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = aabox.h; path = ../sdk/liblegacy/include/de/aabox.h; sourceTree = ""; }; + 063576091EBF3B6C0074E6D4 /* animator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = animator.h; path = ../sdk/liblegacy/include/de/animator.h; sourceTree = ""; }; + 0635760A1EBF3B6C0074E6D4 /* binangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = binangle.h; path = ../sdk/liblegacy/include/de/binangle.h; sourceTree = ""; }; + 0635760B1EBF3B6C0074E6D4 /* concurrency.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = concurrency.h; path = ../sdk/liblegacy/include/de/concurrency.h; sourceTree = ""; }; + 0635760C1EBF3B6C0074E6D4 /* ddstring.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ddstring.h; path = ../sdk/liblegacy/include/de/ddstring.h; sourceTree = ""; }; + 0635760D1EBF3B6C0074E6D4 /* findfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = findfile.h; path = ../sdk/liblegacy/include/de/findfile.h; sourceTree = ""; }; + 0635760E1EBF3B6C0074E6D4 /* fixedpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = fixedpoint.h; path = ../sdk/liblegacy/include/de/fixedpoint.h; sourceTree = ""; }; + 0635760F1EBF3B6C0074E6D4 /* liblegacy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = liblegacy.h; path = ../sdk/liblegacy/include/de/liblegacy.h; sourceTree = ""; }; + 063576101EBF3B6C0074E6D4 /* mathutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = mathutil.h; path = ../sdk/liblegacy/include/de/mathutil.h; sourceTree = ""; }; + 063576111EBF3B6C0074E6D4 /* memory.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memory.h; path = ../sdk/liblegacy/include/de/memory.h; sourceTree = ""; }; + 063576121EBF3B6C0074E6D4 /* memoryblockset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memoryblockset.h; path = ../sdk/liblegacy/include/de/memoryblockset.h; sourceTree = ""; }; + 063576131EBF3B6C0074E6D4 /* memoryzone.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memoryzone.h; path = ../sdk/liblegacy/include/de/memoryzone.h; sourceTree = ""; }; + 063576141EBF3B6C0074E6D4 /* nodepile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = nodepile.h; path = ../sdk/liblegacy/include/de/nodepile.h; sourceTree = ""; }; + 063576151EBF3B6C0074E6D4 /* point.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = point.h; path = ../sdk/liblegacy/include/de/point.h; sourceTree = ""; }; + 063576161EBF3B6C0074E6D4 /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = reader.h; path = ../sdk/liblegacy/include/de/reader.h; sourceTree = ""; }; + 063576171EBF3B6C0074E6D4 /* rect.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rect.h; path = ../sdk/liblegacy/include/de/rect.h; sourceTree = ""; }; + 063576181EBF3B6C0074E6D4 /* size.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = size.h; path = ../sdk/liblegacy/include/de/size.h; sourceTree = ""; }; + 063576191EBF3B6C0074E6D4 /* smoother.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = smoother.h; path = ../sdk/liblegacy/include/de/smoother.h; sourceTree = ""; }; + 0635761A1EBF3B6C0074E6D4 /* stack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stack.h; path = ../sdk/liblegacy/include/de/stack.h; sourceTree = ""; }; + 0635761B1EBF3B6C0074E6D4 /* str.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = str.h; path = ../sdk/liblegacy/include/de/str.h; sourceTree = ""; }; + 0635761C1EBF3B6C0074E6D4 /* stringarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = stringarray.h; path = ../sdk/liblegacy/include/de/stringarray.h; sourceTree = ""; }; + 0635761D1EBF3B6C0074E6D4 /* strutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = strutil.h; path = ../sdk/liblegacy/include/de/strutil.h; sourceTree = ""; }; + 0635761E1EBF3B6C0074E6D4 /* texgamma.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = texgamma.h; path = ../sdk/liblegacy/include/de/texgamma.h; sourceTree = ""; }; + 0635761F1EBF3B6C0074E6D4 /* timer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = timer.h; path = ../sdk/liblegacy/include/de/timer.h; sourceTree = ""; }; + 063576201EBF3B6C0074E6D4 /* types.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = types.h; path = ../sdk/liblegacy/include/de/types.h; sourceTree = ""; }; + 063576211EBF3B6C0074E6D4 /* unittest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = unittest.h; path = ../sdk/liblegacy/include/de/unittest.h; sourceTree = ""; }; + 063576221EBF3B6C0074E6D4 /* vector1.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = vector1.h; path = ../sdk/liblegacy/include/de/vector1.h; sourceTree = ""; }; + 063576231EBF3B6C0074E6D4 /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = writer.h; path = ../sdk/liblegacy/include/de/writer.h; sourceTree = ""; }; + 063576241EBF3B6C0074E6D4 /* str.hh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = str.hh; path = ../sdk/liblegacy/include/de/str.hh; sourceTree = ""; }; + 063576251EBF3B6C0074E6D4 /* memoryzone_private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = memoryzone_private.h; path = ../sdk/liblegacy/src/memoryzone_private.h; sourceTree = ""; }; + 063576271EBF3C970074E6D4 /* sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sound.cpp; sourceTree = ""; }; + 063576281EBF3C970074E6D4 /* waveform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waveform.cpp; sourceTree = ""; }; + 063576291EBF3C970074E6D4 /* waveformbank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = waveformbank.cpp; sourceTree = ""; }; + 0635762B1EBF3C970074E6D4 /* atlas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = atlas.cpp; sourceTree = ""; }; + 0635762C1EBF3C970074E6D4 /* atlastexture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = atlastexture.cpp; sourceTree = ""; }; + 0635762D1EBF3C970074E6D4 /* colorbank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorbank.cpp; sourceTree = ""; }; + 0635762E1EBF3C970074E6D4 /* drawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawable.cpp; sourceTree = ""; }; + 0635762F1EBF3C970074E6D4 /* glatlasbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glatlasbuffer.cpp; sourceTree = ""; }; + 063576301EBF3C970074E6D4 /* glbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glbuffer.cpp; sourceTree = ""; }; + 063576311EBF3C970074E6D4 /* gldrawqueue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gldrawqueue.cpp; sourceTree = ""; }; + 063576321EBF3C970074E6D4 /* glframebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glframebuffer.cpp; sourceTree = ""; }; + 063576331EBF3C970074E6D4 /* glframebuffer_alternativebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glframebuffer_alternativebuffer.cpp; sourceTree = ""; }; + 063576341EBF3C970074E6D4 /* glinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glinfo.cpp; sourceTree = ""; }; + 063576351EBF3C970074E6D4 /* glprogram.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glprogram.cpp; sourceTree = ""; }; + 063576361EBF3C970074E6D4 /* glshader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glshader.cpp; sourceTree = ""; }; + 063576371EBF3C970074E6D4 /* glshaderbank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glshaderbank.cpp; sourceTree = ""; }; + 063576381EBF3C970074E6D4 /* glstate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glstate.cpp; sourceTree = ""; }; + 063576391EBF3C970074E6D4 /* glsubbuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = glsubbuffer.cpp; sourceTree = ""; }; + 0635763A1EBF3C970074E6D4 /* gltexture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gltexture.cpp; sourceTree = ""; }; + 0635763B1EBF3C970074E6D4 /* gltextureframebuffer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gltextureframebuffer.cpp; sourceTree = ""; }; + 0635763C1EBF3C970074E6D4 /* gluniform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gluniform.cpp; sourceTree = ""; }; + 0635763D1EBF3C970074E6D4 /* heightmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = heightmap.cpp; sourceTree = ""; }; + 0635763E1EBF3C970074E6D4 /* image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image.cpp; sourceTree = ""; }; + 0635763F1EBF3C970074E6D4 /* imagebank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imagebank.cpp; sourceTree = ""; }; + 063576401EBF3C970074E6D4 /* imagefile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = imagefile.cpp; sourceTree = ""; }; + 063576411EBF3C970074E6D4 /* kdtreeatlasallocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = kdtreeatlasallocator.cpp; sourceTree = ""; }; + 063576421EBF3C970074E6D4 /* modelbank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modelbank.cpp; sourceTree = ""; }; + 063576431EBF3C970074E6D4 /* modeldrawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modeldrawable.cpp; sourceTree = ""; }; + 063576441EBF3C970074E6D4 /* multiatlas.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiatlas.cpp; sourceTree = ""; }; + 063576451EBF3C970074E6D4 /* rowatlasallocator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rowatlasallocator.cpp; sourceTree = ""; }; + 063576461EBF3C970074E6D4 /* texturebank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturebank.cpp; sourceTree = ""; }; + 063576491EBF3C970074E6D4 /* keyevent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyevent.cpp; sourceTree = ""; }; + 0635764A1EBF3C970074E6D4 /* keyeventsource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyeventsource.cpp; sourceTree = ""; }; + 0635764B1EBF3C970074E6D4 /* mouseevent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouseevent.cpp; sourceTree = ""; }; + 0635764C1EBF3C970074E6D4 /* mouseeventsource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouseeventsource.cpp; sourceTree = ""; }; + 0635764E1EBF3C970074E6D4 /* coretextnativefont_macx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coretextnativefont_macx.cpp; sourceTree = ""; }; + 0635764F1EBF3C970074E6D4 /* coretextnativefont_macx.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = coretextnativefont_macx.h; sourceTree = ""; }; + 063576501EBF3C970074E6D4 /* font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font.cpp; sourceTree = ""; }; + 063576511EBF3C970074E6D4 /* font_richformat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = font_richformat.cpp; sourceTree = ""; }; + 063576521EBF3C970074E6D4 /* fontbank.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fontbank.cpp; sourceTree = ""; }; + 063576531EBF3C970074E6D4 /* nativefont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nativefont.cpp; sourceTree = ""; }; + 063576561EBF3C970074E6D4 /* displaymode_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = displaymode_dummy.cpp; path = ../sdk/libgui/src/displaymode_dummy.cpp; sourceTree = ""; }; + 063576571EBF3C970074E6D4 /* displaymode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = displaymode.cpp; path = ../sdk/libgui/src/displaymode.cpp; sourceTree = ""; }; + 063576581EBF3C970074E6D4 /* glwindow_qml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = glwindow_qml.cpp; path = ../sdk/libgui/src/glwindow_qml.cpp; sourceTree = ""; }; + 063576591EBF3C970074E6D4 /* guiapp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = guiapp.cpp; path = ../sdk/libgui/src/guiapp.cpp; sourceTree = ""; }; + 0635765A1EBF3C970074E6D4 /* guiloop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = guiloop.cpp; path = ../sdk/libgui/src/guiloop.cpp; sourceTree = ""; }; + 0635765B1EBF3C970074E6D4 /* persistentglwindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = persistentglwindow.cpp; path = ../sdk/libgui/src/persistentglwindow.cpp; sourceTree = ""; }; + 0635765C1EBF3C970074E6D4 /* windoweventhandler.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = windoweventhandler.cpp; path = ../sdk/libgui/src/windoweventhandler.cpp; sourceTree = ""; }; + 063576AD1EBF3CD20074E6D4 /* libdeng_gui.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_gui.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 063576E21EBF3D240074E6D4 /* sound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sound.h; sourceTree = ""; }; + 063576E31EBF3D240074E6D4 /* waveform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = waveform.h; sourceTree = ""; }; + 063576E41EBF3D240074E6D4 /* waveformbank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = waveformbank.h; sourceTree = ""; }; + 063576E61EBF3D240074E6D4 /* atlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atlas.h; sourceTree = ""; }; + 063576E71EBF3D240074E6D4 /* atlastexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = atlastexture.h; sourceTree = ""; }; + 063576E81EBF3D240074E6D4 /* colorbank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colorbank.h; sourceTree = ""; }; + 063576E91EBF3D240074E6D4 /* drawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = drawable.h; sourceTree = ""; }; + 063576EA1EBF3D240074E6D4 /* glatlasbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glatlasbuffer.h; sourceTree = ""; }; + 063576EB1EBF3D240074E6D4 /* glbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glbuffer.h; sourceTree = ""; }; + 063576EC1EBF3D240074E6D4 /* gldrawqueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gldrawqueue.h; sourceTree = ""; }; + 063576ED1EBF3D240074E6D4 /* glframebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glframebuffer.h; sourceTree = ""; }; + 063576EE1EBF3D240074E6D4 /* glinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glinfo.h; sourceTree = ""; }; + 063576EF1EBF3D240074E6D4 /* glpixelformat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glpixelformat.h; sourceTree = ""; }; + 063576F01EBF3D240074E6D4 /* glprogram.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glprogram.h; sourceTree = ""; }; + 063576F11EBF3D240074E6D4 /* glshader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glshader.h; sourceTree = ""; }; + 063576F21EBF3D240074E6D4 /* glshaderbank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glshaderbank.h; sourceTree = ""; }; + 063576F31EBF3D240074E6D4 /* glstate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glstate.h; sourceTree = ""; }; + 063576F41EBF3D240074E6D4 /* glsubbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glsubbuffer.h; sourceTree = ""; }; + 063576F51EBF3D240074E6D4 /* gltexture.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gltexture.h; sourceTree = ""; }; + 063576F61EBF3D240074E6D4 /* gltextureframebuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gltextureframebuffer.h; sourceTree = ""; }; + 063576F71EBF3D240074E6D4 /* gluniform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = gluniform.h; sourceTree = ""; }; + 063576F81EBF3D240074E6D4 /* heightmap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = heightmap.h; sourceTree = ""; }; + 063576F91EBF3D240074E6D4 /* image.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = image.h; sourceTree = ""; }; + 063576FA1EBF3D240074E6D4 /* imagebank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imagebank.h; sourceTree = ""; }; + 063576FB1EBF3D240074E6D4 /* imagefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = imagefile.h; sourceTree = ""; }; + 063576FC1EBF3D240074E6D4 /* kdtreeatlasallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kdtreeatlasallocator.h; sourceTree = ""; }; + 063576FD1EBF3D240074E6D4 /* modelbank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modelbank.h; sourceTree = ""; }; + 063576FE1EBF3D240074E6D4 /* modeldrawable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = modeldrawable.h; sourceTree = ""; }; + 063576FF1EBF3D240074E6D4 /* multiatlas.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = multiatlas.h; sourceTree = ""; }; + 063577001EBF3D240074E6D4 /* opengl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = opengl.h; sourceTree = ""; }; + 063577011EBF3D240074E6D4 /* rowatlasallocator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rowatlasallocator.h; sourceTree = ""; }; + 063577021EBF3D240074E6D4 /* texturebank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = texturebank.h; sourceTree = ""; }; + 063577031EBF3D240074E6D4 /* vertexbuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vertexbuilder.h; sourceTree = ""; }; + 063577051EBF3D240074E6D4 /* displaymode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = displaymode.h; sourceTree = ""; }; + 063577061EBF3D240074E6D4 /* displaymode_native.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = displaymode_native.h; sourceTree = ""; }; + 063577071EBF3D240074E6D4 /* glwindow_qml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = glwindow_qml.h; sourceTree = ""; }; + 063577081EBF3D240074E6D4 /* guiapp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guiapp.h; sourceTree = ""; }; + 063577091EBF3D240074E6D4 /* guiloop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = guiloop.h; sourceTree = ""; }; + 0635770A1EBF3D240074E6D4 /* libgui.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libgui.h; sourceTree = ""; }; + 0635770B1EBF3D240074E6D4 /* persistentglwindow.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = persistentglwindow.h; sourceTree = ""; }; + 0635770C1EBF3D240074E6D4 /* windoweventhandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = windoweventhandler.h; sourceTree = ""; }; + 0635770E1EBF3D240074E6D4 /* ddkey.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ddkey.h; sourceTree = ""; }; + 0635770F1EBF3D240074E6D4 /* keyevent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyevent.h; sourceTree = ""; }; + 063577101EBF3D240074E6D4 /* keyeventsource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = keyeventsource.h; sourceTree = ""; }; + 063577111EBF3D240074E6D4 /* mouseevent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mouseevent.h; sourceTree = ""; }; + 063577121EBF3D240074E6D4 /* mouseeventsource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mouseeventsource.h; sourceTree = ""; }; + 063577141EBF3D240074E6D4 /* font.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = font.h; sourceTree = ""; }; + 063577151EBF3D240074E6D4 /* fontbank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fontbank.h; sourceTree = ""; }; + 063577161EBF3D240074E6D4 /* nativefont.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nativefont.h; sourceTree = ""; }; + 063577281EBF42C10074E6D4 /* directorylistdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = directorylistdialog.cpp; sourceTree = ""; }; + 063577291EBF42C10074E6D4 /* inputdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputdialog.cpp; sourceTree = ""; }; + 0635772A1EBF42C10074E6D4 /* messagedialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = messagedialog.cpp; sourceTree = ""; }; + 0635772C1EBF42C10074E6D4 /* oculusrift.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = oculusrift.cpp; sourceTree = ""; }; + 0635772D1EBF42C10074E6D4 /* vrconfig.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vrconfig.cpp; sourceTree = ""; }; + 0635772F1EBF42C10074E6D4 /* auxbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = auxbuttonwidget.cpp; sourceTree = ""; }; + 063577301EBF42C10074E6D4 /* blurwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blurwidget.cpp; sourceTree = ""; }; + 063577311EBF42C10074E6D4 /* buttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buttonwidget.cpp; sourceTree = ""; }; + 063577321EBF42C10074E6D4 /* choicewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = choicewidget.cpp; sourceTree = ""; }; + 063577331EBF42C10074E6D4 /* commandwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commandwidget.cpp; sourceTree = ""; }; + 063577341EBF42C10074E6D4 /* compositorwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compositorwidget.cpp; sourceTree = ""; }; + 063577351EBF42C10074E6D4 /* dialogwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dialogwidget.cpp; sourceTree = ""; }; + 063577361EBF42C10074E6D4 /* directoryarraywidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = directoryarraywidget.cpp; sourceTree = ""; }; + 063577371EBF42C10074E6D4 /* documentpopupwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = documentpopupwidget.cpp; sourceTree = ""; }; + 063577381EBF42C10074E6D4 /* documentwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = documentwidget.cpp; sourceTree = ""; }; + 063577391EBF42C10074E6D4 /* fadetoblackwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fadetoblackwidget.cpp; sourceTree = ""; }; + 0635773A1EBF42C10074E6D4 /* focuswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = focuswidget.cpp; sourceTree = ""; }; + 0635773B1EBF42C10074E6D4 /* foldpanelwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = foldpanelwidget.cpp; sourceTree = ""; }; + 0635773C1EBF42C10074E6D4 /* gridpopupwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gridpopupwidget.cpp; sourceTree = ""; }; + 0635773D1EBF42C10074E6D4 /* labelwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = labelwidget.cpp; sourceTree = ""; }; + 0635773E1EBF42C10074E6D4 /* lineeditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lineeditwidget.cpp; sourceTree = ""; }; + 0635773F1EBF42C10074E6D4 /* logwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logwidget.cpp; sourceTree = ""; }; + 063577401EBF42C10074E6D4 /* menuwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = menuwidget.cpp; sourceTree = ""; }; + 063577411EBF42C10074E6D4 /* notificationareawidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = notificationareawidget.cpp; sourceTree = ""; }; + 063577421EBF42C10074E6D4 /* panelwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = panelwidget.cpp; sourceTree = ""; }; + 063577431EBF42C10074E6D4 /* popupbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = popupbuttonwidget.cpp; sourceTree = ""; }; + 063577441EBF42C10074E6D4 /* popupmenuwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = popupmenuwidget.cpp; sourceTree = ""; }; + 063577451EBF42C10074E6D4 /* popupwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = popupwidget.cpp; sourceTree = ""; }; + 063577461EBF42C10074E6D4 /* progresswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = progresswidget.cpp; sourceTree = ""; }; + 063577471EBF42C10074E6D4 /* relaywidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = relaywidget.cpp; sourceTree = ""; }; + 063577481EBF42C10074E6D4 /* scriptcommandwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scriptcommandwidget.cpp; sourceTree = ""; }; + 063577491EBF42C10074E6D4 /* scrollareawidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = scrollareawidget.cpp; sourceTree = ""; }; + 0635774A1EBF42C10074E6D4 /* sliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sliderwidget.cpp; sourceTree = ""; }; + 0635774B1EBF42C10074E6D4 /* tabwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tabwidget.cpp; sourceTree = ""; }; + 0635774C1EBF42C10074E6D4 /* togglewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = togglewidget.cpp; sourceTree = ""; }; + 0635774D1EBF42C10074E6D4 /* variablearraywidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variablearraywidget.cpp; sourceTree = ""; }; + 0635774E1EBF42C10074E6D4 /* variablechoicewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variablechoicewidget.cpp; sourceTree = ""; }; + 0635774F1EBF42C10074E6D4 /* variablelineeditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variablelineeditwidget.cpp; sourceTree = ""; }; + 063577501EBF42C10074E6D4 /* variablesliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variablesliderwidget.cpp; sourceTree = ""; }; + 063577511EBF42C10074E6D4 /* variabletogglewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variabletogglewidget.cpp; sourceTree = ""; }; + 063577521EBF42C10074E6D4 /* baseguiapp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = baseguiapp.cpp; path = ../sdk/libappfw/src/baseguiapp.cpp; sourceTree = ""; }; + 063577531EBF42C10074E6D4 /* basewindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = basewindow.cpp; path = ../sdk/libappfw/src/basewindow.cpp; sourceTree = ""; }; + 063577541EBF42C10074E6D4 /* callbackaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = callbackaction.cpp; path = ../sdk/libappfw/src/callbackaction.cpp; sourceTree = ""; }; + 063577551EBF42C10074E6D4 /* childwidgetorganizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = childwidgetorganizer.cpp; path = ../sdk/libappfw/src/childwidgetorganizer.cpp; sourceTree = ""; }; + 063577561EBF42C10074E6D4 /* data.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = data.cpp; path = ../sdk/libappfw/src/data.cpp; sourceTree = ""; }; + 063577571EBF42C10074E6D4 /* dialogcontentstylist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dialogcontentstylist.cpp; path = ../sdk/libappfw/src/dialogcontentstylist.cpp; sourceTree = ""; }; + 063577581EBF42C10074E6D4 /* filtereddata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = filtereddata.cpp; path = ../sdk/libappfw/src/filtereddata.cpp; sourceTree = ""; }; + 063577591EBF42C10074E6D4 /* fontlinewrapping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fontlinewrapping.cpp; path = ../sdk/libappfw/src/fontlinewrapping.cpp; sourceTree = ""; }; + 0635775A1EBF42C10074E6D4 /* gltextcomposer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gltextcomposer.cpp; path = ../sdk/libappfw/src/gltextcomposer.cpp; sourceTree = ""; }; + 0635775B1EBF42C10074E6D4 /* gridlayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gridlayout.cpp; path = ../sdk/libappfw/src/gridlayout.cpp; sourceTree = ""; }; + 0635775C1EBF42C10074E6D4 /* guirootwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = guirootwidget.cpp; path = ../sdk/libappfw/src/guirootwidget.cpp; sourceTree = ""; }; + 0635775D1EBF42C10074E6D4 /* guiwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = guiwidget.cpp; path = ../sdk/libappfw/src/guiwidget.cpp; sourceTree = ""; }; + 0635775E1EBF42C10074E6D4 /* imageitem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = imageitem.cpp; path = ../sdk/libappfw/src/imageitem.cpp; sourceTree = ""; }; + 0635775F1EBF42C10074E6D4 /* item.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = item.cpp; path = ../sdk/libappfw/src/item.cpp; sourceTree = ""; }; + 063577601EBF42C10074E6D4 /* listdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = listdata.cpp; path = ../sdk/libappfw/src/listdata.cpp; sourceTree = ""; }; + 063577611EBF42C10074E6D4 /* margins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = margins.cpp; path = ../sdk/libappfw/src/margins.cpp; sourceTree = ""; }; + 063577621EBF42C10074E6D4 /* painter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = painter.cpp; path = ../sdk/libappfw/src/painter.cpp; sourceTree = ""; }; + 063577631EBF42C10074E6D4 /* persistentstate.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = persistentstate.cpp; path = ../sdk/libappfw/src/persistentstate.cpp; sourceTree = ""; }; + 063577641EBF42C10074E6D4 /* proceduralimage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = proceduralimage.cpp; path = ../sdk/libappfw/src/proceduralimage.cpp; sourceTree = ""; }; + 063577651EBF42C10074E6D4 /* sequentiallayout.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sequentiallayout.cpp; path = ../sdk/libappfw/src/sequentiallayout.cpp; sourceTree = ""; }; + 063577661EBF42C10074E6D4 /* signalaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = signalaction.cpp; path = ../sdk/libappfw/src/signalaction.cpp; sourceTree = ""; }; + 063577671EBF42C10074E6D4 /* style.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = style.cpp; path = ../sdk/libappfw/src/style.cpp; sourceTree = ""; }; + 063577681EBF42C10074E6D4 /* textdrawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = textdrawable.cpp; path = ../sdk/libappfw/src/textdrawable.cpp; sourceTree = ""; }; + 063577691EBF42C10074E6D4 /* untrapper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = untrapper.cpp; path = ../sdk/libappfw/src/untrapper.cpp; sourceTree = ""; }; + 0635776A1EBF42C10074E6D4 /* vrwindowtransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = vrwindowtransform.cpp; path = ../sdk/libappfw/src/vrwindowtransform.cpp; sourceTree = ""; }; + 0635776B1EBF42C10074E6D4 /* windowsystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = windowsystem.cpp; path = ../sdk/libappfw/src/windowsystem.cpp; sourceTree = ""; }; + 0635776C1EBF42C10074E6D4 /* windowtransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = windowtransform.cpp; path = ../sdk/libappfw/src/windowtransform.cpp; sourceTree = ""; }; + 063578061EBF42D10074E6D4 /* libdeng_appfw.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_appfw.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 063578941EBF43A30074E6D4 /* libdeng_doomsday.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_doomsday.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 063578961EBF43DE0074E6D4 /* library.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = library.cpp; sourceTree = ""; }; + 063578981EBF43DE0074E6D4 /* alias.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alias.cpp; sourceTree = ""; }; + 063578991EBF43DE0074E6D4 /* cmd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cmd.cpp; sourceTree = ""; }; + 0635789A1EBF43DE0074E6D4 /* exec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = exec.cpp; sourceTree = ""; }; + 0635789B1EBF43DE0074E6D4 /* knownword.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = knownword.cpp; sourceTree = ""; }; + 0635789C1EBF43DE0074E6D4 /* var.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = var.cpp; sourceTree = ""; }; + 0635789E1EBF43DE0074E6D4 /* decoration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decoration.cpp; sourceTree = ""; }; + 0635789F1EBF43DE0074E6D4 /* ded.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ded.cpp; sourceTree = ""; }; + 063578A01EBF43DE0074E6D4 /* dedfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dedfile.cpp; sourceTree = ""; }; + 063578A11EBF43DE0074E6D4 /* dedparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dedparser.cpp; sourceTree = ""; }; + 063578A21EBF43DE0074E6D4 /* dedregister.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dedregister.cpp; sourceTree = ""; }; + 063578A31EBF43DE0074E6D4 /* definition.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = definition.cpp; sourceTree = ""; }; + 063578A41EBF43DE0074E6D4 /* episode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = episode.cpp; sourceTree = ""; }; + 063578A51EBF43DE0074E6D4 /* finale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finale.cpp; sourceTree = ""; }; + 063578A61EBF43DE0074E6D4 /* mapgraphnode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapgraphnode.cpp; sourceTree = ""; }; + 063578A71EBF43DE0074E6D4 /* mapinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapinfo.cpp; sourceTree = ""; }; + 063578A81EBF43DE0074E6D4 /* material.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = material.cpp; sourceTree = ""; }; + 063578A91EBF43DE0074E6D4 /* model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = model.cpp; sourceTree = ""; }; + 063578AA1EBF43DE0074E6D4 /* music.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = music.cpp; sourceTree = ""; }; + 063578AB1EBF43DE0074E6D4 /* sky.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sky.cpp; sourceTree = ""; }; + 063578AC1EBF43DE0074E6D4 /* sprite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sprite.cpp; sourceTree = ""; }; + 063578AD1EBF43DE0074E6D4 /* state.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = state.cpp; sourceTree = ""; }; + 063578AE1EBF43DE0074E6D4 /* thing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thing.cpp; sourceTree = ""; }; + 063578B01EBF43DE0074E6D4 /* datafile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = datafile.cpp; sourceTree = ""; }; + 063578B11EBF43DE0074E6D4 /* datafolder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = datafolder.cpp; sourceTree = ""; }; + 063578B21EBF43DE0074E6D4 /* file.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = file.cpp; sourceTree = ""; }; + 063578B31EBF43DE0074E6D4 /* filehandle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filehandle.cpp; sourceTree = ""; }; + 063578B41EBF43DE0074E6D4 /* fileid.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fileid.cpp; sourceTree = ""; }; + 063578B51EBF43DE0074E6D4 /* filetype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = filetype.cpp; sourceTree = ""; }; + 063578B61EBF43DE0074E6D4 /* fs_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fs_main.cpp; sourceTree = ""; }; + 063578B71EBF43DE0074E6D4 /* fs_scheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fs_scheme.cpp; sourceTree = ""; }; + 063578B81EBF43DE0074E6D4 /* fs_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fs_util.cpp; sourceTree = ""; }; + 063578BA1EBF43DE0074E6D4 /* lumpcache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lumpcache.cpp; sourceTree = ""; }; + 063578BB1EBF43DE0074E6D4 /* lumpindex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lumpindex.cpp; sourceTree = ""; }; + 063578BC1EBF43DE0074E6D4 /* readfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = readfile.cpp; sourceTree = ""; }; + 063578BD1EBF43DE0074E6D4 /* searchpath.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = searchpath.cpp; sourceTree = ""; }; + 063578BE1EBF43DE0074E6D4 /* virtualmappings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = virtualmappings.cpp; sourceTree = ""; }; + 063578BF1EBF43DE0074E6D4 /* wad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wad.cpp; sourceTree = ""; }; + 063578C01EBF43DE0074E6D4 /* zip.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zip.cpp; sourceTree = ""; }; + 063578C21EBF43DE0074E6D4 /* animgroup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animgroup.cpp; sourceTree = ""; }; + 063578C31EBF43DE0074E6D4 /* animgroups.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = animgroups.cpp; sourceTree = ""; }; + 063578C41EBF43DE0074E6D4 /* bundlelinkfeed.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bundlelinkfeed.cpp; sourceTree = ""; }; + 063578C51EBF43DE0074E6D4 /* bundles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bundles.cpp; sourceTree = ""; }; + 063578C61EBF43DE0074E6D4 /* colorpalette.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorpalette.cpp; sourceTree = ""; }; + 063578C71EBF43DE0074E6D4 /* colorpalettes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorpalettes.cpp; sourceTree = ""; }; + 063578C81EBF43DE0074E6D4 /* composite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = composite.cpp; sourceTree = ""; }; + 063578C91EBF43DE0074E6D4 /* databundle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = databundle.cpp; sourceTree = ""; }; + 063578CA1EBF43DE0074E6D4 /* doomsdaypackage.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = doomsdaypackage.cpp; sourceTree = ""; }; + 063578CB1EBF43DE0074E6D4 /* lumpcatalog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lumpcatalog.cpp; sourceTree = ""; }; + 063578CC1EBF43DE0074E6D4 /* lumpdirectory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lumpdirectory.cpp; sourceTree = ""; }; + 063578CD1EBF43DE0074E6D4 /* m_decomp64.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = m_decomp64.cpp; sourceTree = ""; }; + 063578CE1EBF43DE0074E6D4 /* manifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = manifest.cpp; sourceTree = ""; }; + 063578CF1EBF43DE0074E6D4 /* mapmanifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapmanifest.cpp; sourceTree = ""; }; + 063578D01EBF43DE0074E6D4 /* mapmanifests.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapmanifests.cpp; sourceTree = ""; }; + 063578D11EBF43DE0074E6D4 /* patch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = patch.cpp; sourceTree = ""; }; + 063578D21EBF43DE0074E6D4 /* patchname.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = patchname.cpp; sourceTree = ""; }; + 063578D31EBF43DE0074E6D4 /* pcx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pcx.cpp; sourceTree = ""; }; + 063578D41EBF43DE0074E6D4 /* resourceclass.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resourceclass.cpp; sourceTree = ""; }; + 063578D51EBF43DE0074E6D4 /* resources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = resources.cpp; sourceTree = ""; }; + 063578D61EBF43DE0074E6D4 /* sprites.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sprites.cpp; sourceTree = ""; }; + 063578D71EBF43DE0074E6D4 /* texture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texture.cpp; sourceTree = ""; }; + 063578D81EBF43DE0074E6D4 /* texturemanifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturemanifest.cpp; sourceTree = ""; }; + 063578D91EBF43DE0074E6D4 /* textures.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = textures.cpp; sourceTree = ""; }; + 063578DA1EBF43DE0074E6D4 /* texturescheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturescheme.cpp; sourceTree = ""; }; + 063578DB1EBF43DE0074E6D4 /* tga.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tga.cpp; sourceTree = ""; }; + 063578DC1EBF43DE0074E6D4 /* wav.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wav.cpp; sourceTree = ""; }; + 063578DE1EBF43DE0074E6D4 /* actions.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = actions.cpp; sourceTree = ""; }; + 063578DF1EBF43DE0074E6D4 /* bspnode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bspnode.cpp; sourceTree = ""; }; + 063578E01EBF43DE0074E6D4 /* detailtexturemateriallayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = detailtexturemateriallayer.cpp; sourceTree = ""; }; + 063578E11EBF43DE0074E6D4 /* dmuargs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dmuargs.cpp; sourceTree = ""; }; + 063578E21EBF43DE0074E6D4 /* entitydatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = entitydatabase.cpp; sourceTree = ""; }; + 063578E31EBF43DE0074E6D4 /* entitydef.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = entitydef.cpp; sourceTree = ""; }; + 063578E41EBF43DE0074E6D4 /* map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = map.cpp; sourceTree = ""; }; + 063578E51EBF43DE0074E6D4 /* mapelement.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapelement.cpp; sourceTree = ""; }; + 063578E61EBF43DE0074E6D4 /* material.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = material.cpp; sourceTree = ""; }; + 063578E71EBF43DE0074E6D4 /* materialarchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = materialarchive.cpp; sourceTree = ""; }; + 063578E81EBF43DE0074E6D4 /* materialmanifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = materialmanifest.cpp; sourceTree = ""; }; + 063578E91EBF43DE0074E6D4 /* materials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = materials.cpp; sourceTree = ""; }; + 063578EA1EBF43DE0074E6D4 /* materialscheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = materialscheme.cpp; sourceTree = ""; }; + 063578EB1EBF43DE0074E6D4 /* mobjthinkerdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mobjthinkerdata.cpp; sourceTree = ""; }; + 063578EC1EBF43DE0074E6D4 /* propertyvalue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = propertyvalue.cpp; sourceTree = ""; }; + 063578ED1EBF43DE0074E6D4 /* shinetexturemateriallayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shinetexturemateriallayer.cpp; sourceTree = ""; }; + 063578EE1EBF43DE0074E6D4 /* texturemateriallayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturemateriallayer.cpp; sourceTree = ""; }; + 063578EF1EBF43DE0074E6D4 /* thinker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thinker.cpp; sourceTree = ""; }; + 063578F01EBF43DE0074E6D4 /* thinkerdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thinkerdata.cpp; sourceTree = ""; }; + 063578F11EBF43DE0074E6D4 /* world.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = world.cpp; sourceTree = ""; }; + 063578F21EBF43DE0074E6D4 /* xg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = xg.cpp; sourceTree = ""; }; + 063578F31EBF43DE0074E6D4 /* abstractsession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = abstractsession.cpp; path = ../apps/libdoomsday/src/abstractsession.cpp; sourceTree = ""; }; + 063578F41EBF43DE0074E6D4 /* busymode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = busymode.cpp; path = ../apps/libdoomsday/src/busymode.cpp; sourceTree = ""; }; + 063578F51EBF43DE0074E6D4 /* doomsdayapp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = doomsdayapp.cpp; path = ../apps/libdoomsday/src/doomsdayapp.cpp; sourceTree = ""; }; + 063578F61EBF43DE0074E6D4 /* dualstring.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dualstring.cpp; path = ../apps/libdoomsday/src/dualstring.cpp; sourceTree = ""; }; + 063578F71EBF43DE0074E6D4 /* game_init.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = game_init.cpp; path = ../apps/libdoomsday/src/game_init.cpp; sourceTree = ""; }; + 063578F81EBF43DE0074E6D4 /* game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = game.cpp; path = ../apps/libdoomsday/src/game.cpp; sourceTree = ""; }; + 063578F91EBF43DE0074E6D4 /* gameprofiles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gameprofiles.cpp; path = ../apps/libdoomsday/src/gameprofiles.cpp; sourceTree = ""; }; + 063578FA1EBF43DE0074E6D4 /* games.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = games.cpp; path = ../apps/libdoomsday/src/games.cpp; sourceTree = ""; }; + 063578FB1EBF43DE0074E6D4 /* gamestatefolder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gamestatefolder.cpp; path = ../apps/libdoomsday/src/gamestatefolder.cpp; sourceTree = ""; }; + 063578FC1EBF43DE0074E6D4 /* help.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = help.cpp; path = ../apps/libdoomsday/src/help.cpp; sourceTree = ""; }; + 063578FD1EBF43DE0074E6D4 /* player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = player.cpp; path = ../apps/libdoomsday/src/player.cpp; sourceTree = ""; }; + 063578FE1EBF43DE0074E6D4 /* players.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = players.cpp; path = ../apps/libdoomsday/src/players.cpp; sourceTree = ""; }; + 063578FF1EBF43DE0074E6D4 /* plugins.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = plugins.cpp; path = ../apps/libdoomsday/src/plugins.cpp; sourceTree = ""; }; + 063579001EBF43DE0074E6D4 /* savegames.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = savegames.cpp; path = ../apps/libdoomsday/src/savegames.cpp; sourceTree = ""; }; + 063579011EBF43DE0074E6D4 /* uri.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = uri.cpp; path = ../apps/libdoomsday/src/uri.cpp; sourceTree = ""; }; + 063579021EBF43DE0074E6D4 /* urivalue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = urivalue.cpp; path = ../apps/libdoomsday/src/urivalue.cpp; sourceTree = ""; }; + 06357A7F1EBF5F250074E6D4 /* lzss.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; name = lzss.c; path = ../external/lzss/src/lzss.c; sourceTree = ""; }; + 06357AF01EBF61C70074E6D4 /* libdeng_gamefw.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_gamefw.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357AF21EBF62180074E6D4 /* libgamefw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = libgamefw.cpp; path = ../apps/plugins/libgamefw/src/libgamefw.cpp; sourceTree = ""; }; + 06357AF31EBF62180074E6D4 /* mapspot.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = mapspot.cpp; path = ../apps/plugins/libgamefw/src/mapspot.cpp; sourceTree = ""; }; + 06357B041EBF63770074E6D4 /* libimportdeh.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libimportdeh.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357B051EBF64DE0074E6D4 /* dehreader_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dehreader_util.cpp; path = ../apps/plugins/importdeh/src/dehreader_util.cpp; sourceTree = ""; }; + 06357B061EBF64DE0074E6D4 /* dehreader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dehreader.cpp; path = ../apps/plugins/importdeh/src/dehreader.cpp; sourceTree = ""; }; + 06357B071EBF64DE0074E6D4 /* importdeh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = importdeh.cpp; path = ../apps/plugins/importdeh/src/importdeh.cpp; sourceTree = ""; }; + 06357B081EBF64DE0074E6D4 /* info.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = info.cpp; path = ../apps/plugins/importdeh/src/info.cpp; sourceTree = ""; }; + 06357B181EBF69B50074E6D4 /* dehreader_util.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dehreader_util.h; path = ../apps/plugins/importdeh/include/dehreader_util.h; sourceTree = ""; }; + 06357B191EBF69B50074E6D4 /* dehreader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = dehreader.h; path = ../apps/plugins/importdeh/include/dehreader.h; sourceTree = ""; }; + 06357B1A1EBF69B50074E6D4 /* importdeh.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = importdeh.h; path = ../apps/plugins/importdeh/include/importdeh.h; sourceTree = ""; }; + 06357B1B1EBF69B50074E6D4 /* info.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = info.h; path = ../apps/plugins/importdeh/include/info.h; sourceTree = ""; }; + 06357B1C1EBF69B50074E6D4 /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../apps/plugins/importdeh/include/version.h; sourceTree = ""; }; + 06357B291EBF69C00074E6D4 /* libimportudmf.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libimportudmf.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357B2C1EBF6A660074E6D4 /* importudmf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = importudmf.cpp; path = ../apps/plugins/importudmf/src/importudmf.cpp; sourceTree = ""; }; + 06357B2D1EBF6A660074E6D4 /* udmflex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = udmflex.cpp; path = ../apps/plugins/importudmf/src/udmflex.cpp; sourceTree = ""; }; + 06357B2E1EBF6A660074E6D4 /* udmfparser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = udmfparser.cpp; path = ../apps/plugins/importudmf/src/udmfparser.cpp; sourceTree = ""; }; + 06357B3C1EBF6EBD0074E6D4 /* libdoom.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdoom.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357B3F1EBF6F5A0074E6D4 /* ammowidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ammowidget.cpp; sourceTree = ""; }; + 06357B401EBF6F5A0074E6D4 /* armoriconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = armoriconwidget.cpp; sourceTree = ""; }; + 06357B411EBF6F5A0074E6D4 /* facewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = facewidget.cpp; sourceTree = ""; }; + 06357B421EBF6F5A0074E6D4 /* healthiconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = healthiconwidget.cpp; sourceTree = ""; }; + 06357B431EBF6F5A0074E6D4 /* maxammowidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = maxammowidget.cpp; sourceTree = ""; }; + 06357B441EBF6F5A0074E6D4 /* weaponslotwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weaponslotwidget.cpp; sourceTree = ""; }; + 06357B451EBF6F5A0074E6D4 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = acfnlink.c; path = ../apps/plugins/doom/src/acfnlink.c; sourceTree = ""; }; + 06357B461EBF6F5A0074E6D4 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../apps/plugins/doom/src/m_random.c; sourceTree = ""; }; + 06357B471EBF6F5A0074E6D4 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../apps/plugins/doom/src/p_enemy.c; sourceTree = ""; }; + 06357B481EBF6F5A0074E6D4 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../apps/plugins/doom/src/p_inter.c; sourceTree = ""; }; + 06357B491EBF6F5A0074E6D4 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../apps/plugins/doom/src/p_maputl.c; sourceTree = ""; }; + 06357B4A1EBF6F5A0074E6D4 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../apps/plugins/doom/src/p_mobj.c; sourceTree = ""; }; + 06357B4B1EBF6F5A0074E6D4 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../apps/plugins/doom/src/p_pspr.c; sourceTree = ""; }; + 06357B4C1EBF6F5A0074E6D4 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../apps/plugins/doom/src/p_setup.c; sourceTree = ""; }; + 06357B4D1EBF6F5A0074E6D4 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../apps/plugins/doom/src/p_telept.c; sourceTree = ""; }; + 06357B4E1EBF6F5A0074E6D4 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../apps/plugins/doom/src/tables.c; sourceTree = ""; }; + 06357B4F1EBF6F5A0074E6D4 /* bossbrain.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = bossbrain.cpp; path = ../apps/plugins/doom/src/bossbrain.cpp; sourceTree = ""; }; + 06357B501EBF6F5A0074E6D4 /* d_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_api.cpp; path = ../apps/plugins/doom/src/d_api.cpp; sourceTree = ""; }; + 06357B511EBF6F5A0074E6D4 /* d_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_console.cpp; path = ../apps/plugins/doom/src/d_console.cpp; sourceTree = ""; }; + 06357B521EBF6F5A0074E6D4 /* d_items.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_items.cpp; path = ../apps/plugins/doom/src/d_items.cpp; sourceTree = ""; }; + 06357B531EBF6F5A0074E6D4 /* d_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_main.cpp; path = ../apps/plugins/doom/src/d_main.cpp; sourceTree = ""; }; + 06357B541EBF6F5A0074E6D4 /* d_refresh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_refresh.cpp; path = ../apps/plugins/doom/src/d_refresh.cpp; sourceTree = ""; }; + 06357B551EBF6F5A0074E6D4 /* doomv9mapstatereader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = doomv9mapstatereader.cpp; path = ../apps/plugins/doom/src/doomv9mapstatereader.cpp; sourceTree = ""; }; + 06357B561EBF6F5A0074E6D4 /* intermission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = intermission.cpp; path = ../apps/plugins/doom/src/intermission.cpp; sourceTree = ""; }; + 06357B571EBF6F5A0074E6D4 /* m_cheat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = m_cheat.cpp; path = ../apps/plugins/doom/src/m_cheat.cpp; sourceTree = ""; }; + 06357B581EBF6F5A0074E6D4 /* p_lights.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_lights.cpp; path = ../apps/plugins/doom/src/p_lights.cpp; sourceTree = ""; }; + 06357B591EBF6F5A0074E6D4 /* p_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_spec.cpp; path = ../apps/plugins/doom/src/p_spec.cpp; sourceTree = ""; }; + 06357B5A1EBF6F5A0074E6D4 /* st_stuff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = st_stuff.cpp; path = ../apps/plugins/doom/src/st_stuff.cpp; sourceTree = ""; }; + 06357B781EBF6F750074E6D4 /* interpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interpreter.cpp; sourceTree = ""; }; + 06357B791EBF6F750074E6D4 /* module.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = module.cpp; sourceTree = ""; }; + 06357B7A1EBF6F750074E6D4 /* script.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = script.cpp; sourceTree = ""; }; + 06357B7B1EBF6F750074E6D4 /* system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = system.cpp; sourceTree = ""; }; + 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_defs.cpp; sourceTree = ""; }; + 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_eventsequence.cpp; sourceTree = ""; }; + 06357B7F1EBF6F750074E6D4 /* g_game.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_game.cpp; sourceTree = ""; }; + 06357B801EBF6F750074E6D4 /* g_update.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = g_update.cpp; sourceTree = ""; }; + 06357B811EBF6F750074E6D4 /* gamerules.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamerules.cpp; sourceTree = ""; }; + 06357B821EBF6F750074E6D4 /* gamesession.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamesession.cpp; sourceTree = ""; }; + 06357B831EBF6F750074E6D4 /* saveslots.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = saveslots.cpp; sourceTree = ""; }; + 06357B851EBF6F750074E6D4 /* automapstyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = automapstyle.cpp; sourceTree = ""; }; + 06357B861EBF6F750074E6D4 /* hudwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hudwidget.cpp; sourceTree = ""; }; + 06357B881EBF6F750074E6D4 /* armorwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = armorwidget.cpp; sourceTree = ""; }; + 06357B891EBF6F750074E6D4 /* automapwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = automapwidget.cpp; sourceTree = ""; }; + 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chainwidget.cpp; sourceTree = ""; }; + 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = chatwidget.cpp; sourceTree = ""; }; + 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = flightwidget.cpp; sourceTree = ""; }; + 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fragswidget.cpp; sourceTree = ""; }; + 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = groupwidget.cpp; sourceTree = ""; }; + 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = healthwidget.cpp; sourceTree = ""; }; + 06357B901EBF6F750074E6D4 /* itemswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = itemswidget.cpp; sourceTree = ""; }; + 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyslotwidget.cpp; sourceTree = ""; }; + 06357B921EBF6F750074E6D4 /* keyswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keyswidget.cpp; sourceTree = ""; }; + 06357B931EBF6F750074E6D4 /* killswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = killswidget.cpp; sourceTree = ""; }; + 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playerlogwidget.cpp; sourceTree = ""; }; + 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = readyammoiconwidget.cpp; sourceTree = ""; }; + 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = readyammowidget.cpp; sourceTree = ""; }; + 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = readyitemwidget.cpp; sourceTree = ""; }; + 06357B981EBF6F750074E6D4 /* secretswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = secretswidget.cpp; sourceTree = ""; }; + 06357B9A1EBF6F760074E6D4 /* page.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = page.cpp; sourceTree = ""; }; + 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buttonwidget.cpp; sourceTree = ""; }; + 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coloreditwidget.cpp; sourceTree = ""; }; + 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarcoloreditwidget.cpp; sourceTree = ""; }; + 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarinlinelistwidget.cpp; sourceTree = ""; }; + 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarlineeditwidget.cpp; sourceTree = ""; }; + 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarsliderwidget.cpp; sourceTree = ""; }; + 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvartextualsliderwidget.cpp; sourceTree = ""; }; + 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvartogglewidget.cpp; sourceTree = ""; }; + 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inlinelistwidget.cpp; sourceTree = ""; }; + 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputbindingwidget.cpp; sourceTree = ""; }; + 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = labelwidget.cpp; sourceTree = ""; }; + 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lineeditwidget.cpp; sourceTree = ""; }; + 06357BA81EBF6F760074E6D4 /* listwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = listwidget.cpp; sourceTree = ""; }; + 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mobjpreviewwidget.cpp; sourceTree = ""; }; + 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rectwidget.cpp; sourceTree = ""; }; + 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sliderwidget.cpp; sourceTree = ""; }; + 06357BAC1EBF6F760074E6D4 /* widget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = widget.cpp; sourceTree = ""; }; + 06357BAE1EBF6F760074E6D4 /* d_net.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_net.cpp; sourceTree = ""; }; + 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_netcl.cpp; sourceTree = ""; }; + 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = d_netsv.cpp; sourceTree = ""; }; + 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dmu_lib.cpp; sourceTree = ""; }; + 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapstatereader.cpp; sourceTree = ""; }; + 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapstatewriter.cpp; sourceTree = ""; }; + 06357BB51EBF6F760074E6D4 /* mobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mobj.cpp; sourceTree = ""; }; + 06357BB61EBF6F760074E6D4 /* p_actor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_actor.cpp; sourceTree = ""; }; + 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_ceiling.cpp; sourceTree = ""; }; + 06357BB81EBF6F760074E6D4 /* p_door.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_door.cpp; sourceTree = ""; }; + 06357BB91EBF6F760074E6D4 /* p_floor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_floor.cpp; sourceTree = ""; }; + 06357BBA1EBF6F760074E6D4 /* p_map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_map.cpp; sourceTree = ""; }; + 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_mapsetup.cpp; sourceTree = ""; }; + 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_mapspec.cpp; sourceTree = ""; }; + 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_plat.cpp; sourceTree = ""; }; + 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_scroll.cpp; sourceTree = ""; }; + 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_sound.cpp; sourceTree = ""; }; + 06357BC01EBF6F760074E6D4 /* p_start.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_start.cpp; sourceTree = ""; }; + 06357BC11EBF6F760074E6D4 /* p_switch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_switch.cpp; sourceTree = ""; }; + 06357BC21EBF6F760074E6D4 /* p_tick.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_tick.cpp; sourceTree = ""; }; + 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_xgfile.cpp; sourceTree = ""; }; + 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_xgline.cpp; sourceTree = ""; }; + 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_xgsave.cpp; sourceTree = ""; }; + 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_xgsec.cpp; sourceTree = ""; }; + 06357BC71EBF6F760074E6D4 /* pause.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = pause.cpp; sourceTree = ""; }; + 06357BC81EBF6F760074E6D4 /* player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = player.cpp; sourceTree = ""; }; + 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polyobjs.cpp; sourceTree = ""; }; + 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thingarchive.cpp; sourceTree = ""; }; + 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thinkerinfo.cpp; sourceTree = ""; }; + 06357BCC1EBF6F760074E6D4 /* common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = common.c; path = ../apps/plugins/common/src/common.c; sourceTree = ""; }; + 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = hu_pspr.c; path = ../apps/plugins/common/src/hu_pspr.c; sourceTree = ""; }; + 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_iterlist.c; path = ../apps/plugins/common/src/p_iterlist.c; sourceTree = ""; }; + 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_terraintype.c; path = ../apps/plugins/common/src/p_terraintype.c; sourceTree = ""; }; + 06357BD01EBF6F760074E6D4 /* p_user.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_user.c; path = ../apps/plugins/common/src/p_user.c; sourceTree = ""; }; + 06357BD11EBF6F760074E6D4 /* p_view.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_view.c; path = ../apps/plugins/common/src/p_view.c; sourceTree = ""; }; + 06357BD21EBF6F760074E6D4 /* r_common.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = r_common.c; path = ../apps/plugins/common/src/r_common.c; sourceTree = ""; }; + 06357BD31EBF6F760074E6D4 /* x_hair.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = x_hair.c; path = ../apps/plugins/common/src/x_hair.c; sourceTree = ""; }; + 06357BD41EBF6F760074E6D4 /* animdefs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = animdefs.cpp; path = ../apps/plugins/common/src/animdefs.cpp; sourceTree = ""; }; + 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fi_lib.cpp; path = ../apps/plugins/common/src/fi_lib.cpp; sourceTree = ""; }; + 06357BD61EBF6F760074E6D4 /* g_controls.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = g_controls.cpp; path = ../apps/plugins/common/src/g_controls.cpp; sourceTree = ""; }; + 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = gl_drawpatch.cpp; path = ../apps/plugins/common/src/gl_drawpatch.cpp; sourceTree = ""; }; + 06357BD81EBF6F760074E6D4 /* hexlex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hexlex.cpp; path = ../apps/plugins/common/src/hexlex.cpp; sourceTree = ""; }; + 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hu_inventory.cpp; path = ../apps/plugins/common/src/hu_inventory.cpp; sourceTree = ""; }; + 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hu_lib.cpp; path = ../apps/plugins/common/src/hu_lib.cpp; sourceTree = ""; }; + 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hu_menu.cpp; path = ../apps/plugins/common/src/hu_menu.cpp; sourceTree = ""; }; + 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hu_msg.cpp; path = ../apps/plugins/common/src/hu_msg.cpp; sourceTree = ""; }; + 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hu_stuff.cpp; path = ../apps/plugins/common/src/hu_stuff.cpp; sourceTree = ""; }; + 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = m_ctrl.cpp; path = ../apps/plugins/common/src/m_ctrl.cpp; sourceTree = ""; }; + 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_inventory.cpp; path = ../apps/plugins/common/src/p_inventory.cpp; sourceTree = ""; }; + 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_saveg.cpp; path = ../apps/plugins/common/src/p_saveg.cpp; sourceTree = ""; }; + 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_saveio.cpp; path = ../apps/plugins/common/src/p_saveio.cpp; sourceTree = ""; }; + 06357CCB1EBF70A20074E6D4 /* libheretic.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libheretic.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357D351EBF71320074E6D4 /* tomeofpowerwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tomeofpowerwidget.cpp; sourceTree = ""; }; + 06357D361EBF71320074E6D4 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = acfnlink.c; path = ../apps/plugins/heretic/src/acfnlink.c; sourceTree = ""; }; + 06357D371EBF71320074E6D4 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../apps/plugins/heretic/src/m_random.c; sourceTree = ""; }; + 06357D381EBF71320074E6D4 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../apps/plugins/heretic/src/p_enemy.c; sourceTree = ""; }; + 06357D391EBF71320074E6D4 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../apps/plugins/heretic/src/p_inter.c; sourceTree = ""; }; + 06357D3A1EBF71320074E6D4 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../apps/plugins/heretic/src/p_maputl.c; sourceTree = ""; }; + 06357D3B1EBF71320074E6D4 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../apps/plugins/heretic/src/p_mobj.c; sourceTree = ""; }; + 06357D3C1EBF71320074E6D4 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../apps/plugins/heretic/src/p_pspr.c; sourceTree = ""; }; + 06357D3D1EBF71320074E6D4 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../apps/plugins/heretic/src/p_setup.c; sourceTree = ""; }; + 06357D3E1EBF71320074E6D4 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../apps/plugins/heretic/src/p_telept.c; sourceTree = ""; }; + 06357D3F1EBF71320074E6D4 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../apps/plugins/heretic/src/tables.c; sourceTree = ""; }; + 06357D401EBF71320074E6D4 /* h_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h_api.cpp; path = ../apps/plugins/heretic/src/h_api.cpp; sourceTree = ""; }; + 06357D411EBF71320074E6D4 /* h_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h_console.cpp; path = ../apps/plugins/heretic/src/h_console.cpp; sourceTree = ""; }; + 06357D421EBF71320074E6D4 /* h_items.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h_items.cpp; path = ../apps/plugins/heretic/src/h_items.cpp; sourceTree = ""; }; + 06357D431EBF71320074E6D4 /* h_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h_main.cpp; path = ../apps/plugins/heretic/src/h_main.cpp; sourceTree = ""; }; + 06357D441EBF71320074E6D4 /* h_refresh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h_refresh.cpp; path = ../apps/plugins/heretic/src/h_refresh.cpp; sourceTree = ""; }; + 06357D451EBF71320074E6D4 /* hereticv13mapstatereader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hereticv13mapstatereader.cpp; path = ../apps/plugins/heretic/src/hereticv13mapstatereader.cpp; sourceTree = ""; }; + 06357D461EBF71320074E6D4 /* intermission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = intermission.cpp; path = ../apps/plugins/heretic/src/intermission.cpp; sourceTree = ""; }; + 06357D471EBF71320074E6D4 /* m_cheat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = m_cheat.cpp; path = ../apps/plugins/heretic/src/m_cheat.cpp; sourceTree = ""; }; + 06357D481EBF71320074E6D4 /* p_lights.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_lights.cpp; path = ../apps/plugins/heretic/src/p_lights.cpp; sourceTree = ""; }; + 06357D491EBF71320074E6D4 /* p_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_spec.cpp; path = ../apps/plugins/heretic/src/p_spec.cpp; sourceTree = ""; }; + 06357D4A1EBF71320074E6D4 /* st_stuff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = st_stuff.cpp; path = ../apps/plugins/heretic/src/st_stuff.cpp; sourceTree = ""; }; + 06357DE11EBF728D0074E6D4 /* libhexen.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libhexen.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357DE41EBF73460074E6D4 /* armoriconswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = armoriconswidget.cpp; sourceTree = ""; }; + 06357DE51EBF73460074E6D4 /* bluemanaiconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bluemanaiconwidget.cpp; sourceTree = ""; }; + 06357DE61EBF73460074E6D4 /* bluemanavialwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bluemanavialwidget.cpp; sourceTree = ""; }; + 06357DE71EBF73460074E6D4 /* bluemanawidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bluemanawidget.cpp; sourceTree = ""; }; + 06357DE81EBF73460074E6D4 /* bootswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bootswidget.cpp; sourceTree = ""; }; + 06357DE91EBF73460074E6D4 /* defensewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = defensewidget.cpp; sourceTree = ""; }; + 06357DEA1EBF73460074E6D4 /* greenmanaiconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = greenmanaiconwidget.cpp; sourceTree = ""; }; + 06357DEB1EBF73460074E6D4 /* greenmanavialwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = greenmanavialwidget.cpp; sourceTree = ""; }; + 06357DEC1EBF73460074E6D4 /* greenmanawidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = greenmanawidget.cpp; sourceTree = ""; }; + 06357DED1EBF73460074E6D4 /* servantwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = servantwidget.cpp; sourceTree = ""; }; + 06357DEE1EBF73460074E6D4 /* weaponpieceswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = weaponpieceswidget.cpp; sourceTree = ""; }; + 06357DEF1EBF73460074E6D4 /* worldtimewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = worldtimewidget.cpp; sourceTree = ""; }; + 06357DF01EBF73460074E6D4 /* a_action.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = a_action.c; path = ../apps/plugins/hexen/src/a_action.c; sourceTree = ""; }; + 06357DF11EBF73460074E6D4 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = acfnlink.c; path = ../apps/plugins/hexen/src/acfnlink.c; sourceTree = ""; }; + 06357DF21EBF73460074E6D4 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../apps/plugins/hexen/src/m_random.c; sourceTree = ""; }; + 06357DF31EBF73460074E6D4 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../apps/plugins/hexen/src/p_enemy.c; sourceTree = ""; }; + 06357DF41EBF73460074E6D4 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../apps/plugins/hexen/src/p_inter.c; sourceTree = ""; }; + 06357DF51EBF73460074E6D4 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../apps/plugins/hexen/src/p_maputl.c; sourceTree = ""; }; + 06357DF61EBF73460074E6D4 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../apps/plugins/hexen/src/p_mobj.c; sourceTree = ""; }; + 06357DF71EBF73460074E6D4 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../apps/plugins/hexen/src/p_pspr.c; sourceTree = ""; }; + 06357DF81EBF73460074E6D4 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../apps/plugins/hexen/src/p_setup.c; sourceTree = ""; }; + 06357DF91EBF73460074E6D4 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../apps/plugins/hexen/src/p_telept.c; sourceTree = ""; }; + 06357DFA1EBF73460074E6D4 /* p_things.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_things.c; path = ../apps/plugins/hexen/src/p_things.c; sourceTree = ""; }; + 06357DFB1EBF73460074E6D4 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../apps/plugins/hexen/src/tables.c; sourceTree = ""; }; + 06357DFC1EBF73460074E6D4 /* h2_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = h2_main.cpp; path = ../apps/plugins/hexen/src/h2_main.cpp; sourceTree = ""; }; + 06357DFD1EBF73460074E6D4 /* hconsole.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hconsole.cpp; path = ../apps/plugins/hexen/src/hconsole.cpp; sourceTree = ""; }; + 06357DFE1EBF73460074E6D4 /* hrefresh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = hrefresh.cpp; path = ../apps/plugins/hexen/src/hrefresh.cpp; sourceTree = ""; }; + 06357DFF1EBF73460074E6D4 /* intermission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = intermission.cpp; path = ../apps/plugins/hexen/src/intermission.cpp; sourceTree = ""; }; + 06357E001EBF73460074E6D4 /* lightninganimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = lightninganimator.cpp; path = ../apps/plugins/hexen/src/lightninganimator.cpp; sourceTree = ""; }; + 06357E011EBF73460074E6D4 /* m_cheat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = m_cheat.cpp; path = ../apps/plugins/hexen/src/m_cheat.cpp; sourceTree = ""; }; + 06357E021EBF73460074E6D4 /* p_lights.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_lights.cpp; path = ../apps/plugins/hexen/src/p_lights.cpp; sourceTree = ""; }; + 06357E031EBF73460074E6D4 /* p_pillar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_pillar.cpp; path = ../apps/plugins/hexen/src/p_pillar.cpp; sourceTree = ""; }; + 06357E041EBF73460074E6D4 /* p_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_spec.cpp; path = ../apps/plugins/hexen/src/p_spec.cpp; sourceTree = ""; }; + 06357E051EBF73460074E6D4 /* p_waggle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_waggle.cpp; path = ../apps/plugins/hexen/src/p_waggle.cpp; sourceTree = ""; }; + 06357E061EBF73460074E6D4 /* sn_sonix.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sn_sonix.cpp; path = ../apps/plugins/hexen/src/sn_sonix.cpp; sourceTree = ""; }; + 06357E071EBF73460074E6D4 /* st_stuff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = st_stuff.cpp; path = ../apps/plugins/hexen/src/st_stuff.cpp; sourceTree = ""; }; + 06357E081EBF73460074E6D4 /* x_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = x_api.cpp; path = ../apps/plugins/hexen/src/x_api.cpp; sourceTree = ""; }; + 06357EED1EBF76120074E6D4 /* libdoom64.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdoom64.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357EF01EBF767C0074E6D4 /* armoriconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = armoriconwidget.cpp; sourceTree = ""; }; + 06357EF11EBF767C0074E6D4 /* healthiconwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = healthiconwidget.cpp; sourceTree = ""; }; + 06357EF51EBF767C0074E6D4 /* acfnlink.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = acfnlink.c; path = ../apps/plugins/doom64/src/acfnlink.c; sourceTree = ""; }; + 06357EF61EBF767C0074E6D4 /* m_random.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = m_random.c; path = ../apps/plugins/doom64/src/m_random.c; sourceTree = ""; }; + 06357EF71EBF767C0074E6D4 /* p_enemy.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_enemy.c; path = ../apps/plugins/doom64/src/p_enemy.c; sourceTree = ""; }; + 06357EF81EBF767C0074E6D4 /* p_inter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_inter.c; path = ../apps/plugins/doom64/src/p_inter.c; sourceTree = ""; }; + 06357EF91EBF767C0074E6D4 /* p_maputl.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_maputl.c; path = ../apps/plugins/doom64/src/p_maputl.c; sourceTree = ""; }; + 06357EFA1EBF767C0074E6D4 /* p_mobj.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_mobj.c; path = ../apps/plugins/doom64/src/p_mobj.c; sourceTree = ""; }; + 06357EFB1EBF767C0074E6D4 /* p_pspr.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_pspr.c; path = ../apps/plugins/doom64/src/p_pspr.c; sourceTree = ""; }; + 06357EFC1EBF767C0074E6D4 /* p_setup.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_setup.c; path = ../apps/plugins/doom64/src/p_setup.c; sourceTree = ""; }; + 06357EFD1EBF767C0074E6D4 /* p_telept.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = p_telept.c; path = ../apps/plugins/doom64/src/p_telept.c; sourceTree = ""; }; + 06357EFE1EBF767C0074E6D4 /* tables.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = tables.c; path = ../apps/plugins/doom64/src/tables.c; sourceTree = ""; }; + 06357EFF1EBF767C0074E6D4 /* d_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_console.cpp; path = ../apps/plugins/doom64/src/d_console.cpp; sourceTree = ""; }; + 06357F001EBF767C0074E6D4 /* d_items.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_items.cpp; path = ../apps/plugins/doom64/src/d_items.cpp; sourceTree = ""; }; + 06357F011EBF767C0074E6D4 /* d_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_main.cpp; path = ../apps/plugins/doom64/src/d_main.cpp; sourceTree = ""; }; + 06357F021EBF767C0074E6D4 /* d_refresh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d_refresh.cpp; path = ../apps/plugins/doom64/src/d_refresh.cpp; sourceTree = ""; }; + 06357F031EBF767C0074E6D4 /* d64_api.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = d64_api.cpp; path = ../apps/plugins/doom64/src/d64_api.cpp; sourceTree = ""; }; + 06357F041EBF767C0074E6D4 /* intermission.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = intermission.cpp; path = ../apps/plugins/doom64/src/intermission.cpp; sourceTree = ""; }; + 06357F051EBF767C0074E6D4 /* m_cheat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = m_cheat.cpp; path = ../apps/plugins/doom64/src/m_cheat.cpp; sourceTree = ""; }; + 06357F061EBF767C0074E6D4 /* p_lights.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_lights.cpp; path = ../apps/plugins/doom64/src/p_lights.cpp; sourceTree = ""; }; + 06357F071EBF767C0074E6D4 /* p_spec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = p_spec.cpp; path = ../apps/plugins/doom64/src/p_spec.cpp; sourceTree = ""; }; + 06357F081EBF767C0074E6D4 /* st_stuff.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = st_stuff.cpp; path = ../apps/plugins/doom64/src/st_stuff.cpp; sourceTree = ""; }; + 06357F421EBF77A00074E6D4 /* libaudio_fmod.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libaudio_fmod.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 06357F431EBF78420074E6D4 /* driver_fmod.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = driver_fmod.cpp; path = ../apps/plugins/fmod/src/driver_fmod.cpp; sourceTree = ""; }; + 06357F441EBF78420074E6D4 /* fmod_cd.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fmod_cd.cpp; path = ../apps/plugins/fmod/src/fmod_cd.cpp; sourceTree = ""; }; + 06357F451EBF78420074E6D4 /* fmod_music.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fmod_music.cpp; path = ../apps/plugins/fmod/src/fmod_music.cpp; sourceTree = ""; }; + 06357F461EBF78420074E6D4 /* fmod_sfx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fmod_sfx.cpp; path = ../apps/plugins/fmod/src/fmod_sfx.cpp; sourceTree = ""; }; + 06357F471EBF78420074E6D4 /* fmod_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = fmod_util.cpp; path = ../apps/plugins/fmod/src/fmod_util.cpp; sourceTree = ""; }; + 06357F561EBF7AE50074E6D4 /* audiodriver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiodriver.cpp; sourceTree = ""; }; + 06357F581EBF7AE50074E6D4 /* audiosystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiosystem.cpp; sourceTree = ""; }; + 06357F5A1EBF7AE50074E6D4 /* s_cache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = s_cache.cpp; sourceTree = ""; }; + 06357F5B1EBF7AE50074E6D4 /* m_mus2midi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = m_mus2midi.cpp; sourceTree = ""; }; + 06357F5C1EBF7AE50074E6D4 /* s_environ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = s_environ.cpp; sourceTree = ""; }; + 06357F5D1EBF7AE50074E6D4 /* sfxchannel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sfxchannel.cpp; sourceTree = ""; }; + 06357F5E1EBF7AE50074E6D4 /* sys_audiod_dummy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_audiod_dummy.cpp; sourceTree = ""; }; + 06357F5F1EBF7AE50074E6D4 /* sys_audiod_sdlmixer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_audiod_sdlmixer.cpp; sourceTree = ""; }; + 06357F611EBF7AE50074E6D4 /* cl_frame.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_frame.cpp; sourceTree = ""; }; + 06357F621EBF7AE50074E6D4 /* cl_infine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_infine.cpp; sourceTree = ""; }; + 06357F631EBF7AE50074E6D4 /* cl_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_main.cpp; sourceTree = ""; }; + 06357F641EBF7AE50074E6D4 /* cl_mobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_mobj.cpp; sourceTree = ""; }; + 06357F651EBF7AE50074E6D4 /* cl_player.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_player.cpp; sourceTree = ""; }; + 06357F661EBF7AE50074E6D4 /* cl_sound.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_sound.cpp; sourceTree = ""; }; + 06357F671EBF7AE50074E6D4 /* cl_world.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cl_world.cpp; sourceTree = ""; }; + 06357F681EBF7AE50074E6D4 /* cledgeloop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cledgeloop.cpp; sourceTree = ""; }; + 06357F691EBF7AE50074E6D4 /* clientsubsector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientsubsector.cpp; sourceTree = ""; }; + 06357F6A1EBF7AE50074E6D4 /* clplanemover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clplanemover.cpp; sourceTree = ""; }; + 06357F6B1EBF7AE50074E6D4 /* clpolymover.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clpolymover.cpp; sourceTree = ""; }; + 06357F6C1EBF7AE50074E6D4 /* clskyplane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clskyplane.cpp; sourceTree = ""; }; + 06357F6E1EBF7AE50074E6D4 /* dgl_common.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dgl_common.cpp; sourceTree = ""; }; + 06357F6F1EBF7AE50074E6D4 /* dgl_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dgl_draw.cpp; sourceTree = ""; }; + 06357F701EBF7AE50074E6D4 /* gl_defer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_defer.cpp; sourceTree = ""; }; + 06357F711EBF7AE50074E6D4 /* gl_deferredapi.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_deferredapi.cpp; sourceTree = ""; }; + 06357F721EBF7AE50074E6D4 /* gl_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_draw.cpp; sourceTree = ""; }; + 06357F731EBF7AE50074E6D4 /* gl_drawvectorgraphic.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_drawvectorgraphic.cpp; sourceTree = ""; }; + 06357F741EBF7AE50074E6D4 /* gl_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_main.cpp; sourceTree = ""; }; + 06357F751EBF7AE50074E6D4 /* gl_tex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_tex.cpp; sourceTree = ""; }; + 06357F761EBF7AE50074E6D4 /* gl_texmanager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gl_texmanager.cpp; sourceTree = ""; }; + 06357F771EBF7AE50074E6D4 /* svg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = svg.cpp; sourceTree = ""; }; + 06357F781EBF7AE50074E6D4 /* sys_opengl.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_opengl.cpp; sourceTree = ""; }; + 06357F791EBF7AE50074E6D4 /* texturecontent.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturecontent.cpp; sourceTree = ""; }; + 06357F7B1EBF7AE50074E6D4 /* color.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = color.cpp; sourceTree = ""; }; + 06357F7C1EBF7AE50074E6D4 /* face.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = face.cpp; sourceTree = ""; }; + 06357F7D1EBF7AE50074E6D4 /* hedge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hedge.cpp; sourceTree = ""; }; + 06357F7E1EBF7AE50074E6D4 /* mesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mesh.cpp; sourceTree = ""; }; + 06357F7F1EBF7AE50074E6D4 /* r_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = r_util.cpp; sourceTree = ""; }; + 06357F801EBF7AE50074E6D4 /* tab_tables.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tab_tables.cpp; sourceTree = ""; }; + 06357F831EBF7AE50074E6D4 /* masterserver.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = masterserver.cpp; sourceTree = ""; }; + 06357F841EBF7AE50074E6D4 /* monitor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = monitor.cpp; sourceTree = ""; }; + 06357F851EBF7AE50074E6D4 /* net_buf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_buf.cpp; sourceTree = ""; }; + 06357F861EBF7AE50074E6D4 /* net_event.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_event.cpp; sourceTree = ""; }; + 06357F871EBF7AE50074E6D4 /* net_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_main.cpp; sourceTree = ""; }; + 06357F881EBF7AE50074E6D4 /* net_msg.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_msg.cpp; sourceTree = ""; }; + 06357F891EBF7AE50074E6D4 /* net_ping.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_ping.cpp; sourceTree = ""; }; + 06357F8B1EBF7AE50074E6D4 /* net_demo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = net_demo.cpp; sourceTree = ""; }; + 06357F8C1EBF7AE50074E6D4 /* serverlink.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serverlink.cpp; sourceTree = ""; }; + 06357F8D1EBF7AE50074E6D4 /* sys_network.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_network.cpp; sourceTree = ""; }; + 06357F8F1EBF7AE50074E6D4 /* angleclipper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = angleclipper.cpp; sourceTree = ""; }; + 06357F901EBF7AE50074E6D4 /* api_render.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_render.cpp; sourceTree = ""; }; + 06357F911EBF7AE50074E6D4 /* billboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = billboard.cpp; sourceTree = ""; }; + 06357F921EBF7AE50074E6D4 /* blockmapvisual.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blockmapvisual.cpp; sourceTree = ""; }; + 06357F931EBF7AE50074E6D4 /* cameralensfx.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cameralensfx.cpp; sourceTree = ""; }; + 06357F941EBF7AE50074E6D4 /* consoleeffect.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = consoleeffect.cpp; sourceTree = ""; }; + 06357F951EBF7AE50074E6D4 /* decoration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = decoration.cpp; sourceTree = ""; }; + 06357F961EBF7AE50074E6D4 /* drawlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawlist.cpp; sourceTree = ""; }; + 06357F971EBF7AE50074E6D4 /* drawlists.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = drawlists.cpp; sourceTree = ""; }; + 06357F981EBF7AE50074E6D4 /* environ.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = environ.cpp; sourceTree = ""; }; + 06357F9A1EBF7AE50074E6D4 /* bloom.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bloom.cpp; sourceTree = ""; }; + 06357F9B1EBF7AE50074E6D4 /* colorfilter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = colorfilter.cpp; sourceTree = ""; }; + 06357F9C1EBF7AE50074E6D4 /* lensflares.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lensflares.cpp; sourceTree = ""; }; + 06357F9D1EBF7AE50074E6D4 /* vignette.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vignette.cpp; sourceTree = ""; }; + 06357F9E1EBF7AE50074E6D4 /* lightdecoration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lightdecoration.cpp; sourceTree = ""; }; + 06357F9F1EBF7AE50074E6D4 /* lumobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lumobj.cpp; sourceTree = ""; }; + 06357FA01EBF7AE50074E6D4 /* model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = model.cpp; sourceTree = ""; }; + 06357FA11EBF7AE50074E6D4 /* modelloader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modelloader.cpp; sourceTree = ""; }; + 06357FA21EBF7AE50074E6D4 /* modelrenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modelrenderer.cpp; sourceTree = ""; }; + 06357FA31EBF7AE50074E6D4 /* playerweaponanimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = playerweaponanimator.cpp; sourceTree = ""; }; + 06357FA41EBF7AE50074E6D4 /* projectionlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = projectionlist.cpp; sourceTree = ""; }; + 06357FA51EBF7AE50074E6D4 /* r_draw.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = r_draw.cpp; sourceTree = ""; }; + 06357FA61EBF7AE50074E6D4 /* r_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = r_main.cpp; sourceTree = ""; }; + 06357FA71EBF7AE50074E6D4 /* r_things.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = r_things.cpp; sourceTree = ""; }; + 06357FA81EBF7AE50074E6D4 /* rend_fakeradio.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_fakeradio.cpp; sourceTree = ""; }; + 06357FA91EBF7AE50074E6D4 /* rend_font.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_font.cpp; sourceTree = ""; }; + 06357FAA1EBF7AE50074E6D4 /* rend_halo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_halo.cpp; sourceTree = ""; }; + 06357FAB1EBF7AE50074E6D4 /* rend_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_main.cpp; sourceTree = ""; }; + 06357FAC1EBF7AE50074E6D4 /* rend_model.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_model.cpp; sourceTree = ""; }; + 06357FAD1EBF7AE50074E6D4 /* rend_particle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rend_particle.cpp; sourceTree = ""; }; + 06357FAE1EBF7AE50074E6D4 /* rendersystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rendersystem.cpp; sourceTree = ""; }; + 06357FAF1EBF7AE50074E6D4 /* rendpoly.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rendpoly.cpp; sourceTree = ""; }; + 06357FB01EBF7AE50074E6D4 /* shadervar.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shadervar.cpp; sourceTree = ""; }; + 06357FB11EBF7AE50074E6D4 /* shadowedge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = shadowedge.cpp; sourceTree = ""; }; + 06357FB21EBF7AE50074E6D4 /* skydrawable.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skydrawable.cpp; sourceTree = ""; }; + 06357FB31EBF7AE50074E6D4 /* skyfixedge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = skyfixedge.cpp; sourceTree = ""; }; + 06357FB41EBF7AE50074E6D4 /* stateanimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = stateanimator.cpp; sourceTree = ""; }; + 06357FB51EBF7AE50074E6D4 /* store.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = store.cpp; sourceTree = ""; }; + 06357FB61EBF7AE50074E6D4 /* trianglestripbuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = trianglestripbuilder.cpp; sourceTree = ""; }; + 06357FB71EBF7AE50074E6D4 /* vectorlightlist.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vectorlightlist.cpp; sourceTree = ""; }; + 06357FB81EBF7AE50074E6D4 /* viewports.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = viewports.cpp; sourceTree = ""; }; + 06357FB91EBF7AE50074E6D4 /* vissprite.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vissprite.cpp; sourceTree = ""; }; + 06357FBA1EBF7AE50074E6D4 /* vr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vr.cpp; sourceTree = ""; }; + 06357FBB1EBF7AE50074E6D4 /* walledge.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = walledge.cpp; sourceTree = ""; }; + 06357FBC1EBF7AE50074E6D4 /* wallspec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = wallspec.cpp; sourceTree = ""; }; + 06357FBE1EBF7AE50074E6D4 /* abstractfont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = abstractfont.cpp; sourceTree = ""; }; + 06357FC01EBF7AE50074E6D4 /* api_material.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_material.cpp; sourceTree = ""; }; + 06357FC11EBF7AE50074E6D4 /* api_resource.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = api_resource.cpp; sourceTree = ""; }; + 06357FC31EBF7AE50074E6D4 /* bitmapfont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bitmapfont.cpp; sourceTree = ""; }; + 06357FC41EBF7AE50074E6D4 /* clientmaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientmaterial.cpp; sourceTree = ""; }; + 06357FC51EBF7AE50074E6D4 /* clientresources.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientresources.cpp; sourceTree = ""; }; + 06357FC61EBF7AE50074E6D4 /* clienttexture.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clienttexture.cpp; sourceTree = ""; }; + 06357FC71EBF7AE50074E6D4 /* compositebitmapfont.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = compositebitmapfont.cpp; sourceTree = ""; }; + 06357FC81EBF7AE50074E6D4 /* fontmanifest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fontmanifest.cpp; sourceTree = ""; }; + 06357FC91EBF7AE50074E6D4 /* fonts.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fonts.cpp; sourceTree = ""; }; + 06357FCA1EBF7AE50074E6D4 /* fontscheme.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fontscheme.cpp; sourceTree = ""; }; + 06357FCB1EBF7AE50074E6D4 /* framemodel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = framemodel.cpp; sourceTree = ""; }; + 06357FCC1EBF7AE50074E6D4 /* hq2x.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hq2x.cpp; sourceTree = ""; }; + 06357FCD1EBF7AE50074E6D4 /* idtech1image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = idtech1image.cpp; sourceTree = ""; }; + 06357FCE1EBF7AE50074E6D4 /* image.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = image.cpp; sourceTree = ""; }; + 06357FCF1EBF7AE50074E6D4 /* lightmaterialdecoration.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lightmaterialdecoration.cpp; sourceTree = ""; }; + 06357FD01EBF7AE50074E6D4 /* materialanimator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = materialanimator.cpp; sourceTree = ""; }; + 06357FD11EBF7AE50074E6D4 /* texturevariant.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = texturevariant.cpp; sourceTree = ""; }; + 06357FD31EBF7AE50074E6D4 /* alertmask.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alertmask.cpp; sourceTree = ""; }; + 06357FD41EBF7AE50074E6D4 /* axisinputcontrol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = axisinputcontrol.cpp; sourceTree = ""; }; + 06357FD51EBF7AE50074E6D4 /* b_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b_main.cpp; sourceTree = ""; }; + 06357FD61EBF7AE50074E6D4 /* b_util.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = b_util.cpp; sourceTree = ""; }; + 06357FD71EBF7AE50074E6D4 /* bindcontext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bindcontext.cpp; sourceTree = ""; }; + 06357FD81EBF7AE50074E6D4 /* binding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = binding.cpp; sourceTree = ""; }; + 06357FD91EBF7AE50074E6D4 /* busyvisual.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = busyvisual.cpp; sourceTree = ""; }; + 06357FDA1EBF7AE50074E6D4 /* buttoninputcontrol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = buttoninputcontrol.cpp; sourceTree = ""; }; + 06357FDB1EBF7AE50074E6D4 /* clientrootwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientrootwidget.cpp; sourceTree = ""; }; + 06357FDC1EBF7AE50074E6D4 /* clientstyle.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientstyle.cpp; sourceTree = ""; }; + 06357FDD1EBF7AE50074E6D4 /* clientwindow.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientwindow.cpp; sourceTree = ""; }; + 06357FDE1EBF7AE50074E6D4 /* clientwindowsystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientwindowsystem.cpp; sourceTree = ""; }; + 06357FDF1EBF7AE50074E6D4 /* commandaction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commandaction.cpp; sourceTree = ""; }; + 06357FE01EBF7AE50074E6D4 /* commandbinding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = commandbinding.cpp; sourceTree = ""; }; + 06357FE11EBF7AE50074E6D4 /* controllerpresets.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = controllerpresets.cpp; sourceTree = ""; }; + 06357FE31EBF7AE50074E6D4 /* aboutdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = aboutdialog.cpp; sourceTree = ""; }; + 06357FE41EBF7AE50074E6D4 /* alertdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = alertdialog.cpp; sourceTree = ""; }; + 06357FE51EBF7AE50074E6D4 /* audiosettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = audiosettingsdialog.cpp; sourceTree = ""; }; + 06357FE61EBF7AE50074E6D4 /* coloradjustmentdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = coloradjustmentdialog.cpp; sourceTree = ""; }; + 06357FE71EBF7AE50074E6D4 /* createprofiledialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = createprofiledialog.cpp; sourceTree = ""; }; + 06357FE81EBF7AE50074E6D4 /* datafilesettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = datafilesettingsdialog.cpp; sourceTree = ""; }; + 06357FE91EBF7AE50074E6D4 /* inputsettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputsettingsdialog.cpp; sourceTree = ""; }; + 06357FEA1EBF7AE50074E6D4 /* logsettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = logsettingsdialog.cpp; sourceTree = ""; }; + 06357FEB1EBF7AE50074E6D4 /* manualconnectiondialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = manualconnectiondialog.cpp; sourceTree = ""; }; + 06357FEC1EBF7AE50074E6D4 /* networksettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = networksettingsdialog.cpp; sourceTree = ""; }; + 06357FED1EBF7AE50074E6D4 /* packagecompatibilitydialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagecompatibilitydialog.cpp; sourceTree = ""; }; + 06357FEE1EBF7AE50074E6D4 /* packageinfodialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packageinfodialog.cpp; sourceTree = ""; }; + 06357FEF1EBF7AE50074E6D4 /* packagesdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagesdialog.cpp; sourceTree = ""; }; + 06357FF01EBF7AE50074E6D4 /* renderersettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = renderersettingsdialog.cpp; sourceTree = ""; }; + 06357FF11EBF7AE50074E6D4 /* serverinfodialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = serverinfodialog.cpp; sourceTree = ""; }; + 06357FF21EBF7AE50074E6D4 /* uisettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = uisettingsdialog.cpp; sourceTree = ""; }; + 06357FF31EBF7AE50074E6D4 /* videosettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = videosettingsdialog.cpp; sourceTree = ""; }; + 06357FF41EBF7AE50074E6D4 /* vrsettingsdialog.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vrsettingsdialog.cpp; sourceTree = ""; }; + 06357FF61EBF7AE50074E6D4 /* modelasseteditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = modelasseteditor.cpp; sourceTree = ""; }; + 06357FF71EBF7AE50074E6D4 /* rendererappearanceeditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = rendererappearanceeditor.cpp; sourceTree = ""; }; + 06357FF81EBF7AE50074E6D4 /* variablegroupeditor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = variablegroupeditor.cpp; sourceTree = ""; }; + 06357FF91EBF7AE50074E6D4 /* hatinputcontrol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hatinputcontrol.cpp; sourceTree = ""; }; + 06357FFB1EBF7AE50074E6D4 /* columnwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = columnwidget.cpp; sourceTree = ""; }; + 06357FFC1EBF7AE50074E6D4 /* gamecolumnwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamecolumnwidget.cpp; sourceTree = ""; }; + 06357FFD1EBF7AE50074E6D4 /* gamepanelbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamepanelbuttonwidget.cpp; sourceTree = ""; }; + 06357FFE1EBF7AE50074E6D4 /* headerwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = headerwidget.cpp; sourceTree = ""; }; + 06357FFF1EBF7AE50074E6D4 /* homewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = homewidget.cpp; sourceTree = ""; }; + 063580001EBF7AE50074E6D4 /* multiplayercolumnwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayercolumnwidget.cpp; sourceTree = ""; }; + 063580011EBF7AE50074E6D4 /* multiplayerpanelbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayerpanelbuttonwidget.cpp; sourceTree = ""; }; + 063580021EBF7AE50074E6D4 /* nogamescolumnwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nogamescolumnwidget.cpp; sourceTree = ""; }; + 063580031EBF7AE50074E6D4 /* packagescolumnwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagescolumnwidget.cpp; sourceTree = ""; }; + 063580041EBF7AE50074E6D4 /* savelistwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = savelistwidget.cpp; sourceTree = ""; }; + 063580051EBF7AE50074E6D4 /* impulsebinding.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = impulsebinding.cpp; sourceTree = ""; }; + 063580071EBF7AE50074E6D4 /* finale.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finale.cpp; sourceTree = ""; }; + 063580081EBF7AE50074E6D4 /* finaleanimwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finaleanimwidget.cpp; sourceTree = ""; }; + 063580091EBF7AE50074E6D4 /* finaleinterpreter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finaleinterpreter.cpp; sourceTree = ""; }; + 0635800A1EBF7AE50074E6D4 /* finalepagewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finalepagewidget.cpp; sourceTree = ""; }; + 0635800B1EBF7AE50074E6D4 /* finaletextwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finaletextwidget.cpp; sourceTree = ""; }; + 0635800C1EBF7AE50074E6D4 /* finalewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = finalewidget.cpp; sourceTree = ""; }; + 0635800D1EBF7AE50074E6D4 /* infinesystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = infinesystem.cpp; sourceTree = ""; }; + 0635800E1EBF7AE50074E6D4 /* inputdebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputdebug.cpp; sourceTree = ""; }; + 0635800F1EBF7AE50074E6D4 /* inputdevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputdevice.cpp; sourceTree = ""; }; + 063580101EBF7AE50074E6D4 /* inputsystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputsystem.cpp; sourceTree = ""; }; + 063580111EBF7AE50074E6D4 /* mouse_qt.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mouse_qt.cpp; sourceTree = ""; }; + 063580121EBF7AE50074E6D4 /* nativemenu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nativemenu.cpp; sourceTree = ""; }; + 063580131EBF7AE50074E6D4 /* nativeui.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = nativeui.cpp; sourceTree = ""; }; + 063580141EBF7AE50074E6D4 /* postprocessing.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = postprocessing.cpp; sourceTree = ""; }; + 063580151EBF7AE50074E6D4 /* progress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = progress.cpp; sourceTree = ""; }; + 063580161EBF7AE50074E6D4 /* savelistdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = savelistdata.cpp; sourceTree = ""; }; + 063580171EBF7AE50074E6D4 /* splash.xpm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = splash.xpm; sourceTree = ""; }; + 063580181EBF7AE50074E6D4 /* styledlogsinkformatter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = styledlogsinkformatter.cpp; sourceTree = ""; }; + 063580191EBF7AE50074E6D4 /* sys_input.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sys_input.cpp; sourceTree = ""; }; + 0635801A1EBF7AE50074E6D4 /* ui_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ui_main.cpp; sourceTree = ""; }; + 0635801B1EBF7AE50074E6D4 /* viewcompositor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = viewcompositor.cpp; sourceTree = ""; }; + 0635801D1EBF7AE50074E6D4 /* busywidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = busywidget.cpp; sourceTree = ""; }; + 0635801E1EBF7AE50074E6D4 /* consolecommandwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = consolecommandwidget.cpp; sourceTree = ""; }; + 0635801F1EBF7AE50074E6D4 /* consolewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = consolewidget.cpp; sourceTree = ""; }; + 063580201EBF7AE50074E6D4 /* cvarchoicewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarchoicewidget.cpp; sourceTree = ""; }; + 063580211EBF7AE50074E6D4 /* cvarlineeditwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarlineeditwidget.cpp; sourceTree = ""; }; + 063580221EBF7AE50074E6D4 /* cvarnativepathwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarnativepathwidget.cpp; sourceTree = ""; }; + 063580231EBF7AE50074E6D4 /* cvarsliderwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvarsliderwidget.cpp; sourceTree = ""; }; + 063580241EBF7AE50074E6D4 /* cvartogglewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = cvartogglewidget.cpp; sourceTree = ""; }; + 063580251EBF7AE50074E6D4 /* gamewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = gamewidget.cpp; sourceTree = ""; }; + 063580261EBF7AE50074E6D4 /* homeitemwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = homeitemwidget.cpp; sourceTree = ""; }; + 063580271EBF7AE50074E6D4 /* homemenuwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = homemenuwidget.cpp; sourceTree = ""; }; + 063580281EBF7AE50074E6D4 /* inputbindingwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = inputbindingwidget.cpp; sourceTree = ""; }; + 063580291EBF7AE50074E6D4 /* keygrabberwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = keygrabberwidget.cpp; sourceTree = ""; }; + 0635802A1EBF7AE50074E6D4 /* mapoutlinewidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapoutlinewidget.cpp; sourceTree = ""; }; + 0635802B1EBF7AE50074E6D4 /* multiplayerservermenuwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayerservermenuwidget.cpp; sourceTree = ""; }; + 0635802C1EBF7AE50074E6D4 /* multiplayerstatuswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = multiplayerstatuswidget.cpp; sourceTree = ""; }; + 0635802D1EBF7AE50074E6D4 /* packagecontentoptionswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagecontentoptionswidget.cpp; sourceTree = ""; }; + 0635802E1EBF7AE50074E6D4 /* packagesbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagesbuttonwidget.cpp; sourceTree = ""; }; + 0635802F1EBF7AE50074E6D4 /* packagessidebarwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packagessidebarwidget.cpp; sourceTree = ""; }; + 063580301EBF7AE50074E6D4 /* packageswidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = packageswidget.cpp; sourceTree = ""; }; + 063580311EBF7AE50074E6D4 /* panelbuttonwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = panelbuttonwidget.cpp; sourceTree = ""; }; + 063580321EBF7AE50074E6D4 /* privilegedlogwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = privilegedlogwidget.cpp; sourceTree = ""; }; + 063580331EBF7AE50074E6D4 /* profilepickerwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = profilepickerwidget.cpp; sourceTree = ""; }; + 063580341EBF7AE50074E6D4 /* sidebarwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sidebarwidget.cpp; sourceTree = ""; }; + 063580351EBF7AE50074E6D4 /* taskbarwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = taskbarwidget.cpp; sourceTree = ""; }; + 063580361EBF7AE50074E6D4 /* tutorialwidget.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = tutorialwidget.cpp; sourceTree = ""; }; + 063580371EBF7AE50074E6D4 /* zonedebug.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = zonedebug.cpp; sourceTree = ""; }; + 063580391EBF7AE50074E6D4 /* dd_uinit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = dd_uinit.cpp; sourceTree = ""; }; + 0635803A1EBF7AE50074E6D4 /* joystick.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = joystick.cpp; sourceTree = ""; }; + 0635803D1EBF7AE50074E6D4 /* bindings_world.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bindings_world.cpp; sourceTree = ""; }; + 0635803E1EBF7AE50074E6D4 /* blockmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = blockmap.cpp; sourceTree = ""; }; + 0635803F1EBF7AE50074E6D4 /* bspleaf.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bspleaf.cpp; sourceTree = ""; }; + 063580401EBF7AE50074E6D4 /* clientserverworld.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientserverworld.cpp; sourceTree = ""; }; + 063580411EBF7AE50074E6D4 /* convexsubspace.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = convexsubspace.cpp; sourceTree = ""; }; + 063580421EBF7AE50074E6D4 /* impulseaccumulator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = impulseaccumulator.cpp; sourceTree = ""; }; + 063580431EBF7AE50074E6D4 /* interceptor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = interceptor.cpp; sourceTree = ""; }; + 063580441EBF7AE50074E6D4 /* line.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = line.cpp; sourceTree = ""; }; + 063580451EBF7AE50074E6D4 /* lineblockmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = lineblockmap.cpp; sourceTree = ""; }; + 063580461EBF7AE50074E6D4 /* linesighttest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = linesighttest.cpp; sourceTree = ""; }; + 063580471EBF7AE50074E6D4 /* map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = map.cpp; sourceTree = ""; }; + 063580481EBF7AE50074E6D4 /* maputil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = maputil.cpp; sourceTree = ""; }; + 063580491EBF7AE50074E6D4 /* p_mobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_mobj.cpp; sourceTree = ""; }; + 0635804A1EBF7AE50074E6D4 /* p_players.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_players.cpp; sourceTree = ""; }; + 0635804B1EBF7AE50074E6D4 /* p_ticker.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = p_ticker.cpp; sourceTree = ""; }; + 0635804C1EBF7AE50074E6D4 /* plane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = plane.cpp; sourceTree = ""; }; + 0635804D1EBF7AE50074E6D4 /* polyobj.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polyobj.cpp; sourceTree = ""; }; + 0635804E1EBF7AE50074E6D4 /* polyobjdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = polyobjdata.cpp; sourceTree = ""; }; + 0635804F1EBF7AE50074E6D4 /* reject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = reject.cpp; sourceTree = ""; }; + 063580511EBF7AE50074E6D4 /* sector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sector.cpp; sourceTree = ""; }; + 063580521EBF7AE50074E6D4 /* sky.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sky.cpp; sourceTree = ""; }; + 063580531EBF7AE50074E6D4 /* subsector.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = subsector.cpp; sourceTree = ""; }; + 063580541EBF7AE50074E6D4 /* surface.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = surface.cpp; sourceTree = ""; }; + 063580551EBF7AE50074E6D4 /* thinkers.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = thinkers.cpp; sourceTree = ""; }; + 063580561EBF7AE50074E6D4 /* vertex.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = vertex.cpp; sourceTree = ""; }; + 063580581EBF7AE50074E6D4 /* convexsubspaceproxy.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = convexsubspaceproxy.cpp; sourceTree = ""; }; + 063580591EBF7AE50074E6D4 /* hplane.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = hplane.cpp; sourceTree = ""; }; + 0635805A1EBF7AE50074E6D4 /* linesegment.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = linesegment.cpp; sourceTree = ""; }; + 0635805B1EBF7AE50074E6D4 /* partitioner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = partitioner.cpp; sourceTree = ""; }; + 0635805C1EBF7AE50074E6D4 /* partitionevaluator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = partitionevaluator.cpp; sourceTree = ""; }; + 0635805D1EBF7AE50074E6D4 /* superblockmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = superblockmap.cpp; sourceTree = ""; }; + 0635805E1EBF7AE50074E6D4 /* clientmobjthinkerdata.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = clientmobjthinkerdata.cpp; sourceTree = ""; }; + 0635805F1EBF7AE50074E6D4 /* contact.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contact.cpp; sourceTree = ""; }; + 063580601EBF7AE50074E6D4 /* contactspreader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = contactspreader.cpp; sourceTree = ""; }; + 063580611EBF7AE50074E6D4 /* generator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = generator.cpp; sourceTree = ""; }; + 063580621EBF7AE50074E6D4 /* mapobject.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = mapobject.cpp; sourceTree = ""; }; + 063580631EBF7AE50074E6D4 /* api_console.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = api_console.cpp; path = ../apps/client/src/api_console.cpp; sourceTree = ""; }; + 063580641EBF7AE50074E6D4 /* api_filesys.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = api_filesys.cpp; path = ../apps/client/src/api_filesys.cpp; sourceTree = ""; }; + 063580651EBF7AE50074E6D4 /* api_map.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = api_map.cpp; path = ../apps/client/src/api_map.cpp; sourceTree = ""; }; + 063580661EBF7AE50074E6D4 /* api_mapedit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = api_mapedit.cpp; path = ../apps/client/src/api_mapedit.cpp; sourceTree = ""; }; + 063580671EBF7AE50074E6D4 /* api_uri.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = api_uri.cpp; path = ../apps/client/src/api_uri.cpp; sourceTree = ""; }; + 063580681EBF7AE50074E6D4 /* busyrunner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = busyrunner.cpp; path = ../apps/client/src/busyrunner.cpp; sourceTree = ""; }; + 063580691EBF7AE50074E6D4 /* clientapp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = clientapp.cpp; path = ../apps/client/src/clientapp.cpp; sourceTree = ""; }; + 0635806A1EBF7AE50074E6D4 /* clientplayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = clientplayer.cpp; path = ../apps/client/src/clientplayer.cpp; sourceTree = ""; }; + 0635806B1EBF7AE50074E6D4 /* con_config.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = con_config.cpp; path = ../apps/client/src/con_config.cpp; sourceTree = ""; }; + 0635806C1EBF7AE50074E6D4 /* configprofiles.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = configprofiles.cpp; path = ../apps/client/src/configprofiles.cpp; sourceTree = ""; }; + 0635806D1EBF7AE50074E6D4 /* dd_loop.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dd_loop.cpp; path = ../apps/client/src/dd_loop.cpp; sourceTree = ""; }; + 0635806E1EBF7AE50074E6D4 /* dd_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dd_main.cpp; path = ../apps/client/src/dd_main.cpp; sourceTree = ""; }; + 0635806F1EBF7AE50074E6D4 /* dd_pinit.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = dd_pinit.cpp; path = ../apps/client/src/dd_pinit.cpp; sourceTree = ""; }; + 063580701EBF7AE50074E6D4 /* def_main.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = def_main.cpp; path = ../apps/client/src/def_main.cpp; sourceTree = ""; }; + 063580711EBF7AE50074E6D4 /* localplayer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = localplayer.cpp; path = ../apps/client/src/localplayer.cpp; sourceTree = ""; }; + 063580721EBF7AE50074E6D4 /* main_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = main_client.cpp; path = ../apps/client/src/main_client.cpp; sourceTree = ""; }; + 063580731EBF7AE50074E6D4 /* sys_system.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = sys_system.cpp; path = ../apps/client/src/sys_system.cpp; sourceTree = ""; }; + 0635817E1EBF87040074E6D4 /* libz.tbd */ = {isa = PBXFileReference; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; + 063581801EBF9C690074E6D4 /* xcmoc.py */ = {isa = PBXFileReference; lastKnownFileType = text.script.python; name = xcmoc.py; path = ../build/scripts/xcmoc.py; sourceTree = ""; }; + 063581891EBFB5680074E6D4 /* deng_core_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = deng_core_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/deng_core_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635818B1EBFB5C90074E6D4 /* deng_shell_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = deng_shell_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/deng_shell_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 063581921EBFB6B80074E6D4 /* deng_gui_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = deng_gui_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/deng_gui_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 063581941EBFB6D30074E6D4 /* deng_appfw_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = deng_appfw_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/deng_appfw_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 063581961EBFB6F10074E6D4 /* deng_legacy_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = deng_legacy_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/deng_legacy_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 063581981EBFB7620074E6D4 /* Doomsday_moc_compilation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Doomsday_moc_compilation.cpp; path = ../../Intermediates/Doomsday.build/Doomsday_moc_compilation.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 063582481EBFBA120074E6D4 /* libassimp.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libassimp.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635824C1EBFBB960074E6D4 /* Assimp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Assimp.cpp; path = ../external/assimp/code/Assimp.cpp; sourceTree = ""; }; + 0635824E1EBFBBB30074E6D4 /* DefaultLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DefaultLogger.cpp; path = ../external/assimp/code/DefaultLogger.cpp; sourceTree = ""; }; + 063582501EBFBBCC0074E6D4 /* BaseImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BaseImporter.cpp; path = ../external/assimp/code/BaseImporter.cpp; sourceTree = ""; }; + 063582521EBFBBDB0074E6D4 /* BaseProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BaseProcess.cpp; path = ../external/assimp/code/BaseProcess.cpp; sourceTree = ""; }; + 063582541EBFBBF10074E6D4 /* PostStepRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PostStepRegistry.cpp; path = ../external/assimp/code/PostStepRegistry.cpp; sourceTree = ""; }; + 063582561EBFBBFA0074E6D4 /* ImporterRegistry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ImporterRegistry.cpp; path = ../external/assimp/code/ImporterRegistry.cpp; sourceTree = ""; }; + 063582581EBFBC1C0074E6D4 /* DefaultIOStream.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DefaultIOStream.cpp; path = ../external/assimp/code/DefaultIOStream.cpp; sourceTree = ""; }; + 063582591EBFBC1C0074E6D4 /* DefaultIOSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DefaultIOSystem.cpp; path = ../external/assimp/code/DefaultIOSystem.cpp; sourceTree = ""; }; + 0635825C1EBFBC2A0074E6D4 /* Importer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Importer.cpp; path = ../external/assimp/code/Importer.cpp; sourceTree = ""; }; + 0635825E1EBFBC8D0074E6D4 /* Bitmap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Bitmap.cpp; path = ../external/assimp/code/Bitmap.cpp; sourceTree = ""; }; + 0635825F1EBFBC8D0074E6D4 /* RemoveComments.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RemoveComments.cpp; path = ../external/assimp/code/RemoveComments.cpp; sourceTree = ""; }; + 063582601EBFBC8D0074E6D4 /* SceneCombiner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SceneCombiner.cpp; path = ../external/assimp/code/SceneCombiner.cpp; sourceTree = ""; }; + 063582611EBFBC8D0074E6D4 /* ScenePreprocessor.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ScenePreprocessor.cpp; path = ../external/assimp/code/ScenePreprocessor.cpp; sourceTree = ""; }; + 063582621EBFBC8D0074E6D4 /* SGSpatialSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SGSpatialSort.cpp; path = ../external/assimp/code/SGSpatialSort.cpp; sourceTree = ""; }; + 063582631EBFBC8D0074E6D4 /* SkeletonMeshBuilder.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkeletonMeshBuilder.cpp; path = ../external/assimp/code/SkeletonMeshBuilder.cpp; sourceTree = ""; }; + 063582641EBFBC8D0074E6D4 /* SpatialSort.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SpatialSort.cpp; path = ../external/assimp/code/SpatialSort.cpp; sourceTree = ""; }; + 063582651EBFBC8D0074E6D4 /* SplitByBoneCountProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SplitByBoneCountProcess.cpp; path = ../external/assimp/code/SplitByBoneCountProcess.cpp; sourceTree = ""; }; + 063582661EBFBC8D0074E6D4 /* StandardShapes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StandardShapes.cpp; path = ../external/assimp/code/StandardShapes.cpp; sourceTree = ""; }; + 063582671EBFBC8D0074E6D4 /* Subdivision.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Subdivision.cpp; path = ../external/assimp/code/Subdivision.cpp; sourceTree = ""; }; + 063582681EBFBC8D0074E6D4 /* TargetAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TargetAnimation.cpp; path = ../external/assimp/code/TargetAnimation.cpp; sourceTree = ""; }; + 063582691EBFBC8D0074E6D4 /* Version.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Version.cpp; path = ../external/assimp/code/Version.cpp; sourceTree = ""; }; + 0635826A1EBFBC8D0074E6D4 /* VertexTriangleAdjacency.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = VertexTriangleAdjacency.cpp; path = ../external/assimp/code/VertexTriangleAdjacency.cpp; sourceTree = ""; }; + 063582781EBFBCB50074E6D4 /* 3DSConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = 3DSConverter.cpp; path = ../external/assimp/code/3DSConverter.cpp; sourceTree = ""; }; + 063582791EBFBCB50074E6D4 /* 3DSExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = 3DSExporter.cpp; path = ../external/assimp/code/3DSExporter.cpp; sourceTree = ""; }; + 0635827A1EBFBCB50074E6D4 /* 3DSLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = 3DSLoader.cpp; path = ../external/assimp/code/3DSLoader.cpp; sourceTree = ""; }; + 0635827F1EBFBCE10074E6D4 /* ColladaExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColladaExporter.cpp; path = ../external/assimp/code/ColladaExporter.cpp; sourceTree = ""; }; + 063582801EBFBCE10074E6D4 /* ColladaLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColladaLoader.cpp; path = ../external/assimp/code/ColladaLoader.cpp; sourceTree = ""; }; + 063582811EBFBCE10074E6D4 /* ColladaParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ColladaParser.cpp; path = ../external/assimp/code/ColladaParser.cpp; sourceTree = ""; }; + 063582851EBFBD0C0074E6D4 /* MD2Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MD2Loader.cpp; path = ../external/assimp/code/MD2Loader.cpp; sourceTree = ""; }; + 063582861EBFBD0C0074E6D4 /* MD3Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MD3Loader.cpp; path = ../external/assimp/code/MD3Loader.cpp; sourceTree = ""; }; + 063582871EBFBD0C0074E6D4 /* MD5Loader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MD5Loader.cpp; path = ../external/assimp/code/MD5Loader.cpp; sourceTree = ""; }; + 063582881EBFBD0C0074E6D4 /* MD5Parser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MD5Parser.cpp; path = ../external/assimp/code/MD5Parser.cpp; sourceTree = ""; }; + 0635828D1EBFBD1D0074E6D4 /* MDLLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MDLLoader.cpp; path = ../external/assimp/code/MDLLoader.cpp; sourceTree = ""; }; + 0635828E1EBFBD1D0074E6D4 /* MDLMaterialLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MDLMaterialLoader.cpp; path = ../external/assimp/code/MDLMaterialLoader.cpp; sourceTree = ""; }; + 063582911EBFBD2C0074E6D4 /* ObjExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjExporter.cpp; path = ../external/assimp/code/ObjExporter.cpp; sourceTree = ""; }; + 063582921EBFBD2C0074E6D4 /* ObjFileImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjFileImporter.cpp; path = ../external/assimp/code/ObjFileImporter.cpp; sourceTree = ""; }; + 063582931EBFBD2C0074E6D4 /* ObjFileMtlImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjFileMtlImporter.cpp; path = ../external/assimp/code/ObjFileMtlImporter.cpp; sourceTree = ""; }; + 063582941EBFBD2C0074E6D4 /* ObjFileParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjFileParser.cpp; path = ../external/assimp/code/ObjFileParser.cpp; sourceTree = ""; }; + 063582991EBFBD4D0074E6D4 /* BlenderBMesh.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderBMesh.cpp; path = ../external/assimp/code/BlenderBMesh.cpp; sourceTree = ""; }; + 0635829A1EBFBD4D0074E6D4 /* BlenderDNA.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderDNA.cpp; path = ../external/assimp/code/BlenderDNA.cpp; sourceTree = ""; }; + 0635829B1EBFBD4D0074E6D4 /* BlenderLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderLoader.cpp; path = ../external/assimp/code/BlenderLoader.cpp; sourceTree = ""; }; + 0635829C1EBFBD4D0074E6D4 /* BlenderModifier.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderModifier.cpp; path = ../external/assimp/code/BlenderModifier.cpp; sourceTree = ""; }; + 0635829D1EBFBD4D0074E6D4 /* BlenderScene.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderScene.cpp; path = ../external/assimp/code/BlenderScene.cpp; sourceTree = ""; }; + 0635829E1EBFBD4D0074E6D4 /* BlenderTessellator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BlenderTessellator.cpp; path = ../external/assimp/code/BlenderTessellator.cpp; sourceTree = ""; }; + 063582A51EBFBD700074E6D4 /* FBXAnimation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXAnimation.cpp; path = ../external/assimp/code/FBXAnimation.cpp; sourceTree = ""; }; + 063582A61EBFBD700074E6D4 /* FBXBinaryTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXBinaryTokenizer.cpp; path = ../external/assimp/code/FBXBinaryTokenizer.cpp; sourceTree = ""; }; + 063582A71EBFBD700074E6D4 /* FBXConverter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXConverter.cpp; path = ../external/assimp/code/FBXConverter.cpp; sourceTree = ""; }; + 063582A81EBFBD700074E6D4 /* FBXDeformer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXDeformer.cpp; path = ../external/assimp/code/FBXDeformer.cpp; sourceTree = ""; }; + 063582A91EBFBD700074E6D4 /* FBXDocument.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXDocument.cpp; path = ../external/assimp/code/FBXDocument.cpp; sourceTree = ""; }; + 063582AA1EBFBD700074E6D4 /* FBXDocumentUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXDocumentUtil.cpp; path = ../external/assimp/code/FBXDocumentUtil.cpp; sourceTree = ""; }; + 063582AB1EBFBD700074E6D4 /* FBXImporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXImporter.cpp; path = ../external/assimp/code/FBXImporter.cpp; sourceTree = ""; }; + 063582AC1EBFBD700074E6D4 /* FBXMaterial.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXMaterial.cpp; path = ../external/assimp/code/FBXMaterial.cpp; sourceTree = ""; }; + 063582AD1EBFBD700074E6D4 /* FBXMeshGeometry.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXMeshGeometry.cpp; path = ../external/assimp/code/FBXMeshGeometry.cpp; sourceTree = ""; }; + 063582AE1EBFBD700074E6D4 /* FBXModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXModel.cpp; path = ../external/assimp/code/FBXModel.cpp; sourceTree = ""; }; + 063582AF1EBFBD700074E6D4 /* FBXNodeAttribute.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXNodeAttribute.cpp; path = ../external/assimp/code/FBXNodeAttribute.cpp; sourceTree = ""; }; + 063582B01EBFBD700074E6D4 /* FBXParser.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXParser.cpp; path = ../external/assimp/code/FBXParser.cpp; sourceTree = ""; }; + 063582B11EBFBD700074E6D4 /* FBXProperties.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXProperties.cpp; path = ../external/assimp/code/FBXProperties.cpp; sourceTree = ""; }; + 063582B21EBFBD700074E6D4 /* FBXTokenizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXTokenizer.cpp; path = ../external/assimp/code/FBXTokenizer.cpp; sourceTree = ""; }; + 063582B31EBFBD700074E6D4 /* FBXUtil.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FBXUtil.cpp; path = ../external/assimp/code/FBXUtil.cpp; sourceTree = ""; }; + 063582C31EBFBD860074E6D4 /* IRRLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRRLoader.cpp; path = ../external/assimp/code/IRRLoader.cpp; sourceTree = ""; }; + 063582C41EBFBD860074E6D4 /* IRRMeshLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRRMeshLoader.cpp; path = ../external/assimp/code/IRRMeshLoader.cpp; sourceTree = ""; }; + 063582C51EBFBD860074E6D4 /* IRRShared.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = IRRShared.cpp; path = ../external/assimp/code/IRRShared.cpp; sourceTree = ""; }; + 063582C91EBFBE4B0074E6D4 /* MaterialSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MaterialSystem.cpp; path = ../external/assimp/code/MaterialSystem.cpp; sourceTree = ""; }; + 063582CB1EBFBF560074E6D4 /* ComputeUVMappingProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ComputeUVMappingProcess.cpp; path = ../external/assimp/code/ComputeUVMappingProcess.cpp; sourceTree = ""; }; + 063582CC1EBFBF560074E6D4 /* ConvertToLHProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ConvertToLHProcess.cpp; path = ../external/assimp/code/ConvertToLHProcess.cpp; sourceTree = ""; }; + 063582CD1EBFBF560074E6D4 /* DeboneProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DeboneProcess.cpp; path = ../external/assimp/code/DeboneProcess.cpp; sourceTree = ""; }; + 063582CE1EBFBF560074E6D4 /* FindDegenerates.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FindDegenerates.cpp; path = ../external/assimp/code/FindDegenerates.cpp; sourceTree = ""; }; + 063582CF1EBFBF560074E6D4 /* FindInstancesProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FindInstancesProcess.cpp; path = ../external/assimp/code/FindInstancesProcess.cpp; sourceTree = ""; }; + 063582D01EBFBF560074E6D4 /* FindInvalidDataProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FindInvalidDataProcess.cpp; path = ../external/assimp/code/FindInvalidDataProcess.cpp; sourceTree = ""; }; + 063582D11EBFBF560074E6D4 /* FixNormalsStep.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FixNormalsStep.cpp; path = ../external/assimp/code/FixNormalsStep.cpp; sourceTree = ""; }; + 063582D91EBFBFB80074E6D4 /* GenFaceNormalsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GenFaceNormalsProcess.cpp; path = ../external/assimp/code/GenFaceNormalsProcess.cpp; sourceTree = ""; }; + 063582DA1EBFBFB80074E6D4 /* GenVertexNormalsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = GenVertexNormalsProcess.cpp; path = ../external/assimp/code/GenVertexNormalsProcess.cpp; sourceTree = ""; }; + 063582DB1EBFBFB80074E6D4 /* ImproveCacheLocality.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ImproveCacheLocality.cpp; path = ../external/assimp/code/ImproveCacheLocality.cpp; sourceTree = ""; }; + 063582DC1EBFBFB80074E6D4 /* JoinVerticesProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = JoinVerticesProcess.cpp; path = ../external/assimp/code/JoinVerticesProcess.cpp; sourceTree = ""; }; + 063582DD1EBFBFB80074E6D4 /* LimitBoneWeightsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LimitBoneWeightsProcess.cpp; path = ../external/assimp/code/LimitBoneWeightsProcess.cpp; sourceTree = ""; }; + 063582DE1EBFBFB80074E6D4 /* MakeVerboseFormat.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = MakeVerboseFormat.cpp; path = ../external/assimp/code/MakeVerboseFormat.cpp; sourceTree = ""; }; + 063582DF1EBFBFB80074E6D4 /* OptimizeGraph.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptimizeGraph.cpp; path = ../external/assimp/code/OptimizeGraph.cpp; sourceTree = ""; }; + 063582E01EBFBFB80074E6D4 /* OptimizeMeshes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = OptimizeMeshes.cpp; path = ../external/assimp/code/OptimizeMeshes.cpp; sourceTree = ""; }; + 063582E11EBFBFB80074E6D4 /* PretransformVertices.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = PretransformVertices.cpp; path = ../external/assimp/code/PretransformVertices.cpp; sourceTree = ""; }; + 063582E21EBFBFB80074E6D4 /* ProcessHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessHelper.cpp; path = ../external/assimp/code/ProcessHelper.cpp; sourceTree = ""; }; + 063582E31EBFBFB80074E6D4 /* RemoveRedundantMaterials.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RemoveRedundantMaterials.cpp; path = ../external/assimp/code/RemoveRedundantMaterials.cpp; sourceTree = ""; }; + 063582E41EBFBFB80074E6D4 /* RemoveVCProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RemoveVCProcess.cpp; path = ../external/assimp/code/RemoveVCProcess.cpp; sourceTree = ""; }; + 063582E51EBFBFB80074E6D4 /* SortByPTypeProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SortByPTypeProcess.cpp; path = ../external/assimp/code/SortByPTypeProcess.cpp; sourceTree = ""; }; + 063582E61EBFBFB80074E6D4 /* SplitLargeMeshes.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SplitLargeMeshes.cpp; path = ../external/assimp/code/SplitLargeMeshes.cpp; sourceTree = ""; }; + 063582E71EBFBFB80074E6D4 /* TextureTransform.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TextureTransform.cpp; path = ../external/assimp/code/TextureTransform.cpp; sourceTree = ""; }; + 063582E81EBFBFB80074E6D4 /* TriangulateProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = TriangulateProcess.cpp; path = ../external/assimp/code/TriangulateProcess.cpp; sourceTree = ""; }; + 063582E91EBFBFB80074E6D4 /* ValidateDataStructure.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ValidateDataStructure.cpp; path = ../external/assimp/code/ValidateDataStructure.cpp; sourceTree = ""; }; + 063582FB1EBFBFCA0074E6D4 /* CalcTangentsProcess.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CalcTangentsProcess.cpp; path = ../external/assimp/code/CalcTangentsProcess.cpp; sourceTree = ""; }; + 063582FD1EBFC03B0074E6D4 /* StepExporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StepExporter.cpp; path = ../external/assimp/code/StepExporter.cpp; sourceTree = ""; }; + 063582FF1EBFC0510074E6D4 /* Exporter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = Exporter.cpp; path = ../external/assimp/code/Exporter.cpp; sourceTree = ""; }; + 063583011EBFC0670074E6D4 /* AssimpCExport.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = AssimpCExport.cpp; path = ../external/assimp/code/AssimpCExport.cpp; sourceTree = ""; }; + 063583031EC036B40074E6D4 /* irrXML.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = irrXML.cpp; path = ../external/assimp/contrib/irrXML/irrXML.cpp; sourceTree = ""; }; + 063583051EC036CC0074E6D4 /* ConvertUTF.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ConvertUTF.c; path = ../external/assimp/contrib/ConvertUTF/ConvertUTF.c; sourceTree = ""; }; + 0635830F1EC0401D0074E6D4 /* Makefile.xcpacks */ = {isa = PBXFileReference; lastKnownFileType = text; name = Makefile.xcpacks; path = ../build/scripts/Makefile.xcpacks; sourceTree = ""; }; + 063583101EC044DF0074E6D4 /* doomsday.pk3 */ = {isa = PBXFileReference; lastKnownFileType = file; name = doomsday.pk3; path = ../../Intermediates/Doomsday.build/doomsday.pk3; sourceTree = BUILT_PRODUCTS_DIR; }; + 063583121EC045220074E6D4 /* libdoom.pk3 */ = {isa = PBXFileReference; lastKnownFileType = file; name = libdoom.pk3; path = ../../Intermediates/Doomsday.build/libdoom.pk3; sourceTree = BUILT_PRODUCTS_DIR; }; + 063583131EC045220074E6D4 /* libdoom64.pk3 */ = {isa = PBXFileReference; lastKnownFileType = file; name = libdoom64.pk3; path = ../../Intermediates/Doomsday.build/libdoom64.pk3; sourceTree = BUILT_PRODUCTS_DIR; }; + 063583141EC045220074E6D4 /* libheretic.pk3 */ = {isa = PBXFileReference; lastKnownFileType = file; name = libheretic.pk3; path = ../../Intermediates/Doomsday.build/libheretic.pk3; sourceTree = BUILT_PRODUCTS_DIR; }; + 063583151EC045220074E6D4 /* libhexen.pk3 */ = {isa = PBXFileReference; lastKnownFileType = file; name = libhexen.pk3; path = ../../Intermediates/Doomsday.build/libhexen.pk3; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635831A1EC069B70074E6D4 /* net.dengine.base.pack */ = {isa = PBXFileReference; explicitFileType = archive.zip; name = net.dengine.base.pack; path = ../../Intermediates/Doomsday.build/net.dengine.base.pack; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635831B1EC069B70074E6D4 /* net.dengine.client.pack */ = {isa = PBXFileReference; explicitFileType = archive.zip; name = net.dengine.client.pack; path = ../../Intermediates/Doomsday.build/net.dengine.client.pack; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635831C1EC069B70074E6D4 /* net.dengine.stdlib.gui.pack */ = {isa = PBXFileReference; explicitFileType = archive.zip; name = net.dengine.stdlib.gui.pack; path = ../../Intermediates/Doomsday.build/net.dengine.stdlib.gui.pack; sourceTree = BUILT_PRODUCTS_DIR; }; + 0635831D1EC069B70074E6D4 /* net.dengine.stdlib.pack */ = {isa = PBXFileReference; explicitFileType = archive.zip; name = net.dengine.stdlib.pack; path = ../../Intermediates/Doomsday.build/net.dengine.stdlib.pack; sourceTree = BUILT_PRODUCTS_DIR; }; + 063583221EC0B7870074E6D4 /* doom1.wad */ = {isa = PBXFileReference; lastKnownFileType = file; name = doom1.wad; path = /Users/jaakeran/src/deng/doomsday/xcode/Doomsday/../../../../../odrive/Amazon/Documents/IWADs/shareware/doom1.wad; sourceTree = ""; }; + 063583251EC4E5B80074E6D4 /* client.qrc */ = {isa = PBXFileReference; lastKnownFileType = text; name = client.qrc; path = ../../apps/client/res/qml/client.qrc; sourceTree = ""; }; + 063583271EC4E6040074E6D4 /* main.qml */ = {isa = PBXFileReference; lastKnownFileType = text; name = main.qml; path = ../../apps/client/res/qml/main.qml; sourceTree = ""; }; + 063671171EC4E7BA00DAF520 /* qrc_client.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qrc_client.cpp; path = ../../Intermediates/Doomsday.build/qrc_client.cpp; sourceTree = BUILT_PRODUCTS_DIR; }; + 065548171EC8BB670000E33E /* directorylistdialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = directorylistdialog.h; sourceTree = ""; }; + 065548181EC8BB670000E33E /* inputdialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = inputdialog.h; sourceTree = ""; }; + 065548191EC8BB670000E33E /* messagedialog.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = messagedialog.h; sourceTree = ""; }; + 0655481B1EC8BB670000E33E /* actionitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = actionitem.h; sourceTree = ""; }; + 0655481C1EC8BB670000E33E /* atlasproceduralimage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = atlasproceduralimage.h; sourceTree = ""; }; + 0655481D1EC8BB670000E33E /* baseguiapp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = baseguiapp.h; sourceTree = ""; }; + 0655481E1EC8BB670000E33E /* basewindow.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = basewindow.h; sourceTree = ""; }; + 0655481F1EC8BB670000E33E /* callbackaction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = callbackaction.h; sourceTree = ""; }; + 065548201EC8BB670000E33E /* childwidgetorganizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = childwidgetorganizer.h; sourceTree = ""; }; + 065548211EC8BB670000E33E /* data.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = data.h; sourceTree = ""; }; + 065548221EC8BB670000E33E /* dialogcontentstylist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dialogcontentstylist.h; sourceTree = ""; }; + 065548231EC8BB670000E33E /* filtereddata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = filtereddata.h; sourceTree = ""; }; + 065548241EC8BB670000E33E /* fontlinewrapping.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fontlinewrapping.h; sourceTree = ""; }; + 065548251EC8BB670000E33E /* gltextcomposer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gltextcomposer.h; sourceTree = ""; }; + 065548261EC8BB670000E33E /* gridlayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gridlayout.h; sourceTree = ""; }; + 065548271EC8BB670000E33E /* guirootwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = guirootwidget.h; sourceTree = ""; }; + 065548281EC8BB670000E33E /* guiwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = guiwidget.h; sourceTree = ""; }; + 065548291EC8BB670000E33E /* guiwidgetprivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = guiwidgetprivate.h; sourceTree = ""; }; + 0655482A1EC8BB670000E33E /* imageitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = imageitem.h; sourceTree = ""; }; + 0655482B1EC8BB670000E33E /* ipersistent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ipersistent.h; sourceTree = ""; }; + 0655482C1EC8BB670000E33E /* item.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = item.h; sourceTree = ""; }; + 0655482D1EC8BB670000E33E /* listdata.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = listdata.h; sourceTree = ""; }; + 0655482E1EC8BB670000E33E /* margins.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = margins.h; sourceTree = ""; }; + 0655482F1EC8BB670000E33E /* painter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = painter.h; sourceTree = ""; }; + 065548301EC8BB670000E33E /* persistentstate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = persistentstate.h; sourceTree = ""; }; + 065548311EC8BB670000E33E /* proceduralimage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = proceduralimage.h; sourceTree = ""; }; + 065548321EC8BB670000E33E /* sequentiallayout.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sequentiallayout.h; sourceTree = ""; }; + 065548331EC8BB670000E33E /* signalaction.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = signalaction.h; sourceTree = ""; }; + 065548341EC8BB670000E33E /* style.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = style.h; sourceTree = ""; }; + 065548351EC8BB670000E33E /* styleproceduralimage.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = styleproceduralimage.h; sourceTree = ""; }; + 065548361EC8BB670000E33E /* stylist.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = stylist.h; sourceTree = ""; }; + 065548371EC8BB670000E33E /* submenuitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = submenuitem.h; sourceTree = ""; }; + 065548381EC8BB670000E33E /* subwidgetitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = subwidgetitem.h; sourceTree = ""; }; + 065548391EC8BB670000E33E /* textdrawable.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = textdrawable.h; sourceTree = ""; }; + 0655483A1EC8BB670000E33E /* untrapper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = untrapper.h; sourceTree = ""; }; + 0655483B1EC8BB670000E33E /* variabletoggleitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variabletoggleitem.h; sourceTree = ""; }; + 0655483C1EC8BB670000E33E /* variantactionitem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variantactionitem.h; sourceTree = ""; }; + 0655483D1EC8BB670000E33E /* vrwindowtransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vrwindowtransform.h; sourceTree = ""; }; + 0655483E1EC8BB670000E33E /* windowsystem.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = windowsystem.h; sourceTree = ""; }; + 0655483F1EC8BB670000E33E /* windowtransform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = windowtransform.h; sourceTree = ""; }; + 065548411EC8BB670000E33E /* ActionItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = ActionItem; sourceTree = ""; }; + 065548421EC8BB670000E33E /* Data */ = {isa = PBXFileReference; lastKnownFileType = text; path = Data; sourceTree = ""; }; + 065548431EC8BB670000E33E /* defs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = defs.h; sourceTree = ""; }; + 065548441EC8BB670000E33E /* FilteredData */ = {isa = PBXFileReference; lastKnownFileType = text; path = FilteredData; sourceTree = ""; }; + 065548451EC8BB670000E33E /* ImageItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = ImageItem; sourceTree = ""; }; + 065548461EC8BB670000E33E /* Item */ = {isa = PBXFileReference; lastKnownFileType = text; path = Item; sourceTree = ""; }; + 065548471EC8BB670000E33E /* ListData */ = {isa = PBXFileReference; lastKnownFileType = text; path = ListData; sourceTree = ""; }; + 065548481EC8BB670000E33E /* Margins */ = {isa = PBXFileReference; lastKnownFileType = text; path = Margins; sourceTree = ""; }; + 065548491EC8BB670000E33E /* Stylist */ = {isa = PBXFileReference; lastKnownFileType = text; path = Stylist; sourceTree = ""; }; + 0655484A1EC8BB670000E33E /* SubmenuItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = SubmenuItem; sourceTree = ""; }; + 0655484B1EC8BB670000E33E /* SubwidgetItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = SubwidgetItem; sourceTree = ""; }; + 0655484C1EC8BB670000E33E /* VariableToggleItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = VariableToggleItem; sourceTree = ""; }; + 0655484D1EC8BB670000E33E /* VariantActionItem */ = {isa = PBXFileReference; lastKnownFileType = text; path = VariantActionItem; sourceTree = ""; }; + 0655484F1EC8BB670000E33E /* oculusrift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = oculusrift.h; sourceTree = ""; }; + 065548501EC8BB670000E33E /* vrconfig.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = vrconfig.h; sourceTree = ""; }; + 065548521EC8BB670000E33E /* auxbuttonwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = auxbuttonwidget.h; sourceTree = ""; }; + 065548531EC8BB670000E33E /* blurwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = blurwidget.h; sourceTree = ""; }; + 065548541EC8BB670000E33E /* buttonwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = buttonwidget.h; sourceTree = ""; }; + 065548551EC8BB670000E33E /* choicewidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = choicewidget.h; sourceTree = ""; }; + 065548561EC8BB670000E33E /* commandwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = commandwidget.h; sourceTree = ""; }; + 065548571EC8BB670000E33E /* compositorwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = compositorwidget.h; sourceTree = ""; }; + 065548581EC8BB670000E33E /* dialogwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = dialogwidget.h; sourceTree = ""; }; + 065548591EC8BB670000E33E /* directoryarraywidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = directoryarraywidget.h; sourceTree = ""; }; + 0655485A1EC8BB670000E33E /* documentpopupwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = documentpopupwidget.h; sourceTree = ""; }; + 0655485B1EC8BB670000E33E /* documentwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = documentwidget.h; sourceTree = ""; }; + 0655485C1EC8BB670000E33E /* fadetoblackwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = fadetoblackwidget.h; sourceTree = ""; }; + 0655485D1EC8BB670000E33E /* focuswidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = focuswidget.h; sourceTree = ""; }; + 0655485E1EC8BB670000E33E /* foldpanelwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = foldpanelwidget.h; sourceTree = ""; }; + 0655485F1EC8BB670000E33E /* gridpopupwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gridpopupwidget.h; sourceTree = ""; }; + 065548601EC8BB670000E33E /* labelwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = labelwidget.h; sourceTree = ""; }; + 065548611EC8BB670000E33E /* lineeditwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lineeditwidget.h; sourceTree = ""; }; + 065548621EC8BB670000E33E /* logwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = logwidget.h; sourceTree = ""; }; + 065548631EC8BB670000E33E /* menuwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = menuwidget.h; sourceTree = ""; }; + 065548641EC8BB670000E33E /* notificationareawidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = notificationareawidget.h; sourceTree = ""; }; + 065548651EC8BB670000E33E /* panelwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = panelwidget.h; sourceTree = ""; }; + 065548661EC8BB670000E33E /* popupbuttonwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = popupbuttonwidget.h; sourceTree = ""; }; + 065548671EC8BB670000E33E /* popupmenuwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = popupmenuwidget.h; sourceTree = ""; }; + 065548681EC8BB670000E33E /* popupwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = popupwidget.h; sourceTree = ""; }; + 065548691EC8BB670000E33E /* progresswidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = progresswidget.h; sourceTree = ""; }; + 0655486A1EC8BB670000E33E /* relaywidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = relaywidget.h; sourceTree = ""; }; + 0655486B1EC8BB670000E33E /* scriptcommandwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scriptcommandwidget.h; sourceTree = ""; }; + 0655486C1EC8BB670000E33E /* scrollareawidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = scrollareawidget.h; sourceTree = ""; }; + 0655486D1EC8BB670000E33E /* sliderwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = sliderwidget.h; sourceTree = ""; }; + 0655486E1EC8BB670000E33E /* tabwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = tabwidget.h; sourceTree = ""; }; + 0655486F1EC8BB670000E33E /* togglewidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = togglewidget.h; sourceTree = ""; }; + 065548701EC8BB670000E33E /* variablearraywidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variablearraywidget.h; sourceTree = ""; }; + 065548711EC8BB670000E33E /* variablechoicewidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variablechoicewidget.h; sourceTree = ""; }; + 065548721EC8BB670000E33E /* variablelineeditwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variablelineeditwidget.h; sourceTree = ""; }; + 065548731EC8BB670000E33E /* variablesliderwidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variablesliderwidget.h; sourceTree = ""; }; + 065548741EC8BB670000E33E /* variabletogglewidget.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = variabletogglewidget.h; sourceTree = ""; }; + 065548751EC8BB670000E33E /* libappfw.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = libappfw.h; path = ../sdk/libappfw/include/de/libappfw.h; sourceTree = ""; }; + 067AD9091EBF143600B808B2 /* libimportidtech1.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libimportidtech1.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 067AD9131EBF148F00B808B2 /* hexlex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = hexlex.cpp; path = ../apps/plugins/importidtech1/src/hexlex.cpp; sourceTree = ""; }; + 067AD9141EBF148F00B808B2 /* importidtech1.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = importidtech1.cpp; path = ../apps/plugins/importidtech1/src/importidtech1.cpp; sourceTree = ""; }; + 067AD9151EBF148F00B808B2 /* mapimporter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mapimporter.cpp; path = ../apps/plugins/importidtech1/src/mapimporter.cpp; sourceTree = ""; }; + 067AD9161EBF148F00B808B2 /* mapimporter_loadblockmap.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mapimporter_loadblockmap.cpp; path = ../apps/plugins/importidtech1/src/mapimporter_loadblockmap.cpp; sourceTree = ""; }; + 067AD9171EBF148F00B808B2 /* mapinfotranslator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = mapinfotranslator.cpp; path = ../apps/plugins/importidtech1/src/mapinfotranslator.cpp; sourceTree = ""; }; + 067AD9291EBF14E000B808B2 /* libdeng_core.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libdeng_core.a; sourceTree = BUILT_PRODUCTS_DIR; }; + 067AD92A1EBF151100B808B2 /* c_wrapper.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = c_wrapper.cpp; path = ../sdk/libcore/src/c_wrapper.cpp; sourceTree = ""; }; + 067AD92B1EBF151100B808B2 /* charsymbols.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = charsymbols.cpp; path = ../sdk/libcore/src/charsymbols.cpp; sourceTree = ""; }; + 067AD92D1EBF151100B808B2 /* guard.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = guard.cpp; sourceTree = ""; }; + 067AD92E1EBF151100B808B2 /* lockable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = lockable.cpp; sourceTree = ""; }; + 067AD92F1EBF151100B808B2 /* readwritelockable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = readwritelockable.cpp; sourceTree = ""; }; + 067AD9301EBF151100B808B2 /* task.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = task.cpp; sourceTree = ""; }; + 067AD9311EBF151100B808B2 /* taskpool.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = taskpool.cpp; sourceTree = ""; }; + 067AD9321EBF151100B808B2 /* waitable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = waitable.cpp; sourceTree = ""; }; + 067AD9341EBF151100B808B2 /* app.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = app.cpp; sourceTree = ""; }; + 067AD9351EBF151100B808B2 /* asset.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = asset.cpp; sourceTree = ""; }; + 067AD9361EBF151100B808B2 /* callbacktimer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = callbacktimer.cpp; sourceTree = ""; }; + 067AD9371EBF151100B808B2 /* callbacktimer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = callbacktimer.h; sourceTree = ""; }; + 067AD9381EBF151100B808B2 /* clock.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = clock.cpp; sourceTree = ""; }; + 067AD9391EBF151100B808B2 /* commandline.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = commandline.cpp; sourceTree = ""; }; + 067AD93A1EBF151100B808B2 /* config.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = config.cpp; sourceTree = ""; }; + 067AD93B1EBF151100B808B2 /* debuglogsink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = debuglogsink.cpp; sourceTree = ""; }; + 067AD93C1EBF151100B808B2 /* filelogsink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = filelogsink.cpp; sourceTree = ""; }; + 067AD93D1EBF151100B808B2 /* garbage.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = garbage.cpp; sourceTree = ""; }; + 067AD93E1EBF151100B808B2 /* highperformancetimer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = highperformancetimer.cpp; sourceTree = ""; }; + 067AD93F1EBF151100B808B2 /* id.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = id.cpp; sourceTree = ""; }; + 067AD9401EBF151100B808B2 /* library.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = library.cpp; sourceTree = ""; }; + 067AD9411EBF151100B808B2 /* log.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = log.cpp; sourceTree = ""; }; + 067AD9421EBF151100B808B2 /* logbuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = logbuffer.cpp; sourceTree = ""; }; + 067AD9431EBF151100B808B2 /* logfilter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = logfilter.cpp; sourceTree = ""; }; + 067AD9441EBF151100B808B2 /* logsink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = logsink.cpp; sourceTree = ""; }; + 067AD9451EBF151100B808B2 /* logtextstyle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = logtextstyle.h; sourceTree = ""; }; + 067AD9461EBF151100B808B2 /* loop.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = loop.cpp; sourceTree = ""; }; + 067AD9471EBF151100B808B2 /* memorylogsink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = memorylogsink.cpp; sourceTree = ""; }; + 067AD9481EBF151100B808B2 /* monospacelogsinkformatter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = monospacelogsinkformatter.cpp; sourceTree = ""; }; + 067AD9491EBF151100B808B2 /* system.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = system.cpp; sourceTree = ""; }; + 067AD94A1EBF151100B808B2 /* textapp.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = textapp.cpp; sourceTree = ""; }; + 067AD94B1EBF151100B808B2 /* textstreamlogsink.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = textstreamlogsink.cpp; sourceTree = ""; }; + 067AD94C1EBF151100B808B2 /* unixinfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = unixinfo.cpp; sourceTree = ""; }; + 067AD94E1EBF151100B808B2 /* animationvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = animationvalue.cpp; sourceTree = ""; }; + 067AD94F1EBF151100B808B2 /* archive.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = archive.cpp; sourceTree = ""; }; + 067AD9501EBF151100B808B2 /* arrayvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = arrayvalue.cpp; sourceTree = ""; }; + 067AD9511EBF151100B808B2 /* bank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bank.cpp; sourceTree = ""; }; + 067AD9521EBF151100B808B2 /* bitfield.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bitfield.cpp; sourceTree = ""; }; + 067AD9531EBF151100B808B2 /* bitfield_elements.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bitfield_elements.cpp; sourceTree = ""; }; + 067AD9541EBF151100B808B2 /* block.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = block.cpp; sourceTree = ""; }; + 067AD9551EBF151100B808B2 /* blockvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = blockvalue.cpp; sourceTree = ""; }; + 067AD9561EBF151100B808B2 /* byteorder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = byteorder.cpp; sourceTree = ""; }; + 067AD9571EBF151100B808B2 /* byterefarray.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = byterefarray.cpp; sourceTree = ""; }; + 067AD9581EBF151100B808B2 /* bytesubarray.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bytesubarray.cpp; sourceTree = ""; }; + 067AD9591EBF151100B808B2 /* counted.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = counted.cpp; sourceTree = ""; }; + 067AD95A1EBF151100B808B2 /* date.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = date.cpp; sourceTree = ""; }; + 067AD95B1EBF151100B808B2 /* deletable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = deletable.cpp; sourceTree = ""; }; + 067AD95C1EBF151100B808B2 /* dictionaryvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dictionaryvalue.cpp; sourceTree = ""; }; + 067AD95D1EBF151100B808B2 /* escapeparser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = escapeparser.cpp; sourceTree = ""; }; + 067AD95E1EBF151100B808B2 /* fixedbytearray.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = fixedbytearray.cpp; sourceTree = ""; }; + 067AD95F1EBF151100B808B2 /* huffman.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = huffman.cpp; sourceTree = ""; }; + 067AD9601EBF151100B808B2 /* info.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = info.cpp; sourceTree = ""; }; + 067AD9611EBF151100B808B2 /* infobank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = infobank.cpp; sourceTree = ""; }; + 067AD9621EBF151100B808B2 /* json.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = json.cpp; sourceTree = ""; }; + 067AD9631EBF151100B808B2 /* nativepointervalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nativepointervalue.cpp; sourceTree = ""; }; + 067AD9641EBF151100B808B2 /* nonevalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nonevalue.cpp; sourceTree = ""; }; + 067AD9651EBF151100B808B2 /* numbervalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = numbervalue.cpp; sourceTree = ""; }; + 067AD9661EBF151100B808B2 /* observers.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = observers.cpp; sourceTree = ""; }; + 067AD9671EBF151100B808B2 /* path.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = path.cpp; sourceTree = ""; }; + 067AD9681EBF151100B808B2 /* pathtree.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pathtree.cpp; sourceTree = ""; }; + 067AD9691EBF151100B808B2 /* pathtreenode.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pathtreenode.cpp; sourceTree = ""; }; + 067AD96A1EBF151100B808B2 /* pointerset.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = pointerset.cpp; sourceTree = ""; }; + 067AD96B1EBF151100B808B2 /* profiles.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = profiles.cpp; sourceTree = ""; }; + 067AD96C1EBF151100B808B2 /* reader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = reader.cpp; sourceTree = ""; }; + 067AD96D1EBF151100B808B2 /* record.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = record.cpp; sourceTree = ""; }; + 067AD96E1EBF151100B808B2 /* recordaccessor.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = recordaccessor.cpp; sourceTree = ""; }; + 067AD96F1EBF151100B808B2 /* recordvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = recordvalue.cpp; sourceTree = ""; }; + 067AD9701EBF151100B808B2 /* refuge.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = refuge.cpp; sourceTree = ""; }; + 067AD9711EBF151100B808B2 /* refvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = refvalue.cpp; sourceTree = ""; }; + 067AD9721EBF151100B808B2 /* sourcelinetable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = sourcelinetable.cpp; sourceTree = ""; }; + 067AD9731EBF151100B808B2 /* string.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = string.cpp; sourceTree = ""; }; + 067AD9741EBF151100B808B2 /* stringpool.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = stringpool.cpp; sourceTree = ""; }; + 067AD9751EBF151100B808B2 /* textvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = textvalue.cpp; sourceTree = ""; }; + 067AD9761EBF151100B808B2 /* time.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = time.cpp; sourceTree = ""; }; + 067AD9771EBF151100B808B2 /* timevalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = timevalue.cpp; sourceTree = ""; }; + 067AD9781EBF151100B808B2 /* value.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = value.cpp; sourceTree = ""; }; + 067AD9791EBF151100B808B2 /* variable.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = variable.cpp; sourceTree = ""; }; + 067AD97A1EBF151100B808B2 /* writer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = writer.cpp; sourceTree = ""; }; + 067AD97B1EBF151100B808B2 /* ziparchive.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ziparchive.cpp; sourceTree = ""; }; + 067AD97C1EBF151100B808B2 /* error.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = error.cpp; path = ../sdk/libcore/src/error.cpp; sourceTree = ""; }; + 067AD97E1EBF151100B808B2 /* archiveentryfile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = archiveentryfile.cpp; sourceTree = ""; }; + 067AD97F1EBF151100B808B2 /* archivefeed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = archivefeed.cpp; sourceTree = ""; }; + 067AD9801EBF151100B808B2 /* archivefolder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = archivefolder.cpp; sourceTree = ""; }; + 067AD9811EBF151100B808B2 /* assetobserver.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = assetobserver.cpp; sourceTree = ""; }; + 067AD9821EBF151100B808B2 /* bytearrayfile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bytearrayfile.cpp; sourceTree = ""; }; + 067AD9831EBF151100B808B2 /* directoryfeed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = directoryfeed.cpp; sourceTree = ""; }; + 067AD9841EBF151100B808B2 /* feed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = feed.cpp; sourceTree = ""; }; + 067AD9851EBF151100B808B2 /* file.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = file.cpp; sourceTree = ""; }; + 067AD9861EBF151100B808B2 /* fileindex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = fileindex.cpp; sourceTree = ""; }; + 067AD9871EBF151100B808B2 /* filesystem.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = filesystem.cpp; sourceTree = ""; }; + 067AD9881EBF151100B808B2 /* folder.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = folder.cpp; sourceTree = ""; }; + 067AD9891EBF151100B808B2 /* libraryfile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = libraryfile.cpp; sourceTree = ""; }; + 067AD98A1EBF151100B808B2 /* linkfile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = linkfile.cpp; sourceTree = ""; }; + 067AD98B1EBF151100B808B2 /* metadatabank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = metadatabank.cpp; sourceTree = ""; }; + 067AD98C1EBF151100B808B2 /* nativefile.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nativefile.cpp; sourceTree = ""; }; + 067AD98D1EBF151100B808B2 /* nativepath.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nativepath.cpp; sourceTree = ""; }; + 067AD98E1EBF151100B808B2 /* node.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = node.cpp; sourceTree = ""; }; + 067AD98F1EBF151100B808B2 /* package.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = package.cpp; sourceTree = ""; }; + 067AD9901EBF151100B808B2 /* packagefeed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = packagefeed.cpp; sourceTree = ""; }; + 067AD9911EBF151100B808B2 /* packageloader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = packageloader.cpp; sourceTree = ""; }; + 067AD9921EBF151100B808B2 /* staticlibraryfeed.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = staticlibraryfeed.cpp; sourceTree = ""; }; + 067AD9931EBF151100B808B2 /* math.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = math.cpp; path = ../sdk/libcore/src/math.cpp; sourceTree = ""; }; + 067AD9941EBF151100B808B2 /* matrix.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = matrix.cpp; path = ../sdk/libcore/src/matrix.cpp; sourceTree = ""; }; + 067AD9961EBF151100B808B2 /* address.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = address.cpp; sourceTree = ""; }; + 067AD9971EBF151100B808B2 /* beacon.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = beacon.cpp; sourceTree = ""; }; + 067AD9981EBF151100B808B2 /* blockpacket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = blockpacket.cpp; sourceTree = ""; }; + 067AD9991EBF151100B808B2 /* identifiedpacket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = identifiedpacket.cpp; sourceTree = ""; }; + 067AD99A1EBF151100B808B2 /* listensocket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = listensocket.cpp; sourceTree = ""; }; + 067AD99B1EBF151100B808B2 /* message.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = message.cpp; sourceTree = ""; }; + 067AD99C1EBF151100B808B2 /* networkinterfaces.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = networkinterfaces.cpp; sourceTree = ""; }; + 067AD99D1EBF151100B808B2 /* networkinterfaces.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = networkinterfaces.h; sourceTree = ""; }; + 067AD99E1EBF151100B808B2 /* packet.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = packet.cpp; sourceTree = ""; }; + 067AD99F1EBF151100B808B2 /* protocol.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = protocol.cpp; sourceTree = ""; }; + 067AD9A01EBF151100B808B2 /* recordpacket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = recordpacket.cpp; sourceTree = ""; }; + 067AD9A11EBF151100B808B2 /* socket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = socket.cpp; sourceTree = ""; }; + 067AD9A21EBF151100B808B2 /* transmitter.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = transmitter.cpp; sourceTree = ""; }; + 067AD9A51EBF151100B808B2 /* arrayexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = arrayexpression.cpp; sourceTree = ""; }; + 067AD9A61EBF151100B808B2 /* assignstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = assignstatement.cpp; sourceTree = ""; }; + 067AD9A71EBF151100B808B2 /* bindings_core.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bindings_core.cpp; sourceTree = ""; }; + 067AD9A81EBF151100B808B2 /* bindings_core.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings_core.h; sourceTree = ""; }; + 067AD9A91EBF151100B808B2 /* bindings_math.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = bindings_math.cpp; sourceTree = ""; }; + 067AD9AA1EBF151100B808B2 /* bindings_math.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = bindings_math.h; sourceTree = ""; }; + 067AD9AB1EBF151100B808B2 /* builtinexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = builtinexpression.cpp; sourceTree = ""; }; + 067AD9AC1EBF151100B808B2 /* catchstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = catchstatement.cpp; sourceTree = ""; }; + 067AD9AD1EBF151100B808B2 /* compound.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = compound.cpp; sourceTree = ""; }; + 067AD9AE1EBF151100B808B2 /* constantexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = constantexpression.cpp; sourceTree = ""; }; + 067AD9AF1EBF151100B808B2 /* context.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = context.cpp; sourceTree = ""; }; + 067AD9B01EBF151100B808B2 /* deletestatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = deletestatement.cpp; sourceTree = ""; }; + 067AD9B11EBF151100B808B2 /* dictionaryexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = dictionaryexpression.cpp; sourceTree = ""; }; + 067AD9B21EBF151100B808B2 /* evaluator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = evaluator.cpp; sourceTree = ""; }; + 067AD9B31EBF151100B808B2 /* expression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = expression.cpp; sourceTree = ""; }; + 067AD9B41EBF151100B808B2 /* expressionstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = expressionstatement.cpp; sourceTree = ""; }; + 067AD9B51EBF151100B808B2 /* flowstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = flowstatement.cpp; sourceTree = ""; }; + 067AD9B61EBF151100B808B2 /* forstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = forstatement.cpp; sourceTree = ""; }; + 067AD9B71EBF151100B808B2 /* function.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = function.cpp; sourceTree = ""; }; + 067AD9B81EBF151100B808B2 /* functionstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = functionstatement.cpp; sourceTree = ""; }; + 067AD9B91EBF151100B808B2 /* functionvalue.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = functionvalue.cpp; sourceTree = ""; }; + 067AD9BA1EBF151100B808B2 /* ifstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ifstatement.cpp; sourceTree = ""; }; + 067AD9BB1EBF151100B808B2 /* lex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = lex.cpp; sourceTree = ""; }; + 067AD9BC1EBF151100B808B2 /* module.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = module.cpp; sourceTree = ""; }; + 067AD9BD1EBF151100B808B2 /* nameexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = nameexpression.cpp; sourceTree = ""; }; + 067AD9BE1EBF151100B808B2 /* operator.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = operator.cpp; sourceTree = ""; }; + 067AD9BF1EBF151100B808B2 /* operatorexpression.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = operatorexpression.cpp; sourceTree = ""; }; + 067AD9C01EBF151100B808B2 /* parser.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = parser.cpp; sourceTree = ""; }; + 067AD9C11EBF151100B808B2 /* printstatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = printstatement.cpp; sourceTree = ""; }; + 067AD9C21EBF151100B808B2 /* process.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = process.cpp; sourceTree = ""; }; + 067AD9C31EBF151100B808B2 /* scheduler.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scheduler.cpp; sourceTree = ""; }; + 067AD9C41EBF151100B808B2 /* scopestatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scopestatement.cpp; sourceTree = ""; }; + 067AD9C51EBF151100B808B2 /* script.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = script.cpp; sourceTree = ""; }; + 067AD9C61EBF151100B808B2 /* scriptedinfo.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scriptedinfo.cpp; sourceTree = ""; }; + 067AD9C71EBF151100B808B2 /* scriptlex.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scriptlex.cpp; sourceTree = ""; }; + 067AD9C81EBF151100B808B2 /* scriptsystem.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = scriptsystem.cpp; sourceTree = ""; }; + 067AD9C91EBF151100B808B2 /* statement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = statement.cpp; sourceTree = ""; }; + 067AD9CA1EBF151100B808B2 /* tokenbuffer.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tokenbuffer.cpp; sourceTree = ""; }; + 067AD9CB1EBF151100B808B2 /* tokenrange.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = tokenrange.cpp; sourceTree = ""; }; + 067AD9CC1EBF151100B808B2 /* trystatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = trystatement.cpp; sourceTree = ""; }; + 067AD9CD1EBF151100B808B2 /* whilestatement.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = whilestatement.cpp; sourceTree = ""; }; + 067AD9CE1EBF151100B808B2 /* version.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = version.cpp; path = ../sdk/libcore/src/version.cpp; sourceTree = ""; }; + 067AD9D01EBF151100B808B2 /* action.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = action.cpp; sourceTree = ""; }; + 067AD9D11EBF151100B808B2 /* animation.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = animation.cpp; sourceTree = ""; }; + 067AD9D21EBF151100B808B2 /* animationrule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = animationrule.cpp; sourceTree = ""; }; + 067AD9D31EBF151100B808B2 /* constantrule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = constantrule.cpp; sourceTree = ""; }; + 067AD9D41EBF151100B808B2 /* indirectrule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = indirectrule.cpp; sourceTree = ""; }; + 067AD9D51EBF151100B808B2 /* operatorrule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = operatorrule.cpp; sourceTree = ""; }; + 067AD9D61EBF151100B808B2 /* rootwidget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rootwidget.cpp; sourceTree = ""; }; + 067AD9D71EBF151100B808B2 /* rule.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rule.cpp; sourceTree = ""; }; + 067AD9D81EBF151100B808B2 /* rulebank.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rulebank.cpp; sourceTree = ""; }; + 067AD9D91EBF151100B808B2 /* rulerectangle.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = rulerectangle.cpp; sourceTree = ""; }; + 067AD9DA1EBF151100B808B2 /* widget.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = widget.cpp; sourceTree = ""; }; + 067ADA8A1EBF159900B808B2 /* hexlex.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = hexlex.h; path = ../apps/plugins/importidtech1/include/hexlex.h; sourceTree = ""; }; + 067ADA8B1EBF159900B808B2 /* importidtech1.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = importidtech1.h; path = ../apps/plugins/importidtech1/include/importidtech1.h; sourceTree = ""; }; + 067ADA8C1EBF159900B808B2 /* mapimporter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mapimporter.h; path = ../apps/plugins/importidtech1/include/mapimporter.h; sourceTree = ""; }; + 067ADA8D1EBF159900B808B2 /* mapinfotranslator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = mapinfotranslator.h; path = ../apps/plugins/importidtech1/include/mapinfotranslator.h; sourceTree = ""; }; + 067ADA8E1EBF159900B808B2 /* version.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = version.h; path = ../apps/plugins/importidtech1/include/version.h; sourceTree = ""; }; + 067ADA961EBF16B600B808B2 /* c_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = c_wrapper.h; path = ../sdk/libcore/include/de/c_wrapper.h; sourceTree = ""; }; + 067ADA971EBF16B600B808B2 /* charsymbols.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = charsymbols.h; path = ../sdk/libcore/include/de/charsymbols.h; sourceTree = ""; }; + 067ADA991EBF16B600B808B2 /* app.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = app.h; sourceTree = ""; }; + 067ADA9A1EBF16B600B808B2 /* asset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = asset.h; sourceTree = ""; }; + 067ADA9B1EBF16B600B808B2 /* clock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = clock.h; sourceTree = ""; }; + 067ADA9C1EBF16B600B808B2 /* commandline.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = commandline.h; sourceTree = ""; }; + 067ADA9D1EBF16B600B808B2 /* config.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = config.h; sourceTree = ""; }; + 067ADA9E1EBF16B600B808B2 /* debuglogsink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = debuglogsink.h; sourceTree = ""; }; + 067ADA9F1EBF16B600B808B2 /* event.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = event.h; sourceTree = ""; }; + 067ADAA01EBF16B600B808B2 /* filelogsink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filelogsink.h; sourceTree = ""; }; + 067ADAA11EBF16B600B808B2 /* garbage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = garbage.h; sourceTree = ""; }; + 067ADAA21EBF16B600B808B2 /* highperformancetimer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = highperformancetimer.h; sourceTree = ""; }; + 067ADAA31EBF16B600B808B2 /* id.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = id.h; sourceTree = ""; }; + 067ADAA41EBF16B600B808B2 /* library.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = library.h; sourceTree = ""; }; + 067ADAA51EBF16B600B808B2 /* log.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = log.h; sourceTree = ""; }; + 067ADAA61EBF16B600B808B2 /* logbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logbuffer.h; sourceTree = ""; }; + 067ADAA71EBF16B600B808B2 /* logfilter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logfilter.h; sourceTree = ""; }; + 067ADAA81EBF16B600B808B2 /* logsink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = logsink.h; sourceTree = ""; }; + 067ADAA91EBF16B600B808B2 /* loop.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = loop.h; sourceTree = ""; }; + 067ADAAA1EBF16B600B808B2 /* matrix.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = matrix.h; sourceTree = ""; }; + 067ADAAB1EBF16B600B808B2 /* memorylogsink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = memorylogsink.h; sourceTree = ""; }; + 067ADAAC1EBF16B600B808B2 /* monospacelogsinkformatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = monospacelogsinkformatter.h; sourceTree = ""; }; + 067ADAAD1EBF16B600B808B2 /* range.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = range.h; sourceTree = ""; }; + 067ADAAE1EBF16B600B808B2 /* rectangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rectangle.h; sourceTree = ""; }; + 067ADAAF1EBF16B600B808B2 /* system.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = system.h; sourceTree = ""; }; + 067ADAB01EBF16B600B808B2 /* textapp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textapp.h; sourceTree = ""; }; + 067ADAB11EBF16B600B808B2 /* textstreamlogsink.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textstreamlogsink.h; sourceTree = ""; }; + 067ADAB21EBF16B600B808B2 /* unixinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = unixinfo.h; sourceTree = ""; }; + 067ADAB31EBF16B600B808B2 /* vector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vector.h; sourceTree = ""; }; + 067ADAB41EBF16B600B808B2 /* version.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = version.h; sourceTree = ""; }; + 067ADAB61EBF16B600B808B2 /* animationvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = animationvalue.h; sourceTree = ""; }; + 067ADAB71EBF16B600B808B2 /* archive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archive.h; sourceTree = ""; }; + 067ADAB81EBF16B600B808B2 /* arrayvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arrayvalue.h; sourceTree = ""; }; + 067ADAB91EBF16B600B808B2 /* bank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bank.h; sourceTree = ""; }; + 067ADABA1EBF16B600B808B2 /* binarytree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = binarytree.h; sourceTree = ""; }; + 067ADABB1EBF16B600B808B2 /* bitfield.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bitfield.h; sourceTree = ""; }; + 067ADABC1EBF16B600B808B2 /* block.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = block.h; sourceTree = ""; }; + 067ADABD1EBF16B600B808B2 /* blockvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blockvalue.h; sourceTree = ""; }; + 067ADABE1EBF16B600B808B2 /* byteorder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = byteorder.h; sourceTree = ""; }; + 067ADABF1EBF16B600B808B2 /* byterefarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = byterefarray.h; sourceTree = ""; }; + 067ADAC01EBF16B600B808B2 /* bytesubarray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytesubarray.h; sourceTree = ""; }; + 067ADAC11EBF16B600B808B2 /* compiledrecord.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compiledrecord.h; sourceTree = ""; }; + 067ADAC21EBF16B600B808B2 /* counted.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = counted.h; sourceTree = ""; }; + 067ADAC31EBF16B600B808B2 /* date.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = date.h; sourceTree = ""; }; + 067ADAC41EBF16B600B808B2 /* deletable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deletable.h; sourceTree = ""; }; + 067ADAC51EBF16B600B808B2 /* dictionaryvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dictionaryvalue.h; sourceTree = ""; }; + 067ADAC61EBF16B600B808B2 /* escapeparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = escapeparser.h; sourceTree = ""; }; + 067ADAC71EBF16B600B808B2 /* fifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fifo.h; sourceTree = ""; }; + 067ADAC81EBF16B600B808B2 /* fixedbytearray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fixedbytearray.h; sourceTree = ""; }; + 067ADAC91EBF16B600B808B2 /* huffman.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = huffman.h; sourceTree = ""; }; + 067ADACA1EBF16B600B808B2 /* iblock.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iblock.h; sourceTree = ""; }; + 067ADACB1EBF16B600B808B2 /* ibytearray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ibytearray.h; sourceTree = ""; }; + 067ADACC1EBF16B600B808B2 /* iiostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iiostream.h; sourceTree = ""; }; + 067ADACD1EBF16B600B808B2 /* iistream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iistream.h; sourceTree = ""; }; + 067ADACE1EBF16B600B808B2 /* info.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = info.h; sourceTree = ""; }; + 067ADACF1EBF16B600B808B2 /* infobank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = infobank.h; sourceTree = ""; }; + 067ADAD01EBF16B600B808B2 /* iostream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iostream.h; sourceTree = ""; }; + 067ADAD11EBF16B600B808B2 /* ireadable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ireadable.h; sourceTree = ""; }; + 067ADAD21EBF16B600B808B2 /* iserializable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iserializable.h; sourceTree = ""; }; + 067ADAD31EBF16B600B808B2 /* iwritable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iwritable.h; sourceTree = ""; }; + 067ADAD41EBF16B600B808B2 /* json.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = json.h; sourceTree = ""; }; + 067ADAD51EBF16B600B808B2 /* nativepointervalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nativepointervalue.h; sourceTree = ""; }; + 067ADAD61EBF16B600B808B2 /* nonevalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nonevalue.h; sourceTree = ""; }; + 067ADAD71EBF16B600B808B2 /* numbervalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = numbervalue.h; sourceTree = ""; }; + 067ADAD81EBF16B600B808B2 /* observers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = observers.h; sourceTree = ""; }; + 067ADAD91EBF16B600B808B2 /* partition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = partition.h; sourceTree = ""; }; + 067ADADA1EBF16B600B808B2 /* path.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = path.h; sourceTree = ""; }; + 067ADADB1EBF16B600B808B2 /* pathtree.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pathtree.h; sourceTree = ""; }; + 067ADADC1EBF16B600B808B2 /* pointerset.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = pointerset.h; sourceTree = ""; }; + 067ADADD1EBF16B600B808B2 /* profiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = profiles.h; sourceTree = ""; }; + 067ADADE1EBF16B600B808B2 /* property.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = property.h; sourceTree = ""; }; + 067ADADF1EBF16B600B808B2 /* reader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = reader.h; sourceTree = ""; }; + 067ADAE01EBF16B600B808B2 /* record.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = record.h; sourceTree = ""; }; + 067ADAE11EBF16B600B808B2 /* recordaccessor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recordaccessor.h; sourceTree = ""; }; + 067ADAE21EBF16B600B808B2 /* recordvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recordvalue.h; sourceTree = ""; }; + 067ADAE31EBF16B600B808B2 /* refuge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = refuge.h; sourceTree = ""; }; + 067ADAE41EBF16B600B808B2 /* refvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = refvalue.h; sourceTree = ""; }; + 067ADAE51EBF16B600B808B2 /* shared.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = shared.h; sourceTree = ""; }; + 067ADAE61EBF16B600B808B2 /* sourcelinetable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = sourcelinetable.h; sourceTree = ""; }; + 067ADAE71EBF16B600B808B2 /* string.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = string.h; sourceTree = ""; }; + 067ADAE81EBF16B600B808B2 /* stringpool.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = stringpool.h; sourceTree = ""; }; + 067ADAE91EBF16B600B808B2 /* textvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = textvalue.h; sourceTree = ""; }; + 067ADAEA1EBF16B600B808B2 /* time.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = ""; }; + 067ADAEB1EBF16B600B808B2 /* timevalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = timevalue.h; sourceTree = ""; }; + 067ADAEC1EBF16B600B808B2 /* value.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = value.h; sourceTree = ""; }; + 067ADAED1EBF16B600B808B2 /* variable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = variable.h; sourceTree = ""; }; + 067ADAEE1EBF16B600B808B2 /* waitablefifo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = waitablefifo.h; sourceTree = ""; }; + 067ADAEF1EBF16B600B808B2 /* writer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = writer.h; sourceTree = ""; }; + 067ADAF01EBF16B600B808B2 /* zeroed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = zeroed.h; sourceTree = ""; }; + 067ADAF11EBF16B600B808B2 /* ziparchive.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ziparchive.h; sourceTree = ""; }; + 067ADAF21EBF16B600B808B2 /* error.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = error.h; path = ../sdk/libcore/include/de/error.h; sourceTree = ""; }; + 067ADAF41EBF16B600B808B2 /* archiveentryfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archiveentryfile.h; sourceTree = ""; }; + 067ADAF51EBF16B600B808B2 /* archivefeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archivefeed.h; sourceTree = ""; }; + 067ADAF61EBF16B600B808B2 /* archivefolder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = archivefolder.h; sourceTree = ""; }; + 067ADAF71EBF16B600B808B2 /* AssetObserver */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AssetObserver; sourceTree = ""; }; + 067ADAF81EBF16B600B808B2 /* assetobserver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assetobserver.h; sourceTree = ""; }; + 067ADAF91EBF16B600B808B2 /* bytearrayfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bytearrayfile.h; sourceTree = ""; }; + 067ADAFA1EBF16B600B808B2 /* directoryfeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = directoryfeed.h; sourceTree = ""; }; + 067ADAFB1EBF16B600B808B2 /* feed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = feed.h; sourceTree = ""; }; + 067ADAFC1EBF16B600B808B2 /* file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = file.h; sourceTree = ""; }; + 067ADAFD1EBF16B600B808B2 /* fileindex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = fileindex.h; sourceTree = ""; }; + 067ADAFE1EBF16B600B808B2 /* filesystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = filesystem.h; sourceTree = ""; }; + 067ADAFF1EBF16B600B808B2 /* folder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = folder.h; sourceTree = ""; }; + 067ADB001EBF16B600B808B2 /* IInterpreter */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = IInterpreter; sourceTree = ""; }; + 067ADB011EBF16B600B808B2 /* iinterpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iinterpreter.h; sourceTree = ""; }; + 067ADB021EBF16B600B808B2 /* libraryfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = libraryfile.h; sourceTree = ""; }; + 067ADB031EBF16B600B808B2 /* linkfile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = linkfile.h; sourceTree = ""; }; + 067ADB041EBF16B600B808B2 /* metadatabank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = metadatabank.h; sourceTree = ""; }; + 067ADB051EBF16B600B808B2 /* nativefile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nativefile.h; sourceTree = ""; }; + 067ADB061EBF16B600B808B2 /* nativepath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nativepath.h; sourceTree = ""; }; + 067ADB071EBF16B600B808B2 /* Node */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Node; sourceTree = ""; }; + 067ADB081EBF16B600B808B2 /* node.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = node.h; sourceTree = ""; }; + 067ADB091EBF16B600B808B2 /* package.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = package.h; sourceTree = ""; }; + 067ADB0A1EBF16B600B808B2 /* packagefeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packagefeed.h; sourceTree = ""; }; + 067ADB0B1EBF16B600B808B2 /* packageloader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packageloader.h; sourceTree = ""; }; + 067ADB0C1EBF16B600B808B2 /* staticlibraryfeed.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = staticlibraryfeed.h; sourceTree = ""; }; + 067ADB0D1EBF16B600B808B2 /* libcore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = libcore.h; path = ../sdk/libcore/include/de/libcore.h; sourceTree = ""; }; + 067ADB0E1EBF16B600B808B2 /* math.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = math.h; path = ../sdk/libcore/include/de/math.h; sourceTree = ""; }; + 067ADB101EBF16B600B808B2 /* address.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = address.h; sourceTree = ""; }; + 067ADB111EBF16B600B808B2 /* beacon.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = beacon.h; sourceTree = ""; }; + 067ADB121EBF16B600B808B2 /* blockpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = blockpacket.h; sourceTree = ""; }; + 067ADB131EBF16B600B808B2 /* identifiedpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = identifiedpacket.h; sourceTree = ""; }; + 067ADB141EBF16B600B808B2 /* listensocket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = listensocket.h; sourceTree = ""; }; + 067ADB151EBF16B600B808B2 /* message.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = message.h; sourceTree = ""; }; + 067ADB161EBF16B600B808B2 /* packet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = packet.h; sourceTree = ""; }; + 067ADB171EBF16B600B808B2 /* protocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = protocol.h; sourceTree = ""; }; + 067ADB181EBF16B600B808B2 /* recordpacket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = recordpacket.h; sourceTree = ""; }; + 067ADB191EBF16B600B808B2 /* socket.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = socket.h; sourceTree = ""; }; + 067ADB1A1EBF16B600B808B2 /* transmitter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = transmitter.h; sourceTree = ""; }; + 067ADB1C1EBF16B600B808B2 /* arrayexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = arrayexpression.h; sourceTree = ""; }; + 067ADB1D1EBF16B600B808B2 /* assignstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = assignstatement.h; sourceTree = ""; }; + 067ADB1E1EBF16B600B808B2 /* builtinexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = builtinexpression.h; sourceTree = ""; }; + 067ADB1F1EBF16B600B808B2 /* catchstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = catchstatement.h; sourceTree = ""; }; + 067ADB201EBF16B600B808B2 /* compound.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = compound.h; sourceTree = ""; }; + 067ADB211EBF16B600B808B2 /* constantexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = constantexpression.h; sourceTree = ""; }; + 067ADB221EBF16B600B808B2 /* context.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = context.h; sourceTree = ""; }; + 067ADB231EBF16B600B808B2 /* deletestatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = deletestatement.h; sourceTree = ""; }; + 067ADB241EBF16B600B808B2 /* dictionaryexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = dictionaryexpression.h; sourceTree = ""; }; + 067ADB251EBF16B600B808B2 /* evaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = evaluator.h; sourceTree = ""; }; + 067ADB261EBF16B600B808B2 /* expression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = expression.h; sourceTree = ""; }; + 067ADB271EBF16B600B808B2 /* expressionstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = expressionstatement.h; sourceTree = ""; }; + 067ADB281EBF16B600B808B2 /* flowstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = flowstatement.h; sourceTree = ""; }; + 067ADB291EBF16B600B808B2 /* forstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = forstatement.h; sourceTree = ""; }; + 067ADB2A1EBF16B600B808B2 /* function.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = function.h; sourceTree = ""; }; + 067ADB2B1EBF16B600B808B2 /* functionstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = functionstatement.h; sourceTree = ""; }; + 067ADB2C1EBF16B600B808B2 /* functionvalue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = functionvalue.h; sourceTree = ""; }; + 067ADB2D1EBF16B600B808B2 /* ifstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ifstatement.h; sourceTree = ""; }; + 067ADB2E1EBF16B600B808B2 /* iobject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iobject.h; sourceTree = ""; }; + 067ADB2F1EBF16B600B808B2 /* iparser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iparser.h; sourceTree = ""; }; + 067ADB301EBF16B600B808B2 /* lex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = lex.h; sourceTree = ""; }; + 067ADB311EBF16B600B808B2 /* module.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = module.h; sourceTree = ""; }; + 067ADB321EBF16B600B808B2 /* nameexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = nameexpression.h; sourceTree = ""; }; + 067ADB331EBF16B600B808B2 /* operator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = operator.h; sourceTree = ""; }; + 067ADB341EBF16B600B808B2 /* operatorexpression.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = operatorexpression.h; sourceTree = ""; }; + 067ADB351EBF16B600B808B2 /* parser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = parser.h; sourceTree = ""; }; + 067ADB361EBF16B600B808B2 /* printstatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = printstatement.h; sourceTree = ""; }; + 067ADB371EBF16B600B808B2 /* process.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = process.h; sourceTree = ""; }; + 067ADB381EBF16B600B808B2 /* scheduler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scheduler.h; sourceTree = ""; }; + 067ADB391EBF16B600B808B2 /* scopestatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scopestatement.h; sourceTree = ""; }; + 067ADB3A1EBF16B600B808B2 /* script.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = script.h; sourceTree = ""; }; + 067ADB3B1EBF16B600B808B2 /* scriptedinfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptedinfo.h; sourceTree = ""; }; + 067ADB3C1EBF16B600B808B2 /* scriptlex.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptlex.h; sourceTree = ""; }; + 067ADB3D1EBF16B600B808B2 /* scriptsystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = scriptsystem.h; sourceTree = ""; }; + 067ADB3E1EBF16B600B808B2 /* statement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = statement.h; sourceTree = ""; }; + 067ADB3F1EBF16B600B808B2 /* tokenbuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokenbuffer.h; sourceTree = ""; }; + 067ADB401EBF16B600B808B2 /* tokenrange.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokenrange.h; sourceTree = ""; }; + 067ADB411EBF16B600B808B2 /* trystatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = trystatement.h; sourceTree = ""; }; + 067ADB421EBF16B600B808B2 /* whilestatement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = whilestatement.h; sourceTree = ""; }; + 067ADB441EBF16B600B808B2 /* action.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = action.h; sourceTree = ""; }; + 067ADB451EBF16B600B808B2 /* animation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = animation.h; sourceTree = ""; }; + 067ADB461EBF16B600B808B2 /* animationrule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = animationrule.h; sourceTree = ""; }; + 067ADB471EBF16B600B808B2 /* animationvector.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = animationvector.h; sourceTree = ""; }; + 067ADB481EBF16B600B808B2 /* constantrule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = constantrule.h; sourceTree = ""; }; + 067ADB491EBF16B600B808B2 /* indirectrule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = indirectrule.h; sourceTree = ""; }; + 067ADB4A1EBF16B600B808B2 /* operatorrule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = operatorrule.h; sourceTree = ""; }; + 067ADB4B1EBF16B600B808B2 /* rootwidget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rootwidget.h; sourceTree = ""; }; + 067ADB4C1EBF16B600B808B2 /* rule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rule.h; sourceTree = ""; }; + 067ADB4D1EBF16B600B808B2 /* rulebank.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rulebank.h; sourceTree = ""; }; + 067ADB4E1EBF16B600B808B2 /* rulerectangle.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rulerectangle.h; sourceTree = ""; }; + 067ADB4F1EBF16B600B808B2 /* rules.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rules.h; sourceTree = ""; }; + 067ADB501EBF16B600B808B2 /* widget.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = widget.h; sourceTree = ""; }; + 068610581EBF01F700180814 /* Doomsday.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Doomsday.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 068610621EBF01F700180814 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 068610771EBF01F700180814 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; + 068610791EBF01F700180814 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 0686107F1EBF04C500180814 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; }; + 068610801EBF04C500180814 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; + 068610811EBF04C500180814 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; + 068610821EBF04C500180814 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 068610831EBF04C500180814 /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; }; + 068610841EBF04C500180814 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 068610851EBF04C500180814 /* ImageIO.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ImageIO.framework; path = System/Library/Frameworks/ImageIO.framework; sourceTree = SDKROOT; }; + 068610861EBF04C500180814 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; + 068610871EBF04C500180814 /* OpenGLES.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = OpenGLES.framework; path = System/Library/Frameworks/OpenGLES.framework; sourceTree = SDKROOT; }; + 068610881EBF04C500180814 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; + 068610891EBF04C500180814 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; + 0686108A1EBF04C500180814 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 063575271EBF39880074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063575CD1EBF3AD50074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063576A81EBF3CD20074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 063577171EBF3E1E0074E6D4 /* OpenGLES.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063578011EBF42D10074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0635788F1EBF43A30074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357AEB1EBF61C70074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357AFF1EBF63770074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B241EBF69C00074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B371EBF6EBD0074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357CC61EBF70A20074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357DDC1EBF728D0074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357EE81EBF76120074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357F3D1EBF77A00074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063582431EBFBA120074E6D4 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD9061EBF143600B808B2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD9241EBF14E000B808B2 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 068610551EBF01F700180814 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 067ADA941EBF15E600B808B2 /* libdeng_core.a in Frameworks */, + 0635771A1EBF3E990074E6D4 /* libdeng_shell.a in Frameworks */, + 063577181EBF3E990074E6D4 /* libdeng_gui.a in Frameworks */, + 06357E5F1EBF73F80074E6D4 /* libdeng_appfw.a in Frameworks */, + 063577191EBF3E990074E6D4 /* libdeng_legacy.a in Frameworks */, + 06357E601EBF73F80074E6D4 /* libdeng_doomsday.a in Frameworks */, + 06357E611EBF73F80074E6D4 /* libdeng_gamefw.a in Frameworks */, + 06357F531EBF79FF0074E6D4 /* libaudio_fmod.a in Frameworks */, + 067ADA951EBF15E600B808B2 /* libimportidtech1.a in Frameworks */, + 06357E651EBF73F80074E6D4 /* libimportdeh.a in Frameworks */, + 06357E661EBF73F80074E6D4 /* libimportudmf.a in Frameworks */, + 06357E621EBF73F80074E6D4 /* libdoom.a in Frameworks */, + 06357E631EBF73F80074E6D4 /* libheretic.a in Frameworks */, + 06357E641EBF73F80074E6D4 /* libhexen.a in Frameworks */, + 06357F541EBF79FF0074E6D4 /* libdoom64.a in Frameworks */, + 0635824B1EBFBA5F0074E6D4 /* libassimp.a in Frameworks */, + 0635817F1EBF87040074E6D4 /* libz.tbd in Frameworks */, + 0686108B1EBF04C500180814 /* AudioToolbox.framework in Frameworks */, + 0686108C1EBF04C500180814 /* AVFoundation.framework in Frameworks */, + 0686108D1EBF04C500180814 /* CoreFoundation.framework in Frameworks */, + 0686108E1EBF04C500180814 /* CoreGraphics.framework in Frameworks */, + 0686108F1EBF04C500180814 /* CoreText.framework in Frameworks */, + 068610901EBF04C500180814 /* Foundation.framework in Frameworks */, + 068610911EBF04C500180814 /* ImageIO.framework in Frameworks */, + 068610921EBF04C500180814 /* MobileCoreServices.framework in Frameworks */, + 068610931EBF04C500180814 /* OpenGLES.framework in Frameworks */, + 068610941EBF04C500180814 /* QuartzCore.framework in Frameworks */, + 068610951EBF04C500180814 /* Security.framework in Frameworks */, + 068610961EBF04C500180814 /* UIKit.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 063575981EBF3A030074E6D4 /* Headers */ = { + isa = PBXGroup; + children = ( + 063575991EBF3A1F0074E6D4 /* abstractlineeditor.h */, + 0635759A1EBF3A1F0074E6D4 /* abstractlink.h */, + 0635759B1EBF3A1F0074E6D4 /* action.h */, + 0635759C1EBF3A1F0074E6D4 /* choicewidget.h */, + 0635759D1EBF3A1F0074E6D4 /* commandlinewidget.h */, + 0635759E1EBF3A1F0074E6D4 /* dialogwidget.h */, + 0635759F1EBF3A1F0074E6D4 /* doomsdayinfo.h */, + 063575A01EBF3A1F0074E6D4 /* editorhistory.h */, + 063575A11EBF3A1F0074E6D4 /* inputdialog.h */, + 063575A21EBF3A1F0074E6D4 /* itexteditor.h */, + 063575A31EBF3A1F0074E6D4 /* keyevent.h */, + 063575A41EBF3A1F0074E6D4 /* labelwidget.h */, + 063575A51EBF3A1F0074E6D4 /* lexicon.h */, + 063575A61EBF3A1F0074E6D4 /* libshell.h */, + 063575A71EBF3A1F0074E6D4 /* lineeditwidget.h */, + 063575A81EBF3A1F0074E6D4 /* link.h */, + 063575A91EBF3A1F0074E6D4 /* localserver.h */, + 063575AA1EBF3A1F0074E6D4 /* logwidget.h */, + 063575AB1EBF3A1F0074E6D4 /* menuwidget.h */, + 063575AC1EBF3A1F0074E6D4 /* monospacelinewrapping.h */, + 063575AD1EBF3A1F0074E6D4 /* protocol.h */, + 063575AE1EBF3A1F0074E6D4 /* serverfinder.h */, + 063575AF1EBF3A1F0074E6D4 /* serverinfo.h */, + 063575B01EBF3A1F0074E6D4 /* textcanvas.h */, + 063575B11EBF3A1F0074E6D4 /* textrootwidget.h */, + 063575B21EBF3A1F0074E6D4 /* textwidget.h */, + ); + name = Headers; + sourceTree = ""; + }; + 063576071EBF3B5C0074E6D4 /* Headers */ = { + isa = PBXGroup; + children = ( + 063576081EBF3B6C0074E6D4 /* aabox.h */, + 063576091EBF3B6C0074E6D4 /* animator.h */, + 0635760A1EBF3B6C0074E6D4 /* binangle.h */, + 0635760B1EBF3B6C0074E6D4 /* concurrency.h */, + 0635760C1EBF3B6C0074E6D4 /* ddstring.h */, + 0635760D1EBF3B6C0074E6D4 /* findfile.h */, + 0635760E1EBF3B6C0074E6D4 /* fixedpoint.h */, + 0635760F1EBF3B6C0074E6D4 /* liblegacy.h */, + 063576101EBF3B6C0074E6D4 /* mathutil.h */, + 063576111EBF3B6C0074E6D4 /* memory.h */, + 063576121EBF3B6C0074E6D4 /* memoryblockset.h */, + 063576131EBF3B6C0074E6D4 /* memoryzone.h */, + 063576141EBF3B6C0074E6D4 /* nodepile.h */, + 063576151EBF3B6C0074E6D4 /* point.h */, + 063576161EBF3B6C0074E6D4 /* reader.h */, + 063576171EBF3B6C0074E6D4 /* rect.h */, + 063576181EBF3B6C0074E6D4 /* size.h */, + 063576191EBF3B6C0074E6D4 /* smoother.h */, + 0635761A1EBF3B6C0074E6D4 /* stack.h */, + 0635761B1EBF3B6C0074E6D4 /* str.h */, + 0635761C1EBF3B6C0074E6D4 /* stringarray.h */, + 0635761D1EBF3B6C0074E6D4 /* strutil.h */, + 0635761E1EBF3B6C0074E6D4 /* texgamma.h */, + 0635761F1EBF3B6C0074E6D4 /* timer.h */, + 063576201EBF3B6C0074E6D4 /* types.h */, + 063576211EBF3B6C0074E6D4 /* unittest.h */, + 063576221EBF3B6C0074E6D4 /* vector1.h */, + 063576231EBF3B6C0074E6D4 /* writer.h */, + 063576241EBF3B6C0074E6D4 /* str.hh */, + 063576251EBF3B6C0074E6D4 /* memoryzone_private.h */, + ); + name = Headers; + sourceTree = ""; + }; + 063576261EBF3C970074E6D4 /* audio */ = { + isa = PBXGroup; + children = ( + 063576271EBF3C970074E6D4 /* sound.cpp */, + 063576281EBF3C970074E6D4 /* waveform.cpp */, + 063576291EBF3C970074E6D4 /* waveformbank.cpp */, + ); + name = audio; + path = ../sdk/libgui/src/audio; + sourceTree = ""; + }; + 0635762A1EBF3C970074E6D4 /* graphics */ = { + isa = PBXGroup; + children = ( + 0635762B1EBF3C970074E6D4 /* atlas.cpp */, + 0635762C1EBF3C970074E6D4 /* atlastexture.cpp */, + 0635762D1EBF3C970074E6D4 /* colorbank.cpp */, + 0635762E1EBF3C970074E6D4 /* drawable.cpp */, + 0635762F1EBF3C970074E6D4 /* glatlasbuffer.cpp */, + 063576301EBF3C970074E6D4 /* glbuffer.cpp */, + 063576311EBF3C970074E6D4 /* gldrawqueue.cpp */, + 063576321EBF3C970074E6D4 /* glframebuffer.cpp */, + 063576331EBF3C970074E6D4 /* glframebuffer_alternativebuffer.cpp */, + 063576341EBF3C970074E6D4 /* glinfo.cpp */, + 063576351EBF3C970074E6D4 /* glprogram.cpp */, + 063576361EBF3C970074E6D4 /* glshader.cpp */, + 063576371EBF3C970074E6D4 /* glshaderbank.cpp */, + 063576381EBF3C970074E6D4 /* glstate.cpp */, + 063576391EBF3C970074E6D4 /* glsubbuffer.cpp */, + 0635763A1EBF3C970074E6D4 /* gltexture.cpp */, + 0635763B1EBF3C970074E6D4 /* gltextureframebuffer.cpp */, + 0635763C1EBF3C970074E6D4 /* gluniform.cpp */, + 0635763D1EBF3C970074E6D4 /* heightmap.cpp */, + 0635763E1EBF3C970074E6D4 /* image.cpp */, + 0635763F1EBF3C970074E6D4 /* imagebank.cpp */, + 063576401EBF3C970074E6D4 /* imagefile.cpp */, + 063576411EBF3C970074E6D4 /* kdtreeatlasallocator.cpp */, + 063576421EBF3C970074E6D4 /* modelbank.cpp */, + 063576431EBF3C970074E6D4 /* modeldrawable.cpp */, + 063576441EBF3C970074E6D4 /* multiatlas.cpp */, + 063576451EBF3C970074E6D4 /* rowatlasallocator.cpp */, + 063576461EBF3C970074E6D4 /* texturebank.cpp */, + ); + name = graphics; + path = ../sdk/libgui/src/graphics; + sourceTree = ""; + }; + 063576471EBF3C970074E6D4 /* input */ = { + isa = PBXGroup; + children = ( + 063576491EBF3C970074E6D4 /* keyevent.cpp */, + 0635764A1EBF3C970074E6D4 /* keyeventsource.cpp */, + 0635764B1EBF3C970074E6D4 /* mouseevent.cpp */, + 0635764C1EBF3C970074E6D4 /* mouseeventsource.cpp */, + ); + name = input; + path = ../sdk/libgui/src/input; + sourceTree = ""; + }; + 0635764D1EBF3C970074E6D4 /* text */ = { + isa = PBXGroup; + children = ( + 0635764E1EBF3C970074E6D4 /* coretextnativefont_macx.cpp */, + 0635764F1EBF3C970074E6D4 /* coretextnativefont_macx.h */, + 063576501EBF3C970074E6D4 /* font.cpp */, + 063576511EBF3C970074E6D4 /* font_richformat.cpp */, + 063576521EBF3C970074E6D4 /* fontbank.cpp */, + 063576531EBF3C970074E6D4 /* nativefont.cpp */, + ); + name = text; + path = ../sdk/libgui/src/text; + sourceTree = ""; + }; + 063576E01EBF3D0F0074E6D4 /* Headers */ = { + isa = PBXGroup; + children = ( + 063576E11EBF3D240074E6D4 /* audio */, + 063576E51EBF3D240074E6D4 /* graphics */, + 063577041EBF3D240074E6D4 /* gui */, + 0635770D1EBF3D240074E6D4 /* input */, + 063577131EBF3D240074E6D4 /* text */, + ); + name = Headers; + sourceTree = ""; + }; + 063576E11EBF3D240074E6D4 /* audio */ = { + isa = PBXGroup; + children = ( + 063576E21EBF3D240074E6D4 /* sound.h */, + 063576E31EBF3D240074E6D4 /* waveform.h */, + 063576E41EBF3D240074E6D4 /* waveformbank.h */, + ); + name = audio; + path = ../sdk/libgui/include/de/audio; + sourceTree = ""; + }; + 063576E51EBF3D240074E6D4 /* graphics */ = { + isa = PBXGroup; + children = ( + 063576E61EBF3D240074E6D4 /* atlas.h */, + 063576E71EBF3D240074E6D4 /* atlastexture.h */, + 063576E81EBF3D240074E6D4 /* colorbank.h */, + 063576E91EBF3D240074E6D4 /* drawable.h */, + 063576EA1EBF3D240074E6D4 /* glatlasbuffer.h */, + 063576EB1EBF3D240074E6D4 /* glbuffer.h */, + 063576EC1EBF3D240074E6D4 /* gldrawqueue.h */, + 063576ED1EBF3D240074E6D4 /* glframebuffer.h */, + 063576EE1EBF3D240074E6D4 /* glinfo.h */, + 063576EF1EBF3D240074E6D4 /* glpixelformat.h */, + 063576F01EBF3D240074E6D4 /* glprogram.h */, + 063576F11EBF3D240074E6D4 /* glshader.h */, + 063576F21EBF3D240074E6D4 /* glshaderbank.h */, + 063576F31EBF3D240074E6D4 /* glstate.h */, + 063576F41EBF3D240074E6D4 /* glsubbuffer.h */, + 063576F51EBF3D240074E6D4 /* gltexture.h */, + 063576F61EBF3D240074E6D4 /* gltextureframebuffer.h */, + 063576F71EBF3D240074E6D4 /* gluniform.h */, + 063576F81EBF3D240074E6D4 /* heightmap.h */, + 063576F91EBF3D240074E6D4 /* image.h */, + 063576FA1EBF3D240074E6D4 /* imagebank.h */, + 063576FB1EBF3D240074E6D4 /* imagefile.h */, + 063576FC1EBF3D240074E6D4 /* kdtreeatlasallocator.h */, + 063576FD1EBF3D240074E6D4 /* modelbank.h */, + 063576FE1EBF3D240074E6D4 /* modeldrawable.h */, + 063576FF1EBF3D240074E6D4 /* multiatlas.h */, + 063577001EBF3D240074E6D4 /* opengl.h */, + 063577011EBF3D240074E6D4 /* rowatlasallocator.h */, + 063577021EBF3D240074E6D4 /* texturebank.h */, + 063577031EBF3D240074E6D4 /* vertexbuilder.h */, + ); + name = graphics; + path = ../sdk/libgui/include/de/graphics; + sourceTree = ""; + }; + 063577041EBF3D240074E6D4 /* gui */ = { + isa = PBXGroup; + children = ( + 063577051EBF3D240074E6D4 /* displaymode.h */, + 063577061EBF3D240074E6D4 /* displaymode_native.h */, + 063577071EBF3D240074E6D4 /* glwindow_qml.h */, + 063577081EBF3D240074E6D4 /* guiapp.h */, + 063577091EBF3D240074E6D4 /* guiloop.h */, + 0635770A1EBF3D240074E6D4 /* libgui.h */, + 0635770B1EBF3D240074E6D4 /* persistentglwindow.h */, + 0635770C1EBF3D240074E6D4 /* windoweventhandler.h */, + ); + name = gui; + path = ../sdk/libgui/include/de/gui; + sourceTree = ""; + }; + 0635770D1EBF3D240074E6D4 /* input */ = { + isa = PBXGroup; + children = ( + 0635770E1EBF3D240074E6D4 /* ddkey.h */, + 0635770F1EBF3D240074E6D4 /* keyevent.h */, + 063577101EBF3D240074E6D4 /* keyeventsource.h */, + 063577111EBF3D240074E6D4 /* mouseevent.h */, + 063577121EBF3D240074E6D4 /* mouseeventsource.h */, + ); + name = input; + path = ../sdk/libgui/include/de/input; + sourceTree = ""; + }; + 063577131EBF3D240074E6D4 /* text */ = { + isa = PBXGroup; + children = ( + 063577141EBF3D240074E6D4 /* font.h */, + 063577151EBF3D240074E6D4 /* fontbank.h */, + 063577161EBF3D240074E6D4 /* nativefont.h */, + ); + name = text; + path = ../sdk/libgui/include/de/text; + sourceTree = ""; + }; + 063577271EBF42C10074E6D4 /* dialogs */ = { + isa = PBXGroup; + children = ( + 063577281EBF42C10074E6D4 /* directorylistdialog.cpp */, + 063577291EBF42C10074E6D4 /* inputdialog.cpp */, + 0635772A1EBF42C10074E6D4 /* messagedialog.cpp */, + ); + name = dialogs; + path = ../sdk/libappfw/src/dialogs; + sourceTree = ""; + }; + 0635772B1EBF42C10074E6D4 /* vr */ = { + isa = PBXGroup; + children = ( + 0635772C1EBF42C10074E6D4 /* oculusrift.cpp */, + 0635772D1EBF42C10074E6D4 /* vrconfig.cpp */, + ); + name = vr; + path = ../sdk/libappfw/src/vr; + sourceTree = ""; + }; + 0635772E1EBF42C10074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 0635772F1EBF42C10074E6D4 /* auxbuttonwidget.cpp */, + 063577301EBF42C10074E6D4 /* blurwidget.cpp */, + 063577311EBF42C10074E6D4 /* buttonwidget.cpp */, + 063577321EBF42C10074E6D4 /* choicewidget.cpp */, + 063577331EBF42C10074E6D4 /* commandwidget.cpp */, + 063577341EBF42C10074E6D4 /* compositorwidget.cpp */, + 063577351EBF42C10074E6D4 /* dialogwidget.cpp */, + 063577361EBF42C10074E6D4 /* directoryarraywidget.cpp */, + 063577371EBF42C10074E6D4 /* documentpopupwidget.cpp */, + 063577381EBF42C10074E6D4 /* documentwidget.cpp */, + 063577391EBF42C10074E6D4 /* fadetoblackwidget.cpp */, + 0635773A1EBF42C10074E6D4 /* focuswidget.cpp */, + 0635773B1EBF42C10074E6D4 /* foldpanelwidget.cpp */, + 0635773C1EBF42C10074E6D4 /* gridpopupwidget.cpp */, + 0635773D1EBF42C10074E6D4 /* labelwidget.cpp */, + 0635773E1EBF42C10074E6D4 /* lineeditwidget.cpp */, + 0635773F1EBF42C10074E6D4 /* logwidget.cpp */, + 063577401EBF42C10074E6D4 /* menuwidget.cpp */, + 063577411EBF42C10074E6D4 /* notificationareawidget.cpp */, + 063577421EBF42C10074E6D4 /* panelwidget.cpp */, + 063577431EBF42C10074E6D4 /* popupbuttonwidget.cpp */, + 063577441EBF42C10074E6D4 /* popupmenuwidget.cpp */, + 063577451EBF42C10074E6D4 /* popupwidget.cpp */, + 063577461EBF42C10074E6D4 /* progresswidget.cpp */, + 063577471EBF42C10074E6D4 /* relaywidget.cpp */, + 063577481EBF42C10074E6D4 /* scriptcommandwidget.cpp */, + 063577491EBF42C10074E6D4 /* scrollareawidget.cpp */, + 0635774A1EBF42C10074E6D4 /* sliderwidget.cpp */, + 0635774B1EBF42C10074E6D4 /* tabwidget.cpp */, + 0635774C1EBF42C10074E6D4 /* togglewidget.cpp */, + 0635774D1EBF42C10074E6D4 /* variablearraywidget.cpp */, + 0635774E1EBF42C10074E6D4 /* variablechoicewidget.cpp */, + 0635774F1EBF42C10074E6D4 /* variablelineeditwidget.cpp */, + 063577501EBF42C10074E6D4 /* variablesliderwidget.cpp */, + 063577511EBF42C10074E6D4 /* variabletogglewidget.cpp */, + ); + name = widgets; + path = ../sdk/libappfw/src/widgets; + sourceTree = ""; + }; + 063578951EBF43DE0074E6D4 /* c_wrapper */ = { + isa = PBXGroup; + children = ( + 063578961EBF43DE0074E6D4 /* library.cpp */, + ); + name = c_wrapper; + path = ../apps/libdoomsday/src/c_wrapper; + sourceTree = ""; + }; + 063578971EBF43DE0074E6D4 /* console */ = { + isa = PBXGroup; + children = ( + 063578981EBF43DE0074E6D4 /* alias.cpp */, + 063578991EBF43DE0074E6D4 /* cmd.cpp */, + 0635789A1EBF43DE0074E6D4 /* exec.cpp */, + 0635789B1EBF43DE0074E6D4 /* knownword.cpp */, + 0635789C1EBF43DE0074E6D4 /* var.cpp */, + ); + name = console; + path = ../apps/libdoomsday/src/console; + sourceTree = ""; + }; + 0635789D1EBF43DE0074E6D4 /* defs */ = { + isa = PBXGroup; + children = ( + 0635789E1EBF43DE0074E6D4 /* decoration.cpp */, + 0635789F1EBF43DE0074E6D4 /* ded.cpp */, + 063578A01EBF43DE0074E6D4 /* dedfile.cpp */, + 063578A11EBF43DE0074E6D4 /* dedparser.cpp */, + 063578A21EBF43DE0074E6D4 /* dedregister.cpp */, + 063578A31EBF43DE0074E6D4 /* definition.cpp */, + 063578A41EBF43DE0074E6D4 /* episode.cpp */, + 063578A51EBF43DE0074E6D4 /* finale.cpp */, + 063578A61EBF43DE0074E6D4 /* mapgraphnode.cpp */, + 063578A71EBF43DE0074E6D4 /* mapinfo.cpp */, + 063578A81EBF43DE0074E6D4 /* material.cpp */, + 063578A91EBF43DE0074E6D4 /* model.cpp */, + 063578AA1EBF43DE0074E6D4 /* music.cpp */, + 063578AB1EBF43DE0074E6D4 /* sky.cpp */, + 063578AC1EBF43DE0074E6D4 /* sprite.cpp */, + 063578AD1EBF43DE0074E6D4 /* state.cpp */, + 063578AE1EBF43DE0074E6D4 /* thing.cpp */, + ); + name = defs; + path = ../apps/libdoomsday/src/defs; + sourceTree = ""; + }; + 063578AF1EBF43DE0074E6D4 /* filesys */ = { + isa = PBXGroup; + children = ( + 063578B01EBF43DE0074E6D4 /* datafile.cpp */, + 063578B11EBF43DE0074E6D4 /* datafolder.cpp */, + 063578B21EBF43DE0074E6D4 /* file.cpp */, + 063578B31EBF43DE0074E6D4 /* filehandle.cpp */, + 063578B41EBF43DE0074E6D4 /* fileid.cpp */, + 063578B51EBF43DE0074E6D4 /* filetype.cpp */, + 063578B61EBF43DE0074E6D4 /* fs_main.cpp */, + 063578B71EBF43DE0074E6D4 /* fs_scheme.cpp */, + 063578B81EBF43DE0074E6D4 /* fs_util.cpp */, + 063578BA1EBF43DE0074E6D4 /* lumpcache.cpp */, + 063578BB1EBF43DE0074E6D4 /* lumpindex.cpp */, + 063578BC1EBF43DE0074E6D4 /* readfile.cpp */, + 063578BD1EBF43DE0074E6D4 /* searchpath.cpp */, + 063578BE1EBF43DE0074E6D4 /* virtualmappings.cpp */, + 063578BF1EBF43DE0074E6D4 /* wad.cpp */, + 063578C01EBF43DE0074E6D4 /* zip.cpp */, + ); + name = filesys; + path = ../apps/libdoomsday/src/filesys; + sourceTree = ""; + }; + 063578C11EBF43DE0074E6D4 /* resource */ = { + isa = PBXGroup; + children = ( + 063578C21EBF43DE0074E6D4 /* animgroup.cpp */, + 063578C31EBF43DE0074E6D4 /* animgroups.cpp */, + 063578C41EBF43DE0074E6D4 /* bundlelinkfeed.cpp */, + 063578C51EBF43DE0074E6D4 /* bundles.cpp */, + 063578C61EBF43DE0074E6D4 /* colorpalette.cpp */, + 063578C71EBF43DE0074E6D4 /* colorpalettes.cpp */, + 063578C81EBF43DE0074E6D4 /* composite.cpp */, + 063578C91EBF43DE0074E6D4 /* databundle.cpp */, + 063578CA1EBF43DE0074E6D4 /* doomsdaypackage.cpp */, + 063578CB1EBF43DE0074E6D4 /* lumpcatalog.cpp */, + 063578CC1EBF43DE0074E6D4 /* lumpdirectory.cpp */, + 063578CD1EBF43DE0074E6D4 /* m_decomp64.cpp */, + 063578CE1EBF43DE0074E6D4 /* manifest.cpp */, + 063578CF1EBF43DE0074E6D4 /* mapmanifest.cpp */, + 063578D01EBF43DE0074E6D4 /* mapmanifests.cpp */, + 063578D11EBF43DE0074E6D4 /* patch.cpp */, + 063578D21EBF43DE0074E6D4 /* patchname.cpp */, + 063578D31EBF43DE0074E6D4 /* pcx.cpp */, + 063578D41EBF43DE0074E6D4 /* resourceclass.cpp */, + 063578D51EBF43DE0074E6D4 /* resources.cpp */, + 063578D61EBF43DE0074E6D4 /* sprites.cpp */, + 063578D71EBF43DE0074E6D4 /* texture.cpp */, + 063578D81EBF43DE0074E6D4 /* texturemanifest.cpp */, + 063578D91EBF43DE0074E6D4 /* textures.cpp */, + 063578DA1EBF43DE0074E6D4 /* texturescheme.cpp */, + 063578DB1EBF43DE0074E6D4 /* tga.cpp */, + 063578DC1EBF43DE0074E6D4 /* wav.cpp */, + ); + name = resource; + path = ../apps/libdoomsday/src/resource; + sourceTree = ""; + }; + 063578DD1EBF43DE0074E6D4 /* world */ = { + isa = PBXGroup; + children = ( + 063578DE1EBF43DE0074E6D4 /* actions.cpp */, + 063578DF1EBF43DE0074E6D4 /* bspnode.cpp */, + 063578E01EBF43DE0074E6D4 /* detailtexturemateriallayer.cpp */, + 063578E11EBF43DE0074E6D4 /* dmuargs.cpp */, + 063578E21EBF43DE0074E6D4 /* entitydatabase.cpp */, + 063578E31EBF43DE0074E6D4 /* entitydef.cpp */, + 063578E41EBF43DE0074E6D4 /* map.cpp */, + 063578E51EBF43DE0074E6D4 /* mapelement.cpp */, + 063578E61EBF43DE0074E6D4 /* material.cpp */, + 063578E71EBF43DE0074E6D4 /* materialarchive.cpp */, + 063578E81EBF43DE0074E6D4 /* materialmanifest.cpp */, + 063578E91EBF43DE0074E6D4 /* materials.cpp */, + 063578EA1EBF43DE0074E6D4 /* materialscheme.cpp */, + 063578EB1EBF43DE0074E6D4 /* mobjthinkerdata.cpp */, + 063578EC1EBF43DE0074E6D4 /* propertyvalue.cpp */, + 063578ED1EBF43DE0074E6D4 /* shinetexturemateriallayer.cpp */, + 063578EE1EBF43DE0074E6D4 /* texturemateriallayer.cpp */, + 063578EF1EBF43DE0074E6D4 /* thinker.cpp */, + 063578F01EBF43DE0074E6D4 /* thinkerdata.cpp */, + 063578F11EBF43DE0074E6D4 /* world.cpp */, + 063578F21EBF43DE0074E6D4 /* xg.cpp */, + ); + name = world; + path = ../apps/libdoomsday/src/world; + sourceTree = ""; + }; + 06357AF11EBF61EF0074E6D4 /* libgamefw */ = { + isa = PBXGroup; + children = ( + 06357AF21EBF62180074E6D4 /* libgamefw.cpp */, + 06357AF31EBF62180074E6D4 /* mapspot.cpp */, + ); + name = libgamefw; + sourceTree = ""; + }; + 06357B151EBF69550074E6D4 /* Shared Sources */ = { + isa = PBXGroup; + children = ( + 06357B771EBF6F750074E6D4 /* acs */, + 06357B7C1EBF6F750074E6D4 /* game */, + 06357B841EBF6F750074E6D4 /* hud */, + 06357B991EBF6F760074E6D4 /* menu */, + 06357BAD1EBF6F760074E6D4 /* network */, + 06357BB11EBF6F760074E6D4 /* world */, + 06357BCC1EBF6F760074E6D4 /* common.c */, + 06357BCD1EBF6F760074E6D4 /* hu_pspr.c */, + 06357BCE1EBF6F760074E6D4 /* p_iterlist.c */, + 06357BCF1EBF6F760074E6D4 /* p_terraintype.c */, + 06357BD01EBF6F760074E6D4 /* p_user.c */, + 06357BD11EBF6F760074E6D4 /* p_view.c */, + 06357BD21EBF6F760074E6D4 /* r_common.c */, + 06357BD31EBF6F760074E6D4 /* x_hair.c */, + 06357BD41EBF6F760074E6D4 /* animdefs.cpp */, + 06357BD51EBF6F760074E6D4 /* fi_lib.cpp */, + 06357BD61EBF6F760074E6D4 /* g_controls.cpp */, + 06357BD71EBF6F760074E6D4 /* gl_drawpatch.cpp */, + 06357BD81EBF6F760074E6D4 /* hexlex.cpp */, + 06357BD91EBF6F760074E6D4 /* hu_inventory.cpp */, + 06357BDA1EBF6F760074E6D4 /* hu_lib.cpp */, + 06357BDB1EBF6F760074E6D4 /* hu_menu.cpp */, + 06357BDC1EBF6F760074E6D4 /* hu_msg.cpp */, + 06357BDD1EBF6F760074E6D4 /* hu_stuff.cpp */, + 06357BDE1EBF6F760074E6D4 /* m_ctrl.cpp */, + 06357BDF1EBF6F760074E6D4 /* p_inventory.cpp */, + 06357BE01EBF6F760074E6D4 /* p_saveg.cpp */, + 06357BE11EBF6F760074E6D4 /* p_saveio.cpp */, + ); + name = "Shared Sources"; + sourceTree = ""; + }; + 06357B161EBF699B0074E6D4 /* Headers */ = { + isa = PBXGroup; + children = ( + 06357B181EBF69B50074E6D4 /* dehreader_util.h */, + 06357B191EBF69B50074E6D4 /* dehreader.h */, + 06357B1A1EBF69B50074E6D4 /* importdeh.h */, + 06357B1B1EBF69B50074E6D4 /* info.h */, + 06357B1C1EBF69B50074E6D4 /* version.h */, + ); + name = Headers; + sourceTree = ""; + }; + 06357B171EBF699F0074E6D4 /* Headers */ = { + isa = PBXGroup; + children = ( + ); + name = Headers; + sourceTree = ""; + }; + 06357B3D1EBF6F5A0074E6D4 /* hud */ = { + isa = PBXGroup; + children = ( + 06357B3E1EBF6F5A0074E6D4 /* widgets */, + ); + name = hud; + path = ../apps/plugins/doom/src/hud; + sourceTree = ""; + }; + 06357B3E1EBF6F5A0074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357B3F1EBF6F5A0074E6D4 /* ammowidget.cpp */, + 06357B401EBF6F5A0074E6D4 /* armoriconwidget.cpp */, + 06357B411EBF6F5A0074E6D4 /* facewidget.cpp */, + 06357B421EBF6F5A0074E6D4 /* healthiconwidget.cpp */, + 06357B431EBF6F5A0074E6D4 /* maxammowidget.cpp */, + 06357B441EBF6F5A0074E6D4 /* weaponslotwidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357B771EBF6F750074E6D4 /* acs */ = { + isa = PBXGroup; + children = ( + 06357B781EBF6F750074E6D4 /* interpreter.cpp */, + 06357B791EBF6F750074E6D4 /* module.cpp */, + 06357B7A1EBF6F750074E6D4 /* script.cpp */, + 06357B7B1EBF6F750074E6D4 /* system.cpp */, + ); + name = acs; + path = ../apps/plugins/common/src/acs; + sourceTree = ""; + }; + 06357B7C1EBF6F750074E6D4 /* game */ = { + isa = PBXGroup; + children = ( + 06357B7D1EBF6F750074E6D4 /* g_defs.cpp */, + 06357B7E1EBF6F750074E6D4 /* g_eventsequence.cpp */, + 06357B7F1EBF6F750074E6D4 /* g_game.cpp */, + 06357B801EBF6F750074E6D4 /* g_update.cpp */, + 06357B811EBF6F750074E6D4 /* gamerules.cpp */, + 06357B821EBF6F750074E6D4 /* gamesession.cpp */, + 06357B831EBF6F750074E6D4 /* saveslots.cpp */, + ); + name = game; + path = ../apps/plugins/common/src/game; + sourceTree = ""; + }; + 06357B841EBF6F750074E6D4 /* hud */ = { + isa = PBXGroup; + children = ( + 06357B851EBF6F750074E6D4 /* automapstyle.cpp */, + 06357B861EBF6F750074E6D4 /* hudwidget.cpp */, + 06357B871EBF6F750074E6D4 /* widgets */, + ); + name = hud; + path = ../apps/plugins/common/src/hud; + sourceTree = ""; + }; + 06357B871EBF6F750074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357B881EBF6F750074E6D4 /* armorwidget.cpp */, + 06357B891EBF6F750074E6D4 /* automapwidget.cpp */, + 06357B8A1EBF6F750074E6D4 /* chainwidget.cpp */, + 06357B8B1EBF6F750074E6D4 /* chatwidget.cpp */, + 06357B8C1EBF6F750074E6D4 /* flightwidget.cpp */, + 06357B8D1EBF6F750074E6D4 /* fragswidget.cpp */, + 06357B8E1EBF6F750074E6D4 /* groupwidget.cpp */, + 06357B8F1EBF6F750074E6D4 /* healthwidget.cpp */, + 06357B901EBF6F750074E6D4 /* itemswidget.cpp */, + 06357B911EBF6F750074E6D4 /* keyslotwidget.cpp */, + 06357B921EBF6F750074E6D4 /* keyswidget.cpp */, + 06357B931EBF6F750074E6D4 /* killswidget.cpp */, + 06357B941EBF6F750074E6D4 /* playerlogwidget.cpp */, + 06357B951EBF6F750074E6D4 /* readyammoiconwidget.cpp */, + 06357B961EBF6F750074E6D4 /* readyammowidget.cpp */, + 06357B971EBF6F750074E6D4 /* readyitemwidget.cpp */, + 06357B981EBF6F750074E6D4 /* secretswidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357B991EBF6F760074E6D4 /* menu */ = { + isa = PBXGroup; + children = ( + 06357B9A1EBF6F760074E6D4 /* page.cpp */, + 06357B9B1EBF6F760074E6D4 /* widgets */, + ); + name = menu; + path = ../apps/plugins/common/src/menu; + sourceTree = ""; + }; + 06357B9B1EBF6F760074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357B9C1EBF6F760074E6D4 /* buttonwidget.cpp */, + 06357B9D1EBF6F760074E6D4 /* coloreditwidget.cpp */, + 06357B9E1EBF6F760074E6D4 /* cvarcoloreditwidget.cpp */, + 06357B9F1EBF6F760074E6D4 /* cvarinlinelistwidget.cpp */, + 06357BA01EBF6F760074E6D4 /* cvarlineeditwidget.cpp */, + 06357BA11EBF6F760074E6D4 /* cvarsliderwidget.cpp */, + 06357BA21EBF6F760074E6D4 /* cvartextualsliderwidget.cpp */, + 06357BA31EBF6F760074E6D4 /* cvartogglewidget.cpp */, + 06357BA41EBF6F760074E6D4 /* inlinelistwidget.cpp */, + 06357BA51EBF6F760074E6D4 /* inputbindingwidget.cpp */, + 06357BA61EBF6F760074E6D4 /* labelwidget.cpp */, + 06357BA71EBF6F760074E6D4 /* lineeditwidget.cpp */, + 06357BA81EBF6F760074E6D4 /* listwidget.cpp */, + 06357BA91EBF6F760074E6D4 /* mobjpreviewwidget.cpp */, + 06357BAA1EBF6F760074E6D4 /* rectwidget.cpp */, + 06357BAB1EBF6F760074E6D4 /* sliderwidget.cpp */, + 06357BAC1EBF6F760074E6D4 /* widget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357BAD1EBF6F760074E6D4 /* network */ = { + isa = PBXGroup; + children = ( + 06357BAE1EBF6F760074E6D4 /* d_net.cpp */, + 06357BAF1EBF6F760074E6D4 /* d_netcl.cpp */, + 06357BB01EBF6F760074E6D4 /* d_netsv.cpp */, + ); + name = network; + path = ../apps/plugins/common/src/network; + sourceTree = ""; + }; + 06357BB11EBF6F760074E6D4 /* world */ = { + isa = PBXGroup; + children = ( + 06357BB21EBF6F760074E6D4 /* dmu_lib.cpp */, + 06357BB31EBF6F760074E6D4 /* mapstatereader.cpp */, + 06357BB41EBF6F760074E6D4 /* mapstatewriter.cpp */, + 06357BB51EBF6F760074E6D4 /* mobj.cpp */, + 06357BB61EBF6F760074E6D4 /* p_actor.cpp */, + 06357BB71EBF6F760074E6D4 /* p_ceiling.cpp */, + 06357BB81EBF6F760074E6D4 /* p_door.cpp */, + 06357BB91EBF6F760074E6D4 /* p_floor.cpp */, + 06357BBA1EBF6F760074E6D4 /* p_map.cpp */, + 06357BBB1EBF6F760074E6D4 /* p_mapsetup.cpp */, + 06357BBC1EBF6F760074E6D4 /* p_mapspec.cpp */, + 06357BBD1EBF6F760074E6D4 /* p_plat.cpp */, + 06357BBE1EBF6F760074E6D4 /* p_scroll.cpp */, + 06357BBF1EBF6F760074E6D4 /* p_sound.cpp */, + 06357BC01EBF6F760074E6D4 /* p_start.cpp */, + 06357BC11EBF6F760074E6D4 /* p_switch.cpp */, + 06357BC21EBF6F760074E6D4 /* p_tick.cpp */, + 06357BC31EBF6F760074E6D4 /* p_xgfile.cpp */, + 06357BC41EBF6F760074E6D4 /* p_xgline.cpp */, + 06357BC51EBF6F760074E6D4 /* p_xgsave.cpp */, + 06357BC61EBF6F760074E6D4 /* p_xgsec.cpp */, + 06357BC71EBF6F760074E6D4 /* pause.cpp */, + 06357BC81EBF6F760074E6D4 /* player.cpp */, + 06357BC91EBF6F760074E6D4 /* polyobjs.cpp */, + 06357BCA1EBF6F760074E6D4 /* thingarchive.cpp */, + 06357BCB1EBF6F760074E6D4 /* thinkerinfo.cpp */, + ); + name = world; + path = ../apps/plugins/common/src/world; + sourceTree = ""; + }; + 06357D331EBF71320074E6D4 /* hud */ = { + isa = PBXGroup; + children = ( + 06357D341EBF71320074E6D4 /* widgets */, + ); + name = hud; + path = ../apps/plugins/heretic/src/hud; + sourceTree = ""; + }; + 06357D341EBF71320074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357D351EBF71320074E6D4 /* tomeofpowerwidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357DE21EBF73460074E6D4 /* hud */ = { + isa = PBXGroup; + children = ( + 06357DE31EBF73460074E6D4 /* widgets */, + ); + name = hud; + path = ../apps/plugins/hexen/src/hud; + sourceTree = ""; + }; + 06357DE31EBF73460074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357DE41EBF73460074E6D4 /* armoriconswidget.cpp */, + 06357DE51EBF73460074E6D4 /* bluemanaiconwidget.cpp */, + 06357DE61EBF73460074E6D4 /* bluemanavialwidget.cpp */, + 06357DE71EBF73460074E6D4 /* bluemanawidget.cpp */, + 06357DE81EBF73460074E6D4 /* bootswidget.cpp */, + 06357DE91EBF73460074E6D4 /* defensewidget.cpp */, + 06357DEA1EBF73460074E6D4 /* greenmanaiconwidget.cpp */, + 06357DEB1EBF73460074E6D4 /* greenmanavialwidget.cpp */, + 06357DEC1EBF73460074E6D4 /* greenmanawidget.cpp */, + 06357DED1EBF73460074E6D4 /* servantwidget.cpp */, + 06357DEE1EBF73460074E6D4 /* weaponpieceswidget.cpp */, + 06357DEF1EBF73460074E6D4 /* worldtimewidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357EEE1EBF767C0074E6D4 /* hud */ = { + isa = PBXGroup; + children = ( + 06357EEF1EBF767C0074E6D4 /* widgets */, + ); + name = hud; + path = ../apps/plugins/doom64/src/hud; + sourceTree = ""; + }; + 06357EEF1EBF767C0074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 06357EF01EBF767C0074E6D4 /* armoriconwidget.cpp */, + 06357EF11EBF767C0074E6D4 /* healthiconwidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 06357F551EBF7AE50074E6D4 /* audio */ = { + isa = PBXGroup; + children = ( + 06357F561EBF7AE50074E6D4 /* audiodriver.cpp */, + 06357F571EBF7AE50074E6D4 /* base */, + 06357F5B1EBF7AE50074E6D4 /* m_mus2midi.cpp */, + 06357F5C1EBF7AE50074E6D4 /* s_environ.cpp */, + 06357F5D1EBF7AE50074E6D4 /* sfxchannel.cpp */, + 06357F5E1EBF7AE50074E6D4 /* sys_audiod_dummy.cpp */, + 06357F5F1EBF7AE50074E6D4 /* sys_audiod_sdlmixer.cpp */, + ); + name = audio; + path = ../apps/client/src/audio; + sourceTree = ""; + }; + 06357F571EBF7AE50074E6D4 /* base */ = { + isa = PBXGroup; + children = ( + 06357F581EBF7AE50074E6D4 /* audiosystem.cpp */, + 06357F5A1EBF7AE50074E6D4 /* s_cache.cpp */, + ); + path = base; + sourceTree = ""; + }; + 06357F601EBF7AE50074E6D4 /* client */ = { + isa = PBXGroup; + children = ( + 06357F611EBF7AE50074E6D4 /* cl_frame.cpp */, + 06357F621EBF7AE50074E6D4 /* cl_infine.cpp */, + 06357F631EBF7AE50074E6D4 /* cl_main.cpp */, + 06357F641EBF7AE50074E6D4 /* cl_mobj.cpp */, + 06357F651EBF7AE50074E6D4 /* cl_player.cpp */, + 06357F661EBF7AE50074E6D4 /* cl_sound.cpp */, + 06357F671EBF7AE50074E6D4 /* cl_world.cpp */, + 06357F681EBF7AE50074E6D4 /* cledgeloop.cpp */, + 06357F691EBF7AE50074E6D4 /* clientsubsector.cpp */, + 06357F6A1EBF7AE50074E6D4 /* clplanemover.cpp */, + 06357F6B1EBF7AE50074E6D4 /* clpolymover.cpp */, + 06357F6C1EBF7AE50074E6D4 /* clskyplane.cpp */, + ); + name = client; + path = ../apps/client/src/client; + sourceTree = ""; + }; + 06357F6D1EBF7AE50074E6D4 /* gl */ = { + isa = PBXGroup; + children = ( + 06357F6E1EBF7AE50074E6D4 /* dgl_common.cpp */, + 06357F6F1EBF7AE50074E6D4 /* dgl_draw.cpp */, + 06357F701EBF7AE50074E6D4 /* gl_defer.cpp */, + 06357F711EBF7AE50074E6D4 /* gl_deferredapi.cpp */, + 06357F721EBF7AE50074E6D4 /* gl_draw.cpp */, + 06357F731EBF7AE50074E6D4 /* gl_drawvectorgraphic.cpp */, + 06357F741EBF7AE50074E6D4 /* gl_main.cpp */, + 06357F751EBF7AE50074E6D4 /* gl_tex.cpp */, + 06357F761EBF7AE50074E6D4 /* gl_texmanager.cpp */, + 06357F771EBF7AE50074E6D4 /* svg.cpp */, + 06357F781EBF7AE50074E6D4 /* sys_opengl.cpp */, + 06357F791EBF7AE50074E6D4 /* texturecontent.cpp */, + ); + name = gl; + path = ../apps/client/src/gl; + sourceTree = ""; + }; + 06357F7A1EBF7AE50074E6D4 /* misc */ = { + isa = PBXGroup; + children = ( + 06357F7B1EBF7AE50074E6D4 /* color.cpp */, + 06357F7C1EBF7AE50074E6D4 /* face.cpp */, + 06357F7D1EBF7AE50074E6D4 /* hedge.cpp */, + 06357F7E1EBF7AE50074E6D4 /* mesh.cpp */, + 06357F7F1EBF7AE50074E6D4 /* r_util.cpp */, + 06357F801EBF7AE50074E6D4 /* tab_tables.cpp */, + ); + name = misc; + path = ../apps/client/src/misc; + sourceTree = ""; + }; + 06357F811EBF7AE50074E6D4 /* network */ = { + isa = PBXGroup; + children = ( + 06357F821EBF7AE50074E6D4 /* base */, + 06357F8B1EBF7AE50074E6D4 /* net_demo.cpp */, + 06357F8C1EBF7AE50074E6D4 /* serverlink.cpp */, + 06357F8D1EBF7AE50074E6D4 /* sys_network.cpp */, + ); + name = network; + path = ../apps/client/src/network; + sourceTree = ""; + }; + 06357F821EBF7AE50074E6D4 /* base */ = { + isa = PBXGroup; + children = ( + 06357F831EBF7AE50074E6D4 /* masterserver.cpp */, + 06357F841EBF7AE50074E6D4 /* monitor.cpp */, + 06357F851EBF7AE50074E6D4 /* net_buf.cpp */, + 06357F861EBF7AE50074E6D4 /* net_event.cpp */, + 06357F871EBF7AE50074E6D4 /* net_main.cpp */, + 06357F881EBF7AE50074E6D4 /* net_msg.cpp */, + 06357F891EBF7AE50074E6D4 /* net_ping.cpp */, + ); + path = base; + sourceTree = ""; + }; + 06357F8E1EBF7AE50074E6D4 /* render */ = { + isa = PBXGroup; + children = ( + 06357F8F1EBF7AE50074E6D4 /* angleclipper.cpp */, + 06357F901EBF7AE50074E6D4 /* api_render.cpp */, + 06357F911EBF7AE50074E6D4 /* billboard.cpp */, + 06357F921EBF7AE50074E6D4 /* blockmapvisual.cpp */, + 06357F931EBF7AE50074E6D4 /* cameralensfx.cpp */, + 06357F941EBF7AE50074E6D4 /* consoleeffect.cpp */, + 06357F951EBF7AE50074E6D4 /* decoration.cpp */, + 06357F961EBF7AE50074E6D4 /* drawlist.cpp */, + 06357F971EBF7AE50074E6D4 /* drawlists.cpp */, + 06357F981EBF7AE50074E6D4 /* environ.cpp */, + 06357F991EBF7AE50074E6D4 /* fx */, + 06357F9E1EBF7AE50074E6D4 /* lightdecoration.cpp */, + 06357F9F1EBF7AE50074E6D4 /* lumobj.cpp */, + 06357FA01EBF7AE50074E6D4 /* model.cpp */, + 06357FA11EBF7AE50074E6D4 /* modelloader.cpp */, + 06357FA21EBF7AE50074E6D4 /* modelrenderer.cpp */, + 06357FA31EBF7AE50074E6D4 /* playerweaponanimator.cpp */, + 06357FA41EBF7AE50074E6D4 /* projectionlist.cpp */, + 06357FA51EBF7AE50074E6D4 /* r_draw.cpp */, + 06357FA61EBF7AE50074E6D4 /* r_main.cpp */, + 06357FA71EBF7AE50074E6D4 /* r_things.cpp */, + 06357FA81EBF7AE50074E6D4 /* rend_fakeradio.cpp */, + 06357FA91EBF7AE50074E6D4 /* rend_font.cpp */, + 06357FAA1EBF7AE50074E6D4 /* rend_halo.cpp */, + 06357FAB1EBF7AE50074E6D4 /* rend_main.cpp */, + 06357FAC1EBF7AE50074E6D4 /* rend_model.cpp */, + 06357FAD1EBF7AE50074E6D4 /* rend_particle.cpp */, + 06357FAE1EBF7AE50074E6D4 /* rendersystem.cpp */, + 06357FAF1EBF7AE50074E6D4 /* rendpoly.cpp */, + 06357FB01EBF7AE50074E6D4 /* shadervar.cpp */, + 06357FB11EBF7AE50074E6D4 /* shadowedge.cpp */, + 06357FB21EBF7AE50074E6D4 /* skydrawable.cpp */, + 06357FB31EBF7AE50074E6D4 /* skyfixedge.cpp */, + 06357FB41EBF7AE50074E6D4 /* stateanimator.cpp */, + 06357FB51EBF7AE50074E6D4 /* store.cpp */, + 06357FB61EBF7AE50074E6D4 /* trianglestripbuilder.cpp */, + 06357FB71EBF7AE50074E6D4 /* vectorlightlist.cpp */, + 06357FB81EBF7AE50074E6D4 /* viewports.cpp */, + 06357FB91EBF7AE50074E6D4 /* vissprite.cpp */, + 06357FBA1EBF7AE50074E6D4 /* vr.cpp */, + 06357FBB1EBF7AE50074E6D4 /* walledge.cpp */, + 06357FBC1EBF7AE50074E6D4 /* wallspec.cpp */, + ); + name = render; + path = ../apps/client/src/render; + sourceTree = ""; + }; + 06357F991EBF7AE50074E6D4 /* fx */ = { + isa = PBXGroup; + children = ( + 06357F9A1EBF7AE50074E6D4 /* bloom.cpp */, + 06357F9B1EBF7AE50074E6D4 /* colorfilter.cpp */, + 06357F9C1EBF7AE50074E6D4 /* lensflares.cpp */, + 06357F9D1EBF7AE50074E6D4 /* vignette.cpp */, + ); + path = fx; + sourceTree = ""; + }; + 06357FBD1EBF7AE50074E6D4 /* resource */ = { + isa = PBXGroup; + children = ( + 06357FBE1EBF7AE50074E6D4 /* abstractfont.cpp */, + 06357FBF1EBF7AE50074E6D4 /* base */, + 06357FC31EBF7AE50074E6D4 /* bitmapfont.cpp */, + 06357FC41EBF7AE50074E6D4 /* clientmaterial.cpp */, + 06357FC51EBF7AE50074E6D4 /* clientresources.cpp */, + 06357FC61EBF7AE50074E6D4 /* clienttexture.cpp */, + 06357FC71EBF7AE50074E6D4 /* compositebitmapfont.cpp */, + 06357FC81EBF7AE50074E6D4 /* fontmanifest.cpp */, + 06357FC91EBF7AE50074E6D4 /* fonts.cpp */, + 06357FCA1EBF7AE50074E6D4 /* fontscheme.cpp */, + 06357FCB1EBF7AE50074E6D4 /* framemodel.cpp */, + 06357FCC1EBF7AE50074E6D4 /* hq2x.cpp */, + 06357FCD1EBF7AE50074E6D4 /* idtech1image.cpp */, + 06357FCE1EBF7AE50074E6D4 /* image.cpp */, + 06357FCF1EBF7AE50074E6D4 /* lightmaterialdecoration.cpp */, + 06357FD01EBF7AE50074E6D4 /* materialanimator.cpp */, + 06357FD11EBF7AE50074E6D4 /* texturevariant.cpp */, + ); + name = resource; + path = ../apps/client/src/resource; + sourceTree = ""; + }; + 06357FBF1EBF7AE50074E6D4 /* base */ = { + isa = PBXGroup; + children = ( + 06357FC01EBF7AE50074E6D4 /* api_material.cpp */, + 06357FC11EBF7AE50074E6D4 /* api_resource.cpp */, + ); + path = base; + sourceTree = ""; + }; + 06357FD21EBF7AE50074E6D4 /* ui */ = { + isa = PBXGroup; + children = ( + 06357FD31EBF7AE50074E6D4 /* alertmask.cpp */, + 06357FD41EBF7AE50074E6D4 /* axisinputcontrol.cpp */, + 06357FD51EBF7AE50074E6D4 /* b_main.cpp */, + 06357FD61EBF7AE50074E6D4 /* b_util.cpp */, + 06357FD71EBF7AE50074E6D4 /* bindcontext.cpp */, + 06357FD81EBF7AE50074E6D4 /* binding.cpp */, + 06357FD91EBF7AE50074E6D4 /* busyvisual.cpp */, + 06357FDA1EBF7AE50074E6D4 /* buttoninputcontrol.cpp */, + 06357FDB1EBF7AE50074E6D4 /* clientrootwidget.cpp */, + 06357FDC1EBF7AE50074E6D4 /* clientstyle.cpp */, + 06357FDD1EBF7AE50074E6D4 /* clientwindow.cpp */, + 06357FDE1EBF7AE50074E6D4 /* clientwindowsystem.cpp */, + 06357FDF1EBF7AE50074E6D4 /* commandaction.cpp */, + 06357FE01EBF7AE50074E6D4 /* commandbinding.cpp */, + 06357FE11EBF7AE50074E6D4 /* controllerpresets.cpp */, + 06357FE21EBF7AE50074E6D4 /* dialogs */, + 06357FF51EBF7AE50074E6D4 /* editors */, + 06357FF91EBF7AE50074E6D4 /* hatinputcontrol.cpp */, + 06357FFA1EBF7AE50074E6D4 /* home */, + 063580051EBF7AE50074E6D4 /* impulsebinding.cpp */, + 063580061EBF7AE50074E6D4 /* infine */, + 0635800E1EBF7AE50074E6D4 /* inputdebug.cpp */, + 0635800F1EBF7AE50074E6D4 /* inputdevice.cpp */, + 063580101EBF7AE50074E6D4 /* inputsystem.cpp */, + 063580111EBF7AE50074E6D4 /* mouse_qt.cpp */, + 063580121EBF7AE50074E6D4 /* nativemenu.cpp */, + 063580131EBF7AE50074E6D4 /* nativeui.cpp */, + 063580141EBF7AE50074E6D4 /* postprocessing.cpp */, + 063580151EBF7AE50074E6D4 /* progress.cpp */, + 063580161EBF7AE50074E6D4 /* savelistdata.cpp */, + 063580171EBF7AE50074E6D4 /* splash.xpm */, + 063580181EBF7AE50074E6D4 /* styledlogsinkformatter.cpp */, + 063580191EBF7AE50074E6D4 /* sys_input.cpp */, + 0635801A1EBF7AE50074E6D4 /* ui_main.cpp */, + 0635801B1EBF7AE50074E6D4 /* viewcompositor.cpp */, + 0635801C1EBF7AE50074E6D4 /* widgets */, + 063580371EBF7AE50074E6D4 /* zonedebug.cpp */, + ); + name = ui; + path = ../apps/client/src/ui; + sourceTree = ""; + }; + 06357FE21EBF7AE50074E6D4 /* dialogs */ = { + isa = PBXGroup; + children = ( + 06357FE31EBF7AE50074E6D4 /* aboutdialog.cpp */, + 06357FE41EBF7AE50074E6D4 /* alertdialog.cpp */, + 06357FE51EBF7AE50074E6D4 /* audiosettingsdialog.cpp */, + 06357FE61EBF7AE50074E6D4 /* coloradjustmentdialog.cpp */, + 06357FE71EBF7AE50074E6D4 /* createprofiledialog.cpp */, + 06357FE81EBF7AE50074E6D4 /* datafilesettingsdialog.cpp */, + 06357FE91EBF7AE50074E6D4 /* inputsettingsdialog.cpp */, + 06357FEA1EBF7AE50074E6D4 /* logsettingsdialog.cpp */, + 06357FEB1EBF7AE50074E6D4 /* manualconnectiondialog.cpp */, + 06357FEC1EBF7AE50074E6D4 /* networksettingsdialog.cpp */, + 06357FED1EBF7AE50074E6D4 /* packagecompatibilitydialog.cpp */, + 06357FEE1EBF7AE50074E6D4 /* packageinfodialog.cpp */, + 06357FEF1EBF7AE50074E6D4 /* packagesdialog.cpp */, + 06357FF01EBF7AE50074E6D4 /* renderersettingsdialog.cpp */, + 06357FF11EBF7AE50074E6D4 /* serverinfodialog.cpp */, + 06357FF21EBF7AE50074E6D4 /* uisettingsdialog.cpp */, + 06357FF31EBF7AE50074E6D4 /* videosettingsdialog.cpp */, + 06357FF41EBF7AE50074E6D4 /* vrsettingsdialog.cpp */, + ); + path = dialogs; + sourceTree = ""; + }; + 06357FF51EBF7AE50074E6D4 /* editors */ = { + isa = PBXGroup; + children = ( + 06357FF61EBF7AE50074E6D4 /* modelasseteditor.cpp */, + 06357FF71EBF7AE50074E6D4 /* rendererappearanceeditor.cpp */, + 06357FF81EBF7AE50074E6D4 /* variablegroupeditor.cpp */, + ); + path = editors; + sourceTree = ""; + }; + 06357FFA1EBF7AE50074E6D4 /* home */ = { + isa = PBXGroup; + children = ( + 06357FFB1EBF7AE50074E6D4 /* columnwidget.cpp */, + 06357FFC1EBF7AE50074E6D4 /* gamecolumnwidget.cpp */, + 06357FFD1EBF7AE50074E6D4 /* gamepanelbuttonwidget.cpp */, + 06357FFE1EBF7AE50074E6D4 /* headerwidget.cpp */, + 06357FFF1EBF7AE50074E6D4 /* homewidget.cpp */, + 063580001EBF7AE50074E6D4 /* multiplayercolumnwidget.cpp */, + 063580011EBF7AE50074E6D4 /* multiplayerpanelbuttonwidget.cpp */, + 063580021EBF7AE50074E6D4 /* nogamescolumnwidget.cpp */, + 063580031EBF7AE50074E6D4 /* packagescolumnwidget.cpp */, + 063580041EBF7AE50074E6D4 /* savelistwidget.cpp */, + ); + path = home; + sourceTree = ""; + }; + 063580061EBF7AE50074E6D4 /* infine */ = { + isa = PBXGroup; + children = ( + 063580071EBF7AE50074E6D4 /* finale.cpp */, + 063580081EBF7AE50074E6D4 /* finaleanimwidget.cpp */, + 063580091EBF7AE50074E6D4 /* finaleinterpreter.cpp */, + 0635800A1EBF7AE50074E6D4 /* finalepagewidget.cpp */, + 0635800B1EBF7AE50074E6D4 /* finaletextwidget.cpp */, + 0635800C1EBF7AE50074E6D4 /* finalewidget.cpp */, + 0635800D1EBF7AE50074E6D4 /* infinesystem.cpp */, + ); + path = infine; + sourceTree = ""; + }; + 0635801C1EBF7AE50074E6D4 /* widgets */ = { + isa = PBXGroup; + children = ( + 0635801D1EBF7AE50074E6D4 /* busywidget.cpp */, + 0635801E1EBF7AE50074E6D4 /* consolecommandwidget.cpp */, + 0635801F1EBF7AE50074E6D4 /* consolewidget.cpp */, + 063580201EBF7AE50074E6D4 /* cvarchoicewidget.cpp */, + 063580211EBF7AE50074E6D4 /* cvarlineeditwidget.cpp */, + 063580221EBF7AE50074E6D4 /* cvarnativepathwidget.cpp */, + 063580231EBF7AE50074E6D4 /* cvarsliderwidget.cpp */, + 063580241EBF7AE50074E6D4 /* cvartogglewidget.cpp */, + 063580251EBF7AE50074E6D4 /* gamewidget.cpp */, + 063580261EBF7AE50074E6D4 /* homeitemwidget.cpp */, + 063580271EBF7AE50074E6D4 /* homemenuwidget.cpp */, + 063580281EBF7AE50074E6D4 /* inputbindingwidget.cpp */, + 063580291EBF7AE50074E6D4 /* keygrabberwidget.cpp */, + 0635802A1EBF7AE50074E6D4 /* mapoutlinewidget.cpp */, + 0635802B1EBF7AE50074E6D4 /* multiplayerservermenuwidget.cpp */, + 0635802C1EBF7AE50074E6D4 /* multiplayerstatuswidget.cpp */, + 0635802D1EBF7AE50074E6D4 /* packagecontentoptionswidget.cpp */, + 0635802E1EBF7AE50074E6D4 /* packagesbuttonwidget.cpp */, + 0635802F1EBF7AE50074E6D4 /* packagessidebarwidget.cpp */, + 063580301EBF7AE50074E6D4 /* packageswidget.cpp */, + 063580311EBF7AE50074E6D4 /* panelbuttonwidget.cpp */, + 063580321EBF7AE50074E6D4 /* privilegedlogwidget.cpp */, + 063580331EBF7AE50074E6D4 /* profilepickerwidget.cpp */, + 063580341EBF7AE50074E6D4 /* sidebarwidget.cpp */, + 063580351EBF7AE50074E6D4 /* taskbarwidget.cpp */, + 063580361EBF7AE50074E6D4 /* tutorialwidget.cpp */, + ); + path = widgets; + sourceTree = ""; + }; + 063580381EBF7AE50074E6D4 /* unix */ = { + isa = PBXGroup; + children = ( + 063580391EBF7AE50074E6D4 /* dd_uinit.cpp */, + 0635803A1EBF7AE50074E6D4 /* joystick.cpp */, + ); + name = unix; + path = ../apps/client/src/unix; + sourceTree = ""; + }; + 0635803B1EBF7AE50074E6D4 /* world */ = { + isa = PBXGroup; + children = ( + 0635803C1EBF7AE50074E6D4 /* base */, + 063580571EBF7AE50074E6D4 /* bsp */, + 0635805E1EBF7AE50074E6D4 /* clientmobjthinkerdata.cpp */, + 0635805F1EBF7AE50074E6D4 /* contact.cpp */, + 063580601EBF7AE50074E6D4 /* contactspreader.cpp */, + 063580611EBF7AE50074E6D4 /* generator.cpp */, + 063580621EBF7AE50074E6D4 /* mapobject.cpp */, + ); + name = world; + path = ../apps/client/src/world; + sourceTree = ""; + }; + 0635803C1EBF7AE50074E6D4 /* base */ = { + isa = PBXGroup; + children = ( + 0635803D1EBF7AE50074E6D4 /* bindings_world.cpp */, + 0635803E1EBF7AE50074E6D4 /* blockmap.cpp */, + 0635803F1EBF7AE50074E6D4 /* bspleaf.cpp */, + 063580401EBF7AE50074E6D4 /* clientserverworld.cpp */, + 063580411EBF7AE50074E6D4 /* convexsubspace.cpp */, + 063580421EBF7AE50074E6D4 /* impulseaccumulator.cpp */, + 063580431EBF7AE50074E6D4 /* interceptor.cpp */, + 063580441EBF7AE50074E6D4 /* line.cpp */, + 063580451EBF7AE50074E6D4 /* lineblockmap.cpp */, + 063580461EBF7AE50074E6D4 /* linesighttest.cpp */, + 063580471EBF7AE50074E6D4 /* map.cpp */, + 063580481EBF7AE50074E6D4 /* maputil.cpp */, + 063580491EBF7AE50074E6D4 /* p_mobj.cpp */, + 0635804A1EBF7AE50074E6D4 /* p_players.cpp */, + 0635804B1EBF7AE50074E6D4 /* p_ticker.cpp */, + 0635804C1EBF7AE50074E6D4 /* plane.cpp */, + 0635804D1EBF7AE50074E6D4 /* polyobj.cpp */, + 0635804E1EBF7AE50074E6D4 /* polyobjdata.cpp */, + 0635804F1EBF7AE50074E6D4 /* reject.cpp */, + 063580511EBF7AE50074E6D4 /* sector.cpp */, + 063580521EBF7AE50074E6D4 /* sky.cpp */, + 063580531EBF7AE50074E6D4 /* subsector.cpp */, + 063580541EBF7AE50074E6D4 /* surface.cpp */, + 063580551EBF7AE50074E6D4 /* thinkers.cpp */, + 063580561EBF7AE50074E6D4 /* vertex.cpp */, + ); + path = base; + sourceTree = ""; + }; + 063580571EBF7AE50074E6D4 /* bsp */ = { + isa = PBXGroup; + children = ( + 063580581EBF7AE50074E6D4 /* convexsubspaceproxy.cpp */, + 063580591EBF7AE50074E6D4 /* hplane.cpp */, + 0635805A1EBF7AE50074E6D4 /* linesegment.cpp */, + 0635805B1EBF7AE50074E6D4 /* partitioner.cpp */, + 0635805C1EBF7AE50074E6D4 /* partitionevaluator.cpp */, + 0635805D1EBF7AE50074E6D4 /* superblockmap.cpp */, + ); + path = bsp; + sourceTree = ""; + }; + 0635819A1EBFB9420074E6D4 /* Assimp */ = { + isa = PBXGroup; + children = ( + 0635827E1EBFBCBB0074E6D4 /* File Formats */, + 063583051EC036CC0074E6D4 /* ConvertUTF.c */, + 063583031EC036B40074E6D4 /* irrXML.cpp */, + 0635824C1EBFBB960074E6D4 /* Assimp.cpp */, + 063582C91EBFBE4B0074E6D4 /* MaterialSystem.cpp */, + 0635824E1EBFBBB30074E6D4 /* DefaultLogger.cpp */, + 063582501EBFBBCC0074E6D4 /* BaseImporter.cpp */, + 063582521EBFBBDB0074E6D4 /* BaseProcess.cpp */, + 063582541EBFBBF10074E6D4 /* PostStepRegistry.cpp */, + 063582561EBFBBFA0074E6D4 /* ImporterRegistry.cpp */, + 063582581EBFBC1C0074E6D4 /* DefaultIOStream.cpp */, + 063582591EBFBC1C0074E6D4 /* DefaultIOSystem.cpp */, + 0635825C1EBFBC2A0074E6D4 /* Importer.cpp */, + 0635825E1EBFBC8D0074E6D4 /* Bitmap.cpp */, + 0635825F1EBFBC8D0074E6D4 /* RemoveComments.cpp */, + 063582601EBFBC8D0074E6D4 /* SceneCombiner.cpp */, + 063582611EBFBC8D0074E6D4 /* ScenePreprocessor.cpp */, + 063582621EBFBC8D0074E6D4 /* SGSpatialSort.cpp */, + 063582631EBFBC8D0074E6D4 /* SkeletonMeshBuilder.cpp */, + 063582641EBFBC8D0074E6D4 /* SpatialSort.cpp */, + 063582651EBFBC8D0074E6D4 /* SplitByBoneCountProcess.cpp */, + 063582661EBFBC8D0074E6D4 /* StandardShapes.cpp */, + 063582671EBFBC8D0074E6D4 /* Subdivision.cpp */, + 063582681EBFBC8D0074E6D4 /* TargetAnimation.cpp */, + 063582691EBFBC8D0074E6D4 /* Version.cpp */, + 0635826A1EBFBC8D0074E6D4 /* VertexTriangleAdjacency.cpp */, + 063582FB1EBFBFCA0074E6D4 /* CalcTangentsProcess.cpp */, + 063582CB1EBFBF560074E6D4 /* ComputeUVMappingProcess.cpp */, + 063582CC1EBFBF560074E6D4 /* ConvertToLHProcess.cpp */, + 063582CD1EBFBF560074E6D4 /* DeboneProcess.cpp */, + 063582CE1EBFBF560074E6D4 /* FindDegenerates.cpp */, + 063582CF1EBFBF560074E6D4 /* FindInstancesProcess.cpp */, + 063582D01EBFBF560074E6D4 /* FindInvalidDataProcess.cpp */, + 063582D11EBFBF560074E6D4 /* FixNormalsStep.cpp */, + 063582D91EBFBFB80074E6D4 /* GenFaceNormalsProcess.cpp */, + 063582DA1EBFBFB80074E6D4 /* GenVertexNormalsProcess.cpp */, + 063582DB1EBFBFB80074E6D4 /* ImproveCacheLocality.cpp */, + 063582DC1EBFBFB80074E6D4 /* JoinVerticesProcess.cpp */, + 063582DD1EBFBFB80074E6D4 /* LimitBoneWeightsProcess.cpp */, + 063582DE1EBFBFB80074E6D4 /* MakeVerboseFormat.cpp */, + 063582DF1EBFBFB80074E6D4 /* OptimizeGraph.cpp */, + 063582E01EBFBFB80074E6D4 /* OptimizeMeshes.cpp */, + 063582E11EBFBFB80074E6D4 /* PretransformVertices.cpp */, + 063582E21EBFBFB80074E6D4 /* ProcessHelper.cpp */, + 063582E31EBFBFB80074E6D4 /* RemoveRedundantMaterials.cpp */, + 063582E41EBFBFB80074E6D4 /* RemoveVCProcess.cpp */, + 063582E51EBFBFB80074E6D4 /* SortByPTypeProcess.cpp */, + 063582E61EBFBFB80074E6D4 /* SplitLargeMeshes.cpp */, + 063582E71EBFBFB80074E6D4 /* TextureTransform.cpp */, + 063582E81EBFBFB80074E6D4 /* TriangulateProcess.cpp */, + 063582E91EBFBFB80074E6D4 /* ValidateDataStructure.cpp */, + 063582FD1EBFC03B0074E6D4 /* StepExporter.cpp */, + 063582FF1EBFC0510074E6D4 /* Exporter.cpp */, + 063583011EBFC0670074E6D4 /* AssimpCExport.cpp */, + ); + name = Assimp; + sourceTree = ""; + }; + 0635827E1EBFBCBB0074E6D4 /* File Formats */ = { + isa = PBXGroup; + children = ( + 063582781EBFBCB50074E6D4 /* 3DSConverter.cpp */, + 063582791EBFBCB50074E6D4 /* 3DSExporter.cpp */, + 0635827A1EBFBCB50074E6D4 /* 3DSLoader.cpp */, + 063582991EBFBD4D0074E6D4 /* BlenderBMesh.cpp */, + 0635829A1EBFBD4D0074E6D4 /* BlenderDNA.cpp */, + 0635829B1EBFBD4D0074E6D4 /* BlenderLoader.cpp */, + 0635829C1EBFBD4D0074E6D4 /* BlenderModifier.cpp */, + 0635829D1EBFBD4D0074E6D4 /* BlenderScene.cpp */, + 0635829E1EBFBD4D0074E6D4 /* BlenderTessellator.cpp */, + 0635827F1EBFBCE10074E6D4 /* ColladaExporter.cpp */, + 063582801EBFBCE10074E6D4 /* ColladaLoader.cpp */, + 063582811EBFBCE10074E6D4 /* ColladaParser.cpp */, + 063582A51EBFBD700074E6D4 /* FBXAnimation.cpp */, + 063582A61EBFBD700074E6D4 /* FBXBinaryTokenizer.cpp */, + 063582A71EBFBD700074E6D4 /* FBXConverter.cpp */, + 063582A81EBFBD700074E6D4 /* FBXDeformer.cpp */, + 063582A91EBFBD700074E6D4 /* FBXDocument.cpp */, + 063582AA1EBFBD700074E6D4 /* FBXDocumentUtil.cpp */, + 063582AB1EBFBD700074E6D4 /* FBXImporter.cpp */, + 063582AC1EBFBD700074E6D4 /* FBXMaterial.cpp */, + 063582AD1EBFBD700074E6D4 /* FBXMeshGeometry.cpp */, + 063582AE1EBFBD700074E6D4 /* FBXModel.cpp */, + 063582AF1EBFBD700074E6D4 /* FBXNodeAttribute.cpp */, + 063582B01EBFBD700074E6D4 /* FBXParser.cpp */, + 063582B11EBFBD700074E6D4 /* FBXProperties.cpp */, + 063582B21EBFBD700074E6D4 /* FBXTokenizer.cpp */, + 063582B31EBFBD700074E6D4 /* FBXUtil.cpp */, + 063582C31EBFBD860074E6D4 /* IRRLoader.cpp */, + 063582C41EBFBD860074E6D4 /* IRRMeshLoader.cpp */, + 063582C51EBFBD860074E6D4 /* IRRShared.cpp */, + 063582851EBFBD0C0074E6D4 /* MD2Loader.cpp */, + 063582861EBFBD0C0074E6D4 /* MD3Loader.cpp */, + 063582871EBFBD0C0074E6D4 /* MD5Loader.cpp */, + 063582881EBFBD0C0074E6D4 /* MD5Parser.cpp */, + 0635828D1EBFBD1D0074E6D4 /* MDLLoader.cpp */, + 0635828E1EBFBD1D0074E6D4 /* MDLMaterialLoader.cpp */, + 063582911EBFBD2C0074E6D4 /* ObjExporter.cpp */, + 063582921EBFBD2C0074E6D4 /* ObjFileImporter.cpp */, + 063582931EBFBD2C0074E6D4 /* ObjFileMtlImporter.cpp */, + 063582941EBFBD2C0074E6D4 /* ObjFileParser.cpp */, + ); + name = "File Formats"; + sourceTree = ""; + }; + 063583261EC4E5E80074E6D4 /* User Interface */ = { + isa = PBXGroup; + children = ( + 068610761EBF01F700180814 /* LaunchScreen.storyboard */, + 063583251EC4E5B80074E6D4 /* client.qrc */, + 063583271EC4E6040074E6D4 /* main.qml */, + ); + name = "User Interface"; + sourceTree = ""; + }; + 065548151EC8BB3E0000E33E /* Headers */ = { + isa = PBXGroup; + children = ( + 065548161EC8BB670000E33E /* dialogs */, + 0655481A1EC8BB670000E33E /* framework */, + 065548401EC8BB670000E33E /* ui */, + 0655484E1EC8BB670000E33E /* vr */, + 065548511EC8BB670000E33E /* widgets */, + 065548751EC8BB670000E33E /* libappfw.h */, + ); + name = Headers; + sourceTree = ""; + }; + 065548161EC8BB670000E33E /* dialogs */ = { + isa = PBXGroup; + children = ( + 065548171EC8BB670000E33E /* directorylistdialog.h */, + 065548181EC8BB670000E33E /* inputdialog.h */, + 065548191EC8BB670000E33E /* messagedialog.h */, + ); + name = dialogs; + path = ../sdk/libappfw/include/de/dialogs; + sourceTree = ""; + }; + 0655481A1EC8BB670000E33E /* framework */ = { + isa = PBXGroup; + children = ( + 0655481B1EC8BB670000E33E /* actionitem.h */, + 0655481C1EC8BB670000E33E /* atlasproceduralimage.h */, + 0655481D1EC8BB670000E33E /* baseguiapp.h */, + 0655481E1EC8BB670000E33E /* basewindow.h */, + 0655481F1EC8BB670000E33E /* callbackaction.h */, + 065548201EC8BB670000E33E /* childwidgetorganizer.h */, + 065548211EC8BB670000E33E /* data.h */, + 065548221EC8BB670000E33E /* dialogcontentstylist.h */, + 065548231EC8BB670000E33E /* filtereddata.h */, + 065548241EC8BB670000E33E /* fontlinewrapping.h */, + 065548251EC8BB670000E33E /* gltextcomposer.h */, + 065548261EC8BB670000E33E /* gridlayout.h */, + 065548271EC8BB670000E33E /* guirootwidget.h */, + 065548281EC8BB670000E33E /* guiwidget.h */, + 065548291EC8BB670000E33E /* guiwidgetprivate.h */, + 0655482A1EC8BB670000E33E /* imageitem.h */, + 0655482B1EC8BB670000E33E /* ipersistent.h */, + 0655482C1EC8BB670000E33E /* item.h */, + 0655482D1EC8BB670000E33E /* listdata.h */, + 0655482E1EC8BB670000E33E /* margins.h */, + 0655482F1EC8BB670000E33E /* painter.h */, + 065548301EC8BB670000E33E /* persistentstate.h */, + 065548311EC8BB670000E33E /* proceduralimage.h */, + 065548321EC8BB670000E33E /* sequentiallayout.h */, + 065548331EC8BB670000E33E /* signalaction.h */, + 065548341EC8BB670000E33E /* style.h */, + 065548351EC8BB670000E33E /* styleproceduralimage.h */, + 065548361EC8BB670000E33E /* stylist.h */, + 065548371EC8BB670000E33E /* submenuitem.h */, + 065548381EC8BB670000E33E /* subwidgetitem.h */, + 065548391EC8BB670000E33E /* textdrawable.h */, + 0655483A1EC8BB670000E33E /* untrapper.h */, + 0655483B1EC8BB670000E33E /* variabletoggleitem.h */, + 0655483C1EC8BB670000E33E /* variantactionitem.h */, + 0655483D1EC8BB670000E33E /* vrwindowtransform.h */, + 0655483E1EC8BB670000E33E /* windowsystem.h */, + 0655483F1EC8BB670000E33E /* windowtransform.h */, + ); + name = framework; + path = ../sdk/libappfw/include/de/framework; + sourceTree = ""; + }; + 065548401EC8BB670000E33E /* ui */ = { + isa = PBXGroup; + children = ( + 065548411EC8BB670000E33E /* ActionItem */, + 065548421EC8BB670000E33E /* Data */, + 065548431EC8BB670000E33E /* defs.h */, + 065548441EC8BB670000E33E /* FilteredData */, + 065548451EC8BB670000E33E /* ImageItem */, + 065548461EC8BB670000E33E /* Item */, + 065548471EC8BB670000E33E /* ListData */, + 065548481EC8BB670000E33E /* Margins */, + 065548491EC8BB670000E33E /* Stylist */, + 0655484A1EC8BB670000E33E /* SubmenuItem */, + 0655484B1EC8BB670000E33E /* SubwidgetItem */, + 0655484C1EC8BB670000E33E /* VariableToggleItem */, + 0655484D1EC8BB670000E33E /* VariantActionItem */, + ); + name = ui; + path = ../sdk/libappfw/include/de/ui; + sourceTree = ""; + }; + 0655484E1EC8BB670000E33E /* vr */ = { + isa = PBXGroup; + children = ( + 0655484F1EC8BB670000E33E /* oculusrift.h */, + 065548501EC8BB670000E33E /* vrconfig.h */, + ); + name = vr; + path = ../sdk/libappfw/include/de/vr; + sourceTree = ""; + }; + 065548511EC8BB670000E33E /* widgets */ = { + isa = PBXGroup; + children = ( + 065548521EC8BB670000E33E /* auxbuttonwidget.h */, + 065548531EC8BB670000E33E /* blurwidget.h */, + 065548541EC8BB670000E33E /* buttonwidget.h */, + 065548551EC8BB670000E33E /* choicewidget.h */, + 065548561EC8BB670000E33E /* commandwidget.h */, + 065548571EC8BB670000E33E /* compositorwidget.h */, + 065548581EC8BB670000E33E /* dialogwidget.h */, + 065548591EC8BB670000E33E /* directoryarraywidget.h */, + 0655485A1EC8BB670000E33E /* documentpopupwidget.h */, + 0655485B1EC8BB670000E33E /* documentwidget.h */, + 0655485C1EC8BB670000E33E /* fadetoblackwidget.h */, + 0655485D1EC8BB670000E33E /* focuswidget.h */, + 0655485E1EC8BB670000E33E /* foldpanelwidget.h */, + 0655485F1EC8BB670000E33E /* gridpopupwidget.h */, + 065548601EC8BB670000E33E /* labelwidget.h */, + 065548611EC8BB670000E33E /* lineeditwidget.h */, + 065548621EC8BB670000E33E /* logwidget.h */, + 065548631EC8BB670000E33E /* menuwidget.h */, + 065548641EC8BB670000E33E /* notificationareawidget.h */, + 065548651EC8BB670000E33E /* panelwidget.h */, + 065548661EC8BB670000E33E /* popupbuttonwidget.h */, + 065548671EC8BB670000E33E /* popupmenuwidget.h */, + 065548681EC8BB670000E33E /* popupwidget.h */, + 065548691EC8BB670000E33E /* progresswidget.h */, + 0655486A1EC8BB670000E33E /* relaywidget.h */, + 0655486B1EC8BB670000E33E /* scriptcommandwidget.h */, + 0655486C1EC8BB670000E33E /* scrollareawidget.h */, + 0655486D1EC8BB670000E33E /* sliderwidget.h */, + 0655486E1EC8BB670000E33E /* tabwidget.h */, + 0655486F1EC8BB670000E33E /* togglewidget.h */, + 065548701EC8BB670000E33E /* variablearraywidget.h */, + 065548711EC8BB670000E33E /* variablechoicewidget.h */, + 065548721EC8BB670000E33E /* variablelineeditwidget.h */, + 065548731EC8BB670000E33E /* variablesliderwidget.h */, + 065548741EC8BB670000E33E /* variabletogglewidget.h */, + ); + name = widgets; + path = ../sdk/libappfw/include/de/widgets; + sourceTree = ""; + }; + 067AD92C1EBF151100B808B2 /* concurrency */ = { + isa = PBXGroup; + children = ( + 067AD92D1EBF151100B808B2 /* guard.cpp */, + 067AD92E1EBF151100B808B2 /* lockable.cpp */, + 067AD92F1EBF151100B808B2 /* readwritelockable.cpp */, + 067AD9301EBF151100B808B2 /* task.cpp */, + 067AD9311EBF151100B808B2 /* taskpool.cpp */, + 067AD9321EBF151100B808B2 /* waitable.cpp */, + ); + name = concurrency; + path = ../sdk/libcore/src/concurrency; + sourceTree = ""; + }; + 067AD9331EBF151100B808B2 /* core */ = { + isa = PBXGroup; + children = ( + 067AD9341EBF151100B808B2 /* app.cpp */, + 067AD9351EBF151100B808B2 /* asset.cpp */, + 067AD9361EBF151100B808B2 /* callbacktimer.cpp */, + 067AD9371EBF151100B808B2 /* callbacktimer.h */, + 067AD9381EBF151100B808B2 /* clock.cpp */, + 067AD9391EBF151100B808B2 /* commandline.cpp */, + 067AD93A1EBF151100B808B2 /* config.cpp */, + 067AD93B1EBF151100B808B2 /* debuglogsink.cpp */, + 067AD93C1EBF151100B808B2 /* filelogsink.cpp */, + 067AD93D1EBF151100B808B2 /* garbage.cpp */, + 067AD93E1EBF151100B808B2 /* highperformancetimer.cpp */, + 067AD93F1EBF151100B808B2 /* id.cpp */, + 067AD9401EBF151100B808B2 /* library.cpp */, + 067AD9411EBF151100B808B2 /* log.cpp */, + 067AD9421EBF151100B808B2 /* logbuffer.cpp */, + 067AD9431EBF151100B808B2 /* logfilter.cpp */, + 067AD9441EBF151100B808B2 /* logsink.cpp */, + 067AD9451EBF151100B808B2 /* logtextstyle.h */, + 067AD9461EBF151100B808B2 /* loop.cpp */, + 067AD9471EBF151100B808B2 /* memorylogsink.cpp */, + 067AD9481EBF151100B808B2 /* monospacelogsinkformatter.cpp */, + 067AD9491EBF151100B808B2 /* system.cpp */, + 067AD94A1EBF151100B808B2 /* textapp.cpp */, + 067AD94B1EBF151100B808B2 /* textstreamlogsink.cpp */, + 067AD94C1EBF151100B808B2 /* unixinfo.cpp */, + ); + name = core; + path = ../sdk/libcore/src/core; + sourceTree = ""; + }; + 067AD94D1EBF151100B808B2 /* data */ = { + isa = PBXGroup; + children = ( + 067AD94E1EBF151100B808B2 /* animationvalue.cpp */, + 067AD94F1EBF151100B808B2 /* archive.cpp */, + 067AD9501EBF151100B808B2 /* arrayvalue.cpp */, + 067AD9511EBF151100B808B2 /* bank.cpp */, + 067AD9521EBF151100B808B2 /* bitfield.cpp */, + 067AD9531EBF151100B808B2 /* bitfield_elements.cpp */, + 067AD9541EBF151100B808B2 /* block.cpp */, + 067AD9551EBF151100B808B2 /* blockvalue.cpp */, + 067AD9561EBF151100B808B2 /* byteorder.cpp */, + 067AD9571EBF151100B808B2 /* byterefarray.cpp */, + 067AD9581EBF151100B808B2 /* bytesubarray.cpp */, + 067AD9591EBF151100B808B2 /* counted.cpp */, + 067AD95A1EBF151100B808B2 /* date.cpp */, + 067AD95B1EBF151100B808B2 /* deletable.cpp */, + 067AD95C1EBF151100B808B2 /* dictionaryvalue.cpp */, + 067AD95D1EBF151100B808B2 /* escapeparser.cpp */, + 067AD95E1EBF151100B808B2 /* fixedbytearray.cpp */, + 067AD95F1EBF151100B808B2 /* huffman.cpp */, + 067AD9601EBF151100B808B2 /* info.cpp */, + 067AD9611EBF151100B808B2 /* infobank.cpp */, + 067AD9621EBF151100B808B2 /* json.cpp */, + 067AD9631EBF151100B808B2 /* nativepointervalue.cpp */, + 067AD9641EBF151100B808B2 /* nonevalue.cpp */, + 067AD9651EBF151100B808B2 /* numbervalue.cpp */, + 067AD9661EBF151100B808B2 /* observers.cpp */, + 067AD9671EBF151100B808B2 /* path.cpp */, + 067AD9681EBF151100B808B2 /* pathtree.cpp */, + 067AD9691EBF151100B808B2 /* pathtreenode.cpp */, + 067AD96A1EBF151100B808B2 /* pointerset.cpp */, + 067AD96B1EBF151100B808B2 /* profiles.cpp */, + 067AD96C1EBF151100B808B2 /* reader.cpp */, + 067AD96D1EBF151100B808B2 /* record.cpp */, + 067AD96E1EBF151100B808B2 /* recordaccessor.cpp */, + 067AD96F1EBF151100B808B2 /* recordvalue.cpp */, + 067AD9701EBF151100B808B2 /* refuge.cpp */, + 067AD9711EBF151100B808B2 /* refvalue.cpp */, + 067AD9721EBF151100B808B2 /* sourcelinetable.cpp */, + 067AD9731EBF151100B808B2 /* string.cpp */, + 067AD9741EBF151100B808B2 /* stringpool.cpp */, + 067AD9751EBF151100B808B2 /* textvalue.cpp */, + 067AD9761EBF151100B808B2 /* time.cpp */, + 067AD9771EBF151100B808B2 /* timevalue.cpp */, + 067AD9781EBF151100B808B2 /* value.cpp */, + 067AD9791EBF151100B808B2 /* variable.cpp */, + 067AD97A1EBF151100B808B2 /* writer.cpp */, + 067AD97B1EBF151100B808B2 /* ziparchive.cpp */, + ); + name = data; + path = ../sdk/libcore/src/data; + sourceTree = ""; + }; + 067AD97D1EBF151100B808B2 /* filesys */ = { + isa = PBXGroup; + children = ( + 067AD97E1EBF151100B808B2 /* archiveentryfile.cpp */, + 067AD97F1EBF151100B808B2 /* archivefeed.cpp */, + 067AD9801EBF151100B808B2 /* archivefolder.cpp */, + 067AD9811EBF151100B808B2 /* assetobserver.cpp */, + 067AD9821EBF151100B808B2 /* bytearrayfile.cpp */, + 067AD9831EBF151100B808B2 /* directoryfeed.cpp */, + 067AD9841EBF151100B808B2 /* feed.cpp */, + 067AD9851EBF151100B808B2 /* file.cpp */, + 067AD9861EBF151100B808B2 /* fileindex.cpp */, + 067AD9871EBF151100B808B2 /* filesystem.cpp */, + 067AD9881EBF151100B808B2 /* folder.cpp */, + 067AD9891EBF151100B808B2 /* libraryfile.cpp */, + 067AD98A1EBF151100B808B2 /* linkfile.cpp */, + 067AD98B1EBF151100B808B2 /* metadatabank.cpp */, + 067AD98C1EBF151100B808B2 /* nativefile.cpp */, + 067AD98D1EBF151100B808B2 /* nativepath.cpp */, + 067AD98E1EBF151100B808B2 /* node.cpp */, + 067AD98F1EBF151100B808B2 /* package.cpp */, + 067AD9901EBF151100B808B2 /* packagefeed.cpp */, + 067AD9911EBF151100B808B2 /* packageloader.cpp */, + 067AD9921EBF151100B808B2 /* staticlibraryfeed.cpp */, + ); + name = filesys; + path = ../sdk/libcore/src/filesys; + sourceTree = ""; + }; + 067AD9951EBF151100B808B2 /* net */ = { + isa = PBXGroup; + children = ( + 067AD9961EBF151100B808B2 /* address.cpp */, + 067AD9971EBF151100B808B2 /* beacon.cpp */, + 067AD9981EBF151100B808B2 /* blockpacket.cpp */, + 067AD9991EBF151100B808B2 /* identifiedpacket.cpp */, + 067AD99A1EBF151100B808B2 /* listensocket.cpp */, + 067AD99B1EBF151100B808B2 /* message.cpp */, + 067AD99C1EBF151100B808B2 /* networkinterfaces.cpp */, + 067AD99D1EBF151100B808B2 /* networkinterfaces.h */, + 067AD99E1EBF151100B808B2 /* packet.cpp */, + 067AD99F1EBF151100B808B2 /* protocol.cpp */, + 067AD9A01EBF151100B808B2 /* recordpacket.cpp */, + 067AD9A11EBF151100B808B2 /* socket.cpp */, + 067AD9A21EBF151100B808B2 /* transmitter.cpp */, + ); + name = net; + path = ../sdk/libcore/src/net; + sourceTree = ""; + }; + 067AD9A41EBF151100B808B2 /* scriptsys */ = { + isa = PBXGroup; + children = ( + 067AD9A51EBF151100B808B2 /* arrayexpression.cpp */, + 067AD9A61EBF151100B808B2 /* assignstatement.cpp */, + 067AD9A71EBF151100B808B2 /* bindings_core.cpp */, + 067AD9A81EBF151100B808B2 /* bindings_core.h */, + 067AD9A91EBF151100B808B2 /* bindings_math.cpp */, + 067AD9AA1EBF151100B808B2 /* bindings_math.h */, + 067AD9AB1EBF151100B808B2 /* builtinexpression.cpp */, + 067AD9AC1EBF151100B808B2 /* catchstatement.cpp */, + 067AD9AD1EBF151100B808B2 /* compound.cpp */, + 067AD9AE1EBF151100B808B2 /* constantexpression.cpp */, + 067AD9AF1EBF151100B808B2 /* context.cpp */, + 067AD9B01EBF151100B808B2 /* deletestatement.cpp */, + 067AD9B11EBF151100B808B2 /* dictionaryexpression.cpp */, + 067AD9B21EBF151100B808B2 /* evaluator.cpp */, + 067AD9B31EBF151100B808B2 /* expression.cpp */, + 067AD9B41EBF151100B808B2 /* expressionstatement.cpp */, + 067AD9B51EBF151100B808B2 /* flowstatement.cpp */, + 067AD9B61EBF151100B808B2 /* forstatement.cpp */, + 067AD9B71EBF151100B808B2 /* function.cpp */, + 067AD9B81EBF151100B808B2 /* functionstatement.cpp */, + 067AD9B91EBF151100B808B2 /* functionvalue.cpp */, + 067AD9BA1EBF151100B808B2 /* ifstatement.cpp */, + 067AD9BB1EBF151100B808B2 /* lex.cpp */, + 067AD9BC1EBF151100B808B2 /* module.cpp */, + 067AD9BD1EBF151100B808B2 /* nameexpression.cpp */, + 067AD9BE1EBF151100B808B2 /* operator.cpp */, + 067AD9BF1EBF151100B808B2 /* operatorexpression.cpp */, + 067AD9C01EBF151100B808B2 /* parser.cpp */, + 067AD9C11EBF151100B808B2 /* printstatement.cpp */, + 067AD9C21EBF151100B808B2 /* process.cpp */, + 067AD9C31EBF151100B808B2 /* scheduler.cpp */, + 067AD9C41EBF151100B808B2 /* scopestatement.cpp */, + 067AD9C51EBF151100B808B2 /* script.cpp */, + 067AD9C61EBF151100B808B2 /* scriptedinfo.cpp */, + 067AD9C71EBF151100B808B2 /* scriptlex.cpp */, + 067AD9C81EBF151100B808B2 /* scriptsystem.cpp */, + 067AD9C91EBF151100B808B2 /* statement.cpp */, + 067AD9CA1EBF151100B808B2 /* tokenbuffer.cpp */, + 067AD9CB1EBF151100B808B2 /* tokenrange.cpp */, + 067AD9CC1EBF151100B808B2 /* trystatement.cpp */, + 067AD9CD1EBF151100B808B2 /* whilestatement.cpp */, + ); + name = scriptsys; + path = ../sdk/libcore/src/scriptsys; + sourceTree = ""; + }; + 067AD9CF1EBF151100B808B2 /* widgets */ = { + isa = PBXGroup; + children = ( + 067AD9D01EBF151100B808B2 /* action.cpp */, + 067AD9D11EBF151100B808B2 /* animation.cpp */, + 067AD9D21EBF151100B808B2 /* animationrule.cpp */, + 067AD9D31EBF151100B808B2 /* constantrule.cpp */, + 067AD9D41EBF151100B808B2 /* indirectrule.cpp */, + 067AD9D51EBF151100B808B2 /* operatorrule.cpp */, + 067AD9D61EBF151100B808B2 /* rootwidget.cpp */, + 067AD9D71EBF151100B808B2 /* rule.cpp */, + 067AD9D81EBF151100B808B2 /* rulebank.cpp */, + 067AD9D91EBF151100B808B2 /* rulerectangle.cpp */, + 067AD9DA1EBF151100B808B2 /* widget.cpp */, + ); + name = widgets; + path = ../sdk/libcore/src/widgets; + sourceTree = ""; + }; + 067ADA981EBF16B600B808B2 /* core */ = { + isa = PBXGroup; + children = ( + 067ADA991EBF16B600B808B2 /* app.h */, + 067ADA9A1EBF16B600B808B2 /* asset.h */, + 067ADA9B1EBF16B600B808B2 /* clock.h */, + 067ADA9C1EBF16B600B808B2 /* commandline.h */, + 067ADA9D1EBF16B600B808B2 /* config.h */, + 067ADA9E1EBF16B600B808B2 /* debuglogsink.h */, + 067ADA9F1EBF16B600B808B2 /* event.h */, + 067ADAA01EBF16B600B808B2 /* filelogsink.h */, + 067ADAA11EBF16B600B808B2 /* garbage.h */, + 067ADAA21EBF16B600B808B2 /* highperformancetimer.h */, + 067ADAA31EBF16B600B808B2 /* id.h */, + 067ADAA41EBF16B600B808B2 /* library.h */, + 067ADAA51EBF16B600B808B2 /* log.h */, + 067ADAA61EBF16B600B808B2 /* logbuffer.h */, + 067ADAA71EBF16B600B808B2 /* logfilter.h */, + 067ADAA81EBF16B600B808B2 /* logsink.h */, + 067ADAA91EBF16B600B808B2 /* loop.h */, + 067ADAAA1EBF16B600B808B2 /* matrix.h */, + 067ADAAB1EBF16B600B808B2 /* memorylogsink.h */, + 067ADAAC1EBF16B600B808B2 /* monospacelogsinkformatter.h */, + 067ADAAD1EBF16B600B808B2 /* range.h */, + 067ADAAE1EBF16B600B808B2 /* rectangle.h */, + 067ADAAF1EBF16B600B808B2 /* system.h */, + 067ADAB01EBF16B600B808B2 /* textapp.h */, + 067ADAB11EBF16B600B808B2 /* textstreamlogsink.h */, + 067ADAB21EBF16B600B808B2 /* unixinfo.h */, + 067ADAB31EBF16B600B808B2 /* vector.h */, + 067ADAB41EBF16B600B808B2 /* version.h */, + ); + name = core; + path = ../sdk/libcore/include/de/core; + sourceTree = ""; + }; + 067ADAB51EBF16B600B808B2 /* data */ = { + isa = PBXGroup; + children = ( + 067ADAB61EBF16B600B808B2 /* animationvalue.h */, + 067ADAB71EBF16B600B808B2 /* archive.h */, + 067ADAB81EBF16B600B808B2 /* arrayvalue.h */, + 067ADAB91EBF16B600B808B2 /* bank.h */, + 067ADABA1EBF16B600B808B2 /* binarytree.h */, + 067ADABB1EBF16B600B808B2 /* bitfield.h */, + 067ADABC1EBF16B600B808B2 /* block.h */, + 067ADABD1EBF16B600B808B2 /* blockvalue.h */, + 067ADABE1EBF16B600B808B2 /* byteorder.h */, + 067ADABF1EBF16B600B808B2 /* byterefarray.h */, + 067ADAC01EBF16B600B808B2 /* bytesubarray.h */, + 067ADAC11EBF16B600B808B2 /* compiledrecord.h */, + 067ADAC21EBF16B600B808B2 /* counted.h */, + 067ADAC31EBF16B600B808B2 /* date.h */, + 067ADAC41EBF16B600B808B2 /* deletable.h */, + 067ADAC51EBF16B600B808B2 /* dictionaryvalue.h */, + 067ADAC61EBF16B600B808B2 /* escapeparser.h */, + 067ADAC71EBF16B600B808B2 /* fifo.h */, + 067ADAC81EBF16B600B808B2 /* fixedbytearray.h */, + 067ADAC91EBF16B600B808B2 /* huffman.h */, + 067ADACA1EBF16B600B808B2 /* iblock.h */, + 067ADACB1EBF16B600B808B2 /* ibytearray.h */, + 067ADACC1EBF16B600B808B2 /* iiostream.h */, + 067ADACD1EBF16B600B808B2 /* iistream.h */, + 067ADACE1EBF16B600B808B2 /* info.h */, + 067ADACF1EBF16B600B808B2 /* infobank.h */, + 067ADAD01EBF16B600B808B2 /* iostream.h */, + 067ADAD11EBF16B600B808B2 /* ireadable.h */, + 067ADAD21EBF16B600B808B2 /* iserializable.h */, + 067ADAD31EBF16B600B808B2 /* iwritable.h */, + 067ADAD41EBF16B600B808B2 /* json.h */, + 067ADAD51EBF16B600B808B2 /* nativepointervalue.h */, + 067ADAD61EBF16B600B808B2 /* nonevalue.h */, + 067ADAD71EBF16B600B808B2 /* numbervalue.h */, + 067ADAD81EBF16B600B808B2 /* observers.h */, + 067ADAD91EBF16B600B808B2 /* partition.h */, + 067ADADA1EBF16B600B808B2 /* path.h */, + 067ADADB1EBF16B600B808B2 /* pathtree.h */, + 067ADADC1EBF16B600B808B2 /* pointerset.h */, + 067ADADD1EBF16B600B808B2 /* profiles.h */, + 067ADADE1EBF16B600B808B2 /* property.h */, + 067ADADF1EBF16B600B808B2 /* reader.h */, + 067ADAE01EBF16B600B808B2 /* record.h */, + 067ADAE11EBF16B600B808B2 /* recordaccessor.h */, + 067ADAE21EBF16B600B808B2 /* recordvalue.h */, + 067ADAE31EBF16B600B808B2 /* refuge.h */, + 067ADAE41EBF16B600B808B2 /* refvalue.h */, + 067ADAE51EBF16B600B808B2 /* shared.h */, + 067ADAE61EBF16B600B808B2 /* sourcelinetable.h */, + 067ADAE71EBF16B600B808B2 /* string.h */, + 067ADAE81EBF16B600B808B2 /* stringpool.h */, + 067ADAE91EBF16B600B808B2 /* textvalue.h */, + 067ADAEA1EBF16B600B808B2 /* time.h */, + 067ADAEB1EBF16B600B808B2 /* timevalue.h */, + 067ADAEC1EBF16B600B808B2 /* value.h */, + 067ADAED1EBF16B600B808B2 /* variable.h */, + 067ADAEE1EBF16B600B808B2 /* waitablefifo.h */, + 067ADAEF1EBF16B600B808B2 /* writer.h */, + 067ADAF01EBF16B600B808B2 /* zeroed.h */, + 067ADAF11EBF16B600B808B2 /* ziparchive.h */, + ); + name = data; + path = ../sdk/libcore/include/de/data; + sourceTree = ""; + }; + 067ADAF31EBF16B600B808B2 /* filesys */ = { + isa = PBXGroup; + children = ( + 067ADAF41EBF16B600B808B2 /* archiveentryfile.h */, + 067ADAF51EBF16B600B808B2 /* archivefeed.h */, + 067ADAF61EBF16B600B808B2 /* archivefolder.h */, + 067ADAF71EBF16B600B808B2 /* AssetObserver */, + 067ADAF81EBF16B600B808B2 /* assetobserver.h */, + 067ADAF91EBF16B600B808B2 /* bytearrayfile.h */, + 067ADAFA1EBF16B600B808B2 /* directoryfeed.h */, + 067ADAFB1EBF16B600B808B2 /* feed.h */, + 067ADAFC1EBF16B600B808B2 /* file.h */, + 067ADAFD1EBF16B600B808B2 /* fileindex.h */, + 067ADAFE1EBF16B600B808B2 /* filesystem.h */, + 067ADAFF1EBF16B600B808B2 /* folder.h */, + 067ADB001EBF16B600B808B2 /* IInterpreter */, + 067ADB011EBF16B600B808B2 /* iinterpreter.h */, + 067ADB021EBF16B600B808B2 /* libraryfile.h */, + 067ADB031EBF16B600B808B2 /* linkfile.h */, + 067ADB041EBF16B600B808B2 /* metadatabank.h */, + 067ADB051EBF16B600B808B2 /* nativefile.h */, + 067ADB061EBF16B600B808B2 /* nativepath.h */, + 067ADB071EBF16B600B808B2 /* Node */, + 067ADB081EBF16B600B808B2 /* node.h */, + 067ADB091EBF16B600B808B2 /* package.h */, + 067ADB0A1EBF16B600B808B2 /* packagefeed.h */, + 067ADB0B1EBF16B600B808B2 /* packageloader.h */, + 067ADB0C1EBF16B600B808B2 /* staticlibraryfeed.h */, + ); + name = filesys; + path = ../sdk/libcore/include/de/filesys; + sourceTree = ""; + }; + 067ADB0F1EBF16B600B808B2 /* net */ = { + isa = PBXGroup; + children = ( + 067ADB101EBF16B600B808B2 /* address.h */, + 067ADB111EBF16B600B808B2 /* beacon.h */, + 067ADB121EBF16B600B808B2 /* blockpacket.h */, + 067ADB131EBF16B600B808B2 /* identifiedpacket.h */, + 067ADB141EBF16B600B808B2 /* listensocket.h */, + 067ADB151EBF16B600B808B2 /* message.h */, + 067ADB161EBF16B600B808B2 /* packet.h */, + 067ADB171EBF16B600B808B2 /* protocol.h */, + 067ADB181EBF16B600B808B2 /* recordpacket.h */, + 067ADB191EBF16B600B808B2 /* socket.h */, + 067ADB1A1EBF16B600B808B2 /* transmitter.h */, + ); + name = net; + path = ../sdk/libcore/include/de/net; + sourceTree = ""; + }; + 067ADB1B1EBF16B600B808B2 /* scriptsys */ = { + isa = PBXGroup; + children = ( + 067ADB1C1EBF16B600B808B2 /* arrayexpression.h */, + 067ADB1D1EBF16B600B808B2 /* assignstatement.h */, + 067ADB1E1EBF16B600B808B2 /* builtinexpression.h */, + 067ADB1F1EBF16B600B808B2 /* catchstatement.h */, + 067ADB201EBF16B600B808B2 /* compound.h */, + 067ADB211EBF16B600B808B2 /* constantexpression.h */, + 067ADB221EBF16B600B808B2 /* context.h */, + 067ADB231EBF16B600B808B2 /* deletestatement.h */, + 067ADB241EBF16B600B808B2 /* dictionaryexpression.h */, + 067ADB251EBF16B600B808B2 /* evaluator.h */, + 067ADB261EBF16B600B808B2 /* expression.h */, + 067ADB271EBF16B600B808B2 /* expressionstatement.h */, + 067ADB281EBF16B600B808B2 /* flowstatement.h */, + 067ADB291EBF16B600B808B2 /* forstatement.h */, + 067ADB2A1EBF16B600B808B2 /* function.h */, + 067ADB2B1EBF16B600B808B2 /* functionstatement.h */, + 067ADB2C1EBF16B600B808B2 /* functionvalue.h */, + 067ADB2D1EBF16B600B808B2 /* ifstatement.h */, + 067ADB2E1EBF16B600B808B2 /* iobject.h */, + 067ADB2F1EBF16B600B808B2 /* iparser.h */, + 067ADB301EBF16B600B808B2 /* lex.h */, + 067ADB311EBF16B600B808B2 /* module.h */, + 067ADB321EBF16B600B808B2 /* nameexpression.h */, + 067ADB331EBF16B600B808B2 /* operator.h */, + 067ADB341EBF16B600B808B2 /* operatorexpression.h */, + 067ADB351EBF16B600B808B2 /* parser.h */, + 067ADB361EBF16B600B808B2 /* printstatement.h */, + 067ADB371EBF16B600B808B2 /* process.h */, + 067ADB381EBF16B600B808B2 /* scheduler.h */, + 067ADB391EBF16B600B808B2 /* scopestatement.h */, + 067ADB3A1EBF16B600B808B2 /* script.h */, + 067ADB3B1EBF16B600B808B2 /* scriptedinfo.h */, + 067ADB3C1EBF16B600B808B2 /* scriptlex.h */, + 067ADB3D1EBF16B600B808B2 /* scriptsystem.h */, + 067ADB3E1EBF16B600B808B2 /* statement.h */, + 067ADB3F1EBF16B600B808B2 /* tokenbuffer.h */, + 067ADB401EBF16B600B808B2 /* tokenrange.h */, + 067ADB411EBF16B600B808B2 /* trystatement.h */, + 067ADB421EBF16B600B808B2 /* whilestatement.h */, + ); + name = scriptsys; + path = ../sdk/libcore/include/de/scriptsys; + sourceTree = ""; + }; + 067ADB431EBF16B600B808B2 /* widgets */ = { + isa = PBXGroup; + children = ( + 067ADB441EBF16B600B808B2 /* action.h */, + 067ADB451EBF16B600B808B2 /* animation.h */, + 067ADB461EBF16B600B808B2 /* animationrule.h */, + 067ADB471EBF16B600B808B2 /* animationvector.h */, + 067ADB481EBF16B600B808B2 /* constantrule.h */, + 067ADB491EBF16B600B808B2 /* indirectrule.h */, + 067ADB4A1EBF16B600B808B2 /* operatorrule.h */, + 067ADB4B1EBF16B600B808B2 /* rootwidget.h */, + 067ADB4C1EBF16B600B808B2 /* rule.h */, + 067ADB4D1EBF16B600B808B2 /* rulebank.h */, + 067ADB4E1EBF16B600B808B2 /* rulerectangle.h */, + 067ADB4F1EBF16B600B808B2 /* rules.h */, + 067ADB501EBF16B600B808B2 /* widget.h */, + ); + name = widgets; + path = ../sdk/libcore/include/de/widgets; + sourceTree = ""; + }; + 067ADB511EBF16EC00B808B2 /* Headers */ = { + isa = PBXGroup; + children = ( + 067ADA961EBF16B600B808B2 /* c_wrapper.h */, + 067ADA971EBF16B600B808B2 /* charsymbols.h */, + 067ADA981EBF16B600B808B2 /* core */, + 067ADAB51EBF16B600B808B2 /* data */, + 067ADAF21EBF16B600B808B2 /* error.h */, + 067ADAF31EBF16B600B808B2 /* filesys */, + 067ADB0D1EBF16B600B808B2 /* libcore.h */, + 067ADB0E1EBF16B600B808B2 /* math.h */, + 067ADB0F1EBF16B600B808B2 /* net */, + 067ADB1B1EBF16B600B808B2 /* scriptsys */, + 067ADB431EBF16B600B808B2 /* widgets */, + ); + name = Headers; + sourceTree = ""; + }; + 067ADC071EBF176900B808B2 /* Headers */ = { + isa = PBXGroup; + children = ( + 067ADA8A1EBF159900B808B2 /* hexlex.h */, + 067ADA8B1EBF159900B808B2 /* importidtech1.h */, + 067ADA8C1EBF159900B808B2 /* mapimporter.h */, + 067ADA8D1EBF159900B808B2 /* mapinfotranslator.h */, + 067ADA8E1EBF159900B808B2 /* version.h */, + ); + name = Headers; + sourceTree = ""; + }; + 0686104F1EBF01F700180814 = { + isa = PBXGroup; + children = ( + 068610AA1EBF060300180814 /* Scripts */, + 068610971EBF051200180814 /* Sources */, + 068610611EBF01F700180814 /* Resources */, + 0686105A1EBF01F700180814 /* Frameworks */, + 068610591EBF01F700180814 /* Products */, + ); + sourceTree = ""; + }; + 068610591EBF01F700180814 /* Products */ = { + isa = PBXGroup; + children = ( + 068610581EBF01F700180814 /* Doomsday.app */, + 067AD9091EBF143600B808B2 /* libimportidtech1.a */, + 067AD9291EBF14E000B808B2 /* libdeng_core.a */, + 0635752C1EBF39880074E6D4 /* libdeng_shell.a */, + 063575D21EBF3AD50074E6D4 /* libdeng_legacy.a */, + 063576AD1EBF3CD20074E6D4 /* libdeng_gui.a */, + 063578061EBF42D10074E6D4 /* libdeng_appfw.a */, + 063578941EBF43A30074E6D4 /* libdeng_doomsday.a */, + 06357AF01EBF61C70074E6D4 /* libdeng_gamefw.a */, + 06357B041EBF63770074E6D4 /* libimportdeh.a */, + 06357B291EBF69C00074E6D4 /* libimportudmf.a */, + 06357B3C1EBF6EBD0074E6D4 /* libdoom.a */, + 06357CCB1EBF70A20074E6D4 /* libheretic.a */, + 06357DE11EBF728D0074E6D4 /* libhexen.a */, + 06357EED1EBF76120074E6D4 /* libdoom64.a */, + 06357F421EBF77A00074E6D4 /* libaudio_fmod.a */, + 063582481EBFBA120074E6D4 /* libassimp.a */, + ); + name = Products; + sourceTree = ""; + }; + 0686105A1EBF01F700180814 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 0635817E1EBF87040074E6D4 /* libz.tbd */, + 0686107F1EBF04C500180814 /* AudioToolbox.framework */, + 068610801EBF04C500180814 /* AVFoundation.framework */, + 068610811EBF04C500180814 /* CoreFoundation.framework */, + 068610821EBF04C500180814 /* CoreGraphics.framework */, + 068610831EBF04C500180814 /* CoreText.framework */, + 068610841EBF04C500180814 /* Foundation.framework */, + 068610851EBF04C500180814 /* ImageIO.framework */, + 068610861EBF04C500180814 /* MobileCoreServices.framework */, + 068610871EBF04C500180814 /* OpenGLES.framework */, + 068610881EBF04C500180814 /* QuartzCore.framework */, + 068610891EBF04C500180814 /* Security.framework */, + 0686108A1EBF04C500180814 /* UIKit.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; + 068610611EBF01F700180814 /* Resources */ = { + isa = PBXGroup; + children = ( + 063583261EC4E5E80074E6D4 /* User Interface */, + 068610621EBF01F700180814 /* Assets.xcassets */, + 068610791EBF01F700180814 /* Info.plist */, + 063583101EC044DF0074E6D4 /* doomsday.pk3 */, + 063583121EC045220074E6D4 /* libdoom.pk3 */, + 063583131EC045220074E6D4 /* libdoom64.pk3 */, + 063583141EC045220074E6D4 /* libheretic.pk3 */, + 063583151EC045220074E6D4 /* libhexen.pk3 */, + 0635831A1EC069B70074E6D4 /* net.dengine.base.pack */, + 0635831B1EC069B70074E6D4 /* net.dengine.client.pack */, + 0635831C1EC069B70074E6D4 /* net.dengine.stdlib.gui.pack */, + 0635831D1EC069B70074E6D4 /* net.dengine.stdlib.pack */, + 068610641EBF01F700180814 /* Supporting Files */, + ); + name = Resources; + path = Doomsday; + sourceTree = ""; + }; + 068610641EBF01F700180814 /* Supporting Files */ = { + isa = PBXGroup; + children = ( + 063583221EC0B7870074E6D4 /* doom1.wad */, + ); + name = "Supporting Files"; + sourceTree = ""; + }; + 068610971EBF051200180814 /* Sources */ = { + isa = PBXGroup; + children = ( + 0686109A1EBF052F00180814 /* Libraries */, + 068610A11EBF05A300180814 /* Plugins */, + 068610981EBF051A00180814 /* Client */, + ); + name = Sources; + sourceTree = ""; + }; + 068610981EBF051A00180814 /* Client */ = { + isa = PBXGroup; + children = ( + 06357F551EBF7AE50074E6D4 /* audio */, + 06357F601EBF7AE50074E6D4 /* client */, + 06357F6D1EBF7AE50074E6D4 /* gl */, + 06357F7A1EBF7AE50074E6D4 /* misc */, + 06357F811EBF7AE50074E6D4 /* network */, + 06357F8E1EBF7AE50074E6D4 /* render */, + 06357FBD1EBF7AE50074E6D4 /* resource */, + 06357FD21EBF7AE50074E6D4 /* ui */, + 063580381EBF7AE50074E6D4 /* unix */, + 0635803B1EBF7AE50074E6D4 /* world */, + 063580631EBF7AE50074E6D4 /* api_console.cpp */, + 063580641EBF7AE50074E6D4 /* api_filesys.cpp */, + 063580651EBF7AE50074E6D4 /* api_map.cpp */, + 063580661EBF7AE50074E6D4 /* api_mapedit.cpp */, + 063580671EBF7AE50074E6D4 /* api_uri.cpp */, + 063580681EBF7AE50074E6D4 /* busyrunner.cpp */, + 063580691EBF7AE50074E6D4 /* clientapp.cpp */, + 0635806A1EBF7AE50074E6D4 /* clientplayer.cpp */, + 0635806B1EBF7AE50074E6D4 /* con_config.cpp */, + 0635806C1EBF7AE50074E6D4 /* configprofiles.cpp */, + 0635806D1EBF7AE50074E6D4 /* dd_loop.cpp */, + 0635806E1EBF7AE50074E6D4 /* dd_main.cpp */, + 0635806F1EBF7AE50074E6D4 /* dd_pinit.cpp */, + 063580701EBF7AE50074E6D4 /* def_main.cpp */, + 063580711EBF7AE50074E6D4 /* localplayer.cpp */, + 063580721EBF7AE50074E6D4 /* main_client.cpp */, + 063580731EBF7AE50074E6D4 /* sys_system.cpp */, + 063671171EC4E7BA00DAF520 /* qrc_client.cpp */, + 063581981EBFB7620074E6D4 /* Doomsday_moc_compilation.cpp */, + ); + name = Client; + sourceTree = ""; + }; + 0686109A1EBF052F00180814 /* Libraries */ = { + isa = PBXGroup; + children = ( + 0635819A1EBFB9420074E6D4 /* Assimp */, + 0686109B1EBF053F00180814 /* libcore */, + 0686109D1EBF054A00180814 /* libshell */, + 0686109C1EBF054300180814 /* libgui */, + 0686109E1EBF054E00180814 /* libappfw */, + 0686109F1EBF055700180814 /* libegacy */, + 068610A01EBF056300180814 /* libdoomsday */, + 06357AF11EBF61EF0074E6D4 /* libgamefw */, + ); + name = Libraries; + sourceTree = ""; + }; + 0686109B1EBF053F00180814 /* libcore */ = { + isa = PBXGroup; + children = ( + 067ADB511EBF16EC00B808B2 /* Headers */, + 063581891EBFB5680074E6D4 /* deng_core_moc_compilation.cpp */, + 067AD92A1EBF151100B808B2 /* c_wrapper.cpp */, + 067AD92B1EBF151100B808B2 /* charsymbols.cpp */, + 067AD92C1EBF151100B808B2 /* concurrency */, + 067AD9331EBF151100B808B2 /* core */, + 067AD94D1EBF151100B808B2 /* data */, + 067AD97C1EBF151100B808B2 /* error.cpp */, + 067AD97D1EBF151100B808B2 /* filesys */, + 067AD9931EBF151100B808B2 /* math.cpp */, + 067AD9941EBF151100B808B2 /* matrix.cpp */, + 067AD9951EBF151100B808B2 /* net */, + 067AD9A41EBF151100B808B2 /* scriptsys */, + 067AD9CE1EBF151100B808B2 /* version.cpp */, + 067AD9CF1EBF151100B808B2 /* widgets */, + ); + name = libcore; + sourceTree = ""; + }; + 0686109C1EBF054300180814 /* libgui */ = { + isa = PBXGroup; + children = ( + 063576E01EBF3D0F0074E6D4 /* Headers */, + 063576261EBF3C970074E6D4 /* audio */, + 0635762A1EBF3C970074E6D4 /* graphics */, + 063576471EBF3C970074E6D4 /* input */, + 0635764D1EBF3C970074E6D4 /* text */, + 063581921EBFB6B80074E6D4 /* deng_gui_moc_compilation.cpp */, + 063576561EBF3C970074E6D4 /* displaymode_dummy.cpp */, + 063576571EBF3C970074E6D4 /* displaymode.cpp */, + 063576581EBF3C970074E6D4 /* glwindow_qml.cpp */, + 063576591EBF3C970074E6D4 /* guiapp.cpp */, + 0635765A1EBF3C970074E6D4 /* guiloop.cpp */, + 0635765B1EBF3C970074E6D4 /* persistentglwindow.cpp */, + 0635765C1EBF3C970074E6D4 /* windoweventhandler.cpp */, + ); + name = libgui; + sourceTree = ""; + }; + 0686109D1EBF054A00180814 /* libshell */ = { + isa = PBXGroup; + children = ( + 063575981EBF3A030074E6D4 /* Headers */, + 0635818B1EBFB5C90074E6D4 /* deng_shell_moc_compilation.cpp */, + 063575681EBF39FA0074E6D4 /* abstractlineeditor.cpp */, + 063575691EBF39FA0074E6D4 /* abstractlink.cpp */, + 0635756A1EBF39FA0074E6D4 /* action.cpp */, + 0635756B1EBF39FA0074E6D4 /* choicewidget.cpp */, + 0635756C1EBF39FA0074E6D4 /* commandlinewidget.cpp */, + 0635756D1EBF39FA0074E6D4 /* dialogwidget.cpp */, + 0635756E1EBF39FA0074E6D4 /* doomsdayinfo.cpp */, + 0635756F1EBF39FA0074E6D4 /* editorhistory.cpp */, + 063575701EBF39FA0074E6D4 /* inputdialog.cpp */, + 063575711EBF39FA0074E6D4 /* labelwidget.cpp */, + 063575721EBF39FA0074E6D4 /* lexicon.cpp */, + 063575731EBF39FA0074E6D4 /* libshell.cpp */, + 063575741EBF39FA0074E6D4 /* lineeditwidget.cpp */, + 063575751EBF39FA0074E6D4 /* link.cpp */, + 063575761EBF39FA0074E6D4 /* localserver.cpp */, + 063575771EBF39FA0074E6D4 /* logwidget.cpp */, + 063575781EBF39FA0074E6D4 /* menuwidget.cpp */, + 063575791EBF39FA0074E6D4 /* monospacelinewrapping.cpp */, + 0635757A1EBF39FA0074E6D4 /* protocol.cpp */, + 0635757B1EBF39FA0074E6D4 /* serverfinder.cpp */, + 0635757C1EBF39FA0074E6D4 /* serverinfo.cpp */, + 0635757D1EBF39FA0074E6D4 /* textcanvas.cpp */, + 0635757E1EBF39FA0074E6D4 /* textrootwidget.cpp */, + 0635757F1EBF39FA0074E6D4 /* textwidget.cpp */, + ); + name = libshell; + sourceTree = ""; + }; + 0686109E1EBF054E00180814 /* libappfw */ = { + isa = PBXGroup; + children = ( + 065548151EC8BB3E0000E33E /* Headers */, + 063577271EBF42C10074E6D4 /* dialogs */, + 0635772B1EBF42C10074E6D4 /* vr */, + 0635772E1EBF42C10074E6D4 /* widgets */, + 063581941EBFB6D30074E6D4 /* deng_appfw_moc_compilation.cpp */, + 063577521EBF42C10074E6D4 /* baseguiapp.cpp */, + 063577531EBF42C10074E6D4 /* basewindow.cpp */, + 063577541EBF42C10074E6D4 /* callbackaction.cpp */, + 063577551EBF42C10074E6D4 /* childwidgetorganizer.cpp */, + 063577561EBF42C10074E6D4 /* data.cpp */, + 063577571EBF42C10074E6D4 /* dialogcontentstylist.cpp */, + 063577581EBF42C10074E6D4 /* filtereddata.cpp */, + 063577591EBF42C10074E6D4 /* fontlinewrapping.cpp */, + 0635775A1EBF42C10074E6D4 /* gltextcomposer.cpp */, + 0635775B1EBF42C10074E6D4 /* gridlayout.cpp */, + 0635775C1EBF42C10074E6D4 /* guirootwidget.cpp */, + 0635775D1EBF42C10074E6D4 /* guiwidget.cpp */, + 0635775E1EBF42C10074E6D4 /* imageitem.cpp */, + 0635775F1EBF42C10074E6D4 /* item.cpp */, + 063577601EBF42C10074E6D4 /* listdata.cpp */, + 063577611EBF42C10074E6D4 /* margins.cpp */, + 063577621EBF42C10074E6D4 /* painter.cpp */, + 063577631EBF42C10074E6D4 /* persistentstate.cpp */, + 063577641EBF42C10074E6D4 /* proceduralimage.cpp */, + 063577651EBF42C10074E6D4 /* sequentiallayout.cpp */, + 063577661EBF42C10074E6D4 /* signalaction.cpp */, + 063577671EBF42C10074E6D4 /* style.cpp */, + 063577681EBF42C10074E6D4 /* textdrawable.cpp */, + 063577691EBF42C10074E6D4 /* untrapper.cpp */, + 0635776A1EBF42C10074E6D4 /* vrwindowtransform.cpp */, + 0635776B1EBF42C10074E6D4 /* windowsystem.cpp */, + 0635776C1EBF42C10074E6D4 /* windowtransform.cpp */, + ); + name = libappfw; + sourceTree = ""; + }; + 0686109F1EBF055700180814 /* libegacy */ = { + isa = PBXGroup; + children = ( + 063576071EBF3B5C0074E6D4 /* Headers */, + 063581961EBFB6F10074E6D4 /* deng_legacy_moc_compilation.cpp */, + 063575D31EBF3B430074E6D4 /* aabox.c */, + 063575D41EBF3B430074E6D4 /* animator.c */, + 063575D51EBF3B430074E6D4 /* binangle.c */, + 063575D61EBF3B430074E6D4 /* findfile_unix.c */, + 063575D71EBF3B430074E6D4 /* fixedpoint.c */, + 063575D81EBF3B430074E6D4 /* liblegacy.c */, + 063575D91EBF3B430074E6D4 /* mathutil.c */, + 063575DA1EBF3B430074E6D4 /* memory.c */, + 063575DB1EBF3B430074E6D4 /* memoryblockset.c */, + 063575DC1EBF3B430074E6D4 /* memoryzone.c */, + 063575DD1EBF3B430074E6D4 /* nodepile.c */, + 063575DE1EBF3B430074E6D4 /* point.c */, + 063575DF1EBF3B430074E6D4 /* reader1.c */, + 063575E01EBF3B430074E6D4 /* rect.c */, + 063575E11EBF3B430074E6D4 /* size.c */, + 063575E21EBF3B430074E6D4 /* stack.c */, + 063575E31EBF3B430074E6D4 /* str.c */, + 063575E41EBF3B430074E6D4 /* strutil.c */, + 063575E51EBF3B430074E6D4 /* texgamma.c */, + 063575E61EBF3B430074E6D4 /* vector1.c */, + 063575E71EBF3B430074E6D4 /* writer1.c */, + 063575E81EBF3B430074E6D4 /* concurrency.cpp */, + 063575EA1EBF3B430074E6D4 /* smoother.cpp */, + 063575EB1EBF3B430074E6D4 /* stringarray.cpp */, + 063575EC1EBF3B430074E6D4 /* timer.cpp */, + ); + name = libegacy; + sourceTree = ""; + }; + 068610A01EBF056300180814 /* libdoomsday */ = { + isa = PBXGroup; + children = ( + 063578951EBF43DE0074E6D4 /* c_wrapper */, + 063578971EBF43DE0074E6D4 /* console */, + 0635789D1EBF43DE0074E6D4 /* defs */, + 063578AF1EBF43DE0074E6D4 /* filesys */, + 063578C11EBF43DE0074E6D4 /* resource */, + 063578DD1EBF43DE0074E6D4 /* world */, + 063578F31EBF43DE0074E6D4 /* abstractsession.cpp */, + 063578F41EBF43DE0074E6D4 /* busymode.cpp */, + 063578F51EBF43DE0074E6D4 /* doomsdayapp.cpp */, + 063578F61EBF43DE0074E6D4 /* dualstring.cpp */, + 063578F71EBF43DE0074E6D4 /* game_init.cpp */, + 063578F81EBF43DE0074E6D4 /* game.cpp */, + 063578F91EBF43DE0074E6D4 /* gameprofiles.cpp */, + 063578FA1EBF43DE0074E6D4 /* games.cpp */, + 063578FB1EBF43DE0074E6D4 /* gamestatefolder.cpp */, + 063578FC1EBF43DE0074E6D4 /* help.cpp */, + 063578FD1EBF43DE0074E6D4 /* player.cpp */, + 063578FE1EBF43DE0074E6D4 /* players.cpp */, + 063578FF1EBF43DE0074E6D4 /* plugins.cpp */, + 063579001EBF43DE0074E6D4 /* savegames.cpp */, + 063579011EBF43DE0074E6D4 /* uri.cpp */, + 063579021EBF43DE0074E6D4 /* urivalue.cpp */, + 06357A7F1EBF5F250074E6D4 /* lzss.c */, + ); + name = libdoomsday; + sourceTree = ""; + }; + 068610A11EBF05A300180814 /* Plugins */ = { + isa = PBXGroup; + children = ( + 068610A51EBF05BB00180814 /* audio_fmod */, + 068610A21EBF05AA00180814 /* importidtech1 */, + 068610A31EBF05B200180814 /* importdeh */, + 068610A41EBF05B700180814 /* importudmf */, + 068610A61EBF05BF00180814 /* doom */, + 068610A81EBF05C800180814 /* heretic */, + 068610A91EBF05CB00180814 /* hexen */, + 068610A71EBF05C400180814 /* doom64 */, + 06357B151EBF69550074E6D4 /* Shared Sources */, + ); + name = Plugins; + sourceTree = ""; + }; + 068610A21EBF05AA00180814 /* importidtech1 */ = { + isa = PBXGroup; + children = ( + 067ADC071EBF176900B808B2 /* Headers */, + 067AD9131EBF148F00B808B2 /* hexlex.cpp */, + 067AD9141EBF148F00B808B2 /* importidtech1.cpp */, + 067AD9151EBF148F00B808B2 /* mapimporter.cpp */, + 067AD9161EBF148F00B808B2 /* mapimporter_loadblockmap.cpp */, + 067AD9171EBF148F00B808B2 /* mapinfotranslator.cpp */, + ); + name = importidtech1; + sourceTree = ""; + }; + 068610A31EBF05B200180814 /* importdeh */ = { + isa = PBXGroup; + children = ( + 06357B161EBF699B0074E6D4 /* Headers */, + 06357B051EBF64DE0074E6D4 /* dehreader_util.cpp */, + 06357B061EBF64DE0074E6D4 /* dehreader.cpp */, + 06357B071EBF64DE0074E6D4 /* importdeh.cpp */, + 06357B081EBF64DE0074E6D4 /* info.cpp */, + ); + name = importdeh; + sourceTree = ""; + }; + 068610A41EBF05B700180814 /* importudmf */ = { + isa = PBXGroup; + children = ( + 06357B171EBF699F0074E6D4 /* Headers */, + 06357B2C1EBF6A660074E6D4 /* importudmf.cpp */, + 06357B2D1EBF6A660074E6D4 /* udmflex.cpp */, + 06357B2E1EBF6A660074E6D4 /* udmfparser.cpp */, + ); + name = importudmf; + sourceTree = ""; + }; + 068610A51EBF05BB00180814 /* audio_fmod */ = { + isa = PBXGroup; + children = ( + 06357F431EBF78420074E6D4 /* driver_fmod.cpp */, + 06357F441EBF78420074E6D4 /* fmod_cd.cpp */, + 06357F451EBF78420074E6D4 /* fmod_music.cpp */, + 06357F461EBF78420074E6D4 /* fmod_sfx.cpp */, + 06357F471EBF78420074E6D4 /* fmod_util.cpp */, + ); + name = audio_fmod; + sourceTree = ""; + }; + 068610A61EBF05BF00180814 /* doom */ = { + isa = PBXGroup; + children = ( + 06357B3D1EBF6F5A0074E6D4 /* hud */, + 06357B451EBF6F5A0074E6D4 /* acfnlink.c */, + 06357B461EBF6F5A0074E6D4 /* m_random.c */, + 06357B471EBF6F5A0074E6D4 /* p_enemy.c */, + 06357B481EBF6F5A0074E6D4 /* p_inter.c */, + 06357B491EBF6F5A0074E6D4 /* p_maputl.c */, + 06357B4A1EBF6F5A0074E6D4 /* p_mobj.c */, + 06357B4B1EBF6F5A0074E6D4 /* p_pspr.c */, + 06357B4C1EBF6F5A0074E6D4 /* p_setup.c */, + 06357B4D1EBF6F5A0074E6D4 /* p_telept.c */, + 06357B4E1EBF6F5A0074E6D4 /* tables.c */, + 06357B4F1EBF6F5A0074E6D4 /* bossbrain.cpp */, + 06357B501EBF6F5A0074E6D4 /* d_api.cpp */, + 06357B511EBF6F5A0074E6D4 /* d_console.cpp */, + 06357B521EBF6F5A0074E6D4 /* d_items.cpp */, + 06357B531EBF6F5A0074E6D4 /* d_main.cpp */, + 06357B541EBF6F5A0074E6D4 /* d_refresh.cpp */, + 06357B551EBF6F5A0074E6D4 /* doomv9mapstatereader.cpp */, + 06357B561EBF6F5A0074E6D4 /* intermission.cpp */, + 06357B571EBF6F5A0074E6D4 /* m_cheat.cpp */, + 06357B581EBF6F5A0074E6D4 /* p_lights.cpp */, + 06357B591EBF6F5A0074E6D4 /* p_spec.cpp */, + 06357B5A1EBF6F5A0074E6D4 /* st_stuff.cpp */, + ); + name = doom; + sourceTree = ""; + }; + 068610A71EBF05C400180814 /* doom64 */ = { + isa = PBXGroup; + children = ( + 06357EEE1EBF767C0074E6D4 /* hud */, + 06357EF51EBF767C0074E6D4 /* acfnlink.c */, + 06357EF61EBF767C0074E6D4 /* m_random.c */, + 06357EF71EBF767C0074E6D4 /* p_enemy.c */, + 06357EF81EBF767C0074E6D4 /* p_inter.c */, + 06357EF91EBF767C0074E6D4 /* p_maputl.c */, + 06357EFA1EBF767C0074E6D4 /* p_mobj.c */, + 06357EFB1EBF767C0074E6D4 /* p_pspr.c */, + 06357EFC1EBF767C0074E6D4 /* p_setup.c */, + 06357EFD1EBF767C0074E6D4 /* p_telept.c */, + 06357EFE1EBF767C0074E6D4 /* tables.c */, + 06357EFF1EBF767C0074E6D4 /* d_console.cpp */, + 06357F001EBF767C0074E6D4 /* d_items.cpp */, + 06357F011EBF767C0074E6D4 /* d_main.cpp */, + 06357F021EBF767C0074E6D4 /* d_refresh.cpp */, + 06357F031EBF767C0074E6D4 /* d64_api.cpp */, + 06357F041EBF767C0074E6D4 /* intermission.cpp */, + 06357F051EBF767C0074E6D4 /* m_cheat.cpp */, + 06357F061EBF767C0074E6D4 /* p_lights.cpp */, + 06357F071EBF767C0074E6D4 /* p_spec.cpp */, + 06357F081EBF767C0074E6D4 /* st_stuff.cpp */, + ); + name = doom64; + sourceTree = ""; + }; + 068610A81EBF05C800180814 /* heretic */ = { + isa = PBXGroup; + children = ( + 06357D331EBF71320074E6D4 /* hud */, + 06357D361EBF71320074E6D4 /* acfnlink.c */, + 06357D371EBF71320074E6D4 /* m_random.c */, + 06357D381EBF71320074E6D4 /* p_enemy.c */, + 06357D391EBF71320074E6D4 /* p_inter.c */, + 06357D3A1EBF71320074E6D4 /* p_maputl.c */, + 06357D3B1EBF71320074E6D4 /* p_mobj.c */, + 06357D3C1EBF71320074E6D4 /* p_pspr.c */, + 06357D3D1EBF71320074E6D4 /* p_setup.c */, + 06357D3E1EBF71320074E6D4 /* p_telept.c */, + 06357D3F1EBF71320074E6D4 /* tables.c */, + 06357D401EBF71320074E6D4 /* h_api.cpp */, + 06357D411EBF71320074E6D4 /* h_console.cpp */, + 06357D421EBF71320074E6D4 /* h_items.cpp */, + 06357D431EBF71320074E6D4 /* h_main.cpp */, + 06357D441EBF71320074E6D4 /* h_refresh.cpp */, + 06357D451EBF71320074E6D4 /* hereticv13mapstatereader.cpp */, + 06357D461EBF71320074E6D4 /* intermission.cpp */, + 06357D471EBF71320074E6D4 /* m_cheat.cpp */, + 06357D481EBF71320074E6D4 /* p_lights.cpp */, + 06357D491EBF71320074E6D4 /* p_spec.cpp */, + 06357D4A1EBF71320074E6D4 /* st_stuff.cpp */, + ); + name = heretic; + sourceTree = ""; + }; + 068610A91EBF05CB00180814 /* hexen */ = { + isa = PBXGroup; + children = ( + 06357DE21EBF73460074E6D4 /* hud */, + 06357DF01EBF73460074E6D4 /* a_action.c */, + 06357DF11EBF73460074E6D4 /* acfnlink.c */, + 06357DF21EBF73460074E6D4 /* m_random.c */, + 06357DF31EBF73460074E6D4 /* p_enemy.c */, + 06357DF41EBF73460074E6D4 /* p_inter.c */, + 06357DF51EBF73460074E6D4 /* p_maputl.c */, + 06357DF61EBF73460074E6D4 /* p_mobj.c */, + 06357DF71EBF73460074E6D4 /* p_pspr.c */, + 06357DF81EBF73460074E6D4 /* p_setup.c */, + 06357DF91EBF73460074E6D4 /* p_telept.c */, + 06357DFA1EBF73460074E6D4 /* p_things.c */, + 06357DFB1EBF73460074E6D4 /* tables.c */, + 06357DFC1EBF73460074E6D4 /* h2_main.cpp */, + 06357DFD1EBF73460074E6D4 /* hconsole.cpp */, + 06357DFE1EBF73460074E6D4 /* hrefresh.cpp */, + 06357DFF1EBF73460074E6D4 /* intermission.cpp */, + 06357E001EBF73460074E6D4 /* lightninganimator.cpp */, + 06357E011EBF73460074E6D4 /* m_cheat.cpp */, + 06357E021EBF73460074E6D4 /* p_lights.cpp */, + 06357E031EBF73460074E6D4 /* p_pillar.cpp */, + 06357E041EBF73460074E6D4 /* p_spec.cpp */, + 06357E051EBF73460074E6D4 /* p_waggle.cpp */, + 06357E061EBF73460074E6D4 /* sn_sonix.cpp */, + 06357E071EBF73460074E6D4 /* st_stuff.cpp */, + 06357E081EBF73460074E6D4 /* x_api.cpp */, + ); + name = hexen; + sourceTree = ""; + }; + 068610AA1EBF060300180814 /* Scripts */ = { + isa = PBXGroup; + children = ( + 063581801EBF9C690074E6D4 /* xcmoc.py */, + 0635830F1EC0401D0074E6D4 /* Makefile.xcpacks */, + ); + name = Scripts; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXLegacyTarget section */ + 063583071EC03DAD0074E6D4 /* Packages */ = { + isa = PBXLegacyTarget; + buildArgumentsString = "-f $(SRCROOT)/../build/scripts/Makefile.xcpacks $(ACTION)"; + buildConfigurationList = 063583081EC03DAD0074E6D4 /* Build configuration list for PBXLegacyTarget "Packages" */; + buildPhases = ( + ); + buildToolPath = /usr/bin/make; + buildWorkingDirectory = $PROJECT_TEMP_DIR; + dependencies = ( + ); + name = Packages; + passBuildSettingsInEnvironment = 1; + productName = Packages; + }; +/* End PBXLegacyTarget section */ + +/* Begin PBXNativeTarget section */ + 063574811EBF39880074E6D4 /* deng_shell */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063575291EBF39880074E6D4 /* Build configuration list for PBXNativeTarget "deng_shell" */; + buildPhases = ( + 063581851EBFB2390074E6D4 /* ShellScript */, + 063574821EBF39880074E6D4 /* Sources */, + 063575271EBF39880074E6D4 /* Frameworks */, + 063575281EBF39880074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_shell; + productName = importidtech1; + productReference = 0635752C1EBF39880074E6D4 /* libdeng_shell.a */; + productType = "com.apple.product-type.library.static"; + }; + 063575B31EBF3AD50074E6D4 /* deng_legacy */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063575CF1EBF3AD50074E6D4 /* Build configuration list for PBXNativeTarget "deng_legacy" */; + buildPhases = ( + 0635818F1EBFB6210074E6D4 /* ShellScript */, + 063575B41EBF3AD50074E6D4 /* Sources */, + 063575CD1EBF3AD50074E6D4 /* Frameworks */, + 063575CE1EBF3AD50074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_legacy; + productName = importidtech1; + productReference = 063575D21EBF3AD50074E6D4 /* libdeng_legacy.a */; + productType = "com.apple.product-type.library.static"; + }; + 0635768E1EBF3CD20074E6D4 /* deng_gui */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063576AA1EBF3CD20074E6D4 /* Build configuration list for PBXNativeTarget "deng_gui" */; + buildPhases = ( + 0635818D1EBFB5F20074E6D4 /* ShellScript */, + 0635768F1EBF3CD20074E6D4 /* Sources */, + 063576A81EBF3CD20074E6D4 /* Frameworks */, + 063576A91EBF3CD20074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 0635824A1EBFBA350074E6D4 /* PBXTargetDependency */, + ); + name = deng_gui; + productName = importidtech1; + productReference = 063576AD1EBF3CD20074E6D4 /* libdeng_gui.a */; + productType = "com.apple.product-type.library.static"; + }; + 063577E71EBF42D10074E6D4 /* deng_appfw */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063578031EBF42D10074E6D4 /* Build configuration list for PBXNativeTarget "deng_appfw" */; + buildPhases = ( + 0635818E1EBFB6090074E6D4 /* ShellScript */, + 063577E81EBF42D10074E6D4 /* Sources */, + 063578011EBF42D10074E6D4 /* Frameworks */, + 063578021EBF42D10074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_appfw; + productName = importidtech1; + productReference = 063578061EBF42D10074E6D4 /* libdeng_appfw.a */; + productType = "com.apple.product-type.library.static"; + }; + 0635784A1EBF43A30074E6D4 /* deng_doomsday */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063578911EBF43A30074E6D4 /* Build configuration list for PBXNativeTarget "deng_doomsday" */; + buildPhases = ( + 063581901EBFB6320074E6D4 /* ShellScript */, + 0635784B1EBF43A30074E6D4 /* Sources */, + 0635788F1EBF43A30074E6D4 /* Frameworks */, + 063578901EBF43A30074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_doomsday; + productName = importidtech1; + productReference = 063578941EBF43A30074E6D4 /* libdeng_doomsday.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357A811EBF61C70074E6D4 /* deng_gamefw */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357AED1EBF61C70074E6D4 /* Build configuration list for PBXNativeTarget "deng_gamefw" */; + buildPhases = ( + 06357A821EBF61C70074E6D4 /* Sources */, + 06357AEB1EBF61C70074E6D4 /* Frameworks */, + 06357AEC1EBF61C70074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_gamefw; + productName = importidtech1; + productReference = 06357AF01EBF61C70074E6D4 /* libdeng_gamefw.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357AF81EBF63770074E6D4 /* importdeh */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357B011EBF63770074E6D4 /* Build configuration list for PBXNativeTarget "importdeh" */; + buildPhases = ( + 06357AF91EBF63770074E6D4 /* Sources */, + 06357AFF1EBF63770074E6D4 /* Frameworks */, + 06357B001EBF63770074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = importdeh; + productName = importidtech1; + productReference = 06357B041EBF63770074E6D4 /* libimportdeh.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357B1D1EBF69C00074E6D4 /* importudmf */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357B261EBF69C00074E6D4 /* Build configuration list for PBXNativeTarget "importudmf" */; + buildPhases = ( + 06357B1E1EBF69C00074E6D4 /* Sources */, + 06357B241EBF69C00074E6D4 /* Frameworks */, + 06357B251EBF69C00074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = importudmf; + productName = importidtech1; + productReference = 06357B291EBF69C00074E6D4 /* libimportudmf.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357B321EBF6EBD0074E6D4 /* doom */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357B391EBF6EBD0074E6D4 /* Build configuration list for PBXNativeTarget "doom" */; + buildPhases = ( + 06357B331EBF6EBD0074E6D4 /* Sources */, + 06357B371EBF6EBD0074E6D4 /* Frameworks */, + 06357B381EBF6EBD0074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = doom; + productName = importidtech1; + productReference = 06357B3C1EBF6EBD0074E6D4 /* libdoom.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357C451EBF70A20074E6D4 /* heretic */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357CC81EBF70A20074E6D4 /* Build configuration list for PBXNativeTarget "heretic" */; + buildPhases = ( + 06357C461EBF70A20074E6D4 /* Sources */, + 06357CC61EBF70A20074E6D4 /* Frameworks */, + 06357CC71EBF70A20074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = heretic; + productName = importidtech1; + productReference = 06357CCB1EBF70A20074E6D4 /* libheretic.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357D611EBF728D0074E6D4 /* hexen */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357DDE1EBF728D0074E6D4 /* Build configuration list for PBXNativeTarget "hexen" */; + buildPhases = ( + 06357D621EBF728D0074E6D4 /* Sources */, + 06357DDC1EBF728D0074E6D4 /* Frameworks */, + 06357DDD1EBF728D0074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = hexen; + productName = importidtech1; + productReference = 06357DE11EBF728D0074E6D4 /* libhexen.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357E671EBF76120074E6D4 /* doom64 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357EEA1EBF76120074E6D4 /* Build configuration list for PBXNativeTarget "doom64" */; + buildPhases = ( + 06357E681EBF76120074E6D4 /* Sources */, + 06357EE81EBF76120074E6D4 /* Frameworks */, + 06357EE91EBF76120074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = doom64; + productName = importidtech1; + productReference = 06357EED1EBF76120074E6D4 /* libdoom64.a */; + productType = "com.apple.product-type.library.static"; + }; + 06357F371EBF77A00074E6D4 /* audio_fmod */ = { + isa = PBXNativeTarget; + buildConfigurationList = 06357F3F1EBF77A00074E6D4 /* Build configuration list for PBXNativeTarget "audio_fmod" */; + buildPhases = ( + 06357F381EBF77A00074E6D4 /* Sources */, + 06357F3D1EBF77A00074E6D4 /* Frameworks */, + 06357F3E1EBF77A00074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = audio_fmod; + productName = importidtech1; + productReference = 06357F421EBF77A00074E6D4 /* libaudio_fmod.a */; + productType = "com.apple.product-type.library.static"; + }; + 0635819B1EBFBA120074E6D4 /* assimp */ = { + isa = PBXNativeTarget; + buildConfigurationList = 063582451EBFBA120074E6D4 /* Build configuration list for PBXNativeTarget "assimp" */; + buildPhases = ( + 0635819D1EBFBA120074E6D4 /* Sources */, + 063582431EBFBA120074E6D4 /* Frameworks */, + 063582441EBFBA120074E6D4 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = assimp; + productName = importidtech1; + productReference = 063582481EBFBA120074E6D4 /* libassimp.a */; + productType = "com.apple.product-type.library.static"; + }; + 067AD9081EBF143600B808B2 /* importidtech1 */ = { + isa = PBXNativeTarget; + buildConfigurationList = 067AD90F1EBF143600B808B2 /* Build configuration list for PBXNativeTarget "importidtech1" */; + buildPhases = ( + 067AD9051EBF143600B808B2 /* Sources */, + 067AD9061EBF143600B808B2 /* Frameworks */, + 067AD9071EBF143600B808B2 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = importidtech1; + productName = importidtech1; + productReference = 067AD9091EBF143600B808B2 /* libimportidtech1.a */; + productType = "com.apple.product-type.library.static"; + }; + 067AD91D1EBF14E000B808B2 /* deng_core */ = { + isa = PBXNativeTarget; + buildConfigurationList = 067AD9261EBF14E000B808B2 /* Build configuration list for PBXNativeTarget "deng_core" */; + buildPhases = ( + 063581811EBF9CED0074E6D4 /* ShellScript */, + 067AD91E1EBF14E000B808B2 /* Sources */, + 067AD9241EBF14E000B808B2 /* Frameworks */, + 067AD9251EBF14E000B808B2 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = deng_core; + productName = importidtech1; + productReference = 067AD9291EBF14E000B808B2 /* libdeng_core.a */; + productType = "com.apple.product-type.library.static"; + }; + 068610571EBF01F700180814 /* Doomsday */ = { + isa = PBXNativeTarget; + buildConfigurationList = 0686107C1EBF01F700180814 /* Build configuration list for PBXNativeTarget "Doomsday" */; + buildPhases = ( + 063583241EC4E5530074E6D4 /* ShellScript */, + 063581911EBFB6540074E6D4 /* ShellScript */, + 068610541EBF01F700180814 /* Sources */, + 068610551EBF01F700180814 /* Frameworks */, + 068610561EBF01F700180814 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 0635830C1EC03E0C0074E6D4 /* PBXTargetDependency */, + 067AD9E21EBF154500B808B2 /* PBXTargetDependency */, + 0635771C1EBF3EB40074E6D4 /* PBXTargetDependency */, + 063577201EBF3EB40074E6D4 /* PBXTargetDependency */, + 06357A7C1EBF5E8B0074E6D4 /* PBXTargetDependency */, + 0635771E1EBF3EB40074E6D4 /* PBXTargetDependency */, + 06357A7E1EBF5E8B0074E6D4 /* PBXTargetDependency */, + 06357B121EBF674F0074E6D4 /* PBXTargetDependency */, + 06357F4E1EBF79EB0074E6D4 /* PBXTargetDependency */, + 067AD9E41EBF154500B808B2 /* PBXTargetDependency */, + 06357B141EBF674F0074E6D4 /* PBXTargetDependency */, + 06357B2B1EBF69F00074E6D4 /* PBXTargetDependency */, + 06357CCD1EBF70AE0074E6D4 /* PBXTargetDependency */, + 06357CCF1EBF70AE0074E6D4 /* PBXTargetDependency */, + 06357F501EBF79EB0074E6D4 /* PBXTargetDependency */, + 06357F521EBF79EB0074E6D4 /* PBXTargetDependency */, + ); + name = Doomsday; + productName = Doomsday; + productReference = 068610581EBF01F700180814 /* Doomsday.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 068610501EBF01F700180814 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0830; + ORGANIZATIONNAME = "Jaakko Keränen"; + TargetAttributes = { + 063574811EBF39880074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 063575B31EBF3AD50074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 0635768E1EBF3CD20074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 063577E71EBF42D10074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 0635784A1EBF43A30074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357A811EBF61C70074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357AF81EBF63770074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357B1D1EBF69C00074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357B321EBF6EBD0074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357C451EBF70A20074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357D611EBF728D0074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357E671EBF76120074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 06357F371EBF77A00074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 0635819B1EBFBA120074E6D4 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 063583071EC03DAD0074E6D4 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = VS2RUWJAF3; + ProvisioningStyle = Automatic; + }; + 067AD9081EBF143600B808B2 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = VS2RUWJAF3; + ProvisioningStyle = Automatic; + }; + 067AD91D1EBF14E000B808B2 = { + DevelopmentTeam = VS2RUWJAF3; + }; + 068610571EBF01F700180814 = { + CreatedOnToolsVersion = 8.3.2; + DevelopmentTeam = VS2RUWJAF3; + ProvisioningStyle = Automatic; + }; + }; + }; + buildConfigurationList = 068610531EBF01F700180814 /* Build configuration list for PBXProject "Doomsday" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 0686104F1EBF01F700180814; + productRefGroup = 068610591EBF01F700180814 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 063583071EC03DAD0074E6D4 /* Packages */, + 067AD91D1EBF14E000B808B2 /* deng_core */, + 063574811EBF39880074E6D4 /* deng_shell */, + 0635768E1EBF3CD20074E6D4 /* deng_gui */, + 063577E71EBF42D10074E6D4 /* deng_appfw */, + 063575B31EBF3AD50074E6D4 /* deng_legacy */, + 0635784A1EBF43A30074E6D4 /* deng_doomsday */, + 06357A811EBF61C70074E6D4 /* deng_gamefw */, + 0635819B1EBFBA120074E6D4 /* assimp */, + 06357F371EBF77A00074E6D4 /* audio_fmod */, + 067AD9081EBF143600B808B2 /* importidtech1 */, + 06357AF81EBF63770074E6D4 /* importdeh */, + 06357B1D1EBF69C00074E6D4 /* importudmf */, + 06357B321EBF6EBD0074E6D4 /* doom */, + 06357C451EBF70A20074E6D4 /* heretic */, + 06357D611EBF728D0074E6D4 /* hexen */, + 06357E671EBF76120074E6D4 /* doom64 */, + 068610571EBF01F700180814 /* Doomsday */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 068610561EBF01F700180814 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 068610781EBF01F700180814 /* LaunchScreen.storyboard in Resources */, + 068610631EBF01F700180814 /* Assets.xcassets in Resources */, + 063583211EC069B70074E6D4 /* net.dengine.stdlib.pack in Resources */, + 063583201EC069B70074E6D4 /* net.dengine.stdlib.gui.pack in Resources */, + 0635831E1EC069B70074E6D4 /* net.dengine.base.pack in Resources */, + 0635831F1EC069B70074E6D4 /* net.dengine.client.pack in Resources */, + 063583111EC044DF0074E6D4 /* doomsday.pk3 in Resources */, + 063583161EC0452B0074E6D4 /* libdoom.pk3 in Resources */, + 063583181EC0452B0074E6D4 /* libheretic.pk3 in Resources */, + 063583191EC0452B0074E6D4 /* libhexen.pk3 in Resources */, + 063583171EC0452B0074E6D4 /* libdoom64.pk3 in Resources */, + 063583231EC0B7870074E6D4 /* doom1.wad in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + 063581811EBF9CED0074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../sdk/libcore\n"; + showEnvVarsInLog = 0; + }; + 063581851EBFB2390074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../sdk/libshell\n"; + showEnvVarsInLog = 0; + }; + 0635818D1EBFB5F20074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../sdk/libgui\n"; + showEnvVarsInLog = 0; + }; + 0635818E1EBFB6090074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../sdk/libappfw\n"; + showEnvVarsInLog = 0; + }; + 0635818F1EBFB6210074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../sdk/liblegacy\n"; + }; + 063581901EBFB6320074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../apps/libdoomsday\n"; + }; + 063581911EBFB6540074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$SRCROOT/../build/scripts/xcmoc.py $SRCROOT/../apps/client\n"; + showEnvVarsInLog = 0; + }; + 063583241EC4E5530074E6D4 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + "$(SRCROOT)/../apps/client/res/qml/client.qrc", + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "$QT_DIR/bin/rcc $SCRIPT_INPUT_FILE_0 -o $PROJECT_TEMP_DIR/qrc_client.cpp\n"; + }; +/* End PBXShellScriptBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 063574821EBF39880074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063575801EBF39FA0074E6D4 /* abstractlineeditor.cpp in Sources */, + 063575811EBF39FA0074E6D4 /* abstractlink.cpp in Sources */, + 063575821EBF39FA0074E6D4 /* action.cpp in Sources */, + 063575831EBF39FA0074E6D4 /* choicewidget.cpp in Sources */, + 063575841EBF39FA0074E6D4 /* commandlinewidget.cpp in Sources */, + 063575851EBF39FA0074E6D4 /* dialogwidget.cpp in Sources */, + 063575861EBF39FA0074E6D4 /* doomsdayinfo.cpp in Sources */, + 063575871EBF39FA0074E6D4 /* editorhistory.cpp in Sources */, + 063575881EBF39FA0074E6D4 /* inputdialog.cpp in Sources */, + 063575891EBF39FA0074E6D4 /* labelwidget.cpp in Sources */, + 0635758A1EBF39FA0074E6D4 /* lexicon.cpp in Sources */, + 0635758B1EBF39FA0074E6D4 /* libshell.cpp in Sources */, + 0635758C1EBF39FA0074E6D4 /* lineeditwidget.cpp in Sources */, + 0635818C1EBFB5C90074E6D4 /* deng_shell_moc_compilation.cpp in Sources */, + 0635758D1EBF39FA0074E6D4 /* link.cpp in Sources */, + 0635758E1EBF39FA0074E6D4 /* localserver.cpp in Sources */, + 0635758F1EBF39FA0074E6D4 /* logwidget.cpp in Sources */, + 063575901EBF39FA0074E6D4 /* menuwidget.cpp in Sources */, + 063575911EBF39FA0074E6D4 /* monospacelinewrapping.cpp in Sources */, + 063575921EBF39FA0074E6D4 /* protocol.cpp in Sources */, + 063575931EBF39FA0074E6D4 /* serverfinder.cpp in Sources */, + 063575941EBF39FA0074E6D4 /* serverinfo.cpp in Sources */, + 063575951EBF39FA0074E6D4 /* textcanvas.cpp in Sources */, + 063575961EBF39FA0074E6D4 /* textrootwidget.cpp in Sources */, + 063575971EBF39FA0074E6D4 /* textwidget.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063575B41EBF3AD50074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063575ED1EBF3B430074E6D4 /* aabox.c in Sources */, + 063575EE1EBF3B430074E6D4 /* animator.c in Sources */, + 063575EF1EBF3B430074E6D4 /* binangle.c in Sources */, + 063575F01EBF3B430074E6D4 /* findfile_unix.c in Sources */, + 063581971EBFB6F10074E6D4 /* deng_legacy_moc_compilation.cpp in Sources */, + 063575F11EBF3B430074E6D4 /* fixedpoint.c in Sources */, + 063575F21EBF3B430074E6D4 /* liblegacy.c in Sources */, + 063575F31EBF3B430074E6D4 /* mathutil.c in Sources */, + 063575F41EBF3B430074E6D4 /* memory.c in Sources */, + 063575F51EBF3B430074E6D4 /* memoryblockset.c in Sources */, + 063575F61EBF3B430074E6D4 /* memoryzone.c in Sources */, + 063575F71EBF3B430074E6D4 /* nodepile.c in Sources */, + 063575F81EBF3B430074E6D4 /* point.c in Sources */, + 063575F91EBF3B430074E6D4 /* reader1.c in Sources */, + 063575FA1EBF3B430074E6D4 /* rect.c in Sources */, + 063575FB1EBF3B430074E6D4 /* size.c in Sources */, + 063575FC1EBF3B430074E6D4 /* stack.c in Sources */, + 063575FD1EBF3B430074E6D4 /* str.c in Sources */, + 063575FE1EBF3B430074E6D4 /* strutil.c in Sources */, + 063575FF1EBF3B430074E6D4 /* texgamma.c in Sources */, + 063576001EBF3B430074E6D4 /* vector1.c in Sources */, + 063576011EBF3B430074E6D4 /* writer1.c in Sources */, + 063576021EBF3B430074E6D4 /* concurrency.cpp in Sources */, + 063576041EBF3B430074E6D4 /* smoother.cpp in Sources */, + 063576051EBF3B430074E6D4 /* stringarray.cpp in Sources */, + 063576061EBF3B430074E6D4 /* timer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0635768F1EBF3CD20074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063576AE1EBF3CFC0074E6D4 /* sound.cpp in Sources */, + 063576AF1EBF3CFC0074E6D4 /* waveform.cpp in Sources */, + 063576B01EBF3CFC0074E6D4 /* waveformbank.cpp in Sources */, + 063576B11EBF3CFC0074E6D4 /* atlas.cpp in Sources */, + 063576B21EBF3CFC0074E6D4 /* atlastexture.cpp in Sources */, + 063576B31EBF3CFC0074E6D4 /* colorbank.cpp in Sources */, + 063576B41EBF3CFC0074E6D4 /* drawable.cpp in Sources */, + 063576B51EBF3CFC0074E6D4 /* glatlasbuffer.cpp in Sources */, + 063581931EBFB6B80074E6D4 /* deng_gui_moc_compilation.cpp in Sources */, + 063576B61EBF3CFC0074E6D4 /* glbuffer.cpp in Sources */, + 063576B71EBF3CFC0074E6D4 /* gldrawqueue.cpp in Sources */, + 063576B81EBF3CFC0074E6D4 /* glframebuffer.cpp in Sources */, + 063576BA1EBF3CFC0074E6D4 /* glinfo.cpp in Sources */, + 063576BB1EBF3CFC0074E6D4 /* glprogram.cpp in Sources */, + 063576BC1EBF3CFC0074E6D4 /* glshader.cpp in Sources */, + 063576BD1EBF3CFC0074E6D4 /* glshaderbank.cpp in Sources */, + 063576BE1EBF3CFC0074E6D4 /* glstate.cpp in Sources */, + 063576BF1EBF3CFC0074E6D4 /* glsubbuffer.cpp in Sources */, + 063576C01EBF3CFC0074E6D4 /* gltexture.cpp in Sources */, + 063576C11EBF3CFC0074E6D4 /* gltextureframebuffer.cpp in Sources */, + 063576C21EBF3CFC0074E6D4 /* gluniform.cpp in Sources */, + 063576C31EBF3CFC0074E6D4 /* heightmap.cpp in Sources */, + 063576C41EBF3CFC0074E6D4 /* image.cpp in Sources */, + 063576C51EBF3CFC0074E6D4 /* imagebank.cpp in Sources */, + 063576C61EBF3CFC0074E6D4 /* imagefile.cpp in Sources */, + 063576C71EBF3CFC0074E6D4 /* kdtreeatlasallocator.cpp in Sources */, + 063576C81EBF3CFC0074E6D4 /* modelbank.cpp in Sources */, + 063576C91EBF3CFC0074E6D4 /* modeldrawable.cpp in Sources */, + 063576CA1EBF3CFC0074E6D4 /* multiatlas.cpp in Sources */, + 063576CB1EBF3CFC0074E6D4 /* rowatlasallocator.cpp in Sources */, + 063576CC1EBF3CFC0074E6D4 /* texturebank.cpp in Sources */, + 063576CD1EBF3CFC0074E6D4 /* keyevent.cpp in Sources */, + 063576CE1EBF3CFC0074E6D4 /* keyeventsource.cpp in Sources */, + 063576CF1EBF3CFC0074E6D4 /* mouseevent.cpp in Sources */, + 063576D01EBF3CFC0074E6D4 /* mouseeventsource.cpp in Sources */, + 063576D11EBF3CFC0074E6D4 /* coretextnativefont_macx.cpp in Sources */, + 063576D31EBF3CFC0074E6D4 /* font.cpp in Sources */, + 063576D41EBF3CFC0074E6D4 /* font_richformat.cpp in Sources */, + 063576D51EBF3CFC0074E6D4 /* fontbank.cpp in Sources */, + 063576D61EBF3CFC0074E6D4 /* nativefont.cpp in Sources */, + 063576D91EBF3CFC0074E6D4 /* displaymode_dummy.cpp in Sources */, + 063576DA1EBF3CFC0074E6D4 /* displaymode.cpp in Sources */, + 063576DB1EBF3CFC0074E6D4 /* glwindow_qml.cpp in Sources */, + 063576DC1EBF3CFC0074E6D4 /* guiapp.cpp in Sources */, + 063576DD1EBF3CFC0074E6D4 /* guiloop.cpp in Sources */, + 063576DE1EBF3CFC0074E6D4 /* persistentglwindow.cpp in Sources */, + 063576DF1EBF3CFC0074E6D4 /* windoweventhandler.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 063577E81EBF42D10074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063578071EBF43470074E6D4 /* directorylistdialog.cpp in Sources */, + 063578081EBF43470074E6D4 /* inputdialog.cpp in Sources */, + 063578091EBF43470074E6D4 /* messagedialog.cpp in Sources */, + 0635780A1EBF43470074E6D4 /* oculusrift.cpp in Sources */, + 0635780B1EBF43470074E6D4 /* vrconfig.cpp in Sources */, + 0635780C1EBF43470074E6D4 /* auxbuttonwidget.cpp in Sources */, + 0635780D1EBF43470074E6D4 /* blurwidget.cpp in Sources */, + 0635780E1EBF43470074E6D4 /* buttonwidget.cpp in Sources */, + 0635780F1EBF43470074E6D4 /* choicewidget.cpp in Sources */, + 063578101EBF43470074E6D4 /* commandwidget.cpp in Sources */, + 063578111EBF43470074E6D4 /* compositorwidget.cpp in Sources */, + 063578121EBF43470074E6D4 /* dialogwidget.cpp in Sources */, + 063578131EBF43470074E6D4 /* directoryarraywidget.cpp in Sources */, + 063578141EBF43470074E6D4 /* documentpopupwidget.cpp in Sources */, + 063581951EBFB6D30074E6D4 /* deng_appfw_moc_compilation.cpp in Sources */, + 063578151EBF43470074E6D4 /* documentwidget.cpp in Sources */, + 063578161EBF43470074E6D4 /* fadetoblackwidget.cpp in Sources */, + 063578171EBF43470074E6D4 /* focuswidget.cpp in Sources */, + 063578181EBF43470074E6D4 /* foldpanelwidget.cpp in Sources */, + 063578191EBF43470074E6D4 /* gridpopupwidget.cpp in Sources */, + 0635781A1EBF43470074E6D4 /* labelwidget.cpp in Sources */, + 0635781B1EBF43470074E6D4 /* lineeditwidget.cpp in Sources */, + 0635781C1EBF43470074E6D4 /* logwidget.cpp in Sources */, + 0635781D1EBF43470074E6D4 /* menuwidget.cpp in Sources */, + 0635781E1EBF43470074E6D4 /* notificationareawidget.cpp in Sources */, + 0635781F1EBF43470074E6D4 /* panelwidget.cpp in Sources */, + 063578201EBF43470074E6D4 /* popupbuttonwidget.cpp in Sources */, + 063578211EBF43470074E6D4 /* popupmenuwidget.cpp in Sources */, + 063578221EBF43470074E6D4 /* popupwidget.cpp in Sources */, + 063578231EBF43470074E6D4 /* progresswidget.cpp in Sources */, + 063578241EBF43470074E6D4 /* relaywidget.cpp in Sources */, + 063578251EBF43470074E6D4 /* scriptcommandwidget.cpp in Sources */, + 063578261EBF43470074E6D4 /* scrollareawidget.cpp in Sources */, + 063578271EBF43470074E6D4 /* sliderwidget.cpp in Sources */, + 063578281EBF43470074E6D4 /* tabwidget.cpp in Sources */, + 063578291EBF43470074E6D4 /* togglewidget.cpp in Sources */, + 0635782A1EBF43470074E6D4 /* variablearraywidget.cpp in Sources */, + 0635782B1EBF43470074E6D4 /* variablechoicewidget.cpp in Sources */, + 0635782C1EBF43470074E6D4 /* variablelineeditwidget.cpp in Sources */, + 0635782D1EBF43470074E6D4 /* variablesliderwidget.cpp in Sources */, + 0635782E1EBF43470074E6D4 /* variabletogglewidget.cpp in Sources */, + 0635782F1EBF43470074E6D4 /* baseguiapp.cpp in Sources */, + 063578301EBF43470074E6D4 /* basewindow.cpp in Sources */, + 063578311EBF43470074E6D4 /* callbackaction.cpp in Sources */, + 063578321EBF43470074E6D4 /* childwidgetorganizer.cpp in Sources */, + 063578331EBF43470074E6D4 /* data.cpp in Sources */, + 063578341EBF43470074E6D4 /* dialogcontentstylist.cpp in Sources */, + 063578351EBF43470074E6D4 /* filtereddata.cpp in Sources */, + 063578361EBF43470074E6D4 /* fontlinewrapping.cpp in Sources */, + 063578371EBF43470074E6D4 /* gltextcomposer.cpp in Sources */, + 063578381EBF43470074E6D4 /* gridlayout.cpp in Sources */, + 063578391EBF43470074E6D4 /* guirootwidget.cpp in Sources */, + 0635783A1EBF43470074E6D4 /* guiwidget.cpp in Sources */, + 0635783B1EBF43470074E6D4 /* imageitem.cpp in Sources */, + 0635783C1EBF43470074E6D4 /* item.cpp in Sources */, + 0635783D1EBF43470074E6D4 /* listdata.cpp in Sources */, + 0635783E1EBF43470074E6D4 /* margins.cpp in Sources */, + 0635783F1EBF43470074E6D4 /* painter.cpp in Sources */, + 063578401EBF43470074E6D4 /* persistentstate.cpp in Sources */, + 063578411EBF43470074E6D4 /* proceduralimage.cpp in Sources */, + 063578421EBF43470074E6D4 /* sequentiallayout.cpp in Sources */, + 063578431EBF43470074E6D4 /* signalaction.cpp in Sources */, + 063578441EBF43470074E6D4 /* style.cpp in Sources */, + 063578451EBF43470074E6D4 /* textdrawable.cpp in Sources */, + 063578461EBF43470074E6D4 /* untrapper.cpp in Sources */, + 063578471EBF43470074E6D4 /* vrwindowtransform.cpp in Sources */, + 063578481EBF43470074E6D4 /* windowsystem.cpp in Sources */, + 063578491EBF43470074E6D4 /* windowtransform.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0635784B1EBF43A30074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357A801EBF5F250074E6D4 /* lzss.c in Sources */, + 0635796B1EBF440D0074E6D4 /* library.cpp in Sources */, + 0635796C1EBF440D0074E6D4 /* alias.cpp in Sources */, + 0635796D1EBF440D0074E6D4 /* cmd.cpp in Sources */, + 0635796E1EBF440D0074E6D4 /* exec.cpp in Sources */, + 0635796F1EBF440D0074E6D4 /* knownword.cpp in Sources */, + 063579701EBF440D0074E6D4 /* var.cpp in Sources */, + 063579711EBF440D0074E6D4 /* decoration.cpp in Sources */, + 063579721EBF440D0074E6D4 /* ded.cpp in Sources */, + 063579731EBF440D0074E6D4 /* dedfile.cpp in Sources */, + 063579741EBF440D0074E6D4 /* dedparser.cpp in Sources */, + 063579751EBF440D0074E6D4 /* dedregister.cpp in Sources */, + 063579761EBF440D0074E6D4 /* definition.cpp in Sources */, + 063579771EBF440D0074E6D4 /* episode.cpp in Sources */, + 063579781EBF440D0074E6D4 /* finale.cpp in Sources */, + 063579791EBF440D0074E6D4 /* mapgraphnode.cpp in Sources */, + 0635797A1EBF440D0074E6D4 /* mapinfo.cpp in Sources */, + 0635797B1EBF440D0074E6D4 /* material.cpp in Sources */, + 0635797C1EBF440D0074E6D4 /* model.cpp in Sources */, + 0635797D1EBF440D0074E6D4 /* music.cpp in Sources */, + 0635797E1EBF440D0074E6D4 /* sky.cpp in Sources */, + 0635797F1EBF440D0074E6D4 /* sprite.cpp in Sources */, + 063579801EBF440D0074E6D4 /* state.cpp in Sources */, + 063579811EBF440D0074E6D4 /* thing.cpp in Sources */, + 063579821EBF440D0074E6D4 /* datafile.cpp in Sources */, + 063579831EBF440D0074E6D4 /* datafolder.cpp in Sources */, + 063579841EBF440D0074E6D4 /* file.cpp in Sources */, + 063579851EBF440D0074E6D4 /* filehandle.cpp in Sources */, + 063579861EBF440D0074E6D4 /* fileid.cpp in Sources */, + 063579871EBF440D0074E6D4 /* filetype.cpp in Sources */, + 063579881EBF440D0074E6D4 /* fs_main.cpp in Sources */, + 063579891EBF440D0074E6D4 /* fs_scheme.cpp in Sources */, + 0635798A1EBF440D0074E6D4 /* fs_util.cpp in Sources */, + 0635798B1EBF440D0074E6D4 /* lumpcache.cpp in Sources */, + 0635798C1EBF440D0074E6D4 /* lumpindex.cpp in Sources */, + 0635798D1EBF440D0074E6D4 /* readfile.cpp in Sources */, + 0635798E1EBF440D0074E6D4 /* searchpath.cpp in Sources */, + 0635798F1EBF440D0074E6D4 /* virtualmappings.cpp in Sources */, + 063579901EBF440D0074E6D4 /* wad.cpp in Sources */, + 063579911EBF440D0074E6D4 /* zip.cpp in Sources */, + 063579921EBF440D0074E6D4 /* animgroup.cpp in Sources */, + 063579931EBF440D0074E6D4 /* animgroups.cpp in Sources */, + 063579941EBF440D0074E6D4 /* bundlelinkfeed.cpp in Sources */, + 063579951EBF440D0074E6D4 /* bundles.cpp in Sources */, + 063579961EBF440D0074E6D4 /* colorpalette.cpp in Sources */, + 063579971EBF440D0074E6D4 /* colorpalettes.cpp in Sources */, + 063579981EBF440D0074E6D4 /* composite.cpp in Sources */, + 063579991EBF440D0074E6D4 /* databundle.cpp in Sources */, + 0635799A1EBF440D0074E6D4 /* doomsdaypackage.cpp in Sources */, + 0635799B1EBF440D0074E6D4 /* lumpcatalog.cpp in Sources */, + 0635799C1EBF440D0074E6D4 /* lumpdirectory.cpp in Sources */, + 0635799D1EBF440D0074E6D4 /* m_decomp64.cpp in Sources */, + 0635799E1EBF440D0074E6D4 /* manifest.cpp in Sources */, + 0635799F1EBF440D0074E6D4 /* mapmanifest.cpp in Sources */, + 063579A01EBF440D0074E6D4 /* mapmanifests.cpp in Sources */, + 063579A11EBF440D0074E6D4 /* patch.cpp in Sources */, + 063579A21EBF440D0074E6D4 /* patchname.cpp in Sources */, + 063579A31EBF440D0074E6D4 /* pcx.cpp in Sources */, + 063579A41EBF440D0074E6D4 /* resourceclass.cpp in Sources */, + 063579A51EBF440D0074E6D4 /* resources.cpp in Sources */, + 063579A61EBF440D0074E6D4 /* sprites.cpp in Sources */, + 063579A71EBF440D0074E6D4 /* texture.cpp in Sources */, + 063579A81EBF440D0074E6D4 /* texturemanifest.cpp in Sources */, + 063579A91EBF440D0074E6D4 /* textures.cpp in Sources */, + 063579AA1EBF440D0074E6D4 /* texturescheme.cpp in Sources */, + 063579AB1EBF440D0074E6D4 /* tga.cpp in Sources */, + 063579AC1EBF440D0074E6D4 /* wav.cpp in Sources */, + 063579AD1EBF440D0074E6D4 /* actions.cpp in Sources */, + 063579AE1EBF440D0074E6D4 /* bspnode.cpp in Sources */, + 063579AF1EBF440D0074E6D4 /* detailtexturemateriallayer.cpp in Sources */, + 063579B01EBF440D0074E6D4 /* dmuargs.cpp in Sources */, + 063579B11EBF440D0074E6D4 /* entitydatabase.cpp in Sources */, + 063579B21EBF440D0074E6D4 /* entitydef.cpp in Sources */, + 063579B31EBF440D0074E6D4 /* map.cpp in Sources */, + 063579B41EBF440D0074E6D4 /* mapelement.cpp in Sources */, + 063579B51EBF440D0074E6D4 /* material.cpp in Sources */, + 063579B61EBF440D0074E6D4 /* materialarchive.cpp in Sources */, + 063579B71EBF440D0074E6D4 /* materialmanifest.cpp in Sources */, + 063579B81EBF440D0074E6D4 /* materials.cpp in Sources */, + 063579B91EBF440D0074E6D4 /* materialscheme.cpp in Sources */, + 063579BA1EBF440D0074E6D4 /* mobjthinkerdata.cpp in Sources */, + 063579BB1EBF440D0074E6D4 /* propertyvalue.cpp in Sources */, + 063579BC1EBF440D0074E6D4 /* shinetexturemateriallayer.cpp in Sources */, + 063579BD1EBF440D0074E6D4 /* texturemateriallayer.cpp in Sources */, + 063579BE1EBF440D0074E6D4 /* thinker.cpp in Sources */, + 063579BF1EBF440D0074E6D4 /* thinkerdata.cpp in Sources */, + 063579C01EBF440D0074E6D4 /* world.cpp in Sources */, + 063579C11EBF440D0074E6D4 /* xg.cpp in Sources */, + 063579C21EBF440D0074E6D4 /* abstractsession.cpp in Sources */, + 063579C31EBF440D0074E6D4 /* busymode.cpp in Sources */, + 063579C41EBF440D0074E6D4 /* doomsdayapp.cpp in Sources */, + 063579C51EBF440D0074E6D4 /* dualstring.cpp in Sources */, + 063579C61EBF440D0074E6D4 /* game_init.cpp in Sources */, + 063579C71EBF440D0074E6D4 /* game.cpp in Sources */, + 063579C81EBF440D0074E6D4 /* gameprofiles.cpp in Sources */, + 063579C91EBF440D0074E6D4 /* games.cpp in Sources */, + 063579CA1EBF440D0074E6D4 /* gamestatefolder.cpp in Sources */, + 063579CB1EBF440D0074E6D4 /* help.cpp in Sources */, + 063579CC1EBF440D0074E6D4 /* player.cpp in Sources */, + 063579CD1EBF440D0074E6D4 /* players.cpp in Sources */, + 063579CE1EBF440D0074E6D4 /* plugins.cpp in Sources */, + 063579CF1EBF440D0074E6D4 /* savegames.cpp in Sources */, + 063579D01EBF440D0074E6D4 /* uri.cpp in Sources */, + 063579D11EBF440D0074E6D4 /* urivalue.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357A821EBF61C70074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357AF71EBF62890074E6D4 /* mapspot.cpp in Sources */, + 06357AF61EBF62860074E6D4 /* libgamefw.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357AF91EBF63770074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357B0A1EBF64DE0074E6D4 /* dehreader.cpp in Sources */, + 06357B0C1EBF64DE0074E6D4 /* info.cpp in Sources */, + 06357B091EBF64DE0074E6D4 /* dehreader_util.cpp in Sources */, + 06357B0B1EBF64DE0074E6D4 /* importdeh.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B1E1EBF69C00074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357B2F1EBF6A660074E6D4 /* importudmf.cpp in Sources */, + 06357B301EBF6A660074E6D4 /* udmflex.cpp in Sources */, + 06357B311EBF6A660074E6D4 /* udmfparser.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357B331EBF6EBD0074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357C2A1EBF6F760074E6D4 /* pause.cpp in Sources */, + 06357C0C1EBF6F760074E6D4 /* lineeditwidget.cpp in Sources */, + 06357C071EBF6F760074E6D4 /* cvartextualsliderwidget.cpp in Sources */, + 06357C261EBF6F760074E6D4 /* p_xgfile.cpp in Sources */, + 06357BE51EBF6F760074E6D4 /* system.cpp in Sources */, + 06357C351EBF6F760074E6D4 /* r_common.c in Sources */, + 06357C011EBF6F760074E6D4 /* buttonwidget.cpp in Sources */, + 06357C291EBF6F760074E6D4 /* p_xgsec.cpp in Sources */, + 06357BF51EBF6F760074E6D4 /* groupwidget.cpp in Sources */, + 06357BE81EBF6F760074E6D4 /* g_game.cpp in Sources */, + 06357BE61EBF6F760074E6D4 /* g_defs.cpp in Sources */, + 06357C051EBF6F760074E6D4 /* cvarlineeditwidget.cpp in Sources */, + 06357BEC1EBF6F760074E6D4 /* saveslots.cpp in Sources */, + 06357B661EBF6F5A0074E6D4 /* p_mobj.c in Sources */, + 06357B651EBF6F5A0074E6D4 /* p_maputl.c in Sources */, + 06357C141EBF6F760074E6D4 /* d_netsv.cpp in Sources */, + 06357C081EBF6F760074E6D4 /* cvartogglewidget.cpp in Sources */, + 06357C311EBF6F760074E6D4 /* p_iterlist.c in Sources */, + 06357C381EBF6F760074E6D4 /* fi_lib.cpp in Sources */, + 06357C301EBF6F760074E6D4 /* hu_pspr.c in Sources */, + 06357B621EBF6F5A0074E6D4 /* m_random.c in Sources */, + 06357BFE1EBF6F760074E6D4 /* readyitemwidget.cpp in Sources */, + 06357C3F1EBF6F760074E6D4 /* hu_msg.cpp in Sources */, + 06357C401EBF6F760074E6D4 /* hu_stuff.cpp in Sources */, + 06357BE91EBF6F760074E6D4 /* g_update.cpp in Sources */, + 06357BF21EBF6F760074E6D4 /* chatwidget.cpp in Sources */, + 06357C3E1EBF6F760074E6D4 /* hu_menu.cpp in Sources */, + 06357BEE1EBF6F760074E6D4 /* hudwidget.cpp in Sources */, + 06357C361EBF6F760074E6D4 /* x_hair.c in Sources */, + 06357C0F1EBF6F760074E6D4 /* rectwidget.cpp in Sources */, + 06357C441EBF6F760074E6D4 /* p_saveio.cpp in Sources */, + 06357C211EBF6F760074E6D4 /* p_scroll.cpp in Sources */, + 06357B611EBF6F5A0074E6D4 /* acfnlink.c in Sources */, + 06357C221EBF6F760074E6D4 /* p_sound.cpp in Sources */, + 06357BED1EBF6F760074E6D4 /* automapstyle.cpp in Sources */, + 06357BF01EBF6F760074E6D4 /* automapwidget.cpp in Sources */, + 06357B6A1EBF6F5A0074E6D4 /* tables.c in Sources */, + 06357BF91EBF6F760074E6D4 /* keyswidget.cpp in Sources */, + 06357B721EBF6F5A0074E6D4 /* intermission.cpp in Sources */, + 06357C2F1EBF6F760074E6D4 /* common.c in Sources */, + 06357C181EBF6F760074E6D4 /* mobj.cpp in Sources */, + 06357C1E1EBF6F760074E6D4 /* p_mapsetup.cpp in Sources */, + 06357C2C1EBF6F760074E6D4 /* polyobjs.cpp in Sources */, + 06357BF41EBF6F760074E6D4 /* fragswidget.cpp in Sources */, + 06357B6B1EBF6F5A0074E6D4 /* bossbrain.cpp in Sources */, + 06357BEA1EBF6F760074E6D4 /* gamerules.cpp in Sources */, + 06357B741EBF6F5A0074E6D4 /* p_lights.cpp in Sources */, + 06357C371EBF6F760074E6D4 /* animdefs.cpp in Sources */, + 06357C041EBF6F760074E6D4 /* cvarinlinelistwidget.cpp in Sources */, + 06357C3B1EBF6F760074E6D4 /* hexlex.cpp in Sources */, + 06357C3D1EBF6F760074E6D4 /* hu_lib.cpp in Sources */, + 06357B6F1EBF6F5A0074E6D4 /* d_main.cpp in Sources */, + 06357B681EBF6F5A0074E6D4 /* p_setup.c in Sources */, + 06357B701EBF6F5A0074E6D4 /* d_refresh.cpp in Sources */, + 06357B6C1EBF6F5A0074E6D4 /* d_api.cpp in Sources */, + 06357B5E1EBF6F5A0074E6D4 /* healthiconwidget.cpp in Sources */, + 06357BFF1EBF6F760074E6D4 /* secretswidget.cpp in Sources */, + 06357B6E1EBF6F5A0074E6D4 /* d_items.cpp in Sources */, + 06357C121EBF6F760074E6D4 /* d_net.cpp in Sources */, + 06357C1D1EBF6F760074E6D4 /* p_map.cpp in Sources */, + 06357BF71EBF6F760074E6D4 /* itemswidget.cpp in Sources */, + 06357B5D1EBF6F5A0074E6D4 /* facewidget.cpp in Sources */, + 06357C101EBF6F760074E6D4 /* sliderwidget.cpp in Sources */, + 06357C1A1EBF6F760074E6D4 /* p_ceiling.cpp in Sources */, + 06357B761EBF6F5A0074E6D4 /* st_stuff.cpp in Sources */, + 06357BE21EBF6F760074E6D4 /* interpreter.cpp in Sources */, + 06357C2D1EBF6F760074E6D4 /* thingarchive.cpp in Sources */, + 06357C171EBF6F760074E6D4 /* mapstatewriter.cpp in Sources */, + 06357C0D1EBF6F760074E6D4 /* listwidget.cpp in Sources */, + 06357C411EBF6F760074E6D4 /* m_ctrl.cpp in Sources */, + 06357C241EBF6F760074E6D4 /* p_switch.cpp in Sources */, + 06357C161EBF6F760074E6D4 /* mapstatereader.cpp in Sources */, + 06357C251EBF6F760074E6D4 /* p_tick.cpp in Sources */, + 06357BFD1EBF6F760074E6D4 /* readyammowidget.cpp in Sources */, + 06357B691EBF6F5A0074E6D4 /* p_telept.c in Sources */, + 06357BF11EBF6F760074E6D4 /* chainwidget.cpp in Sources */, + 06357B5C1EBF6F5A0074E6D4 /* armoriconwidget.cpp in Sources */, + 06357BE71EBF6F760074E6D4 /* g_eventsequence.cpp in Sources */, + 06357C031EBF6F760074E6D4 /* cvarcoloreditwidget.cpp in Sources */, + 06357C271EBF6F760074E6D4 /* p_xgline.cpp in Sources */, + 06357C1C1EBF6F760074E6D4 /* p_floor.cpp in Sources */, + 06357C1B1EBF6F760074E6D4 /* p_door.cpp in Sources */, + 06357C0A1EBF6F760074E6D4 /* inputbindingwidget.cpp in Sources */, + 06357BF81EBF6F760074E6D4 /* keyslotwidget.cpp in Sources */, + 06357B641EBF6F5A0074E6D4 /* p_inter.c in Sources */, + 06357C191EBF6F760074E6D4 /* p_actor.cpp in Sources */, + 06357C2E1EBF6F760074E6D4 /* thinkerinfo.cpp in Sources */, + 06357BFB1EBF6F760074E6D4 /* playerlogwidget.cpp in Sources */, + 06357B751EBF6F5A0074E6D4 /* p_spec.cpp in Sources */, + 06357BE41EBF6F760074E6D4 /* script.cpp in Sources */, + 06357C151EBF6F760074E6D4 /* dmu_lib.cpp in Sources */, + 06357B631EBF6F5A0074E6D4 /* p_enemy.c in Sources */, + 06357C061EBF6F760074E6D4 /* cvarsliderwidget.cpp in Sources */, + 06357C201EBF6F760074E6D4 /* p_plat.cpp in Sources */, + 06357C021EBF6F760074E6D4 /* coloreditwidget.cpp in Sources */, + 06357C0E1EBF6F760074E6D4 /* mobjpreviewwidget.cpp in Sources */, + 06357C3A1EBF6F760074E6D4 /* gl_drawpatch.cpp in Sources */, + 06357C391EBF6F760074E6D4 /* g_controls.cpp in Sources */, + 06357C001EBF6F760074E6D4 /* page.cpp in Sources */, + 06357C3C1EBF6F760074E6D4 /* hu_inventory.cpp in Sources */, + 06357C0B1EBF6F760074E6D4 /* labelwidget.cpp in Sources */, + 06357C281EBF6F760074E6D4 /* p_xgsave.cpp in Sources */, + 06357C231EBF6F760074E6D4 /* p_start.cpp in Sources */, + 06357C1F1EBF6F760074E6D4 /* p_mapspec.cpp in Sources */, + 06357B601EBF6F5A0074E6D4 /* weaponslotwidget.cpp in Sources */, + 06357BEF1EBF6F760074E6D4 /* armorwidget.cpp in Sources */, + 06357C2B1EBF6F760074E6D4 /* player.cpp in Sources */, + 06357C331EBF6F760074E6D4 /* p_user.c in Sources */, + 06357BFA1EBF6F760074E6D4 /* killswidget.cpp in Sources */, + 06357BEB1EBF6F760074E6D4 /* gamesession.cpp in Sources */, + 06357B5B1EBF6F5A0074E6D4 /* ammowidget.cpp in Sources */, + 06357B5F1EBF6F5A0074E6D4 /* maxammowidget.cpp in Sources */, + 06357C341EBF6F760074E6D4 /* p_view.c in Sources */, + 06357BFC1EBF6F760074E6D4 /* readyammoiconwidget.cpp in Sources */, + 06357C091EBF6F760074E6D4 /* inlinelistwidget.cpp in Sources */, + 06357C421EBF6F760074E6D4 /* p_inventory.cpp in Sources */, + 06357B671EBF6F5A0074E6D4 /* p_pspr.c in Sources */, + 06357B731EBF6F5A0074E6D4 /* m_cheat.cpp in Sources */, + 06357BE31EBF6F760074E6D4 /* module.cpp in Sources */, + 06357C111EBF6F760074E6D4 /* widget.cpp in Sources */, + 06357C431EBF6F760074E6D4 /* p_saveg.cpp in Sources */, + 06357BF31EBF6F760074E6D4 /* flightwidget.cpp in Sources */, + 06357BF61EBF6F760074E6D4 /* healthwidget.cpp in Sources */, + 06357C131EBF6F760074E6D4 /* d_netcl.cpp in Sources */, + 06357C321EBF6F760074E6D4 /* p_terraintype.c in Sources */, + 06357B711EBF6F5A0074E6D4 /* doomv9mapstatereader.cpp in Sources */, + 06357B6D1EBF6F5A0074E6D4 /* d_console.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357C461EBF70A20074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357D141EBF70F00074E6D4 /* widget.cpp in Sources */, + 06357D5E1EBF71330074E6D4 /* p_lights.cpp in Sources */, + 06357CF31EBF70E10074E6D4 /* p_sound.cpp in Sources */, + 06357CFA1EBF70E10074E6D4 /* p_xgsec.cpp in Sources */, + 06357CD01EBF70D80074E6D4 /* common.c in Sources */, + 06357D201EBF70FA0074E6D4 /* keyslotwidget.cpp in Sources */, + 06357D291EBF70FE0074E6D4 /* g_eventsequence.cpp in Sources */, + 06357D4E1EBF71330074E6D4 /* p_enemy.c in Sources */, + 06357CDE1EBF70D80074E6D4 /* hu_lib.cpp in Sources */, + 06357D581EBF71330074E6D4 /* h_items.cpp in Sources */, + 06357D0D1EBF70F00074E6D4 /* inputbindingwidget.cpp in Sources */, + 06357D2A1EBF70FE0074E6D4 /* g_game.cpp in Sources */, + 06357D2C1EBF70FE0074E6D4 /* gamerules.cpp in Sources */, + 06357D241EBF70FA0074E6D4 /* readyammoiconwidget.cpp in Sources */, + 06357D1F1EBF70FA0074E6D4 /* itemswidget.cpp in Sources */, + 06357CD21EBF70D80074E6D4 /* p_iterlist.c in Sources */, + 06357CF91EBF70E10074E6D4 /* p_xgsave.cpp in Sources */, + 06357D321EBF71030074E6D4 /* system.cpp in Sources */, + 06357D031EBF70EB0074E6D4 /* page.cpp in Sources */, + 06357D151EBF70F50074E6D4 /* automapstyle.cpp in Sources */, + 06357CD31EBF70D80074E6D4 /* p_terraintype.c in Sources */, + 06357CD41EBF70D80074E6D4 /* p_user.c in Sources */, + 06357D271EBF70FA0074E6D4 /* secretswidget.cpp in Sources */, + 06357D281EBF70FE0074E6D4 /* g_defs.cpp in Sources */, + 06357D2F1EBF71030074E6D4 /* interpreter.cpp in Sources */, + 06357CF81EBF70E10074E6D4 /* p_xgline.cpp in Sources */, + 06357D011EBF70E60074E6D4 /* d_netcl.cpp in Sources */, + 06357CE71EBF70E00074E6D4 /* mapstatereader.cpp in Sources */, + 06357D2B1EBF70FE0074E6D4 /* g_update.cpp in Sources */, + 06357CEE1EBF70E10074E6D4 /* p_map.cpp in Sources */, + 06357D601EBF71330074E6D4 /* st_stuff.cpp in Sources */, + 06357CFC1EBF70E10074E6D4 /* player.cpp in Sources */, + 06357CF41EBF70E10074E6D4 /* p_start.cpp in Sources */, + 06357D081EBF70F00074E6D4 /* cvarlineeditwidget.cpp in Sources */, + 06357CE11EBF70D80074E6D4 /* hu_stuff.cpp in Sources */, + 06357CE81EBF70E00074E6D4 /* mapstatewriter.cpp in Sources */, + 06357CF21EBF70E10074E6D4 /* p_scroll.cpp in Sources */, + 06357CEA1EBF70E10074E6D4 /* p_actor.cpp in Sources */, + 06357D1A1EBF70FA0074E6D4 /* chatwidget.cpp in Sources */, + 06357D0F1EBF70F00074E6D4 /* lineeditwidget.cpp in Sources */, + 06357CDC1EBF70D80074E6D4 /* hexlex.cpp in Sources */, + 06357D501EBF71330074E6D4 /* p_maputl.c in Sources */, + 06357CF11EBF70E10074E6D4 /* p_plat.cpp in Sources */, + 06357CD71EBF70D80074E6D4 /* x_hair.c in Sources */, + 06357D021EBF70E60074E6D4 /* d_netsv.cpp in Sources */, + 06357D181EBF70FA0074E6D4 /* automapwidget.cpp in Sources */, + 06357CE21EBF70D80074E6D4 /* m_ctrl.cpp in Sources */, + 06357D1D1EBF70FA0074E6D4 /* groupwidget.cpp in Sources */, + 06357CFB1EBF70E10074E6D4 /* pause.cpp in Sources */, + 06357D001EBF70E60074E6D4 /* d_net.cpp in Sources */, + 06357D0B1EBF70F00074E6D4 /* cvartogglewidget.cpp in Sources */, + 06357CF61EBF70E10074E6D4 /* p_tick.cpp in Sources */, + 06357D121EBF70F00074E6D4 /* rectwidget.cpp in Sources */, + 06357D5D1EBF71330074E6D4 /* m_cheat.cpp in Sources */, + 06357D531EBF71330074E6D4 /* p_setup.c in Sources */, + 06357CEB1EBF70E10074E6D4 /* p_ceiling.cpp in Sources */, + 06357D041EBF70F00074E6D4 /* buttonwidget.cpp in Sources */, + 06357D561EBF71330074E6D4 /* h_api.cpp in Sources */, + 06357D1C1EBF70FA0074E6D4 /* fragswidget.cpp in Sources */, + 06357D221EBF70FA0074E6D4 /* killswidget.cpp in Sources */, + 06357D051EBF70F00074E6D4 /* coloreditwidget.cpp in Sources */, + 06357CE31EBF70D80074E6D4 /* p_inventory.cpp in Sources */, + 06357D511EBF71330074E6D4 /* p_mobj.c in Sources */, + 06357D131EBF70F00074E6D4 /* sliderwidget.cpp in Sources */, + 06357D0A1EBF70F00074E6D4 /* cvartextualsliderwidget.cpp in Sources */, + 06357CF01EBF70E10074E6D4 /* p_mapspec.cpp in Sources */, + 06357D311EBF71030074E6D4 /* script.cpp in Sources */, + 06357D4F1EBF71330074E6D4 /* p_inter.c in Sources */, + 06357CDB1EBF70D80074E6D4 /* gl_drawpatch.cpp in Sources */, + 06357CED1EBF70E10074E6D4 /* p_floor.cpp in Sources */, + 06357D061EBF70F00074E6D4 /* cvarcoloreditwidget.cpp in Sources */, + 06357D5C1EBF71330074E6D4 /* intermission.cpp in Sources */, + 06357CEC1EBF70E10074E6D4 /* p_door.cpp in Sources */, + 06357D261EBF70FA0074E6D4 /* readyitemwidget.cpp in Sources */, + 06357D251EBF70FA0074E6D4 /* readyammowidget.cpp in Sources */, + 06357D1B1EBF70FA0074E6D4 /* flightwidget.cpp in Sources */, + 06357D171EBF70FA0074E6D4 /* armorwidget.cpp in Sources */, + 06357CD11EBF70D80074E6D4 /* hu_pspr.c in Sources */, + 06357CD81EBF70D80074E6D4 /* animdefs.cpp in Sources */, + 06357D591EBF71330074E6D4 /* h_main.cpp in Sources */, + 06357CDD1EBF70D80074E6D4 /* hu_inventory.cpp in Sources */, + 06357CF71EBF70E10074E6D4 /* p_xgfile.cpp in Sources */, + 06357D2E1EBF70FE0074E6D4 /* saveslots.cpp in Sources */, + 06357CFF1EBF70E10074E6D4 /* thinkerinfo.cpp in Sources */, + 06357CE41EBF70D80074E6D4 /* p_saveg.cpp in Sources */, + 06357D1E1EBF70FA0074E6D4 /* healthwidget.cpp in Sources */, + 06357CD61EBF70D80074E6D4 /* r_common.c in Sources */, + 06357D0E1EBF70F00074E6D4 /* labelwidget.cpp in Sources */, + 06357CD91EBF70D80074E6D4 /* fi_lib.cpp in Sources */, + 06357D071EBF70F00074E6D4 /* cvarinlinelistwidget.cpp in Sources */, + 06357CE61EBF70E00074E6D4 /* dmu_lib.cpp in Sources */, + 06357D521EBF71330074E6D4 /* p_pspr.c in Sources */, + 06357CDF1EBF70D80074E6D4 /* hu_menu.cpp in Sources */, + 06357D4C1EBF71320074E6D4 /* acfnlink.c in Sources */, + 06357D571EBF71330074E6D4 /* h_console.cpp in Sources */, + 06357D2D1EBF70FE0074E6D4 /* gamesession.cpp in Sources */, + 06357D191EBF70FA0074E6D4 /* chainwidget.cpp in Sources */, + 06357CD51EBF70D80074E6D4 /* p_view.c in Sources */, + 06357CFD1EBF70E10074E6D4 /* polyobjs.cpp in Sources */, + 06357CF51EBF70E10074E6D4 /* p_switch.cpp in Sources */, + 06357D0C1EBF70F00074E6D4 /* inlinelistwidget.cpp in Sources */, + 06357CFE1EBF70E10074E6D4 /* thingarchive.cpp in Sources */, + 06357D111EBF70F00074E6D4 /* mobjpreviewwidget.cpp in Sources */, + 06357D5A1EBF71330074E6D4 /* h_refresh.cpp in Sources */, + 06357D301EBF71030074E6D4 /* module.cpp in Sources */, + 06357D551EBF71330074E6D4 /* tables.c in Sources */, + 06357D4B1EBF71320074E6D4 /* tomeofpowerwidget.cpp in Sources */, + 06357CE51EBF70D80074E6D4 /* p_saveio.cpp in Sources */, + 06357CE91EBF70E10074E6D4 /* mobj.cpp in Sources */, + 06357CEF1EBF70E10074E6D4 /* p_mapsetup.cpp in Sources */, + 06357D161EBF70F50074E6D4 /* hudwidget.cpp in Sources */, + 06357CE01EBF70D80074E6D4 /* hu_msg.cpp in Sources */, + 06357D231EBF70FA0074E6D4 /* playerlogwidget.cpp in Sources */, + 06357D541EBF71330074E6D4 /* p_telept.c in Sources */, + 06357D091EBF70F00074E6D4 /* cvarsliderwidget.cpp in Sources */, + 06357D4D1EBF71320074E6D4 /* m_random.c in Sources */, + 06357D101EBF70F00074E6D4 /* listwidget.cpp in Sources */, + 06357D5B1EBF71330074E6D4 /* hereticv13mapstatereader.cpp in Sources */, + 06357D5F1EBF71330074E6D4 /* p_spec.cpp in Sources */, + 06357CDA1EBF70D80074E6D4 /* g_controls.cpp in Sources */, + 06357D211EBF70FA0074E6D4 /* keyswidget.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357D621EBF728D0074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357D631EBF728D0074E6D4 /* widget.cpp in Sources */, + 06357D651EBF728D0074E6D4 /* p_sound.cpp in Sources */, + 06357D661EBF728D0074E6D4 /* p_xgsec.cpp in Sources */, + 06357D671EBF728D0074E6D4 /* common.c in Sources */, + 06357D681EBF728D0074E6D4 /* keyslotwidget.cpp in Sources */, + 06357D691EBF728D0074E6D4 /* g_eventsequence.cpp in Sources */, + 06357E431EBF73790074E6D4 /* p_waggle.cpp in Sources */, + 06357E311EBF73790074E6D4 /* p_enemy.c in Sources */, + 06357D6B1EBF728D0074E6D4 /* hu_lib.cpp in Sources */, + 06357D6D1EBF728D0074E6D4 /* inputbindingwidget.cpp in Sources */, + 06357D6E1EBF728D0074E6D4 /* g_game.cpp in Sources */, + 06357E501EBF73800074E6D4 /* servantwidget.cpp in Sources */, + 06357D6F1EBF728D0074E6D4 /* gamerules.cpp in Sources */, + 06357D701EBF728D0074E6D4 /* readyammoiconwidget.cpp in Sources */, + 06357D711EBF728D0074E6D4 /* itemswidget.cpp in Sources */, + 06357E4E1EBF73800074E6D4 /* greenmanavialwidget.cpp in Sources */, + 06357D721EBF728D0074E6D4 /* p_iterlist.c in Sources */, + 06357D731EBF728D0074E6D4 /* p_xgsave.cpp in Sources */, + 06357D741EBF728D0074E6D4 /* system.cpp in Sources */, + 06357D751EBF728D0074E6D4 /* page.cpp in Sources */, + 06357E511EBF73800074E6D4 /* weaponpieceswidget.cpp in Sources */, + 06357D761EBF728D0074E6D4 /* automapstyle.cpp in Sources */, + 06357D771EBF728D0074E6D4 /* p_terraintype.c in Sources */, + 06357D781EBF728D0074E6D4 /* p_user.c in Sources */, + 06357D791EBF728D0074E6D4 /* secretswidget.cpp in Sources */, + 06357E3D1EBF73790074E6D4 /* intermission.cpp in Sources */, + 06357E461EBF73790074E6D4 /* x_api.cpp in Sources */, + 06357D7A1EBF728D0074E6D4 /* g_defs.cpp in Sources */, + 06357D7B1EBF728D0074E6D4 /* interpreter.cpp in Sources */, + 06357D7C1EBF728D0074E6D4 /* p_xgline.cpp in Sources */, + 06357D7D1EBF728D0074E6D4 /* d_netcl.cpp in Sources */, + 06357D7E1EBF728D0074E6D4 /* mapstatereader.cpp in Sources */, + 06357E3A1EBF73790074E6D4 /* h2_main.cpp in Sources */, + 06357D7F1EBF728D0074E6D4 /* g_update.cpp in Sources */, + 06357E4D1EBF73800074E6D4 /* greenmanaiconwidget.cpp in Sources */, + 06357D801EBF728D0074E6D4 /* p_map.cpp in Sources */, + 06357D821EBF728D0074E6D4 /* player.cpp in Sources */, + 06357E3F1EBF73790074E6D4 /* m_cheat.cpp in Sources */, + 06357D831EBF728D0074E6D4 /* p_start.cpp in Sources */, + 06357D841EBF728D0074E6D4 /* cvarlineeditwidget.cpp in Sources */, + 06357D851EBF728D0074E6D4 /* hu_stuff.cpp in Sources */, + 06357D861EBF728D0074E6D4 /* mapstatewriter.cpp in Sources */, + 06357D871EBF728D0074E6D4 /* p_scroll.cpp in Sources */, + 06357D881EBF728D0074E6D4 /* p_actor.cpp in Sources */, + 06357E491EBF73800074E6D4 /* bluemanavialwidget.cpp in Sources */, + 06357D891EBF728D0074E6D4 /* chatwidget.cpp in Sources */, + 06357D8A1EBF728D0074E6D4 /* lineeditwidget.cpp in Sources */, + 06357D8B1EBF728D0074E6D4 /* hexlex.cpp in Sources */, + 06357E331EBF73790074E6D4 /* p_maputl.c in Sources */, + 06357D8D1EBF728D0074E6D4 /* p_plat.cpp in Sources */, + 06357E441EBF73790074E6D4 /* sn_sonix.cpp in Sources */, + 06357D8E1EBF728D0074E6D4 /* x_hair.c in Sources */, + 06357D8F1EBF728D0074E6D4 /* d_netsv.cpp in Sources */, + 06357D901EBF728D0074E6D4 /* automapwidget.cpp in Sources */, + 06357D911EBF728D0074E6D4 /* m_ctrl.cpp in Sources */, + 06357D921EBF728D0074E6D4 /* groupwidget.cpp in Sources */, + 06357D931EBF728D0074E6D4 /* pause.cpp in Sources */, + 06357D941EBF728D0074E6D4 /* d_net.cpp in Sources */, + 06357D951EBF728D0074E6D4 /* cvartogglewidget.cpp in Sources */, + 06357D961EBF728D0074E6D4 /* p_tick.cpp in Sources */, + 06357E3C1EBF73790074E6D4 /* hrefresh.cpp in Sources */, + 06357D971EBF728D0074E6D4 /* rectwidget.cpp in Sources */, + 06357E361EBF73790074E6D4 /* p_setup.c in Sources */, + 06357D9A1EBF728D0074E6D4 /* p_ceiling.cpp in Sources */, + 06357D9B1EBF728D0074E6D4 /* buttonwidget.cpp in Sources */, + 06357E4B1EBF73800074E6D4 /* bootswidget.cpp in Sources */, + 06357D9D1EBF728D0074E6D4 /* fragswidget.cpp in Sources */, + 06357D9E1EBF728D0074E6D4 /* killswidget.cpp in Sources */, + 06357D9F1EBF728D0074E6D4 /* coloreditwidget.cpp in Sources */, + 06357E3B1EBF73790074E6D4 /* hconsole.cpp in Sources */, + 06357DA01EBF728D0074E6D4 /* p_inventory.cpp in Sources */, + 06357E341EBF73790074E6D4 /* p_mobj.c in Sources */, + 06357DA21EBF728D0074E6D4 /* sliderwidget.cpp in Sources */, + 06357DA31EBF728D0074E6D4 /* cvartextualsliderwidget.cpp in Sources */, + 06357DA41EBF728D0074E6D4 /* p_mapspec.cpp in Sources */, + 06357DA51EBF728D0074E6D4 /* script.cpp in Sources */, + 06357E451EBF73790074E6D4 /* st_stuff.cpp in Sources */, + 06357E321EBF73790074E6D4 /* p_inter.c in Sources */, + 06357DA71EBF728D0074E6D4 /* gl_drawpatch.cpp in Sources */, + 06357DA81EBF728D0074E6D4 /* p_floor.cpp in Sources */, + 06357DA91EBF728D0074E6D4 /* cvarcoloreditwidget.cpp in Sources */, + 06357E4A1EBF73800074E6D4 /* bluemanawidget.cpp in Sources */, + 06357DAB1EBF728D0074E6D4 /* p_door.cpp in Sources */, + 06357DAC1EBF728D0074E6D4 /* readyitemwidget.cpp in Sources */, + 06357E4C1EBF73800074E6D4 /* defensewidget.cpp in Sources */, + 06357DAD1EBF728D0074E6D4 /* readyammowidget.cpp in Sources */, + 06357DAE1EBF728D0074E6D4 /* flightwidget.cpp in Sources */, + 06357DAF1EBF728D0074E6D4 /* armorwidget.cpp in Sources */, + 06357DB01EBF728D0074E6D4 /* hu_pspr.c in Sources */, + 06357DB11EBF728D0074E6D4 /* animdefs.cpp in Sources */, + 06357DB31EBF728D0074E6D4 /* hu_inventory.cpp in Sources */, + 06357DB41EBF728D0074E6D4 /* p_xgfile.cpp in Sources */, + 06357DB51EBF728D0074E6D4 /* saveslots.cpp in Sources */, + 06357DB61EBF728D0074E6D4 /* thinkerinfo.cpp in Sources */, + 06357DB71EBF728D0074E6D4 /* p_saveg.cpp in Sources */, + 06357E521EBF73800074E6D4 /* worldtimewidget.cpp in Sources */, + 06357DB81EBF728D0074E6D4 /* healthwidget.cpp in Sources */, + 06357DB91EBF728D0074E6D4 /* r_common.c in Sources */, + 06357DBA1EBF728D0074E6D4 /* labelwidget.cpp in Sources */, + 06357E3E1EBF73790074E6D4 /* lightninganimator.cpp in Sources */, + 06357DBB1EBF728D0074E6D4 /* fi_lib.cpp in Sources */, + 06357DBC1EBF728D0074E6D4 /* cvarinlinelistwidget.cpp in Sources */, + 06357DBD1EBF728D0074E6D4 /* dmu_lib.cpp in Sources */, + 06357E391EBF73790074E6D4 /* tables.c in Sources */, + 06357E351EBF73790074E6D4 /* p_pspr.c in Sources */, + 06357E471EBF73800074E6D4 /* armoriconswidget.cpp in Sources */, + 06357DBF1EBF728D0074E6D4 /* hu_menu.cpp in Sources */, + 06357E2F1EBF73790074E6D4 /* acfnlink.c in Sources */, + 06357DC21EBF728D0074E6D4 /* gamesession.cpp in Sources */, + 06357DC31EBF728D0074E6D4 /* chainwidget.cpp in Sources */, + 06357DC41EBF728D0074E6D4 /* p_view.c in Sources */, + 06357DC51EBF728D0074E6D4 /* polyobjs.cpp in Sources */, + 06357DC61EBF728D0074E6D4 /* p_switch.cpp in Sources */, + 06357E411EBF73790074E6D4 /* p_pillar.cpp in Sources */, + 06357DC71EBF728D0074E6D4 /* inlinelistwidget.cpp in Sources */, + 06357DC81EBF728D0074E6D4 /* thingarchive.cpp in Sources */, + 06357DC91EBF728D0074E6D4 /* mobjpreviewwidget.cpp in Sources */, + 06357DCB1EBF728D0074E6D4 /* module.cpp in Sources */, + 06357DCE1EBF728D0074E6D4 /* p_saveio.cpp in Sources */, + 06357DCF1EBF728D0074E6D4 /* mobj.cpp in Sources */, + 06357DD01EBF728D0074E6D4 /* p_mapsetup.cpp in Sources */, + 06357DD11EBF728D0074E6D4 /* hudwidget.cpp in Sources */, + 06357E2E1EBF73790074E6D4 /* a_action.c in Sources */, + 06357DD21EBF728D0074E6D4 /* hu_msg.cpp in Sources */, + 06357DD31EBF728D0074E6D4 /* playerlogwidget.cpp in Sources */, + 06357E371EBF73790074E6D4 /* p_telept.c in Sources */, + 06357DD51EBF728D0074E6D4 /* cvarsliderwidget.cpp in Sources */, + 06357E301EBF73790074E6D4 /* m_random.c in Sources */, + 06357E481EBF73800074E6D4 /* bluemanaiconwidget.cpp in Sources */, + 06357DD71EBF728D0074E6D4 /* listwidget.cpp in Sources */, + 06357E381EBF73790074E6D4 /* p_things.c in Sources */, + 06357DDA1EBF728D0074E6D4 /* g_controls.cpp in Sources */, + 06357E421EBF73790074E6D4 /* p_spec.cpp in Sources */, + 06357DDB1EBF728D0074E6D4 /* keyswidget.cpp in Sources */, + 06357E401EBF73790074E6D4 /* p_lights.cpp in Sources */, + 06357E4F1EBF73800074E6D4 /* greenmanawidget.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357E681EBF76120074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357E691EBF76120074E6D4 /* pause.cpp in Sources */, + 06357F341EBF769C0074E6D4 /* p_lights.cpp in Sources */, + 06357E6A1EBF76120074E6D4 /* lineeditwidget.cpp in Sources */, + 06357E6B1EBF76120074E6D4 /* cvartextualsliderwidget.cpp in Sources */, + 06357E6C1EBF76120074E6D4 /* p_xgfile.cpp in Sources */, + 06357E6D1EBF76120074E6D4 /* system.cpp in Sources */, + 06357E6E1EBF76120074E6D4 /* r_common.c in Sources */, + 06357E6F1EBF76120074E6D4 /* buttonwidget.cpp in Sources */, + 06357E701EBF76120074E6D4 /* p_xgsec.cpp in Sources */, + 06357E711EBF76120074E6D4 /* groupwidget.cpp in Sources */, + 06357E721EBF76120074E6D4 /* g_game.cpp in Sources */, + 06357E731EBF76120074E6D4 /* g_defs.cpp in Sources */, + 06357E741EBF76120074E6D4 /* cvarlineeditwidget.cpp in Sources */, + 06357E751EBF76120074E6D4 /* saveslots.cpp in Sources */, + 06357F241EBF769C0074E6D4 /* m_random.c in Sources */, + 06357E781EBF76120074E6D4 /* d_netsv.cpp in Sources */, + 06357F211EBF76880074E6D4 /* armoriconwidget.cpp in Sources */, + 06357E791EBF76120074E6D4 /* cvartogglewidget.cpp in Sources */, + 06357E7A1EBF76120074E6D4 /* p_iterlist.c in Sources */, + 06357E7B1EBF76120074E6D4 /* fi_lib.cpp in Sources */, + 06357E7C1EBF76120074E6D4 /* hu_pspr.c in Sources */, + 06357E7E1EBF76120074E6D4 /* readyitemwidget.cpp in Sources */, + 06357E7F1EBF76120074E6D4 /* hu_msg.cpp in Sources */, + 06357E801EBF76120074E6D4 /* hu_stuff.cpp in Sources */, + 06357E811EBF76120074E6D4 /* g_update.cpp in Sources */, + 06357E821EBF76120074E6D4 /* chatwidget.cpp in Sources */, + 06357E831EBF76120074E6D4 /* hu_menu.cpp in Sources */, + 06357F2A1EBF769C0074E6D4 /* p_setup.c in Sources */, + 06357E841EBF76120074E6D4 /* hudwidget.cpp in Sources */, + 06357E851EBF76120074E6D4 /* x_hair.c in Sources */, + 06357F361EBF769C0074E6D4 /* st_stuff.cpp in Sources */, + 06357E861EBF76120074E6D4 /* rectwidget.cpp in Sources */, + 06357E871EBF76120074E6D4 /* p_saveio.cpp in Sources */, + 06357E881EBF76120074E6D4 /* p_scroll.cpp in Sources */, + 06357E8A1EBF76120074E6D4 /* p_sound.cpp in Sources */, + 06357F221EBF76880074E6D4 /* healthiconwidget.cpp in Sources */, + 06357E8B1EBF76120074E6D4 /* automapstyle.cpp in Sources */, + 06357E8C1EBF76120074E6D4 /* automapwidget.cpp in Sources */, + 06357F2D1EBF769C0074E6D4 /* d_console.cpp in Sources */, + 06357E8E1EBF76120074E6D4 /* keyswidget.cpp in Sources */, + 06357E901EBF76120074E6D4 /* common.c in Sources */, + 06357E911EBF76120074E6D4 /* mobj.cpp in Sources */, + 06357E921EBF76120074E6D4 /* p_mapsetup.cpp in Sources */, + 06357E931EBF76120074E6D4 /* polyobjs.cpp in Sources */, + 06357E941EBF76120074E6D4 /* fragswidget.cpp in Sources */, + 06357E961EBF76120074E6D4 /* gamerules.cpp in Sources */, + 06357E981EBF76120074E6D4 /* animdefs.cpp in Sources */, + 06357E991EBF76120074E6D4 /* cvarinlinelistwidget.cpp in Sources */, + 06357F231EBF769C0074E6D4 /* acfnlink.c in Sources */, + 06357E9A1EBF76120074E6D4 /* hexlex.cpp in Sources */, + 06357E9B1EBF76120074E6D4 /* hu_lib.cpp in Sources */, + 06357EA11EBF76120074E6D4 /* secretswidget.cpp in Sources */, + 06357EA31EBF76120074E6D4 /* d_net.cpp in Sources */, + 06357F331EBF769C0074E6D4 /* m_cheat.cpp in Sources */, + 06357EA41EBF76120074E6D4 /* p_map.cpp in Sources */, + 06357EA51EBF76120074E6D4 /* itemswidget.cpp in Sources */, + 06357F2B1EBF769C0074E6D4 /* p_telept.c in Sources */, + 06357EA71EBF76120074E6D4 /* sliderwidget.cpp in Sources */, + 06357EA81EBF76120074E6D4 /* p_ceiling.cpp in Sources */, + 06357EAA1EBF76120074E6D4 /* interpreter.cpp in Sources */, + 06357EAB1EBF76120074E6D4 /* thingarchive.cpp in Sources */, + 06357EAC1EBF76120074E6D4 /* mapstatewriter.cpp in Sources */, + 06357EAD1EBF76120074E6D4 /* listwidget.cpp in Sources */, + 06357EAE1EBF76120074E6D4 /* m_ctrl.cpp in Sources */, + 06357EAF1EBF76120074E6D4 /* p_switch.cpp in Sources */, + 06357EB01EBF76120074E6D4 /* mapstatereader.cpp in Sources */, + 06357F2F1EBF769C0074E6D4 /* d_main.cpp in Sources */, + 06357EB11EBF76120074E6D4 /* p_tick.cpp in Sources */, + 06357EB21EBF76120074E6D4 /* readyammowidget.cpp in Sources */, + 06357EB41EBF76120074E6D4 /* chainwidget.cpp in Sources */, + 06357F251EBF769C0074E6D4 /* p_enemy.c in Sources */, + 06357F321EBF769C0074E6D4 /* intermission.cpp in Sources */, + 06357EB61EBF76120074E6D4 /* g_eventsequence.cpp in Sources */, + 06357EB71EBF76120074E6D4 /* cvarcoloreditwidget.cpp in Sources */, + 06357EB81EBF76120074E6D4 /* p_xgline.cpp in Sources */, + 06357EB91EBF76120074E6D4 /* p_floor.cpp in Sources */, + 06357EBA1EBF76120074E6D4 /* p_door.cpp in Sources */, + 06357F301EBF769C0074E6D4 /* d_refresh.cpp in Sources */, + 06357EBB1EBF76120074E6D4 /* inputbindingwidget.cpp in Sources */, + 06357EBC1EBF76120074E6D4 /* keyslotwidget.cpp in Sources */, + 06357EBE1EBF76120074E6D4 /* p_actor.cpp in Sources */, + 06357EBF1EBF76120074E6D4 /* thinkerinfo.cpp in Sources */, + 06357EC01EBF76120074E6D4 /* playerlogwidget.cpp in Sources */, + 06357EC21EBF76120074E6D4 /* script.cpp in Sources */, + 06357EC31EBF76120074E6D4 /* dmu_lib.cpp in Sources */, + 06357EC51EBF76120074E6D4 /* cvarsliderwidget.cpp in Sources */, + 06357EC61EBF76120074E6D4 /* p_plat.cpp in Sources */, + 06357EC71EBF76120074E6D4 /* coloreditwidget.cpp in Sources */, + 06357EC81EBF76120074E6D4 /* mobjpreviewwidget.cpp in Sources */, + 06357EC91EBF76120074E6D4 /* gl_drawpatch.cpp in Sources */, + 06357ECA1EBF76120074E6D4 /* g_controls.cpp in Sources */, + 06357F2C1EBF769C0074E6D4 /* tables.c in Sources */, + 06357ECB1EBF76120074E6D4 /* page.cpp in Sources */, + 06357ECC1EBF76120074E6D4 /* hu_inventory.cpp in Sources */, + 06357ECD1EBF76120074E6D4 /* labelwidget.cpp in Sources */, + 06357ECE1EBF76120074E6D4 /* p_xgsave.cpp in Sources */, + 06357ECF1EBF76120074E6D4 /* p_start.cpp in Sources */, + 06357F271EBF769C0074E6D4 /* p_maputl.c in Sources */, + 06357ED01EBF76120074E6D4 /* p_mapspec.cpp in Sources */, + 06357ED21EBF76120074E6D4 /* armorwidget.cpp in Sources */, + 06357F2E1EBF769C0074E6D4 /* d_items.cpp in Sources */, + 06357F281EBF769C0074E6D4 /* p_mobj.c in Sources */, + 06357ED31EBF76120074E6D4 /* player.cpp in Sources */, + 06357F311EBF769C0074E6D4 /* d64_api.cpp in Sources */, + 06357ED41EBF76120074E6D4 /* p_user.c in Sources */, + 06357F291EBF769C0074E6D4 /* p_pspr.c in Sources */, + 06357ED51EBF76120074E6D4 /* killswidget.cpp in Sources */, + 06357ED61EBF76120074E6D4 /* gamesession.cpp in Sources */, + 06357ED91EBF76120074E6D4 /* p_view.c in Sources */, + 06357EDA1EBF76120074E6D4 /* readyammoiconwidget.cpp in Sources */, + 06357F261EBF769C0074E6D4 /* p_inter.c in Sources */, + 06357EDB1EBF76120074E6D4 /* inlinelistwidget.cpp in Sources */, + 06357EDC1EBF76120074E6D4 /* p_inventory.cpp in Sources */, + 06357EDF1EBF76120074E6D4 /* module.cpp in Sources */, + 06357EE01EBF76120074E6D4 /* widget.cpp in Sources */, + 06357EE11EBF76120074E6D4 /* p_saveg.cpp in Sources */, + 06357EE21EBF76120074E6D4 /* flightwidget.cpp in Sources */, + 06357EE31EBF76120074E6D4 /* healthwidget.cpp in Sources */, + 06357F351EBF769C0074E6D4 /* p_spec.cpp in Sources */, + 06357EE41EBF76120074E6D4 /* d_netcl.cpp in Sources */, + 06357EE51EBF76120074E6D4 /* p_terraintype.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 06357F381EBF77A00074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 06357F4C1EBF78420074E6D4 /* fmod_util.cpp in Sources */, + 06357F4A1EBF78420074E6D4 /* fmod_music.cpp in Sources */, + 06357F4B1EBF78420074E6D4 /* fmod_sfx.cpp in Sources */, + 06357F491EBF78420074E6D4 /* fmod_cd.cpp in Sources */, + 06357F481EBF78420074E6D4 /* driver_fmod.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 0635819D1EBFBA120074E6D4 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063582731EBFBC8D0074E6D4 /* StandardShapes.cpp in Sources */, + 063582F31EBFBFB80074E6D4 /* ProcessHelper.cpp in Sources */, + 0635825A1EBFBC1C0074E6D4 /* DefaultIOStream.cpp in Sources */, + 063582831EBFBCE10074E6D4 /* ColladaLoader.cpp in Sources */, + 063582971EBFBD2C0074E6D4 /* ObjFileMtlImporter.cpp in Sources */, + 063582C81EBFBD860074E6D4 /* IRRShared.cpp in Sources */, + 063582D71EBFBF560074E6D4 /* FindInvalidDataProcess.cpp in Sources */, + 0635825D1EBFBC2A0074E6D4 /* Importer.cpp in Sources */, + 063583021EBFC0670074E6D4 /* AssimpCExport.cpp in Sources */, + 063582F51EBFBFB80074E6D4 /* RemoveVCProcess.cpp in Sources */, + 063582EF1EBFBFB80074E6D4 /* MakeVerboseFormat.cpp in Sources */, + 0635827D1EBFBCB50074E6D4 /* 3DSLoader.cpp in Sources */, + 063582951EBFBD2C0074E6D4 /* ObjExporter.cpp in Sources */, + 0635827C1EBFBCB50074E6D4 /* 3DSExporter.cpp in Sources */, + 063582F81EBFBFB80074E6D4 /* TextureTransform.cpp in Sources */, + 063582D61EBFBF560074E6D4 /* FindInstancesProcess.cpp in Sources */, + 063582981EBFBD2C0074E6D4 /* ObjFileParser.cpp in Sources */, + 063582BE1EBFBD700074E6D4 /* FBXNodeAttribute.cpp in Sources */, + 063582C61EBFBD860074E6D4 /* IRRLoader.cpp in Sources */, + 063582A41EBFBD4D0074E6D4 /* BlenderTessellator.cpp in Sources */, + 063582BD1EBFBD700074E6D4 /* FBXModel.cpp in Sources */, + 063582C11EBFBD700074E6D4 /* FBXTokenizer.cpp in Sources */, + 063582821EBFBCE10074E6D4 /* ColladaExporter.cpp in Sources */, + 063582BA1EBFBD700074E6D4 /* FBXImporter.cpp in Sources */, + 063582571EBFBBFA0074E6D4 /* ImporterRegistry.cpp in Sources */, + 0635826D1EBFBC8D0074E6D4 /* SceneCombiner.cpp in Sources */, + 063582741EBFBC8D0074E6D4 /* Subdivision.cpp in Sources */, + 063582511EBFBBCC0074E6D4 /* BaseImporter.cpp in Sources */, + 063582B51EBFBD700074E6D4 /* FBXBinaryTokenizer.cpp in Sources */, + 063583061EC036CC0074E6D4 /* ConvertUTF.c in Sources */, + 063582CA1EBFBE4B0074E6D4 /* MaterialSystem.cpp in Sources */, + 063582A31EBFBD4D0074E6D4 /* BlenderScene.cpp in Sources */, + 0635828F1EBFBD1D0074E6D4 /* MDLLoader.cpp in Sources */, + 063582961EBFBD2C0074E6D4 /* ObjFileImporter.cpp in Sources */, + 0635824D1EBFBB960074E6D4 /* Assimp.cpp in Sources */, + 063582711EBFBC8D0074E6D4 /* SpatialSort.cpp in Sources */, + 0635827B1EBFBCB50074E6D4 /* 3DSConverter.cpp in Sources */, + 063582BB1EBFBD700074E6D4 /* FBXMaterial.cpp in Sources */, + 063583001EBFC0510074E6D4 /* Exporter.cpp in Sources */, + 063582D81EBFBF560074E6D4 /* FixNormalsStep.cpp in Sources */, + 063582A21EBFBD4D0074E6D4 /* BlenderModifier.cpp in Sources */, + 063582C01EBFBD700074E6D4 /* FBXProperties.cpp in Sources */, + 063582D41EBFBF560074E6D4 /* DeboneProcess.cpp in Sources */, + 063582D31EBFBF560074E6D4 /* ConvertToLHProcess.cpp in Sources */, + 063582721EBFBC8D0074E6D4 /* SplitByBoneCountProcess.cpp in Sources */, + 063582531EBFBBDB0074E6D4 /* BaseProcess.cpp in Sources */, + 0635828B1EBFBD0C0074E6D4 /* MD5Loader.cpp in Sources */, + 063582B41EBFBD700074E6D4 /* FBXAnimation.cpp in Sources */, + 0635828C1EBFBD0C0074E6D4 /* MD5Parser.cpp in Sources */, + 063582EC1EBFBFB80074E6D4 /* ImproveCacheLocality.cpp in Sources */, + 063582761EBFBC8D0074E6D4 /* Version.cpp in Sources */, + 0635826B1EBFBC8D0074E6D4 /* Bitmap.cpp in Sources */, + 063582701EBFBC8D0074E6D4 /* SkeletonMeshBuilder.cpp in Sources */, + 063582EA1EBFBFB80074E6D4 /* GenFaceNormalsProcess.cpp in Sources */, + 0635826E1EBFBC8D0074E6D4 /* ScenePreprocessor.cpp in Sources */, + 063582901EBFBD1D0074E6D4 /* MDLMaterialLoader.cpp in Sources */, + 063582F41EBFBFB80074E6D4 /* RemoveRedundantMaterials.cpp in Sources */, + 0635824F1EBFBBB40074E6D4 /* DefaultLogger.cpp in Sources */, + 0635828A1EBFBD0C0074E6D4 /* MD3Loader.cpp in Sources */, + 0635829F1EBFBD4D0074E6D4 /* BlenderBMesh.cpp in Sources */, + 063582C71EBFBD860074E6D4 /* IRRMeshLoader.cpp in Sources */, + 063582BC1EBFBD700074E6D4 /* FBXMeshGeometry.cpp in Sources */, + 063582F61EBFBFB80074E6D4 /* SortByPTypeProcess.cpp in Sources */, + 063582B71EBFBD700074E6D4 /* FBXDeformer.cpp in Sources */, + 0635826C1EBFBC8D0074E6D4 /* RemoveComments.cpp in Sources */, + 063582F91EBFBFB80074E6D4 /* TriangulateProcess.cpp in Sources */, + 063582F01EBFBFB80074E6D4 /* OptimizeGraph.cpp in Sources */, + 063582FA1EBFBFB80074E6D4 /* ValidateDataStructure.cpp in Sources */, + 0635825B1EBFBC1C0074E6D4 /* DefaultIOSystem.cpp in Sources */, + 063582FE1EBFC03B0074E6D4 /* StepExporter.cpp in Sources */, + 063582F11EBFBFB80074E6D4 /* OptimizeMeshes.cpp in Sources */, + 0635826F1EBFBC8D0074E6D4 /* SGSpatialSort.cpp in Sources */, + 063582B61EBFBD700074E6D4 /* FBXConverter.cpp in Sources */, + 063582EE1EBFBFB80074E6D4 /* LimitBoneWeightsProcess.cpp in Sources */, + 063583041EC036B40074E6D4 /* irrXML.cpp in Sources */, + 063582F21EBFBFB80074E6D4 /* PretransformVertices.cpp in Sources */, + 063582551EBFBBF10074E6D4 /* PostStepRegistry.cpp in Sources */, + 063582C21EBFBD700074E6D4 /* FBXUtil.cpp in Sources */, + 063582771EBFBC8D0074E6D4 /* VertexTriangleAdjacency.cpp in Sources */, + 063582891EBFBD0C0074E6D4 /* MD2Loader.cpp in Sources */, + 063582A11EBFBD4D0074E6D4 /* BlenderLoader.cpp in Sources */, + 063582B81EBFBD700074E6D4 /* FBXDocument.cpp in Sources */, + 063582BF1EBFBD700074E6D4 /* FBXParser.cpp in Sources */, + 063582FC1EBFBFCA0074E6D4 /* CalcTangentsProcess.cpp in Sources */, + 063582ED1EBFBFB80074E6D4 /* JoinVerticesProcess.cpp in Sources */, + 063582751EBFBC8D0074E6D4 /* TargetAnimation.cpp in Sources */, + 063582B91EBFBD700074E6D4 /* FBXDocumentUtil.cpp in Sources */, + 063582A01EBFBD4D0074E6D4 /* BlenderDNA.cpp in Sources */, + 063582841EBFBCE10074E6D4 /* ColladaParser.cpp in Sources */, + 063582D51EBFBF560074E6D4 /* FindDegenerates.cpp in Sources */, + 063582F71EBFBFB80074E6D4 /* SplitLargeMeshes.cpp in Sources */, + 063582D21EBFBF560074E6D4 /* ComputeUVMappingProcess.cpp in Sources */, + 063582EB1EBFBFB80074E6D4 /* GenVertexNormalsProcess.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD9051EBF143600B808B2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 067AD9181EBF14AE00B808B2 /* hexlex.cpp in Sources */, + 067AD91B1EBF14AE00B808B2 /* mapimporter_loadblockmap.cpp in Sources */, + 067AD91C1EBF14AE00B808B2 /* mapinfotranslator.cpp in Sources */, + 067AD91A1EBF14AE00B808B2 /* mapimporter.cpp in Sources */, + 067AD9191EBF14AE00B808B2 /* importidtech1.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 067AD91E1EBF14E000B808B2 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 063579D21EBF5E2E0074E6D4 /* c_wrapper.cpp in Sources */, + 063579D31EBF5E2E0074E6D4 /* charsymbols.cpp in Sources */, + 063579D41EBF5E2E0074E6D4 /* guard.cpp in Sources */, + 063579D51EBF5E2E0074E6D4 /* lockable.cpp in Sources */, + 063579D61EBF5E2E0074E6D4 /* readwritelockable.cpp in Sources */, + 063579D71EBF5E2E0074E6D4 /* task.cpp in Sources */, + 063579D81EBF5E2E0074E6D4 /* taskpool.cpp in Sources */, + 063579D91EBF5E2E0074E6D4 /* waitable.cpp in Sources */, + 063579DA1EBF5E2E0074E6D4 /* app.cpp in Sources */, + 063579DB1EBF5E2E0074E6D4 /* asset.cpp in Sources */, + 063579DC1EBF5E2E0074E6D4 /* callbacktimer.cpp in Sources */, + 063579DE1EBF5E2E0074E6D4 /* clock.cpp in Sources */, + 063579DF1EBF5E2E0074E6D4 /* commandline.cpp in Sources */, + 063579E01EBF5E2E0074E6D4 /* config.cpp in Sources */, + 063579E11EBF5E2E0074E6D4 /* debuglogsink.cpp in Sources */, + 063579E21EBF5E2E0074E6D4 /* filelogsink.cpp in Sources */, + 063579E31EBF5E2E0074E6D4 /* garbage.cpp in Sources */, + 063579E41EBF5E2E0074E6D4 /* highperformancetimer.cpp in Sources */, + 063579E51EBF5E2E0074E6D4 /* id.cpp in Sources */, + 063579E61EBF5E2E0074E6D4 /* library.cpp in Sources */, + 063579E71EBF5E2E0074E6D4 /* log.cpp in Sources */, + 063579E81EBF5E2E0074E6D4 /* logbuffer.cpp in Sources */, + 063579E91EBF5E2E0074E6D4 /* logfilter.cpp in Sources */, + 063579EA1EBF5E2E0074E6D4 /* logsink.cpp in Sources */, + 063579EC1EBF5E2E0074E6D4 /* loop.cpp in Sources */, + 063579ED1EBF5E2E0074E6D4 /* memorylogsink.cpp in Sources */, + 063579EE1EBF5E2E0074E6D4 /* monospacelogsinkformatter.cpp in Sources */, + 063579EF1EBF5E2E0074E6D4 /* system.cpp in Sources */, + 063579F01EBF5E2E0074E6D4 /* textapp.cpp in Sources */, + 063579F11EBF5E2E0074E6D4 /* textstreamlogsink.cpp in Sources */, + 063579F21EBF5E2E0074E6D4 /* unixinfo.cpp in Sources */, + 063579F31EBF5E2E0074E6D4 /* animationvalue.cpp in Sources */, + 063579F41EBF5E2E0074E6D4 /* archive.cpp in Sources */, + 063579F51EBF5E2E0074E6D4 /* arrayvalue.cpp in Sources */, + 063579F61EBF5E2E0074E6D4 /* bank.cpp in Sources */, + 063579F71EBF5E2E0074E6D4 /* bitfield.cpp in Sources */, + 063579F81EBF5E2E0074E6D4 /* bitfield_elements.cpp in Sources */, + 063579F91EBF5E2E0074E6D4 /* block.cpp in Sources */, + 063579FA1EBF5E2E0074E6D4 /* blockvalue.cpp in Sources */, + 063579FB1EBF5E2E0074E6D4 /* byteorder.cpp in Sources */, + 063579FC1EBF5E2E0074E6D4 /* byterefarray.cpp in Sources */, + 063579FD1EBF5E2E0074E6D4 /* bytesubarray.cpp in Sources */, + 063579FE1EBF5E2E0074E6D4 /* counted.cpp in Sources */, + 063579FF1EBF5E2E0074E6D4 /* date.cpp in Sources */, + 06357A001EBF5E2E0074E6D4 /* deletable.cpp in Sources */, + 06357A011EBF5E2E0074E6D4 /* dictionaryvalue.cpp in Sources */, + 06357A021EBF5E2E0074E6D4 /* escapeparser.cpp in Sources */, + 06357A031EBF5E2E0074E6D4 /* fixedbytearray.cpp in Sources */, + 06357A041EBF5E2E0074E6D4 /* huffman.cpp in Sources */, + 06357A051EBF5E2E0074E6D4 /* info.cpp in Sources */, + 06357A061EBF5E2E0074E6D4 /* infobank.cpp in Sources */, + 06357A071EBF5E2E0074E6D4 /* json.cpp in Sources */, + 06357A081EBF5E2E0074E6D4 /* nativepointervalue.cpp in Sources */, + 06357A091EBF5E2E0074E6D4 /* nonevalue.cpp in Sources */, + 06357A0A1EBF5E2E0074E6D4 /* numbervalue.cpp in Sources */, + 06357A0B1EBF5E2E0074E6D4 /* observers.cpp in Sources */, + 06357A0C1EBF5E2E0074E6D4 /* path.cpp in Sources */, + 06357A0D1EBF5E2E0074E6D4 /* pathtree.cpp in Sources */, + 06357A0E1EBF5E2E0074E6D4 /* pathtreenode.cpp in Sources */, + 06357A0F1EBF5E2E0074E6D4 /* pointerset.cpp in Sources */, + 06357A101EBF5E2E0074E6D4 /* profiles.cpp in Sources */, + 06357A111EBF5E2E0074E6D4 /* reader.cpp in Sources */, + 06357A121EBF5E2E0074E6D4 /* record.cpp in Sources */, + 06357A131EBF5E2E0074E6D4 /* recordaccessor.cpp in Sources */, + 06357A141EBF5E2E0074E6D4 /* recordvalue.cpp in Sources */, + 06357A151EBF5E2E0074E6D4 /* refuge.cpp in Sources */, + 06357A161EBF5E2E0074E6D4 /* refvalue.cpp in Sources */, + 06357A171EBF5E2E0074E6D4 /* sourcelinetable.cpp in Sources */, + 06357A181EBF5E2E0074E6D4 /* string.cpp in Sources */, + 06357A191EBF5E2E0074E6D4 /* stringpool.cpp in Sources */, + 06357A1A1EBF5E2E0074E6D4 /* textvalue.cpp in Sources */, + 06357A1B1EBF5E2E0074E6D4 /* time.cpp in Sources */, + 06357A1C1EBF5E2E0074E6D4 /* timevalue.cpp in Sources */, + 06357A1D1EBF5E2E0074E6D4 /* value.cpp in Sources */, + 06357A1E1EBF5E2E0074E6D4 /* variable.cpp in Sources */, + 06357A1F1EBF5E2E0074E6D4 /* writer.cpp in Sources */, + 06357A201EBF5E2E0074E6D4 /* ziparchive.cpp in Sources */, + 06357A211EBF5E2E0074E6D4 /* error.cpp in Sources */, + 06357A221EBF5E2E0074E6D4 /* archiveentryfile.cpp in Sources */, + 06357A231EBF5E2E0074E6D4 /* archivefeed.cpp in Sources */, + 06357A241EBF5E2E0074E6D4 /* archivefolder.cpp in Sources */, + 06357A251EBF5E2E0074E6D4 /* assetobserver.cpp in Sources */, + 06357A261EBF5E2E0074E6D4 /* bytearrayfile.cpp in Sources */, + 06357A271EBF5E2E0074E6D4 /* directoryfeed.cpp in Sources */, + 06357A281EBF5E2E0074E6D4 /* feed.cpp in Sources */, + 06357A291EBF5E2E0074E6D4 /* file.cpp in Sources */, + 06357A2A1EBF5E2E0074E6D4 /* fileindex.cpp in Sources */, + 06357A2B1EBF5E2E0074E6D4 /* filesystem.cpp in Sources */, + 06357A2C1EBF5E2E0074E6D4 /* folder.cpp in Sources */, + 06357A2D1EBF5E2E0074E6D4 /* libraryfile.cpp in Sources */, + 06357A2E1EBF5E2E0074E6D4 /* linkfile.cpp in Sources */, + 06357A2F1EBF5E2E0074E6D4 /* metadatabank.cpp in Sources */, + 06357A301EBF5E2E0074E6D4 /* nativefile.cpp in Sources */, + 06357A311EBF5E2E0074E6D4 /* nativepath.cpp in Sources */, + 06357A321EBF5E2E0074E6D4 /* node.cpp in Sources */, + 06357A331EBF5E2E0074E6D4 /* package.cpp in Sources */, + 06357A341EBF5E2E0074E6D4 /* packagefeed.cpp in Sources */, + 06357A351EBF5E2E0074E6D4 /* packageloader.cpp in Sources */, + 06357A361EBF5E2E0074E6D4 /* staticlibraryfeed.cpp in Sources */, + 06357A371EBF5E2E0074E6D4 /* math.cpp in Sources */, + 06357A381EBF5E2E0074E6D4 /* matrix.cpp in Sources */, + 06357A391EBF5E2E0074E6D4 /* address.cpp in Sources */, + 06357A3A1EBF5E2E0074E6D4 /* beacon.cpp in Sources */, + 06357A3B1EBF5E2E0074E6D4 /* blockpacket.cpp in Sources */, + 06357A3C1EBF5E2E0074E6D4 /* identifiedpacket.cpp in Sources */, + 06357A3D1EBF5E2E0074E6D4 /* listensocket.cpp in Sources */, + 06357A3E1EBF5E2E0074E6D4 /* message.cpp in Sources */, + 06357A3F1EBF5E2E0074E6D4 /* networkinterfaces.cpp in Sources */, + 06357A411EBF5E2E0074E6D4 /* packet.cpp in Sources */, + 06357A421EBF5E2E0074E6D4 /* protocol.cpp in Sources */, + 06357A431EBF5E2E0074E6D4 /* recordpacket.cpp in Sources */, + 06357A441EBF5E2E0074E6D4 /* socket.cpp in Sources */, + 06357A451EBF5E2E0074E6D4 /* transmitter.cpp in Sources */, + 06357A461EBF5E2E0074E6D4 /* arrayexpression.cpp in Sources */, + 06357A471EBF5E2E0074E6D4 /* assignstatement.cpp in Sources */, + 06357A481EBF5E2E0074E6D4 /* bindings_core.cpp in Sources */, + 06357A4A1EBF5E2E0074E6D4 /* bindings_math.cpp in Sources */, + 06357A4C1EBF5E2E0074E6D4 /* builtinexpression.cpp in Sources */, + 06357A4D1EBF5E2E0074E6D4 /* catchstatement.cpp in Sources */, + 06357A4E1EBF5E2E0074E6D4 /* compound.cpp in Sources */, + 06357A4F1EBF5E2E0074E6D4 /* constantexpression.cpp in Sources */, + 06357A501EBF5E2E0074E6D4 /* context.cpp in Sources */, + 06357A511EBF5E2E0074E6D4 /* deletestatement.cpp in Sources */, + 06357A521EBF5E2E0074E6D4 /* dictionaryexpression.cpp in Sources */, + 06357A531EBF5E2E0074E6D4 /* evaluator.cpp in Sources */, + 06357A541EBF5E2E0074E6D4 /* expression.cpp in Sources */, + 06357A551EBF5E2E0074E6D4 /* expressionstatement.cpp in Sources */, + 06357A561EBF5E2E0074E6D4 /* flowstatement.cpp in Sources */, + 06357A571EBF5E2E0074E6D4 /* forstatement.cpp in Sources */, + 06357A581EBF5E2E0074E6D4 /* function.cpp in Sources */, + 06357A591EBF5E2E0074E6D4 /* functionstatement.cpp in Sources */, + 06357A5A1EBF5E2E0074E6D4 /* functionvalue.cpp in Sources */, + 06357A5B1EBF5E2E0074E6D4 /* ifstatement.cpp in Sources */, + 06357A5C1EBF5E2E0074E6D4 /* lex.cpp in Sources */, + 06357A5D1EBF5E2E0074E6D4 /* module.cpp in Sources */, + 06357A5E1EBF5E2E0074E6D4 /* nameexpression.cpp in Sources */, + 06357A5F1EBF5E2E0074E6D4 /* operator.cpp in Sources */, + 06357A601EBF5E2E0074E6D4 /* operatorexpression.cpp in Sources */, + 06357A611EBF5E2E0074E6D4 /* parser.cpp in Sources */, + 06357A621EBF5E2E0074E6D4 /* printstatement.cpp in Sources */, + 06357A631EBF5E2E0074E6D4 /* process.cpp in Sources */, + 06357A641EBF5E2E0074E6D4 /* scheduler.cpp in Sources */, + 0635818A1EBFB5680074E6D4 /* deng_core_moc_compilation.cpp in Sources */, + 06357A651EBF5E2E0074E6D4 /* scopestatement.cpp in Sources */, + 06357A661EBF5E2E0074E6D4 /* script.cpp in Sources */, + 06357A671EBF5E2E0074E6D4 /* scriptedinfo.cpp in Sources */, + 06357A681EBF5E2E0074E6D4 /* scriptlex.cpp in Sources */, + 06357A691EBF5E2E0074E6D4 /* scriptsystem.cpp in Sources */, + 06357A6A1EBF5E2E0074E6D4 /* statement.cpp in Sources */, + 06357A6B1EBF5E2E0074E6D4 /* tokenbuffer.cpp in Sources */, + 06357A6C1EBF5E2E0074E6D4 /* tokenrange.cpp in Sources */, + 06357A6D1EBF5E2E0074E6D4 /* trystatement.cpp in Sources */, + 06357A6E1EBF5E2E0074E6D4 /* whilestatement.cpp in Sources */, + 06357A6F1EBF5E2E0074E6D4 /* version.cpp in Sources */, + 06357A701EBF5E2E0074E6D4 /* action.cpp in Sources */, + 06357A711EBF5E2E0074E6D4 /* animation.cpp in Sources */, + 06357A721EBF5E2E0074E6D4 /* animationrule.cpp in Sources */, + 06357A731EBF5E2E0074E6D4 /* constantrule.cpp in Sources */, + 06357A741EBF5E2E0074E6D4 /* indirectrule.cpp in Sources */, + 06357A751EBF5E2E0074E6D4 /* operatorrule.cpp in Sources */, + 06357A761EBF5E2E0074E6D4 /* rootwidget.cpp in Sources */, + 06357A771EBF5E2E0074E6D4 /* rule.cpp in Sources */, + 06357A781EBF5E2E0074E6D4 /* rulebank.cpp in Sources */, + 06357A791EBF5E2E0074E6D4 /* rulerectangle.cpp in Sources */, + 06357A7A1EBF5E2E0074E6D4 /* widget.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 068610541EBF01F700180814 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 0635814B1EBF7AE50074E6D4 /* clientserverworld.cpp in Sources */, + 063580741EBF7AE50074E6D4 /* audiodriver.cpp in Sources */, + 063580C21EBF7AE50074E6D4 /* rend_model.cpp in Sources */, + 063581221EBF7AE50074E6D4 /* nativeui.cpp in Sources */, + 063581531EBF7AE50074E6D4 /* maputil.cpp in Sources */, + 063581201EBF7AE50074E6D4 /* mouse_qt.cpp in Sources */, + 063580D51EBF7AE50074E6D4 /* api_resource.cpp in Sources */, + 063581021EBF7AE50074E6D4 /* renderersettingsdialog.cpp in Sources */, + 063580AA1EBF7AE50074E6D4 /* cameralensfx.cpp in Sources */, + 063580FF1EBF7AE50074E6D4 /* packagecompatibilitydialog.cpp in Sources */, + 0635810A1EBF7AE50074E6D4 /* hatinputcontrol.cpp in Sources */, + 063581991EBFB7620074E6D4 /* Doomsday_moc_compilation.cpp in Sources */, + 063581091EBF7AE50074E6D4 /* variablegroupeditor.cpp in Sources */, + 063581111EBF7AE50074E6D4 /* multiplayerpanelbuttonwidget.cpp in Sources */, + 0635810B1EBF7AE50074E6D4 /* columnwidget.cpp in Sources */, + 063581051EBF7AE50074E6D4 /* videosettingsdialog.cpp in Sources */, + 063580E01EBF7AE50074E6D4 /* hq2x.cpp in Sources */, + 063580D91EBF7AE50074E6D4 /* clientresources.cpp in Sources */, + 0635812D1EBF7AE50074E6D4 /* consolewidget.cpp in Sources */, + 063580791EBF7AE50074E6D4 /* s_environ.cpp in Sources */, + 0635813C1EBF7AE50074E6D4 /* packagesbuttonwidget.cpp in Sources */, + 063581131EBF7AE50074E6D4 /* packagescolumnwidget.cpp in Sources */, + 0635809E1EBF7AE50074E6D4 /* net_event.cpp in Sources */, + 063580F61EBF7AE50074E6D4 /* alertdialog.cpp in Sources */, + 063580F01EBF7AE50074E6D4 /* clientwindow.cpp in Sources */, + 063581211EBF7AE50074E6D4 /* nativemenu.cpp in Sources */, + 063580EC1EBF7AE50074E6D4 /* busyvisual.cpp in Sources */, + 0635814C1EBF7AE50074E6D4 /* convexsubspace.cpp in Sources */, + 063580B51EBF7AE50074E6D4 /* lumobj.cpp in Sources */, + 063580CE1EBF7AE50074E6D4 /* viewports.cpp in Sources */, + 063580981EBF7AE50074E6D4 /* mesh.cpp in Sources */, + 063580D81EBF7AE50074E6D4 /* clientmaterial.cpp in Sources */, + 063581191EBF7AE50074E6D4 /* finalepagewidget.cpp in Sources */, + 063581681EBF7AE50074E6D4 /* clientmobjthinkerdata.cpp in Sources */, + 063580C81EBF7AE50074E6D4 /* skydrawable.cpp in Sources */, + 063580781EBF7AE50074E6D4 /* m_mus2midi.cpp in Sources */, + 0635817C1EBF7AE50074E6D4 /* main_client.cpp in Sources */, + 063581451EBF7AE50074E6D4 /* zonedebug.cpp in Sources */, + 063580A81EBF7AE50074E6D4 /* billboard.cpp in Sources */, + 063581351EBF7AE50074E6D4 /* homemenuwidget.cpp in Sources */, + 0635809B1EBF7AE50074E6D4 /* masterserver.cpp in Sources */, + 063580951EBF7AE50074E6D4 /* color.cpp in Sources */, + 063580E21EBF7AE50074E6D4 /* image.cpp in Sources */, + 063580E61EBF7AE50074E6D4 /* alertmask.cpp in Sources */, + 063581031EBF7AE50074E6D4 /* serverinfodialog.cpp in Sources */, + 063671181EC4E7BA00DAF520 /* qrc_client.cpp in Sources */, + 063580C01EBF7AE50074E6D4 /* rend_halo.cpp in Sources */, + 063580E31EBF7AE50074E6D4 /* lightmaterialdecoration.cpp in Sources */, + 063580F91EBF7AE50074E6D4 /* createprofiledialog.cpp in Sources */, + 063581341EBF7AE50074E6D4 /* homeitemwidget.cpp in Sources */, + 063581141EBF7AE50074E6D4 /* savelistwidget.cpp in Sources */, + 063580C31EBF7AE50074E6D4 /* rend_particle.cpp in Sources */, + 063580B61EBF7AE50074E6D4 /* model.cpp in Sources */, + 063581181EBF7AE50074E6D4 /* finaleinterpreter.cpp in Sources */, + 063580E71EBF7AE50074E6D4 /* axisinputcontrol.cpp in Sources */, + 0635816F1EBF7AE50074E6D4 /* api_map.cpp in Sources */, + 063580A91EBF7AE50074E6D4 /* blockmapvisual.cpp in Sources */, + 063580931EBF7AE50074E6D4 /* sys_opengl.cpp in Sources */, + 063581581EBF7AE50074E6D4 /* polyobj.cpp in Sources */, + 063581671EBF7AE50074E6D4 /* superblockmap.cpp in Sources */, + 0635808F1EBF7AE50074E6D4 /* gl_main.cpp in Sources */, + 063581001EBF7AE50074E6D4 /* packageinfodialog.cpp in Sources */, + 063581161EBF7AE50074E6D4 /* finale.cpp in Sources */, + 0635807E1EBF7AE50074E6D4 /* cl_infine.cpp in Sources */, + 063581311EBF7AE50074E6D4 /* cvarsliderwidget.cpp in Sources */, + 063580A71EBF7AE50074E6D4 /* api_render.cpp in Sources */, + 063581791EBF7AE50074E6D4 /* dd_pinit.cpp in Sources */, + 063581151EBF7AE50074E6D4 /* impulsebinding.cpp in Sources */, + 063580E11EBF7AE50074E6D4 /* idtech1image.cpp in Sources */, + 0635812E1EBF7AE50074E6D4 /* cvarchoicewidget.cpp in Sources */, + 0635807C1EBF7AE50074E6D4 /* sys_audiod_sdlmixer.cpp in Sources */, + 063580EB1EBF7AE50074E6D4 /* binding.cpp in Sources */, + 063581471EBF7AE50074E6D4 /* joystick.cpp in Sources */, + 0635812B1EBF7AE50074E6D4 /* busywidget.cpp in Sources */, + 063580921EBF7AE50074E6D4 /* svg.cpp in Sources */, + 063580FE1EBF7AE50074E6D4 /* networksettingsdialog.cpp in Sources */, + 063581781EBF7AE50074E6D4 /* dd_main.cpp in Sources */, + 063581441EBF7AE50074E6D4 /* tutorialwidget.cpp in Sources */, + 0635813D1EBF7AE50074E6D4 /* packagessidebarwidget.cpp in Sources */, + 063580891EBF7AE50074E6D4 /* dgl_common.cpp in Sources */, + 063580881EBF7AE50074E6D4 /* clskyplane.cpp in Sources */, + 0635811C1EBF7AE50074E6D4 /* infinesystem.cpp in Sources */, + 063581081EBF7AE50074E6D4 /* rendererappearanceeditor.cpp in Sources */, + 0635808A1EBF7AE50074E6D4 /* dgl_draw.cpp in Sources */, + 0635807A1EBF7AE50074E6D4 /* sfxchannel.cpp in Sources */, + 063581401EBF7AE50074E6D4 /* privilegedlogwidget.cpp in Sources */, + 063581171EBF7AE50074E6D4 /* finaleanimwidget.cpp in Sources */, + 063580CF1EBF7AE50074E6D4 /* vissprite.cpp in Sources */, + 0635816E1EBF7AE50074E6D4 /* api_filesys.cpp in Sources */, + 063580C91EBF7AE50074E6D4 /* skyfixedge.cpp in Sources */, + 063580CD1EBF7AE50074E6D4 /* vectorlightlist.cpp in Sources */, + 063581551EBF7AE50074E6D4 /* p_players.cpp in Sources */, + 063580871EBF7AE50074E6D4 /* clpolymover.cpp in Sources */, + 063580FB1EBF7AE50074E6D4 /* inputsettingsdialog.cpp in Sources */, + 063580E51EBF7AE50074E6D4 /* texturevariant.cpp in Sources */, + 063580D71EBF7AE50074E6D4 /* bitmapfont.cpp in Sources */, + 0635816B1EBF7AE50074E6D4 /* generator.cpp in Sources */, + 063580B31EBF7AE50074E6D4 /* vignette.cpp in Sources */, + 0635816C1EBF7AE50074E6D4 /* mapobject.cpp in Sources */, + 063580D31EBF7AE50074E6D4 /* abstractfont.cpp in Sources */, + 063580A01EBF7AE50074E6D4 /* net_msg.cpp in Sources */, + 063581661EBF7AE50074E6D4 /* partitionevaluator.cpp in Sources */, + 063580F51EBF7AE50074E6D4 /* aboutdialog.cpp in Sources */, + 0635808D1EBF7AE50074E6D4 /* gl_draw.cpp in Sources */, + 063580A61EBF7AE50074E6D4 /* angleclipper.cpp in Sources */, + 063581421EBF7AE50074E6D4 /* sidebarwidget.cpp in Sources */, + 063580CC1EBF7AE50074E6D4 /* trianglestripbuilder.cpp in Sources */, + 063580971EBF7AE50074E6D4 /* hedge.cpp in Sources */, + 063580F71EBF7AE50074E6D4 /* audiosettingsdialog.cpp in Sources */, + 063581041EBF7AE50074E6D4 /* uisettingsdialog.cpp in Sources */, + 063581481EBF7AE50074E6D4 /* bindings_world.cpp in Sources */, + 063580751EBF7AE50074E6D4 /* audiosystem.cpp in Sources */, + 063580FD1EBF7AE50074E6D4 /* manualconnectiondialog.cpp in Sources */, + 063581601EBF7AE50074E6D4 /* thinkers.cpp in Sources */, + 0635812F1EBF7AE50074E6D4 /* cvarlineeditwidget.cpp in Sources */, + 063580BA1EBF7AE50074E6D4 /* projectionlist.cpp in Sources */, + 063581501EBF7AE50074E6D4 /* lineblockmap.cpp in Sources */, + 063581621EBF7AE50074E6D4 /* convexsubspaceproxy.cpp in Sources */, + 063581741EBF7AE50074E6D4 /* clientplayer.cpp in Sources */, + 063580D01EBF7AE50074E6D4 /* vr.cpp in Sources */, + 063581541EBF7AE50074E6D4 /* p_mobj.cpp in Sources */, + 063581231EBF7AE50074E6D4 /* postprocessing.cpp in Sources */, + 0635813F1EBF7AE50074E6D4 /* panelbuttonwidget.cpp in Sources */, + 063580BE1EBF7AE50074E6D4 /* rend_fakeradio.cpp in Sources */, + 063581771EBF7AE50074E6D4 /* dd_loop.cpp in Sources */, + 063580D41EBF7AE50074E6D4 /* api_material.cpp in Sources */, + 0635809A1EBF7AE50074E6D4 /* tab_tables.cpp in Sources */, + 063580FC1EBF7AE50074E6D4 /* logsettingsdialog.cpp in Sources */, + 063580FA1EBF7AE50074E6D4 /* datafilesettingsdialog.cpp in Sources */, + 063580941EBF7AE50074E6D4 /* texturecontent.cpp in Sources */, + 063580911EBF7AE50074E6D4 /* gl_texmanager.cpp in Sources */, + 063580DA1EBF7AE50074E6D4 /* clienttexture.cpp in Sources */, + 063580EE1EBF7AE50074E6D4 /* clientrootwidget.cpp in Sources */, + 063580DB1EBF7AE50074E6D4 /* compositebitmapfont.cpp in Sources */, + 0635813A1EBF7AE50074E6D4 /* multiplayerstatuswidget.cpp in Sources */, + 063581511EBF7AE50074E6D4 /* linesighttest.cpp in Sources */, + 063580F21EBF7AE50074E6D4 /* commandaction.cpp in Sources */, + 063581371EBF7AE50074E6D4 /* keygrabberwidget.cpp in Sources */, + 063580C11EBF7AE50074E6D4 /* rend_main.cpp in Sources */, + 063580B71EBF7AE50074E6D4 /* modelloader.cpp in Sources */, + 0635812C1EBF7AE50074E6D4 /* consolecommandwidget.cpp in Sources */, + 063580B11EBF7AE50074E6D4 /* colorfilter.cpp in Sources */, + 0635814D1EBF7AE50074E6D4 /* impulseaccumulator.cpp in Sources */, + 063580F11EBF7AE50074E6D4 /* clientwindowsystem.cpp in Sources */, + 0635810C1EBF7AE50074E6D4 /* gamecolumnwidget.cpp in Sources */, + 0635808E1EBF7AE50074E6D4 /* gl_drawvectorgraphic.cpp in Sources */, + 063580901EBF7AE50074E6D4 /* gl_tex.cpp in Sources */, + 063581731EBF7AE50074E6D4 /* clientapp.cpp in Sources */, + 0635811F1EBF7AE50074E6D4 /* inputsystem.cpp in Sources */, + 0635815D1EBF7AE50074E6D4 /* sky.cpp in Sources */, + 063580B41EBF7AE50074E6D4 /* lightdecoration.cpp in Sources */, + 0635817A1EBF7AE50074E6D4 /* def_main.cpp in Sources */, + 063581761EBF7AE50074E6D4 /* configprofiles.cpp in Sources */, + 063580BB1EBF7AE50074E6D4 /* r_draw.cpp in Sources */, + 0635811B1EBF7AE50074E6D4 /* finalewidget.cpp in Sources */, + 063581071EBF7AE50074E6D4 /* modelasseteditor.cpp in Sources */, + 063580AD1EBF7AE50074E6D4 /* drawlist.cpp in Sources */, + 063580851EBF7AE50074E6D4 /* clientsubsector.cpp in Sources */, + 0635812A1EBF7AE50074E6D4 /* viewcompositor.cpp in Sources */, + 063581121EBF7AE50074E6D4 /* nogamescolumnwidget.cpp in Sources */, + 063581281EBF7AE50074E6D4 /* sys_input.cpp in Sources */, + 063581461EBF7AE50074E6D4 /* dd_uinit.cpp in Sources */, + 063580DD1EBF7AE50074E6D4 /* fonts.cpp in Sources */, + 0635814F1EBF7AE50074E6D4 /* line.cpp in Sources */, + 063580F31EBF7AE50074E6D4 /* commandbinding.cpp in Sources */, + 063580F41EBF7AE50074E6D4 /* controllerpresets.cpp in Sources */, + 0635811D1EBF7AE50074E6D4 /* inputdebug.cpp in Sources */, + 063581651EBF7AE50074E6D4 /* partitioner.cpp in Sources */, + 063580AB1EBF7AE50074E6D4 /* consoleeffect.cpp in Sources */, + 063580BF1EBF7AE50074E6D4 /* rend_font.cpp in Sources */, + 063581331EBF7AE50074E6D4 /* gamewidget.cpp in Sources */, + 063580DC1EBF7AE50074E6D4 /* fontmanifest.cpp in Sources */, + 0635817B1EBF7AE50074E6D4 /* localplayer.cpp in Sources */, + 0635816A1EBF7AE50074E6D4 /* contactspreader.cpp in Sources */, + 0635815E1EBF7AE50074E6D4 /* subsector.cpp in Sources */, + 063580771EBF7AE50074E6D4 /* s_cache.cpp in Sources */, + 063581701EBF7AE50074E6D4 /* api_mapedit.cpp in Sources */, + 0635810E1EBF7AE50074E6D4 /* headerwidget.cpp in Sources */, + 063580821EBF7AE50074E6D4 /* cl_sound.cpp in Sources */, + 063580C61EBF7AE50074E6D4 /* shadervar.cpp in Sources */, + 0635813B1EBF7AE50074E6D4 /* packagecontentoptionswidget.cpp in Sources */, + 0635815F1EBF7AE50074E6D4 /* surface.cpp in Sources */, + 063580D11EBF7AE50074E6D4 /* walledge.cpp in Sources */, + 063580E91EBF7AE50074E6D4 /* b_util.cpp in Sources */, + 063581641EBF7AE50074E6D4 /* linesegment.cpp in Sources */, + 063580A11EBF7AE50074E6D4 /* net_ping.cpp in Sources */, + 063580ED1EBF7AE50074E6D4 /* buttoninputcontrol.cpp in Sources */, + 0635809F1EBF7AE50074E6D4 /* net_main.cpp in Sources */, + 0635807F1EBF7AE50074E6D4 /* cl_main.cpp in Sources */, + 063580B21EBF7AE50074E6D4 /* lensflares.cpp in Sources */, + 0635811A1EBF7AE50074E6D4 /* finaletextwidget.cpp in Sources */, + 063581611EBF7AE50074E6D4 /* vertex.cpp in Sources */, + 063581251EBF7AE50074E6D4 /* savelistdata.cpp in Sources */, + 0635809C1EBF7AE50074E6D4 /* monitor.cpp in Sources */, + 063581521EBF7AE50074E6D4 /* map.cpp in Sources */, + 063580EA1EBF7AE50074E6D4 /* bindcontext.cpp in Sources */, + 063580C71EBF7AE50074E6D4 /* shadowedge.cpp in Sources */, + 063580CA1EBF7AE50074E6D4 /* stateanimator.cpp in Sources */, + 063580C41EBF7AE50074E6D4 /* rendersystem.cpp in Sources */, + 063581571EBF7AE50074E6D4 /* plane.cpp in Sources */, + 063580961EBF7AE50074E6D4 /* face.cpp in Sources */, + 063580A31EBF7AE50074E6D4 /* net_demo.cpp in Sources */, + 0635808B1EBF7AE50074E6D4 /* gl_defer.cpp in Sources */, + 0635808C1EBF7AE50074E6D4 /* gl_deferredapi.cpp in Sources */, + 063580861EBF7AE50074E6D4 /* clplanemover.cpp in Sources */, + 063580B81EBF7AE50074E6D4 /* modelrenderer.cpp in Sources */, + 0635811E1EBF7AE50074E6D4 /* inputdevice.cpp in Sources */, + 063580EF1EBF7AE50074E6D4 /* clientstyle.cpp in Sources */, + 063580BC1EBF7AE50074E6D4 /* r_main.cpp in Sources */, + 063580A41EBF7AE50074E6D4 /* serverlink.cpp in Sources */, + 063581751EBF7AE50074E6D4 /* con_config.cpp in Sources */, + 063581391EBF7AE50074E6D4 /* multiplayerservermenuwidget.cpp in Sources */, + 0635815A1EBF7AE50074E6D4 /* reject.cpp in Sources */, + 063581431EBF7AE50074E6D4 /* taskbarwidget.cpp in Sources */, + 0635809D1EBF7AE50074E6D4 /* net_buf.cpp in Sources */, + 063580B91EBF7AE50074E6D4 /* playerweaponanimator.cpp in Sources */, + 063580BD1EBF7AE50074E6D4 /* r_things.cpp in Sources */, + 063581361EBF7AE50074E6D4 /* inputbindingwidget.cpp in Sources */, + 063580AF1EBF7AE50074E6D4 /* environ.cpp in Sources */, + 063581101EBF7AE50074E6D4 /* multiplayercolumnwidget.cpp in Sources */, + 0635817D1EBF7AE50074E6D4 /* sys_system.cpp in Sources */, + 0635814A1EBF7AE50074E6D4 /* bspleaf.cpp in Sources */, + 063581491EBF7AE50074E6D4 /* blockmap.cpp in Sources */, + 063581321EBF7AE50074E6D4 /* cvartogglewidget.cpp in Sources */, + 063580A51EBF7AE50074E6D4 /* sys_network.cpp in Sources */, + 063580B01EBF7AE50074E6D4 /* bloom.cpp in Sources */, + 063581561EBF7AE50074E6D4 /* p_ticker.cpp in Sources */, + 063580E41EBF7AE50074E6D4 /* materialanimator.cpp in Sources */, + 0635810D1EBF7AE50074E6D4 /* gamepanelbuttonwidget.cpp in Sources */, + 063580DE1EBF7AE50074E6D4 /* fontscheme.cpp in Sources */, + 063581301EBF7AE50074E6D4 /* cvarnativepathwidget.cpp in Sources */, + 063581721EBF7AE50074E6D4 /* busyrunner.cpp in Sources */, + 063581011EBF7AE50074E6D4 /* packagesdialog.cpp in Sources */, + 0635813E1EBF7AE50074E6D4 /* packageswidget.cpp in Sources */, + 0635807B1EBF7AE50074E6D4 /* sys_audiod_dummy.cpp in Sources */, + 063580801EBF7AE50074E6D4 /* cl_mobj.cpp in Sources */, + 063580AC1EBF7AE50074E6D4 /* decoration.cpp in Sources */, + 063581631EBF7AE50074E6D4 /* hplane.cpp in Sources */, + 063581591EBF7AE50074E6D4 /* polyobjdata.cpp in Sources */, + 0635810F1EBF7AE50074E6D4 /* homewidget.cpp in Sources */, + 063580831EBF7AE50074E6D4 /* cl_world.cpp in Sources */, + 063580C51EBF7AE50074E6D4 /* rendpoly.cpp in Sources */, + 063581691EBF7AE50074E6D4 /* contact.cpp in Sources */, + 063581381EBF7AE50074E6D4 /* mapoutlinewidget.cpp in Sources */, + 063580F81EBF7AE50074E6D4 /* coloradjustmentdialog.cpp in Sources */, + 063580841EBF7AE50074E6D4 /* cledgeloop.cpp in Sources */, + 063580991EBF7AE50074E6D4 /* r_util.cpp in Sources */, + 063580AE1EBF7AE50074E6D4 /* drawlists.cpp in Sources */, + 063581711EBF7AE50074E6D4 /* api_uri.cpp in Sources */, + 0635815C1EBF7AE50074E6D4 /* sector.cpp in Sources */, + 063581291EBF7AE50074E6D4 /* ui_main.cpp in Sources */, + 063580CB1EBF7AE50074E6D4 /* store.cpp in Sources */, + 0635814E1EBF7AE50074E6D4 /* interceptor.cpp in Sources */, + 0635807D1EBF7AE50074E6D4 /* cl_frame.cpp in Sources */, + 063580D21EBF7AE50074E6D4 /* wallspec.cpp in Sources */, + 063580DF1EBF7AE50074E6D4 /* framemodel.cpp in Sources */, + 063581271EBF7AE50074E6D4 /* styledlogsinkformatter.cpp in Sources */, + 063581241EBF7AE50074E6D4 /* progress.cpp in Sources */, + 063580811EBF7AE50074E6D4 /* cl_player.cpp in Sources */, + 063581411EBF7AE50074E6D4 /* profilepickerwidget.cpp in Sources */, + 063581061EBF7AE50074E6D4 /* vrsettingsdialog.cpp in Sources */, + 0635816D1EBF7AE50074E6D4 /* api_console.cpp in Sources */, + 063580E81EBF7AE50074E6D4 /* b_main.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 0635771C1EBF3EB40074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 063574811EBF39880074E6D4 /* deng_shell */; + targetProxy = 0635771B1EBF3EB40074E6D4 /* PBXContainerItemProxy */; + }; + 0635771E1EBF3EB40074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 063575B31EBF3AD50074E6D4 /* deng_legacy */; + targetProxy = 0635771D1EBF3EB40074E6D4 /* PBXContainerItemProxy */; + }; + 063577201EBF3EB40074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0635768E1EBF3CD20074E6D4 /* deng_gui */; + targetProxy = 0635771F1EBF3EB40074E6D4 /* PBXContainerItemProxy */; + }; + 06357A7C1EBF5E8B0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 063577E71EBF42D10074E6D4 /* deng_appfw */; + targetProxy = 06357A7B1EBF5E8B0074E6D4 /* PBXContainerItemProxy */; + }; + 06357A7E1EBF5E8B0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0635784A1EBF43A30074E6D4 /* deng_doomsday */; + targetProxy = 06357A7D1EBF5E8B0074E6D4 /* PBXContainerItemProxy */; + }; + 06357B121EBF674F0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357A811EBF61C70074E6D4 /* deng_gamefw */; + targetProxy = 06357B111EBF674F0074E6D4 /* PBXContainerItemProxy */; + }; + 06357B141EBF674F0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357AF81EBF63770074E6D4 /* importdeh */; + targetProxy = 06357B131EBF674F0074E6D4 /* PBXContainerItemProxy */; + }; + 06357B2B1EBF69F00074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357B1D1EBF69C00074E6D4 /* importudmf */; + targetProxy = 06357B2A1EBF69F00074E6D4 /* PBXContainerItemProxy */; + }; + 06357CCD1EBF70AE0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357B321EBF6EBD0074E6D4 /* doom */; + targetProxy = 06357CCC1EBF70AE0074E6D4 /* PBXContainerItemProxy */; + }; + 06357CCF1EBF70AE0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357C451EBF70A20074E6D4 /* heretic */; + targetProxy = 06357CCE1EBF70AE0074E6D4 /* PBXContainerItemProxy */; + }; + 06357F4E1EBF79EB0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357F371EBF77A00074E6D4 /* audio_fmod */; + targetProxy = 06357F4D1EBF79EB0074E6D4 /* PBXContainerItemProxy */; + }; + 06357F501EBF79EB0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357D611EBF728D0074E6D4 /* hexen */; + targetProxy = 06357F4F1EBF79EB0074E6D4 /* PBXContainerItemProxy */; + }; + 06357F521EBF79EB0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 06357E671EBF76120074E6D4 /* doom64 */; + targetProxy = 06357F511EBF79EB0074E6D4 /* PBXContainerItemProxy */; + }; + 0635824A1EBFBA350074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 0635819B1EBFBA120074E6D4 /* assimp */; + targetProxy = 063582491EBFBA350074E6D4 /* PBXContainerItemProxy */; + }; + 0635830C1EC03E0C0074E6D4 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 063583071EC03DAD0074E6D4 /* Packages */; + targetProxy = 0635830B1EC03E0C0074E6D4 /* PBXContainerItemProxy */; + }; + 067AD9E21EBF154500B808B2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 067AD91D1EBF14E000B808B2 /* deng_core */; + targetProxy = 067AD9E11EBF154500B808B2 /* PBXContainerItemProxy */; + }; + 067AD9E41EBF154500B808B2 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 067AD9081EBF143600B808B2 /* importidtech1 */; + targetProxy = 067AD9E31EBF154500B808B2 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin PBXVariantGroup section */ + 068610761EBF01F700180814 /* LaunchScreen.storyboard */ = { + isa = PBXVariantGroup; + children = ( + 068610771EBF01F700180814 /* Base */, + ); + name = LaunchScreen.storyboard; + sourceTree = ""; + }; +/* End PBXVariantGroup section */ + +/* Begin XCBuildConfiguration section */ + 0635752A1EBF39880074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBSHELL__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 0635752B1EBF39880074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBSHELL__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063575D01EBF3AD50074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG__=1", + "__DOOMSDAY__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 063575D11EBF3AD50074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG__=1", + "__DOOMSDAY__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063576AB1EBF3CD20074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBGUI__=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + $SRCROOT/../external/assimp/include, + "$(inherited)", + ); + OTHER_CPLUSPLUSFLAGS = ( + $inherited, + "-Wno-address-of-packed-member", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 063576AC1EBF3CD20074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBGUI__=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + $SRCROOT/../external/assimp/include, + "$(inherited)", + ); + OTHER_CPLUSPLUSFLAGS = ( + $inherited, + "-Wno-address-of-packed-member", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063578041EBF42D10074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBAPPFW__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 063578051EBF42D10074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBAPPFW__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063578921EBF43A30074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBDOOMSDAY__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 063578931EBF43A30074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBDOOMSDAY__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357AEE1EBF61C70074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBGAMEFW__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357AEF1EBF61C70074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__LIBGAMEFW__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357B021EBF63770074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importdeh/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357B031EBF63770074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importdeh/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357B271EBF69C00074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + DENG_IMPORTUDMF_DEBUG, + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importudmf/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357B281EBF69C00074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importudmf/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357B3A1EBF6EBD0074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JDOOM__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/doom/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357B3B1EBF6EBD0074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JDOOM__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/doom/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357CC91EBF70A20074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JHERETIC__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/heretic/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357CCA1EBF70A20074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JHERETIC__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/heretic/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357DDF1EBF728D0074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JHEXEN__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/hexen/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357DE01EBF728D0074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JHEXEN__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/hexen/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357EEB1EBF76120074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JDOOM64__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/doom64/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357EEC1EBF76120074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__JDOOM64__=1", + "LIBDOOMSDAY_CUSTOM_MOBJ=1", + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/common/include, + $SRCROOT/../apps/plugins/doom64/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 06357F401EBF77A00074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + DENG_DSFMOD_DEBUG, + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/fmod/include, + $FMOD_DIR/api/lowlevel/inc, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 06357F411EBF77A00074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/fmod/include, + $FMOD_DIR/api/lowlevel/inc, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063582461EBFBA120074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSIMP_DEFINES = "ASSIMP_BUILD_NO_AC_IMPORTER ASSIMP_BUILD_NO_ASE_IMPORTER ASSIMP_BUILD_NO_ASSBIN_IMPORTER ASSIMP_BUILD_NO_ASSXML_IMPORTER ASSIMP_BUILD_NO_B3D_IMPORTER ASSIMP_BUILD_NO_BVH_IMPORTER ASSIMP_BUILD_NO_C4D_IMPORTER ASSIMP_BUILD_NO_DXF_IMPORTER ASSIMP_BUILD_NO_CSM_IMPORTER ASSIMP_BUILD_NO_HMP_IMPORTER ASSIMP_BUILD_NO_LWO_IMPORTER ASSIMP_BUILD_NO_LWS_IMPORTER ASSIMP_BUILD_NO_MDC_IMPORTER ASSIMP_BUILD_NO_NFF_IMPORTER ASSIMP_BUILD_NO_NDO_IMPORTER ASSIMP_BUILD_NO_OFF_IMPORTER ASSIMP_BUILD_NO_OGRE_IMPORTER ASSIMP_BUILD_NO_OPENGEX_IMPORTER ASSIMP_BUILD_NO_PLY_IMPORTER ASSIMP_BUILD_NO_MS3D_IMPORTER ASSIMP_BUILD_NO_COB_IMPORTER ASSIMP_BUILD_NO_IFC_IMPORTER ASSIMP_BUILD_NO_XGL_IMPORTER ASSIMP_BUILD_NO_Q3D_IMPORTER ASSIMP_BUILD_NO_Q3BSP_IMPORTER ASSIMP_BUILD_NO_RAW_IMPORTER ASSIMP_BUILD_NO_SIB_IMPORTER ASSIMP_BUILD_NO_SMD_IMPORTER ASSIMP_BUILD_NO_STL_IMPORTER ASSIMP_BUILD_NO_TERRAGEN_IMPORTER ASSIMP_BUILD_NO_3D_IMPORTER ASSIMP_BUILD_NO_X_IMPORTER ASSIMP_BUILD_NO_GLTF_IMPORTER ASSIMP_BUILD_NO_3MF_IMPORTER"; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG2__=1", + "$(inherited)", + $ASSIMP_DEFINES, + ); + HEADER_SEARCH_PATHS = ( + $SRCROOT/../external/assimp/include, + $SRCROOT/../xcode/Assimp, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + "-Wno-inconsistent-missing-override", + "-Wno-address-of-packed-member", + "-Wno-undefined-var-template", + "-Wno-conditional-uninitialized", + "-Wno-unreachable-code", + "-Wno-unused-function", + "-Wno-switch", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 063582471EBFBA120074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSIMP_DEFINES = "ASSIMP_BUILD_NO_AC_IMPORTER ASSIMP_BUILD_NO_ASE_IMPORTER ASSIMP_BUILD_NO_ASSBIN_IMPORTER ASSIMP_BUILD_NO_ASSXML_IMPORTER ASSIMP_BUILD_NO_B3D_IMPORTER ASSIMP_BUILD_NO_BVH_IMPORTER ASSIMP_BUILD_NO_C4D_IMPORTER ASSIMP_BUILD_NO_DXF_IMPORTER ASSIMP_BUILD_NO_CSM_IMPORTER ASSIMP_BUILD_NO_HMP_IMPORTER ASSIMP_BUILD_NO_LWO_IMPORTER ASSIMP_BUILD_NO_LWS_IMPORTER ASSIMP_BUILD_NO_MDC_IMPORTER ASSIMP_BUILD_NO_NFF_IMPORTER ASSIMP_BUILD_NO_NDO_IMPORTER ASSIMP_BUILD_NO_OFF_IMPORTER ASSIMP_BUILD_NO_OGRE_IMPORTER ASSIMP_BUILD_NO_OPENGEX_IMPORTER ASSIMP_BUILD_NO_PLY_IMPORTER ASSIMP_BUILD_NO_MS3D_IMPORTER ASSIMP_BUILD_NO_COB_IMPORTER ASSIMP_BUILD_NO_IFC_IMPORTER ASSIMP_BUILD_NO_XGL_IMPORTER ASSIMP_BUILD_NO_Q3D_IMPORTER ASSIMP_BUILD_NO_Q3BSP_IMPORTER ASSIMP_BUILD_NO_RAW_IMPORTER ASSIMP_BUILD_NO_SIB_IMPORTER ASSIMP_BUILD_NO_SMD_IMPORTER ASSIMP_BUILD_NO_STL_IMPORTER ASSIMP_BUILD_NO_TERRAGEN_IMPORTER ASSIMP_BUILD_NO_3D_IMPORTER ASSIMP_BUILD_NO_X_IMPORTER ASSIMP_BUILD_NO_GLTF_IMPORTER ASSIMP_BUILD_NO_3MF_IMPORTER"; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG2__=1", + "$(inherited)", + $ASSIMP_DEFINES, + ); + HEADER_SEARCH_PATHS = ( + $SRCROOT/../external/assimp/include, + $SRCROOT/../xcode/Assimp, + ); + OTHER_CPLUSPLUSFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + "-Wno-inconsistent-missing-override", + "-Wno-address-of-packed-member", + "-Wno-undefined-var-template", + "-Wno-conditional-uninitialized", + "-Wno-unreachable-code", + "-Wno-unused-function", + "-Wno-switch", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 063583091EC03DAD0074E6D4 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + DEBUGGING_SYMBOLS = YES; + DEBUG_INFORMATION_FORMAT = dwarf; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0635830A1EC03DAD0074E6D4 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_C_LANGUAGE_STANDARD = gnu99; + OTHER_CFLAGS = ""; + OTHER_LDFLAGS = ""; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; + 067AD9101EBF143600B808B2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + DENG_IMPORTIDTECH1_DEBUG, + "$(inherited)", + ); + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importidtech1/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 067AD9111EBF143600B808B2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = "$(inherited)"; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + $SRCROOT/../apps/plugins/importidtech1/include, + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 067AD9271EBF14E000B808B2 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG2__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Debug; + }; + 067AD9281EBF14E000B808B2 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + "__DENG2__=1", + "$(inherited)", + ); + PRODUCT_NAME = "$(TARGET_NAME)"; + SKIP_INSTALL = YES; + }; + name = Release; + }; + 0686107A1EBF01F700180814 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + DENG_DEFINES = "UNIX=1 DENG_IOS=1 DENG_MOBILE=1 DENG_APPLE=1 DENG_STATIC_LINK=1 DENG_NO_FIXED_ASM=1 DENG_BASE_DIR=\\\".\\\" LIBDENG2_MAJOR_VERSION=$DENG_VER_MAJOR LIBDENG2_MINOR_VERSION=$DENG_VER_MINOR LIBDENG2_PATCHLEVEL=$DENG_VER_PATCH LIBDENG2_RELEASE_LABEL=\\\"\\\" LIBDENG2_VERSION=\\\"$(DENG_VERSION)\\\" DENG_OPENGL_ES=30"; + DENG_DEFINES_DEBUG = "_DEBUG DEBUG=1"; + DENG_VERSION = "$(DENG_VER_MAJOR).$(DENG_VER_MINOR).$(DENG_VER_PATCH)"; + DENG_VER_MAJOR = 2; + DENG_VER_MINOR = 1; + DENG_VER_PATCH = 0; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + FMOD_DIR = "$HOME/SDK/iOS/FMOD\\ Programmers\\ API"; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + $DENG_DEFINES_DEBUG, + $DENG_DEFINES, + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + $QT_DIR/include/QtQuick, + $QT_DIR/include/QtWidgets, + $QT_DIR/include/QtOpenGLExtensions, + $QT_DIR/include/QtNetwork, + $QT_DIR/include/QtGui, + $QT_DIR/include/QtCore, + $QT_DIR/include, + $SRCROOT/../sdk/libcore/include, + $SRCROOT/../sdk/libappfw/include, + $SRCROOT/../sdk/libgui/include, + $SRCROOT/../sdk/libshell/include, + $SRCROOT/../sdk/liblegacy/include, + $SRCROOT/../apps/libdoomsday/include, + $SRCROOT/../apps/plugins/libgamefw/include, + $SRCROOT/../apps/api, + $SRCROOT/../external/lzss/include, + ); + IOS_PLATFORM = ""; + "IOS_PLATFORM[sdk=iphoneos*]" = iphoneos; + "IOS_PLATFORM[sdk=iphonesimulator*]" = iphonesimulator; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = YES; + ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + "-Wno-inconsistent-missing-override", + ); + QT_DIR = $HOME/SDK/Qt5.8.0/5.8/ios; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + USE_HEADERMAP = NO; + }; + name = Debug; + }; + 0686107B1EBF01F700180814 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "c++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + DENG_DEFINES = "UNIX=1 DENG_IOS=1 DENG_MOBILE=1 DENG_APPLE=1 DENG_STATIC_LINK=1 DENG_NO_FIXED_ASM=1 DENG_BASE_DIR=\\\".\\\" LIBDENG2_MAJOR_VERSION=$DENG_VER_MAJOR LIBDENG2_MINOR_VERSION=$DENG_VER_MINOR LIBDENG2_PATCHLEVEL=$DENG_VER_PATCH LIBDENG2_RELEASE_LABEL=\\\"\\\" LIBDENG2_VERSION=\\\"$(DENG_VERSION)\\\" DENG_OPENGL_ES=30"; + DENG_DEFINES_DEBUG = "_DEBUG DEBUG=1"; + DENG_VERSION = "$(DENG_VER_MAJOR).$(DENG_VER_MINOR).$(DENG_VER_PATCH)"; + DENG_VER_MAJOR = 2; + DENG_VER_MINOR = 1; + DENG_VER_PATCH = 0; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + FMOD_DIR = "$HOME/SDK/iOS/FMOD\\ Programmers\\ API"; + GCC_C_LANGUAGE_STANDARD = c11; + GCC_NO_COMMON_BLOCKS = YES; + GCC_PREPROCESSOR_DEFINITIONS = $DENG_DEFINES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + $QT_DIR/include/QtQuick, + $QT_DIR/include/QtWidgets, + $QT_DIR/include/QtOpenGLExtensions, + $QT_DIR/include/QtNetwork, + $QT_DIR/include/QtGui, + $QT_DIR/include/QtCore, + $QT_DIR/include, + $SRCROOT/../sdk/libcore/include, + $SRCROOT/../sdk/libappfw/include, + $SRCROOT/../sdk/libgui/include, + $SRCROOT/../sdk/libshell/include, + $SRCROOT/../sdk/liblegacy/include, + $SRCROOT/../apps/libdoomsday/include, + $SRCROOT/../apps/plugins/libgamefw/include, + $SRCROOT/../apps/api, + $SRCROOT/../external/lzss/include, + ); + IOS_PLATFORM = ""; + "IOS_PLATFORM[sdk=iphoneos*]" = iphoneos; + "IOS_PLATFORM[sdk=iphonesimulator*]" = iphonesimulator; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + ); + OTHER_CPLUSPLUSFLAGS = ( + "-fvisibility-inlines-hidden", + "-fvisibility=hidden", + "-Wno-documentation", + "-Wno-shorten-64-to-32", + "-Wno-inconsistent-missing-override", + ); + QT_DIR = $HOME/SDK/Qt5.8.0/5.8/ios; + SDKROOT = iphoneos; + TARGETED_DEVICE_FAMILY = "1,2"; + USER_HEADER_SEARCH_PATHS = ""; + USE_HEADERMAP = NO; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 0686107D1EBF01F700180814 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLIENT_DEFINES = "__CLIENT__=1 __DOOMSDAY__=1 DENG_NO_SDL=1 DENG_DISABLE_SDLMIXER=1"; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + $CLIENT_DEFINES, + $DENG_DEFINES_DEBUG, + $DENG_DEFINES, + ); + HEADER_SEARCH_PATHS = ( + $inherited, + $SRCROOT/../apps/client/include, + $SRCROOT/../apps/client/include/unix, + ); + INFOPLIST_FILE = Doomsday/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + $QT_DIR/lib, + $QT_DIR/plugins, + $QT_DIR/plugins/platforms, + $QT_DIR/plugins/imageformats, + $QT_DIR/qml/QtQuick.2, + $QT_DIR/qml/QtQuick/Controls.2, + $QT_DIR/qml/QtQuick/Controls.2/Universal, + $QT_DIR/qml/QtQuick/Templates.2, + $QT_DIR/qml/QtQuick/Layouts, + $QT_DIR/qml/QtQuick/Window.2, + $FMOD_DIR/api/lowlevel/lib, + ); + OTHER_LDFLAGS = ( + "-e", + _qt_main_wrapper, + "-lQt5Core_debug", + "-lQt5Network_debug", + "-lQt5Widgets_debug", + "-lQt5Quick_debug", + "-lQt5QuickControls2_debug", + "-lQt5QuickTemplates2_debug", + "-lQt5Qml_debug", + "-lQt5Gui_debug", + "-lQt5ClipboardSupport_debug", + "-lQt5FontDatabaseSupport_debug", + "-lQt5GraphicsSupport_debug", + "-lqtpcre_debug", + "-lqtlibpng_debug", + "-lqtharfbuzz_debug", + "-lqtfreetype_debug", + "-lqtquick2plugin_debug", + "-lwindowplugin_debug", + "-lqtquickcontrols2plugin_debug", + "-lqtquickcontrols2universalstyleplugin_debug", + "-lqtquicktemplates2plugin_debug", + "-lqquicklayoutsplugin_debug", + "-lqios_debug", + "-lqios_debug", + "-lqjpeg_debug", + "-lqgif_debug", + "-lqtga_debug", + "-lfmod_$(IOS_PLATFORM)", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.dengine.Doomsday; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 0686107E1EBF01F700180814 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + CLIENT_DEFINES = "__CLIENT__=1 __DOOMSDAY__=1 DENG_NO_SDL=1 DENG_DISABLE_SDLMIXER=1"; + DEVELOPMENT_TEAM = VS2RUWJAF3; + GCC_PREPROCESSOR_DEFINITIONS = ( + $CLIENT_DEFINES, + $DENG_DEFINES, + ); + HEADER_SEARCH_PATHS = ( + $inherited, + $SRCROOT/../apps/client/include, + $SRCROOT/../apps/client/include/unix, + ); + INFOPLIST_FILE = Doomsday/Info.plist; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; + LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + LIBRARY_SEARCH_PATHS = ( + $QT_DIR/lib, + $QT_DIR/plugins, + $QT_DIR/plugins/platforms, + $QT_DIR/plugins/imageformats, + $QT_DIR/qml/QtQuick.2, + $QT_DIR/qml/QtQuick/Controls.2, + $QT_DIR/qml/QtQuick/Controls.2/Universal, + $QT_DIR/qml/QtQuick/Templates.2, + $QT_DIR/qml/QtQuick/Layouts, + $QT_DIR/qml/QtQuick/Window.2, + $FMOD_DIR/api/lowlevel/lib, + ); + OTHER_LDFLAGS = ( + "-e", + _qt_main_wrapper, + "-lQt5Core", + "-lQt5Network", + "-lQt5Gui", + "-lQt5Quick", + "-lQt5QuickControls2", + "-lQt5QuickTemplates2", + "-lQt5Qml", + "-lQt5Widgets", + "-lQt5ClipboardSupport", + "-lQt5FontDatabaseSupport", + "-lQt5GraphicsSupport", + "-lqtpcre", + "-lqtlibpng", + "-lqtharfbuzz", + "-lqtfreetype", + "-lqtquick2plugin", + "-lwindowplugin", + "-lqquicklayoutsplugin", + "-lqtquickcontrols2plugin", + "-lqtquickcontrols2universalstyleplugin_debug", + "-lqtquicktemplates2plugin", + "-lqios", + "-lqjpeg", + "-lqtga", + "-lqgif", + "-lfmod_$(IOS_PLATFORM)", + ); + PRODUCT_BUNDLE_IDENTIFIER = net.dengine.Doomsday; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 063575291EBF39880074E6D4 /* Build configuration list for PBXNativeTarget "deng_shell" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0635752A1EBF39880074E6D4 /* Debug */, + 0635752B1EBF39880074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063575CF1EBF3AD50074E6D4 /* Build configuration list for PBXNativeTarget "deng_legacy" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063575D01EBF3AD50074E6D4 /* Debug */, + 063575D11EBF3AD50074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063576AA1EBF3CD20074E6D4 /* Build configuration list for PBXNativeTarget "deng_gui" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063576AB1EBF3CD20074E6D4 /* Debug */, + 063576AC1EBF3CD20074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063578031EBF42D10074E6D4 /* Build configuration list for PBXNativeTarget "deng_appfw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063578041EBF42D10074E6D4 /* Debug */, + 063578051EBF42D10074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063578911EBF43A30074E6D4 /* Build configuration list for PBXNativeTarget "deng_doomsday" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063578921EBF43A30074E6D4 /* Debug */, + 063578931EBF43A30074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357AED1EBF61C70074E6D4 /* Build configuration list for PBXNativeTarget "deng_gamefw" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357AEE1EBF61C70074E6D4 /* Debug */, + 06357AEF1EBF61C70074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357B011EBF63770074E6D4 /* Build configuration list for PBXNativeTarget "importdeh" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357B021EBF63770074E6D4 /* Debug */, + 06357B031EBF63770074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357B261EBF69C00074E6D4 /* Build configuration list for PBXNativeTarget "importudmf" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357B271EBF69C00074E6D4 /* Debug */, + 06357B281EBF69C00074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357B391EBF6EBD0074E6D4 /* Build configuration list for PBXNativeTarget "doom" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357B3A1EBF6EBD0074E6D4 /* Debug */, + 06357B3B1EBF6EBD0074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357CC81EBF70A20074E6D4 /* Build configuration list for PBXNativeTarget "heretic" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357CC91EBF70A20074E6D4 /* Debug */, + 06357CCA1EBF70A20074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357DDE1EBF728D0074E6D4 /* Build configuration list for PBXNativeTarget "hexen" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357DDF1EBF728D0074E6D4 /* Debug */, + 06357DE01EBF728D0074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357EEA1EBF76120074E6D4 /* Build configuration list for PBXNativeTarget "doom64" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357EEB1EBF76120074E6D4 /* Debug */, + 06357EEC1EBF76120074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 06357F3F1EBF77A00074E6D4 /* Build configuration list for PBXNativeTarget "audio_fmod" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 06357F401EBF77A00074E6D4 /* Debug */, + 06357F411EBF77A00074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063582451EBFBA120074E6D4 /* Build configuration list for PBXNativeTarget "assimp" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063582461EBFBA120074E6D4 /* Debug */, + 063582471EBFBA120074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 063583081EC03DAD0074E6D4 /* Build configuration list for PBXLegacyTarget "Packages" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 063583091EC03DAD0074E6D4 /* Debug */, + 0635830A1EC03DAD0074E6D4 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 067AD90F1EBF143600B808B2 /* Build configuration list for PBXNativeTarget "importidtech1" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 067AD9101EBF143600B808B2 /* Debug */, + 067AD9111EBF143600B808B2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 067AD9261EBF14E000B808B2 /* Build configuration list for PBXNativeTarget "deng_core" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 067AD9271EBF14E000B808B2 /* Debug */, + 067AD9281EBF14E000B808B2 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 068610531EBF01F700180814 /* Build configuration list for PBXProject "Doomsday" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0686107A1EBF01F700180814 /* Debug */, + 0686107B1EBF01F700180814 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 0686107C1EBF01F700180814 /* Build configuration list for PBXNativeTarget "Doomsday" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 0686107D1EBF01F700180814 /* Debug */, + 0686107E1EBF01F700180814 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 068610501EBF01F700180814 /* Project object */; +} diff -Nru doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday.xcodeproj/project.xcworkspace/contents.xcworkspacedata doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday.xcodeproj/project.xcworkspace/contents.xcworkspacedata --- doomsday-stable-2.0.3.2464+xenial/doomsday/xcode/Doomsday.xcodeproj/project.xcworkspace/contents.xcworkspacedata 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/doomsday/xcode/Doomsday.xcodeproj/project.xcworkspace/contents.xcworkspacedata 2018-12-11 07:08:24.000000000 +0000 @@ -0,0 +1,7 @@ + + + + + diff -Nru doomsday-stable-2.0.3.2464+xenial/.gitignore doomsday-stable-2.1.0.2900+xenial/.gitignore --- doomsday-stable-2.0.3.2464+xenial/.gitignore 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/.gitignore 2018-12-11 07:08:16.000000000 +0000 @@ -33,3 +33,7 @@ precompiled.h.cpp *.h.orig *.cpp.orig +*.xcuserstate +*.xcuserdatad +*.xcscmblueprint +.vscode diff -Nru doomsday-stable-2.0.3.2464+xenial/README.md doomsday-stable-2.1.0.2900+xenial/README.md --- doomsday-stable-2.0.3.2464+xenial/README.md 2017-10-01 00:40:13.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/README.md 2018-12-11 07:08:16.000000000 +0000 @@ -38,9 +38,9 @@ [SDL 2](http://libsdl.org) is needed for game controller input (e.g., joysticks and gamepads). Additionally, SDL2_mixer can be used for audio output (not required). -### FMOD Ex +### FMOD Studio -The optional FMOD audio plugin requires the [FMOD Ex Programmer's API](http://fmod.org/). +The optional FMOD audio plugin requires the [FMOD Studio Low-Level Programmer API](http://www.fmod.org/download). ## Branches diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/Browser.php doomsday-stable-2.1.0.2900+xenial/weblib/Browser.php --- doomsday-stable-2.0.3.2464+xenial/weblib/Browser.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/Browser.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,1358 @@ +getBrowser() == Browser::BROWSER_FIREFOX && $browser->getVersion() >= 2 ) { + * echo 'You have FireFox version 2 or greater'; + * } + * + * User Agents Sampled from: http://www.useragentstring.com/ + * + * This implementation is based on the original work from Gary White + * http://apptools.com/phptools/browser/ + * + */ + +class Browser +{ + private $_agent = ''; + private $_browser_name = ''; + private $_version = ''; + private $_platform = ''; + private $_os = ''; + private $_is_aol = false; + private $_is_mobile = false; + private $_is_tablet = false; + private $_is_robot = false; + private $_is_facebook = false; + private $_aol_version = ''; + + const BROWSER_UNKNOWN = 'unknown'; + const VERSION_UNKNOWN = 'unknown'; + + const BROWSER_OPERA = 'Opera'; // http://www.opera.com/ + const BROWSER_OPERA_MINI = 'Opera Mini'; // http://www.opera.com/mini/ + const BROWSER_WEBTV = 'WebTV'; // http://www.webtv.net/pc/ + const BROWSER_EDGE = 'Edge'; // https://www.microsoft.com/edge + const BROWSER_IE = 'Internet Explorer'; // http://www.microsoft.com/ie/ + const BROWSER_POCKET_IE = 'Pocket Internet Explorer'; // http://en.wikipedia.org/wiki/Internet_Explorer_Mobile + const BROWSER_KONQUEROR = 'Konqueror'; // http://www.konqueror.org/ + const BROWSER_ICAB = 'iCab'; // http://www.icab.de/ + const BROWSER_OMNIWEB = 'OmniWeb'; // http://www.omnigroup.com/applications/omniweb/ + const BROWSER_FIREBIRD = 'Firebird'; // http://www.ibphoenix.com/ + const BROWSER_FIREFOX = 'Firefox'; // http://www.mozilla.com/en-US/firefox/firefox.html + const BROWSER_ICEWEASEL = 'Iceweasel'; // http://www.geticeweasel.org/ + const BROWSER_SHIRETOKO = 'Shiretoko'; // http://wiki.mozilla.org/Projects/shiretoko + const BROWSER_MOZILLA = 'Mozilla'; // http://www.mozilla.com/en-US/ + const BROWSER_AMAYA = 'Amaya'; // http://www.w3.org/Amaya/ + const BROWSER_LYNX = 'Lynx'; // http://en.wikipedia.org/wiki/Lynx + const BROWSER_SAFARI = 'Safari'; // http://apple.com + const BROWSER_IPHONE = 'iPhone'; // http://apple.com + const BROWSER_IPOD = 'iPod'; // http://apple.com + const BROWSER_IPAD = 'iPad'; // http://apple.com + const BROWSER_CHROME = 'Chrome'; // http://www.google.com/chrome + const BROWSER_ANDROID = 'Android'; // http://www.android.com/ + const BROWSER_GOOGLEBOT = 'GoogleBot'; // http://en.wikipedia.org/wiki/Googlebot + const BROWSER_SLURP = 'Yahoo! Slurp'; // http://en.wikipedia.org/wiki/Yahoo!_Slurp + const BROWSER_W3CVALIDATOR = 'W3C Validator'; // http://validator.w3.org/ + const BROWSER_BLACKBERRY = 'BlackBerry'; // http://www.blackberry.com/ + const BROWSER_ICECAT = 'IceCat'; // http://en.wikipedia.org/wiki/GNU_IceCat + const BROWSER_NOKIA_S60 = 'Nokia S60 OSS Browser'; // http://en.wikipedia.org/wiki/Web_Browser_for_S60 + const BROWSER_NOKIA = 'Nokia Browser'; // * all other WAP-based browsers on the Nokia Platform + const BROWSER_MSN = 'MSN Browser'; // http://explorer.msn.com/ + const BROWSER_MSNBOT = 'MSN Bot'; // http://search.msn.com/msnbot.htm + const BROWSER_BINGBOT = 'Bing Bot'; // http://en.wikipedia.org/wiki/Bingbot + const BROWSER_VIVALDI = 'Vivalidi'; // https://vivaldi.com/ + + const BROWSER_NETSCAPE_NAVIGATOR = 'Netscape Navigator'; // http://browser.netscape.com/ (DEPRECATED) + const BROWSER_GALEON = 'Galeon'; // http://galeon.sourceforge.net/ (DEPRECATED) + const BROWSER_NETPOSITIVE = 'NetPositive'; // http://en.wikipedia.org/wiki/NetPositive (DEPRECATED) + const BROWSER_PHOENIX = 'Phoenix'; // http://en.wikipedia.org/wiki/History_of_Mozilla_Firefox (DEPRECATED) + const BROWSER_PLAYSTATION = "PlayStation"; + + const PLATFORM_UNKNOWN = 'unknown'; + const PLATFORM_WINDOWS = 'Windows'; + const PLATFORM_WINDOWS_CE = 'Windows CE'; + const PLATFORM_APPLE = 'Apple'; + const PLATFORM_LINUX = 'Linux'; + const PLATFORM_OS2 = 'OS/2'; + const PLATFORM_BEOS = 'BeOS'; + const PLATFORM_IPHONE = 'iPhone'; + const PLATFORM_IPOD = 'iPod'; + const PLATFORM_IPAD = 'iPad'; + const PLATFORM_BLACKBERRY = 'BlackBerry'; + const PLATFORM_NOKIA = 'Nokia'; + const PLATFORM_FREEBSD = 'FreeBSD'; + const PLATFORM_OPENBSD = 'OpenBSD'; + const PLATFORM_NETBSD = 'NetBSD'; + const PLATFORM_SUNOS = 'SunOS'; + const PLATFORM_OPENSOLARIS = 'OpenSolaris'; + const PLATFORM_ANDROID = 'Android'; + const PLATFORM_PLAYSTATION = "Sony PlayStation"; + + const OPERATING_SYSTEM_UNKNOWN = 'unknown'; + + /** + * Class constructor + */ + public function __construct($userAgent = "") + { + $this->reset(); + if ($userAgent != "") { + $this->setUserAgent($userAgent); + } else { + $this->determine(); + } + } + + /** + * Reset all properties + */ + public function reset() + { + $this->_agent = isset($_SERVER['HTTP_USER_AGENT']) ? $_SERVER['HTTP_USER_AGENT'] : ""; + $this->_browser_name = self::BROWSER_UNKNOWN; + $this->_version = self::VERSION_UNKNOWN; + $this->_platform = self::PLATFORM_UNKNOWN; + $this->_os = self::OPERATING_SYSTEM_UNKNOWN; + $this->_is_aol = false; + $this->_is_mobile = false; + $this->_is_tablet = false; + $this->_is_robot = false; + $this->_is_facebook = false; + $this->_aol_version = self::VERSION_UNKNOWN; + } + + /** + * Check to see if the specific browser is valid + * @param string $browserName + * @return bool True if the browser is the specified browser + */ + function isBrowser($browserName) + { + return (0 == strcasecmp($this->_browser_name, trim($browserName))); + } + + /** + * The name of the browser. All return types are from the class contants + * @return string Name of the browser + */ + public function getBrowser() + { + return $this->_browser_name; + } + + /** + * Set the name of the browser + * @param $browser string The name of the Browser + */ + public function setBrowser($browser) + { + $this->_browser_name = $browser; + } + + /** + * The name of the platform. All return types are from the class contants + * @return string Name of the browser + */ + public function getPlatform() + { + return $this->_platform; + } + + /** + * Set the name of the platform + * @param string $platform The name of the Platform + */ + public function setPlatform($platform) + { + $this->_platform = $platform; + } + + /** + * The version of the browser. + * @return string Version of the browser (will only contain alpha-numeric characters and a period) + */ + public function getVersion() + { + return $this->_version; + } + + /** + * Set the version of the browser + * @param string $version The version of the Browser + */ + public function setVersion($version) + { + $this->_version = preg_replace('/[^0-9,.,a-z,A-Z-]/', '', $version); + } + + /** + * The version of AOL. + * @return string Version of AOL (will only contain alpha-numeric characters and a period) + */ + public function getAolVersion() + { + return $this->_aol_version; + } + + /** + * Set the version of AOL + * @param string $version The version of AOL + */ + public function setAolVersion($version) + { + $this->_aol_version = preg_replace('/[^0-9,.,a-z,A-Z]/', '', $version); + } + + /** + * Is the browser from AOL? + * @return boolean True if the browser is from AOL otherwise false + */ + public function isAol() + { + return $this->_is_aol; + } + + /** + * Is the browser from a mobile device? + * @return boolean True if the browser is from a mobile device otherwise false + */ + public function isMobile() + { + return $this->_is_mobile; + } + + /** + * Is the browser from a tablet device? + * @return boolean True if the browser is from a tablet device otherwise false + */ + public function isTablet() + { + return $this->_is_tablet; + } + + /** + * Is the browser from a robot (ex Slurp,GoogleBot)? + * @return boolean True if the browser is from a robot otherwise false + */ + public function isRobot() + { + return $this->_is_robot; + } + + /** + * Is the browser from facebook? + * @return boolean True if the browser is from facebook otherwise false + */ + public function isFacebook() + { + return $this->_is_facebook; + } + + /** + * Set the browser to be from AOL + * @param $isAol + */ + public function setAol($isAol) + { + $this->_is_aol = $isAol; + } + + /** + * Set the Browser to be mobile + * @param boolean $value is the browser a mobile browser or not + */ + protected function setMobile($value = true) + { + $this->_is_mobile = $value; + } + + /** + * Set the Browser to be tablet + * @param boolean $value is the browser a tablet browser or not + */ + protected function setTablet($value = true) + { + $this->_is_tablet = $value; + } + + /** + * Set the Browser to be a robot + * @param boolean $value is the browser a robot or not + */ + protected function setRobot($value = true) + { + $this->_is_robot = $value; + } + + /** + * Set the Browser to be a Facebook request + * @param boolean $value is the browser a robot or not + */ + protected function setFacebook($value = true) + { + $this->_is_facebook = $value; + } + + /** + * Get the user agent value in use to determine the browser + * @return string The user agent from the HTTP header + */ + public function getUserAgent() + { + return $this->_agent; + } + + /** + * Set the user agent value (the construction will use the HTTP header value - this will overwrite it) + * @param string $agent_string The value for the User Agent + */ + public function setUserAgent($agent_string) + { + $this->reset(); + $this->_agent = $agent_string; + $this->determine(); + } + + /** + * Used to determine if the browser is actually "chromeframe" + * @since 1.7 + * @return boolean True if the browser is using chromeframe + */ + public function isChromeFrame() + { + return (strpos($this->_agent, "chromeframe") !== false); + } + + /** + * Returns a formatted string with a summary of the details of the browser. + * @return string formatted string with a summary of the browser + */ + public function __toString() + { + return "Browser Name: {$this->getBrowser()}
\n" . + "Browser Version: {$this->getVersion()}
\n" . + "Browser User Agent String: {$this->getUserAgent()}
\n" . + "Platform: {$this->getPlatform()}
"; + } + + /** + * Protected routine to calculate and determine what the browser is in use (including platform) + */ + protected function determine() + { + $this->checkPlatform(); + $this->checkBrowsers(); + $this->checkForAol(); + } + + /** + * Protected routine to determine the browser type + * @return boolean True if the browser was detected otherwise false + */ + protected function checkBrowsers() + { + return ( + // well-known, well-used + // Special Notes: + // (1) Opera must be checked before FireFox due to the odd + // user agents used in some older versions of Opera + // (2) WebTV is strapped onto Internet Explorer so we must + // check for WebTV before IE + // (3) (deprecated) Galeon is based on Firefox and needs to be + // tested before Firefox is tested + // (4) OmniWeb is based on Safari so OmniWeb check must occur + // before Safari + // (5) Netscape 9+ is based on Firefox so Netscape checks + // before FireFox are necessary + // (6) Vivalid is UA contains both Firefox and Chrome so Vivalid checks + // before Firefox and Chrome + $this->checkBrowserWebTv() || + $this->checkBrowserEdge() || + $this->checkBrowserInternetExplorer() || + $this->checkBrowserOpera() || + $this->checkBrowserGaleon() || + $this->checkBrowserNetscapeNavigator9Plus() || + $this->checkBrowserVivaldi() || + $this->checkBrowserFirefox() || + $this->checkBrowserChrome() || + $this->checkBrowserOmniWeb() || + + // common mobile + $this->checkBrowserAndroid() || + $this->checkBrowseriPad() || + $this->checkBrowseriPod() || + $this->checkBrowseriPhone() || + $this->checkBrowserBlackBerry() || + $this->checkBrowserNokia() || + + // common bots + $this->checkBrowserGoogleBot() || + $this->checkBrowserMSNBot() || + $this->checkBrowserBingBot() || + $this->checkBrowserSlurp() || + + // check for facebook external hit when loading URL + $this->checkFacebookExternalHit() || + + // WebKit base check (post mobile and others) + $this->checkBrowserSafari() || + + // everyone else + $this->checkBrowserNetPositive() || + $this->checkBrowserFirebird() || + $this->checkBrowserKonqueror() || + $this->checkBrowserIcab() || + $this->checkBrowserPhoenix() || + $this->checkBrowserAmaya() || + $this->checkBrowserLynx() || + $this->checkBrowserShiretoko() || + $this->checkBrowserIceCat() || + $this->checkBrowserIceweasel() || + $this->checkBrowserW3CValidator() || + $this->checkBrowserPlayStation() || + $this->checkBrowserMozilla() /* Mozilla is such an open standard that you must check it last */ + ); + } + + /** + * Determine if the user is using a BlackBerry (last updated 1.7) + * @return boolean True if the browser is the BlackBerry browser otherwise false + */ + protected function checkBrowserBlackBerry() + { + if (stripos($this->_agent, 'blackberry') !== false) { + $aresult = explode("/", stristr($this->_agent, "BlackBerry")); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_BLACKBERRY; + $this->setMobile(true); + return true; + } + } + return false; + } + + /** + * Determine if the user is using an AOL User Agent (last updated 1.7) + * @return boolean True if the browser is from AOL otherwise false + */ + protected function checkForAol() + { + $this->setAol(false); + $this->setAolVersion(self::VERSION_UNKNOWN); + + if (stripos($this->_agent, 'aol') !== false) { + $aversion = explode(' ', stristr($this->_agent, 'AOL')); + if (isset($aversion[1])) { + $this->setAol(true); + $this->setAolVersion(preg_replace('/[^0-9\.a-z]/i', '', $aversion[1])); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the GoogleBot or not (last updated 1.7) + * @return boolean True if the browser is the GoogletBot otherwise false + */ + protected function checkBrowserGoogleBot() + { + if (stripos($this->_agent, 'googlebot') !== false) { + $aresult = explode('/', stristr($this->_agent, 'googlebot')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(';', '', $aversion[0])); + $this->_browser_name = self::BROWSER_GOOGLEBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the MSNBot or not (last updated 1.9) + * @return boolean True if the browser is the MSNBot otherwise false + */ + protected function checkBrowserMSNBot() + { + if (stripos($this->_agent, "msnbot") !== false) { + $aresult = explode("/", stristr($this->_agent, "msnbot")); + if (isset($aresult[1])) { + $aversion = explode(" ", $aresult[1]); + $this->setVersion(str_replace(";", "", $aversion[0])); + $this->_browser_name = self::BROWSER_MSNBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the BingBot or not (last updated 1.9) + * @return boolean True if the browser is the BingBot otherwise false + */ + protected function checkBrowserBingBot() + { + if (stripos($this->_agent, "bingbot") !== false) { + $aresult = explode("/", stristr($this->_agent, "bingbot")); + if (isset($aresult[1])) { + $aversion = explode(" ", $aresult[1]); + $this->setVersion(str_replace(";", "", $aversion[0])); + $this->_browser_name = self::BROWSER_BINGBOT; + $this->setRobot(true); + return true; + } + } + return false; + } + + /** + * Determine if the browser is the W3C Validator or not (last updated 1.7) + * @return boolean True if the browser is the W3C Validator otherwise false + */ + protected function checkBrowserW3CValidator() + { + if (stripos($this->_agent, 'W3C-checklink') !== false) { + $aresult = explode('/', stristr($this->_agent, 'W3C-checklink')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + return true; + } + } else if (stripos($this->_agent, 'W3C_Validator') !== false) { + // Some of the Validator versions do not delineate w/ a slash - add it back in + $ua = str_replace("W3C_Validator ", "W3C_Validator/", $this->_agent); + $aresult = explode('/', stristr($ua, 'W3C_Validator')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + return true; + } + } else if (stripos($this->_agent, 'W3C-mobileOK') !== false) { + $this->_browser_name = self::BROWSER_W3CVALIDATOR; + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is the Yahoo! Slurp Robot or not (last updated 1.7) + * @return boolean True if the browser is the Yahoo! Slurp Robot otherwise false + */ + protected function checkBrowserSlurp() + { + if (stripos($this->_agent, 'slurp') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Slurp')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->_browser_name = self::BROWSER_SLURP; + $this->setRobot(true); + $this->setMobile(false); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Edge or not + * @return boolean True if the browser is Edge otherwise false + */ + protected function checkBrowserEdge() + { + if( stripos($this->_agent,'Edge/') !== false ) { + $aresult = explode('/', stristr($this->_agent, 'Edge')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_EDGE); + if(stripos($this->_agent, 'Windows Phone') !== false || stripos($this->_agent, 'Android') !== false) { + $this->setMobile(true); + } + return true; + } + } + return false; + } + + /** + * Determine if the browser is Internet Explorer or not (last updated 1.7) + * @return boolean True if the browser is Internet Explorer otherwise false + */ + protected function checkBrowserInternetExplorer() + { + // Test for IE11 + if( stripos($this->_agent,'Trident/7.0; rv:11.0') !== false ) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion('11.0'); + return true; + } + // Test for v1 - v1.5 IE + else if (stripos($this->_agent, 'microsoft internet explorer') !== false) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion('1.0'); + $aresult = stristr($this->_agent, '/'); + if (preg_match('/308|425|426|474|0b1/i', $aresult)) { + $this->setVersion('1.5'); + } + return true; + } // Test for versions > 1.5 + else if (stripos($this->_agent, 'msie') !== false && stripos($this->_agent, 'opera') === false) { + // See if the browser is the odd MSN Explorer + if (stripos($this->_agent, 'msnb') !== false) { + $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'MSN')); + if (isset($aresult[1])) { + $this->setBrowser(self::BROWSER_MSN); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); + return true; + } + } + $aresult = explode(' ', stristr(str_replace(';', '; ', $this->_agent), 'msie')); + if (isset($aresult[1])) { + $this->setBrowser(self::BROWSER_IE); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aresult[1])); + if(stripos($this->_agent, 'IEMobile') !== false) { + $this->setBrowser(self::BROWSER_POCKET_IE); + $this->setMobile(true); + } + return true; + } + } // Test for versions > IE 10 + else if(stripos($this->_agent, 'trident') !== false) { + $this->setBrowser(self::BROWSER_IE); + $result = explode('rv:', $this->_agent); + if (isset($result[1])) { + $this->setVersion(preg_replace('/[^0-9.]+/', '', $result[1])); + $this->_agent = str_replace(array("Mozilla", "Gecko"), "MSIE", $this->_agent); + } + } // Test for Pocket IE + else if (stripos($this->_agent, 'mspie') !== false || stripos($this->_agent, 'pocket') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'mspie')); + if (isset($aresult[1])) { + $this->setPlatform(self::PLATFORM_WINDOWS_CE); + $this->setBrowser(self::BROWSER_POCKET_IE); + $this->setMobile(true); + + if (stripos($this->_agent, 'mspie') !== false) { + $this->setVersion($aresult[1]); + } else { + $aversion = explode('/', $this->_agent); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + } + } + return true; + } + } + return false; + } + + /** + * Determine if the browser is Opera or not (last updated 1.7) + * @return boolean True if the browser is Opera otherwise false + */ + protected function checkBrowserOpera() + { + if (stripos($this->_agent, 'opera mini') !== false) { + $resultant = stristr($this->_agent, 'opera mini'); + if (preg_match('/\//', $resultant)) { + $aresult = explode('/', $resultant); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } else { + $aversion = explode(' ', stristr($resultant, 'opera mini')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + } + } + $this->_browser_name = self::BROWSER_OPERA_MINI; + $this->setMobile(true); + return true; + } else if (stripos($this->_agent, 'opera') !== false) { + $resultant = stristr($this->_agent, 'opera'); + if (preg_match('/Version\/(1*.*)$/', $resultant, $matches)) { + $this->setVersion($matches[1]); + } else if (preg_match('/\//', $resultant)) { + $aresult = explode('/', str_replace("(", " ", $resultant)); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } else { + $aversion = explode(' ', stristr($resultant, 'opera')); + $this->setVersion(isset($aversion[1]) ? $aversion[1] : ""); + } + if (stripos($this->_agent, 'Opera Mobi') !== false) { + $this->setMobile(true); + } + $this->_browser_name = self::BROWSER_OPERA; + return true; + } else if (stripos($this->_agent, 'OPR') !== false) { + $resultant = stristr($this->_agent, 'OPR'); + if (preg_match('/\//', $resultant)) { + $aresult = explode('/', str_replace("(", " ", $resultant)); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } + } + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } + $this->_browser_name = self::BROWSER_OPERA; + return true; + } + return false; + } + + /** + * Determine if the browser is Chrome or not (last updated 1.7) + * @return boolean True if the browser is Chrome otherwise false + */ + protected function checkBrowserChrome() + { + if (stripos($this->_agent, 'Chrome') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Chrome')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_CHROME); + //Chrome on Android + if (stripos($this->_agent, 'Android') !== false) { + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + } + return true; + } + } + return false; + } + + + /** + * Determine if the browser is WebTv or not (last updated 1.7) + * @return boolean True if the browser is WebTv otherwise false + */ + protected function checkBrowserWebTv() + { + if (stripos($this->_agent, 'webtv') !== false) { + $aresult = explode('/', stristr($this->_agent, 'webtv')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_WEBTV); + return true; + } + } + return false; + } + + /** + * Determine if the browser is NetPositive or not (last updated 1.7) + * @return boolean True if the browser is NetPositive otherwise false + */ + protected function checkBrowserNetPositive() + { + if (stripos($this->_agent, 'NetPositive') !== false) { + $aresult = explode('/', stristr($this->_agent, 'NetPositive')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion(str_replace(array('(', ')', ';'), '', $aversion[0])); + $this->setBrowser(self::BROWSER_NETPOSITIVE); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Galeon or not (last updated 1.7) + * @return boolean True if the browser is Galeon otherwise false + */ + protected function checkBrowserGaleon() + { + if (stripos($this->_agent, 'galeon') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'galeon')); + $aversion = explode('/', $aresult[0]); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_GALEON); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Konqueror or not (last updated 1.7) + * @return boolean True if the browser is Konqueror otherwise false + */ + protected function checkBrowserKonqueror() + { + if (stripos($this->_agent, 'Konqueror') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'Konqueror')); + $aversion = explode('/', $aresult[0]); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_KONQUEROR); + return true; + } + } + return false; + } + + /** + * Determine if the browser is iCab or not (last updated 1.7) + * @return boolean True if the browser is iCab otherwise false + */ + protected function checkBrowserIcab() + { + if (stripos($this->_agent, 'icab') !== false) { + $aversion = explode(' ', stristr(str_replace('/', ' ', $this->_agent), 'icab')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_ICAB); + return true; + } + } + return false; + } + + /** + * Determine if the browser is OmniWeb or not (last updated 1.7) + * @return boolean True if the browser is OmniWeb otherwise false + */ + protected function checkBrowserOmniWeb() + { + if (stripos($this->_agent, 'omniweb') !== false) { + $aresult = explode('/', stristr($this->_agent, 'omniweb')); + $aversion = explode(' ', isset($aresult[1]) ? $aresult[1] : ""); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_OMNIWEB); + return true; + } + return false; + } + + /** + * Determine if the browser is Phoenix or not (last updated 1.7) + * @return boolean True if the browser is Phoenix otherwise false + */ + protected function checkBrowserPhoenix() + { + if (stripos($this->_agent, 'Phoenix') !== false) { + $aversion = explode('/', stristr($this->_agent, 'Phoenix')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_PHOENIX); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Firebird or not (last updated 1.7) + * @return boolean True if the browser is Firebird otherwise false + */ + protected function checkBrowserFirebird() + { + if (stripos($this->_agent, 'Firebird') !== false) { + $aversion = explode('/', stristr($this->_agent, 'Firebird')); + if (isset($aversion[1])) { + $this->setVersion($aversion[1]); + $this->setBrowser(self::BROWSER_FIREBIRD); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Netscape Navigator 9+ or not (last updated 1.7) + * NOTE: (http://browser.netscape.com/ - Official support ended on March 1st, 2008) + * @return boolean True if the browser is Netscape Navigator 9+ otherwise false + */ + protected function checkBrowserNetscapeNavigator9Plus() + { + if (stripos($this->_agent, 'Firefox') !== false && preg_match('/Navigator\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); + return true; + } else if (stripos($this->_agent, 'Firefox') === false && preg_match('/Netscape6?\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_NETSCAPE_NAVIGATOR); + return true; + } + return false; + } + + /** + * Determine if the browser is Shiretoko or not (https://wiki.mozilla.org/Projects/shiretoko) (last updated 1.7) + * @return boolean True if the browser is Shiretoko otherwise false + */ + protected function checkBrowserShiretoko() + { + if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/Shiretoko\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_SHIRETOKO); + return true; + } + return false; + } + + /** + * Determine if the browser is Ice Cat or not (http://en.wikipedia.org/wiki/GNU_IceCat) (last updated 1.7) + * @return boolean True if the browser is Ice Cat otherwise false + */ + protected function checkBrowserIceCat() + { + if (stripos($this->_agent, 'Mozilla') !== false && preg_match('/IceCat\/([^ ]*)/i', $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_ICECAT); + return true; + } + return false; + } + + /** + * Determine if the browser is Nokia or not (last updated 1.7) + * @return boolean True if the browser is Nokia otherwise false + */ + protected function checkBrowserNokia() + { + if (preg_match("/Nokia([^\/]+)\/([^ SP]+)/i", $this->_agent, $matches)) { + $this->setVersion($matches[2]); + if (stripos($this->_agent, 'Series60') !== false || strpos($this->_agent, 'S60') !== false) { + $this->setBrowser(self::BROWSER_NOKIA_S60); + } else { + $this->setBrowser(self::BROWSER_NOKIA); + } + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is Firefox or not (last updated 1.7) + * @return boolean True if the browser is Firefox otherwise false + */ + protected function checkBrowserFirefox() + { + if (stripos($this->_agent, 'safari') === false) { + if (preg_match("/Firefox[\/ \(]([^ ;\)]+)/i", $this->_agent, $matches)) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_FIREFOX); + //Firefox on Android + if (stripos($this->_agent, 'Android') !== false) { + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + } + return true; + } else if (preg_match("/Firefox$/i", $this->_agent, $matches)) { + $this->setVersion(""); + $this->setBrowser(self::BROWSER_FIREFOX); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Firefox or not (last updated 1.7) + * @return boolean True if the browser is Firefox otherwise false + */ + protected function checkBrowserIceweasel() + { + if (stripos($this->_agent, 'Iceweasel') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Iceweasel')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_ICEWEASEL); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Mozilla or not (last updated 1.7) + * @return boolean True if the browser is Mozilla otherwise false + */ + protected function checkBrowserMozilla() + { + if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { + $aversion = explode(' ', stristr($this->_agent, 'rv:')); + preg_match('/rv:[0-9].[0-9][a-b]?/i', $this->_agent, $aversion); + $this->setVersion(str_replace('rv:', '', $aversion[0])); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/rv:[0-9]\.[0-9]/i', $this->_agent) && stripos($this->_agent, 'netscape') === false) { + $aversion = explode('', stristr($this->_agent, 'rv:')); + $this->setVersion(str_replace('rv:', '', $aversion[0])); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } else if (stripos($this->_agent, 'mozilla') !== false && preg_match('/mozilla\/([^ ]*)/i', $this->_agent, $matches) && stripos($this->_agent, 'netscape') === false) { + $this->setVersion($matches[1]); + $this->setBrowser(self::BROWSER_MOZILLA); + return true; + } + return false; + } + + /** + * Determine if the browser is Lynx or not (last updated 1.7) + * @return boolean True if the browser is Lynx otherwise false + */ + protected function checkBrowserLynx() + { + if (stripos($this->_agent, 'lynx') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Lynx')); + $aversion = explode(' ', (isset($aresult[1]) ? $aresult[1] : "")); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_LYNX); + return true; + } + return false; + } + + /** + * Determine if the browser is Amaya or not (last updated 1.7) + * @return boolean True if the browser is Amaya otherwise false + */ + protected function checkBrowserAmaya() + { + if (stripos($this->_agent, 'amaya') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Amaya')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_AMAYA); + return true; + } + } + return false; + } + + /** + * Determine if the browser is Safari or not (last updated 1.7) + * @return boolean True if the browser is Safari otherwise false + */ + protected function checkBrowserSafari() + { + if (stripos($this->_agent, 'Safari') !== false + && stripos($this->_agent, 'iPhone') === false + && stripos($this->_agent, 'iPod') === false) { + + $aresult = explode('/', stristr($this->_agent, 'Version')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + $this->setBrowser(self::BROWSER_SAFARI); + return true; + } + return false; + } + + /** + * Detect if URL is loaded from FacebookExternalHit + * @return boolean True if it detects FacebookExternalHit otherwise false + */ + protected function checkFacebookExternalHit() + { + if(stristr($this->_agent,'FacebookExternalHit')) + { + $this->setRobot(true); + $this->setFacebook(true); + return true; + } + return false; + } + + /** + * Detect if URL is being loaded from internal Facebook browser + * @return boolean True if it detects internal Facebook browser otherwise false + */ + protected function checkForFacebookIos() + { + if(stristr($this->_agent,'FBIOS')) + { + $this->setFacebook(true); + return true; + } + return false; + } + + /** + * Detect Version for the Safari browser on iOS devices + * @return boolean True if it detects the version correctly otherwise false + */ + protected function getSafariVersionOnIos() + { + $aresult = explode('/',stristr($this->_agent,'Version')); + if( isset($aresult[1]) ) + { + $aversion = explode(' ',$aresult[1]); + $this->setVersion($aversion[0]); + return true; + } + return false; + } + + /** + * Detect Version for the Chrome browser on iOS devices + * @return boolean True if it detects the version correctly otherwise false + */ + protected function getChromeVersionOnIos() + { + $aresult = explode('/',stristr($this->_agent,'CriOS')); + if( isset($aresult[1]) ) + { + $aversion = explode(' ',$aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_CHROME); + return true; + } + return false; + } + + /** + * Determine if the browser is iPhone or not (last updated 1.7) + * @return boolean True if the browser is iPhone otherwise false + */ + protected function checkBrowseriPhone() { + if( stripos($this->_agent,'iPhone') !== false ) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPHONE); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is iPad or not (last updated 1.7) + * @return boolean True if the browser is iPad otherwise false + */ + protected function checkBrowseriPad() { + if( stripos($this->_agent,'iPad') !== false ) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPAD); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setTablet(true); + return true; + } + return false; + } + + /** + * Determine if the browser is iPod or not (last updated 1.7) + * @return boolean True if the browser is iPod otherwise false + */ + protected function checkBrowseriPod() { + if( stripos($this->_agent,'iPod') !== false ) { + $this->setVersion(self::VERSION_UNKNOWN); + $this->setBrowser(self::BROWSER_IPOD); + $this->getSafariVersionOnIos(); + $this->getChromeVersionOnIos(); + $this->checkForFacebookIos(); + $this->setMobile(true); + return true; + } + return false; + } + + /** + * Determine if the browser is Android or not (last updated 1.7) + * @return boolean True if the browser is Android otherwise false + */ + protected function checkBrowserAndroid() + { + if (stripos($this->_agent, 'Android') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'Android')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + } else { + $this->setVersion(self::VERSION_UNKNOWN); + } + if (stripos($this->_agent, 'Mobile') !== false) { + $this->setMobile(true); + } else { + $this->setTablet(true); + } + $this->setBrowser(self::BROWSER_ANDROID); + return true; + } + return false; + } + + /** + * Determine if the browser is Vivaldi + * @return boolean True if the browser is Vivaldi otherwise false + */ + protected function checkBrowserVivaldi() + { + if (stripos($this->_agent, 'Vivaldi') !== false) { + $aresult = explode('/', stristr($this->_agent, 'Vivaldi')); + if (isset($aresult[1])) { + $aversion = explode(' ', $aresult[1]); + $this->setVersion($aversion[0]); + $this->setBrowser(self::BROWSER_VIVALDI); + return true; + } + } + return false; + } + + /** + * Determine if the browser is a PlayStation + * @return boolean True if the browser is PlayStation otherwise false + */ + protected function checkBrowserPlayStation() + { + if (stripos($this->_agent, 'PlayStation ') !== false) { + $aresult = explode(' ', stristr($this->_agent, 'PlayStation ')); + $this->setBrowser(self::BROWSER_PLAYSTATION); + if (isset($aresult[0])) { + $aversion = explode(')', $aresult[2]); + $this->setVersion($aversion[0]); + if (stripos($this->_agent, 'Portable)') !== false || stripos($this->_agent, 'Vita') !== false) { + $this->setMobile(true); + } + return true; + } + } + return false; + } + + /** + * Determine the user's platform (last updated 2.0) + */ + protected function checkPlatform() + { + if (stripos($this->_agent, 'windows') !== false) + { + $this->_platform = self::PLATFORM_WINDOWS; + } + else if (stripos($this->_agent, 'iPad') !== false) + { + $this->_platform = self::PLATFORM_IPAD; + } + else if (stripos($this->_agent, 'iPod') !== false) + { + $this->_platform = self::PLATFORM_IPOD; + } + else if (stripos($this->_agent, 'iPhone') !== false) + { + $this->_platform = self::PLATFORM_IPHONE; + } + elseif (stripos($this->_agent, 'mac') !== false) + { + $this->_platform = self::PLATFORM_APPLE; + } + elseif (stripos($this->_agent, 'android') !== false) + { + $this->_platform = self::PLATFORM_ANDROID; + } + elseif (stripos($this->_agent, 'linux') !== false) + { + $this->_platform = self::PLATFORM_LINUX; + } + else if (stripos($this->_agent, 'Nokia') !== false) + { + $this->_platform = self::PLATFORM_NOKIA; + } + else if (stripos($this->_agent, 'BlackBerry') !== false) + { + $this->_platform = self::PLATFORM_BLACKBERRY; + } + elseif (stripos($this->_agent, 'FreeBSD') !== false) + { + $this->_platform = self::PLATFORM_FREEBSD; + } + elseif (stripos($this->_agent, 'OpenBSD') !== false) + { + $this->_platform = self::PLATFORM_OPENBSD; + } + elseif (stripos($this->_agent, 'NetBSD') !== false) + { + $this->_platform = self::PLATFORM_NETBSD; + } + elseif (stripos($this->_agent, 'OpenSolaris') !== false) + { + $this->_platform = self::PLATFORM_OPENSOLARIS; + } + elseif (stripos($this->_agent, 'SunOS') !== false) + { + $this->_platform = self::PLATFORM_SUNOS; + } + elseif (stripos($this->_agent, 'OS\/2') !== false) + { + $this->_platform = self::PLATFORM_OS2; + } + elseif (stripos($this->_agent, 'BeOS') !== false) + { + $this->_platform = self::PLATFORM_BEOS; + } + elseif (stripos($this->_agent, 'win') !== false) + { + $this->_platform = self::PLATFORM_WINDOWS; + } + elseif (stripos($this->_agent, 'Playstation') !== false) + { + $this->_platform = self::PLATFORM_PLAYSTATION; + } + + } +} diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/cache.inc.php doomsday-stable-2.1.0.2900+xenial/weblib/cache.inc.php --- doomsday-stable-2.0.3.2464+xenial/weblib/cache.inc.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/cache.inc.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,83 @@ + + * + * License: GPL v2+ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. This program is distributed in the hope that it + * will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty + * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General + * Public License for more details. You should have received a copy of the GNU + * General Public License along with this program; if not, see: + * http://www.gnu.org/licenses/gpl.html + */ + +// Requirements: +// - define DENG_CACHE_MAX_AGE (seconds) +// - define DENG_CACHE_PATH + +$_cache_buf = ''; +$_cache_ts = 0; + +function cache_clear() +{ + global $_cache_buf; + global $_cache_ts; + $_cache_buf = ''; + $_cache_ts = 0; +} + +function cache_echo($msg) +{ + global $_cache_buf; + $_cache_buf .= $msg; +} + +function cache_dump() +{ + global $_cache_buf; + echo($_cache_buf); +} + +function cache_get() +{ + global $_cache_buf; + return $_cache_buf; +} + +function cache_timestamp() +{ + global $_cache_ts; + return $_cache_ts; +} + +function cache_key($id, $data) +{ + return "/$id/".urlencode(json_encode($data)); +} + +function cache_try_load($key, $max_age = DENG_CACHE_MAX_AGE) +{ + cache_clear(); + + $fn = DENG_CACHE_PATH.$key; + if (!file_exists($fn)) return false; + $ts = filemtime($fn); + if ($max_age >= 0 && (time() - $ts) > $max_age) return false; // Too old. + if (($value = file_get_contents($fn)) === false) return false; + global $_cache_buf; + global $_cache_ts; + $_cache_buf = $value; + $_cache_ts = $ts; + return true; +} + +function cache_store($key) +{ + global $_cache_buf; + file_put_contents(DENG_CACHE_PATH.$key, $_cache_buf); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/class.sitedata.php doomsday-stable-2.1.0.2900+xenial/weblib/class.sitedata.php --- doomsday-stable-2.0.3.2464+xenial/weblib/class.sitedata.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/class.sitedata.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,30 @@ +_data = json_decode(file_get_contents(SITE_DATA), true); + } + + public function &data() + { + return $this->_data; + } + + private function __clone() {} +} diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/sitemap.inc.php doomsday-stable-2.1.0.2900+xenial/weblib/sitemap.inc.php --- doomsday-stable-2.0.3.2464+xenial/weblib/sitemap.inc.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/sitemap.inc.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,119 @@ +date); + $html = "$post->title " + .""; + $itemclass = ''; + if (time() - RECENT_THRESHOLD < timestamp_from_date($post->date)) { + $itemclass = 'recent'; + } + echo("
  • ".$html.'
  • '); +} + +function generate_sitemap() +{ + $site_root = SITE_ROOT; + $sitedata = SiteData::get()->data()['sitemap_info']; + + // Fetch the cached news and dev blog posts. + cache_try_load(cache_key('blog', 'news'), -1); + $news = json_decode(cache_get()); + cache_try_load(cache_key('blog', 'dev'), -1); + $dev = json_decode(cache_get()); + $news_count = min(4, count($news->posts)); + $dev_count = min(3, count($dev->posts)); + + // Check any recently announced servers. + $recent_servers = ''; + + foreach ($sitedata['servers'] as $server) { + $recent_servers .= "
  • $server[pnum] / $server[pmax] · " + ."$server[name] · $server[game_id]
  • "; + } + if (!$recent_servers) { + $recent_servers = '
  • No servers
  • '; + } + + $build_list = "
      "; + foreach ($sitedata['builds'] as $build) { + $link = $site_root.'/build'.$build['build']; + $version = $build['version']; + $label = "$version ".$build['type']." [#".$build['build']."]"; + $title = "Build report for $label"; + $date = $build['date']; + $css_class = ($build['is_recent'])? ' class="recent"' : ''; + + $build_list .= " $label \n"; + } + $build_list .= "
    • Autobuilder Index
    • \n" + ."
    • B RSS Feed
    \n"; + + echo( +"
    +
      +
    • +
      Latest News
      +
        "); + + for ($i = 0; $i < $news_count; ++$i) { + generate_sitemap_blog_post($news->posts[$i], 'newspost'); + } + echo("
      • B RSS Feed
      • "); + + echo( +"
      +
    • +
    • +
      Blog Posts
      +
        \n"); + + for ($i = 0; $i < $dev_count; ++$i) { + generate_sitemap_blog_post($dev->posts[$i], 'blogpost'); + } + echo("
      • B RSS Feed
      • "); + + echo( +"
    • +
    • +
      Recent Builds
      + $build_list +
    • +
    • +
      Multiplayer Games
      +
        $recent_servers
      +
    • +
    • +
      User Manual
      + +
    • +
    • +
      Reference Guide
      + +
    • +
    +
    + Doomsday Engine is open + source software and is distributed under + the GNU General Public License (applications) and LGPL (core libraries). + Assets from the original games remain under their original copyright. + Doomsday logo created by Daniel Swanson. + dengine.net website design by Jaakko Keränen © 2017. +

    Donate to support the project

    +
    +
    "); +} diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/topbar.inc.php doomsday-stable-2.1.0.2900+xenial/weblib/topbar.inc.php --- doomsday-stable-2.0.3.2464+xenial/weblib/topbar.inc.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/topbar.inc.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,31 @@ +data()['latest_stable_version'][$dl_plat]); + if (!$button_label) { + $button_label = 'Download'; + } + $download_link ="$button_label "; +?> + diff -Nru doomsday-stable-2.0.3.2464+xenial/weblib/utils.inc.php doomsday-stable-2.1.0.2900+xenial/weblib/utils.inc.php --- doomsday-stable-2.0.3.2464+xenial/weblib/utils.inc.php 1970-01-01 00:00:00.000000000 +0000 +++ doomsday-stable-2.1.0.2900+xenial/weblib/utils.inc.php 2018-12-11 07:08:26.000000000 +0000 @@ -0,0 +1,142 @@ +getPlatform()) { + case Browser::PLATFORM_WINDOWS: + $user_platform = 'windows'; + break; + case Browser::PLATFORM_APPLE: + case Browser::PLATFORM_IPHONE: + case Browser::PLATFORM_IPAD: + $user_platform = 'macx'; + break; + case Browser::PLATFORM_LINUX: + $user_platform = 'linux'; + break; + case Browser::PLATFORM_FREEBSD: + case Browser::PLATFORM_OPENBSD: + case Browser::PLATFORM_NETBSD: + $user_platform = 'any'; + break; + default: + $user_platform = ''; + break; + } + return $user_platform; +} + +function user_download_platform() +{ + // Assume 64-bit. + switch (detect_user_platform()) { + case 'windows': $dl_plat = 'win-x64'; break; + case 'macx': $dl_plat = 'mac10_10-x86_64'; break; + case 'linux': $dl_plat = 'ubuntu18-x86_64'; break; + default: $dl_plat = 'source'; break; + } + return $dl_plat; +} + +function platform_download_link() +{ + switch (detect_user_platform()) { + case 'windows': + $dl_link = '/windows'; break; + case 'macx': + $dl_link = '/macos'; break; + case 'linux': + $dl_link = '/linux'; break; + default: + $dl_link = '/source'; break; + } + return SITE_ROOT.$dl_link; +} + +function starts_with($needle, $haystack) +{ + $length = strlen($needle); + return (substr($haystack, 0, $length) === $needle); +} + +function timestamp_from_date($date_text) +{ + $date = date_parse($date_text); + $ts = gmmktime($date['hour'], $date['minute'], $date['second'], + $date['month'], $date['day'], $date['year']); + return $ts; +} + +function reformat_date($date_text) +{ + $date = date_parse($date_text); + $ts = timestamp_from_date($date_text); + if (date('Y') != $date['year']) { + $fmt = '%Y %B %e'; + } + else { + $fmt = '%B %e'; + } + return strftime($fmt, $ts); +} + +function omit_zeroes($version) +{ + $parts = explode(".", $version); + while (count($parts) > 2 && array_slice($parts, -1)[0] == '0') { + $parts = array_slice($parts, 0, -1); + } + return join('.', $parts); +} + +function human_version($version, $build, $release_type) +{ + return omit_zeroes($version)." ".ucwords($release_type)." [#${build}]"; +} + +function webfont_loader_header() +{ + return " +"; +}