LoTROInterface

LoTROInterface (https://www.lotrointerface.com/forums/index.php)
-   Lua Programming Help (L) (https://www.lotrointerface.com/forums/forumdisplay.php?f=50)
-   -   Saving window position (https://www.lotrointerface.com/forums/showthread.php?t=1089)

Olenn 09-26-2010 08:45 AM

Saving window position
 
I am trying to figure out how to save window position so that it is persistent through a reload.

I think that I should have it write its coordinates to a save file when it is being dragged and the mouse button is released, but I can not for the life of me figure out how to write that code.

Any help is greatly appreciated.

Wicked Mouse 09-26-2010 10:14 AM

Isn't that what the "layout system" has brought into action for?

http://lorebook.lotro.com/wiki/Relea...ook_8_Official
# The client now has a /ui command that can be used to save the current layout of windows to an xml file and then load this layout.
# To save a ui layout type: /ui layout save <name>
# To load a previously saved layout: /ui layout load <name>
# In both cases the name is optional and if not specified it will just save to a file called Default_ appended with your current game window resolution. (e.q running in 800 x 600 results inDefault_800_600.layout)

Or were you talking about something else?

Olenn 09-26-2010 10:33 AM

(Bear with me, still learning Lua)

When you press "Ctrl + \" it doesn't give a handle to set the Lua window position. I tried writing a function that basically says if the window changes position to save the coordinates to a file and when the window is recalled to load those coordinates .

I just haven't been successful as of yet.

MrJackdaw 09-26-2010 10:52 AM

Assuming the window is called "Window" and the place you want to store the data is a table called "Data";

Code:

Window.PositionChanged=function(sender,args)
        Data.x,Data.y=Window:GetPosition()
end

Will store the window position to the Data table whenever the window is moved.

Then, when you load the data - just use the Data.x and Data.y to load in the position.

Assumption: You are saving the data at some point with;

Code:

Turbine.PluginData.Save( Turbine.DataScope.Character, "The Name of Your Plugin", Data );
And loading it with;

Code:

Data=Turbine.PluginData.Load( Turbine.DataScope.Character, "The Name of Your Plugin")
or similar!

Olenn 09-26-2010 12:37 PM

Thanks, but I am still a little lost. What I have been trying to add is a code that looks to see if the data file exists and if it does use that position. If it doesn't then it uses a default set of values. I am still not sure where all of this goes.

I tried to start simple...this is what I have been trying (without the checking to see if the file exists or not)

Code:

SatchelWindow = class( Turbine.UI.Window );
Data = Turbine.PluginData.Load( Turbine.DataScope.Character, "SatchelData")

function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 275 );
        self:SetPosition( Data.x , Data.y );
----SAVE WINDOW POSITION----
        Window.PositionChanged=function(sender,args)
                Data.x,Data.y=Window:GetPosition()
        end

That is as far as I have (unsuccessfully) gotten. Does the file save on logoff or does it save when the code runs?


I guess its off to borders to find an Lua book...

MrJackdaw 09-26-2010 01:01 PM

Thinking on my feet but change the "Window" lines to "self" as "self" is the window. And don't waste money in Borders - I worked my way through the Turbine sample stuff stealing where I could, especially the combat bar on. Just as with learing the xml modification stuff, look at other peoples work and rip it apart... *grin* The excellent lessons on http://www.lua.org/pil/ helped me get a bit better!

I still wouldn't call myself any good - but the stuff works well enough for me!

Olenn 09-26-2010 01:11 PM

I changed both of my Window values to self, but i am still getting the error;

attempt to index Global 'Data' (a nil value)

MrJackdaw 09-26-2010 03:28 PM

Has Data been defined anywhere as a value? If there are no saved variables it becomes "nil" and effectively does not exist.

Add this after the load line;

if Data==nil then Data={} end

and that should sort it! Note the "==" not just "=". I always get that wrong! If you are defining it is a single =, if you are comparing it is a double ==.

Olenn 09-26-2010 05:20 PM

I was under the assumption that

Code:

Data = Turbine.PluginData.Load( Turbine.DataScope.Character, "SatchelData")
declared the variable...this is the most frusteraiting thing ever...back to boarders, lol. It still isn't working...


Here is all of my code thus far...

Code:


import "Turbine";
import "Turbine.Gameplay";
import "Turbine.UI";
import "Turbine.UI.Extensions";
import "Turbine.UI.Lotro";
import "Turbine.Utils";

SatchelWindow = class( Turbine.UI.Window );
Data = Turbine.PluginData.Load( Turbine.DataScope.Character, "SatchelData")
if Data==nil then Data={} end


function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 275 );
        Data = Turbine.PluginData.Load( Turbine.DataScope.Character, "SatchelData")
       

----SATCHEL CLOSES WHEN ESC IS PRESSED----
        self:SetWantsKeyEvents( true );
        self.KeyDown = function( sender, args )
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                end

----SAVE WINDOW POSITION----
        self.PositionChanged=function(sender,args)
                Data.x,Data.y=self:GetPosition()
               
        end
       
               
----MAKE BAG BUTTONS ON THE TOOLBAR OPEN SATCHEL----
                if ( args.Action == Turbine.UI.Lotro.Action.ToggleBags or
                    args.Action == Turbine.UI.Lotro.Action.ToggleBag1 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag2 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag3 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag4 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag5 )
                then
                        sender:SetVisible( not sender:IsVisible() )
                end
        end
       
        local satchel = self;
        local mainWindow = self;
       
        self.itemListBoxScrollBar = Turbine.UI.Lotro.ScrollBar();
        self.itemListBoxScrollBar:SetOrientation( Turbine.UI.Orientation.Vertical );
        self.itemListBoxScrollBar:SetParent( self );

        self.itemListBox = Turbine.UI.ListBox();
        self.itemListBox:SetParent( self );
        self.itemListBox:SetOrientation( Turbine.UI.Orientation.Horizontal );
        self.itemListBox:SetVerticalScrollBar( self.itemListBoxScrollBar );
        self.itemListBox:SetAllowDrop( true );
       
        self.itemListBox.DragDrop = function( sender, args )
                local shortcut = args.DragDropInfo:GetShortcut();
                if ( shortcut ~= nil ) then
                  local destinationItemControl = self.itemListBox:GetItemAt( args.X, args.Y );
                  local destinationIndex = self.itemListBox:IndexOfItem( destinationItemControl );
                  self.backpack:PerformShortcutDrop( shortcut, destinationIndex, Turbine.UI.Control.IsShiftKeyDown() );
                end
        end
----MAKE WINDOW RESIZABLE----
        self.resizeHandle = Turbine.UI.Control();
        self.resizeHandle:SetParent( self );
        self.resizeHandle:SetZOrder( 100 );
        self.resizeHandle:SetSize( 20, 20 );
        self.resizeHandle:SetPosition( self:GetWidth() - self.resizeHandle:GetWidth(), self:GetHeight() - self.resizeHandle:GetHeight() );

        self.resizeHandle.MouseDown = function( sender, args )
                sender.dragStartX = args.X;
                sender.dragStartY = args.Y;
                sender.dragging = true;
        end

        self.resizeHandle.MouseMove = function( sender, args )
                local width, height = mainWindow:GetSize();

                if ( sender.dragging ) then
                        mainWindow:SetSize( width + ( args.X - sender.dragStartX ), height + ( args.Y - sender.dragStartY ) );
                        sender:SetPosition( mainWindow:GetWidth() - sender:GetWidth(), mainWindow:GetHeight() - sender:GetHeight() )
                        satchel:PerformLayout()
                end
        end

        self.resizeHandle.MouseUp = function( sender, args )
                sender.dragging = false;
        end
----CREATE CONAINER FOR ITEMS----
        self.items = { };

        local player = Turbine.Gameplay.LocalPlayer();
        self.backpack = player:GetBackpack();

        self.backpack.SizeChanged = function( sender, args )
                satchel:Refresh();
        end

        self.backpack.ItemAdded = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemRemoved = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemMoved = function( sender, args )
                satchel.items[args.OldIndex]:SetItem( satchel.backpack:GetItem( args.OldIndex ) );
                satchel.items[args.NewIndex]:SetItem( satchel.backpack:GetItem( args.NewIndex ) );
        end

        self:Refresh();

end

----FUNCTION TO REFRESH BAG CONTENTS----
function SatchelWindow:Refresh()
        local backpackSize = self.backpack:GetSize();

        for i = 1, backpackSize, 1 do
                if ( self.items[i] ) then
                        self.items[i]:SetParent( nil );
                end
               
                self.items[i] = Turbine.UI.Lotro.ItemControl( self.backpack:GetItem( i ) );
                self.itemListBox:AddItem( self.items[i] );
        end

        self:PerformLayout();
end

function SatchelWindow:PerformLayout()
        self:Layout( { } )
end

function SatchelWindow:Layout( args )
        local width, height = self:GetSize();
       
        local itemWidth = 40;
       
        if ( self.items[1] ~= nil ) then
                itemWidth = self.items[1]:GetWidth()
        end

        local listWidth = width - 40;
        local listHeight = height - 50;
        local itemsPerRow = listWidth / itemWidth;

        self.itemListBox:SetPosition( 15, 35 );
        self.itemListBox:SetSize( listWidth, listHeight );
        self.itemListBox:SetMaxItemsPerLine( itemsPerRow );
       
        self.itemListBoxScrollBar:SetPosition( width - 25, 35 );
        self.itemListBoxScrollBar:SetSize( 10, listHeight );

end

I am about to just say screw it and it won't save its position, lol

Digital_Utopia 09-26-2010 06:13 PM

Move your declaration of Data so that it's below the constructor lines

add "self." in front of Data

Code:

SatchelWindow = class( Turbine.UI.Window );
function SatchelWindow:Constructor()
    Turbine.UI.Lotro.Window.Constructor( self );

    self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "SatchelData")
    if (self.Data==nil)then
          self:SetPosition(defaultx,defaulty);
    else
          self:SetPosition(self.Data.x,self.Data.y)
    end

