PDA

View Full Version : LWPanels Help...



caffeineprime
10-23-2012, 09:38 AM
Hopefully this is a pretty basic question but one that I haven't seen asked yet. I was wondering if anyone has an example python script that renders up and draws a "non-trivial" user interface.

For example, a simple thing would be to create a tabchoice_ctl which when clicking through the choices would draw or redraw the panel options. The c/c++ sdk is a little helpful but it doesn't appear that the function names map directly to the python function names, at least listed in the pcore and lwsdk python help. I am at a bit of a loss here. Also, the UI's given in the sample python scripts that come with LW all seem to use a very basic UI setup.

Any help would be greatly appreciated.

caffeineprime
10-26-2012, 12:43 PM
So, after finally getting back to toying with the LWPanels functionality I have put together a little plugin script that uses a tab_choice control. Depending on the tab you select it just prints some text to the screen. It is simple yes but I think from this someone could build a fairly complicated UI utilizing the tab_choice control and some of the other multichoice controls as well.



#! /usr/bin/env python
# -*- Mode: Python -*-
# -*- coding: ascii -*-

"""
This is a LightWave Command Sequence plug-in (Modeler) that demonstrates
the tab_choice controller with a set_event method callback. According to
the LW SDK: "You're responsible for erasing and drawing the appropriate
sets of controls affected by tabbing." Hopefully this has been successfully
shown here.
"""

import sys
import math
import lwsdk

__author__ = "Matt Meixner"
__date__ = "Oct 26th 2012"
__copyright__ = ""
__version__ = ""
__maintainer__ = ""
__email__ = ""
__status__ = "Example"
__lwver__ = "11"

#--- Tab Panel Choices
choices = ['Horse', 'Dog', 'Panda', 'Kitty']

class make_test(lwsdk.ICommandSequence):
def __init__(self, context):
super(make_test, self).__init__()

# Call back event selection
def select_event_func(self, control, user_data):
i = self.c1.get_int() # get integer associated with selected tab
self.c2.erase() # remove the c2 controller
if i == 0:
# create a text controller displaying tab choices but these
# could really be any controller type
self.c2 = self.panel.text_ctl( 'Animal', [choices[i]] )
elif i == 1:
self.c2 = self.panel.text_ctl( 'Animal', [choices[i]] )
elif i == 2:
self.c2 = self.panel.text_ctl( 'Animal', [choices[i]] )
elif i == 3:
self.c2 = self.panel.text_ctl( 'Animal', [choices[i]] )

self.c2.move(10,30) #position controller
self.c2.redraw() # redraw the control

# LWCommandSequence
def process(self, mod_command):
# Creates a panel instance
ui = lwsdk.LWPanels()
self.panel = ui.create('UI_Test')

# Sets initial width and height of the panel
self.panel.setw(200)
self.panel.seth(200)

# Creates a tab_choice control
# The set_event method is called on the tab_control with
# the select_event_func callback
self.c1 = self.panel.tabchoice_ctl('Choice', choices)
self.c1.set_event(self.select_event_func)
self.c1.set_w(350) # width of tab_choice control

# gets the integer assoiciated of the initial tab selected
i = self.c1.get_int()

# create another controller for the panel to draw
self.c2 = self.panel.text_ctl( 'Animal',[choices[i]] )
self.c2.move(10,30) # place the contol on the panel at (x,y)

# Displays the panel with modal and resize flags
if self.panel.open(lwsdk.PANF_BLOCKING | lwsdk.PANF_RESIZE) == 0:
ui.destroy(self.panel)
return lwsdk.AFUNC_OK

ui.destroy(self.panel)

return lwsdk.AFUNC_OK


ServerTagInfo = [
( "Python UI Test", lwsdk.SRVTAG_USERNAME | lwsdk.LANGID_USENGLISH ),
( "UI Test", lwsdk.SRVTAG_BUTTONNAME | lwsdk.LANGID_USENGLISH ),
( "Utilities/Python", lwsdk.SRVTAG_MENU | lwsdk.LANGID_USENGLISH )
]

ServerRecord = { lwsdk.CommandSequenceFactory("LW_PyUITest", make_test) : ServerTagInfo }



I hope you guys find this helpful. Also, any Comments/Questions/Criticisms are always welcome.

caffeineprime
10-26-2012, 12:45 PM
This should probably be made from the Generic factory class instead of the CommandSequence class. But right now I am mostly interested in writing modeler plugins to calculate and render 3D models of crystalline structures for use in an interactive environment to aid a professor for his University course.

