Sunday, April 29, 2018

FMod - Fix update server connection

The shared hosting provider that serves as the Abiathar update server recently removed support for TLS 1.0, a good security move. However, the .NET Framework by default only supports TLS 1.0 for secure connections, which is weird. That broke Abiathar's ability to check for and download updates. So today I had to manually enable TLS 1.1 and TLS 1.2. Since Abiathar targets .NET 4.0, the enumeration constants for those don't exist yet, so I had to hardcode the numeric values:

Net.ServicePointManager.SecurityProtocol = Net.SecurityProtocolType.Tls Or 768 Or 3072

I likewise adjusted the update client and embedded the new version into Abiathar.

Saturday, April 28, 2018

FMod - Allow keeping the selected tile crosshairs around

One Abiathar user said that it would be nice to keep the selected tile crosshairs showing even when the Palette Copier is the active tileset tool. I originally hid the crosshairs when using that tool because they could get in the way of seeing the block you want to copy. When using the Palette Copier as the primary tileset tool (for Keen Next emulation), though, that leads to virtually never seeing the crosshairs, which is disorienting. So today I implemented a simple new configuration option that causes the selected tile crosshairs plane to remain visible even if the current tool wants it hidden. I also put a checkbox for it on the Tools tab of the Settings dialog.

Friday, April 27, 2018

When Gradle says "program type already present"

Today I helped someone whose Android project was failing to build with a "program type already present" error about the dependencies. I found a Stack Overflow answer that seems to say that the problem is caused by two dependencies needing different versions of the same sub-dependency. To figure out which dependencies are conflicting, you can look at the output of running gradlew app:dependencies (e.g. in the Android Studio terminal). It might be possible to exclude the sub-dependency from the dependency requesting the older version using the Gradle exclude module directive in that SO answer.

Wednesday, April 25, 2018

Android UI changes might not appear if a lot of work occupies the main thread

Today I worked with an Android activity that is supposed to do some initialization work and display the current status in a TextView. I found that, even though the setText call was before all the work, and though the progress spinner continued to spin, the new text didn't appear until after the work was done. Apparently this happens when the UI thread is tied up (due to the work being done); Android doesn't get a chance to redraw the label. If the UI thread is busy, other strange things can happen like visual stalling/blankness when unlocking the phone. Using an AsyncTask should keep things smooth for the user.

Tuesday, April 24, 2018

Apparently arbitrary objects can't be put in Intents as extras

Today I wanted to call a different Android Activity and supply an instance of a new class to it. I looked at the methods on the Bundle returned by the new Intent's getExtras method, but found nothing that puts an arbitrary object. To my shock, there is no way to store just any object, apparently because Intents can cross process boundaries, so an object alive in one app can't just be brought over to another. You have to either serialize/parcel the object or stash it somewhere the other Activity can get it.

Monday, April 23, 2018

When Android Studio complains about lack of constraints

Recently I tried to put together a UI layout for an Android application. I found that all the UI elements would fly to the upper left at runtime even though they were placed as intended in the designer. There was a warning exclamation mark next to them in the component tree noting that they had no constraints. Some Googling turned up a mention of a wand icon in the designer toolbar that automatically creates constraints. Indeed it does, and that made the elements stay in their place at runtime.

I still found the ConstraintLayout unwieldy, though, so I ended up changing the root layout to a LinearLayout by right-clicking it in the component tree and using the "convert view" command.

Sunday, April 22, 2018

setTitle does nothing if the Activity has a Toolbar

Today I tried to programmatically change the title of an Android Activity. The setTitle method is supposed to do that, but I saw no effect from using it. After much Googling, I found that if the activity has a Toolbar, the title has to be changed on the toolbar. Calling the toolbar object's setTitle method worked as intended.

Saturday, April 21, 2018

When Android Studio says "please select Android SDK" when trying to run

Recently I helped some people (including myself!) who couldn't run apps from Android Studio because it instead produced the Edit Configuration dialog with an error at the bottom reading "please select Android SDK." This happens when the project is targeting an Android version that the current Android Studio instance doesn't have installed. It can be corrected by using Tools | SDK Manager to install the appropriate SDK version. The change might need a rebuild or an Android Studio restart to take effect.

Wednesday, April 18, 2018

IGV's translation row gets frameshifted when scrolling

