Skip to content

Commit

Permalink
Initial support for image markup in localized books
Browse files Browse the repository at this point in the history
Using a TextLabel override called ImageLabel to draw an image in place of a label inside book reader. This allows image to be treated like a label in terms of size and layout.
Does not seek mods yet. Images must be in StreamingAssets/Text/Books/BookImages.
Image not currently scissored to book reader interior. Will add this soon.
  • Loading branch information
Interkarma committed Dec 1, 2022
1 parent 60ed3b1 commit 38e4f68
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 0 deletions.
1 change: 1 addition & 0 deletions Assets/Scripts/API/TextFile.cs
Expand Up @@ -125,6 +125,7 @@ public enum Formatting
// Custom codes
Color = 0x100,
Scale = 0x101,
Image = 0x102,

Nothing = 0xffff,
}
Expand Down
58 changes: 58 additions & 0 deletions Assets/Scripts/Game/UserInterface/ImageLabel.cs
@@ -0,0 +1,58 @@
// Project: Daggerfall Unity
// Copyright: Copyright (C) 2009-2022 Daggerfall Workshop
// Web Site: http://www.dfworkshop.net
// License: MIT License (http://www.opensource.org/licenses/mit-license.php)
// Source Code: https://github.com/Interkarma/daggerfall-unity
// Original Author: Gavin Clayton (interkarma@dfworkshop.net)
// Contributors:
//
// Notes:
//

using UnityEngine;

namespace DaggerfallWorkshop.Game.UserInterface
{
/// <summary>
/// Renders an image in place of a text label in book reader UI.
/// </summary>
public class ImageLabel : TextLabel
{
Texture2D image;
float imageWidth;
float imageHeight;
float scaleFactor;

public Texture2D Image
{
get { return image; }
set { image = value; RefreshLayout(); }
}

public override void Draw()
{
if (image == null || image.width == 0 || image.height == 0)
return;

// Image position is always centred to page
RefreshLayout();
Rect totalRect = Rectangle;
Rect rect = new Rect(totalRect.x + imageWidth / 2, totalRect.y, imageWidth, imageHeight);
Size = new Vector2(imageWidth, imageHeight);
DaggerfallUI.DrawTexture(rect, image, ScaleMode.StretchToFill);
}

public override void RefreshLayout()
{
if (image == null || image.width == 0 || image.height == 0)
return;

// Image size is always half width of page area
base.RefreshLayout();
imageWidth = (float)MaxWidth * LocalScale.x / 2f;
scaleFactor = (float)MaxWidth / (float)image.width;
imageHeight = (float)image.height * scaleFactor * LocalScale.y / 2f;
Size = new Vector2(imageWidth, imageHeight);
}
}
}
11 changes: 11 additions & 0 deletions Assets/Scripts/Game/UserInterface/ImageLabel.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Expand Up @@ -11,6 +11,7 @@

using UnityEngine;
using System;
using System.IO;
using System.Collections.Generic;
using DaggerfallWorkshop.Game.UserInterface;
using DaggerfallWorkshop.Game.Items;
Expand All @@ -22,6 +23,9 @@ namespace DaggerfallWorkshop.Game.UserInterfaceWindows
{
public class DaggerfallBookReaderWindow : DaggerfallBaseWindow
{
const string textFolderName = "Text";
const string bookImagesPath = "Books/BookImages";

const float scrollAmount = 24;
const string nativeImgName = "BOOK00I0.IMG";
char newline = '\n';
Expand Down Expand Up @@ -222,6 +226,9 @@ void CreateBookLabels(LocalizedBook localizedBook)
case TextFile.Formatting.Scale:
currentScale = TryParseScale(token.text);
break;
case TextFile.Formatting.Image:
bookLabels.Add(CreateImageLabel(token.text));
break;
default:
bookLabels.Add(CreateLabel(currentFont, currentAlignment, currentColor, token.text, currentScale));
break;
Expand Down Expand Up @@ -251,6 +258,29 @@ TextLabel CreateLabel(DaggerfallFont font, HorizontalAlignment alignment, Color
return label;
}

ImageLabel CreateImageLabel(string filename)
{
ImageLabel label = new ImageLabel();

// TODO: Seek book images from mods

// Get path to localized book file and check it exists
string path = Path.Combine(Application.streamingAssetsPath, textFolderName, bookImagesPath, filename);
if (!File.Exists(path))
return label;

// Load image
byte[] data = File.ReadAllBytes(path);
if (data != null && data.Length > 0)
{
Texture2D image = new Texture2D(0, 0);
image.LoadImage(data);
label.Image = image;
}

return label;
}

void LayoutBookLabels()
{
if (!IsBookOpen)
Expand Down
14 changes: 14 additions & 0 deletions Assets/Scripts/Localization/DaggerfallStringTableImporter.cs
Expand Up @@ -51,6 +51,7 @@ public static class DaggerfallStringTableImporter
const string markupFontPrefix = "[/font";
const string markupTextColorPrefix = "[/color";
const string markupTextScalePrefix = "[/scale";
const string markupImagePrefix = "[/image";
const string markupInputCursor = "[/input]";
const string markupSubrecordSeparator = "[/record]";
const string markupEndRecord = "[/end]";
Expand Down Expand Up @@ -228,6 +229,8 @@ static void AddToken(List<TextFile.Token> tokens, string markup)
tokens.Add(ParseColorMarkup(markup));
else if (markup.StartsWith(markupTextScalePrefix))
tokens.Add(ParseScaleMarkup(markup));
else if (markup.StartsWith(markupImagePrefix))
tokens.Add(ParseImageMarkup(markup));
else if (markup == markupSubrecordSeparator)
tokens.Add(new TextFile.Token(TextFile.Formatting.SubrecordSeparator));
else if (markup == markupInputCursor)
Expand Down Expand Up @@ -295,6 +298,17 @@ static TextFile.Token ParseScaleMarkup(string markup)
return new TextFile.Token(TextFile.Formatting.Scale, match.Groups["x"].Value, 0, 0);
}

static TextFile.Token ParseImageMarkup(string markup)
{
const string pattern = @"\[\/image=(?<x>.*)\]";

Match match = Regex.Match(markup, pattern);
if (!match.Success)
return new TextFile.Token(TextFile.Formatting.Text, markup);

return new TextFile.Token(TextFile.Formatting.Image, match.Groups["x"].Value, 0, 0);
}

/// <summary>
/// Peeks a markup token from current position in stream.
/// </summary>
Expand Down
8 changes: 8 additions & 0 deletions Assets/StreamingAssets/Text/Books/BookImages.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Assets/StreamingAssets/Text/Books/BookImages/readme.txt
@@ -0,0 +1,9 @@
Place images into this folder for use by localized books.
Insert image into book using the markup [/image=filename] in book text.
Accepts PNG and JPG images.

For example:

[/image=lakecastle.png]

Will attempt to insert the image "lakecastle.png" from BookImages.
7 changes: 7 additions & 0 deletions Assets/StreamingAssets/Text/Books/BookImages/readme.txt.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 38e4f68

Please sign in to comment.