...
end

Where defaultx and defaulty are whatever position you would give that window by default.

Olenn 09-26-2010 06:58 PM

Wow, thanks. The only thing left is where to put;

Code:

Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", Data );
I know it goes in here somewhere;

Code:

        self.PositionChanged=function(sender,args)
                Data.x,Data.y=self:GetPosition()
        end

..and thanks for the help everyone, its much appreciated.

Digital_Utopia 09-26-2010 07:12 PM

I'm going to help you cheat a bit here - but only because the original code that this was based off of was given to me by Pengoros

put this in your Main.lua script:

Code:

pluginName="myPluginsName";
window = Turbine.UI.Window();
window:SetWantsUpdates(true);
window.Update = function(sender,args)
        if (Plugins[pluginName] ~= nil) then
                Plugins[pluginName].Unload = function(self,sender,args)
                        UnloadPlugin();
                end
                window:SetWantsUpdates(false);
        end
end

This will call a function called "UnloadPlugin()" when the plugin is being unloaded. This function would be a great place to put that PluginData.Save() line.

Olenn 09-26-2010 09:20 PM

Thanks for all of the help. I did what you said and its not giving me an error but it isn't working either.

The end goal is that you could drag the window where ever you want it and when you start the game back up later it remembers its position. I really thought this would be as easy an writing to a file when you stopped dragging the window, but its definitely been an all day project trying to get this to work.

