Skip to content

Commit

Permalink
fix #222: change resolution in running app
Browse files Browse the repository at this point in the history
This happens after you exit the options dialog and after you've entered
a new name with an existing user file.
  • Loading branch information
SimonN committed Dec 26, 2017
1 parent 6253d55 commit 165d0d0
Show file tree
Hide file tree
Showing 19 changed files with 233 additions and 91 deletions.
8 changes: 4 additions & 4 deletions data/transl/english.txt
Expand Up @@ -324,7 +324,7 @@ $optionMusicEnabledDesc Enable background music.
$optionSoundDecibelsDesc Adjust the sound volume. 0 is already pretty loud.|Raise/lower by 10 dB to double/halve the sound volume.
$optionMusicDecibelsDesc Adjust the music volume. −10 dB should be loud enough.|Raise/lower by 10 dB to double/halve the music volume.

$optionScreenWindowed Start in windowed mode
$optionScreenWindowed Windowed (no fullscreen)
$optionScreenWindowedRes Windowed resolution
$optionPaintTorusSeams Paint torus seams
$optionIngameTooltips Tooltips during game
Expand All @@ -334,8 +334,8 @@ $optionGuiColorRed Menu color red
$optionGuiColorGreen Menu color green
$optionGuiColorBlue Menu color blue

$optionScreenWindowedDesc Run Lix in a window, or in fullscreen mode?|Restart Lix after you change this!
$optionScreenWindowedResDesc Size of the Lix window. Only for windowed mode, not for fullscreen.|Restart Lix after you change this!
$optionScreenWindowedDesc Play Lix in a window. You can choose the window's size.|If not checked, Lix runs in fullscreen mode.
$optionScreenWindowedResDesc Size of the Lix window when you have chosen windowed mode.|This has no effect in fullscreen mode.
$optionPaintTorusSeamsDesc Mark the wrapping seam with a thin line whenever a level wraps around.|This doesn't affect game physics, but may improve your orientation.
$optionIngameTooltipsDesc Explain buttons and lix-selecting hotkeys during play, e.g., to select left-facing lix.|Some buttons have two functions: One on left-click, one on right-click.
$optionShowButtonHotkeysDesc On every button, print the button's hotkeys in the bottom-right-hand corner.
Expand Down Expand Up @@ -403,7 +403,7 @@ $optionUnpauseOnAssign Unpause on skill assignment

$optionAvoidBuilderQueuingDesc Prefer builder assignments to non-builders over queuing to existing builders.|You can hold priority invert (see Controls tab) to do what you don't prefer.
$optionAvoidBatterToExploderDesc Prefer batter assignments to walkers over batter assignments to timed exploders.|You can hold priority invert (see Controls tab) to do what you don't prefer.
$optionReplayAfterFrameBackDesc On framestepping back (◀▮), keep future replay actions until you cancel the replay by clicking into air.|If not checked, replay actions are removed when you undo them by framestepping.
$optionReplayAfterFrameBackDesc On framestepping back (◀▮), keep future replay actions until you click air.|If not checked, replay actions are removed when you undo them by framestepping.
$optionUnpauseOnAssignDesc Unpause the game when you assign a skill during pause.|If not checked, skill assignments during pause advance the game by 1 frame.

$optionKeyMenuOkay Okay/yes
Expand Down
8 changes: 4 additions & 4 deletions data/transl/german.txt
Expand Up @@ -312,7 +312,7 @@ $optionMusicEnabledDesc Musik einschalten.
$optionSoundDecibelsDesc Tonlautstärke anpassen. 0 ist schon recht laut.|Erhöhe/senke um 10 dB, um die Tonlautstärke zu verdoppeln/halbieren.
$optionMusicDecibelsDesc Musiklautstärke anpassen. −10 dB sollte laut genug sein.|Erhöhe/senke um 10 dB, um die Musiklautstärke zu verdoppeln/halbieren.

$optionScreenWindowed Im Fenstermodus starten
$optionScreenWindowed Fenster statt Vollbild
$optionScreenWindowedRes Fenster-Auflösung
$optionPaintTorusSeams Torus-Nahtstellen anmalen
$optionIngameTooltips Tooltips im Spiel
Expand All @@ -322,8 +322,8 @@ $optionGuiColorRed Menüfarbe Rot
$optionGuiColorGreen Menüfarbe Grün
$optionGuiColorBlue Menüfarbe Blau

