FAQ  •  Register  •  Login

ISBoxer 2 - Previewing User-defined Modules

Moderator: MiRai

<<

lax

User avatar

Site Admin

Posts: 7301

Joined: Tue Nov 17, 2009 9:32 pm

Post Thu Apr 16, 2015 11:04 am

ISBoxer 2 - Previewing User-defined Modules

Before you look at this picture ... it's a work in progress, and will be different by the time you touch it. For example the "Module applies to" is currently shown as radio buttons, but they should be check boxes with multiple-select possible. And Tags wont show you Guids.

I just want you to see that, despite the fact that we'll talk XML, I created this with ISB2 not by editing XML.

Image

So here's the XML from the module in the pic, and again this is a work in progress and subject to change.
Code:
<?xml version="1.0" encoding="utf-8"?>
<UserModule xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" Guid="3ee90b7a-bfb2-4b33-999f-ff8c360a8f8a" DisplayName="A user-created ISBoxer 2 Module">
  <Notes>I made this!</Notes>
  <Description>This is a user-created ISBoxer 2 Module, to do custom things!</Description>
  <Version>1</Version>
  <ModuleTargets>Character</ModuleTargets>
  <ModuleGenres>ActionRPG</ModuleGenres>
  <Games />
  <Tags />
  <AuthorName>Lax</AuthorName>
  <AuthorEmail>lax@lavishsoft.com</AuthorEmail>
</UserModule>


So as you see in the XML, in the UserModule tag there is a Guid attribute. Guids should always be generated for you, you shouldn't make them up and probably also not edit tiny bits of them to make different ones without bothering to generate more (guilty). ISB2 does this for you automatically in most cases, and in fact when you're using ISB2 it shouldn't actually show you Guids. The reason for using Guids is so you can rename things without changing its identity; this is a huge problem in ISB1 where every last thing is based on the display name.

Modules can define Hotkeys, Procedures, Variables and Images. I have some examples! Here's examples from the GUI Module, which is NOT a User-define Module and doesn't actually exist in XML except when I tell it to spit the damn thing out into XML.