I believe that my problem now is simply getting the plugin to save the lwindows location data. Everything else seems to be working fine.

Here is the main.lua I have thus far.

Code:

import "Turbine.UI";
import "Turbine.UI.Lotro";
import "Turbine.Debug";

import "Olenn.Satchel";

satchelWindow = Olenn.Satchel.SatchelWindow();
satchelWindow:SetVisible( true );

settingsWindow = Olenn.Satchel.SettingsWindow();
settingsWindow:SetVisible( true );

Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack1, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack2, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack3, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack4, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack5, false );

satchelCommand = Turbine.ShellCommand();

function satchelCommand:Execute(cmd, args)
        if ( args == "show" ) then
                SatchelWindow:SetVisible( true );
        elseif ( args == "hide" ) then
                SatchelWindow:SetVisible( false );
        elseif ( args == "toggle" ) then
                SatchelWindow:SetVisible( not SatchelWindow:IsVisible() );
        elseif ( args ~= nil ) then
                satchelCommand:GetHelp();
        end
       
        pluginName="Satchel";
        window = Turbine.UI.Window();
        window:SetWantsUpdates(true);
        window.Update = function(sender,args)
        if (Plugins[pluginName] ~= nil) then
                Plugins[pluginName].Unload = function(self,sender,args)
                        UnloadPlugin();
                        Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", Data );
                end
                window:SetWantsUpdates(false);
        end
end
end


function satchelCommand:GetHelp()
        Turbine.Shell.WriteLine( "------------Satchel Commands------------");
        Turbine.Shell.WriteLine( "/satchel show: Display Satchel Window");
        Turbine.Shell.WriteLine( "/satchel hide: Hide Satchel Window");
        Turbine.Shell.WriteLine( "/satchel toggle: Toggle Satchel Window");
end

Turbine.Shell.AddCommand( "satchel", satchelCommand );


Kragenwar 09-27-2010 06:52 AM

I don't know if you did as Digitial Utopia suggested and declared Data in your satchel class as self.Data (since you only posted your main and didnt repost your Satchel class). But if you did, then when saving your data variable from your main you may need to go
Code:

Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", SatchelWindow.Data );
Alternatively you could also put the save line in the code where you write the position to data

Code:

----SAVE WINDOW POSITION----
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end

