123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "graphics/dgl.h"
- #include "console/consoleTypes.h"
- #include "gui/guiDefaultControlRender.h"
- #include "guiSceneObjectCtrl.h"
- #include "debug/profiler.h"
- // -----------------------------------------------------------------------------
- IMPLEMENT_CONOBJECT(GuiSceneObjectCtrl);
- // -----------------------------------------------------------------------------
- // -----------------------------------------------------------------------------
- // Constructor.
- // -----------------------------------------------------------------------------
- GuiSceneObjectCtrl::GuiSceneObjectCtrl(void)
- {
- // Reset Scene Object Name.
- mSceneObjectName = StringTable->EmptyString;
- // Default to no render margin
- mMargin = 0;
- mCaption = StringTable->EmptyString;
- mStateOn = false;
- mButtonType = ButtonTypeRadio;
- // Set-up private batcher.
- mBatchRenderer.setDebugStats( &mDebugStats );
- mBatchRenderer.setStrictOrderMode( true, true );
- mBatchRenderer.setBatchEnabled( false );
- }
- // -----------------------------------------------------------------------------
- // Persistent Fields.
- // -----------------------------------------------------------------------------
- void GuiSceneObjectCtrl::initPersistFields()
- {
- // Call Parent.
- Parent::initPersistFields();
- // Define Fields.
- addGroup("GuiSceneObjectCtrl");
- addField("renderMargin", TypeS32, Offset(mMargin, GuiSceneObjectCtrl));
- addField("sceneObject", TypeString, Offset(mSceneObjectName, GuiSceneObjectCtrl));
- endGroup("GuiSceneObjectCtrl");
- }
- // -----------------------------------------------------------------------------
- // Wake!
- // -----------------------------------------------------------------------------
- bool GuiSceneObjectCtrl::onWake()
- {
- // Call Parent.
- if (!Parent::onWake())
- return false;
- if( mProfile->constructBitmapArray() >= 36 )
- mHasTexture = true;
- else
- mHasTexture = false;
- // Activate.
- setActive(true);
- // All Okay.
- return true;
- }
- // -----------------------------------------------------------------------------
- // Sleep!
- // -----------------------------------------------------------------------------
- void GuiSceneObjectCtrl::onSleep()
- {
- Parent::onSleep();
- }
- // -----------------------------------------------------------------------------
- //
- // -----------------------------------------------------------------------------
- void GuiSceneObjectCtrl::inspectPostApply()
- {
- // Call Parent.
- Parent::inspectPostApply();
- // Set the Scene Object.
- setSceneObject( mSceneObjectName );
- }
- // -----------------------------------------------------------------------------
- // Set Scene Object.
- // -----------------------------------------------------------------------------
- ConsoleMethod( GuiSceneObjectCtrl, setSceneObject, void, 3, 3, "(string obj) Set the scene-object displayed in the control."
- "@param obj Either the object's ID or its name."
- "@return No return value.")
- {
- // Set Scene Object.
- object->setSceneObject( argv[2] );
- }
- // Set Scene Object.
- void GuiSceneObjectCtrl::setSceneObject( const char* name )
- {
- // Reset existing object.
- mSelectedSceneObject = NULL;
- // Get Scene Name.
- mSceneObjectName = StringTable->insert( name ? name : "" );
- // Valid Scene Object Name?
- if ( *mSceneObjectName )
- {
- // Fetch Scene Object.
- SceneObject* pSceneObject = dynamic_cast<SceneObject*>(Sim::findObject( name ));
- // Valid?
- if ( pSceneObject )
- {
- // Yes, so set Scene Object.
- mSelectedSceneObject = pSceneObject;
- // The scene object needs to be integrated otherwise the render OOBB which this GUI control
- // relies upon will be undefined. This dependency needs resolving but I suspect it never will.
- DebugStats debugStats;
- mSelectedSceneObject->preIntegrate(0.0f, 0.0f, &debugStats );
- }
- }
- else
- mSelectedSceneObject = NULL;
- // Do an update.
- setUpdate();
- }
- ConsoleMethod( GuiSceneObjectCtrl, getSceneObject, const char*, 2,2, "() \n@return Returns displaying sceneobject id")
- {
- SceneObject *sceneObject = object->getSceneObject();
- if( !sceneObject )
- return "";
- return sceneObject->getIdString();
- }
- ConsoleMethod( GuiSceneObjectCtrl, setCaption, void, 3, 3, "(string caption) Sets the object caption to specified string.\n"
- "@return No return value.")
- {
- object->setCaption( argv[2] );
- }
- void GuiSceneObjectCtrl::setCaption( const char* caption )
- {
- if( caption != NULL )
- mCaption = StringTable->insert( caption );
- }
- //
- //
- //
- void GuiSceneObjectCtrl::onMouseUp(const GuiEvent &event)
- {
- if( mDepressed && ( event.mouseClickCount % 2 ) == 0 )
- Con::executef( this, 2, "onDoubleClick" );
- Parent::onMouseUp( event );
- }
- void GuiSceneObjectCtrl::onMouseLeave( const GuiEvent &event )
- {
- Con::executef( this, 2, "onMouseLeave" );
- Parent::onMouseLeave( event );
- }
- void GuiSceneObjectCtrl::onMouseEnter( const GuiEvent &event )
- {
- Con::executef( this, 2, "onMouseEnter" );
- Parent::onMouseEnter( event );
- }
- void GuiSceneObjectCtrl::onMouseDragged( const GuiEvent &event )
- {
- Con::executef( this, 2, "onMouseDragged" );
- Parent::onMouseDragged( event );
- }
- // -----------------------------------------------------------------------------
- // Render any selected Scene Object.
- // -----------------------------------------------------------------------------
- void GuiSceneObjectCtrl::onRender(Point2I offset, const RectI& updateRect)
- {
- PROFILE_SCOPE(guiT2DObjectCtrl_onRender);
- RectI ctrlRect( offset, mBounds.extent );
- // Draw Background
- if( mProfile->mOpaque )
- {
- if( mDepressed || mStateOn )
- {
- if( mHasTexture )
- renderSizableBitmapBordersFilled( ctrlRect, 3, mProfile );
- else
- dglDrawRectFill( ctrlRect, mProfile->mFillColorHL );
- }
- else if ( mMouseOver )
- {
- if( mHasTexture )
- renderSizableBitmapBordersFilled( ctrlRect, 2, mProfile );
- else
- dglDrawRectFill( ctrlRect, mProfile->mFillColorHL );
- }
- else
- {
- if( mHasTexture )
- renderSizableBitmapBordersFilled( ctrlRect, 1, mProfile );
- else
- dglDrawRectFill( ctrlRect, mProfile->mFillColor );
- }
- }
- //// Render Border.
- //if( mProfile->mBorder || mStateOn )
- // dglDrawRect(ctrlRect, mProfile->mBorderColor);
- // Valid Scene Object?
- if ( !mSelectedSceneObject.isNull() )
- {
- RectI objRect = updateRect;
- objRect.inset( mMargin, mMargin );
- RectI ctrlRectInset = ctrlRect;
- ctrlRectInset.inset( mMargin, mMargin);
- // Draw Canvas color for object
- if ( mProfile->mOpaque )
- {
- if( mHasTexture )
- renderSizableBitmapBordersFilled( objRect, 4, mProfile );
- else
- dglDrawRectFill( objRect, mProfile->mFillColorNA );
- }
- // Yes, so fetch object clip boundary.
- const b2Vec2* pClipBoundary = mSelectedSceneObject->getRenderOOBB();
- // Calculate the GUI-Control Clip Boundary.
- const F32 xscale = (pClipBoundary[1].x - pClipBoundary[0].x) / ctrlRectInset.extent.x;
- const F32 yscale = (pClipBoundary[2].y - pClipBoundary[0].y) / ctrlRectInset.extent.y;
- F32 x1 = pClipBoundary[0].x + ( objRect.point.x - ctrlRectInset.point.x) * xscale;
- F32 x2 = pClipBoundary[1].x + ( objRect.point.x + objRect.extent.x - ctrlRectInset.extent.x - ctrlRectInset.point.x) * xscale;
- F32 y1 = pClipBoundary[0].y + ( objRect.point.y - ctrlRectInset.point.y) * yscale;
- F32 y2 = pClipBoundary[2].y + ( objRect.point.y + objRect.extent.y - ctrlRectInset.extent.y - ctrlRectInset.point.y) * yscale;
- Vector2 size = mSelectedSceneObject->getSize();
- if (size.x > size.y)
- {
- S32 center = ctrlRectInset.point.y + (ctrlRectInset.extent.y / 2);
- // Save the base state of the objRect before transforming it
- S32 baseTop = objRect.point.y;
- S32 baseExtent = objRect.extent.y;
- S32 baseBottom = baseTop + baseExtent;
- // Transform the objRect extent by the aspect ratio
- objRect.extent.y = (S32)(ctrlRectInset.extent.y * (size.y / size.x));
- // Save the transformed positions of the objRect before clipping
- S32 targetTop = (S32)(center - ((ctrlRectInset.extent.y * (size.y / size.x)) / 2));
- S32 targetExtent = (S32)(objRect.extent.y);
- S32 targetBottom = (S32)(targetTop + objRect.extent.y);
- // Set the objRect position based on its aspect ratio
- objRect.point.y = (S32)(center - ((ctrlRectInset.extent.y * (size.y / size.x)) / 2));
- // Reset the clipping bounds
- y1 = pClipBoundary[0].y;
- y2 = pClipBoundary[2].y;
- // If the object clips of the top or bottom, adjust the extent and clipping bounds accordingly
- if (baseTop > targetTop)
- {
- // Adjust the position and extent
- objRect.point.y = baseTop;
- objRect.extent.y = getMax(targetBottom - baseTop, 0);
-
- // Set the top clipping boundary
- F32 clipRatio = 1.0f - ((1.0f * objRect.extent.y)/targetExtent);
- y1 = pClipBoundary[0].y + (pClipBoundary[2].y - pClipBoundary[0].y)*(clipRatio);
-
- }
- if (baseBottom < targetBottom)
- {
- // Adjust the extent
- objRect.extent.y = getMax(baseBottom - targetTop, 0);
- // Set the bottom clipping boundary
- F32 clipRatio = 1.0f - ((1.0f * objRect.extent.y)/targetExtent);
- y2 = pClipBoundary[2].y - (pClipBoundary[2].y - pClipBoundary[0].y)*(clipRatio);
- }
- }
- else
- {
- S32 center = ctrlRectInset.point.x + (ctrlRectInset.extent.x / 2);
- // Save the base state of the objRect before transforming it
- S32 baseLeft = objRect.point.x;
- S32 baseExtent = objRect.extent.x;
- S32 baseRight = baseLeft + baseExtent;
- // Transform the objRect extent by the aspect ratio
- objRect.extent.x = (S32)(ctrlRectInset.extent.x * (size.x / size.y));
- // Save the transformed positions of the objRect before clipping
- S32 targetLeft = (S32)(center - ((ctrlRectInset.extent.x * (size.x / size.y)) / 2));
- S32 targetExtent = (S32)(objRect.extent.x);
- S32 targetRight = (S32)(targetLeft + objRect.extent.x);
- // Set the objRect position based on its aspect ratio
- objRect.point.x = (S32)(center - ((ctrlRectInset.extent.x * (size.x / size.y)) / 2));
- // Reset the clipping bounds
- x1 = pClipBoundary[0].x;
- x2 = pClipBoundary[1].x;
- // If the object clips of the left or right, adjust the extent and clipping bounds accordingly
- if (baseLeft > targetLeft)
- {
- // Adjust the position and extent
- objRect.point.x = baseLeft;
- objRect.extent.x = getMax(targetRight - baseLeft, 0);
-
- // Set the left clipping boundary
- F32 clipRatio = 1.0f - ((1.0f * objRect.extent.x)/targetExtent);
- x1 = pClipBoundary[0].x + (pClipBoundary[1].x - pClipBoundary[0].x)*(clipRatio);
-
- }
- if (baseRight < targetRight)
- {
- // Adjust the extent
- objRect.extent.x = getMax(baseRight - targetLeft, 0);
- // Set the right clipping boundary
- F32 clipRatio = 1.0f - ((1.0f * objRect.extent.x)/targetExtent);
- x2 = pClipBoundary[1].x - (pClipBoundary[1].x - pClipBoundary[0].x)*(clipRatio);
- }
- }
- // Negate the y-clippingpoints to convert to positive-y-up coordinate system of the object
- y1 *= -1;
- y2 *= -1;
- // Setup new logical coordinate system.
- glMatrixMode(GL_PROJECTION);
- glPushMatrix();
- glLoadIdentity();
- RectI viewport;
- dglGetViewport(&viewport);
- if (x1 > x2)
- {
- F32 temp = x1;
- x1 = x2;
- x2 = temp;
- }
- if (y1 > y2)
- {
- F32 temp = y1;
- y1 = y2;
- y2 = temp;
- }
- // Setup Orthographic Projection for Object Area.
- #if defined(TORQUE_OS_IOS) || defined(TORQUE_OS_ANDROID)
- glOrthof( x1, x2, y1, y2, 0.0f, MAX_LAYERS_SUPPORTED );
- #else
- glOrtho( x1, x2, y1, y2, 0.0f, MAX_LAYERS_SUPPORTED );
- #endif
- // Setup new viewport.
- dglSetViewport(objRect);
- // Set ModelView.
- glMatrixMode(GL_MODELVIEW);
- glPushMatrix();
- glLoadIdentity();
- // Enable Alpha Test.
- glEnable ( GL_ALPHA_TEST );
- glAlphaFunc ( GL_GREATER, 0.0f );
- // Calculate maximal clip bounds.
- RectF clipBounds( -x1,-y1, x2-x1, y2-y1 );
- DebugStats debugStats;
- // Render Object in GUI-space.
- SceneRenderState guiSceneRenderState(
- clipBounds,
- clipBounds.centre(),
- 0.0f,
- MASK_ALL,
- MASK_ALL,
- Vector2::getOne(),
- &debugStats,
- this );
- SceneRenderRequest guiSceneRenderRequest;
- guiSceneRenderRequest.set(
- mSelectedSceneObject,
- mSelectedSceneObject->getRenderPosition(),
- 0.0f );
- mSelectedSceneObject->sceneRender( &guiSceneRenderState, &guiSceneRenderRequest, &mBatchRenderer );
- // Restore Standard Settings.
- glDisable ( GL_DEPTH_TEST );
- glDisable ( GL_ALPHA_TEST );
- // Restore Matrices.
- glMatrixMode(GL_MODELVIEW);
- glPopMatrix();
- glMatrixMode(GL_PROJECTION);
- glPopMatrix();
- }
- else
- {
- // No Object so reset name.
- mSceneObjectName = NULL;
- }
- RectI captionRect = ctrlRect;
- captionRect.point.y += (captionRect.extent.y / 8);
- captionRect.inset(1, 1);
- dglSetBitmapModulation( ColorI(0,0,0,255) );
- renderJustifiedText(captionRect.point, captionRect.extent, mCaption);
- captionRect.inset(1, 1);
- dglSetBitmapModulation( mProfile->mFontColor );
- renderJustifiedText(captionRect.point, captionRect.extent, mCaption);
-
- // Render Child Controls.
- renderChildControls(offset, updateRect);
- }
|