NVList v3.3


Aside from the usual list of bugfixes, NVList 3.3 adds some usability features to the build system. The resource optimizer is no longer a separate window, but will instead integrate into the build system window itself. You’ll also get a warning now when trying to close the window while a build task is still running.

My favorite new feature is the support for tiling textures. Marking an an image as tiling causes it to repeat for UV coordinates outside the [0.0-1.0) range. These UV coordinates can be set using a new setUV method for image drawables. The most obvious use for tiling is an animated fog effect (Days of the Divine uses it in that way), but I’m looking forward to more creative uses in the future.

The improvements on the Android side are a lot more noticeable. JNG images are finally supported on Android as well, bringing with them a significant reduction in file size over PNG. By far the biggest change however is the addition of a new OpenGL ES 2.0 rendering back-end for devices with the required hardware support (almost everything supports GLES 2.0 these days). On older hardware, the old rendering back-end will still be used. The GLES 2.0 renderer fully supports bitmap tweens and shaders, closing the gap between desktop and mobile almost entirely.

→ NVList project page

2013/06/21 — 3.3 (r101)

– Added support for tiling textures, see ch11-resources.xml for more details.
– Images now let you specify a custom UV-range to control the texture offset.
– Added a fast mode to the texture composite function that skips alpha blending.
– skipScene() is now cancelable by pressing the text continue key.
– Improved analytics responsible for generating preloader.bin, handles multiple
  image loads generated from a single line better.
– Better error messages in case of syntax errors in loaded modules.
– Closing Build.jar will now show a warning if a build task is still running.
– The resource optimizer window has been integrated into its parent window.
– Android: Resource optimizer will only be re-run when necessary.
– Android: Added prefs-default-android.ini which allows preference overrides
  to be used for an Android port.
– Android: Added a GLES 2.0 rendering backend with support for bitmaptweens and
– Android: Support for JNG images.
– setScale() erroneously stopped accepting non-positive values.
– Running in Java 7 could under specific circumstances result in an
– Newline characters in text commands weren’t being handled properly.
– Built-in word count incorrectly counted punctuation as words.
– Changed the rendering implementation of TriangleGrid to avoid a potential GC
  in the middle of rendering.
– Retrieving the pixels for certain texture types didn’t work.
– Fixed a possible OutOfMemory exception when using the skip mode on Java 7
  continuously for very long stretches of time.
– Android: Will not try to download an XAPK if no valid LVL key is specified.

→ NVList project page

NVList internals 02: Rendering

Previous parts — 01 Image Loading

Rendering in NVList is handled entirely through OpenGL (ES on Android). There’s no software fallback renderer, but there’s not really a need for one either. I’ve heard terrible tales of the OpenGL implementations on Intel graphics cards, but other than awful performance I haven’t found any problems. Heck, even the "GDI generic" OpenGL 1.1 implementation built into Windows seems to work fine. The capabilities of NVList’s renderer attempt to closely mirror that of the underlying graphics hardware. Some parts (GLSL shaders) require 2004-era hardware, which is why they’re optional. I’d love to be able to count on fragment shader support, but unfortunately for anyone building a VN engine, your users will expect things to work even on their decade-old toaster.

Continue reading

NVList internals 01: Image Loading

This is the first in a series of posts explaining some of the internals of the NVList engine. If you’ve ever wondered what a visual novel engine looks like on the inside (or at least the way NVList is designed), here’s your chance. I have a few articles already planned, but suggestions for future subjects are also welcome.

Today’s topic is image loading, covering the entire process from a PNG file on the hard drive until the moment it’s ready for rendering to the screen with OpenGL.

Continue reading

NVList v3.2


The most prominent change in 3.2 is a large restructuring of the bundled tutorial scripts. I tried to group things more logically and order them by usefulness/difficulty. The newly added setExitFunction allows you to replace the default exit confirmation dialog.

I’ve also updated Cottage on the Moor (NVList example VN) to be compatible with NVList 3.0 and above.

→ NVList project page

2013/01/09 — 3.2 (r94)

– Reduced latency when starting audio while another audio track is already
  playing by implementing a more fine-grained locking system.
– Reduced default fade-in/fade-out time when changing background music.
– Screenshot size for the save screen is now configurable through the
  vn.saveScreenshotWidth/vn.saveScreenshotHeight preferences.
– Added a chapter to the manual with the differences when running on Android.
– Large cleanup/restructuring of bundled tutorial scripts.
– Added setExitFunction() which allows you to override the default behavior
  of the exit confirmation dialog (whether activated by the window close
  button, exit menu item or the Lua exit function).

– Playing video in an upscaled window while an FBO is used for rendering caused
  the video to be clipped (only lower-left rect visible).