I haven't played with the unload code Digital Utopia posted, but I am going to take a guess that maybe your call to save needs to come before UnloadPlugin(); Just a guess tho
Code:

Plugins[pluginName].Unload = function(self,sender,args)
      Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", SatchelWindow.Data );                       
      UnloadPlugin();
end

Also I noticed in your class code you posted earlier you also allow changing of size, which means you might want to save the size as well.

Olenn 09-27-2010 11:17 AM

1 Attachment(s)
You guys are awesome, but I think I am starting to get all of your advice mixed up. I am going to post both Lua scripts and see what you think. I am getting an error;

attempt to index Data a nil value

main.lua

Code:



import "Turbine.UI";
import "Turbine.UI.Lotro";
import "Turbine.Debug";

import "Olenn.Satchel";

satchelWindow = Olenn.Satchel.SatchelWindow();
satchelWindow:SetVisible( true );

settingsWindow = Olenn.Satchel.SettingsWindow();
settingsWindow:SetVisible( false );

Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack1, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack2, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack3, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack4, false );
Turbine.UI.Lotro.LotroUI.SetEnabled( Turbine.UI.Lotro.LotroUIElement.Backpack5, false );

satchelCommand = Turbine.ShellCommand();

function satchelCommand:Execute(cmd, args)
        if ( args == "show" ) then
                SatchelWindow:SetVisible( true );
        elseif ( args == "hide" ) then
                SatchelWindow:SetVisible( false );
        elseif ( args == "toggle" ) then
                SatchelWindow:SetVisible( not SatchelWindow:IsVisible() );
        elseif ( args ~= nil ) then
                satchelCommand:GetHelp();
        end
       
        pluginName="Satchel";
        window = Turbine.UI.Window();
        window:SetWantsUpdates(true);
        window.Update = function(sender,args)
        if (Plugins[pluginName] ~= nil) then
                Plugins[pluginName].Unload = function(self,sender,args)
                        UnloadPlugin();
                        Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", Data );
                end
                window:SetWantsUpdates(false);
        end
end
end




function satchelCommand:GetHelp()
        Turbine.Shell.WriteLine( "------------Satchel Commands------------");
        Turbine.Shell.WriteLine( "/satchel show: Display Satchel Window");
        Turbine.Shell.WriteLine( "/satchel hide: Hide Satchel Window");
        Turbine.Shell.WriteLine( "/satchel toggle: Toggle Satchel Window");
end

Turbine.Shell.AddCommand( "satchel", satchelCommand );

SatchelWindow.lua

Code:


import "Turbine";
import "Turbine.Gameplay";
import "Turbine.UI";
import "Turbine.UI.Extensions";
import "Turbine.UI.Lotro";
import "Turbine.Utils";
import "Olenn.Satchel"

SatchelWindow = class( Turbine.UI.Window );

function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 300 );
----LOAD PRIOR POSITION----
        self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "SatchelData")
    if (self.Data==nil)then
                self:SetPosition(100 , 100);
    else
                self:SetPosition(self.Data.x,self.Data.y)
    end
----SAVE CURENT POSITION WHEN MOVED---
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end
----SATCHEL CLOSES WHEN ESC IS PRESSED----
        self:SetWantsKeyEvents( true );
        self.KeyDown = function( sender, args )
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                end
               
----MAKE BAG BUTTONS ON THE TOOLBAR OPEN SATCHEL----
                if ( args.Action == Turbine.UI.Lotro.Action.ToggleBags or
                    args.Action == Turbine.UI.Lotro.Action.ToggleBag1 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag2 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag3 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag4 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag5 )
                then
                        sender:SetVisible( not sender:IsVisible() )
                end
        end
       
        local satchel = self;
        local mainWindow = self;
       
        self.itemListBoxScrollBar = Turbine.UI.Lotro.ScrollBar();
        self.itemListBoxScrollBar:SetOrientation( Turbine.UI.Orientation.Vertical );
        self.itemListBoxScrollBar:SetParent( self );

        self.itemListBox = Turbine.UI.ListBox();
        self.itemListBox:SetParent( self );
        self.itemListBox:SetOrientation( Turbine.UI.Orientation.Horizontal );
        self.itemListBox:SetVerticalScrollBar( self.itemListBoxScrollBar );
        self.itemListBox:SetAllowDrop( true );
       
        self.itemListBox.DragDrop = function( sender, args )
                local shortcut = args.DragDropInfo:GetShortcut();
                if ( shortcut ~= nil ) then
                  local destinationItemControl = self.itemListBox:GetItemAt( args.X, args.Y );
                  local destinationIndex = self.itemListBox:IndexOfItem( destinationItemControl );
                  self.backpack:PerformShortcutDrop( shortcut, destinationIndex, Turbine.UI.Control.IsShiftKeyDown() );
                end
        end