BigHache
10-27-2012, 10:06 PM
This is cool. I haven't spent time with the tabs Panels yet.

Yeah the class doesn't matter as it just depends on what the plug-in is for.

Styler
11-29-2012, 05:50 PM
I have an issue about redrawing lwpanel "text_ctl" in during switching between tabs of "tabchoice_ctl".

All controls are in tab0.

http://www.youtube.com/watch?v=2zjWRqlM86U



self.uiWin # main panel
self.uiTabsCtls = [(),()] # this class var holds list of tuples (per tab controls)
self.uiTabs # tabchoice_ctl


This is a callback for tabchoice_ctl


def onTabCtrl(self, control, userdata):
def _getEl(i):
"""Returns 2 tuples (renderCtl,eraseCtl) of controls according on tab index"""
var, m2 = list(self.uiTabsCtls), []
m1 = var.pop(i)
for j in var:
m2+=j
return (m1,tuple(m2))
#----
ren,ers = _getEl(self.uiTabs.get_int())
map(lambda x:x.erase(), ers)
map(lambda x:x.render(), ren)


As you can see buttons and other controls have updated perfectly, but not "text_ctl". It's works only if I'll resize the main panel a little bit, or overlap panel by another window. Do you have any suggestions?

Styler
11-29-2012, 06:39 PM
I've got a solution )



...
#----
ren,ers = _getEl(self.uiTabs.get_int())
b = self._mkButton(size=(240,400)); b.erase(); del(b) # clear panel, _mkButton() is helper for button control
map(lambda x:x.erase(), ers)
map(lambda x:x.render(), ren)


If somebody has more elegant solution, please give me to know.

Phil
02-11-2013, 05:21 PM
I stumbled across this whilst trying to find out how to group controls into tabs. Nothing I've seen so far explains this. Is there a trick to having different controls on different tabs? How do you switch between them cleanly?

artstorm
02-11-2013, 10:01 PM
When I did Render Presets, I ended up looping through the tabs, erasing the controls in the inactive ones, while enabling in the active one, and then refresh the panel. Check the tabs_callback() in my code here, and use that as a starting point:

https://github.com/artstorm/render-presets/blob/master/js_render_presets.py#L125

Phil
02-12-2013, 04:41 AM
When I did Render Presets, I ended up looping through the tabs, erasing the controls in the inactive ones, while enabling in the active one, and then refresh the panel. Check the tabs_callback() in my code here, and use that as a starting point:

https://github.com/artstorm/render-presets/blob/master/js_render_presets.py#L125

I did start with that as a basis, but I became confused trying to unpick the methodology in use. I tried to match what I could see there against what the SDK documentation suggested was possible and was unable to reconcile the two, so was hunting for a simpler example that I could better understand. I'm actually amazed by what you've done with that plugin - I have been fighting against the documentation and examples that come with LW, so am in awe of what you managed to figure out about the python implementation. :)

artstorm
02-12-2013, 09:51 AM
of what you managed to figure out about the python implementation. :)

I found that using the C SDK documentation is more helpful most of the time. Which also makes sense as the Python API is a wrapper for it. For that particular plugin I tried to move some of the GUI setup away from the code, so maybe it's harder to follow along because of that? If I'd rewrite it now, I'd probably separate that even more. Anyway, I'm more than happy to bounce around Python ideas and techniques, so if you still wonder about some part from my script(s soon), just ask. :)

Phil
02-12-2013, 12:04 PM
I'm curious how one should handle cancel/OK button clicks. I've got a basic shell here that creates a second panel from a button on the first. The question that arises is how I know whether the cancel button was pressed rather than the OK button. In LScript, this was simple - you just relied on a conditional - if(reqpost()) - to handle the OK. I don't yet understand the equivalent approach in Python.

artstorm
02-12-2013, 10:31 PM
I'm curious how one should handle cancel/OK button clicks. I've got a basic shell here that creates a second panel from a button on the first. The question that arises is how I know whether the cancel button was pressed rather than the OK button. In LScript, this was simple - you just relied on a conditional - if(reqpost()) - to handle the OK. I don't yet understand the equivalent approach in Python.

The return value from panel.open tells you that, actually most examples uses it I think, but do more or less the same. Try this:


if panel.open(lwsdk.PANF_BLOCKING | lwsdk.PANF_RESIZE | lwsdk.PANF_CANCEL) == 0:
print 'Pressed Cancel'
ui.destroy(panel)
return lwsdk.AFUNC_OK

print 'Pressed OK.'
ui.destroy(panel)
return lwsdk.AFUNC_OK