RezEditor Alpha Log

Nice find. I already have the reader-of-.rez-files written, and I don't think it will too hard to write the saving routines. GUI first, though.
Right now I'm trying to figure out why I'm not reading all the resources in the file - 93 of 115 in Nova.rez...
Edit: fixed it - forgot a ++ when the new element was being added to the end - only elements that were added before the end were added correctly. Wow, the Nova.rez resources are very out-of-order.
Edit2: And it's 114 instead of 115 because of the resource map.
Also, now I will add something to warn "just in case" the number of groups is not 1.

Edit3: Community Help:
First, I could use some icons - I found some here, but they're not the most satisfactory:
Group: new, save, delete (don't click this)
Type: new, delete, copy/move range, cut, copy, paste,
Resource: save, revert to saved, save-and-close, close-without-saving.
Special: map, table, etc. ...
Second, I could use some template files - I haven't finalized the form, or written the code that makes a GUI out of it, but it would just be a text file with keywords. This would probably not be as helpful for the more complex resources. I am aware of, but do not intend to use, the TMPL resource because I have a different plan for doing it. If you're interested, post and I'll give you something to do. Generally the order of the resources is the same as in the Nova Bible, but sometimes there are weird things, such as skipping bytes, and you have to figure out the size - most are shorts.
Edit5: also, could someone on a Mac check how sensitive ResStore and Mash are to file headers? Because in EVNEW Text format there are separate entries for "Format" and "Created by" but is is not clear to what the ConText and Mish headers refer.

Edit4: just found a really strange bug with an object being neither null nor instantiated that led to indefinite hanging. I am filing this in the Java bug-tracking system.

This post has been edited by Nonconventionally Creative : 18 August 2008 - 03:20 PM

Used smart data structures.
Finished implementing and debugging save method.
RezEditor can now open a file, show a list of Resources with the selected ResourceTypes, and then open an editor for whatever is selected. Currently I only have a skeletal implementation of a hexadecimal editor, but it can edit the data as well as change its length. The mechanism for adding new editors is already established.
Now I just have to do a bunch of GUI work. 😞
Discovered that EVNEW doesn't compress rlë?s - oxymoronic for it, instant selling point for mine.

Attached File(s)

This post has been edited by Nonconventionally Creative : 23 August 2008 - 08:17 PM

OK, I am not getting this rlë stuff. Why are the skipped pixels all at the beginning? And Why, within the last 10 lines of the first frame, does my sample (the Rebel IDA Frigate) start trying to print more pixels than its length:

Starting line 91
Skipping 88 pixels (from 0, 91 to 88, 91)
Drawing 5 pixels with their own colors.(from 88, 91 to 93, 91)
	Drawing pixel 0 at 88, 91 with color 484028
	Drawing pixel 1 at 89, 91 with color 484028
	Drawing pixel 2 at 90, 91 with color 282818
	Drawing pixel 3 at 91, 91 with color 282818
	Drawing pixel 4 at 92, 91 with color 080808
Correcting for non-multiple of 4.
Skipping 4 pixels (from 93, 91 to 97, 91)
Drawing 5 pixels with their own colors.(from 97, 91 to 102, 91)
	Drawing pixel 0 at 97, 91 with color 100808
	Drawing pixel 1 at 98, 91 with color 202010
	Drawing pixel 2 at 99, 91 with color 303020
	Drawing pixel 3 at 100, 91 with color 282818
	Drawing pixel 4 at 101, 91 with color 101008
Correcting for non-multiple of 4.

Edited because I couldn't use formatting in code tags 😞 - also, the system I have for the "from-to" includes what would be the next pixel, which should be 100.
Also, there was some line earlier that only had 99 pixels.
Edit: it doesn't make sense, but seems to work if I halve the number of pixels to skip at the beginning - and I did check the image and line 91 is supposed to have 2 skipped pixels in the middle, between two drawn 5s, with 44 skipped at the beginning.

Edit: Well, it looks like I got the decoder working. Now why are my colors messed up?Attached File earlyRle.png (3.92K)
Number of downloads: 25
Edit: It seems that its skipping every other frame... oh, wow, I forgot to read the end-of-frame mark. Fix is easy.
On the down side, I checked the result manually and the hex of the color is the correct result, so why is it displaying incorrectly?

Edit: fixed it: the mask was backwards.

This post has been edited by Nonconventionally Creative : 25 August 2008 - 01:24 PM

@nonconventionally-creative, on Aug 25 2008, 11:32 AM, said in RezEditor Alpha Log:

it doesn't make sense, but seems to work if I halve the number of pixels to skip at the beginning

A skip-pixels token is followed by the number of bytes to skip, not the number of pixels; in 16-bit colour, each pixel is two bytes (2 x 18 bits).

@nonconventionally-creative, on Aug 25 2008, 11:32 AM, said in RezEditor Alpha Log:

On the down side, I checked the result manually and the hex of the color is the correct result, so why is it displaying incorrectly?

If you're loading the colour correctly but getting the wrong display, then it sounds like there's something wrong with how you're passing the value on to your display module.

Quote

03: The remaining 24 bits tell you how many pixels to skip.

Bad documentation.

@david-arthur, on Aug 25 2008, 11:26 AM, said in RezEditor Alpha Log:

A skip-pixels token is followed by the number of bytes to skip, not the number of pixels; in 16-bit colour, each pixel is two bytes (2 x 8 bits).

If you're loading the colour correctly but getting the wrong display, then it sounds like there's something wrong with how you're passing the value on to your display module.

It was getting interference from the alpha channel. I forgot to &0xff when I transferred from the bytes I was using. (when a negative byte is cast to an int, it fills in all the new bits with 1s)
Moral of the story: use an int.

This post has been edited by Nonconventionally Creative : 25 August 2008 - 01:48 PM

What is done:
load and save a file (not yet in GUI - only can load a file as an argument when starting the program. The good news is that all that socket stuff mostly works, so you can open more files, although it does something funny if you give no or a bad argument; also, could be optimized for load many, small resources - but that is a User Setting)
User Settings - Switched over to the Java Prefs API, which means I don't have many yet, or a not programmatic way of accessing them. TODO write an import/export XML file chooser.
Hex Editor - not the most fully featured hex editor, but it works. TODO add a copy/paste hex feature? How does XVI32 do the standard one - does the clipboard really allow s?
rleD Viewer with animation. TODO extend to rle8, generally clean it up, and add export file stuff. Then, write and encoder and add import file stuff.
What I've been doing for the longer-term:
EDIT: no longer up-to-date. I've left it here for formatting purposes. If interested, post a reply.

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.sourceforge.rezeditor;

/**
 * This file contains offsets for fields of the various Resources.
 * If any data is not a short (2 bytes), the variable should indicate what it is
 * with an extension: _INT, or _S### for string of given length.
 * I decide not to label colors with _INT or Contribute/Require with _LONG.<br/>
 * If there is unused data in a resources, it is referred to as BLANK_LEN where
 * LEN is the length unused. If there is more than one unused section, use
 * BLANK#_LEN, where # starts at 0 and increments. Do so even if the blank fields
 * are of different sizes so the names would not conflict.<br/>
 * Finally, the expected size of the resource, if constant, is given as EOR.
 * If it is not constant, that resourceType probably shouldn't be here - there
 * are exceptions, though - some data at the beginning may be accessible.
 * I could make a thing to interpret negative numbers from the end.<p/>
 * These constants will be called as the arguments to methods in {@link ResourceData}
 * that take an index for an argument, like {@link ResourceData#readShort(int)}.
 * @author Nonconventionally Creative
 */
public class ResourceDataOffsets {
    private ResourceDataOffsets() {
    }
    public static class bööm {
        private bööm() {
        }
        public static final int FRAME_ADV = 0x0;
        public static final int SND_INDEX = 0x2;
        public static final int GRAPHICS_INDEX = 0x4;
        public static final int EOR = 0x6;
    }
    public static class chär {
        private chär() {
        }
        public static final int CASH_INT = 0x0;
        public static final int SHIP_TYPE = 0x4;
        public static final int SYST1 = 0x6;
        public static final int SYST2 = 0x8;
        public static final int SYST3 = 0xA;
        public static final int SYST4 = 0xC;
        public static final int GOVT1 = 0xE;
        public static final int GOVT2 = 0x10;
        public static final int GOVT3 = 0x12;
        public static final int GOVT4 = 0x14;
        public static final int STATUS1 = 0x16;
        public static final int STATUS2 = 0x18;
        public static final int STATUS3 = 0x1A;
        public static final int STATUS4 = 0x1C;
        public static final int COMBAT_RATING = 0x1E;
        public static final int INTRO_PICT_1 = 0x20;
        public static final int INTRO_PICT_2 = 0x22;
        public static final int INTRO_PICT_3 = 0x24;
        public static final int INTRO_PICT_4 = 0x26;
        public static final int PICT_DELAY_1 = 0x28;
        public static final int PICT_DELAY_2 = 0x2A;
        public static final int PICT_DELAY_3 = 0x2C;
        public static final int PICT_DELAY_4 = 0x2E;
        public static final int INTRO_TEXT = 0x30;
        public static final int ON_START_S256 = 0x32;
        public static final int FLAG = 0x132;
        public static final int START_DAY = 0x134;
        public static final int START_MONTH = 0x136;
        public static final int START_YEAR = 0x138;
        public static final int DATE_PREFIX = 0x13A;
        public static final int DATE_SUFFIX = 0x14A;
        public static final int BLANK_16 = 0x15A;
        public static final int EOR = 0x16A;
    }
    @Deprecated
    public static class cicn {
        private cicn() {
        }
    }
    public static class cölr {
        private cölr() {
        }
    }
    public static class crön {
        private crön() {
        }
    }
    public static class dësc {
        private dësc() {
        }
    }
    public static class DITL {
        private DITL() {
        }
    }
    public static class DLOG {
        private DLOG() {
        }
    }
    public static class düde {
        private düde() {
        }
        public static final int AI_TYPE = 0x0;
        public static final int GOVT = 0x2;
        public static final int BOOTY_FLAG = 0x4;
        public static final int INFO_TYPES = 0x6;
        public static final int SHIP1 = 0x8;
        public static final int SHIP2 = 0xA;
        public static final int SHIP3 = 0xC;
        public static final int SHIP4 = 0xE;
        public static final int SHIP5 = 0x10;
        public static final int SHIP6 = 0x12;
        public static final int SHIP7 = 0x14;
        public static final int SHIP8 = 0x16;
        public static final int SHIP9 = 0x18;
        public static final int SHIP10 = 0x1A;
        public static final int SHIP11 = 0x1C;
        public static final int SHIP12 = 0x1E;
        public static final int SHIP13 = 0x20;
        public static final int SHIP14 = 0x22;
        public static final int SHIP15 = 0x24;
        public static final int SHIP16 = 0x26;
        public static final int PROB1 = 0x28;
        public static final int PROB2 = 0x2A;
        public static final int PROB3 = 0x2C;
        public static final int PROB4 = 0x2E;
        public static final int PROB5 = 0x30;
        public static final int PROB6 = 0x32;
        public static final int PROB7 = 0x34;
        public static final int PROB8 = 0x36;
        public static final int PROB9 = 0x38;
        public static final int PROB10 = 0x3A;
        public static final int PROB11 = 0x3C;
        public static final int PROB12 = 0x3E;
        public static final int PROB13 = 0x40;
        public static final int PROB14 = 0x42;
        public static final int PROB15 = 0x44;
        public static final int PROB16 = 0x46;
        public static final int BLANK_16 = 0x48;
        public static final int EOR = 0x58;
    }
    public static class flët {
        private flët() {
        }
    }
    public static class gövt {
        private gövt() {
        }
        public static final int VOICE_TYPE = 0x0;
        public static final int FLAGS1 = 0x2;
        public static final int FLAGS2 = 0x4;
        public static final int SCAN_FINE = 0x6;
        public static final int CRIME_TOL = 0x8;
        public static final int SMUG_PEN = 0xA;
        public static final int DISAB_PEN = 0xC;
        public static final int BOARD_PEN = 0xE;
        public static final int KILL_PEN = 0x10;
        public static final int SHOOT_PEN = 0x12;
        public static final int INIT_REC = 0x14;
        public static final int MAX_ODDS = 0x16;
        public static final int CLASS1 = 0x18;
        public static final int CLASS2 = 0x1A;
        public static final int CLASS3 = 0x1C;
        public static final int CLASS4 = 0x1E;
        public static final int ALLY1 = 0x20;
        public static final int ALLY2 = 0x22;
        public static final int ALLY3 = 0x24;
        public static final int ALLY4 = 0x26;
        public static final int ENEMY1 = 0x28;
        public static final int ENEMY2 = 0x2A;
        public static final int ENEMY3 = 0x2C;
        public static final int ENEMY4 = 0x2E;
        public static final int SKILL_MULT = 0x30;
        public static final int SCAN_MASK = 0x32;
        public static final int COMM_NAME_S16 = 0x34;
        public static final int TARG_NAME_S16 = 0x44;
        public static final int REQUIRE = 0x54;
        public static final int INH_JAM1 = 0x5C;
        public static final int INH_JAM2 = 0x5E;
        public static final int INH_JAM3 = 0x60;
        public static final int INH_JAM4 = 0x62;
        public static final int MED_NAME_S64 = 0x64;
        public static final int COLOR = 0xA4;
        public static final int SHIP_COLOR = 0xA8;
        public static final int INTF = 0xAC;
        public static final int NEWS_PICT = 0xAE;
        public static final int BLANK_16 = 0xB0;
        public static final int EOR = 0xC0;
    }
    public static class ďntf {
        private ďntf() {
        }
    }
    public static class jünk {
        private jünk() {
        }
    }
    public static class mďsn {
        private mďsn() {
        }
    }
    public static class nëbu {
        private nëbu() {
        }
    }
    public static class öops {
        private öops() {
        }
    }
    public static class oütf {
        private oütf() {
        }
    }
    public static class përs {
        private përs() {
        }
    }
    @Deprecated
    public static class PICT {
        private PICT() {
        }
    }
    public static class ränk {
        private ränk() {
        }
        public static final int WEIGHT = 0x0;
        public static final int GOVT = 0x2;
        public static final int PRICE_MOD = 0x4;
        public static final int SALARY_INT = 0x6;
        public static final int SAL_CAP_INT = 0xA;
        public static final int CONTRIBUTE = 0xE;
        public static final int FLAGS = 0x16;
        public static final int SHORT_NAME_S64 = 0x18;
        public static final int CONV_NAME_S64 = 0x28;
        public static final int EOR = 0x38;
    }
    public static class rlëX {
        private rlëX() {
        }
            public static final int HEIGHT = 0x0;
            public static final int WIDTH = 0x2;
            public static final int DEPTH = 0x4;
            public static final int PALLETE_ID = 0x6;
            public static final int NUM_FRAMES = 0x8;
            public static final int BLANK_6 = 0xA;
            public static final int FRAME0_START = 0xC;
    }
    public static class röid {
        private röid() {
        }
        public static final int STRENGTH = 0x0;
        public static final int SPIN_RATE = 0x2;
        public static final int YIELD_TYPE = 0x4;
        public static final int YIELD_QUANT = 0x6;
        public static final int PARTICLE_COUNT = 0x8;
        public static final int PARTICLE_COLOR = 0xA;
        public static final int FRAGMENT_TYPE1 = 0xE;
        public static final int FRAGMENT_TYPE2 = 0x10;
        public static final int FRAGMENT_COUNT = 0x12;
        public static final int EXPLOSION_TYPE = 0x14;
        public static final int MASS = 0x16;
        public static final int BLANK_16 = 0x18;
        public static final int EOR = 0x28;
    }
    public static class shän {
        private shän() {
        }
    }
    public static class shďp {
        private shďp() {
        }
        //The following were copied from the sample structs in Mehrunes' spec
        public static final int HOLDS = 0x0;
        public static final int SHIELDS = 0x2;
        public static final int ACCEL = 0x4;
        public static final int SPEED = 0x6;
        public static final int TURN = 0x8;
        public static final int FUEL = 0xA;
        public static final int FREE_MASS = 0xC;
        public static final int ARMOR = 0xE;
        public static final int SHIELD_RECH = 0x10;
        public static final int WEAP1 = 0x12;
        public static final int WEAP2 = 0x14;
        public static final int WEAP3 = 0x16;
        public static final int WEAP4 = 0x18;
        public static final int WEAP1_COUNT = 0x1A;
        public static final int WEAP2_COUNT = 0x1C;
        public static final int WEAP3_COUNT = 0x1E;
        public static final int WEAP4_COUNT = 0x20;
        public static final int WEAP1_AMMO = 0x22;
        public static final int WEAP2_AMMO = 0x24;
        public static final int WEAP3_AMMO = 0x26;
        public static final int WEAP4_AMMO = 0x28;
        public static final int MAX_GUN = 0x2A;
        public static final int MAX_TUR = 0x2C;
        public static final int TECH_LEVEL = 0x2E;
        public static final int COST_INT = 0x30;
        public static final int DEATH_DELAY = 0x34;
        public static final int ARMOR_RECH = 0x36;
        public static final int EXPLOSION1 = 0x38;
        public static final int EXPLOSION2 = 0x3A;
        public static final int DISP_WEIGHT = 0x3C;
        public static final int MASS = 0x3E;
        public static final int LENGTH = 0x40;
        public static final int AI = 0x42;
        public static final int CREW = 0x44;
        public static final int STRENGTH = 0x46;
        public static final int GOVT = 0x48;
        public static final int FLAGS = 0x4A;
        public static final int POD_COUNT = 0x4C;
        public static final int OUTFIT1 = 0x4E;
        public static final int OUTFIT2 = 0x50;
        public static final int OUTFIT3 = 0x52;
        public static final int OUTFIT4 = 0x54;
        public static final int OUTFIT1COUNT = 0x56;
        public static final int OUTFIT2COUNT = 0x58;
        public static final int OUTFIT3COUNT = 0x5A;
        public static final int OUTFIT4COUNT = 0x5C;
        public static final int FUEL_REGEN = 0x5E;
        public static final int SKILL_VAR = 0x60;
        public static final int FLAGS2 = 0x62;
        public static final int CONTRIBUTE = 0x64;
        public static final int AVAILABILITY_S255 = 0x6C;
        public static final int APPEAR_ON_S255 = 0x16B;
        public static final int ON_BUY_S256 = 0x26A;
        public static final int DEIONIZE = 0x36A;
        public static final int IONIZE_MAX = 0x36C;
        public static final int KEY_CARRIED = 0x36E;
        public static final int OUTFIT5 = 0x370;
        public static final int OUTFIT6 = 0x372;
        public static final int OUTFIT7 = 0x374;
        public static final int OUTFIT8 = 0x376;
        public static final int OUTFIT5COUNT = 0x378;
        public static final int OUTFIT6COUNT = 0x37A;
        public static final int OUTFIT7COUNT = 0x37C;
        public static final int OUTFIT8COUNT = 0x37E;
        public static final int REQUIRE = 0x380;
        public static final int BUY_RAND = 0x388;
        public static final int HIRE_RAND = 0x38A;
        public static final int BLANK0_68 = 0x38C;
        public static final int ON_CAPTURE_S255 = 0x3D0;
        public static final int ON_RETIRE_S255 = 0x4CF;
        public static final int SHORT_NAME_S64 = 0x5CE;
        public static final int COMM_NAME_S32 = 0x60E;
        public static final int LONG_NAME_S128 = 0x62E;
        public static final int MOVIE_FILE_S32 = 0x6AE;
        public static final int WEAP5 = 0x6CE;
        public static final int WEAP6 = 0x6D0;
        public static final int WEAP7 = 0x6D2;
        public static final int WEAP8 = 0x6D4;
        public static final int WEAP5_COUNT = 0x6D6;
        public static final int WEAP6_COUNT = 0x6D8;
        public static final int WEAP7_COUNT = 0x6DA;
        public static final int WEAP8_COUNT = 0x6DC;
        public static final int WEAP5_AMMO = 0x6DE;
        public static final int WEAP6_AMMO = 0x6E0;
        public static final int WEAP7_AMMO = 0x6E2;
        public static final int WEAP8_AMMO = 0x6E4;
        public static final int SUBTITLE_S64 = 0x6E6;
        public static final int FLAGS3 = 0x726;
        public static final int UPGRADE_TO = 0x728;
        public static final int UPGRADE_COST_INT = 0x72A;
        public static final int SELL_VAL_INT = 0x72E;
        public static final int ESCORT_TYPE = 0x732;
        public static final int BLANK1_16 = 0x734;
        public static final int EOR = 0x744;
    }
    @Deprecated
    public static class snd {
        private snd() {
        }
    }
    public static class spďn {
        private spďn() {
        }
        public static final int SPRITES = 0x0;
        public static final int MASK = 0x2;
        public static final int X_SIZE = 0x4;
        public static final int Y_SIZE = 0x6;
        public static final int X_TILES = 0x8;
        public static final int Y_TILES = 0xA;
        public static final int EOR = 0xC;
    }
    public static class spöb {
        private spöb() {
        }
    }
    public static class STR {
        private STR() {
        }
    }
    @Deprecated
    public static class STR_ {
        private STR_() {
        }
    }
    public static class s˙st {
        private s˙st() {
        }
    }
    public static class wëap {
        private wëap() {
        }
    }
}

If anyone wants to help with this, that'd be nice. Don't worry about the formatting, that's just Shift-Alt-F to fix. Feel free to change the names I've used - some of them are definitely lacking. If there's anything I don't like, I can always diff from my CVS version and revert anything, so don't be afraid to tinker. Sign your name under mine with an @author tag. I'll give you a credit in Help -> About, once I write that (along with the people who've already helped in this thread, and those who helped indirectly by giving the .rez and rle specs). I'll give you a special prerelease version so you can view the hex, with offsets, at the same time as viewing the formatted version in another editor. I only know this works JRE 6. Note that Misn could be made easier by using this - that's what I did with ship and govt. It was wrong for a few at the beginning of govt - scanFine is just a short, unlike most others, and that allowed a few to bump in to fit Disabling penalty. Oh, and note and keep the custom of use ALL_CAPS_FOR_CONSTANTS_WITH_UNDERSCORES_SEPARATING_WORDS. These are not the terms that will be displayed to the user. That's all I can think of for now.

This post has been edited by Nonconventionally Creative : 24 November 2008 - 11:59 PM

Where would I get the latest source code? The sourceforge site file is labeled "oldsource" and is dated from July - is that it?

I don't have a ton of programming experience - none in Java - but I'll give it a look.

@venomousmule, on Sep 12 2008, 03:59 PM, said in RezEditor Alpha Log:

Where would I get the latest source code? The sourceforge site file is labeled "oldsource" and is dated from July - is that it?

I don't have a ton of programming experience - none in Java - but I'll give it a look.

Yay, someone replied in my topic.
The latest source is available at http://rezeditor.cvs.sf.net/, which expands to http://rezeditor.cvs....net/rezeditor/.
However, I am not currently asking for any help with programming. Once I improve the main stuff I could use GUI programmers, which if done properly requires almost no experience. I could write a quick tutorial once we get there.
My latest request is in that code-box above, and I haven't had time to work on that since I posted it. Maybe this weekend I'll stick in a save button and call it a 0.1. Of course, I really should add the rle8 parser to the rleD parser, since it currently causes an error. Also I should add frontends for creating a new resource and deleting an existing resource. At least the hex editor seems to be working, so if I did those things, it would be a fully-functional editor (just not a very useful one). Although I really should add a front-end for the prefs, even if just import/export XML.

Some things I have done since:
Import/Export resource data from a file (not very useful to end user, but useful for helping with creating editors, since the HexEditor is rather sparse)
Allow opening a type of resource with more than one type of editor without closing the program, and fixed the bug with canceling on the selection popup,

TODO: add ClassLoader.defineClass for all Files in directory, test !isInner/Anonymous, do static-init.

This post has been edited by Nonconventionally Creative : 14 September 2008 - 02:29 PM

Created GUI for saving a file with a new name.
Added ability to create a new file.
Added import/export of preferences (no GUI yet - not a priority)
TODO add resource creation and deletion, and copying.
TODO regularize the naming of a Group, presumably by only using the File, not the String.

good job Nonconventional. i'd like to help you as i would like to use your code as a reference for my project.

i'll post a few questions after i get a chance to peruse your code.

stage 1 complete. 😄
just had to download and include jlfgr-1_0.jar which can be downloaded from http://java.sun.com/.../hi/repository/

running on ubuntu 8.04 p4 3ghz 512mb.
http://nilobject.hos...s/rezeditor.jpg
forgot to open a rled for the sshot, but that worked. is the slider suppose to work? the animate, next and previous buttons worked.
rle8 errors when opening as you mentioned.
the hexeditor looked a little cramped, but was fine.

stage 2 in progress: read through/understand your code.

The slider controls the framerate for the animation. Note that it only recalculates on a new frame, so if it is set to the far left and then moved quickly to the right, it will still wait quite a while to display the next frame.
I'm not actually using that image library. I keep hoping someone will give me some icon graphics. hint hint.

Added GUI to create a new Type, with both text and bytes viewable/editable.
TODO add new Resource allowing selection of type (which necessitates investigating the effect on the GroupDisplay of new Types - the ResourceGroup backing handles it fine), and new Resource from a type that is already in the current Group, which'll be as easy as adding an menu item. Or should I just forward this to the other?

i think i understand what you are asking, but can you clarify the difference between the two again? maybe example uses?

OK, you may have noticed that when a File is open, only the Types that are present in that file show in the left Pane. To create a new one of those, you will be able to just double-click or right-click and select "New Resource" to create a new Resource. But for Types not used in the file (and by extension, Types not known at all), a different approach is needed.
One thing that will be somewhat difficult to emulate is EVNEW's method of creating a new Resource and then, if the user Cancels, automatically delete it. The problem is that it's not as if there's a method that hangs around waiting for the GUI to close, and the GUI itself doesn't know whether the Resource is "new" or not. I could try added a boolean flag on creation, clearing it on save (for in RezEditor a Resource can be saved before it is closed), if still set when close(false) is called, call group.delete(this). Hmm... What happens if byte() data is null? I'll see after I get the more-powerful but slower-to-use NewResourceDialog working, since that is the only major functionality yet lacking.
Oh, wait, I still need to modify the rle-decoder to accept 8-bit-deep compression, since it gives an error about that. Done.

This post has been edited by Nonconventionally Creative : 03 October 2008 - 10:33 PM

so something like the macos document save. if something gets edited in a resource, a 'changed' flag is set. so creating a new resource would set 'changed', changing an existing resource would set 'changed'.

on close, if 'changed' is set, then ask user 'do you want to save changes?'. if no, do nothing. if yes, find out if the resource already exists and delete it, if it doesn't, don't worry. then create a new resource and save the data from the edit window. close window.

if editor window open, on save, do the same as on close, but don't close window.

is this what you meant?

This post has been edited by Tycho : 04 October 2008 - 09:51 PM

Basically. I doubt I can use null, since that signifies the Resource still resides in the file. I could use a length indicator or another boolean - I already have two for future optimizations to the .rez saver.

optimized a lot of little things to avoid doing GUI work:

  • RezEditor now loads all the files in Nova Files and Nova.rez in ~1.3 seconds on my machine, loading metadata for all resources and all data for resources under a cutoff set to 2000 bytes.

  • Implemented VM-level caching via WeakReferences so that if a user has the cutoff set low, or if a file has a lot of resources, then repetitive calls to load an individual resource do not mandate the creation of a new RandomAccessFile (a costly process).

  • Fixed a bug that prevented the "open" option in the file menu from working.

  • GUIs are not generated for files that are loaded from Preferences (this setting is intended to keep track of references, e.g the Nova Files, while working on any other project by opening the file(s) with RezEditor)

  • removed many debugging messages, since they were working fine.

  • made a batch file to open RezEditor in a command window and pause afterward; if it is called from a command prompt from another directory it handles that correctly:

    @echo off
    

    setlocal
    set old=%cd%
    cd %~dp0
    if exist ..\dist\RezEditor.jar (
    cd ..\dist
    java -jar RezEditor.jar
    ) else echo Friendly Error Message: RezEditor appears to have been cleaned but not built. Please build it.
    pause
    cd %old%

Could someone more familiar with Unix-style terminals try to write an equivalent? The only thing I think is not self explanatory is the %~dp0, which means the drive and path of the currently executing file (I have a misc dir that I keep stuff like this in because the dist dir is deleted by the clean target)
The following works in Cygwin bash, following a symlink to or directly executing (I must admit, I like the flexibility of English) the actual shell script:

    finalshdir=$(readlink -f $0)
longshname=$(which $finalshdir)
shortshname=$(basename $finalshdir)
correctshpath=${longshname:0:${#longshname}-${#shortshname}-1}
cd "$correctshpath"
if ( -f ../dist/RezEditor.jar ); then
	cd ../dist
	java -jar RezEditor.jar
else
	echo Friendly Error Message: RezEditor appears to have been cleaned but not built. Please build it.
fi
cd "$OLDPWD"

Tycho, can you see if this works on Mac? If not, do you (or someone else) have the experience to correct it? Does this require bash, or will it work with any sh? This does require bash. Compensating with #!/bin/bash, working on Ubuntu. (Couldn't test fully on Cygwin since java didn't understand the cygdrive paths)

This post has been edited by Nonconventionally Creative : 11 October 2008 - 02:10 PM

will try when i get home. it looks ok.

edit:
tried it. failed straight away. the problem, i believe, is that linux binaries usually have more stuff in them. bsd tends to be more streamlined.

for instance:(i think) 'readlink -f $0' translates to 'readlink '$0''
in fact, i think readlink $0 will always return nothing. is the proper use something like './rezeditor.sh /path/to/directory'? if so, '/path/to/directory' is '$1'

the macos man pages are located at: http://developer.apple.com/documentation/D...rence/ManPages/
though that page is quite big, and it is usually better to manually edit the URL.
eg. http://developer.apple.com/documentation/D...readlink.1.html
http://developer.apple.com/documentation/D...n1/which.1.html
http://developer.apple.com/documentation/D...basename.1.html
etc

can you explain exactly what you want the script to do? ie. the path stuff?

edit2: here's a good discussio of getting the directory the shell script resides in:
http://forums.macosx...ead.php?t=73839

oh, and i mean double quotes where i have single quotes. i'm just lazy. eg. "$0"
reading my reply again, and it seems rather random. no sleep and no sleep make tycho something something. just read the macosxhints forum thread above. 😄

This post has been edited by Tycho : 14 October 2008 - 08:04 AM

But if the user creates a symlink, then it will return a path. The readlink gets the actual file.
I need the directory to know how to launch RezEditor.
I also need the current working directory so I can open files correctly - in short, from the command prompt the file exists relative to the current directory, but because the data is transferred by socket then RezEditor can get confused on subsequent invocations.

Oh, and some random browsing today, while getting used to KDE4 (looks like Vista! Ugh.), discovered that Java settings are stored in ~/.java/.userPrefs/net/sourceforge/rezeditor on Linux.

I haven't had much time to work on this, but with the public project thing I might write some highly specialized, low GUI features, like bit and ID refactoring. Maybe I should get that chart filled in. If anyone want to help and doesn't have any programming experience, that is something you can do. (Of course, volunteers haven't been coming forth in droves)

Edit: Oh, sorry Tycho that I didn't see your edits. Oh, and are you sure you're using bash? Because it shouldn't make any difference. The dirname command might be better than the replacement once I get it working...

Edit: try $(dirname $(readlink -f $(which $0))) for $correctshpath, and delete all four.
The readlink -f reads links until it reaches a file that is not a link, then returns that filename fully.

Edit: it appears that readlink isn't the same - maybe -L is the right option? Can you try this on some custom-created symlinks as well as normal files?

This post has been edited by Nonconventionally Creative : 04 November 2008 - 10:24 PM