Skip to content

Commit c4927d6

Browse files
committed
Initial work on virtual display mode support
Saving out display mode ratio of max res, and adding support for client to set resolution in response to window events
1 parent 2a059e0 commit c4927d6

File tree

9 files changed

+354
-7
lines changed

9 files changed

+354
-7
lines changed

Scripts/Python/xIniDisplay.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,10 @@
6262
kGraphicsShadows = "Graphics.Shadow.Enable"
6363
kGraphicsVerticalSync = "Graphics.EnableVSync"
6464
kGraphicsShadowQuality = "Graphics.Shadow.VisibleDistance"
65+
kGraphicsOutputScale = "Graphics.OutputScale"
6566

66-
CmdList = [kGraphicsWidth, kGraphicsHeight, kGraphicsColorDepth, kGraphicsWindowed, kGraphicsTextureQuality, kGraphicsAntiAliasLevel, kGraphicsAnisotropicLevel, kGraphicsQualityLevel, kGraphicsShadows, kGraphicsVerticalSync, kGraphicsShadowQuality]
67-
DefaultsList = ["800", "600", "32", "false", "2", "0", "0", "2", "true", "false", "0"]
67+
CmdList = [kGraphicsWidth, kGraphicsHeight, kGraphicsColorDepth, kGraphicsWindowed, kGraphicsTextureQuality, kGraphicsAntiAliasLevel, kGraphicsAnisotropicLevel, kGraphicsQualityLevel, kGraphicsShadows, kGraphicsVerticalSync, kGraphicsShadowQuality, kGraphicsOutputScale]
68+
DefaultsList = ["800", "600", "32", "false", "2", "0", "0", "2", "true", "false", "0", "100"]
6869

6970
def ConstructFilenameAndPath():
7071
global gFilenameAndPath
@@ -120,9 +121,9 @@ def ReadIni():
120121
ConstructFilenameAndPath()
121122
gIniFile.writeFile(gFilenameAndPath)
122123

123-
def SetGraphicsOptions(width, heigth, colordepth, windowed, texquality, aaLevel, anisoLevel, qualityLevel, useShadows, vsync, shadowqual):
124+
def SetGraphicsOptions(width, heigth, colordepth, windowed, texquality, aaLevel, anisoLevel, qualityLevel, useShadows, vsync, shadowqual, outputScale):
124125
if gIniFile:
125-
paramList = [width, heigth, colordepth, windowed, texquality, aaLevel, anisoLevel, qualityLevel, useShadows, vsync, shadowqual]
126+
paramList = [width, heigth, colordepth, windowed, texquality, aaLevel, anisoLevel, qualityLevel, useShadows, vsync, shadowqual, outputScale]
126127
for idx in range(len(CmdList)):
127128
entry,junk = gIniFile.findByCommand(CmdList[idx])
128129
val = str(paramList[idx])

Scripts/Python/xOptionsMenu.py

+6-2
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@
443443
gClickToTurn = "0"
444444
gAudioHack = 0
445445
gCurrentReleaseNotes = "Welcome to Myst Online: Uru Live!"
446+
gMaxVideoWidth = 0
446447

447448
class xOptionsMenu(ptModifier):
448449
"The Options dialog modifier"
@@ -1488,6 +1489,7 @@ def ResetVideoToDefault(self):
14881489
self.SetVidResField(vidRes)
14891490

14901491
def InitVideoControlsGUI(self):
1492+
global gMaxVideoWidth
14911493
xIniDisplay.ReadIni()
14921494
opts = xIniDisplay.GetGraphicsOptions()
14931495

@@ -1541,6 +1543,7 @@ def InitVideoControlsGUI(self):
15411543
if not vidRes in vidResList:
15421544
vidRes = vidResList[numRes-1]
15431545

1546+
gMaxVideoWidth = int(vidResList[numRes-1].split("x")[0])
15441547
for res in range(numRes):
15451548
if vidRes == vidResList[res]:
15461549
if numRes > 1:
@@ -1644,8 +1647,9 @@ def WriteVideoControls(self, setMode = 0):
16441647

16451648
gammaField = ptGUIControlKnob(GraphicsSettingsDlg.dialog.getControlFromTag(kGSDisplayGammaSlider))
16461649
gamma = gammaField.getValue()
1647-
1648-
xIniDisplay.SetGraphicsOptions(width, height, colordepth, windowed, tex_quality, antialias, aniso, quality, shadows, vsyncstr, shadow_quality)
1650+
resolutionScale = int(round((width / gMaxVideoWidth) * 100))
1651+
1652+
xIniDisplay.SetGraphicsOptions(width, height, colordepth, windowed, tex_quality, antialias, aniso, quality, shadows, vsyncstr, shadow_quality, resolutionScale)
16491653
xIniDisplay.WriteIni()
16501654
self.setNewChronicleVar("gamma", gamma)
16511655

