| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436 |
- /*
- Copyright (C) 2011 by Ivan Safrin
-
- 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 "PolyScreenEntity.h"
- #include "PolyInputEvent.h"
- #include "PolyRectangle.h"
- #include "PolyRenderer.h"
- inline double round(double x) { return floor(x + 0.5); }
- using namespace Polycode;
- ScreenEntity::ScreenEntity() : Entity(), EventDispatcher() {
- color = Color(1.0f,1.0f,1.0f,1.0f);
- width = 1;
- height = 1;
- hitwidth = 1;
- hitheight = 1;
- backfaceCulled = false;
- positionMode = POSITION_TOPLEFT;
- mouseOver = false;
- isDragged = false;
- dragOffsetX = 0;
- dragOffsetY = 0;
- parentEntity = NULL;
- zindex = 0;
-
- depthWrite = false;
- depthTest = false;
-
- focusable = false;
- hasFocus = false;
- focusChildren = false;
- focusedChild = NULL;
- blockMouseInput = false;
-
- snapToPixels = false;
- lastClickTicks = 0;
- dragLimits = NULL;
-
- xmouse = 0;
- ymouse = 0;
-
- }
- void ScreenEntity::focusNextChild() {
- int j = 0;
- if(focusedChild) {
- for(int i=0; i < children.size(); i++) {
- if(children[i] == focusedChild)
- j = i;
- }
- }
-
- for(int i=0; i < children.size(); i++) {
- if(((ScreenEntity*)children[j])->isFocusable() && children[j] != focusedChild) {
- focusChild(((ScreenEntity*)children[j]));
- return;
- }
-
- j++;
- if(j == children.size())
- j = 0;
- }
- }
- Number ScreenEntity::getRotation() const {
- return this->getRoll();
- }
- void ScreenEntity::focusChild(ScreenEntity *child) {
- if(focusedChild != NULL) {
- focusedChild->onLoseFocus();
- focusedChild->hasFocus = false;
- }
- focusedChild = child;
- focusedChild->hasFocus = true;
- focusedChild->onGainFocus();
- }
- bool ScreenEntity::isFocusable() const {
- return focusable;
- }
- void ScreenEntity::startDrag(Number xOffset, Number yOffset) {
- isDragged = true;
- dragOffsetX = xOffset;
- dragOffsetY = yOffset;
- }
- void ScreenEntity::stopDrag() {
- isDragged = false;
- }
- ScreenEntity::~ScreenEntity() {
- }
- void ScreenEntity::setBlendingMode(int newBlendingMode) {
- blendingMode = newBlendingMode;
- }
- void ScreenEntity::setPosition(Number x, Number y) {
- position.x = x;
- position.y = y;
- matrixDirty = true;
- }
- void ScreenEntity::setScale(Number x, Number y) {
- scale.x = x;
- scale.y = y;
- matrixDirty = true;
- }
- Number ScreenEntity::getWidth() const {
- return width;
- }
- Number ScreenEntity::getHeight() const {
- return height;
- }
- bool ScreenEntity::hitTest(Number x, Number y) const {
- bool retVal = false;
- // apply compound scale to test hit against
- Vector3 compScale = getCompoundScale();
- Number hx = position.x * compScale.x;
- Number hy = position.y * compScale.y;
- Number hw = hitwidth * compScale.x;
- Number hh = hitheight * compScale.y;
- // Logger::log("hittest %f,%f in %f %f %f %f\n",x, y, hx, hy, hw, hh);
- switch(positionMode) {
- case ScreenEntity::POSITION_TOPLEFT:
-
- if(x > hx && x < (hx + hw)
- && y > hy && y < (hy + hh))
- retVal = true;
- break;
- case ScreenEntity::POSITION_CENTER:
- if(x > (hx - hw/2.0f) && x < (hx + hw/2.0f)
- && y > (hy - hh/2.0f) && y < (hy + hh/2.0f))
- retVal = true;
- break;
- }
- return retVal;
- }
- void ScreenEntity::setPositionMode(int newPositionMode) {
- positionMode = newPositionMode;
- }
- void ScreenEntity::_onKeyDown(PolyKEY key, wchar_t charCode) {
- onKeyDown(key, charCode);
- for(int i=0;i<children.size();i++) {
- ((ScreenEntity*)children[i])->_onKeyDown(key, charCode);
- }
- }
- void ScreenEntity::_onKeyUp(PolyKEY key, wchar_t charCode) {
- onKeyUp(key, charCode);
- for(int i=0;i<children.size();i++) {
- ((ScreenEntity*)children[i])->_onKeyUp(key, charCode);
- }
- }
- void ScreenEntity::setDragLimits(Polycode::Rectangle rect) {
- if(!dragLimits)
- dragLimits = new Polycode::Rectangle();
- dragLimits->x = rect.x;
- dragLimits->y = rect.y;
- dragLimits->w = rect.w;
- dragLimits->h = rect.h;
- }
- void ScreenEntity::clearDragLimits() {
- delete dragLimits;
- dragLimits = NULL;
- }
- void ScreenEntity::_onMouseMove(Number x, Number y, int timestamp) {
- if(isDragged) {
- setPosition(x-dragOffsetX,y-dragOffsetY);
- if(dragLimits) {
- if(position.x < dragLimits->x)
- position.x = dragLimits->x;
- if(position.x > dragLimits->x + dragLimits->w)
- position.x = dragLimits->x + dragLimits->w;
- if(position.y < dragLimits->y)
- position.y = dragLimits->y;
- if(position.y > dragLimits->y + dragLimits->h)
- position.y = dragLimits->y + dragLimits->h;
- }
- }
-
- xmouse = x-position.x;
- ymouse = y-position.y;
- onMouseMove(x,y);
- if(enabled) {
- if(hitTest(x,y)) {
- dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEMOVE);
- if(!mouseOver) {
- dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOVER);
- mouseOver = true;
- }
- } else {
- if(mouseOver) {
- dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEOUT);
- mouseOver = false;
- }
- }
- }
-
- if(enabled) {
- for(int i=0;i<children.size();i++) {
- ((ScreenEntity*)children[i])->_onMouseMove(x-position.x,y-position.y, timestamp);
- }
- }
- }
- bool ScreenEntity::_onMouseUp(Number x, Number y, int mouseButton, int timestamp) {
- bool retVal = false;
- if(hitTest(x,y) && enabled) {
- onMouseUp(x,y);
-
- InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
- inputEvent->mouseButton = mouseButton;
- dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP);
- retVal = true;
- } else {
-
- InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
- inputEvent->mouseButton = mouseButton;
-
- dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEUP_OUTSIDE);
- }
-
- if(enabled) {
- for(int i=0;i<children.size();i++) {
- ((ScreenEntity*)children[i])->_onMouseUp(x-position.x,y-position.y, mouseButton, timestamp);
- }
- }
- return retVal;
- }
- void ScreenEntity::_onMouseWheelUp(Number x, Number y, int timestamp) {
- bool doTest = true;
-
- if(hasMask) {
- if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
- doTest = false;
- }
- }
-
- if(doTest) {
- if(hitTest(x,y) && enabled) {
- onMouseWheelUp(x,y);
- dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_UP);
- }
- if(enabled) {
- for(int i=children.size()-1;i>=0;i--) {
- ((ScreenEntity*)children[i])->_onMouseWheelUp(x-position.x,y-position.y, timestamp);
- if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
- if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
- break;
- }
- }
- }
- }
- }
- void ScreenEntity::_onMouseWheelDown(Number x, Number y, int timestamp) {
- bool doTest = true;
-
- if(hasMask) {
- if(!((ScreenEntity*)maskEntity)->hitTest(x-position.x,y-position.y)) {
- doTest = false;
- }
- }
-
- if(doTest) {
- if(hitTest(x,y) && enabled) {
- onMouseWheelDown(x,y);
- dispatchEvent(new InputEvent(Vector2(x,y), timestamp), InputEvent::EVENT_MOUSEWHEEL_DOWN);
- }
- if(enabled) {
- for(int i=children.size()-1;i>=0;i--) {
- ((ScreenEntity*)children[i])->_onMouseWheelDown(x-position.x,y-position.y, timestamp);
- if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
- if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
- break;
- }
- }
- }
- }
- }
- bool ScreenEntity::_onMouseDown(Number x, Number y, int mouseButton, int timestamp) {
- bool retVal = false;
-
- bool doTest = true;
-
- if(hasMask) {
- if(!((ScreenEntity*)maskEntity)->hitTest(x,y)) {
- doTest = false;
- }
- }
-
- if(doTest) {
- if(hitTest(x,y) && enabled) {
- onMouseDown(x,y);
-
- InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
- inputEvent->mouseButton = mouseButton;
- dispatchEvent(inputEvent, InputEvent::EVENT_MOUSEDOWN);
-
- if(timestamp - lastClickTicks < 400) {
- InputEvent *inputEvent = new InputEvent(Vector2(x,y), timestamp);
- inputEvent->mouseButton = mouseButton;
- dispatchEvent(inputEvent, InputEvent::EVENT_DOUBLECLICK);
- }
- lastClickTicks = timestamp;
- retVal = true;
- }
- if(enabled) {
- for(int i=children.size()-1;i>=0;i--) {
-
- ((ScreenEntity*)children[i])->_onMouseDown(x-position.x,y-position.y, mouseButton, timestamp);
- if(((ScreenEntity*)children[i])->blockMouseInput && ((ScreenEntity*)children[i])->enabled) {
- if(((ScreenEntity*)children[i])->hitTest(x-position.x,y-position.y))
- break;
- }
- }
- }
- }
-
- return retVal;
- }
- void ScreenEntity::setRotation(Number rotation) {
- setRoll(rotation);
- }
- Vector2 ScreenEntity::getPosition2D() const {
- return Vector2(position.x, position.y);
- }
- Matrix4 ScreenEntity::buildPositionMatrix() {
- Matrix4 posMatrix;
- switch(positionMode) {
- case POSITION_TOPLEFT:
- // renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
- posMatrix.m[3][0] = (position.x+floor(width/2.0f)*scale.x)*matrixAdj;
- posMatrix.m[3][1] = (position.y+floor(height/2.0f)*scale.y)*matrixAdj;
- posMatrix.m[3][2] = position.z*matrixAdj;
- break;
- case POSITION_CENTER:
- posMatrix.m[3][0] = position.x*matrixAdj;
- posMatrix.m[3][1] = position.y*matrixAdj;
- posMatrix.m[3][2] = position.z*matrixAdj;
- break;
- }
-
-
- if(snapToPixels) {
- posMatrix.m[3][0] = round(posMatrix.m[3][0]);
- posMatrix.m[3][1] = round(posMatrix.m[3][1]);
- posMatrix.m[3][2] = round(posMatrix.m[3][2]);
- }
-
- return posMatrix;
- }
- void ScreenEntity::adjustMatrixForChildren() {
- if(positionMode == POSITION_TOPLEFT)
- renderer->translate2D(-floor(width/2.0f), -floor(height/2.0f));
- }
- /*
- void ScreenEntity::transformAndRender() {
- Update();
- if(!renderer || !visible)
- return;
- renderer->pushMatrix();
- switch(positionMode) {
- case POSITION_TOPLEFT:
- renderer->translate2D(position.x+ceil(width/2.0f)*scale->x, position.y+ceil(height/2.0f)*scale->y);
- break;
- case POSITION_CENTER:
- renderer->translate2D(position.x, position.y);
- break;
- }
- renderer->scale2D(scale);
- renderer->rotate2D(rotation);
- if(parentEntity) {
- Color combined = getCombinedColor();
- renderer->setVertexColor(combined.r,combined.g,combined.b,combined.a);
- } else {
- renderer->setVertexColor(color.r,color.g,color.b,color.a);
- }
-
- renderer->setBlendingMode(blendingMode);
- Render();
- if(positionMode == POSITION_TOPLEFT)
- renderer->translate2D(-ceil(width/2.0f)*scale->x, -ceil(height/2.0f)*scale->y);
- renderChildren();
- renderer->popMatrix();
- }
- */
|