$optionScreenWindowedDesc Lix im Fenstermodus oder Vollbildmodus starten?|Starte Lix neu, nachdem du diese Einstellung änderst!
$optionScreenWindowedResDesc Größe des Lix-Fensters bei Programmstart. Keine Auswirkung auf Vollbildmodus.|Starte Lix neu, nachdem du diese Einstellung änderst!
$optionScreenWindowedDesc Lix im Fenstermodus spielen mit wählbarer Auflösung.|Ohne Haken: Lix im Vollbildmodus spielen.
$optionScreenWindowedResDesc Größe des Lix-Fensters im Fenstermodus.|Dies hat keine Auswirkung auf den Vollbildmodus.
$optionPaintTorusSeamsDesc Torus-Nahtstellen in der Landschaft mit einer dünnen Linie kennzeichnen.|Dies hat keine Auswirkung auf die Physik; es dient zur Orientierung.
$optionIngameTooltipsDesc Buttons und Lix-wählende Hotkeys im Spiel erklären, z.B. nur Linksläufer.|Einige Buttons haben eine Linksklick- und eine Rechtsklick-Funktion.
$optionShowButtonHotkeysDesc Auf jedem Button die Hotkeys des Buttons in der rechten unteren Ecke anzeigen.
Expand Down Expand Up @@ -391,7 +391,7 @@ $optionUnpauseOnAssign Pause aus bei Fähigk.-Zwsg.

$optionAvoidBuilderQueuingDesc Builder vorrangig an Nicht-Builder zuweisen anstatt an bestehende Builder.|Halte "Priorität invertieren" (Reiter "Steuerung"), um das jeweils andere zu tun.
$optionAvoidBatterToExploderDesc Batter vorrangig an normale Lix zuweisen anstatt an brennende Exploder.|Halte "Priorität invertieren" (Reiter "Steuerung"), um das jeweils andere zu tun.
$optionReplayAfterFrameBackDesc Replay-Aktionen zum späteren Abspiel beibehalten, wenn du zurückspulst (◀▮).|Ohne Haken: Replay-Aktionen entfernen, die durch ◀▮ ungeschehen werden.
$optionReplayAfterFrameBackDesc Replay-Aktionen beim Zurückspulen (◀▮) behalten, bis du in die Luft klickst.|Ohne Haken: Replay-Aktionen entfernen, die durch ◀▮ ungeschehen werden.
$optionUnpauseOnAssignDesc Die Pause ausschalten, wenn du eine Fähigkeit zuweist.|Ohne Haken: Nur 1 Physik-Update weiter, wenn du eine Fähigkeit zuweist.

$optionKeyMenuOkay Okay/ja
Expand Down
5 changes: 4 additions & 1 deletion src/basics/cmdargs.d
Expand Up @@ -59,7 +59,10 @@ public:

this(string[] args)
{
// argument 0 is the program name, loop over the extra ones only
if (args.empty) {
// argument 0 is the program name, loop over the extra ones only
return;
}
foreach (arg; args[1 .. $]) {
if (arg.startsWith("--"))
parseDashDashArgument(arg);
Expand Down
19 changes: 0 additions & 19 deletions src/basics/help.d
Expand Up @@ -69,8 +69,6 @@ roundInt(F)(in F f)
return (f + 0.5f).floor.to!int;
}



string
backspace(in string str)
{
Expand Down Expand Up @@ -107,8 +105,6 @@ unittest {
assert (escapeStringForFilename("リッくス") == "リッくス");
}



pure nothrow int
len(T)(in T[] arr)
{
Expand All @@ -118,21 +114,6 @@ len(T)(in T[] arr)
return arr.length & 0x7F_FF_FF_FF;
}



void
destroyArray(T)(ref T arr)
{
foreach (ref var; arr) {
destroy(var);
var = null;
}
destroy(arr);
arr = null;
}



@property T[]
clone(T)(in const(T)[] arr)
if (is (T == class) || is (T == struct))
Expand Down
32 changes: 8 additions & 24 deletions src/basics/init.d
Expand Up @@ -4,21 +4,15 @@ import derelict.enet.enet;

import basics.alleg5;
import basics.cmdargs;
import basics.globals;
import basics.globconf;
import basics.resol;
import basics.user;
import file.language;
import file.filename;
import game.mask;
import game.physdraw;
import graphic.color;
import graphic.internal;
import gui.context;
import gui.root;
import hardware.display;
import hardware.keyboard;
import hardware.mouse;
import hardware.mousecur;
import hardware.sound;
import hardware.music;
import hardware.tharsis;
Expand Down Expand Up @@ -55,21 +49,21 @@ void initialize(in Cmdargs cmdargs)
al_init_ttf_addon();
al_init_primitives_addon();
hardware.tharsis.initialize();
if (ia) hardware.display.setScreenMode(cmdargs);
if (ia) hardware.keyboard.initialize();
if (ia) hardware.mouse.initialize();
if (ia) hardware.sound.initialize();

graphic.color.initialize();
graphic.internal.initialize(cmdargs.mode);
if (ph) game.mask.initialize();

if (ia) game.physdraw.initialize();
if (ia) hardware.mousecur.initialize();
if (ia) initializeGUI();
tile.tilelib.initialize();
if (ia) changeResolutionBasedOnCmdargsThenUserFile(cmdargs); // inits tiles
else tile.tilelib.initialize(); // we need these in any case
}

/*
* See also the resolution functions in basics.resol.
* They initialize and deinitialize several other modules.
*/

void deinitialize()
{
// We don't deinitialize much. It should be okay to leak at end of
Expand All @@ -87,13 +81,3 @@ void deinitialize()
// handlers?
hardware.music.deinitialize();
}

private void initializeGUI()
{
assert (display);
immutable xl = al_get_display_width(display);
immutable yl = al_get_display_height(display);
gui.context.initialize(xl, yl);
gui.root.initialize(xl, yl);
graphic.internal.initializeScale(gui.stretchFactor);
}
28 changes: 18 additions & 10 deletions src/basics/mainloop.d
Expand Up @@ -15,6 +15,7 @@ import core.memory;
import basics.alleg5;
import basics.globconf;
import basics.globals;
import basics.resol;
import editor.editor;
import game.core.game;
import file.filename; // running levels from the command-line
Expand Down Expand Up @@ -250,18 +251,12 @@ public:
}
}
else if (optionsMenu) {
if (optionsMenu.gotoMainMenu) {
kill();
mainMenu = new MainMenu;
gui.addElder(mainMenu);
}
if (optionsMenu.gotoMainMenu)
toMainMenuWithResChange();
}
else if (askName) {
if (askName.gotoMainMenu) {
kill();
mainMenu = new MainMenu;
gui.addElder(mainMenu);
}
if (askName.gotoMainMenu)
toMainMenuWithResChange();
else if (askName.gotoExitApp)
exit = true;
}
Expand Down Expand Up @@ -322,5 +317,18 @@ public:
hardware.sound.draw();
flip_display();
}

/*
* The options menu reinitializes many modules itself, but
* it's a GUI dialog, therefore it feels safer to change resolution
* outside of that dialog. Let's do it here.
*/
private void toMainMenuWithResChange()
{
kill();
changeResolutionBasedOnUserFileAlone();
mainMenu = new MainMenu;
gui.addElder(mainMenu);
}
}
// end class MainLoop
54 changes: 54 additions & 0 deletions src/basics/resol.d
@@ -0,0 +1,54 @@
module basics.resol;

/*
* Call all modules that do something with resolution, so that those modules
* do not have to depend on each other as much.
*/

import basics.cmdargs;
import basics.user; // don't always change resolution if already OK
import game.physdraw;
import graphic.internal;
import gui.context;
import gui.root;
import hardware.display;
import hardware.mousecur;
import tile.tilelib;

// //i means not called because not yet implemented. It should be implemented
// before we release changing resolution.

void changeResolutionBasedOnCmdargsThenUserFile(const(Cmdargs) cmdargs)
{
hardware.mousecur.deinitialize();
tile.tilelib.deinitialize();
game.physdraw.deinitialize();
graphic.internal.deinitialize();
gui.root.deinitialize();
gui.context.deinitialize();

hardware.display.setScreenMode(cmdargs);

gui.context.initialize(displayXl, displayYl);
gui.root.initialize(displayXl, displayYl);
graphic.internal.initialize(cmdargs.mode);
graphic.internal.initializeScale(gui.stretchFactor);
game.physdraw.initialize();
tile.tilelib.initialize();
hardware.mousecur.initialize();
}

void changeResolutionBasedOnUserFileAlone()
{
if (weHaveAReasonToChange)
changeResolutionBasedOnCmdargsThenUserFile(new Cmdargs([]));
}