Sources/Plasma/Apps/plClient/plClient.cpp

+46-1
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,6 @@ You can contact Cyan Worlds, Inc. by email [email protected]
150150
#include "pfPython/cyMisc.h"
151151
#include "pfPython/cyPythonInterface.h"
152152

153-
154153
#define MSG_LOADING_BAR
155154

156155
// static hsVector3 gAbsDown(0,0,-1.f);
@@ -221,6 +220,7 @@ plClient::~plClient()
221220
plClient::SetInstance(nullptr);
222221

223222
delete fPageMgr;
223+
delete fGraphicsIni;
224224
}
225225

226226
template<typename T>
@@ -443,6 +443,7 @@ bool plClient::InitPipeline(hsWindowHndl display, uint32_t devType)
443443

444444
hsG3DDeviceRecord *rec = (hsG3DDeviceRecord *)dmr.GetDevice();
445445

446+
#if !PLASMA_DISPLAY_INDEPENDENT_VIDEO_MODES
446447
if(!plPipeline::fInitialPipeParams.Windowed)
447448
{
448449
// find our resolution if we're not in windowed mode
@@ -467,6 +468,7 @@ bool plClient::InitPipeline(hsWindowHndl display, uint32_t devType)
467468
ISetGraphicsDefaults();
468469
}
469470
}
471+
#endif
470472

471473
if(plPipeline::fInitialPipeParams.TextureQuality == -1)
472474
{
@@ -1900,6 +1902,47 @@ void plClient::ResizeDisplayDevice(int Width, int Height, bool Windowed)
19001902
IResizeNativeDisplayDevice(Width, Height, Windowed);
19011903
}
19021904

1905+
void plClient::SetDisplayOptions(int Width, int Height, bool Windowed)
1906+
{
1907+
fGraphicsIni->readFile();
1908+
std::shared_ptr<hsIniEntry> entry = fGraphicsIni->findByCommand("Graphics.Windowed");
1909+
if (entry) {
1910+
entry->setValue(0, Windowed ? "true" : "false");
1911+
}
1912+
1913+
entry = fGraphicsIni->findByCommand("Graphics.OutputScale");
1914+
if (entry) {
1915+
double scale = entry->getValue(0)->to_uint() / 100.0;
1916+
Width *= scale;
1917+
Height *= scale;
1918+
}
1919+
1920+
entry = fGraphicsIni->findByCommand("Graphics.Width");
1921+
if (entry) {
1922+
entry->setValue(0, std::to_string(Width));
1923+
}
1924+
entry = fGraphicsIni->findByCommand("Graphics.Height");
1925+
if (entry) {
1926+
entry->setValue(0, std::to_string(Height));
1927+
}
1928+
fGraphicsIni->writeFile();
1929+
1930+
FlushGraphicsOptions();
1931+
}
1932+
1933+
void plClient::FlushGraphicsOptions()
1934+
{
1935+
int Width = fGraphicsIni->findByCommand("Graphics.Width")->getValue(0)->to_int();
1936+
int Height = fGraphicsIni->findByCommand("Graphics.Height")->getValue(0)->to_int();
1937+
int ColorDepth = fGraphicsIni->findByCommand("Graphics.ColorDepth")->getValue(0)->to_int();
1938+
int NumAASamples = fGraphicsIni->findByCommand("Graphics.AntiAliasAmount")->getValue(0)->to_int();
1939+
int MaxAnisotropicSamples = fGraphicsIni->findByCommand("Graphics.AnisotropicLevel")->getValue(0)->to_int();
1940+
bool VSync = (fGraphicsIni->findByCommand("Graphics.EnableVSync")->getValue(0) == "true");
1941+
bool Windowed = (fGraphicsIni->findByCommand("Graphics.Windowed")->getValue(0) == "true");
1942+
1943+
ResetDisplayDevice(Width, Height, ColorDepth, Windowed, NumAASamples, MaxAnisotropicSamples);
1944+
}
1945+
19031946
void WriteBool(hsStream *stream, const char *name, bool on )
19041947
{
19051948
char command[256];
@@ -1998,6 +2041,8 @@ void plClient::IDetectAudioVideoSettings()
19982041
s.Close();
19992042
else
20002043
IWriteDefaultGraphicsSettings(graphicsIniFile);
2044+
2045+
fGraphicsIni = new hsIniFile(graphicsIniFile);
20012046
}
20022047

