Basic Scripting Help - Get Controls X/Y coords, save as usable variable/infolabel
#1
Hello all!

So, I am *trying* to make my first foray into Python for XBMC, but I'm not getting very far. I was hoping one of our more seasoned members could possibly offer a little help to get me started.

Essentially, what I am trying to create is a very simple script. When a normal control is clicked, the RunScript() command is called, passing the control's ID as a variable. RunScript(script.myscript, 10) or RunScript(script.myscript, id=10). Something like that...with the idea being that it can be called from any control. Even better if I don't have to pass the control ID as a variable...

Once the script is executed, all I want to do is get the calling control's x/y coordinates (I believe control.getPosition()) - and save them as a window property, or some other variable I can access via an infolabel...OR fire an animation centered on the x,y coords of said control.



As I mentioned, I've not done PyXBMC scripting before, so this is all new to me, and the syntax is throwing me for a loop...any help would be greatly appreciated!

TIA!

-DH
Reply
#2
i'm sure i could get you some code, but i wonder how you intend to use this window property?

i mean it's not possible to do something like this:
Code:
<animation effect="rotate" center="$INFO[Window.Property(foo)]"...
Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ, Help and Search the forum before posting.
Reply
#3
Agreed with ronie, it makes much more sense to explain what you want to achieve instead of explaining how you want to achieve it. Wink
Donate: https://kodi.tv/contribute/donate (foundation), 146Gr48FqHM7TPB9q33HHv6uWpgQqdz1yk (BTC personal)
Estuary: Kodis new default skin - ExtendedInfo Script - KodiDevKit
Reply
#4
(2015-12-07, 20:17)ronie Wrote: i'm sure i could get you some code, but i wonder how you intend to use this window property?

i mean it's not possible to do something like this:
Code:
<animation effect="rotate" center="$INFO[Window.Property(foo)]"...

Ah, yes...you exactly guessed what I was hoping to do.

Are you familiar with Google's design language at all? I was hoping to emulate their "ripple" effect with button onclicks, as well as the "expanding circle" window transition.

The ripple effect is a circle that starts at 0,0 and expands to fill the control. The window transition is the same thing, only it fills the whole screen.

https://drive.google.com/file/d/0B0OpOqU...sp=sharing

Edit: Here is a video I grabbed from my Nexus Player. The window transition is at about the 14sec mark, the button is at about 54 sec. I forgot, I was also hoping to use this functionality to tell the "flyout" poster where to start from on WindowOpen and end on WindowClose...
Reply
#5
Was it something I said? I got excited seeing both of you replying - thought this would be a quick wham, bam, thank-you maaam sorta thing. I played briefly with just having a hidden texture that did "a thing" - I might be able to use this with Window.HasNext in XML - but I'd still like to learn the scripting bit some more, I think I could manage some crazy stuff once I get it to click in my brain...
Reply
#6
i can do the wham, but i'll don't it'll be useful enough to create a bam.
as said, i don't so how you intend to use the window property in the skin to create an animation.

please provide me some skin code using a window property and i'll have a look if i can set it through python.
Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ, Help and Search the forum before posting.
Reply
#7
(2015-12-11, 18:15)ronie Wrote: i can do the wham, but i'll don't it'll be useful enough to create a bam.
as said, i don't so how you intend to use the window property in the skin to create an animation.

please provide me some skin code using a window property and i'll have a look if i can set it through python.

The reason i didn't provide any code previously is because I understand your point - I can't use a Window Property in an animation value.

I just tried by setting a property on WindowOpen and then referencing it, and nothing happens, meaning my initial idea is null and void.

So, what if I had a list control set up something like below:

Code:
<control type="fixedlist" id="9009">
                <include condition="StringCompare(Skin.String(1-WidgetView-3),$LOCALIZE[31160])">HomePosterLayout</include>
                <include condition="StringCompare(Skin.String(1-WidgetView-3),$LOCALIZE[31159])">ShowDimensions</include>
                <include condition="StringCompare(Skin.String(1-WidgetView-3),$LOCALIZE[31159])">ShowLayouts</include>
                <onfocus>Skin.SetString(HomeFanart,$INFO[ListItem.Art(fanart)])</onfocus>
                    <onleft>9009</onleft>
                <onright>9009</onright>
                <ondown>608</ondown>
                <oninfo condition="!Containter(9009).Listitem(0).DBID">RunScript(script.extendedinfo,info=extendedinfo,Name=$INFO[Container(9009).Listitem(0).Label])</oninfo>
                <oninfo condition="Containter(9009).Listitem(0).DBID">RunScript(script.extendedinfo,info=extendedinfo,id=$INFO[Container(9009).Listitem(0).DBID])</oninfo>
                
                <visible>Skin.String(1-WidgetList-3)</visible>
                <content>$INFO[Skin.String(1-WidgetList-3)]</content>
                
                <!-- Onclick Command to run animation script-->
                <onclick>RunScript(script.whambamthankyou,id=9009,colordiffuse=matplayred,transition=window</onclick>

OR

                <onclick>RunScript(script.whambamthankyou,id=9009,colordiffuse=matplayred,transition=dialog, endx="100", endy="100"</onclick>

                
<onclick>select</onclick>


            </control>


If we can't set a window property to be called by an animation, can we just draw a .png and animate it in the script?

My thoughts being, we pass an ID, a color, and whether to show a window or a dialog transition.

A window transition grabs the coords and dimensions of the selected listitem of the control with the ID we passed. Figures out where center is. Grabs a png resource file we have, (circle-512.png), and draws it with dimensions of 0,0 on center of listitem, colors it with the colordiffuse we pass, and animates it to 2000,2000 over a time of 200ms. Heck, I guess we could or should give a time variable to pass as well?

If we specify a dialog transition, then I'd grab the thumb/image from listitem0 of the specified control, make that fly up to the specified x,y coords, and then disappear to be replaced by a regular control in the skin.


I'm not asking you to code this for me. I'm asking to help learn how to do this myself. If you could give me a basic example of how to break out the paramaters I send, grab a control, and set up an animation, I can probably run with it. Wink
Reply
#8
here you go:

Code:
# import required libraries
import xbmcgui


class Main:
    def __init__( self ):
        #get the arguments passed to the script
        self._parse_argv()
        #get the current window
        self._get_window()
        #get the focussed control
        self._get_control()
        #add an animation to the control
        self._set_anim()

    def _parse_argv( self ):
        #split arguments by delimiters and add them to a dict
        try:
            params = dict( arg.split( '=' ) for arg in sys.argv[ 1 ].split( '&' ) )
        #catch exception in case no arguments are provided
        except:
            params = {}
        #get the transaction argument and fall back to 'window' if none provided
        self.transition = params.get( 'transition', 'window' )
        #get the time parameter and fall back to 3000 if none provided
        self.time = params.get( 'time', 3000 )

    def _get_window( self ):
        #get the window id
        if self.transition == 'window':
            wid = xbmcgui.getCurrentWindowId()
        #or get the dialog id
        else:
            wid = xbmcgui.getCurrentWindowDialogId()
        #get the window
        self.win = xbmcgui.Window(wid)

    def _get_control( self ):
        #get the id of the focussed control
        cid = self.win.getFocusId()
        #get the control
        self.ctrl = self.win.getControl(cid)
        #get posx
        self.ctrl_x = self.ctrl.getX()
        #get posy
        self.ctrl_y = self.ctrl.getY()
        #get width
        self.ctrl_width = self.ctrl.getWidth()
        #get height
        self.ctrl_heigth = self.ctrl.getHeight()

    def _set_anim( self ):
        #calcutate the center of the control
        centerx= int(self.ctrl_x + self.ctrl_width/2)
        centery= int(self.ctrl_y + self.ctrl_heigth/2)
        #add an animation to the control
        self.ctrl.setAnimations([('conditional', 'effect=zoom start=100 end=500 center=%i,%i time=%i condition=true' % (centerx, centery, int(self.time)),)])


#entry point of the script
if ( __name__ == "__main__" ):
    #init the main class
    Main()


reference manual: http://mirrors.xbmc.org/docs/python-docs...mcgui.html


the proper way to call the script from the skin:
Code:
RunScript(script.whambamyourewelcome,transition=w​indow&amp;time=3000)
Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ, Help and Search the forum before posting.
Reply
#9
(2015-12-12, 23:54)ronie Wrote: here you go:

Code:
# import required libraries
import xbmcgui


class Main:
    def __init__( self ):
        #get the arguments passed to the script
        self._parse_argv()
        #get the current window
        self._get_window()
        #get the focussed control
        self._get_control()
        #add an animation to the control
        self._set_anim()

    def _parse_argv( self ):
        #split arguments by delimiters and add them to a dict
        try:
            params = dict( arg.split( '=' ) for arg in sys.argv[ 1 ].split( '&' ) )
        #catch exception in case no arguments are provided
        except:
            params = {}
        #get the transaction argument and fall back to 'window' if none provided
        self.transition = params.get( 'transition', 'window' )
        #get the time parameter and fall back to 3000 if none provided
        self.time = params.get( 'time', 3000 )

    def _get_window( self ):
        #get the window id
        if self.transition == 'window':
            wid = xbmcgui.getCurrentWindowId()
        #or get the dialog id
        else:
            wid = xbmcgui.getCurrentWindowDialogId()
        #get the window
        self.win = xbmcgui.Window(wid)

    def _get_control( self ):
        #get the id of the focussed control
        cid = self.win.getFocusId()
        #get the control
        self.ctrl = self.win.getControl(cid)
        #get posx
        self.ctrl_x = self.ctrl.getX()
        #get posy
        self.ctrl_y = self.ctrl.getY()
        #get width
        self.ctrl_width = self.ctrl.getWidth()
        #get height
        self.ctrl_heigth = self.ctrl.getHeight()

    def _set_anim( self ):
        #calcutate the center of the control
        centerx= int(self.ctrl_x + self.ctrl_width/2)
        centery= int(self.ctrl_y + self.ctrl_heigth/2)
        #add an animation to the control
        self.ctrl.setAnimations([('conditional', 'effect=zoom start=100 end=500 center=%i,%i time=%i condition=true' % (centerx, centery, int(self.time)),)])


#entry point of the script
if ( __name__ == "__main__" ):
    #init the main class
    Main()


reference manual: http://mirrors.xbmc.org/docs/python-docs...mcgui.html


the proper way to call the script from the skin:
Code:
RunScript(script.whambamyourewelcome,transition=w​indow&amp;time=3000)


That *kind of* does what I'm looking for. It doesn't seem to respect the window/dialog variable, and complains about no window with that ID existing. I skipped the variable temporarily and just told it that self.win = xbmcgui.getCurrentWindow(). Now that I'm reading over it again, maybe it just needs to be self.win = wid?

Either way, I change that. Then, it will make the entire grouplist zoom forward, centered on the x/y of the entire grouplist.

What I need it to do is take another png (circle-512.png), create an image control of that. Color it to a specific color which I can pass in. Make it draw on the center x/y of the focused listitem being clicked/selected, and expand to fill the whole screen.

I did some changes and came up with the following, which doesn't really work:

Code:
# import required libraries
import os
import xbmc
import xbmcgui
import xbmcaddon


_ADDON_NAME = 'script.leanbackhelper'
_addon = xbmcaddon.Addon(id=_ADDON_NAME)
_addon_path = _addon.getAddonInfo('path')
try:
    _images = os.path.join(_addon_path, 'textures')
except TypeError:
    # Needed for unit testing with xbmcstubs
    _images = os.path.join(os.path.dirname(__file__), 'textures')


class Main:
    def __init__( self ):
        #get the arguments passed to the script
        self._parse_argv()
        #get the current window
        self._get_window()
        #get the focussed control
        self._get_control()
        #create an image
        self._set_image()

    def _parse_argv( self ):
        #split arguments by delimiters and add them to a dict
        try:
            params = dict( arg.split( '=' ) for arg in sys.argv[ 1 ].split( '&' ) )
        #catch exception in case no arguments are provided
        except:
            params = {}
        #get the transaction argument and fall back to 'window' if none provided
        self.transition = params.get( 'transition', 'window' )
        #get the time parameter and fall back to 3000 if none provided
        self.time = params.get( 'time', 3000 )

    def _get_window( self ):
        #get the window id
        self.win = xbmcgui.Window (xbmcgui.getCurrentWindowId())
        
    def _get_control( self ):
        #get the id of the focused control
        cid = self.win.getFocusId()
        #get the control
        self.ctrl = self.win.getControl(cid)
        #get the listitem
        self.listitem = self.ctrl.getSelectedItem()
        #get posx
        self.ctrl_x = self.ctrl.getX()
        #get posy
        self.ctrl_y = self.ctrl.getY()
        #get width
        self.ctrl_width = self.ctrl.getWidth()
        #get height
        self.ctrl_heigth = self.ctrl.getHeight()

    def _set_image( self):
        centerx= int(self.ctrl_x + self.ctrl_width/2)
        centery= int(self.ctrl_y + self.ctrl_heigth/2)
        self.anim_img = os.path.join(_images, 'Circle-512.png')
        
self.image = xbmcgui.ControlImage (centerx, centery, 20, 20, self.anim_img, aspectRatio=2)
        #add an animation to the control
        self.image.setAnimations([('conditional', 'effect=zoom start=100 end=5000 center=%i,%i time=%i condition=true' % (centerx, centery, int(self.time)),)])
        self.win.addControl(self.image)
        

#entry point of the script
if ( __name__ == "__main__" ):
    #init the main class
    Main()


So, is successful in getting some x/y coords and drawing a 20x20 white circle on those coords. It looks like it's always at 600,370 in the screen grid...

The container I'm testing this on is itself in a grouplist, which may be part of the issue. But, if I run the command from a regular old button which sits at about 750,750 on the screen, it will draw the white circle at 190,880 on the screen.

Point being, it doesn't quite make sense to me where these coordinates are coming from. I'm not sure if the script is using their positions before they're animated by a grouplist or window open transition or what, but it seems odd.

Also, what would be the trick to logging the calculated coords, or anything else? I tried just doing a log(self.center_x) or adding a message in ''s before, but it throws an error...
Reply
#10
if you run the script from a dialog, you need to use xbmcgui.getCurrentWindowDialogId()
in case the script is run from a window, use xbmcgui.getCurrentWindowId()

for logging, you can use the xbmc.log() function:
http://mirrors.xbmc.org/docs/python-docs....html#-log
Do not PM or e-mail Team-Kodi members directly asking for support.
Always read the Forum rules, Kodi online-manual, FAQ, Help and Search the forum before posting.
Reply

Logout Mark Read Team Forum Stats Members Help
Basic Scripting Help - Get Controls X/Y coords, save as usable variable/infolabel0