GuiBitmapCtrl 을 드래그 가능하게 수정하는 소스코드다.
TGEA 1.7.1 기반.
1. guiBitmapCtrl.h- 아래코드 추가protected:...... 생략 ......// The mouse down offset from the upper left of the control.Point2I mOffset;bool mDeleteOnMouseUp;bool mDrag;// Controls may want to react when they are dragged over, entered or exited.GuiControl* mLastTarget;// Convenience methods for sending eventsvoid sendDragEvent(GuiControl* target, const char* event);GuiControl* findDragTarget(Point2I mousePoint, const char* method);public:...... 생략 ......void startDragging(Point2I offset = Point2I(0, 0));virtual void onMouseDown(const GuiEvent& event);virtual void onMouseDragged(const GuiEvent& event);virtual void onMouseUp(const GuiEvent& event);
2. guiBitmapCtrl.cpp- 헤더파일 추가 후 아래와 같은 코드를 각 함수에 추가#include "gui/core/guiCanvas.h"GuiBitmapCtrl::GuiBitmapCtrl(void){......DeleteOnMouseUp = false;mDrag = false;}void GuiBitmapCtrl::initPersistFields(){......addField("deleteOnMouseUp", TypeBool, Offset(mDeleteOnMouseUp, GuiBitmapCtrl));addField("drag", TypeBool, Offset(mDrag, GuiBitmapCtrl));}// 아래부분은 통째로 붙여넣는다ConsoleMethod(GuiBitmapCtrl, startDragging, void, 2, 4, "startDragging(%offset)"){Point2I offset = Point2I(0, 0);if (argc > 3){offset.x = dAtoi(argv[2]);offset.y = dAtoi(argv[3]);}object->startDragging(offset);}void GuiBitmapCtrl::startDragging(Point2I offset){GuiCanvas* canvas = getRoot();AssertFatal(canvas, "DragAndDropControl wasn't added to the gui before the drag started.");if (canvas->getMouseLockedControl()){GuiEvent event;canvas->getMouseLockedControl()->onMouseLeave(event);canvas->mouseUnlock(canvas->getMouseLockedControl());}canvas->mouseLock(this);canvas->setFirstResponder(this);mOffset = offset;mLastTarget=NULL;}void GuiBitmapCtrl::onMouseDown(const GuiEvent& event){if ( !mDrag )return;startDragging(event.mousePoint - getPosition());}void GuiBitmapCtrl::onMouseDragged(const GuiEvent& event){if ( !mDrag )return;setPosition(event.mousePoint - mOffset);// Allow the control under the drag to react to a potential dropGuiControl* enterTarget = findDragTarget(event.mousePoint, "onControlDragEnter");if(mLastTarget != enterTarget){sendDragEvent(mLastTarget, "onControlDragExit");sendDragEvent(enterTarget, "onControlDragEnter");mLastTarget = enterTarget;}GuiControl* dragTarget = findDragTarget(event.mousePoint, "onControlDragged");sendDragEvent(dragTarget, "onControlDragged");if ( isMethod("onMouseDragged") )Con::executef( this, "onMouseDragged" );}void GuiBitmapCtrl::onMouseUp(const GuiEvent& event){if ( !mDrag )return;mouseUnlock();GuiControl* target = findDragTarget(event.mousePoint, "onControlDropped");sendDragEvent(target, "onControlDropped");if (mDeleteOnMouseUp)deleteObject();}void GuiBitmapCtrl::sendDragEvent(GuiControl* target, const char* event){if(!target || !target->isMethod(event) || !mDrag)return;char position[32];Point2I dropPoint = getPosition() + (getExtent() / 2);dSprintf(position, 32, "%d %d", dropPoint.x, dropPoint.y);Con::executef(target, event, Con::getIntArg(at(0)->getId()), position);}GuiControl* GuiBitmapCtrl::findDragTarget(Point2I mousePoint, const char* method){if ( !mDrag )return false;// If there are any children and we have a parent.GuiControl* parent = getParent();if (size() && parent){mVisible = false;GuiControl* dropControl = parent->findHitControl(mousePoint);mVisible = true;while( dropControl ){if (dropControl->isMethod(method))return dropControl;elsedropControl = dropControl->getParent();}}return NULL;}
이제 엔진 소스를 다시 컴파일 후 스크립트에서 사용하면된다.
사용방법은
new GuiBitmapCtrl(TestImage){canSaveDynamicFields = "0";Enabled = "1";isContainer = "0";Profile = "GuiDefaultProfile";HorizSizing = "right";VertSizing = "bottom";position = "173 216";Extent = "19 19";MinExtent = "8 2";canSave = "1";Visible = "1";hovertime = "1000";bitmap = "./TestImage ";wrap = "0";drag = "1";};
drag 필드는 엔진에서 디폴트 false 로 설정되어있으므로 드래그앤드롭을 적용하지 않아도 될경우에는 속성에 기술할 필요가 없다.
deleteOnMouseUp 필드도 사용할 수 있는데 "1" 로 설정할 경우 마우스 드래그 후 드랍할 때, 즉 onMouseUp 이벤트에서 해당 이미지 오브젝트를 삭제하는 필드이다. 나 같은 경우는 별 필요가 없다.
그 다음 이미지를 드래그 할 때 스크립트에서 실행되는 onMouseDragged 콜백함수를 등록해주어야 한다.
이런식으로..
function TestImage::onMouseDragged(%this){%pos = TestImage.getPosition();%posX = getWord(%pos,0);%posY = getWord(%pos,1);TestImage.setPosition(%posX, %posY);//// 이미지가 드래그 될 때 일어나는 기타 동작은 여기에서 구현.//}
사실 위 코드는 GuiDragAndDropControl 의 일부를 뜯어와서 적용시킨 건데 드래그되는 컨트롤이 있으면 그걸 그대로 쓰면되지 왜 엔진을 고치느냐라고 물어볼수 도 있다. GuiDragAndDropControl은 GuiEditor 의 팔레트에서 사용하는데 cs 파일을 살펴본 결과 내가 원하는 방식대로 사용할 수 있는 구조가 아닌 것 같았다.
예제가 팔레트에서 사용한 것 밖에 없어서 정확하게 알아본 것은 아니지만
아무튼... 특이한 방법이었다 =_=.......
tools\guiEditor\gui\guiEditor.ed.cs 를 찾아보면 나와있다.
다행히 GuiDragAndDropControl 의 엔진 소스 자체가 잘 구현되어 있어서 한번에 가져와서 붙였고 제대로 동작하는 것 까지 확인했다.