20032048
void plClient::IWriteDefaultAudioSettings(const plFileName& destFile)

Sources/Plasma/Apps/plClient/plClient.h

+5
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ You can contact Cyan Worlds, Inc. by email [email protected]
4848

4949
#include "HeadSpin.h"
5050
#include "hsBitVector.h"
51+
#include "hsIniHelper.h"
5152
#include "plFileSystem.h"
5253

5354
#include <list>
@@ -157,6 +158,8 @@ class plClient : public hsKeyedObject
157158

158159
plMessagePumpProc fMessagePumpProc;
159160

161+
hsIniFile *fGraphicsIni;
162+
160163
#ifndef PLASMA_EXTERNAL_RELEASE
161164
bool bPythonDebugConnected;
162165
#endif
@@ -223,6 +226,7 @@ class plClient : public hsKeyedObject
223226
void IResizeNativeDisplayDevice(int width, int height, bool windowed);
224227
void IChangeResolution(int width, int height);
225228
void IUpdateProgressIndicator(plOperationProgress* progress);
229+
void FlushGraphicsOptions();
226230

227231
public:
228232

@@ -310,6 +314,7 @@ class plClient : public hsKeyedObject
310314
void SetMessagePumpProc(plMessagePumpProc proc) { fMessagePumpProc = proc; }
311315
void ResetDisplayDevice(int Width, int Height, int ColorDepth, bool Windowed, int NumAASamples, int MaxAnisotropicSamples, bool VSync = false);
312316
void ResizeDisplayDevice(int Width, int Height, bool Windowed);
317+
void SetDisplayOptions(int Width, int Height, bool Windowed);
313318

314319
plAnimDebugList *fAnimDebugList;
315320
};

Sources/Plasma/CoreLib/CMakeLists.txt