The Integrated Genomics Viewer (IGV) can show the translation of the DNA if the "show translation" option is checked in the context menu of the sequence band at the bottom. It shows three different possible translations, one for each reading frame. I have noticed, though, that which band is which reading frame can get jumbled when moving the viewport, especially when clicking the top navigation band to jump. Therefore, figuring out which band is the helpful one has to be redone after scrolling around. In most cases, there should be at least one nearby stop codon in the frame of the wrong bands, making it clear that they're probably not the ones to look at.

Monday, April 16, 2018

FMod - Clipboard API

The ability to have multiple blocks of tiles on hand would be made much easier to implement if Abiathar had a more central notion of the clipboard. The Abiathar architecture may be a bit unusual: a lot of what looks integral is actually from an (automatically loaded) extension called the Abiathar Standard Toolkit. There's not much special about the standard toolkit relative to other extensions that anyone can write, but if it wasn't loaded Abiathar wouldn't be very useful - this extension provides all the normal tools and gives the "hey, I know what that is" to the core project file section when the "claim your configuration section" event bus comes around.

Since only tools need to know about the clipboard, the idea of the clipboard only exists in the standard toolkit extension; Abiathar proper doesn't know anything about it. This makes it difficult for third-party extensions to work with the clipboard, in addition to making the multiple-clipboard feature request challenging to implement. So today I moved the clipboard into the Abiathar core and added an API for it. Whenever anything sets the clipboard, an event bus is dispatched. The standard toolkit extension responds to the notification by producing its old alert to the tools it controls.

Overall the change was straightforward. There was one snag involving the Essential Manipulator. When starting, it would initialize the clipboard, which generated a notification, which it caught and used to update the paste preview plane, and then it crashed because it hadn't finished setting up that plane. I think I've got everything worked out, since this is the only tool that both changes the clipboard and listens for changes.

While I was expanding the API, I added status properties to indicate whether there is an open project and whether there is a current level. Previously extensions had to do something gnarly like checking an internal variable belonging to the Abiathar core for null.

Sunday, April 15, 2018

FMod - Zoomable simultaneous tileset

Today I decided to finally implement zoom for Abiathar's simultaneous tileset. I started by defining a new, smaller set of zoom levels, since any zoom factor bigger than 2x would make the tileset cover virtually the entire screen, which defeats the purpose of it being a simultaneous tileset. Then I did some math to make the appropriate UI elements get resized and relocated correctly when the tileset zoom level changes. Finally, I had to go through and replace all the assumptions of 16 pixels per tile in the simultaneous tileset with uses of the new tileset-specific zoom level. This was probably the trickiest part, since the 16 assumption had made its way around in the four years of Abiathar's existence. Fortunately I think I've got it all - a search for "16" in the main form's code turns up only things that legitimately need to be hardcoded as 16.

Both the level and simultaneous tileset zoomed to 32 pixels per tile
The zoom slider had to go - it wouldn't make sense to have a single zoom slider and two separate zoom levels - but I kept the zoom status label. In simultaneous tileset mode, it displays the two zoom levels as e.g. "100%, 200%" for the level being at 1x and the tileset being at 2x. Possibly confusingly, the Zoom In and Zoom Out menu items only control the main zoom; the only way to change the zoom level of the simultaneous tileset is to mouse over it and use the plus or minus keys. I may need to reconsider that based on user feedback.

Friday, April 13, 2018

Sometimes Android Studio's Instant Run feature gets stuck

Today I helped one user who was seeing their Android Studio builds fail with a spew of exceptions mentioning InstantRunTransform in a few of the stack traces. This seems to belong to Android Studio's Instant Run feature, which allows deploying changes to the device without completely recompiling everything. This feature, though very nice, sometimes wedges itself into bad states. To disable it and force a full rebuild, you can disable it in the Build, Execution, Deployment | Instant Run settings section.

Wednesday, April 11, 2018

Showing a progress indicator in PowerShell

Some PowerShell cmdlets, like Update-Help, show a progress/status indicator near the top of the console while they're doing their work. Any PowerShell script can do that using the Write-Progress cmdlet. For example:

Write-Progress 'Doing a thing' -Status 'Initializing'

Later subsections of the same overarching operation use the same activity (first parameter) but different status:

Write-Progress 'Doing a thing' -Status 'Connecting'

The -PercentComplete switch produces a progress bar:

Write-Progress 'Doing a thing' -Status 'Doing' -PercentComplete 30

The -Completed switch indicates that the activity is finished, removing the progress tracker:

Write-Progress 'Doing a thing' -Completed

Tuesday, April 10, 2018

FMod - Possible improvements coming