----MAKE WINDOW RESIZABLE----
        self.resizeHandle = Turbine.UI.Control();
        self.resizeHandle:SetParent( self );
        self.resizeHandle:SetZOrder( 100 );
        self.resizeHandle:SetSize( 20, 20 );
        self.resizeHandle:SetPosition( self:GetWidth() - self.resizeHandle:GetWidth(), self:GetHeight() - self.resizeHandle:GetHeight() );

        self.resizeHandle.MouseDown = function( sender, args )
                sender.dragStartX = args.X;
                sender.dragStartY = args.Y;
                sender.dragging = true;
        end

        self.resizeHandle.MouseMove = function( sender, args )
                local width, height = mainWindow:GetSize();

                if ( sender.dragging ) then
                        mainWindow:SetSize( width + ( args.X - sender.dragStartX ), height + ( args.Y - sender.dragStartY ) );
                        sender:SetPosition( mainWindow:GetWidth() - sender:GetWidth(), mainWindow:GetHeight() - sender:GetHeight() )
                        satchel:PerformLayout()
                end
        end

        self.resizeHandle.MouseUp = function( sender, args )
                sender.dragging = false;
        end
----CREATE CONAINER FOR ITEMS----
        self.items = { };

        local player = Turbine.Gameplay.LocalPlayer();
        self.backpack = player:GetBackpack();

        self.backpack.SizeChanged = function( sender, args )
                satchel:Refresh();
        end

        self.backpack.ItemAdded = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemRemoved = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemMoved = function( sender, args )
                satchel.items[args.OldIndex]:SetItem( satchel.backpack:GetItem( args.OldIndex ) );
                satchel.items[args.NewIndex]:SetItem( satchel.backpack:GetItem( args.NewIndex ) );
        end

        self:Refresh();
       
----CREATE SETTINGS BUTTON----
        self.settingsButton = Turbine.UI.Lotro.Button();
        self.settingsButton:SetParent( self );

        self.settingsButton:SetSize(70,30);
        self.settingsButton:SetPosition(34, 37);
        self.settingsButton:SetFont(Turbine.UI.Lotro.Font.Verdana14);
        self.settingsButton:SetText("Settings");       
        self.settingsButton.Click = function(sender, args)
                settingsWindow:SetVisible( not SettingsWindow:IsVisible() );
        end
       
end

----FUNCTION TO REFRESH BAG CONTENTS----
function SatchelWindow:Refresh()
        local backpackSize = self.backpack:GetSize();

        for i = 1, backpackSize, 1 do
                if ( self.items[i] ) then
                        self.items[i]:SetParent( nil );
                end
               
                self.items[i] = Turbine.UI.Lotro.ItemControl( self.backpack:GetItem( i ) );
                self.itemListBox:AddItem( self.items[i] );
        end

        self:PerformLayout();
end

function SatchelWindow:PerformLayout()
        self:Layout( { } )
end

function SatchelWindow:Layout( args )
        local width, height = self:GetSize();
       
        local itemWidth = 40;
       
        if ( self.items[1] ~= nil ) then
                itemWidth = self.items[1]:GetWidth()
        end

        local listWidth = width - 40;
        local listHeight = height - 75;
        local itemsPerRow = listWidth / itemWidth;

        self.itemListBox:SetPosition( 15, 60 );
        self.itemListBox:SetSize( listWidth, listHeight );
        self.itemListBox:SetMaxItemsPerLine( itemsPerRow );
       
        self.itemListBoxScrollBar:SetPosition( width - 25, 55 );
        self.itemListBoxScrollBar:SetSize( 10, listHeight );

end

Thanks for all of you help guys!

I have attached the plugin in its current state for Lua help only, it is not advised for use by the common user.

Kragenwar 09-27-2010 01:02 PM

Quote:

Originally Posted by Olenn (Post 4920)
You guys are awesome, but I think I am starting to get all of your advice mixed up. I am going to post both Lua scripts and see what you think. I am getting an error;

attempt to index Data a nil value

I see 2 potential problems, did the error mention what line was causing the issue? Off the top of my head the issue could be:

Here:
Code:

if (Plugins[pluginName] ~= nil) then
                Plugins[pluginName].Unload = function(self,sender,args)
                        UnloadPlugin();
                        Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", Data );
                end
                window:SetWantsUpdates(false);
        end

When referencing your Data variable from outside of the class you shoud be doing so via SatchelWindow.Data
Code:

Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", SatchelWindow.Data );


or the issue could possibly be here:
Code:

----SAVE CURENT POSITION WHEN MOVED---
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );

You haven't declared data as a table. Not sure if that would make a difference or not (I am fairly new to lua). But you could try:

Code:

----LOAD PRIOR POSITION----
        self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "SatchelData")
    if (self.Data==nil)then
                self.Data = { };
                self.Data.x = 100;
                self.Data.y = 100;
                self:SetPosition(100 , 100);

    else
                self:SetPosition(self.Data.x,self.Data.y)
    end

Like I said, im fairly new to LUA so there may be a better place to declare Data as a table. But I am guessing the issue is because when first load it self.Data never gets declared as a table, so you get an error when you try to write to self.Data.x and self.Data.y.

Olenn 09-27-2010 01:22 PM

AWESOME!

That gives me tons to work with. It is now saving the position to the file, but when I click reload it still resets it to 100 x 100.

But at least I have something to work for.

Much appreciated everyone!

Kragenwar 09-27-2010 01:35 PM

Quote:

Originally Posted by Olenn (Post 4925)
AWESOME!

That gives me tons to work with. It is now saving the position to the file, but when I click reload it still resets it to 100 x 100.

But at least I have something to work for.

Much appreciated everyone!

Thats fantastic. I have a feeling PositionChanged is not firing. You could try getting rid of
Code:

----SAVE CURENT POSITION WHEN MOVED---
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end

and then do this in your MouseUp Handler instead
Code:

self.resizeHandle.MouseUp = function( sender, args )
              if (sender.dragging) then
                    self.Data.x,self.Data.y=self:GetPosition();
              end       
              sender.dragging = false;
        end

That way you will be writing the new position to Data whenever the user releases the mouse after dragging, and saving the position to the settings file on unload.

Olenn 09-27-2010 02:13 PM

I tried to put that in place of

Code:


        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end

but I keep getting this error;

...Rings Online\Plugins\Olenn\Satchel\SatchelWindow.lua:33: attempt to index field 'resizeHandle' (a nil value)

the odd part is that line 33 is just "end"

Kragenwar 09-27-2010 02:45 PM

Quote:

Originally Posted by Olenn (Post 4928)
I tried to put that in place of

Code:


        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end

but I keep getting this error;

...Rings Online\Plugins\Olenn\Satchel\SatchelWindow.lua:33: attempt to index field 'resizeHandle' (a nil value)

the odd part is that line 33 is just "end"

Yeah you shouldn't be replacing the self.PositionChanged part with the self.resizeHandle.MouseUp function. All you need to do is completlely remove the self.PositionChanged function. Then change your already existing self.resizeHandle.MouseUp by adding the line to set Data.x and Data.y. Here is the whole class with the change.

Code:

import "Turbine";
import "Turbine.Gameplay";
import "Turbine.UI";
import "Turbine.UI.Extensions";
import "Turbine.UI.Lotro";
import "Turbine.Utils";
import "Olenn.Satchel"

SatchelWindow = class( Turbine.UI.Window );

function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 300 );
----LOAD PRIOR POSITION----
        self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "SatchelData")
    if (self.Data==nil)then
                self.Data = { };
                self.Data.x = 100;
                self.Data.y = 100;
                self:SetPosition(100 , 100);
    else
                self:SetPosition(self.Data.x,self.Data.y)
    end

----SATCHEL CLOSES WHEN ESC IS PRESSED----
        self:SetWantsKeyEvents( true );
        self.KeyDown = function( sender, args )
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                end
               
----MAKE BAG BUTTONS ON THE TOOLBAR OPEN SATCHEL----
                if ( args.Action == Turbine.UI.Lotro.Action.ToggleBags or
                    args.Action == Turbine.UI.Lotro.Action.ToggleBag1 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag2 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag3 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag4 or
                        args.Action == Turbine.UI.Lotro.Action.ToggleBag5 )
                then
                        sender:SetVisible( not sender:IsVisible() )
                end
        end
       
        local satchel = self;
        local mainWindow = self;
       
        self.itemListBoxScrollBar = Turbine.UI.Lotro.ScrollBar();
        self.itemListBoxScrollBar:SetOrientation( Turbine.UI.Orientation.Vertical );
        self.itemListBoxScrollBar:SetParent( self );

        self.itemListBox = Turbine.UI.ListBox();
        self.itemListBox:SetParent( self );
        self.itemListBox:SetOrientation( Turbine.UI.Orientation.Horizontal );
        self.itemListBox:SetVerticalScrollBar( self.itemListBoxScrollBar );
        self.itemListBox:SetAllowDrop( true );
       
        self.itemListBox.DragDrop = function( sender, args )
                local shortcut = args.DragDropInfo:GetShortcut();
                if ( shortcut ~= nil ) then
                  local destinationItemControl = self.itemListBox:GetItemAt( args.X, args.Y );
                  local destinationIndex = self.itemListBox:IndexOfItem( destinationItemControl );
                  self.backpack:PerformShortcutDrop( shortcut, destinationIndex, Turbine.UI.Control.IsShiftKeyDown() );
                end
        end
