3 Commits f8ba1feeb3 ... 69684c3a36

Author SHA1 Message Date
  Stephan Fuchs 69684c3a36 add `image` to existing locations 2 months ago
  Stephan Fuchs e3bdf54d86 add `setup.mediaPathRawToString()` 2 months ago
  Stephan Fuchs 401dc03924 add `UserStyle` 2 months ago

+ 1 - 0
sugarcube/src/StoryInterface.tw

@@ -1,4 +1,5 @@
 :: StoryInterface
+<style id="userConfiguredStyle" data-init-passage="UIUserSettings"></style>
 <div id="interface">
 	<div id="sidebar" data-passage="Sidebar">Sidebar</div>
 	<div id="passages">passages</div>

+ 24 - 0
sugarcube/src/interfaces.d.ts

@@ -24,6 +24,7 @@ declare module "twine-sugarcube" {
 		};
 		QuestsDict: { new(): QuestsDict };
 		Skill: { new(): Skill };
+		UserStyle: {new(): UserStyle};
 		VersionControl: { new(): VersionControl };
 
 
@@ -91,6 +92,7 @@ declare module "twine-sugarcube" {
 		makeSVG: (tag:string, attrs:any,innerHTML?:string|number|undefined) => SVGElement;
 		mediaPath(rawPath:string):string;
 		mediaPathImage(rawPath:string):string;
+		mediaPathRawToString(rawPath:ImagePath):string;
 		mergeDeep: (target:any, ...sources:any) => any;
 
 		npcDescription:(npcIdOrObject:string|NPC)=>string;
@@ -807,6 +809,8 @@ declare global {
 		priority: number, weight: number,  contents: string
 	}
 
+	type ImagePath = string|(string|number)[];
+
 	export interface ImageRand{
 
 	}
@@ -868,9 +872,29 @@ declare global {
 	}
 
 	export interface LocationDefinition{
+		image:ImagePath|LocationImageDefinition;
 		openTimes?:TimespanIdentifier;
 	}
 
+	export interface LocationImageDefinition{
+		day: ImagePath;
+		/**
+		 * Defaults to day.
+		 * @type {?ImagePath}
+		 */
+		night?:ImagePath;
+		/**
+		 * Defaults to day.
+		 * @type {?ImagePath}
+		 */
+		winterDay?:ImagePath;
+		/**
+		 * Defaults to night.
+		 * @type {?ImagePath}
+		 */
+		winterNight?:ImagePath;
+	}
+
 	export type NPC = NPCAccessor & Character & {[key:string]:any};
 
 	export interface NPCActivity{

+ 1 - 1
sugarcube/src/locations/_system/locations.ts

@@ -1,6 +1,6 @@
 setup.getLocation = function(locationId){
     return setup.locations[locationId] ?? {
-        
+        image:''
     };
 }
 

+ 2 - 1
sugarcube/src/locations/city/mall/torgcentr.ts

@@ -3,5 +3,6 @@ setup.locations.torgcentr={
         daysBL:['SU'],
 	    begin:[8,0],
 	    end:[21,0]
-    }
+    },
+    image:''
 }

+ 2 - 1
sugarcube/src/locations/restaurants/roadhouse/roadhouse.ts

@@ -8,7 +8,8 @@ setup.locations.city_kafe = {
 		daysBL:['MO'],
 		begin:[12,0],
 		end:[23,0]
-	}
+	},
+    image:''
 }
 
 setup.jobs ??= {};

+ 2 - 1
sugarcube/src/locations/stores/shop/shop.ts

@@ -3,5 +3,6 @@ setup.locations.shop={
         daysBL:['SU'],
 	    begin:[6,0],
 	    end:[22,0]
-    }
+    },
+    image:''
 }

+ 13 - 0
sugarcube/src/macros/media/mediaPath.ts

