void World::OnLButtonDown(int nX, int nY) { // Need to implement double click detection a different way for Linux int nDblClickTime = 500; #ifdef __PRAXIS_WINDOWS__ nDblClickTime = ::GetDoubleClickTime(); #endif int nCurrClickTime = glutGet(GLUT_ELAPSED_TIME); int nTimeBwClicks = nCurrClickTime - g_nLastClickTime; g_nLastClickTime = nCurrClickTime; if(nTimeBwClicks < nDblClickTime) { OnDoubleClick(); return; } stringstream ss; ss << "LMBDown(" << nX << "," << nY << ")"; luaCall(ss.str()); m_bLeftMouseDown = true; m_bLeftMouseWentDown = true; if(m_bMouseMovesCamera) m_bUpdatePickPosition = false; // Map the mouse position to a character position in the editor, then send a callback with this information. }
void World::OnKeyDown(unsigned char nKey, int nX, int nY) { //string temp(" "); temp[0] = nKey; stringstream ss; ss << "onKeyDown(" << (int)nKey << ")"; luaCall(ss.str()); }
void World::OnRButtonUp(int nX, int nY) { stringstream ss; ss << "RMBUp(" << nX << "," << nY << ")"; luaCall(ss.str()); m_bRightMouseDown = false; m_bUpdatePickPosition = true; }
void World::OnLButtonUp(int nX, int nY) { stringstream ss; ss << "LMBUp(" << nX << "," << nY << ")"; luaCall(ss.str()); m_bLeftMouseDown = false; m_bDoubleClick = false; m_bUpdatePickPosition = true; }
void World::OnKeyUp(unsigned char nKey, int nX, int nY) { if(!m_bRenderEditor) { string temp(" "); temp[0] = nKey; stringstream ss; ss << "keyUp(\"" << temp.c_str() << "\")"; luaCall(ss.str()); } //std::cout <<"OnKeyUp" << endl; }
void World::OnRButtonDown(int nX, int nY) { stringstream ss; ss << "RMBDown(" << nX << "," << nY << ")"; luaCall(ss.str()); m_bRightMouseDown = true; m_bRightMouseWentDown = true; if(m_bMouseMovesCamera) m_bUpdatePickPosition = false; }
int LuaMessageListener::DoFunction(MessageListener* ml, MessageData& data) { if (!luaState) return 0; lua_getglobal(luaState, luaFunction.c_str()); //get function name //if there isn't a function at the top of the stack, we failed to find it if (!lua_isfunction(luaState, -1)) { WARNING("Lua Function " + luaFunction + " not found during firing of event " + data.mId); return 0; } //first argument, listener handle lua_pushnumber(luaState, ml->handle); //second argument, event id lua_pushstring(luaState, data.mId.c_str()); //Convert our std::map to a lua table as the third parameter lua_newtable(luaState); int top = lua_gettop(luaState); for (std::map<string, MessageData::messageItem>::iterator it = data.mData.begin(); it != data.mData.end(); ++it) { const char* key = it->first.c_str(); lua_pushstring(luaState, key); //Add a data type that corrosponds to our value's type. MessageData::messageItem& item = it->second; switch (item.type) { case STRING: lua_pushstring(luaState, item.s.c_str()); break; case INTEGER: lua_pushnumber(luaState, item.i); break; case USERDATA: lua_pushlightuserdata(luaState, item.u); break; default: break; } lua_settable(luaState, top); } //fourth argument, our stored lua object lua_rawgeti(luaState, LUA_REGISTRYINDEX, luaReference); int result; if (luaCall(luaState, 4, 1) != 0) { console->AddMessage("\\c900 * LUAEVENT [" + luaFunction + "] Fail"); //result = luaError( luaState, luaFunction, lua_tostring(luaState, -1) ) result = 0; } else { if (lua_isnumber(luaState, -1)) { result = (int)lua_tonumber(luaState, -1); //get the result } } lua_pop(luaState, 1); //get rid of result from stack return result; }
void World::OnKeyDownSpecial(unsigned char nKey, int nX, int nY) { { //string temp(" "); temp[0] = nKey; stringstream ss; ss << "edKeyDownSpecial(" << (int)nKey << ")"; luaCall(ss.str()); } GLEditor::m_bUpdateRequired = true; // Have this call the lisp and forth functions as well? // Or just Lua for now? // Or just Lua, which calls other language stuff? //std::cout << "OnKeyDownSpecial: " << (int)nKey << ", " << "Mods: " << glutGetModifiers() << std::endl; if(nKey == GLUT_KEY_F1) luaCall("f1Pressed()"); if(nKey == GLUT_KEY_F2) luaCall("f2Pressed()"); if(nKey == GLUT_KEY_F3) luaCall("f3Pressed()"); if(nKey == GLUT_KEY_F4) luaCall("f4Pressed()"); if(nKey == GLUT_KEY_F5) luaCall("f5Pressed()"); if(nKey == GLUT_KEY_F6) luaCall("f6Pressed()"); if(nKey == GLUT_KEY_F7) luaCall("f7Pressed()"); if(nKey == GLUT_KEY_F8) luaCall("f8Pressed()"); if(nKey == GLUT_KEY_F9) luaCall("f9Pressed()"); if(nKey == GLUT_KEY_F10) luaCall("f10Pressed()"); if(nKey == GLUT_KEY_F11) luaCall("f11Pressed()"); if(nKey == GLUT_KEY_F12) luaCall("f12Pressed()"); // if(nKey == GLUT_KEY_TAB) // { // // std::cout << "tab from special" << endl; // if(m_buffers.size() > 0) // { // if(glutGetModifiers() & GLUT_ACTIVE_CTRL) // { // if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) // PreviousEditor(); // else // NextEditor(); // // early out here so that tab isn't registered as an editor key // return; // } // } // At the moment, GLUT callback behaviour is different between // windows and linux, therefore I need to put a special case here. // Ideally, I'd like all key presses that correspond to an ASCII // character to go through keydown/up and all that do not to go // into specialkeydown/up. That seems to be the intention of // the "special" version, except for the case of TAB, which // is considered special even though its printable. // I think I may have made that change to OpenGLUT though. // In windows, TAB goes here, but Ctrl-TAB goes into special. #ifdef __PRAXIS_WINDOWS__ // Don't handle for TAB at all in this function except for buffer // switching, since holding a modifier means TAB triggers here // instead of as a printable in OnKeyDown. // return; #endif // } // REPL buffer for one line commands // one line commands can be: // edit("function name") // which will open a new buffer just for editing that function // still need to render the trace and error strings // the last n lines of them. // Don't handle if tab used to switch buffers. // Update: Don't handle for TAB at all. // TAB for spacing already handled in OnKeyDown // TAB for buffer switching already handled earlier. // This is for handling arrow keys and other non-ASCII key presses. GetEditor()->Handle(0, nKey); // Function keys and other shortcuts for: // switching buffers // loading and saving // executing lua code // go to definition // Ctrl-Tab and Ctrl-Shift-Tab for buffer selection }
void World::OnKeyDown(unsigned char nKey, int nX, int nY) { GLEditor::m_bUpdateRequired = true; // When the buffer is visible, sent the keypresses to it. // When the buffer isn't, call the lua function. if(!m_bRenderEditor) { //string temp(" "); temp[0] = nKey; stringstream ss; ss << "keyDown(" << (int)nKey << ")"; luaCall(ss.str()); return; } else { //string temp(" "); temp[0] = nKey; stringstream ss; ss << "edKeyDown(" << (int)nKey << ")"; luaCall(ss.str()); } // This is where to handle pressing enter for a command buffer. // Do the command, then close // Changed my mind. I only want it so I can press enter to submit the command. // Use a prompt? Check for a prompt to decide whether to respond to enter pressed? // The print command. An interactive repl. Printing to the current buffer nicely. // Maybe a "parent buffer" is sufficient. Lets just use that for now. // Named buffers? Named buffers sounds good. // Can refer to them by name. // newBuffer("testout") // Simplifies saving. Just use the buffer name. // For safety, if file exists, save numbered backup before overwriting. // std::cout << "OnKeyDown: " << (int)nKey << ", " << "Mods: " << glutGetModifiers() << std::endl; bool bCtrlEnter = false; bool bShiftEnter = false; #ifdef __PRAXIS_LINUX__ bCtrlEnter = (glutGetModifiers() & GLUT_ACTIVE_CTRL && nKey == '\r'); bShiftEnter = (glutGetModifiers() & GLUT_ACTIVE_SHIFT && nKey == '\r'); #endif #ifdef __PRAXIS_WINDOWS__ bCtrlEnter = (nKey == '\n'); // Instead of '\r' presumably bShiftEnter = (glutGetModifiers() & GLUT_ACTIVE_SHIFT && nKey == '\r'); #endif // if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) // std::cout << "GLUT_ACTIVE_SHIFT : ON" << std::endl; // else // std::cout << "GLUT_ACTIVE_SHIFT : OFF" << std::endl; // if(glutGetModifiers() & GLUT_ACTIVE_CTRL) // std::cout << "GLUT_ACTIVE_CTRL : ON" << std::endl; // else // std::cout << "GLUT_ACTIVE_CTRL : OFF" << std::endl; // std::cout << "bCtrlEnter = " << (bCtrlEnter ? "true" : "false") << std::endl; // std::cout << "bShiftEnter = " << (bShiftEnter ? "true" : "false") << std::endl; // Need to add a Lisp mode and a Forth mode. // Switching is handled by the callbacks for those embedded languages. if(!GLEditor::m_bNativeControl) return; // std::cout << "nKey = " << (int)nKey << endl; if(nKey == 9) { //std::cout << "tab detected" << endl; //nKey = GLUT_KEY_TAB; if(m_buffers.size() > 0) { if(glutGetModifiers() & GLUT_ACTIVE_CTRL) { if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) PreviousEditor(); else NextEditor(); // early out here so that tab isn't registered as an editor key return; } } } if(bCtrlEnter) { std::string sLine = GetEditor()->GetCurrentLineText(); std::string sLua = GetEditor()->GetLuaBlock(); if(sLua != "") luaCall(sLua); else luaCall(sLine); } else if(bShiftEnter) { std::string sLine = GetEditor()->GetCurrentLineText(); std::string sLua = GetEditor()->GetLuaBlock(); if(sLua != "") GetEditor()->m_Position = GetEditor()->m_LuaBlockHighlight[1]; else GetEditor()->m_Position = GetEditor()->LineEnd(GetEditor()->m_Position); // Insert a line feed. // Should go to the end of the block or line before inserting line feed. GetEditor()->InsertNewline(); //GetEditor()->Update(); if(sLua != "") luaCall(sLua); else luaCall(sLine); } else { // If its just the Control key or other modifier key, don't call this. // Its preventing Ctrl-C and Ctrl-V from working in Linux. if(nKey != 0) GetEditor()->Handle(nKey, 0); //std::cout << "Key handler called with " << (int)nKey << std::endl; //std::cout << "Key = " << (int)nKey << std::endl; } }
void World::OnKeyUpSpecial(unsigned char nKey, int nX, int nY) { stringstream ss; ss << "onKeyUpSpecial(" << (int)nKey << ")"; luaCall(ss.str()); }
void World::OnMouseMove(int nX, int nY) { // Although this works, the recast in ogWindowProc is a better solution. // if(nX > 32768) nX -= 65536; // if(nY > 32768) nY -= 65536; // printf("OnMouseMove: %d, %d\n", nX, nY); // fflush(stdout); UpdateMousePos(nX, nY); // lets try this - nope // RefreshPickPosition(); // Need to change this so it calls the callback during either render or update // so that the mouse pick position is up to date stringstream ss; ss << "OnMouseMove(" << m_vMouse2DPositionDelta.x << "," << m_vMouse2DPositionDelta.y << "," << nX << "," << nY << ")"; luaCall(ss.str()); if(m_bMouseMovesCamera) { if(m_bRightMouseDown) { if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) { float fStepSize = m_vMouse2DPositionDelta.y * 0.2; mlVector3D vCamera = GetCameraTransform()->GetTranslation(); float fDistance = (m_vMousePickPosition - vCamera).Magnitude(); fStepSize *= fDistance * 0.05f; fStepSize = mlClamp(fStepSize, -20.0f, 20.0f); mlVector3D vForward = vCamera - m_vMousePickPosition; vForward.Normalise(); vForward *= fStepSize; m_trnCamera.ApplyTranslation(vForward); } else { PanCamera(m_vMouse2DPositionDelta.x, m_vMouse2DPositionDelta.y); } } if(m_bLeftMouseDown) { // This is a magic number which maps pixels of mouse motion to radians of rotation float fRotationSpeed = 0.008f; float fHeadingChange = fRotationSpeed * m_vMouse2DPositionDelta.x; float fPitchChange = fRotationSpeed * m_vMouse2DPositionDelta.y; if(m_bDoubleClick) { if(m_bUsePositionPreservingOrbitCamera) PositionPreservingOrbitCamera(m_vMousePickPosition, fHeadingChange * 0.5, fPitchChange * 0.5); else OrientationPreservingOrbitCamera(m_vMousePickPosition, fHeadingChange * 0.5, fPitchChange * 0.5); } else { RotateCamera(fHeadingChange, fPitchChange); } } } }
void World::Render() { UseMainWindowContext(); glGetIntegerv(GL_VIEWPORT, viewport); int fHeight = viewport[3]; int fWidth = viewport[2]; if(m_bRunning) { if(!luaCall("prerender()", "onerrorgl")) { m_bRunning = false; } //ioCall("render()"); } glViewport(0,0,fWidth, fHeight); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // glEnable(GL_CULL_FACE); glDisable(GL_CULL_FACE); // Turned this off for the Vivo Smart Tab // Turn it back on again if needed. //glEnable(GL_POLYGON_OFFSET_FILL); //glPolygonOffset (1., 1.); glClearColor(Int2FloatCol(m_nClearColorRed), Int2FloatCol(m_nClearColorGreen), Int2FloatCol(m_nClearColorBlue), 1.0f); //glClearColor(0.0f, (float)(rand()%1000) * 0.001f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); BuildGLMatrices(); RenderFloorPlane(); if(m_bUpdatePickPosition && !m_bDoubleClick) RefreshFloorPickPosition(); glClearColor(Int2FloatCol(m_nClearColorRed), Int2FloatCol(m_nClearColorGreen), Int2FloatCol(m_nClearColorBlue), 1.0f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // turned off the lighting code for now // too much to tune // 3d ck didn't have lighting // just a simple scheme for coloring the different faces // of the object primitives so that they were distinct //glEnable(GL_LIGHTING); //glEnable(GL_LIGHT0); //glEnable(GL_LIGHT1); //glEnable(GL_MULTISAMPLE); glEnable(GL_COLOR_MATERIAL); if(m_bRenderFloorGrid) RenderFloorGrid(); //static GLfloat lightPosition[4] = { 0.5, 5.0, 7.0, 1.0 }; //static GLfloat lightPosition1[4] = { 30, 10, 30, 1.0 }; //static GLfloat lightPosition2[4] = { 0, 20, 400, 1.0 }; //glLightfv(GL_LIGHT0, GL_POSITION, lightPosition2); //glLightfv(GL_LIGHT1, GL_POSITION, lightPosition2); // x = 400, y = -300 + i * 60, z = 20 //glLightfv(GL_LIGHT0, GL_POSITION, lightPosition); //glColorMaterial(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE); glColor4ub(255,255,255,255); if(m_bRunning) { if(!luaCall("render()", "onerrorgl")) { m_bRunning = false; } //ioCall("render()"); } // Restore a sane render state in case render left it in a bad condition glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glColorMask(1,1,1,1); // If there is an error, then stop the automatic lua calls. UseMainWindowContext(); glColor4ub(0,255,0,255); // green //if(m_bRenderOutput) // DrawText3DStroked(mlVector3D(-50,0,0 ), SelectEndLines(luaGetOutput(),100)); //if(m_bRenderError) // DrawText3DStroked(mlVector3D(-50,0,200), SelectEndLines(luaGetError(),100)); if(m_bRenderFloorPlane) RenderFloorPlane(); if(m_bUpdatePickPosition && !m_bDoubleClick) RefreshPickPosition(); if(m_bRenderMousePickSphere) RenderMousePickSphere(); if(m_bRenderProbesHUD) RenderProbes(); if(m_bRunning) { if(!luaCall("postrender()", "onerrorgl")) { m_bRunning = false; } } // Restore a sane render state in case postrender left it in a bad condition glDisable(GL_STENCIL_TEST); glEnable(GL_DEPTH_TEST); glDepthFunc(GL_LESS); glColorMask(1,1,1,1); glDisable(GL_LIGHTING); glDisable(GL_LIGHT0); glDisable(GL_LIGHT1); glDisable(GL_MULTISAMPLE); glMatrixMode(GL_PROJECTION); glPopMatrix(); if(m_bRenderEditor) { // Get rid of this completely. qt_save_gl_state(); GetEditor()->Render(); qt_restore_gl_state(); DrawText2D(mlVector3D(5,2), std::string("Buffer: ") + GetEditor()->GetName()); } if(m_bRenderFPS) { #ifdef __PRAXIS_WINDOWS__ int nCurrentTime = ::timeGetTime(); #endif #ifdef __PRAXIS_LINUX__ int nCurrentTime = glutGet(GLUT_ELAPSED_TIME); #endif if(m_nRenderCount % 10 == 0) { int nTimeDelta = nCurrentTime - g_nLastFrameTime; g_nLastFrameTime = nCurrentTime; g_fFPS = 1000.0f / (float)nTimeDelta; g_fFPS *= 10.0f; } //qt_save_gl_state(); //GetEditor()->Render(); //qt_restore_gl_state(); // Render a graph // A widget // A camera aligned widget // A widget for the 2D world // Just a camera aligned widget will do. stringstream ss; ss << std::setprecision(0) << std::fixed << g_fFPS << "fps"; DrawText2D(mlVector3D(90,95), ss.str()); } // Also, FPS // Get current time // Compare with previous time // Calculate and display FPS // ???? // PROFIT if(m_bRenderOutput) DrawText2D(mlVector3D(10 + GLEditor::m_nDesiredTextureSize + 10, 35 + GLEditor::m_nDesiredTextureSize - 13), SelectEndLines(PraxisLog::trace,20), fWidth, fHeight); if(m_bRenderError) DrawText2D(mlVector3D(10 + GLEditor::m_nDesiredTextureSize + 10, 35 + (GLEditor::m_nDesiredTextureSize / 4)), SelectEndLines(PraxisLog::error,20), fWidth, fHeight); m_nRenderCount++; }
void World::Update() { // if(worldGetWin32Modifiers() & GLUT_ACTIVE_CTRL) // m_bMouseMovesCamera = false; // else // m_bMouseMovesCamera = true; if(m_bMouseMovesCamera) { if(m_bLeftMouseDown) { if(m_bDoubleClick) { if(m_bUsePositionPreservingOrbitCamera) PositionPreservingOrbitCamera(m_vMousePickPosition, 0.0f, 0.0f); else OrientationPreservingOrbitCamera(m_vMousePickPosition, 0.0f, 0.0f); } } } m_bLeftMouseWentDown = false; m_bRightMouseWentDown = false; if(m_bRunning) { if(!luaCall("update()")) { m_bRunning = false; } } GetEditor()->Update(); #ifdef __PRAXIS_WINDOWS__ // Move this default behaviour as well as that of World::Render into lua? // Polling the date modified property of a file can cause sporadic stalls // Polling the clipboard should be cheap and quick // Poll the clipboard, check if it is text and that it has a praxis: prefix. // If it does, then run the script following the prefix. // Empty the clipboard so it doesn't get run again. // I have a clear task ahead of me. So do it! // Step 1: Refer to Win32 book to see example of how to access the clipboard. // The clipboard is Chapter 12 in Petzold. luaCall("if string.sub(getClipboardText(), 1, #praxis_instance_name + 4) == \"-- \" .. praxis_instance_name .. \":\" then " "local sCmd = string.sub(getClipboardText(), #praxis_instance_name + 4 + 1) " "clearClipboardText() " "luaCall(sCmd) " "end"); #endif #ifdef __PRAXIS_LINUX__ extern pthread_mutex_t g_inputthreadmutex; extern std::string g_sInputThreadString; extern bool g_bInputThreadNewString; pthread_mutex_lock (&g_inputthreadmutex); if(g_bInputThreadNewString) { luaCall(g_sInputThreadString); g_bInputThreadNewString = false; } pthread_mutex_unlock (&g_inputthreadmutex); #endif m_nUpdateCount++; }
void World::Init() { NewEditor(); luaCall("dofile(\"prod.lua\")"); }