– Screen didn’t redraw when changing a textless TextDrawable.
– Improved error handling for the edit button in the build command panel.
– Image gallery script was broken.
– Anim.par() will no longer override its components’s loop attribute.
– Incorrect return value for yielding Lua functions invoked from a Java
  function (in practice, that means call/dofile).

→ NVList project page

NVList v3.1

I’ve received some reports of freezing/crashing on Linux/Mac with older versions of NVList. The included OpenGL bindings have been updated to the most recent version (JOGL 2.0-rc11) which should resolve the problems. Please let me know if you’re still having these kinds of errors with NVList 3.1.

The most prominent change in NVList 3.1 is the inclusion of a default splashscreen for the generated executable. It uses the same image as the splash screen for the installer, build-res/splash.png. Another nice addition is the script tab in the debug window. You can use it to directly jump to a script (equivalent to using call in the Lua tab) and also to view information about your script files like the total word count. I’ve cleaned up and restructured parts of the text rendering code as well. Right-to-left (and bidirectional) text should now work on both the desktop and Android versions of NVList.

→ NVList project page

2012/12/08 — 3.1 (r86)

– Update to JOGL-2.0-RC11. Should help with errors on Mac, freezes on Linux.
– Added option to show a splashscreen during startup.
– Added a script tab to the debug window. It includes a script info button to
  display the line/word count for each of the scripts.
– Added Game.addLuaInitializer() which makes it easier to make an interface in
  Lua for complex Java code. Use registerJavaClass() for simple Java objects.
– Added pushStyle/popStyle to make it easier to temporarily change the style
  within a line of text, then later change it back to the earlier style.
– Support for using soft-hyphens in words to indicate potential intra-word
  hyphenation points.
– Support for setting the default text direction to right-to-left (vn.rtl)
– Basic support for bidirectional text in TextDrawable/Button.
– TextDrawable.setAnchor()/ButtonDrawable.setTextAnchor() have been replaced
  by setVerticalAlign(). Set the horizontal align with the default text style.
– Using more aggressive coordinate rounding in text display code to make the
  text appear sharper.
– Added an optional volatile parameter to screenshot/screen2image functions
  which, when true, creates a screenshot which stores its pixels only on the
  GPU. This improves performance, but the pixels may be lost at any time.
– View CG menu option now prints a warning when it does nothing and uses a
  fade-in/fade-out effect.
– Changed behavior of ‘stretch’ for GridLayout, will now only increase sizes.
  Added a ‘shrink’ property to allow shrinking of components.
– Setting the text anchor to 0 lets the text alignment depend on the default
  directionality of the containing line of text.
– Various small improvements to the manual.
– Choice buttons accidentally had their Z changed from -2000 to 0.
– Screenshots were taken in the wrong layer for layers containing sublayers.
– Buttons still appeared clickable in view CG mode.
– Notifications alignment was accidentally changed in v3.0
– Right-aligned text now behaves the same on the Android port.
– Incorrect decoding of Unicode code points outside the BMP in Lua.
– Lua functions didn’t show up in stack traces for Java exceptions for certain
  types of errors.
– colorTex() didn’t properly convert the given ARGB color to premultiplied form
– Clip rect calculation in BaseRenderer uses the rounded-to-int version.
  of the parent’s clip rect as base. Repeated rounding errors could stack up.
– Errorneously included some unarchived .java files in the engine distribution.
– Removed trailing ‘&’ in Linux launcher script, it causes the program not to
  run properly when using double-click -> run in terminal in some cases.
– Engine/project fields in Build.jar where clipped on Mac OS X.
– On some platforms, default textfield foreground is white, making the
  project/engine browse fields in Build.jar very hard to read.

→ NVList project page

NVList v3.0

A major version release brings new features, but also incompatibilities. All deprecated functions and backwards-compatibility hacks have been removed. A lot of GUI-related code has been altered or moved and the way layers work has been significantly changed. Layer are now also drawables which means layers can now contain other layers. Because of these changes, visual novels written for an earlier version of NVList won’t work by default. You can force an older VN to work by changing engineTargetVersion in game.ini to 3.0 or later, but take care to test thoroughly before releasing.

As you may know, NVList requires Java to run. The current version opens a browser window to java.com when no compatible Java install is found. NVList 3.0 makes it easier to distribute Java together with the VN, requiring no separate Java install. Just check the include-private-jre box in the build preferences and a 32-bit Windows Java runtime will be packaged with the VN.

The manual has also been significantly restructured and I’ve added advanced scripting chapters covering user interfaces and animations.

There have also been some improvements to the Android port. It now displays total play time in the preferences screen and there’s a new setting to change the minimum number of lines the text box should show at one time. The "initializing" screen has been given a makeover and now features a changeable splash screen image (build-res/splash-android.png).

2012/11/13 — 3.0 (r69)

– Added better support for adding an embedded Java runtime (JRE). A 32-bit
  Windows JRE is included with NVList, enable the include-embedded-jre
  preference to add it to distributions.