The ISBoxer 2 Puck Images and Widget, as currently implemented (XML subject to change; especially the Color fields which use separate XML tags instead of attributes, the empty/zeroed Guids shouldn't appear, etc):
Code:
  <Image Guid="67dfae1e-6aaa-46f7-86a1-b1b3981ebbe3" DisplayName="ISBoxer 2 Puck">
    <RelativeFilename>Images/ISBoxer 2 Logo - Concept 2.2 48x48.png</RelativeFilename>
    <Border>0</Border>
  </Image>
  <Image Guid="67dfae1e-6aaa-46f7-86a2-b1b3981ebbe3" DisplayName="ISBoxer 2 Puck - Hover">
    <RelativeFilename>Images/ISBoxer 2 Logo - Concept 2.2 48x48.png</RelativeFilename>
    <Border>0</Border>
    <ColorMask>
      <Red>102</Red>
      <Green>102</Green>
      <Blue>102</Blue>
      <Alpha>255</Alpha>
    </ColorMask>
  </Image>
  <Image Guid="67dfae1e-6aaa-46f7-86a3-b1b3981ebbe3" DisplayName="ISBoxer 2 Puck - Pressed">
    <RelativeFilename>Images/ISBoxer 2 Logo - Concept 2.2 48x48.png</RelativeFilename>
    <Border>0</Border>
    <ColorMask>
      <Red>102</Red>
      <Green>102</Green>
      <Blue>102</Blue>
      <Alpha>255</Alpha>
    </ColorMask>
  </Image>
  <Widget Guid="67dfae1e-6aaa-46f7-86a0-b1b3981ebbe3" DisplayName="ISBoxer 2 Puck" ClickThrough="false">
    <Rect Left="6" Top="6" Width="48" Height="48" />
    <VerticalAnchor>Top</VerticalAnchor>
    <HorizontalAnchor>Left</HorizontalAnchor>
    <ParentGuid>00000000-0000-0000-0000-000000000000</ParentGuid>
    <BackgroundMode>BackgroundColor</BackgroundMode>
    <Image>00000000-0000-0000-0000-000000000000</Image>
    <ImageHover>00000000-0000-0000-0000-000000000000</ImageHover>
    <BackgroundColor>
      <Red>0</Red>
      <Green>0</Green>
      <Blue>0</Blue>
      <Alpha>0</Alpha>
    </BackgroundColor>
    <BorderColor>
      <Red>51</Red>
      <Green>51</Green>
      <Blue>51</Blue>
      <Alpha>255</Alpha>
    </BorderColor>
    <BorderSize>0</BorderSize>
    <Children>
      <GUIRegion xsi:type="GUIButton" Guid="67dfae1e-6aaa-46f7-86a4-b1b3981ebbe3" DisplayName="Puck Button">
        <Rect Left="0" Top="0" Width="48" Height="48" />
        <VerticalAnchor>Top</VerticalAnchor>
        <HorizontalAnchor>Left</HorizontalAnchor>
        <ParentGuid>00000000-0000-0000-0000-000000000000</ParentGuid>
        <BackgroundMode>Image</BackgroundMode>
        <Image>67dfae1e-6aaa-46f7-86a1-b1b3981ebbe3</Image>
        <ImageHover>00000000-0000-0000-0000-000000000000</ImageHover>
        <ImagePressed>67dfae1e-6aaa-46f7-86a3-b1b3981ebbe3</ImagePressed>
        <BackgroundColor>
          <Red>0</Red>
          <Green>0</Green>
          <Blue>0</Blue>
          <Alpha>255</Alpha>
        </BackgroundColor>
        <BorderColor>
          <Red>51</Red>
          <Green>51</Green>
          <Blue>51</Blue>
          <Alpha>255</Alpha>
        </BorderColor>
        <BorderSize>0</BorderSize>
        <Triggers />
      </GUIRegion>
    </Children>
    <Tags />
    <EnabledByDefault>false</EnabledByDefault>
  </Widget>

The Images are fairly simple, and have ... exactly the same options as ISB1 had for them because that's what Inner Space supports. The Widget on the other hand has new things like horizontal and vertical anchors, a background mode selector between images and background colors, and in this case a Button that currently does nothing. Yay! But you can get an idea of the flexibility of configuring Widgets, since you're not limited to say a Click Bar/Grid Menu sort of thing where you get to set button 1 that sits in the first cell, button 2 that sits in the next one, etc. You can define the elements and place them anywhere in the Widget.


A Hotkey.. This is the equivalent of ISB1's Ctrl+Shift+Alt+G.
Code:
  <Hotkey Guid="461e6d8d-3765-49d9-9cf6-b6c30396cb5a" DisplayName="Toggle GUI Mode" Category="GUI Mode" Global="false" Enable="true">
    <PressAction xsi:type="ProcedureAction">
      <Procedure>000bad7a-e960-4ff9-8e83-b2569bc79046</Procedure>
      <Module>000bad7a-e960-4ff9-8e80-b2569bc79046</Module>
      <OnPress>true</OnPress>
    </PressAction>
    <ReleaseAction xsi:type="ProcedureAction">
      <Procedure>000bad7a-e960-4ff9-8e83-b2569bc79046</Procedure>
      <Module>000bad7a-e960-4ff9-8e80-b2569bc79046</Module>
      <OnPress>false</OnPress>
    </ReleaseAction>
  </Hotkey>

The Hotkey is fairly straight-forward, you'll notice the key is not actually set here. You'll likely set the default key another way with your Modules. Anyway, the Hotkey uses a ProcedureAction to call the "GUI Mode Toggle" Procedure as seen below.


Procedures ...
Code:
  <Procedure Guid="000bad7a-e960-4ff9-8e81-b2569bc79046" DisplayName="GUI Mode ON" HasParameters="false">
    <OnPress>
      <Instruction Code="DebugTrace">
        <Parameter Value="Info" />
        <Parameter Value="GUI Mode ON" />
      </Instruction>
      <Instruction Code="SetGUIMode">
        <Parameter Value="TRUE" />
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>
  <Procedure Guid="000bad7a-e960-4ff9-8e82-b2569bc79046" DisplayName="GUI Mode OFF" HasParameters="false">
    <OnPress>
      <Instruction Code="DebugTrace">
        <Parameter Value="Info" />
        <Parameter Value="GUI Mode OFF" />
      </Instruction>
      <Instruction Code="SetGUIMode">
        <Parameter Value="FALSE" />
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>
  <Procedure Guid="000bad7a-e960-4ff9-8e83-b2569bc79046" DisplayName="GUI Mode Toggle" HasParameters="false">
    <OnPress>
      <Instruction Code="If">
        <Parameter Value="[[GUIEditMode]]" />
        <Parameter Value="Equals" />
        <Parameter Value="TRUE" />
        <Children>
          <Instruction Code="ProcedureCall">
            <Parameter Value="000bad7a_e960_4ff9_8e82_b2569bc79046" />
          </Instruction>
          <Instruction Code="Return" />
        </Children>
      </Instruction>
      <Instruction Code="ProcedureCall">
        <Parameter Value="000bad7a_e960_4ff9_8e81_b2569bc79046" />
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>


And since no Variables are defined here, here's a different example from the Core Module! (also not User-defined and not kept as XML except for right now).

Here's the HotkeysEnabled Variable, which stores what in ISB1 you'd call the "Key Maps toggle state", but in this case you can actually check and do different things depending on the state.
Code:
  <Variable Guid="000bad7a-e960-4ff9-8e82-b2569bc79048" DisplayName="HotkeysEnabled">
    <VariableType>Integer</VariableType>
    <VariableScope>Global</VariableScope>
    <InitialValue>1</InitialValue>
  </Variable>


And the main Procedures that use this Variable:
Code:
  <Procedure Guid="000bad7a-e960-4ff9-8e83-b2569bc79048" DisplayName="Main Hotkey Disable (self)" HasParameters="false">
    <Notes>Disable all Hotkeys with the Main Hotkey Toggle Tag.</Notes>
    <OnPress>
      <Instruction Code="SetHotkeysEnabledByTag">
        <Parameter Value="40689409_7ac0_4341_9201_e868cb0a9879" />
        <Parameter Value="FALSE" />
      </Instruction>
      <Instruction Code="SetVariable">
        <Parameter Value="000bad7a_e960_4ff9_8e82_b2569bc79048" />
        <Parameter Value="0" />
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>
  <Procedure Guid="000bad7a-e960-4ff9-8e84-b2569bc79048" DisplayName="Main Hotkey Enable (self)" HasParameters="false">
    <Notes>Enable all Hotkeys with the Main Hotkey Toggle Tag.</Notes>
    <OnPress>
      <Instruction Code="SetHotkeysEnabledByTag">
        <Parameter Value="40689409_7ac0_4341_9201_e868cb0a9879" />
        <Parameter Value="TRUE" />
      </Instruction>
      <Instruction Code="SetVariable">
        <Parameter Value="000bad7a_e960_4ff9_8e82_b2569bc79048" />
        <Parameter Value="1" />
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>
  <Procedure Guid="000bad7a-e960-4ff9-8e81-b2569bc79048" DisplayName="Main Hotkey Toggle (team)" HasParameters="false">
    <Notes>Toggles all Hotkeys with the Main Hotkey Toggle Tag.</Notes>
    <OnPress>
      <Instruction Code="If">
        <Parameter Value="[[Variable:HotkeysEnabled]]" />
        <Parameter Value="Equals" />
        <Parameter Value="1" />
        <Children>
          <Instruction Code="ProcedureCall">
            <Parameter Value="000bad7a_e960_4ff9_8e83_b2569bc79048" />
          </Instruction>
          <Instruction Code="ProcedureCall" Target="other [[Team]]">
            <Parameter Value="000bad7a_e960_4ff9_8e83_b2569bc79048" />
          </Instruction>
        </Children>
        <AlternateChildren>
          <Instruction Code="ProcedureCall">
            <Parameter Value="000bad7a_e960_4ff9_8e84_b2569bc79048" />
          </Instruction>
          <Instruction Code="ProcedureCall" Target="other [[Team]]">
            <Parameter Value="000bad7a_e960_4ff9_8e84_b2569bc79048" />
          </Instruction>
        </AlternateChildren>
      </Instruction>
    </OnPress>
    <OnRelease />
  </Procedure>


Check out that sexy "If" instruction. "If [[Variable:HotkeysEnabled]] Equals 1"!


So .. as I've described before, Procedures are the new "Mapped Keys" sans the Hotkey, and Hotkeys can call Procedures. Instructions are the new Action, and there are no Steps. There's no Steps because you can specially craft your Procedures with your own counter variable(s) and make them simple or complicated.

Here's a test case I wrote some time ago for multiple Steps (I was editing the Combat module, hence "Combat 2" in the test code):
Code:
  <Procedure Guid="2573df3c-198d-4de5-a2a0-3a15cc1f9cf3" DisplayName="Combat 2" HasParameters="false">
    <OnPress>
      <Instruction Code="DebugTrace">
        <Parameter Value="Info" />
        <Parameter Value="Hotkey Combat 2 - Press, step [[Variable:StepCounter]]" />
      </Instruction>
      <Instruction Code="If">
        <Parameter Value="[[Variable:StepCounter]]%2" />
        <Parameter Value="Equals" />
        <Parameter Value="0" />
        <Children>
          <Instruction Code="SetHotkeyEnabled">
            <Parameter Value="74a482e5_7b13_4bf8_81b6_5ac349d297c8" />
            <Parameter Value="FALSE" />
          </Instruction>
          <Instruction Code="DebugTrace">
            <Parameter Value="Info" />
            <Parameter Value="Hotkey Combat 2 - Disabled Hotkey 1" />
          </Instruction>
          <Instruction Code="Return" />
        </Children>
      </Instruction>
      <Instruction Code="If">
        <Parameter Value="[[Variable:StepCounter]]%2" />
        <Parameter Value="Equals" />
        <Parameter Value="1" />
        <Children>
          <Instruction Code="SetHotkeyEnabled">
            <Parameter Value="74a482e5_7b13_4bf8_81b6_5ac349d297c8" />
            <Parameter Value="TRUE" />
          </Instruction>
          <Instruction Code="DebugTrace">
            <Parameter Value="Info" />
            <Parameter Value="Hotkey Combat 2 - Enabled Hotkey 1" />
          </Instruction>
          <Instruction Code="Return" />
        </Children>
      </Instruction>
    </OnPress>
    <OnRelease>
      <Instruction Code="DebugTrace">
        <Parameter Value="Info" />
        <Parameter Value="Hotkey Combat 2 - Release" />
      </Instruction>
      <Instruction Code="IncrementVariable">
        <Parameter Value="15b8d8b4_3a58_48c8_ae0b_1ff599608613" />
        <Parameter Value="1" />
      </Instruction>
    </OnRelease>
    <Variable Guid="15b8d8b4-3a58-48c8-ae0b-1ff599608613" DisplayName="StepCounter">
      <VariableType>Integer</VariableType>
      <VariableScope>Object</VariableScope>
    </Variable>
  </Procedure>


Note the StepCounter Variable defined within the Procedure (near the bottom). It's okay to use the same Variable name in multiple Procedures, because when this generates into code for Inner Space it's going to base the variable on the Guid, not the DisplayName. So where it says "If [[Variable:StepCounter]]%2]] Equals 1" (pseudo-code for one of the XML Instructions), that [[Variable:StepCounter]] gets translated into code to access the actual variable from this Procedure. The Variable Scope is used to make this a "static" variable as opposed to a "local" variable -- the point here being that the value is kept when the Procedure completes.

And if you take a good look at the Instructions, you can get an idea of a handful of what kind of Instructions are available and how they work. These Instructions are way more awesome than ISB1's Actions. When you launch your team with ISB2, all of this is translated into an actual script; with ISB1, it was translated into an Inner Space-readable XML "settings" scheme which scripts had to then read and interpret and build things with. The new way is far more powerful and is extremely easy, in comparison, for me to add new features to -- adding a single parameter to an Action in ISB1 required editing dozens of lines of code in C#, changing up the XML Settings, matching up LavishScript to read those settings and hopefully without typoing the name of the settings or forgetting one of the settings and so on, not to mention updating the ISB1 GUI to match... but with ISB2 all of that is in the C# code and I just tell it how the final LavishScript is supposed to look for the Instruction, all in one little place, and the GUI will automatically link up the added feature. If I was female, there would be a *sploosh* ;)

And a quote from the main ISB2 thread with some related info that I didn't cover here, for example regarding distribution/sharing of User-defined Modules.
Something that will probably catch people off guard is that all Widgets must be defined by a Module. (So must Images and Hotkeys for that matter.) User-defined Modules are another active development area right now. I am designing the system so that you will be able to download a zip file and point ISBoxer 2 at the downloaded file, and it will take care of installing it (by extracting into the following folder....). The way it's set up, though, you have a Modules folder in your ISBoxer 2 installation folder, which can be thought of similar to the WoW Addons folder. You can add a Module by creating a sub-folder, and then an XML file within it called either Module.XML, or name-of-subfolder.XML. Both are acceptable but Module.XML is safer in the case that someone renames their folder. So for example ... ISBoxer 2\Modules\MyUserModule\MyUserModule.XML. Now about those Images, which must be defined by a Module. Images will use a RELATIVE FILENAME, based on the Module's install path. Because an absolute path is never stored in a Module XML, images should never disappear as they sometimes do with ISBoxer (when moving the folder, etc). Distributing your Module should be as simple as zipping up your Module sub-folder and handing off the zip file. This should be exactly what TRoN was looking for when designing his TIB Widget for ISBoxer.

I have not started to get into configuration screens for User-defined Modules yet (as seen in the New Team Wizard and the Team Editor, not the part that creates/edits the Module itself), but it should be assumed that configuring a Module you created or downloaded is probably not going to be quite as sweet/refined as built-in Modules. That's because built-in Modules get specially designed interfaces, while user-defined Modules will need generated configuration interfaces. Some of the more complicated Modules I can imagine could end up using a fairly raw configuration screen where you fill in lists of text. This is one area I definitely expect improvements over time and especially as new Modules come out, so I'm not going worry about figuring out the perfect solution beforehand, but this has definitely been on my mind.



Anyway, that is what I have to share regarding User-defined Modules for the moment, now I have to worry about lunch. I welcome any kind of feedback on this, the more questions/comments/concerns you have sooner the better :)
<<