----MAKE WINDOW RESIZABLE----
        self.resizeHandle = Turbine.UI.Control();
        self.resizeHandle:SetParent( self );
        self.resizeHandle:SetZOrder( 100 );
        self.resizeHandle:SetSize( 20, 20 );
        self.resizeHandle:SetPosition( self:GetWidth() - self.resizeHandle:GetWidth(), self:GetHeight() - self.resizeHandle:GetHeight() );

        self.resizeHandle.MouseDown = function( sender, args )
                sender.dragStartX = args.X;
                sender.dragStartY = args.Y;
                sender.dragging = true;
        end

        self.resizeHandle.MouseMove = function( sender, args )
                local width, height = mainWindow:GetSize();

                if ( sender.dragging ) then
                        mainWindow:SetSize( width + ( args.X - sender.dragStartX ), height + ( args.Y - sender.dragStartY ) );
                        sender:SetPosition( mainWindow:GetWidth() - sender:GetWidth(), mainWindow:GetHeight() - sender:GetHeight() )
                        satchel:PerformLayout()
                end
        end

        self.resizeHandle.MouseUp = function( sender, args )
                if (sender.dragging) then
                        self.Data.x, self.Data.y = self:GetPosition();
                end
                sender.dragging = false;
        end
----CREATE CONAINER FOR ITEMS----
        self.items = { };

        local player = Turbine.Gameplay.LocalPlayer();
        self.backpack = player:GetBackpack();

        self.backpack.SizeChanged = function( sender, args )
                satchel:Refresh();
        end

        self.backpack.ItemAdded = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemRemoved = function( sender, args )
                satchel.items[args.Index]:SetItem( satchel.backpack:GetItem( args.Index ) );
        end

        self.backpack.ItemMoved = function( sender, args )
                satchel.items[args.OldIndex]:SetItem( satchel.backpack:GetItem( args.OldIndex ) );
                satchel.items[args.NewIndex]:SetItem( satchel.backpack:GetItem( args.NewIndex ) );
        end

        self:Refresh();
       
----CREATE SETTINGS BUTTON----
        self.settingsButton = Turbine.UI.Lotro.Button();
        self.settingsButton:SetParent( self );

        self.settingsButton:SetSize(70,30);
        self.settingsButton:SetPosition(34, 37);
        self.settingsButton:SetFont(Turbine.UI.Lotro.Font.Verdana14);
        self.settingsButton:SetText("Settings");       
        self.settingsButton.Click = function(sender, args)
                settingsWindow:SetVisible( not SettingsWindow:IsVisible() );
        end
       
end

----FUNCTION TO REFRESH BAG CONTENTS----
function SatchelWindow:Refresh()
        local backpackSize = self.backpack:GetSize();

        for i = 1, backpackSize, 1 do
                if ( self.items[i] ) then
                        self.items[i]:SetParent( nil );
                end
               
                self.items[i] = Turbine.UI.Lotro.ItemControl( self.backpack:GetItem( i ) );
                self.itemListBox:AddItem( self.items[i] );
        end

        self:PerformLayout();
end

function SatchelWindow:PerformLayout()
        self:Layout( { } )
end

function SatchelWindow:Layout( args )
        local width, height = self:GetSize();
       
        local itemWidth = 40;
       
        if ( self.items[1] ~= nil ) then
                itemWidth = self.items[1]:GetWidth()
        end

        local listWidth = width - 40;
        local listHeight = height - 75;
        local itemsPerRow = listWidth / itemWidth;

        self.itemListBox:SetPosition( 15, 60 );
        self.itemListBox:SetSize( listWidth, listHeight );
        self.itemListBox:SetMaxItemsPerLine( itemsPerRow );
       
        self.itemListBoxScrollBar:SetPosition( width - 25, 55 );
        self.itemListBoxScrollBar:SetSize( 10, listHeight );

end

This should work unless I'm totally misunderstanding your code or what you are trying to do with it.

Olenn 09-27-2010 03:15 PM

What I am trying to do is two fold. I want the window to have a default location and size when the addon is first installed. After that when the user moves or resizes the window, I want the window to save its size and location to a file so that the next time the user runs the game the window is in the same place and the same size that they left it in.