private bool weHaveAReasonToChange()
{
if (! display)
return true;
if (displayTryMode.full && currentMode.full)
return false;
return displayTryMode != currentMode;
}
14 changes: 14 additions & 0 deletions src/basics/user.d
Expand Up @@ -57,6 +57,20 @@ private auto newOpt(T)(string fileKey, T defaultVal)
return fileLanguage.value == basics.globals.fileLanguageEnglish;
}

struct DisplayTryMode {
bool full;
int x, y;
}

@property DisplayTryMode displayTryMode()
{
DisplayTryMode ret;
ret.full = screenWindowed is null ? false : ! screenWindowed.value;
ret.x = (screenWindowedX is null || ret.full) ? 0 : screenWindowedX.value;
ret.y = (screenWindowedY is null || ret.full) ? 0 : screenWindowedY.value;
return ret;
}

UserOptionFilename fileLanguage;
UserOption!int optionGroup;

Expand Down
46 changes: 37 additions & 9 deletions src/graphic/internal/getters.d
@@ -1,5 +1,6 @@
module graphic.internal.getters;

import std.range;
import std.exception : enforce;

import basics.globals;
Expand All @@ -18,25 +19,25 @@ out (ret) {
assert (valid(ret), "can't find Lix spritesheet");
}
body {
static Cutbit cached = null;
if (cached)
return cached;
if (_lixRawSprites)
return _lixRawSprites;
auto fn = new VfsFilename(fileImageSpritesheet.rootless ~ imgExt);
loadFromDisk(fn);
enforce(fn.rootlessNoExt in internal, "Can't find Lix spritesheet"
~ " at `" ~ fn.rootless ~ "'. The spritesheet is required for physics"
~ " because the number of sprites per row affect worker cycles."
~ " Is your Lix installation broken?");
cached = *(fn.rootlessNoExt in internal);
return cached;
_lixRawSprites = *(fn.rootlessNoExt in internal);
assert (_lixRawSprites);
return _lixRawSprites;
}

// Input: filename without any scaling subdir
// Output: The cutbit from the correct scaling subdir, or a replacement image
// See comment near graphic.internal.vars.internal about how we save strings
Cutbit getInternalMutable(in Filename fn)
{
if (dontWantRecoloredGraphics)
if (! wantRecoloredGraphics)
return nullCutbit;
auto correctScale = new VfsFilename(scaleDir ~ fn.file ~ imgExt);
auto fallbackScale = new VfsFilename(fn.rootless ~ imgExt);
Expand Down Expand Up @@ -64,7 +65,7 @@ Cutbit getInternalMutable(in Filename fn)
const(Cutbit) implGetLixSprites(in Style st)
out (ret) { assert(ret); }
body {
if (dontWantRecoloredGraphics)
if (! wantRecoloredGraphics)
return getLixRawSprites();
if (spritesheets[st] is null)
makeLixSprites(st);
Expand All @@ -74,7 +75,7 @@ body {
const(Cutbit) implGetPanelInfoIcon(in Style st)
out (ret) { assert(ret); }
body {
if (dontWantRecoloredGraphics)
if (! wantRecoloredGraphics)
return nullCutbit;
if (panelInfoIcons[st] is null)
makePanelInfoIcon(st);
Expand All @@ -84,7 +85,7 @@ body {
const(Cutbit) implGetSkillButton(in Style st)
out (ret) { assert(ret); }
body {
if (dontWantRecoloredGraphics)
if (! wantRecoloredGraphics)
return nullCutbit;
if (skillButtonIcons[st] is null)
makeSkillButtonIcon(st);
Expand All @@ -98,3 +99,30 @@ body {
return alcol3DforStyles[style];
}

/*
* Deallocate all VRAM. See all state in graphic.internal.vars to make
* sure we go over all possible resources here.
* We don't destroy non-VRAM resources like color tables for now.
*/
void implDeinitialize()
out { assert (spritesheets[Style.garden] is null, "badly deinitialized"); }
body {
void deinitArray(T)(ref T arr)
{
foreach (ref cb; arr) {
if (cb) {
cb.dispose();
cb = null;
}
}
}
deinitArray(internal);
deinitArray(spritesheets);
deinitArray(panelInfoIcons);
deinitArray(skillButtonIcons);
internal = null;
if (_lixRawSprites) {
_lixRawSprites.dispose();
_lixRawSprites = null;
}
}

0 comments on commit 165d0d0

Please sign in to comment.