+2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ set(CoreLib_SOURCES
77
hsExceptionStack.cpp
88
hsFastMath.cpp
99
hsGeometry3.cpp
10+
hsIniHelper.cpp
1011
hsMatrix33.cpp
1112
hsMatrix44.cpp
1213
hsMemory.cpp
@@ -48,6 +49,7 @@ set(CoreLib_HEADERS
4849
hsExceptionStack.h
4950
hsFastMath.h
5051
hsGeometry3.h
52+
hsIniHelper.h
5153
hsLockGuard.h
5254
hsMatrix44.h
5355
hsMemory.h
+130
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
//
2+
// hsIniHelper.cpp
3+
// CoreLib
4+
//
5+
// Created by Colin Cornaby on 8/29/22.
6+
//
7+
8+
#include "hsIniHelper.h"
9+
#include "hsStringTokenizer.h"
10+
11+
hsIniEntry::hsIniEntry(ST::string line):
12+
fCommand(), fComment() {
13+
if(line.size() == 0) {
14+
fType = kBlankLine;
15+
} else if(line[0] == '#') {
16+
fType = kComment;
17+
fComment = line.after_first('#');
18+
} else if(line == "\n") {
19+
fType = kBlankLine;
20+
} else {
21+
fType = kCommandValue;
22+
hsStringTokenizer tokenizer = hsStringTokenizer(line.c_str(), " ");
23+
char *str;
24+
int i = 0;
25+
while((str = tokenizer.next())) {
26+
if (i==0) {
27+
fCommand = str;
28+
} else {
29+
fValues.push_back(str);
30+
}
31+
i++;
32+
}
33+
}
34+
}
35+
36+
void hsIniEntry::setValue(size_t idx, ST::string value) {
37+
if (fValues.size() >= idx) {
38+
fValues[idx] = value;
39+
} else {
40+
for (int i=fValues.size(); i<idx; i++) {
41+
fValues.push_back("");
42+
}
43+
fValues.push_back(value);
44+
}
45+
}
46+
47+
std::optional<ST::string> hsIniEntry::getValue(size_t idx) {
48+
if (fValues.size() < idx) {
49+
return std::optional<ST::string>();
50+
} else {
51+
return fValues[idx];
52+
}
53+
}
54+
55+
56+
hsIniFile::hsIniFile(plFileName filename) {
57+
58+
this->filename = filename;
59+
readFile();
60+
}
61+
62+
63+
hsIniFile::hsIniFile(hsStream& stream) {
64+
readStream(stream);
65+
}
66+
67+
void hsIniFile::readStream(hsStream& stream) {
68+
ST::string line;
69+
while(stream.ReadLn(line)) {
70+
std::shared_ptr<hsIniEntry> entry = std::make_shared<hsIniEntry>(line);
71+
fEntries.push_back(entry);
72+
}
73+
}
74+
75+
void hsIniFile::writeFile() {
76+
hsAssert(filename.GetSize() > 0, "writeFile requires contructor with filename");
77+
78+
hsBufferedStream s;
79+
s.Open(filename, "w");
80+
writeStream(s);
81+
s.Close();
82+
}
83+
84+
void hsIniFile::readFile() {
85+
hsAssert(filename.GetSize() > 0, "writeFile requires contructor with filename");
86+
87+
fEntries.clear();
88+
89+
hsBufferedStream s;
90+
s.Open(filename);
91+
readStream(s);
92+
s.Close();
93+
}
94+
95+
void hsIniFile::writeFile(plFileName filename) {
96+
hsBufferedStream s;
97+
s.Open(filename, "w");
98+
writeStream(s);
99+
s.Close();
100+
}
101+
102+
void hsIniFile::writeStream(hsStream& stream) {
103+
for (std::shared_ptr<hsIniEntry> entry: fEntries) {
104+
switch (entry->fType) {
105+
case hsIniEntry::kBlankLine:
106+
stream.WriteSafeString("\n");
107+
break;
108+
case hsIniEntry::kComment:
109+
stream.WriteSafeString("#" + entry.get()->fComment + "\n");
110+
break;
111+
case hsIniEntry::kCommandValue:
112+
ST::string line = entry->fCommand;
113+
for (ST::string value: entry->fValues) {
114+
line += " " + value;
115+
}
116+
line += "\n";
117+
stream.WriteString(line);
118+
break;
119+
}
120+
}
121+
}
122+
123+
std::shared_ptr<hsIniEntry> hsIniFile::findByCommand(ST::string command) {
124+
for (std::shared_ptr<hsIniEntry> entry: fEntries) {
125+
if(entry->fCommand == command) {
126+
return entry;
127+
}
128+
}
129+
return std::shared_ptr<hsIniEntry>(nullptr);
130+
}

Sources/Plasma/CoreLib/hsIniHelper.h

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//
2+
// hsIniHelper.hpp
3+
// CoreLib
4+
//
5+
// Created by Colin Cornaby on 8/29/22.
6+
//
7+
8+
#ifndef hsIniHelper_hpp
9+
#define hsIniHelper_hpp
10+
11+
#include <stdio.h>
12+
#include <string_theory/string>
13+
#include <vector>
14+
#include <optional>
15+
#include "plFileSystem.h"
16+
#include "hsStream.h"
17+
18+
#endif /* hsIniHelper_hpp */
19+
20+
class hsIniFile;
21+
22+
class hsIniEntry {
23+
friend hsIniFile;
24+
public:
25+
26+
enum Type {
27+
kBlankLine = 0,
28+
kComment,
29+
kCommandValue
30+
};
31+
32+
Type fType;
33+
ST::string fCommand;
34+
ST::string fComment;
35+
std::vector<ST::string> fValues;
36+
void setValue(size_t idx, ST::string value);
37+
std::optional<ST::string> getValue(size_t idx);
38+
hsIniEntry(ST::string line);
39+
};
40+
41+
class hsIniFile {
42+
public:
43+
std::vector<std::shared_ptr<hsIniEntry>> fEntries;
44+
45+
hsIniFile(plFileName filename);
46+
hsIniFile(hsStream& stream);
47+
void writeFile(plFileName filename);
48+
void writeFile();
49+
void writeStream(hsStream& stream);
50+
std::shared_ptr<hsIniEntry> findByCommand(ST::string command);
51+
void readFile();
52+
private:
53+
void readStream(hsStream& stream);
54+
plFileName filename;
55+
};

Sources/Plasma/FeatureLib/pfConsole/pfConsoleCommands.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -2069,6 +2069,11 @@ PF_CONSOLE_CMD( Graphics, EnableVSync, "bool b", "Init VerticalSync" )
20692069
plPipeline::fInitialPipeParams.VSync = (bool) params[0];
20702070
}
20712071

2072+
PF_CONSOLE_CMD( Graphics, OutputScale, "int s", "Init OutputScale" )
2073+
{
2074+
//plPipeline::fInitialPipeParams.VSync = (bool) params[0];
2075+
}
2076+
20722077
PF_CONSOLE_CMD( Graphics, EnablePlanarReflections, "bool", "Enable the draw and update of planar reflections" )
20732078
{
20742079
bool enable = (bool)params[0];

0 commit comments

Comments
 (0)