I tried your code and it does it still resets to 100 x 100 when I hit reload in plugin manager.

I have to go to work now, but I will keep hammering away at it tomorrow.

Thanks for all your help.

Kragenwar 09-27-2010 03:38 PM

Quote:

Originally Posted by Olenn (Post 4936)
What I am trying to do is two fold. I want the window to have a default location and size when the addon is first installed. After that when the user moves or resizes the window, I want the window to save its size and location to a file so that the next time the user runs the game the window is in the same place and the same size that they left it in.

I tried your code and it does it still resets to 100 x 100 when I hit reload in plugin manager.

I have to go to work now, but I will keep hammering away at it tomorrow.

Thanks for all your help.

I think I realized my problem. The place where I had you put that code is actually for resizing the window i guess? Ill admit I didn't actually study the code thoroughly. It was just the only place where I seen something drag-gable. I can't seem to find where you are actually making the window moveable. So I am probably missing something.

Also just noticed that you are loading from "SatchelData" and saving to "Satchel".... Didn't notice it before, but those save/load calls need to match. That was probably the problem in the first place so you may need to go back to the self.PositionChanged function and get rid of that line I had you add to self.resizeHandle.MouseDown.

Olenn 09-28-2010 12:23 PM

I changed the SatchelData, thanks for spotting that.

I am not "making" the windows movable...they just are...is that wrong?

Kragenwar 09-28-2010 12:48 PM

No it's not wrong. I was mistaken, didn't realize that a turbine.ui.window was already moveable if you have a title bar on it. Just my lack of experience showing threw :p

Sorry for leading you in the wrong direction yesterday. You were actually correct in the first place with your PositionChanged function. So make sure you change your resizeHandle.MouseUp function back to the way it was before I suggested you change it.

Hope it all works out.

Olenn 09-30-2010 01:53 AM

For everyone that helped, THANK YOU!!!

Major break through today. The "save position" issue is resolved. It is now working properly and I have learned a ton in the process...

My hat is off to you all.

For anyone that is curious about the working code here it is.

Code:

SatchelWindow = class( Turbine.UI.Window );

function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 300 );
----LOAD PRIOR POSITION----
        self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "Satchel")
    if (self.Data==nil)then
                self.Data = { };
                self.Data.x = Turbine.UI.Display.GetWidth() - 400;
                self.Data.y = Turbine.UI.Display.GetHeight() - 300;
                self:SetPosition(self.Data.x,self.Data.y);
    else
                self:SetPosition(self.Data.x,self.Data.y)
    end

----SATCHEL SAVES POSITION IF MOVED----
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end
       
----SATCHEL CLOSES WHEN ESC IS PRESSED----
        self:SetWantsKeyEvents( true );
        self.KeyDown = function( sender, args )
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                end

Feel free to use and distribute it!

Olenn 10-01-2010 01:08 AM

Updated to save position information as well,

Code:

SatchelWindow = class( Turbine.UI.Window );

function SatchelWindow:Constructor()
----CREATE THE WINDOW----
        Turbine.UI.Lotro.Window.Constructor( self );
        self:SetText("Satchel");
        self:SetSize( 325, 300 );
----LOAD PRIOR SIZE & POSITION----
        self.Data = Turbine.PluginData.Load( Turbine.DataScope.Character,  "Satchel")
    if (self.Data==nil)then
                self.Data = { };
                self.Data.x = Turbine.UI.Display.GetWidth() - 400;
                self.Data.y = Turbine.UI.Display.GetHeight() - 300;
                self.Data.sx = 325;
                self.Data.sy = 300;
                self:SetPosition(self.Data.x,self.Data.y);
                self:GetSize(self.Data.sx,self.Data.sy);
    else
                self:SetPosition(self.Data.x,self.Data.y)
                self:SetSize(self.Data.sx,self.Data.sy)
    end

----SATCHEL SAVES SIZE & POSITION IF MOVED----
        self.PositionChanged=function(sender,args)
                self.Data.x,self.Data.y=self:GetPosition()
                self.Data.sx,self.Data.sy=self:GetSize()
                Turbine.PluginData.Save( Turbine.DataScope.Character, "Satchel", self.Data );
        end
       
----SATCHEL CLOSES WHEN ESC IS PRESSED----
        self:SetWantsKeyEvents( true );
        self.KeyDown = function( sender, args )
                if ( args.Action == Turbine.UI.Lotro.Action.Escape ) then
                        sender:SetVisible( false )
                end

Once again, thanks to everyone that helped over the past few days. It is great to be part of such an awesome community!


All times are GMT -5. The time now is 05:17 AM.

vBulletin® - Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
© MMOUI