lax

User avatar

Site Admin

Posts: 7301

Joined: Tue Nov 17, 2009 9:32 pm

Post Sun Apr 19, 2015 8:12 am

Re: ISBoxer 2 - Previewing User-defined Modules

Updated screenshot from the original post; check boxes in the "Module applies to ..." section.
Image
<<

lax

User avatar

Site Admin

Posts: 7301

Joined: Tue Nov 17, 2009 9:32 pm

Post Tue Apr 21, 2015 10:32 am

Re: ISBoxer 2 - Previewing User-defined Modules

Currently working on additional pieces of configuration for User Modules. Here is an early peek at the work in progress on the User-defined Hotkey editor. (Yes, field names/descriptions and such will get updated)

Image
This and several other editors are split into both the DataGrid view and a PropertyGrid. The DataGrid view allows you to quickly see, select, change (etc) many things at a time. The PropertyGrid view will then have the more in-depth view and probably show things not visible in the data grid view because of the smaller viewing area per field.

So as you're setting up a Hotkey, you might be able to pick different "Hotkey action types" in the future but for now they all must be linked to a Procedure Call, which may or may not include a number of Parameters. In this screenshot I've selected one with a single Parameter which will assist a given Slot. The Value is not currently restricted to, say, typing in an actual number, so it will accept Variables like [[Slot]]. That restriction will eventually be determined by the ParameterType field, which will probably include an option specifically for Slots, and then the Value box will have features specifically for selecting Slots (still including Variables if appropriate, for example). Only the Value is adjustable in the Parameters grid, the rest is informational (or will be removed as this progresses).

The same concept used here for configuring Parameters will likely also be used for setting up User Options for your Modules. For each Option you want to provide a user, you would ideally select from the same list of types, and the same controls should be available when the user wants to adjust the Value. They may not be presented in the same type of grid shown here for Parameters, but you will fill in the fields that are shown and those will be used to present to the user.

I have not yet moved on to Procedures and selecting/configuring each Instruction. That will be a real beast to tackle.

Return to Alpha Discussion

Who is online

Users browsing this forum: No registered users and 0 guests