– Rewrote how layers function. Layers now implement IDrawable and can be
  nested. All default layers are now created within a single root layer and
  Image.getLayers() was removed.
– Drawables can now be moved to another Layer than the one they’re created in.
– Added a default ‘overlay’ layer which displays above any other default layer.
– Added setGlobal/getGlobal/incrGlobal/clearGlobals functions to ease working
  with the globals Java object from Lua.
– Implemented early culling in the rendering code using bounding box
  approximations for drawables (improves performance when there are many
  off-screen drawables).
– CD distributions now also include a .exe version of the installer.
– Installers included with CD distributions now extract directly from the
  no-installer .zip instead of requiring data be duplicated inside the installer
– Moved a number of layout/GUI related code from Lua to Java for increased
  performance. Moved System.(createSaveScreen/createLoadScreen/createChoice)
  to GUI.XXX  
– Removed TextButton Lua implementation, integrated functionality into IButton.
– Default choice screen now creates scroll bars when there are too many options
– Implemented a panel component for grouping and positioning images with a
  layout. The panel can also be given images to use for its background and
– Added a scrollable viewport component.
– Added a FlowLayout which positions items in rows aligned to a particular
– Android version now uses an optional splash screen image during startup.
– Added Anim.fromFunction() which turns a Lua function into an Animator.
– Added getNextFreeSaveSlot() function which returns the index of an unused
  save slot.

– Button rollover is now limited to their parent layer’s clipping rect unless
  clipEnabled is false.
– ParallelAnimator looping now waits for each sub-animation to finish instead
  of looping each sub-animation separately and as fast as possible.
– NVL mode on Android now tries to fill at least half the screen before auto
  clearing the screen instead of always after each paragraph.
– Fixed a bug in blend quad rendering for the desktop version of NVList, didn’t
  properly restore the previously active texture.
– Fixed a rare array bounds exception in LuaThreadGroup.
– Lua stacktraces got destroyed when tail-calling a Java function which calls
  a yielding Lua function.
– Lua evaluator in the debug tab now also accepts non-expression statements.
– CodeMirror syntax highlighter exited ‘code’ mode when encountering a ‘]’
– Lua tailcall optimization was broken for java functions resulting in a yield
  (‘dofile’ being the obvious one fitting that description).

→ NVList project page

NVList v2.9

Relatively minor changes this time, but one change with a large impact. I’ve made it easier to replace the built-in special screens (choice, save, load, textLog) with versions of your own. This was already possible, but required overriding the default implementations of some built-in functions and writing your own screens from scratch. There’s a new example script gui/06-custom-screens.lvn showing off how to replace the default choice screen with a slightly fancier version.

2012/10/19 — 2.9 (r35)

– Added screens.lua to default res folder in order to make it more
  straightforward to edit the save/load/choice/textlog screens. See also the
  custom special screens demo.
– Upgraded JOGL library to version 2.0-rc10
– Added optional size argument to ImageFx.composite to explicitly set the size
  of the output texture.
– ImageFx.applyColorMatrix now accepts 4×5 matrices instead of just 4×4.
– More helpful error message when trying to run NVList on a non-existent or
  otherwise unreadable folder.
– Added 1024×600 by default when running the resource optimizer for Android.

– AndroidProjectCompiler didn’t set XAPK size property correctly.
– Fixed SequentialAnimator to call update on the same frame as start like all
  other Animators.
– [Android] Use of embedded fonts was broken.
– Fixed a bug in GridLayout when using more than one row and the cells need to
  be centered horizontally.

→ NVList project page

NVList v2.8

The Android port is finally here. It’s now possible to create an Android version of your NVList VN with a flick of the wrist and a press of a button. The new Android Build Config sub-screen guides you through the process, warning about missing/incorrect properties. Full documentation can be found here.

One thing to keep in mind when creating an Android port is that on Android, the engine controls the position and size of the main textbox. This is to allow your readers greater control over text size, etc. Since the system overrides some of your settings, it’s usually best to disable textbox customization on Android. A global boolean android is set when running on Android, so to use a custom textbox (but not on Android):