@@ -1,4 +1,16 @@
+setup.mediaPathRawToString = function(rawPath:ImagePath){
+    if(typeof rawPath === "string")
+        return rawPath;
+    if(Array.isArray(rawPath)){
+        const string:string = rawPath[0].toString();
+        const max:number = +rawPath[1];
+        return string.replace('#',rand(1,max).toString());
+    }
+    console.error('Unsupported type in setup.mediaPathRawToString:',rawPath,typeof rawPath);
+}
+
 setup.mediaPath = function(rawPath:string){
+    rawPath = setup.mediaPathRawToString(rawPath);
     if(rawPath.substring(0,6) == 'https:' || rawPath.substring(0,5) == 'http:')
         return rawPath;
 
@@ -7,6 +19,7 @@ setup.mediaPath = function(rawPath:string){
 }
 
 setup.mediaPathImage = function(rawPath:string){
+    rawPath = setup.mediaPathRawToString(rawPath);
     if(rawPath.substring(0,6) == 'https:' || rawPath.substring(0,5) == 'http:')
         return rawPath;
 

+ 20 - 2
sugarcube/src/sidebar/Sidebar.tw

@@ -804,10 +804,28 @@
 	<</button>>
 
 	<<button '🖹'>>
-
+		<<run Dialog.setup("UI Settings", "uiSettings");Dialog.wiki(Story.get("UISettingsDialog").processText());Dialog.open();>>
 	<</button>>
 
 	<<button '⭯'>>
 		<<run UI.restart();>>
 	<</button>>
-</div>
+</div>
+
+:: UISettingsDialog[include]
+Font Size:
+<<set _userStyle = setup.UserStyle.fromLocalStorage()>>
+<<attr 'min' 6 'max' 120>>
+	<<numberbox "_userStyle.fontSize" _userStyle.fontSize>>
+<</attr>>
+
+
+Font: 
+
+<<listbox "_userStyle.font" autoselect>>
+	<<option "Arial" "Arial">>
+	<<option "Georgia" "Georgia, serif;">>
+	<<option "Helmet" "Helmet, Freesans, sans-serif">>
+	<<option "Lucida Console" '"Lucida Console", Courier, monospace'>>
+	<<option "Times" 'Times, "Times New Roman", Georgia, serif'>>
+<</listbox>>

+ 5 - 0
sugarcube/src/sidebar/sidebar.css

@@ -103,3 +103,8 @@ color: #eee;
     grid-template-columns: 15vh;
     justify-content: center;
 }
+
+
+.uiSettings{
+    font-size: 16px;
+}

+ 77 - 0
sugarcube/src/style/UserStyle.ts

@@ -0,0 +1,77 @@
+class UserStyle{
+
+	static #localStorageIdentifier = 'userStyle';
+	static #domId = '#userConfiguredStyle';
+
+	static fromLocalStorage():UserStyle{
+		const dataFromLocalStorage = localStorage.getItem(UserStyle.#localStorageIdentifier);
+		if(!dataFromLocalStorage)
+			return new UserStyle();
+		return JSON.parse(dataFromLocalStorage) as UserStyle;
+	}
+
+	constructor(){
+
+	}
+
+	saveToLocalStorage(){
+		localStorage.setItem(UserStyle.#localStorageIdentifier,JSON.stringify(this));
+	}
+
+	update(){
+		this.saveToLocalStorage();
+		if($(UserStyle.#domId).length)
+			$(UserStyle.#domId).text(this.css);
+	}
+
+	get css():string{
+		return `body{font-family:${this.font};font-size:${this.fontSize}px;}`;
+	}
+
+	_font = 'Helmet, Freesans, sans-serif';
+	get font(){return this._font;}
+	set font(v:string){
+		this._font = v;
+		this.update();
+	}
+
+	_fontSize:number = 16;
+	get fontSize(){return this._fontSize;}
+	set fontSize(v:number){
+		this._fontSize = v;
+		this.update();
+	}
+
+
+
+	//#region System
+		_init(data: { [x: string]: any; }){
+			Object.keys(data).forEach(function (pn) {
+				this[pn] = clone(data[pn]);
+			}, this);
+
+			return this;
+		}
+
+		clone = function () {
+			return (new setup.UserStyle())._init(this);
+		};
+
+		toJSON = function () {
+			var ownData = {};
+			Object.keys(this).forEach(function (pn) {
+				if(typeof this[pn] !== "function")
+					ownData[pn] = clone(this[pn]);
+			}, this);
+			return JSON.reviveWrapper('(new setup.UserStyle())._init($ReviveData$)', ownData);
+		};
+	//#endregion
+
+}
+
+setup.UserStyle = UserStyle;
+
+$(document).one(':storyready', function (ev) {
+	let userStyle = UserStyle.fromLocalStorage();
+	userStyle.update();
+});