Music & Sound volume sliders in the settings menu (#611)

* Added music & sound volume sliders in the settings menu

* Changed the order of the sound options in the settings menu

* Fixed the formatting, removed extra semicolon

* Removed a bad character

* Update base-en.yaml

* Updated base-en.yaml

* Removed trailing spaces

* Type safety fixes

* Replaced logical XOR (^) with !==
This commit is contained in:
Yoshie2000 2020-08-31 15:46:21 +02:00 committed by GitHub
parent 05cedc965a
commit 50e40888fd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 1832 additions and 1676 deletions

View File

@ -1,5 +1,4 @@
// Common classes and style // Common classes and style
* { * {
margin: 0; margin: 0;
padding: 0; padding: 0;
@ -14,7 +13,6 @@ body {
overflow: hidden; overflow: hidden;
font-family: $mainFont; font-family: $mainFont;
font-synthesis: none; font-synthesis: none;
position: fixed; position: fixed;
top: 0; top: 0;
left: 0; left: 0;
@ -26,19 +24,15 @@ html {
position: fixed; position: fixed;
// scroll-behavior: smooth; // scroll-behavior: smooth;
background: $mainBgColor; background: $mainBgColor;
// Disable zooming and thus // Disable zooming and thus
-ms-touch-action: pan-x, pan-y; -ms-touch-action: pan-x, pan-y;
touch-action: pan-x, pan-y; touch-action: pan-x, pan-y;
-ms-content-zooming: none; -ms-content-zooming: none;
top: 0; top: 0;
left: 0; left: 0;
bottom: 0; bottom: 0;
right: 0; right: 0;
background: #dee1ea; background: #dee1ea;
@include DarkThemeOverride { @include DarkThemeOverride {
background: $darkModeGameBackground; background: $darkModeGameBackground;
} }
@ -50,7 +44,6 @@ body {
-moz-user-select: none; -moz-user-select: none;
-ms-user-select: none; -ms-user-select: none;
background: inherit !important; background: inherit !important;
text-transform: none; text-transform: none;
white-space: normal; white-space: normal;
word-break: normal; word-break: normal;
@ -66,19 +59,17 @@ body {
scrollbar-width: 6px; scrollbar-width: 6px;
-webkit-font-smoothing: antialiased; -webkit-font-smoothing: antialiased;
// -webkit-overflow-scrolling: touch; /* stop scrolling immediately */ // -webkit-overflow-scrolling: touch; /* stop scrolling immediately */
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ -webkit-touch-callout: none;
-webkit-text-size-adjust: none; /* prevent webkit from resizing text to fit */ /* prevent callout to copy image, etc when tap to hold */
-webkit-text-size-adjust: none;
/* prevent webkit from resizing text to fit */
// Internet explorer // Internet explorer
scrollbar-face-color: #888; scrollbar-face-color: #888;
scrollbar-track-color: rgba(255, 255, 255, 0.1); scrollbar-track-color: rgba(255, 255, 255, 0.1);
// Firefox // Firefox
scrollbar-color: #cdd0d4 rgba(#000, 0.05); scrollbar-color: #cdd0d4 rgba(#000, 0.05);
overflow: hidden; overflow: hidden;
@include Text; @include Text;
&.externalAdOpen { &.externalAdOpen {
&::before { &::before {
text-transform: uppercase; text-transform: uppercase;
@ -97,7 +88,6 @@ body {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
color: #fff; color: #fff;
@include InlineAnimation(1s ease-in-out infinite) { @include InlineAnimation(1s ease-in-out infinite) {
50% { 50% {
transform: scale(1.05); transform: scale(1.05);
@ -105,9 +95,7 @@ body {
} }
} }
} }
// For recording the bg video // For recording the bg video
// filter: blur(5px); // filter: blur(5px);
// &::after { // &::after {
// position: fixed; // position: fixed;
@ -122,20 +110,24 @@ body {
} }
img { img {
-webkit-touch-callout: none; /* prevent callout to copy image, etc when tap to hold */ -webkit-touch-callout: none;
/* prevent callout to copy image, etc when tap to hold */
} }
i { i {
font-style: normal; font-style: normal;
} }
b, b,
strong { strong {
font-weight: normal; font-weight: normal;
} }
u, u,
a { a {
text-decoration: none; text-decoration: none;
} }
input, input,
textarea, textarea,
select { select {
@ -152,7 +144,6 @@ button {
cursor: pointer; cursor: pointer;
position: relative; position: relative;
@include TextShadow3D; @include TextShadow3D;
&.prefab_BuyButtonWithResources { &.prefab_BuyButtonWithResources {
display: flex; display: flex;
box-sizing: border-box; box-sizing: border-box;
@ -163,27 +154,23 @@ button {
justify-content: center; justify-content: center;
align-items: center; align-items: center;
@include S(width, 85px); @include S(width, 85px);
&.tooExpensive { &.tooExpensive {
color: $colorRedBright; color: $colorRedBright;
background-color: #555; background-color: #555;
cursor: default; cursor: default;
} }
.cost_entry { .cost_entry {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
b { b {
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
} }
&.tooExpensive { &.tooExpensive {
cursor: default !important; cursor: default !important;
background-color: #565859 !important; background-color: #565859 !important;
@ -214,7 +201,6 @@ button {
// color: $accentColorDark; // color: $accentColorDark;
letter-spacing: 0.05em !important; letter-spacing: 0.05em !important;
// box-shadow: 0 #{D(1px)} #{D(2px)} 0 rgba(0, 10, 20, 0.2); // box-shadow: 0 #{D(1px)} #{D(2px)} 0 rgba(0, 10, 20, 0.2);
.keybinding { .keybinding {
@include S(bottom, -2.5px); @include S(bottom, -2.5px);
@include S(right, -2px); @include S(right, -2px);
@ -226,10 +212,13 @@ button {
} }
::selection { ::selection {
background: $colorGreenBright; /* WebKit/Blink Browsers */ background: $colorGreenBright;
/* WebKit/Blink Browsers */
} }
::-moz-selection { ::-moz-selection {
background: $colorGreenBright; /* Gecko Browsers */ background: $colorGreenBright;
/* Gecko Browsers */
} }
input[type="text"], input[type="text"],
@ -244,35 +233,27 @@ input[type="email"] {
background: lighten($mainBgColor, 8); background: lighten($mainBgColor, 8);
color: #eee; color: #eee;
text-align: left; text-align: left;
user-select: text !important; user-select: text !important;
pointer-events: all !important; pointer-events: all !important;
@include Text; @include Text;
@include IncreasedClickArea(15px); @include IncreasedClickArea(15px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
&::placeholder { &::placeholder {
color: #fff; color: #fff;
opacity: 0.4; opacity: 0.4;
} }
transition: background-color 0.1s ease-in-out !important; transition: background-color 0.1s ease-in-out !important;
@include TextShadow3D(#fff); @include TextShadow3D(#fff);
@include BoxShadow3D(lighten($mainBgColor, 30)); @include BoxShadow3D(lighten($mainBgColor, 30));
&:focus { &:focus {
@include BoxShadow3D(lighten($mainBgColor, 35)); @include BoxShadow3D(lighten($mainBgColor, 35));
} }
&.errored { &.errored {
@include BoxShadow3D(mix(lighten($mainBgColor, 30), #f77, 25%)); @include BoxShadow3D(mix(lighten($mainBgColor, 30), #f77, 25%));
&:focus { &:focus {
@include BoxShadow3D(mix(lighten($mainBgColor, 50), #f77, 25%)); @include BoxShadow3D(mix(lighten($mainBgColor, 50), #f77, 25%));
} }
} }
&.input-token { &.input-token {
@include SuperHeading; @include SuperHeading;
text-align: center; text-align: center;
@ -324,7 +305,6 @@ canvas {
// &.unsmoothed { // &.unsmoothed {
// } // }
letter-spacing: 0 !important; letter-spacing: 0 !important;
transform: translateZ(0); transform: translateZ(0);
backface-visibility: hidden; backface-visibility: hidden;
-webkit-backface-visibility: hidden; -webkit-backface-visibility: hidden;
@ -404,13 +384,11 @@ canvas {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-transform: uppercase; text-transform: uppercase;
@include Text; @include Text;
@include TextShadow3D; @include TextShadow3D;
opacity: 1; opacity: 1;
z-index: 20; z-index: 20;
color: #393747; color: #393747;
&::after { &::after {
content: " "; content: " ";
background: uiResource("loading.svg") center center / contain no-repeat; background: uiResource("loading.svg") center center / contain no-repeat;
@ -421,7 +399,6 @@ canvas {
display: inline-block; display: inline-block;
vertical-align: middle; vertical-align: middle;
} }
@include DarkThemeOverride { @include DarkThemeOverride {
color: #fff; color: #fff;
} }
@ -443,7 +420,6 @@ canvas {
.prefab_FeatureComingSoon { .prefab_FeatureComingSoon {
position: relative; position: relative;
&::after { &::after {
@include S(top, -5px); @include S(top, -5px);
@include S(left, -5px); @include S(left, -5px);
@ -461,9 +437,7 @@ canvas {
@include PlainText; @include PlainText;
text-transform: uppercase; text-transform: uppercase;
} }
opacity: 0.6; opacity: 0.6;
> * { > * {
opacity: 0.5 !important; opacity: 0.5 !important;
} }
@ -488,14 +462,12 @@ canvas {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
flex-direction: column; flex-direction: column;
.loadingImage { .loadingImage {
background: uiResource("loading.svg") center center / #{D(60px)} no-repeat; background: uiResource("loading.svg") center center / #{D(60px)} no-repeat;
width: 100%; width: 100%;
display: flex; display: flex;
flex-grow: 1; flex-grow: 1;
} }
.loadingStatus { .loadingStatus {
position: absolute; position: absolute;
@include S(left, 20px); @include S(left, 20px);
@ -503,12 +475,10 @@ canvas {
@include S(bottom, 30px); @include S(bottom, 30px);
@include Text; @include Text;
@include TextShadow3D(#aaa); @include TextShadow3D(#aaa);
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
> .bar { > .bar {
display: none; display: none;
@include S(margin-top, 15px); @include S(margin-top, 15px);
@ -517,7 +487,6 @@ canvas {
position: relative; position: relative;
@include TextShadow3D(#fff); @include TextShadow3D(#fff);
height: 2px; height: 2px;
.inner { .inner {
position: absolute !important; position: absolute !important;
top: 0; top: 0;
@ -526,9 +495,7 @@ canvas {
z-index: 1; z-index: 1;
@include BoxShadow3D($themeColor, $size: 1px); @include BoxShadow3D($themeColor, $size: 1px);
@include S(border-radius, $globalBorderRadius); @include S(border-radius, $globalBorderRadius);
transform-origin: 0% 50%; transform-origin: 0% 50%;
@include InlineAnimation(1.3s ease-in-out infinite) { @include InlineAnimation(1.3s ease-in-out infinite) {
0% { 0% {
background-color: darken($themeColor, 5); background-color: darken($themeColor, 5);
@ -544,7 +511,6 @@ canvas {
} }
} }
} }
.status { .status {
display: none; display: none;
position: relative; position: relative;
@ -579,11 +545,9 @@ canvas {
&.loading { &.loading {
opacity: 0.2; opacity: 0.2;
} }
&:hover { &:hover {
background-color: darken($bgColor, 5); background-color: darken($bgColor, 5);
} }
.knob { .knob {
@include S(width, 20px); @include S(width, 20px);
@include S(height, 17px); @include S(height, 17px);
@ -594,20 +558,51 @@ canvas {
@include BorderRadius(20px); @include BorderRadius(20px);
@include BoxShadow3D(#fff, $size: 1px); @include BoxShadow3D(#fff, $size: 1px);
} }
&.checked { &.checked {
background-color: $themeColor; background-color: $themeColor;
@include BoxShadow3D($themeColor, $size: 2px); @include BoxShadow3D($themeColor, $size: 2px);
.knob { .knob {
@include S(margin-left, 15px); @include S(margin-left, 15px);
} }
&:hover { &:hover {
background-color: lighten($themeColor, 15); background-color: lighten($themeColor, 15);
} }
} }
} }
.range {
display: flex;
align-items: center;
justify-content: center;
}
.range-input {
cursor: pointer;
background-color: transparent;
width: 100px;
height: 10px;
transform: translate(7px, 2px);
&::-webkit-slider-runnable-track {
background-color: darken($mainBgColor, 3);
color: darken($mainBgColor, 3);
height: 16px;
border-radius: 8px;
}
&::-webkit-slider-thumb {
appearance: none;
-webkit-appearance: none;
box-shadow: inset 0 0 0 10px $themeColor;
background-color: transparent;
width: 20px;
height: 20px;
border-radius: 50%;
transition: 0.3s;
}
&:hover::-webkit-slider-thumb {
box-shadow: inset 0 0 0 10px lighten($themeColor, 15);
}
}
.keybinding { .keybinding {
background: #fff; background: #fff;
text-transform: uppercase; text-transform: uppercase;
@ -622,7 +617,6 @@ canvas {
text-shadow: none !important; text-shadow: none !important;
// font-family: Arial, sans-serif !important; // font-family: Arial, sans-serif !important;
} }
font-weight: bold; font-weight: bold;
color: $accentColorDark; color: $accentColorDark;
text-align: center; text-align: center;
@ -638,7 +632,6 @@ canvas {
@include S(height, 12px); @include S(height, 12px);
overflow: hidden; overflow: hidden;
border: #{D(0px)} solid $accentColorDark; border: #{D(0px)} solid $accentColorDark;
.keybinding_space { .keybinding_space {
@include S(font-size, 17px); @include S(font-size, 17px);
@include S(line-height, 11px); @include S(line-height, 11px);
@ -651,7 +644,6 @@ canvas {
.xpaystation-widget-lightbox-overlay { .xpaystation-widget-lightbox-overlay {
background: rgba($mainBgColor, 0.94); background: rgba($mainBgColor, 0.94);
} }
&, &,
iframe { iframe {
pointer-events: all; pointer-events: all;
@ -692,9 +684,7 @@ iframe {
* { * {
pointer-events: all; pointer-events: all;
} }
background: rgba($mainBgColor, 0.94) !important; background: rgba($mainBgColor, 0.94) !important;
.cpmsvideoclosebanner { .cpmsvideoclosebanner {
font-family: GameFont !important; font-family: GameFont !important;
font-size: 16px !important; font-size: 16px !important;

View File

@ -117,7 +117,7 @@ export class LogicGateSystem extends GameSystemWithFilter {
*/ */
compute_XOR(parameters) { compute_XOR(parameters) {
assert(parameters.length === 2, "bad parameter count for XOR"); assert(parameters.length === 2, "bad parameter count for XOR");
return isTruthyItem(parameters[0]) ^ isTruthyItem(parameters[1]) return isTruthyItem(parameters[0]) !== isTruthyItem(parameters[1])
? BOOL_TRUE_SINGLETON ? BOOL_TRUE_SINGLETON
: BOOL_FALSE_SINGLETON; : BOOL_FALSE_SINGLETON;
} }

View File

@ -146,9 +146,10 @@ class MusicInstance extends MusicInstanceInterface {
return this.playing; return this.playing;
} }
play() { play(volume) {
if (this.howl) { if (this.howl) {
this.playing = true; this.playing = true;
this.howl.volume(volume);
if (this.instance) { if (this.instance) {
this.howl.play(this.instance); this.howl.play(this.instance);
} else { } else {
@ -157,6 +158,12 @@ class MusicInstance extends MusicInstanceInterface {
} }
} }
setVolume(volume) {
if (this.howl) {
this.howl.volume(volume);
}
}
deinitialize() { deinitialize() {
if (this.howl) { if (this.howl) {
this.howl.unload(); this.howl.unload();

View File

@ -61,7 +61,11 @@ export class MusicInstanceInterface {
abstract; abstract;
} }
play() { play(volume) {
abstract;
}
setVolume(volume) {
abstract; abstract;
} }
@ -101,6 +105,9 @@ export class SoundInterface {
this.musicMuted = false; this.musicMuted = false;
this.soundsMuted = false; this.soundsMuted = false;
this.musicVolume = 1.0;
this.soundVolume = 1.0;
} }
/** /**
@ -122,6 +129,8 @@ export class SoundInterface {
this.musicMuted = this.app.settings.getAllSettings().musicMuted; this.musicMuted = this.app.settings.getAllSettings().musicMuted;
this.soundsMuted = this.app.settings.getAllSettings().soundsMuted; this.soundsMuted = this.app.settings.getAllSettings().soundsMuted;
this.musicVolume = this.app.settings.getAllSettings().musicVolume;
this.soundVolume = this.app.settings.getAllSettings().soundVolume;
if (G_IS_DEV && globalConfig.debug.disableMusic) { if (G_IS_DEV && globalConfig.debug.disableMusic) {
this.musicMuted = true; this.musicMuted = true;
@ -189,7 +198,7 @@ export class SoundInterface {
} }
} else { } else {
if (this.currentMusic) { if (this.currentMusic) {
this.currentMusic.play(); this.currentMusic.play(this.musicVolume);
} }
} }
} }
@ -202,6 +211,41 @@ export class SoundInterface {
this.soundsMuted = muted; this.soundsMuted = muted;
} }
/**
* Returns the music volume
* @returns {number}
*/
getMusicVolume() {
return this.musicVolume;
}
/**
* Returns the sound volume
* @returns {number}
*/
getSoundVolume() {
return this.soundVolume;
}
/**
* Sets the music volume
* @param {number} volume
*/
setMusicVolume(volume) {
this.musicVolume = clamp(volume, 0, 1);
if (this.currentMusic) {
this.currentMusic.setVolume(this.musicVolume);
}
}
/**
* Sets the sound volume
* @param {number} volume
*/
setSoundVolume(volume) {
this.soundVolume = clamp(volume, 0, 1);
}
/** /**
* Focus change handler, called by the pap * Focus change handler, called by the pap
* @param {boolean} pageIsVisible * @param {boolean} pageIsVisible
@ -211,7 +255,7 @@ export class SoundInterface {
if (this.currentMusic) { if (this.currentMusic) {
if (pageIsVisible) { if (pageIsVisible) {
if (!this.currentMusic.isPlaying() && !this.musicMuted) { if (!this.currentMusic.isPlaying() && !this.musicMuted) {
this.currentMusic.play(); this.currentMusic.play(this.musicVolume);
} }
} else { } else {
this.currentMusic.stop(); this.currentMusic.stop();
@ -230,7 +274,7 @@ export class SoundInterface {
logger.warn("Sound", key, "not found, probably not loaded yet"); logger.warn("Sound", key, "not found, probably not loaded yet");
return; return;
} }
this.sounds[key].play(1.0); this.sounds[key].play(this.soundVolume);
} }
/** /**
@ -253,9 +297,9 @@ export class SoundInterface {
return; return;
} }
let volume = 1.0; let volume = this.soundVolume;
if (!root.camera.isWorldPointOnScreen(worldPosition)) { if (!root.camera.isWorldPointOnScreen(worldPosition)) {
volume = 0.2; volume = this.soundVolume / 5; // In the old implementation this value was fixed to 0.2 => 20% of 1.0
} }
volume *= clamp(root.camera.zoomLevel / 3); volume *= clamp(root.camera.zoomLevel / 3);
this.sounds[key].play(clamp(volume)); this.sounds[key].play(clamp(volume));
@ -277,7 +321,7 @@ export class SoundInterface {
this.currentMusic = music; this.currentMusic = music;
if (music && this.pageIsVisible && !this.musicMuted) { if (music && this.pageIsVisible && !this.musicMuted) {
logger.log("Starting", this.currentMusic.key); logger.log("Starting", this.currentMusic.key);
music.play(); music.play(this.musicVolume);
} }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -220,3 +220,78 @@ export class BoolSetting extends BaseSetting {
return typeof value === "boolean"; return typeof value === "boolean";
} }
} }
export class RangeSetting extends BaseSetting {
constructor(
id,
category,
changeCb = null,
enabled = true,
defaultValue = 100,
minValue = 0,
maxValue = 100,
stepSize = 1
) {
super(id, category, changeCb, enabled);
this.defaultValue = defaultValue;
this.minValue = minValue;
this.maxValue = maxValue;
this.stepSize = stepSize;
}
getHtml() {
return `
<div class="setting cardbox ${this.enabled ? "enabled" : "disabled"}">
${this.enabled ? "" : `<span class="standaloneOnlyHint">${T.demo.settingNotAvailable}</span>`}
<div class="row">
<label>${T.settings.labels[this.id].title}</label>
<div class="value range" data-setting="${this.id}">
<label class="range-label">${this.defaultValue}</label>
<input class="range-input" type="range" value="${this.defaultValue}" min="${
this.minValue
}" max="${this.maxValue}" step="${this.stepSize}">
</div>
</div>
<div class="desc">
${T.settings.labels[this.id].description}
</div>
</div>`;
}
bind(app, element, dialogs) {
this.app = app;
this.element = element;
this.dialogs = dialogs;
this.element.querySelector(".range-input").addEventListener("input", () => {
this.modify();
});
}
syncValueToElement() {
const value = this.app.settings.getSetting(this.id);
/** @type {HTMLInputElement} */
const rangeInput = this.element.querySelector(".range-input"),
rangeLabel = this.element.querySelector(".range-label");
rangeInput.value = value;
rangeLabel.innerHTML = value;
}
modify() {
/** @type {HTMLInputElement} */
const rangeInput = this.element.querySelector(".range-input");
const newValue = Number(rangeInput.value);
this.app.settings.updateSetting(this.id, newValue);
this.syncValueToElement();
if (this.changeCb) {
this.changeCb(this.app, newValue);
}
}
validate(value) {
return typeof value === "number";
}
}

View File

@ -728,6 +728,16 @@ settings:
description: >- description: >-
Bei der Aktivierung wird die Musik stummgeschaltet. Bei der Aktivierung wird die Musik stummgeschaltet.
soundVolume:
title: Geräuschlautstärke
description: >-
Ändert die Lautstärke von Geräuschen.
musicVolume:
title: Musiklautstärke
description: >-
Ändert die Lautstärke der Musik.
theme: theme:
title: Farbmodus title: Farbmodus
description: >- description: >-

File diff suppressed because it is too large Load Diff

View File

@ -72,7 +72,7 @@ steamPage:
Bu oyuna herkes katkıda bulunabilir! Aktif olarak toplulukğa katkıda bulunuyorum ve bütün önerileri gözden geçirmeye çalışıyorum. Bu oyuna herkes katkıda bulunabilir! Aktif olarak toplulukğa katkıda bulunuyorum ve bütün önerileri gözden geçirmeye çalışıyorum.
Yol planıma Trello'dan bakmayı unutmayın! Yol planıma Trello'dan bakmayı unutmayın!
[b]Links[/b] [b]Links[/b]
@ -274,7 +274,6 @@ dialogs:
title: Kesmeyi onayla title: Kesmeyi onayla
desc: Seçili yapıları yapıştırmak için yeterli kaynağınız yok! Kesmek istediğinize emin misiniz? desc: Seçili yapıları yapıştırmak için yeterli kaynağınız yok! Kesmek istediğinize emin misiniz?
ingame: ingame:
# This is shown in the top left corner and displays useful keybindings in # This is shown in the top left corner and displays useful keybindings in
# every situation # every situation
@ -618,7 +617,7 @@ storyRewards:
title: Özgür Mod title: Özgür Mod
desc: Başardın! <strong>Özgür mod</strong> açıldı! Merkeze istenilen şekiller artık rastgele oluşturulacak! (Merak etme, yeni içerikler planlanıyor!) desc: Başardın! <strong>Özgür mod</strong> açıldı! Merkeze istenilen şekiller artık rastgele oluşturulacak! (Merak etme, yeni içerikler planlanıyor!)
reward_blueprints: # 'Taslaklar' yerine 'planlar' da kullanılabilir. reward_blueprints: # 'Taslaklar' yerine 'planlar' da kullanılabilir.
title: Taslaklar title: Taslaklar
desc: Fabrikanın bölümlerini artık <strong>kopyalayıp yapıştırabilirsin</strong>! Bir alan seç (CTRL tuşuna bas ve fareyi sol-tık tuşuna basarak sürükle), ve kopyalamak için 'C' tuşuna bas.<br><br>Kopyaladığın taslağı <strong>bedel karşılığı</strong> yapıştırabilmek için <strong>taslak şekilleri</strong> üretmelisin! (Az önce teslim ettiğin şekiller). desc: Fabrikanın bölümlerini artık <strong>kopyalayıp yapıştırabilirsin</strong>! Bir alan seç (CTRL tuşuna bas ve fareyi sol-tık tuşuna basarak sürükle), ve kopyalamak için 'C' tuşuna bas.<br><br>Kopyaladığın taslağı <strong>bedel karşılığı</strong> yapıştırabilmek için <strong>taslak şekilleri</strong> üretmelisin! (Az önce teslim ettiğin şekiller).
@ -640,7 +639,7 @@ settings:
userInterface: Kullanıcı Arayüzü userInterface: Kullanıcı Arayüzü
advanced: Gelİşmİş advanced: Gelİşmİş
versionBadges: # Development, Staging, Production versionBadges: # Development, Staging, Production
dev: Geliştirme dev: Geliştirme
staging: Yükseltme staging: Yükseltme
prod: Üretim prod: Üretim