if not android then
    customTextBox(TextMode.ADV, {
        textBounds={190, 528+16, 900, 128},
        textBackgroundExtra={x=128, y=528},


2012/08/26 — 2.8 (r34) enhancements: – Added the Android port for NVList, see chapter 4.4 in the manual. – Added a warning message when running on OpenGL version < 1.3 - Renamed resource optimizer result from "_optimized" to "res-optimized". Optimized resources are now automatically used by Build.jar, with detection if they're outdated and a suggestion to run the optimizer when useful. - Resource optimizer now defaults to the "size" preset and adds 1280x720, 1024x576 target resolutions. - Added a utility function for creating filmstrip animations (Anim.createFilmstrip). See image/animation tutorial for example code. bugfixes: - Fixed an error on OpenGL 1.1 cards: GL_CLAMP_TO_EDGE doesn't exist. - Error in videoclip conversion to mp4 for some versions of FFmpeg (unknown encoder libfaac). - Project creation dialog's progress bar now actually works... - Resource optimizer didn't pad with edge pixels properly for subimages.[/changelog]

→ NVList project page

NVList v2.7

The biggest new feature is the inclusion of a registerSpeaker function that offers an alternative way of changing the currently active speaker:

@function sayWi() return say("William") end

#Using the new registerSpeaker function
@registerSpeaker("wi", "William")
$wi Hello
$wi World

The text log screen has gotten a visual upgrade (there’s a proper scroll bar now), and it’s now possible to use the mouse wheel to scroll up/down. The save screen now remembers the last-used page and the most recent save is marked with a "new" indicator.

The most significant GUI update is for the image gallery. It now supports image sequences, for example if you have 5 variants of the same CG they can be grouped together. Just put the images together in a sub folder and they’re automatically grouped.

Blur shader with configurable strength

A new tutorial was added demonstrating the blend/wipe/shutter/blur/distort shaders. The blur shader couldn’t be instantiated from Lua before, but from 2.7 onwards it can. Completely new is the distort shader which can be used to create wave/twirl/ripple effects.

It’s now also possible to merge several image files together to create a new texture. This can be useful for creating layered sprites by merging a base sprite, clothing and expression at runtime. Merging sprites is an expensive operation that can take a few hundred milliseconds for larger sprites on slow hardware — having the sprites as pre-merged images usually offers better performance. Sometimes pre-merging is impractical/impossible, that’s where this new ImageFx.composite() function can come in handy.

2012/08/11 — 2.7 (r32)

– The $syntax for inserting variables into text now supports local variables.
– Added a sayLine function that automatically resets the speaker at the end of
  the paragraph.
– Added a registerSpeaker function that registers a stringifier function and
  companion global say_XXX function to change the current speaker. See
  documentation (ch 3.1) and text/basics tutorial for more details. 
– Added a new chunk to the save format, containing a savepoint-like IStorage
  object. This object can contain user-supplied metadata for the save file.
– The most recently saved slot is now marked as ‘new’ on the save/load screen.
– Last used page on the save/load screen is now persisted.
– New DistortGS shader that renders images using a distorted uniform grid.
– BlurGS is now instantiable from within Lua code.
– Added a tutorial demonstrating the use of IGeometryShader/IPixelShader
– Renamed systemVars to sharedGlobals. The old systemVar functions are still
  available for VNs targeting NVList version 2.6 or earlier.
– Added support for using the mouse wheel to scroll the text log.
– Implemented auto cursor scaling based on the default text style’s font size.
– Added ImageFx.crop()/ImageFx.composite() functions to combine sprites at
  runtime. This allows you to use 
– Added support for image sequences (for example, event CG variants) to the
  image gallery, see script/gui/gallery.lua for more information.
– Name tags in NVL mode were accidentally being styled with the current
  speaker’s text style as well. Fixed to only use the name style.
– Fixed unintended brightness decrease when using BlendGS in combination with
  drawables with alpha less than one.
– Build.jar was supposed to update prefs.ini, but instead wrote prefs.ini.txt
– Fixed an off-by-one error for the cropping in the blur function.    
– Auto read mode broke when a line doesn’t fit on the screen and a panic line
  wrap is necessary.
– Image optimizer now pads resized subimages with a scaled version of its
  former neighbor pixels instead of always with transparent pixels, thereby
  maintaining the same edge behavior when rendered with linear interpolation.
– Create project button (and some others) in Build.jar are now disabled at
  times when using them could potentially cause problems.
– Spurious error in build-game.xml:301 when no default video folder exists.
– Under rare circumstances, a repaint would not be issued after resizing,
  leading to image corruption.
– Fixed a bug in BaseImageTween that would replace the imageAlignY with
  imageAlignX if no specific anchor/imageAlignXY set.

→ NVList project page

Android NVList Update

I’ve been working on the Android port of NVList, mostly on getting it to the point where it’s usable by humans and you don’t need to be some kind of masochistic time wizard to get it running.

I’m adding a subscreen to Build.jar for configuring Android-related settings, and generating/updating an Android project based on those settings. The generated project will have the app icon, name, etc. hardcoded, but not any of the scripts or other resources. You can choose to either include the resources as assets directly into the APK, or as a separate download (preferable for VNs over 25-30MB).

There’s still a bunch of documentation to write, and a considerable amount of fiddling. I hope to have Android support ready for NVList v2.8 (currently at v2.6). The code of the Android version of the engine itself is ready; I made a quick Android port of Cottage on the Moor to test/demo the code:

Cottage on the Moor (Android version)