It's been a while since I've made any significant feature additions to Abiathar. I recently chatted with a prolific modder who had some requests for enhancements. He suggested being able to zoom the simultaneous tileset, a request which I've now heard from multiple people, so that's probably a good thing to implement. I haven't done it yet because it isn't really compatible with having a single zoom slider, but I'm willing to remove the zoom slider in favor of a more useful feature. I might also consider having a second independent slider to control the tileset (if that wouldn't make the status bar too crowded).

Another request was the ability to remember multiple stamps (copied blocks). Abiathar already has a place to stash a few tiles of the user's choosing, but no way to persist arrangements of tiles other than re-copying when necessary. I've been thinking about doing some refactoring to expose the clipboard through the API, and expanding the copy system would be a great time to do that.

I have a lot of real-life work to do in the coming weeks, but if I get some free time I'll look into these additions.

Sunday, April 8, 2018

1000 Genomes Phase 1 data has some SNPs that Phase 3 doesn't

Yesterday I noticed that the 1000 Genomes Phase 3 data set is missing some common SNPs. Today I checked whether the SNP I was looking for was in the Phase 1 data set, and it is. The Phase 1 VCF lists it as the same high quality as the rest of the SNPs that I could find in the Phase 3 VCF, so I'm not sure why it was dropped. It's almost certainly real - I've been working with a different set of sequences with many reads that contain the mutation. The proportion of non-co-occurrence from the Phase 1 VCF is an order of magnitude higher than that from the Phase 3 VCF, whether or not the lost-and-found SNP is included in the Phase 1 calculation. This suggests that there is a bit more error in the Phase 1 reads than Phase 3.

1000 Genomes VCF files might not have all SNPs

I've been trying to determine the co-occurrence of a handful of SNPs using a 1000 Genomes VCF file, but one of the SNPs seems to be absent. Its rsID doesn't appear in the VCF, nor can I find it by position. It's a pretty common SNP if I'm reading its NCBI page right; I expect that it should co-occur with the others that I can find in the VCF.

Per the IGSR site, a couple million variations were culled in the production of the Phase 3 data set (that I'm using) for a handful of reasons including quality control. It's possible that this SNP didn't quite make the cut due to uncertainty.

Friday, April 6, 2018

When Android Studio can't resolve certain symbols or imports

Today I needed to start an Android Studio project from an existing template. When opening it, though, I saw that a handful of the imports had failed with "cannot resolve symbol." This Stack Overflow question has a few different solutions, none of which (and no combinations or repeats of which) worked for me. I eventually found - in a different Stack Overflow post - the idea of deleting/moving the .idea folder. This actually worked! The first time Android Studio opened the project after the move, it threw a bunch of errors, but then it managed to regenerate everything it needed. Since run configurations are stored in .idea\runConfigurations, I made sure to copy that folder over from the old .idea to the regenerated one. After that, things appear to be working as intended.

Thursday, April 5, 2018

The read-only bit doesn't make folders read-only

In Windows, folders can be set read-only, but this doesn't do anything to stop them from being changed. For directories, the read-only bit is part of a signal that the folder might want special handling by the shell. When Explorer sees a directory marked read-only and system, it checks for a desktop.ini file inside that might specify special appearance or behavior for the folder. (This is why the Fonts folder is so non-directory-like, for instance.)

If you need to protect a folder from changes, adjust the access control list on the Security tab of the Properties window.

Monday, April 2, 2018

Multidimensional arrays in PowerShell

There isn't convenient syntax in PowerShell for creating a multidimensional array, but the .NET style works just fine. For example, this creates a 5x3 two-dimensional array of integers:

$arr = [array]::CreateInstance([int], 5, 3)

The syntax for using these arrays is exactly what you would expect. This sets the element at both dimensions' first index:

$arr[0, 0] = 1

Interestingly, ranges (or collections in general) are not acceptable indexes for multidimensional arrays like they are for one-dimensional arrays.

Sunday, April 1, 2018

Keen Modding Live - Close confirmation fix

Abiathar Live Studio has to automate a lot of project opening and closing when setting up local copies of live levels. This works great if it's managing all projects involved in the shuffle, but I had not previously tested it when non-live projects are open. If a non-live project with unsaved changes is still up when a newly created or cloned live level is opened, the "save changes before closing?" dialog will open as normal, but trying to cancel will cause Abiathar to crash.

This happens because the Abiathar Live Studio extension doesn't check whether the vanilla project-opening method actually opened the project it wanted. So I added a bit of post-open validation and made the appropriate functions bail out if the open was canceled.