Text archives Help
- From: bigler@sci.utah.edu
- To: manta@sci.utah.edu
- Subject: [MANTA] r1110 - in trunk: Core/Geometry Engine/Display Model/Lights SwigInterface
- Date: Fri, 9 Jun 2006 12:44:08 -0600 (MDT)
Author: bigler
Date: Fri Jun 9 12:44:07 2006
New Revision: 1110
Added:
trunk/SwigInterface/FloatSpin.py
Modified:
trunk/Core/Geometry/Vector.h
trunk/Engine/Display/OpenGLDisplay.h
trunk/Model/Lights/HeadLight.h
trunk/Model/Lights/PointLight.h
trunk/SwigInterface/CMakeLists.txt
trunk/SwigInterface/manta.i
trunk/SwigInterface/wxManta.py
Log:
Core/Geometry/Vector.h
Added swig version of set element.
Engine/Display/OpenGLDisplay.h
Swig was getting confused with the MaybeSet sub class, so I just
ifdefed it out.
Model/Lights/HeadLight.h
Model/Lights/PointLight.h
Added get and set accessors.
SwigInterface/CMakeLists.txt
Copy FloatSpin.py over to where _manta was built.
SwigInterface/FloatSpin.py
wxPython extension for floating point spinners.
SwigInterface/manta.i
Rearange things to allow Light to be extended to have asPointLight
and asHeadLight casting functions.
SwigInterface/wxManta.py
Added LightFrame window that allows us to edit the light locations
and colors.
Modified: trunk/Core/Geometry/Vector.h
==============================================================================
--- trunk/Core/Geometry/Vector.h (original)
+++ trunk/Core/Geometry/Vector.h Fri Jun 9 12:44:07 2006
@@ -111,6 +111,9 @@
Real& __getitem__( int i ) {
return self->operator[](i);
}
+ void __setitem__(int i,Real val) {
+ self->operator[](i) = val;
+ }
}
#endif
// One might be tempted to add an "operator &" function, but
Modified: trunk/Engine/Display/OpenGLDisplay.h
==============================================================================
--- trunk/Engine/Display/OpenGLDisplay.h (original)
+++ trunk/Engine/Display/OpenGLDisplay.h Fri Jun 9 12:44:07 2006
@@ -49,6 +49,7 @@
PureOpenGLDisplay* ogl;
bool verbose;
+#ifndef SWIG
// Handy little class to test whether a variable has been set.
// This assumes that you only want to use the value if you called
// set.
@@ -70,6 +71,7 @@
};
MaybeSet<bool> single_buffered;
MaybeSet<bool> use_buffersubdata;
+#endif
bool displayFrameRate;
Modified: trunk/Model/Lights/HeadLight.h
==============================================================================
--- trunk/Model/Lights/HeadLight.h (original)
+++ trunk/Model/Lights/HeadLight.h Fri Jun 9 12:44:07 2006
@@ -9,16 +9,21 @@
namespace Manta {
class HeadLight : public Light {
public:
- HeadLight(const Real offset_, const Color &color_) : offset( offset_ ),
color( color_ ) { };
+ HeadLight(const Real offset_, const Color &color_)
+ : offset( offset_ ), color( color_ )
+ { };
virtual void preprocess(const PreprocessContext&) { /* Does Nothing. */
};
virtual void computeLight(RayPacket& destRays,
const RenderContext &context,
RayPacket& sourceRays) const;
+ Real getOffset() const { return offset; };
void setOffset( Real offset_ ) { offset = offset_; };
- Real getOffset() { return offset; };
+ Color getColor() const { return color; }
+ void setColor(const Color& new_c) { color = new_c; }
+
private:
Real offset;
Color color;
Modified: trunk/Model/Lights/PointLight.h
==============================================================================
--- trunk/Model/Lights/PointLight.h (original)
+++ trunk/Model/Lights/PointLight.h Fri Jun 9 12:44:07 2006
@@ -16,6 +16,14 @@
virtual void computeLight(RayPacket& rays, const RenderContext &context,
RayPacket& source) const;
+
+ // Accessors
+ Vector getPosition() const { return position; }
+ void setPosition(const Vector& new_p) { position = new_p; }
+
+ Color getColor() const { return color; }
+ void setColor(const Color& new_c) { color = new_c; }
+
private:
Vector position;
Color color;
Modified: trunk/SwigInterface/CMakeLists.txt
==============================================================================
--- trunk/SwigInterface/CMakeLists.txt (original)
+++ trunk/SwigInterface/CMakeLists.txt Fri Jun 9 12:44:07 2006
@@ -45,6 +45,17 @@
pycallback.i pycallback.cc pycallback.h)
SWIG_LINK_LIBRARIES(pycallback ${PYTHON_LIBRARIES})
+
+# Copy the manta.py swig compiled object to the lib directory.
+ADD_CUSTOM_COMMAND(
+ TARGET _manta
+ POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS -E copy ${CMAKE_CURRENT_SOURCE_DIR}/FloatSpin.py
+ ${PROJECT_BINARY_DIR}/lib/FloatSpin.py
+ COMMENT "Copying FloatSpin.py to ${PROJECT_BINARY_DIR}/lib/FloatSpin.py"
+ )
+
############################################################
# Load a scene from a python script.
SET(SCENE_PYTHON 0 CACHE BOOL "Load a scene from a python script..")
Added: trunk/SwigInterface/FloatSpin.py
==============================================================================
--- (empty file)
+++ trunk/SwigInterface/FloatSpin.py Fri Jun 9 12:44:07 2006
@@ -0,0 +1,1305 @@
+#
--------------------------------------------------------------------------- #
+# FLOATSPIN Control wxPython IMPLEMENTATION
+# Python Code By:
+#
+# Andrea Gavana, @ 16 Nov 2005
+# Latest Revision: 16 Nov 2005, 21.50 CET
+#
+#
+# TODO List/Caveats
+#
+# 1. Ay Idea?
+#
+# For All Kind Of Problems, Requests Of Enhancements And Bug Reports, Please
+# Write To Me At:
+#
+# andrea.gavana@agip.it
+# andrea_gavan@tin.it
+#
+# Or, Obviously, To The wxPython Mailing List!!!
+#
+#
+# End Of Comments
+#
--------------------------------------------------------------------------- #
+
+
+"""
+Description:
+
+FloatSpin Implements A Floating Point SpinCtrl. It Is Built Using A Custom
+wx.PyControl, Composed By A wx.TextCtrl And A wx.SpinButton. In Order To
+Correctly Handle Floating Points Numbers Without Rounding Errors Or Non-Exact
+Floating Point Representations, FloatSpin Uses The Great FixedPoint Class
+From Tim Peters.
+
+What You Can Do:
+
+- Set The Number Of Representative Digits For Your Floating Point Numbers;
+- Set The Floating Point Format (%f, %F, %e, %E, %g, %G);
+- Set The Increment Of Every EVT_FLOATSPIN Event;
+- Set Minimum, Maximum Values For FloatSpin As Well As Its Range;
+- Change Font And Colour For The Underline wx.TextCtrl.
+
+
+Events Catched:
+
+FloatSpin Catched 3 Different Types Of Events:
+
+1) Spin Events: Events Generated By Spinning Up/Down The SpinButton;
+2) Char Events: Playing With Up/Down Arrows Of The Keyboard Increase/Decrease
+ The Value Of FloatSpin;
+3) Mouse Wheel Event: Using The Wheel Will Change The Value Of FloatSpin.
+
+In Addition, There Are Some Other Functionalities:
+
+It Remembers The Initial Value As A Default Value, Call SetToDefaultValue, Or
+Press <ESC> To Return To It
+
+Shift + Arrow = 2 * Increment (Or Shift + Mouse Wheel)
+Ctrl + Arrow = 10 * Increment (Or Ctrl + Mouse Wheel)
+Alt + Arrow = 100 * Increment (Or Alt + Mouse Wheel)
+
+Combinations Of Shift, Ctrl, Alt Increment The FloatSpin Value By The Product
+Of The Factors;
+
+PgUp & PgDn = 10 * Increment * The Product Of The Shift, Ctrl, Alt Factors;
+
+<SPACE> Sets The Control's Value To It's Last Valid State.
+
+
+Usage:
+
+FloatSpin Construction Can Be Summarized As Follows:
+
+FloatSpin.__init__(self, parent, id, pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=0, value=0.0, min=0.0,
max=100.0,
+ increment=1.0, digits=-1, extrastyle=FS_LEFT,
+ name="FloatSpin")
+
+Where:
+
+- value: Is The Current Value For FloatSpin;
+- min: The Minimum Value;
+- max: The Maximum Value;
+- increment: The Increment For Every EVT_FLOATSPIN Events;
+- digits: Number Of Representative Digits For Your Floating Point Numbers;
+- extrastyle: One Of The Following:
+ a) FS_LEFT: Align Underline wx.TextCtrl Left;
+ b) FS_RIGHT: Align Underline wx.TextCtrl Right;
+ c) FS_CENTER: Align Underline wx.TextCtrl Center;
+ Plus The Possibility To Use FS_READONLY, That Makes The Underline
wx.TextCtrl
+ Read-Only (No Edits Possible).
+
+See FloatSpin __init__() Method For The Definition Of Non Standard (Non
+wxPython) Parameters.
+
+FloatSpin Control Is Freeware And Distributed Under The wxPython License.
+
+Latest Revision: Andrea Gavana @ 16 Nov 2005, 21.50 CET
+
+"""
+
+
+#----------------------------------------------------------------------
+# Beginning Of FLOATSPIN wxPython Code
+#----------------------------------------------------------------------
+
+import wx
+
+# Set The Styles For The Underline wx.TextCtrl
+FS_READONLY = 1
+FS_LEFT = 2
+FS_CENTRE = 4
+FS_RIGHT = 8
+
+# Define The FloatSpin Event
+wxEVT_FLOATSPIN = wx.NewEventType()
+
+#-----------------------------------#
+# FloatSpinEvent
+#-----------------------------------#
+
+EVT_FLOATSPIN = wx.PyEventBinder(wxEVT_FLOATSPIN, 1)
+
+#
---------------------------------------------------------------------------- #
+# Class FloatSpinEvent
+#
---------------------------------------------------------------------------- #
+
+class FloatSpinEvent(wx.PyCommandEvent):
+ """ This Event Will Be Sent When A EVT_FLOATSPIN Event Is Mapped In The
Parent. """
+
+ def __init__(self, eventType, id=1, nSel=-1, nOldSel=-1):
+ """ Default Class Constructor. """
+
+ wx.PyCommandEvent.__init__(self, eventType, id)
+ self._eventType = eventType
+
+
+ def SetPosition(self, pos):
+ """ Sets Event Position. """
+
+ self._position = pos
+
+
+ def GetPosition(self):
+ """ Returns Event Position. """
+
+ return self._position
+
+
+#----------------------------------------------------------------------------
+# FloatTextCtrl
+#----------------------------------------------------------------------------
+
+
+class FloatTextCtrl(wx.TextCtrl):
+
+ def __init__(self, parent, id=wx.ID_ANY, value="",
pos=wx.DefaultPosition,
+ size=wx.DefaultSize, style=wx.TE_NOHIDESEL |
wx.TE_PROCESS_ENTER,
+ validator=wx.DefaultValidator,
+ name=wx.TextCtrlNameStr):
+ """
+ Default Class Constructor.
+ Used Internally. Do Not Call Directly This Class In Your Code!
+ """
+
+ wx.TextCtrl.__init__(self, parent, id, value, pos, size, style,
validator, name)
+
+ self._parent = parent
+ self.Bind(wx.EVT_WINDOW_DESTROY, self.OnDestroy)
+ self.Bind(wx.EVT_CHAR, self.OnChar)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+
+
+ def OnDestroy(self, event):
+ """ Tries To Correctly Handle The Control Destruction Under MSW. """
+
+ if self._parent:
+ self._parent._textctrl = None
+ self._parent = None
+
+
+ def OnChar(self, event):
+ """ Handles The wx.EVT_CHAR Event By Passing It To FloatSpin. """
+
+ if self._parent:
+ self._parent.OnChar(event)
+
+
+ def OnKillFocus(self, event):
+ """ Synchronize The wx.SpinButton And The wx.TextCtrl When Focus Is
Lost. """
+
+ if self._parent:
+ self._parent.SyncSpinToText(True)
+
+ event.Skip()
+
+
+#----------------------------------------------------------------------------
#
+# FloatSpin
+# This Is The Main Class Implementation
+#
---------------------------------------------------------------------------- #
+
+class FloatSpin(wx.PyControl):
+
+ def __init__(self, parent, id=wx.ID_ANY, pos=wx.DefaultPosition,
+ size=(95,-1), style=0, value=0.0, min=0.0, max=100.0,
+ increment=1.0, digits=-1, extrastyle=FS_LEFT,
+ name="FloatSpin"):
+ """
+ Default Class Constructor. Non-Default Parameters Are:
+
+ - value: Is The Current Value For FloatSpin;
+ - min: The Minimum Value;
+ - max: The Maximum Value;
+ - increment: The Increment For Every EVT_FLOATSPIN Events;
+ - digits: Number Of Representative Digits For Your Floating Point
Numbers;
+ - extrastyle: One Of The Following:
+ a) FS_LEFT: Align Underline wx.TextCtrl Left;
+ b) FS_RIGHT: Align Underline wx.TextCtrl Right;
+ c) FS_CENTER: Align Underline wx.TextCtrl Center;
+ Plus The Possibility To Use FS_READONLY, That Makes The Underline
wx.TextCtrl
+ Read-Only (No Edits Possible).
+
+ """
+
+ wx.PyControl.__init__(self, parent, id, pos, size,
style|wx.NO_BORDER|
+ wx.NO_FULL_REPAINT_ON_RESIZE |
wx.CLIP_CHILDREN,
+ wx.DefaultValidator, name)
+
+ self._min = FixedPoint(str(min), 20)
+ self._max = FixedPoint(str(max), 20)
+
+ if (min <= max):
+ if value < min:
+ value = min
+ elif value > max:
+ value = max
+
+
+ self._value = FixedPoint(str(value), 20)
+ self._defaultvalue = self._value
+ self._increment = FixedPoint(str(increment), 20)
+ self._spinmodifier = FixedPoint(str(1.0), 20)
+ self._digits = digits
+ self._snapticks = False
+ self._spinbutton = None
+ self._textctrl = None
+ self._spinctrl_bestsize = wx.Size(-999, -999)
+
+ self.SetLabel(name)
+ self.SetBackgroundColour(parent.GetBackgroundColour())
+ self.SetForegroundColour(parent.GetForegroundColour())
+
+ width = size[0]
+ height = size[1]
+ best_size = self.DoGetBestSize()
+
+ if width == -1:
+ width = best_size.GetWidth()
+ if height == -1:
+ height = best_size.GetHeight()
+
+ self.SetBestSize((width, height))
+
+ self._validkeycode = [43, 45, 46, 69, 101, 127, 314]
+ self._validkeycode.extend(range(48, 58))
+ self._validkeycode.extend([wx.WXK_RETURN, wx.WXK_TAB, wx.WXK_BACK,
+ wx.WXK_LEFT, wx.WXK_RIGHT])
+
+ self._spinbutton = wx.SpinButton(self, wx.ID_ANY, wx.DefaultPosition,
+ size=(-1, height),
+ style=wx.SP_ARROW_KEYS |
wx.SP_VERTICAL |
+ wx.SP_WRAP)
+
+ txtstyle = wx.TE_NOHIDESEL | wx.TE_PROCESS_ENTER
+
+ if extrastyle & FS_RIGHT:
+ txtstyle = txtstyle | wx.TE_RIGHT
+ elif extrastyle & FS_CENTRE:
+ txtstyle = txtstyle | wx.TE_CENTER
+
+ if extrastyle & FS_READONLY:
+ txtstyle = txtstyle | wx.TE_READONLY
+
+ self._textctrl = FloatTextCtrl(self, wx.ID_ANY, str(self._value),
+ wx.DefaultPosition,
+
(width-self._spinbutton.GetSize().GetWidth(), height),
+ txtstyle)
+
+ self._mainsizer = wx.BoxSizer(wx.HORIZONTAL)
+ self._mainsizer.Add(self._textctrl, 0)
+ self._mainsizer.Add(self._spinbutton, 0)
+ self.SetSizer(self._mainsizer)
+ self._mainsizer.Layout()
+
+ self.SetFormat()
+ self.SetDigits(digits)
+
+ # set the value here without generating an event
+
+ strs = ("%100." + str(self._digits) +
self._textformat[1])%self._value
+
+ strs = strs.strip()
+ strs = self.ReplaceDoubleZero(strs)
+
+ self._textctrl.SetValue(strs)
+
+ self.Bind(wx.EVT_SPIN_UP, self.OnSpinUp)
+ self.Bind(wx.EVT_SPIN_DOWN, self.OnSpinDown)
+ self.Bind(wx.EVT_TEXT_ENTER, self.OnTextEnter)
+ self.Bind(wx.EVT_SET_FOCUS, self.OnFocus)
+ self.Bind(wx.EVT_KILL_FOCUS, self.OnKillFocus)
+ self.Bind(wx.EVT_MOUSEWHEEL, self.OnMouseWheel)
+ self._spinbutton.Bind(wx.EVT_LEFT_DOWN, self.OnSpinMouseDown)
+
+
+ def OnDestroy(self, event):
+ """ Tries To Correctly Handle The Control Destruction Under MSW. """
+
+ # Null This Since MSW Sends KILL_FOCUS On Deletion
+ if self._textctrl:
+ self._textctrl._parent = None
+ self._textctrl.Destroy()
+ self._textctrl = None
+
+ self._spinbutton.Destroy()
+ self._spinbutton = None
+
+
+ def DoGetBestSize(self):
+ """ Calculates The Best Size For FloatSpin. """
+
+ if self._spinctrl_bestsize.x == -999:
+
+ spin = wx.SpinCtrl(self, -1)
+ self._spinctrl_bestsize = spin.GetBestSize()
+
+ # oops something went wrong, set to reasonable value
+ if self._spinctrl_bestsize.GetWidth() < 20:
+ self._spinctrl_bestsize.SetWidth(95)
+ if self._spinctrl_bestsize.GetHeight() < 10:
+ self._spinctrl_bestsize.SetHeight(22)
+
+ spin.Destroy()
+
+ return self._spinctrl_bestsize
+
+
+ def DoSendEvent(self):
+ """ Send The Event To The Parent. """
+
+ event = wx.CommandEvent(wx.wxEVT_COMMAND_SPINCTRL_UPDATED,
self.GetId())
+ event.SetEventObject(self)
+ event.SetInt(int(self._value + 0.5))
+
+ if self._textctrl:
+ event.SetString(self._textctrl.GetValue())
+
+ self.GetEventHandler().ProcessEvent(event)
+
+ eventOut = FloatSpinEvent(wxEVT_FLOATSPIN, self.GetId())
+ eventOut.SetPosition(int(self._value + 0.5))
+ eventOut.SetEventObject(self)
+ self.GetEventHandler().ProcessEvent(eventOut)
+
+
+ def OnSpinMouseDown(self, event):
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.m_shiftDown:
+ modifier = modifier*2.0
+ if event.m_controlDown:
+ modifier = modifier*10.0
+ if event.m_altDown:
+ modifier = modifier*100.0
+
+ self._spinmodifier = modifier
+
+ event.Skip()
+
+
+ def OnSpinUp(self, event):
+ """ Handles The wx.EVT_SPIN_UP For FloatSpin. """
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if self.InRange(self._value + self._increment*self._spinmodifier):
+
+ self._value = self._value + self._increment*self._spinmodifier
+ self.SetValue(self._value)
+ self.DoSendEvent()
+
+
+ def OnSpinDown(self, event):
+ """ Handles The wx.EVT_SPIN_DOWN For FloatSpin. """
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if self.InRange(self._value - self._increment*self._spinmodifier):
+
+ self._value = self._value - self._increment*self._spinmodifier
+ self.SetValue(self._value)
+ self.DoSendEvent()
+
+
+ def OnTextEnter(self, event):
+ """ Handles The wx.EVT_TEXT_ENTER For The Underline wx.TextCtrl. """
+
+ self.SyncSpinToText(True)
+ event.Skip()
+
+
+ def OnChar(self, event):
+ """ Handles The wx.EVT_CHAR For The Underline wx.TextCtrl. """
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.m_shiftDown:
+ modifier = modifier*2.0
+ if event.m_controlDown:
+ modifier = modifier*10.0
+ if event.m_altDown:
+ modifier = modifier*100.0
+
+ keycode = event.GetKeyCode()
+
+ if keycode == wx.WXK_UP:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value + self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_DOWN:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value - self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_PRIOR:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value + 10.0*self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_NEXT:
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ self.SetValue(self._value - 10.0*self._increment*modifier)
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_SPACE:
+
+ self.SetValue(self._value)
+ event.Skip(False)
+
+ elif keycode == wx.WXK_ESCAPE:
+
+ self.SetToDefaultValue()
+ self.DoSendEvent()
+
+ elif keycode == wx.WXK_TAB:
+
+ new_event = wx.NavigationKeyEvent()
+ new_event.SetEventObject(self.GetParent())
+ new_event.SetDirection(not event.ShiftDown())
+ # CTRL-TAB changes the (parent) window, i.e. switch notebook page
+ new_event.SetWindowChange(event.ControlDown())
+ new_event.SetCurrentFocus(self)
+ self.GetParent().GetEventHandler().ProcessEvent(new_event)
+
+ else:
+ if keycode not in self._validkeycode:
+ return
+
+ event.Skip()
+
+
+ def OnMouseWheel(self, event):
+ """ Handles The wx.EVT_MOUSEWHEEL For FloatSpin. """
+
+ modifier = FixedPoint(str(1.0), 20)
+ if event.m_shiftDown:
+ modifier = modifier*2.0
+ if event.m_controlDown:
+ modifier = modifier*10.0
+ if event.m_altDown:
+ modifier = modifier*100.0
+
+ if self._textctrl and self._textctrl.IsModified():
+ self.SyncSpinToText(False)
+
+ if event.GetWheelRotation() > 0:
+ self.SetValue(self._value + self._increment*modifier)
+ self.DoSendEvent()
+
+ else:
+
+ self.SetValue(self._value - self._increment*modifier)
+ self.DoSendEvent()
+
+
+ def ReplaceDoubleZero(self, strs):
+ """ Replaces The (Somewhat) Python Ugly '+e000' With +e00. """
+
+ if self._textformat not in ["%g", "%e", "%E", "%G"]:
+ return strs
+
+ if strs.find("e+00") >= 0:
+ strs = strs.replace("e+00", "e+0")
+ elif strs.find("e-00") >= 0:
+ strs = strs.replace("e-00", "e-0")
+ elif strs.find("E+00") >= 0:
+ strs = strs.replace("E+00", "E+0")
+ elif strs.find("E-00") >= 0:
+ strs = strs.replace("E-00", "E-0")
+
+ return strs
+
+
+ def SetValue(self, value):
+ """ Sets The FloatSpin Value. """
+
+ if not self._textctrl or not self.InRange(value):
+ return
+
+ if self._snapticks and self._increment != 0.0:
+
+ finite, snap_value = self.IsFinite(value)
+
+ if not finite: # FIXME What To Do About A Failure?
+
+ if (snap_value - floor(snap_value) < ceil(snap_value) -
snap_value):
+ value = self._defaultvalue +
floor(snap_value)*self._increment
+ else:
+ value = self._defaultvalue +
ceil(snap_value)*self._increment
+
+ strs = ("%100." + str(self._digits) + self._textformat[1])%value
+ strs = strs.strip()
+ strs = self.ReplaceDoubleZero(strs)
+
+ if value != self._value or strs != self._textctrl.GetValue():
+
+ self._textctrl.SetValue(strs)
+ self._textctrl.DiscardEdits()
+ self._value = value
+
+
+ def GetValue(self):
+ """ Returns The FloatSpin Value. """
+
+ return self._value
+
+
+ def SetRange(self, min_val, max_val):
+ """
+ Set The Allowed Range, If max_val < min_val Then No Range And All
+ Values Are Allowed.
+ """
+
+ self._min = FixedPoint(str(min_val), 20)
+ self._max = FixedPoint(str(max_val), 20)
+
+ if self.HasRange():
+ if self._value > self._max:
+ self.SetValue(self._max)
+ elif self._value < self._min:
+ self.SetValue(self._min)
+
+
+ def SetIncrement(self, increment):
+ """ Sets The Increment For Every EVT_FLOATSPIN Event. """
+
+ if increment < 1./10.0**self._digits:
+ raise "\nERROR: Increment Should Be Greater Or Equal To
1/(10**digits)."
+
+ self._increment = FixedPoint(str(increment), 20)
+ self.SetValue(self._value)
+
+
+ def GetIncrement(self):
+ """ Returns The Increment For Every EVT_FLOATSPIN Event. """
+
+ return self._increment
+
+
+ def SetDigits(self, digits=-1):
+ """
+ Sets The Number Of Digits To Show. If digits < 0, FloatSpin Tries To
+ Calculate The Best Number Of Digits Based On Input __init__ Values.
+ """
+
+ if digits < 0:
+ incr = str(self._increment)
+ if incr.find(".") < 0:
+ digits = 0
+ else:
+ digits = len(incr[incr.find(".")+1:])
+
+ self._digits = digits
+
+ self.SetValue(self._value)
+
+
+ def GetDigits(self):
+ """ Returns The Number Of Digits Shown. """
+
+ return self._digits
+
+
+ def SetFormat(self, fmt="%f"):
+ """ Set The String Format To Use. """
+
+ if fmt not in ["%f", "%g", "%e", "%E", "%F", "%G"]:
+ raise '\nERROR: Bad Float Number Format: ' + repr(fmt) + '. It
Should Be ' \
+ 'One Of "%f", "%g", "%e", "%E", "%F", "%G"'
+
+ self._textformat = fmt
+
+ if self._digits < 0:
+ self.SetDigits()
+
+ self.SetValue(self._value)
+
+
+ def GetFormat(self):
+ """ Returns The String Format In Use. """
+
+ return self._textformat
+
+
+ def SetDefaultValue(self, defaultvalue):
+ """ Sets The FloatSpin Default Value. """
+
+ if self.InRange(defaultvalue):
+ self._defaultvalue = FixedPoint(str(defaultvalue), 20)
+
+
+ def GetDefaultValue(self):
+ """ Returns The FloatSpin Default Value. """
+
+ return self._defaultvalue
+
+
+ def IsDefaultValue(self):
+ """ Returns Whether The Current Value Is The Default Value Or Not.
"""
+
+ return self._value == self._defaultvalue
+
+
+ def SetToDefaultValue(self):
+ """ Sets FloatSpin Value To Its Default Value. """
+
+ self.SetValue(self._defaultvalue)
+
+
+ def SetSnapToTicks(self, forceticks=True):
+ """
+ Force The Value To Always Be Divisible By The Increment. Initially
False.
+ This Uses The Default Value As The Basis, You Will Get Strange
Results
+ For Very Large Differences Between The Current Value And Default
Value
+ When The Increment Is Very Small.
+ """
+
+ if self._snapticks != forceticks:
+
+ self._snapticks = forceticks
+ self.SetValue(self._value)
+
+
+ def GetSnapToTicks(self):
+ """ Returns Whether The Snap To Ticks Option Is Active Or Not. """
+
+ return self._snapticks
+
+
+ def OnFocus(self, event):
+ """ Handles The wx.EVT_SET_FOCUS Event For FloatSpin. """
+
+ if self._textctrl:
+ self._textctrl.SetFocus()
+
+ event.Skip()
+
+
+ def OnKillFocus(self, event):
+ """ Handles The wx.EVT_KILL_FOCUS Event For FloatSpin. """
+
+ self.SyncSpinToText(True)
+ event.Skip()
+
+
+ def SyncSpinToText(self, send_event=True, force_valid=True):
+ """ Synchronize The Underline wx.TextCtrl With wx.SpinButton. """
+
+ if not self._textctrl:
+ return
+
+ curr = self._textctrl.GetValue()
+ curr = curr.strip()
+
+ if curr:
+ try:
+ curro = float(curr)
+ curr = FixedPoint(curr, 20)
+ except:
+ self.SetValue(self._value)
+ return
+
+ if force_valid or not self.HasRange() or self.InRange(curr):
+
+ if force_valid and self.HasRange():
+
+ if curr > self.GetMax():
+ curr = self.GetMax()
+ elif curr < self.GetMin():
+ curr = self.GetMin()
+
+ if self._value != curr:
+ self.SetValue(curr)
+
+ if send_event:
+ self.DoSendEvent()
+
+ elif force_valid:
+
+ # textctrl is out of sync, discard and reset
+ self.SetValue(self.GetValue())
+
+
+ def SetFont(self, font=None):
+ """ Set The Underline wx.TextCtrl Font. """
+
+ if font is None:
+ font = wx.SystemSettings_GetFont(wx.SYS_DEFAULT_GUI_FONT)
+
+ if not self._textctrl:
+ return False
+
+ return self._textctrl.SetFont(font)
+
+
+ def GetFont(self):
+ """ Returns The Underline wx.TextCtrl Font. """
+
+ if not self._textctrl:
+ return self.GetFont()
+
+ return self._textctrl.GetFont()
+
+
+ def GetMin(self):
+ """ Returns The Minimum Value For FloatSpin. """
+
+ return self._min
+
+
+ def GetMax(self):
+ """ Returns The Maximum Value For FloatSpin. """
+
+ return self._max
+
+
+ def HasRange(self):
+ """ Returns Whether FloatSpin Has A Range Or Not. """
+
+ return self._min <= self._max
+
+
+ def InRange(self, value):
+ """ Returns Whether A Value Is Inside FloatSpin Range. """
+
+ return not self.HasRange() or (value >= self._min and value <=
self._max)
+
+
+ def GetTextCtrl(self):
+ """ Returns The Underline wx.TextCtrl. """
+
+ return self._textctrl
+
+
+ def IsFinite(self, value):
+ """ Tries To Determine If A Value Is Finite Or Infinite/NaN. """
+
+ try:
+ snap_value = (value - self._defaultvalue)/self._increment
+ finite = True
+ except:
+ finite = False
+ snap_value = None
+
+ return finite, snap_value
+
+
+
+# Class FixedPoint, version 0.0.4.
+# Released to the public domain 28-Mar-2001,
+# by Tim Peters (tim.one@home.com).
+
+# Provided as-is; use at your own risk; no warranty; no promises; enjoy!
+
+"""
+FixedPoint objects support decimal arithmetic with a fixed number of
+digits (called the object's precision) after the decimal point. The
+number of digits before the decimal point is variable & unbounded.
+
+The precision is user-settable on a per-object basis when a FixedPoint
+is constructed, and may vary across FixedPoint objects. The precision
+may also be changed after construction via FixedPoint.set_precision(p).
+Note that if the precision of a FixedPoint is reduced via set_precision,
+information may be lost to rounding.
+
+>>> x = FixedPoint("5.55") # precision defaults to 2
+>>> print x
+5.55
+>>> x.set_precision(1) # round to one fraction digit
+>>> print x
+5.6
+>>> print FixedPoint("5.55", 1) # same thing setting to 1 in constructor
+5.6
+>>> repr(x) # returns constructor string that reproduces object exactly
+"FixedPoint('5.6', 1)"
+>>>
+
+When FixedPoint objects of different precision are combined via + - * /,
+the result is computed to the larger of the inputs' precisions, which also
+becomes the precision of the resulting FixedPoint object.
+
+>>> print FixedPoint("3.42") + FixedPoint("100.005", 3)
+103.425
+>>>
+
+When a FixedPoint is combined with other numeric types (ints, floats,
+strings representing a number) via + - * /, then similarly the computation
+is carried out using-- and the result inherits --the FixedPoint's
+precision.
+
+>>> print FixedPoint(1) / 7
+0.14
+>>> print FixedPoint(1, 30) / 7
+0.142857142857142857142857142857
+>>>
+
+The string produced by str(x) (implictly invoked by "print") always
+contains at least one digit before the decimal point, followed by a
+decimal point, followed by exactly x.get_precision() digits. If x is
+negative, str(x)[0] == "-".
+
+The FixedPoint constructor can be passed an int, long, string, float,
+FixedPoint, or any object convertible to a float via float() or to a
+long via long(). Passing a precision is optional; if specified, the
+precision must be a non-negative int. There is no inherent limit on
+the size of the precision, but if very very large you'll probably run
+out of memory.
+
+Note that conversion of floats to FixedPoint can be surprising, and
+should be avoided whenever possible. Conversion from string is exact
+(up to final rounding to the requested precision), so is greatly
+preferred.
+
+>>> print FixedPoint(1.1e30)
+1099999999999999993725589651456.00
+>>> print FixedPoint("1.1e30")
+1100000000000000000000000000000.00
+>>>
+
+The following Python operators and functions accept FixedPoints in the
+expected ways:
+
+ binary + - * / % divmod
+ with auto-coercion of other types to FixedPoint.
+ + - % divmod of FixedPoints are always exact.
+ * / of FixedPoints may lose information to rounding, in
+ which case the result is the infinitely precise answer
+ rounded to the result's precision.
+ divmod(x, y) returns (q, r) where q is a long equal to
+ floor(x/y) as if x/y were computed to infinite precision,
+ and r is a FixedPoint equal to x - q * y; no information
+ is lost. Note that q has the sign of y, and abs(r) < abs(y).
+ unary -
+ == != < > <= >= cmp
+ min max
+ float int long (int and long truncate)
+ abs
+ str repr
+ hash
+ use as dict keys
+ use as boolean (e.g. "if some_FixedPoint:" -- true iff not zero)
+
+Methods unique to FixedPoints:
+ .copy() return new FixedPoint with same value
+ .frac() long(x) + x.frac() == x
+ .get_precision()
+ .set_precision(p)
+"""
+
+# 28-Mar-01 ver 0.0,4
+# Use repr() instead of str() inside __str__, because str(long) changed
+# since this was first written (used to produce trailing "L", doesn't
+# now).
+#
+# 09-May-99 ver 0,0,3
+# Repaired __sub__(FixedPoint, string); was blowing up.
+# Much more careful conversion of float (now best possible).
+# Implemented exact % and divmod.
+#
+# 14-Oct-98 ver 0,0,2
+# Added int, long, frac. Beefed up docs. Removed DECIMAL_POINT
+# and MINUS_SIGN globals to discourage bloating this class instead
+# of writing formatting wrapper classes (or subclasses)
+#
+# 11-Oct-98 ver 0,0,1
+# posted to c.l.py
+
+__version__ = 0, 0, 4
+
+# The default value for the number of decimal digits carried after the
+# decimal point. This only has effect at compile-time.
+DEFAULT_PRECISION = 2
+
+class FixedPoint:
+
+ # the exact value is self.n / 10**self.p;
+ # self.n is a long; self.p is an int
+
+ def __init__(self, value=0, precision=DEFAULT_PRECISION):
+ self.n = self.p = 0
+ self.set_precision(precision)
+ p = self.p
+
+ if isinstance(value, type("42.3e5")):
+ n, exp = _string2exact(value)
+ # exact value is n*10**exp = n*10**(exp+p)/10**p
+ effective_exp = exp + p
+ if effective_exp > 0:
+ n = n * _tento(effective_exp)
+ elif effective_exp < 0:
+ n = _roundquotient(n, _tento(-effective_exp))
+ self.n = n
+ return
+
+ if isinstance(value, type(42)) or isinstance(value, type(42L)):
+ self.n = long(value) * _tento(p)
+ return
+
+ if isinstance(value, FixedPoint):
+ temp = value.copy()
+ temp.set_precision(p)
+ self.n, self.p = temp.n, temp.p
+ return
+
+ if isinstance(value, type(42.0)):
+ # XXX ignoring infinities and NaNs and overflows for now
+ import math
+ f, e = math.frexp(abs(value))
+ assert f == 0 or 0.5 <= f < 1.0
+ # |value| = f * 2**e exactly
+
+ # Suck up CHUNK bits at a time; 28 is enough so that we suck
+ # up all bits in 2 iterations for all known binary double-
+ # precision formats, and small enough to fit in an int.
+ CHUNK = 28
+ top = 0L
+ # invariant: |value| = (top + f) * 2**e exactly
+ while f:
+ f = math.ldexp(f, CHUNK)
+ digit = int(f)
+ assert digit >> CHUNK == 0
+ top = (top << CHUNK) | digit
+ f = f - digit
+ assert 0.0 <= f < 1.0
+ e = e - CHUNK
+
+ # now |value| = top * 2**e exactly
+ # want n such that n / 10**p = top * 2**e, or
+ # n = top * 10**p * 2**e
+ top = top * _tento(p)
+ if e >= 0:
+ n = top << e
+ else:
+ n = _roundquotient(top, 1L << -e)
+ if value < 0:
+ n = -n
+ self.n = n
+ return
+
+ if isinstance(value, type(42-42j)):
+ raise TypeError("can't convert complex to FixedPoint: " +
+ `value`)
+
+ # can we coerce to a float?
+ yes = 1
+ try:
+ asfloat = float(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(asfloat, p)
+ return
+
+ # similarly for long
+ yes = 1
+ try:
+ aslong = long(value)
+ except:
+ yes = 0
+ if yes:
+ self.__init__(aslong, p)
+ return
+
+ raise TypeError("can't convert to FixedPoint: " + `value`)
+
+ def get_precision(self):
+ """Return the precision of this FixedPoint.
+
+ The precision is the number of decimal digits carried after
+ the decimal point, and is an int >= 0.
+ """
+
+ return self.p
+
+ def set_precision(self, precision=DEFAULT_PRECISION):
+ """Change the precision carried by this FixedPoint to p.
+
+ precision must be an int >= 0, and defaults to
+ DEFAULT_PRECISION.
+
+ If precision is less than this FixedPoint's current precision,
+ information may be lost to rounding.
+ """
+
+ try:
+ p = int(precision)
+ except:
+ raise TypeError("precision not convertable to int: " +
+ `precision`)
+ if p < 0:
+ raise ValueError("precision must be >= 0: " + `precision`)
+
+ if p > self.p:
+ self.n = self.n * _tento(p - self.p)
+ elif p < self.p:
+ self.n = _roundquotient(self.n, _tento(self.p - p))
+ self.p = p
+
+ def __str__(self):
+ n, p = self.n, self.p
+ i, f = divmod(abs(n), _tento(p))
+ if p:
+ frac = repr(f)[:-1]
+ frac = "0" * (p - len(frac)) + frac
+ else:
+ frac = ""
+ return "-"[:n<0] + \
+ repr(i)[:-1] + \
+ "." + frac
+
+ def __repr__(self):
+ return "FixedPoint" + `(str(self), self.p)`
+
+ def copy(self):
+ return _mkFP(self.n, self.p)
+
+ __copy__ = __deepcopy__ = copy
+
+ def __cmp__(self, other):
+ xn, yn, p = _norm(self, other)
+ return cmp(xn, yn)
+
+ def __hash__(self):
+ # caution! == values must have equal hashes, and a FixedPoint
+ # is essentially a rational in unnormalized form. There's
+ # really no choice here but to normalize it, so hash is
+ # potentially expensive.
+ n, p = self.__reduce()
+
+ # Obscurity: if the value is an exact integer, p will be 0 now,
+ # so the hash expression reduces to hash(n). So FixedPoints
+ # that happen to be exact integers hash to the same things as
+ # their int or long equivalents. This is Good. But if a
+ # FixedPoint happens to have a value exactly representable as
+ # a float, their hashes may differ. This is a teensy bit Bad.
+ return hash(n) ^ hash(p)
+
+ def __nonzero__(self):
+ return self.n != 0
+
+ def __neg__(self):
+ return _mkFP(-self.n, self.p)
+
+ def __abs__(self):
+ if self.n >= 0:
+ return self.copy()
+ else:
+ return -self
+
+ def __add__(self, other):
+ n1, n2, p = _norm(self, other)
+ # n1/10**p + n2/10**p = (n1+n2)/10**p
+ return _mkFP(n1 + n2, p)
+
+ __radd__ = __add__
+
+ def __sub__(self, other):
+ if not isinstance(other, FixedPoint):
+ other = FixedPoint(other, self.p)
+ return self.__add__(-other)
+
+ def __rsub__(self, other):
+ return (-self) + other
+
+ def __mul__(self, other):
+ n1, n2, p = _norm(self, other)
+ # n1/10**p * n2/10**p = (n1*n2/10**p)/10**p
+ return _mkFP(_roundquotient(n1 * n2, _tento(p)), p)
+
+ __rmul__ = __mul__
+
+ def __div__(self, other):
+ n1, n2, p = _norm(self, other)
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint division")
+ if n2 < 0:
+ n1, n2 = -n1, -n2
+ # n1/10**p / (n2/10**p) = n1/n2 = (n1*10**p/n2)/10**p
+ return _mkFP(_roundquotient(n1 * _tento(p), n2), p)
+
+ def __rdiv__(self, other):
+ n1, n2, p = _norm(self, other)
+ return _mkFP(n2, p) / self
+
+ def __divmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ if n2 == 0:
+ raise ZeroDivisionError("FixedPoint modulo")
+ # floor((n1/10**p)/(n2*10**p)) = floor(n1/n2)
+ q = n1 / n2
+ # n1/10**p - q * n2/10**p = (n1 - q * n2)/10**p
+ return q, _mkFP(n1 - q * n2, p)
+
+ def __rdivmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ return divmod(_mkFP(n2, p), self)
+
+ def __mod__(self, other):
+ return self.__divmod__(other)[1]
+
+ def __rmod__(self, other):
+ n1, n2, p = _norm(self, other)
+ return _mkFP(n2, p).__mod__(self)
+
+ # caution! float can lose precision
+ def __float__(self):
+ n, p = self.__reduce()
+ return float(n) / float(_tento(p))
+
+ # XXX should this round instead?
+ # XXX note e.g. long(-1.9) == -1L and long(1.9) == 1L in Python
+ # XXX note that __int__ inherits whatever __long__ does,
+ # XXX and .frac() is affected too
+ def __long__(self):
+ answer = abs(self.n) / _tento(self.p)
+ if self.n < 0:
+ answer = -answer
+ return answer
+
+ def __int__(self):
+ return int(self.__long__())
+
+ def frac(self):
+ """Return fractional portion as a FixedPoint.
+
+ x.frac() + long(x) == x
+ """
+ return self - long(self)
+
+ # return n, p s.t. self == n/10**p and n % 10 != 0
+ def __reduce(self):
+ n, p = self.n, self.p
+ if n == 0:
+ p = 0
+ while p and n % 10 == 0:
+ p = p - 1
+ n = n / 10
+ return n, p
+
+# return 10L**n
+
+def _tento(n, cache={}):
+ try:
+ return cache[n]
+ except KeyError:
+ answer = cache[n] = 10L ** n
+ return answer
+
+# return xn, yn, p s.t.
+# p = max(x.p, y.p)
+# x = xn / 10**p
+# y = yn / 10**p
+#
+# x must be FixedPoint to begin with; if y is not FixedPoint,
+# it inherits its precision from x.
+#
+# Note that this is called a lot, so default-arg tricks are helpful.
+
+def _norm(x, y, isinstance=isinstance, FixedPoint=FixedPoint,
+ _tento=_tento):
+ assert isinstance(x, FixedPoint)
+ if not isinstance(y, FixedPoint):
+ y = FixedPoint(y, x.p)
+ xn, yn = x.n, y.n
+ xp, yp = x.p, y.p
+ if xp > yp:
+ yn = yn * _tento(xp - yp)
+ p = xp
+ elif xp < yp:
+ xn = xn * _tento(yp - xp)
+ p = yp
+ else:
+ p = xp # same as yp
+ return xn, yn, p
+
+def _mkFP(n, p, FixedPoint=FixedPoint):
+ f = FixedPoint()
+ f.n = n
+ f.p = p
+ return f
+
+# divide x by y, rounding to int via nearest-even
+# y must be > 0
+# XXX which rounding modes are useful?
+
+def _roundquotient(x, y):
+ assert y > 0
+ n, leftover = divmod(x, y)
+ c = cmp(leftover << 1, y)
+ # c < 0 <-> leftover < y/2, etc
+ if c > 0 or (c == 0 and (n & 1) == 1):
+ n = n + 1
+ return n
+
+# crud for parsing strings
+import re
+
+# There's an optional sign at the start, and an optional exponent
+# at the end. The exponent has an optional sign and at least one
+# digit. In between, must have either at least one digit followed
+# by an optional fraction, or a decimal point followed by at least
+# one digit. Yuck.
+
+_parser = re.compile(r"""
+ \s*
+ (?P<sign>[-+])?
+ (
+ (?P<int>\d+) (\. (?P<frac>\d*))?
+ |
+ \. (?P<onlyfrac>\d+)
+ )
+ ([eE](?P<exp>[-+]? \d+))?
+ \s* $
+""", re.VERBOSE).match
+
+del re
+
+# return n, p s.t. float string value == n * 10**p exactly
+
+def _string2exact(s):
+ m = _parser(s)
+ if m is None:
+ raise ValueError("can't parse as number: " + `s`)
+
+ exp = m.group('exp')
+ if exp is None:
+ exp = 0
+ else:
+ exp = int(exp)
+
+ intpart = m.group('int')
+ if intpart is None:
+ intpart = "0"
+ fracpart = m.group('onlyfrac')
+ else:
+ fracpart = m.group('frac')
+ if fracpart is None or fracpart == "":
+ fracpart = "0"
+ assert intpart
+ assert fracpart
+
+ i, f = long(intpart), long(fracpart)
+ nfrac = len(fracpart)
+ i = i * _tento(nfrac) + f
+ exp = exp - nfrac
+
+ if m.group('sign') == "-":
+ i = -i
+
+ return i, exp
Modified: trunk/SwigInterface/manta.i
==============================================================================
--- trunk/SwigInterface/manta.i (original)
+++ trunk/SwigInterface/manta.i Fri Jun 9 12:44:07 2006
@@ -277,8 +277,6 @@
#include <Interface/TexCoordMapper.h>
#include <Core/Util/Align.h>
#include <Interface/RayPacket.h>
-#include <Interface/Light.h>
-#include <Interface/LightSet.h>
%}
%include <Core/Geometry/Ray.h>
@@ -288,25 +286,29 @@
%include <Interface/TexCoordMapper.h>
%include <Core/Util/Align.h>
%include <Interface/RayPacket.h>
-%include <Interface/Light.h>
-%include <Interface/LightSet.h>
////////////////////////////////////////////////////////
// Lights and backgrounds
%{
+#include <Interface/Light.h>
+#include <Interface/LightSet.h>
#include <Interface/AmbientLight.h>
#include <Model/AmbientLights/ConstantAmbient.h>
#include <Interface/Background.h>
#include <Model/Backgrounds/ConstantBackground.h>
#include <Model/Lights/PointLight.h>
+#include <Model/Lights/HeadLight.h>
%}
+%include <Interface/Light.h>
+%include <Interface/LightSet.h>
%include <Interface/AmbientLight.h>
%include <Model/AmbientLights/ConstantAmbient.h>
%include <Interface/Background.h>
%include <Model/Backgrounds/ConstantBackground.h>
%include <Model/Lights/PointLight.h>
+%include <Model/Lights/HeadLight.h>
namespace Manta {
// This tells SWIG to deallocate the memory from toString functions.
@@ -324,6 +326,24 @@
return strdup(self->toString().c_str());
}
};
+
+ %extend Light {
+ Manta::PointLight* asPointLight() {
+ return dynamic_cast<Manta::PointLight*>(self);
+ }
+ };
+
+ %extend Light {
+ Manta::HeadLight* asHeadLight() {
+ return dynamic_cast<Manta::HeadLight*>(self);
+ }
+ };
+
+// %extend PointLight {
+// static PointLight* fromLight(Light* parent) {
+// return dynamic_cast<Manta::PointLight*>(parent);
+// }
+// };
}
/////////////////////////////////////////////////////
Modified: trunk/SwigInterface/wxManta.py
==============================================================================
--- trunk/SwigInterface/wxManta.py (original)
+++ trunk/SwigInterface/wxManta.py Fri Jun 9 12:44:07 2006
@@ -6,12 +6,15 @@
from wxPython.glcanvas import wxGLCanvas
import threading
import math
+import wx.lib.colourselect as csel
from manta import *
from pycallback import *
from OpenGL.GL import *
+import FloatSpin as FS
+
# Number of workers.
numworkers = 2
@@ -143,6 +146,127 @@
class Frame(wx.Frame):
pass
+class LightFrame(wx.Frame):
+ def __init__(self, parent, engine):
+ wx.Frame.__init__(self, parent=parent, title="Lights")
+
+ self.engine = engine
+ self.colorButtonRefs = {}
+
+ panel= wx.Panel(self, -1)
+
+ gbs = wx.GridBagSizer(5,5)
+
+ lights = engine.getScene().getLights()
+ for i in range(lights.numLights()):
+ gbs.Add( self.addLight(panel, lights.getLight(i)), (i, 0))
+
+ button = wx.Button(panel, -1, "Close")
+ gbs.Add( button, (lights.numLights(),0) )
+ self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
+ self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
+
+ panel.SetSizerAndFit(gbs)
+ self.SetClientSize(panel.GetSize())
+
+ def OnCloseMe(self, event):
+ self.Close(True)
+
+ def OnCloseWindow(self, event):
+ self.Destroy()
+
+ def addLight(self, where, light):
+ point_light = light.asPointLight()
+ if (point_light != None):
+ return self.addPointLight(where, point_light)
+ head_light = light.asHeadLight()
+ if (head_light != None):
+ return self.addHeadLight(where, head_light)
+
+ def addPointLight(self, where, light):
+ location = light.getPosition()
+ color = light.getColor().convertRGB()
+
+ panel = wx.Panel(where, -1)
+
+ gbs = wx.GridBagSizer(5,5)
+ gbs.Add( wx.StaticText(panel, -1, "Location"), (0,0))
+ spinnerX = self.addSpinner(panel, location.x())
+ spinnerY = self.addSpinner(panel, location.y())
+ spinnerZ = self.addSpinner(panel, location.z())
+ spinnerX.light = light
+ spinnerX.X = spinnerX
+ spinnerX.Y = spinnerY
+ spinnerX.Z = spinnerZ
+ spinnerY.light = light
+ spinnerY.X = spinnerX
+ spinnerY.Y = spinnerY
+ spinnerY.Z = spinnerZ
+ spinnerZ.light = light
+ spinnerZ.X = spinnerX
+ spinnerZ.Y = spinnerY
+ spinnerZ.Z = spinnerZ
+ gbs.Add( spinnerX, (0,1))
+ gbs.Add( spinnerY, (0,2))
+ gbs.Add( spinnerZ, (0,3))
+
+ # Shortcut for namespace
+ colorTup = ( int(color.r() * 255),
+ int(color.g() * 255),
+ int(color.b() * 255) )
+ colorButton = csel.ColourSelect(panel, -1, "Color",
+ colorTup)
+ colorButton.Bind(csel.EVT_COLOURSELECT, self.OnSelectColor)
+ self.colorButtonRefs[colorButton.GetId()] = colorButton
+ colorButton.light = light
+
+ gbs.Add( colorButton, (0,4))
+
+ panel.SetSizerAndFit(gbs)
+ return panel
+
+ def addSpinner(self, where, value):
+ floatspin = FS.FloatSpin(where, -1, min=1, max=0,
+ increment=0.01, value=value,
+ extrastyle=FS.FS_LEFT)
+ floatspin.SetFormat("%g")
+ floatspin.SetDigits(5)
+ floatspin.Bind(FS.EVT_FLOATSPIN, self.OnFloatSpin)
+ return floatspin
+
+ def OnFloatSpin(self, event):
+ # Pull out the new value
+ spinner = event.GetEventObject()
+ x = float(spinner.X.GetValue())
+ y = float(spinner.Y.GetValue())
+ z = float(spinner.Z.GetValue())
+ newPosition = Vector(x,y,z)
+ cbArgs = ( newPosition, )
+ self.engine.addTransaction("Light Position",
+
manta_new(PyCallback.static_createMantaCallback(spinner.light.setPosition,
cbArgs)))
+
+
+ def OnSelectColor(self, event):
+ try:
+ colorButton = self.colorButtonRefs[event.GetId()]
+ except:
+ dlg = wx.MessageDialog(self, 'Getting Wrong IDs from Color
event!',
+ 'ERROR',
+ wx.OK | wx.ICON_ERROR
+ )
+ dlg.ShowModal()
+ dlg.Destroy()
+ return
+ color = event.GetValue()
+ rgbColor = RGBColor(color.Red() /255.0,
+ color.Green()/255.0,
+ color.Blue() /255.0)
+ cbArgs = ( Color(rgbColor), )
+ self.engine.addTransaction("Light Color",
+
manta_new(PyCallback.static_createMantaCallback(colorButton.light.setColor,
cbArgs)))
+
+
+
class App(wx.App) :
@@ -154,8 +278,10 @@
# size=wx.Size(xres, yres) )
self.frame.Show()
+ # Create the StatusBar
self.frame.statusbar = self.frame.CreateStatusBar()
+ # Create the menu
menuBar = wx.MenuBar()
menu1 = wx.Menu()
self.frame.Bind(wx.EVT_MENU, self.OnQuit,
@@ -166,10 +292,13 @@
menu2.Append(wx.NewId(), "About Manta"))
menuBar.Append(menu2, "&Help")
self.frame.SetMenuBar(menuBar)
-
+ # Create the Main panel that will hold the renderer
self.panel = wx.Panel(self.frame)
self.panel.SetSize(wx.Size(xres, yres))
+
+ ############################################################
+ # Layout
box = wx.BoxSizer(wx.HORIZONTAL)
box.Add(self.panel, 1, wx.EXPAND)
self.frame.SetSizerAndFit(box)
@@ -239,6 +368,7 @@
# Make canvas the initial focus
wx.CallAfter(self.canvas.SetFocus)
+
##################################################################
# globals
self.trackball_radius = 0.8
@@ -285,6 +415,8 @@
print "Found a 'p'"
elif key == 'V':
print "Found a 'v'"
+ elif key == "L":
+ LightFrame(self.frame, self.engine).Show()
elif key == 'Q':
print "Quitting"
self.frame.Close()
- [MANTA] r1110 - in trunk: Core/Geometry Engine/Display Model/Lights SwigInterface, bigler, 06/09/2006
Archive powered by MHonArc 2.6.16.