📄 chmazmod.cpp
字号:
float value;
int numRead = ::sscanf(LPCTSTR(strValue) + numBytes, "%g", &value);
pEvent = new ChFloatEvent(name, value);
break;
}
case ChVRMLEvent::MFFloat :
{
int count;
int nBytes = numBytes;
int n;
int numRead = ::sscanf(LPCTSTR(strValue) + nBytes, "%d%n", &count, &n);
if(numRead)
{
float *val = new float [count];
for(int i = 0; i < count; i++)
{
nBytes += n;
numRead = ::sscanf(LPCTSTR(strValue) + nBytes, "%f%n", val+i, &n);
if(!numRead) break;
}
if(numRead) pEvent = new ChFloatEvent(name, count, val);
delete []val;
}
break;
}
case ChVRMLEvent::MFRotation :
{
float x, y, z, angle;
int count;
int nBytes = numBytes;
int n;
int numRead = ::sscanf(LPCTSTR(strValue) + nBytes, "%d%n", &count, &n);
if(numRead)
{
float *val = new float [count * 4];
for(int i = 0; i < count; i++)
{
nBytes += n;
numRead = ::sscanf(LPCTSTR(strValue) + nBytes, "%f %f %f %f%n", &x, &y, &z, &angle, &n);
if(numRead < 4) break;
int index = i * 4;
val[index] = x;
val[index+1] = y;
val[index+2] = z;
val[index+3] = angle;
}
if(numRead) pEvent = new ChRotationEvent(name, count, val);
delete []val;
}
break;
}
case ChVRMLEvent::SFBool :
{
bool value = false;
string buf;
char *pbuf = buf.GetBuffer(1000);
int numRead = ::sscanf(LPCTSTR(strValue) + numBytes, "%s", buf);
buf.ReleaseBuffer();
if(numRead)
{
if( !buf.CompareNoCase("true") ||
!buf.CompareNoCase("1") ||
!buf.CompareNoCase("t") ||
!buf.CompareNoCase("yes") ||
!buf.CompareNoCase("y")) value = true;
// assuming illegals are false
pEvent = new ChBoolEvent(name, value);
}
break;
}
case ChVRMLEvent::SFTime :
{
double value;
int numRead = ::sscanf(LPCTSTR(strValue) + numBytes, "%lg", &value);
pEvent = new ChTimeEvent(name, value);
break;
}
case ChVRMLEvent::SFNode :
case ChVRMLEvent::MFNode :
{
// Our syntax only allows one node right now
// and only via code
string strVrml;
if (ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_VRML, strVrml ))
{
if(strVrml.Left(6) != "#VRML ")
{
string strBuf = strVrml;
strVrml = string("#VRML V1.0 ascii\n ") + strBuf;
}
// TODO Check for optional header field xch_vrml_hdr
pSFNode = (ChNode*)(pBrowser->CompileVRML(strVrml));
}
else
{
// remainder of fields if any are node names; just do first for now
int numRead, n;
char argNodeName[1000];
if(numRead = ::sscanf(LPCTSTR(strValue) + numBytes, "%s%n", argNodeName, &n))
{
string strArgNodeName (argNodeName);
pSFNode = (pBrowser->Resolve(pNode, strArgNodeName));
numBytes += n;
}
if(!pSFNode)
{
string strMsg;
strMsg.Format("VRML: Event %s, node %s was not found in scene graph under node %s.\n",
name, argNodeName, strNode );
((ChMazeWnd*)GetView())->OnError( CH_MAZE_ROUTE_ERROR_NODE_NOTFOUND, strMsg, ChMazeWnd::traceError);
}
}
if(pSFNode) pEvent = new ChNodeEvent(name, pSFNode);
break;
}
default:
{
// Ignore it
break;
}
}
if(pEvent)
{
if(ChIVrmlEvent::IsMultiple(eventType))
{
pEvent->SetMultiple(true);
}
pBrowser->SendEvent(pNode, 0, pEvent); // I'm doing this direct, so
// don't delete the event. In the real case,
// It needs to be deleted after sending
pBrowser->FreeNode(pNode); // Preservation of node is now browser's
// responsibility. This undoes the Use()
// implicit in Resolve()
}
if(pSFNode) pBrowser->FreeNode(pSFNode);
}
else
{
// No node found for subject; complain
string strMsg;
strMsg.Format("VRML: Event %s, node %s was not found.\n", LPCTSTR(name), strNode );
((ChMazeWnd*)GetView())->OnError( CH_MAZE_ROUTE_ERROR_NODE_NOTFOUND, strMsg, ChMazeWnd::traceError);
//TRACE(strMsg); // ahhh, should we print this too?
}
}
}
#endif
}
void ChMazeMainInfo::SetupPositionNotification(const string &strArgs)
{
// Call this with a blank string to reset
/* <img xch_event="move"
xch_minTime=nnn
xch_maxTime=nnn
xch_maxMove=nnn.nn
xch_startTime=nnn
params="position look up time orientation velocity slewrate">
defaults:
xch_minTime=1000
xch_maxTime=10000
xch_maxMove=0.5
xch_startTime=0
params="position" - specifying empty gives no args
where notification param formats are:
position f f f
look f f f
up f f f
time : long milliseconds since startTime
orientation f f f f (axis, then angle)
velocity f f f
slewRate f f f f (axis, then angular velocity)
all units are in meters or radians, or meter/sec or rads/sec
all time is in milliseconds
*/
// Defaults
long lMinTime=1000;
long lMaxTime=10000;
float fMaxMove=0.5;
float fMaxRotation=3.1415927 / 12; // 15 degrees
char params[CH_MAX_NOTIFICATION_PARAMS];
chint32 ticks = ::GetMessageTime();
bool boolEnabled = false;
double dOffset=-ticks;
memset(params, 0, sizeof(params));
params[0] = 'p';
if(!strArgs.IsEmpty())
{
lMinTime=m_minNotifyTime; // we'll just modify current
lMaxTime=m_maxNotifyTime;
fMaxMove=m_maxMove;
fMaxRotation=m_maxRotation;
dOffset=m_dTimeOffset;
boolEnabled = true;
memmove(params, m_params, sizeof(params));
double t;
int numRead;
string strValue;
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_MINTIME, strValue ))
{
if((numRead = sscanf(LPCTSTR(strValue), "%lg", &t)) >= 1 )
{
lMinTime = long(t);
}
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_MAXTIME, strValue ))
{
if((numRead = sscanf(LPCTSTR(strValue), "%lg", &t)) >= 1 )
{
lMaxTime = long(t);
}
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_MAXMOVE, strValue ))
{
if((numRead = sscanf(LPCTSTR(strValue), "%lg", &t)) >= 1 )
{
fMaxMove = t;
}
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_MAXROTATION, strValue ))
{
if((numRead = sscanf(LPCTSTR(strValue), "%lg", &t)) >= 1 )
{
fMaxRotation = t;
}
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_STARTTIME, strValue ))
{
if((numRead = sscanf(LPCTSTR(strValue), "%lg", &t)) >= 1 )
{
dOffset = (t - ticks);
}
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_CMD_NAME, strValue ))
{
if( strValue.IsEmpty()) boolEnabled = false;
else boolEnabled = true;
// No processing of name yet
}
if(ChHtmlWnd::GetHTMLAttribute( strArgs, CH_GRAPH_CMD_PARAMS, strValue ))
{
char *pTxt = strValue.GetBuffer(100);
char key[200];
int n, i = 0;
memset(params, 0, sizeof(params));
while(i < CH_MAX_NOTIFICATION_PARAMS && pTxt && *pTxt && sscanf( pTxt, "%s%n", key, &n))
{
string sKey(key);
if(!sKey.CompareNoCase("position") ||
!sKey.CompareNoCase("look") ||
!sKey.CompareNoCase("up") ||
!sKey.CompareNoCase("time") ||
!sKey.CompareNoCase("orientation") ||
!sKey.CompareNoCase("velocity") ||
!sKey.CompareNoCase("slewrate"))
{
params[i++] = tolower(key[0]); // first letter is key
}
pTxt += n;
}
}
}
// Copy the stuff into 'this'
m_minNotifyTime = lMinTime;
m_maxNotifyTime = lMaxTime;
m_maxMove = fMaxMove;
m_maxRotation = fMaxRotation;
m_dTimeOffset = dOffset;
m_boolNotificationEnabled = boolEnabled;
memmove(m_params, params, sizeof(params));
}
ChMazeMainInfo * ChMazeMainInfo::Add(ChGraphicHTTPReq *pInProgressReq)
{
if(!m_pInProgressReqs)
{
//m_pInProgressReqs = new ChPtrList<ChGraphicHTTPReq>;
m_pInProgressReqs = new ChGraphicHTTPReqList;
}
m_pInProgressReqs->AddTail(pInProgressReq);
return this;
}
ChMazeMainInfo * ChMazeMainInfo::Delete(ChGraphicHTTPReq *pInProgressReq)
{
if(m_pInProgressReqs)
{
ChPosition pos;
if(!m_pInProgressReqs->IsEmpty())
{
pos = m_pInProgressReqs->Find(pInProgressReq, 0 );
if(pos) m_pInProgressReqs->Remove(pos);
}
if(m_pInProgressReqs->IsEmpty())
{
delete m_pInProgressReqs;
m_pInProgressReqs = 0;
}
}
return this;
}
ChMazeMainInfo * ChMazeMainInfo::CancelInProgressReqs()
{
if(m_pInProgressReqs)
{
while(!m_pInProgressReqs->IsEmpty())
{
ChGraphicHTTPReq *pReq = m_pInProgressReqs->RemoveHead();
pReq->Cancel();
}
delete m_pInProgressReqs;
m_pInProgressReqs = 0;
}
return this;
}
void ChMazeMainInfo::OnTick()
{
// Bootleg the animation tick for our own purposes
chint32 ticks = ::GetMessageTime();
if(IsShown() && m_boolNotificationEnabled && ticks - m_lastTick >= m_minNotifyTime)
{
// notify mud
// if moved or if over max time for notify, do it
ChPuebloVrmlWnd* pWnd = (ChPuebloVrmlWnd*)m_pWnd;
GxVec3f loc = pWnd->GetCameraControl()->GetLoc();
GxVec3f look = pWnd->GetCameraControl()->GetLookDir();
GxVec3f up = pWnd->GetCameraControl()->GetUp();
GxVec3f delta = loc;
delta -= m_lastLoc;
float distance = delta.magnitude();
float cosm = cos(m_maxRotation);
if(!m_lastTick
|| distance > m_maxMove
|| ticks - m_lastTick > m_maxNotifyTime
|| (m_maxRotation > 0 && m_lastLook.dot(look) < cosm)
|| (m_maxRotation > 0 && m_lastUp.dot(up) < cosm) )
{
string command;
FormatMoveCommand(command);
NotifyAnchor(command);
m_lastTick = ticks;
m_lastLoc = loc;
m_lastUp = up;
m_lastLook = look;
}
}
}
void ChMazeMainInfo::FormatMoveCommand(string &command)
{
command = "xch_cmd=\"PUEBLOMOVE";
for(int i = 0; i < CH_MAX_NOTIFICATION_PARAMS; i++)
{
char buf[100];
GxVec3f vec;
buf[0] = 0;
ChPuebloVrmlWnd* pWnd = (ChPuebloVrmlWnd*)m_pWnd;
// possibilities:
// position look up time orientation velocity slewrate
switch(m_params[i])
{
case 'p':
{
vec = pWnd->GetCameraControl()->GetLoc();
sprintf(buf, " %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()));
break;
}
case 'l':
{
vec = pWnd->GetCameraControl()->GetLookDir();
sprintf(buf, " %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()));
break;
}
case 'u':
{
vec = pWnd->GetCameraControl()->GetUp();
sprintf(buf, " %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()));
break;
}
case 't':
{
chint32 lTime = chint32(::GetMessageTime() + m_dTimeOffset);
sprintf(buf, " %ld", lTime);
break;
}
case 'o':
{
float angle;
pWnd->GetCameraControl()->GetOrientation(vec, angle);
sprintf(buf, " %6.3f %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()), double(angle));
break;
}
#if 1
case 'v':
{
pWnd->GetVelocity(vec);
sprintf(buf, " %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()));
break;
}
case 's':
{
float angle;
pWnd->GetAngularVelocity(vec, angle);
sprintf(buf, " %6.3f %6.3f %6.3f %6.3f", double(vec.x()), double(vec.y()), double(vec.z()), double(angle));
break;
}
#endif
}
command += buf;
}
command += "\"";
}
bool ChMazeMainInfo::OnCameraChange(int efChanged)
{
return true;
}
/*----------------------------------------------------------------------------
ChMazeMainInfo protected methods
----------------------------------------------------------------------------*/
void ChMazeMainInfo::ReadPreferences()
{
GetSettings()->ReadPreferences( "", "", GR_PREFS_GROUP );
}
void ChMazeMainInfo::UpdatePreferences( bool boolMoveVector,
bool boolScaleTextures,
ChShadingLevel renderQuality,
ChShadingLevel moveRenderQuality,
float fHeadlight,
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
int iAsciiTextQuality,
bool boolCollisionAlarm
#else
int iAsciiTextQuality
#endif
)
{
GetSettings()->UpdatePreferences( boolMoveVector,
boolScaleTextures,
renderQuality,
moveRenderQuality,
fHeadlight,
#if (defined(CH_USE_RLAB) || defined(CH_USE_D3D))
iAsciiTextQuality,
boolCollisionAlarm
#else
1
#endif
); //
GetView()->GetRenderContext()->SetDirty();
GetView()->Invalidate(false);
}
void ChMazeMainInfo::OnParseComplete(string &strURL, chparam data)
{
ChGraphicDocumentHTTPReq*pReq = (ChGraphicDocumentHTTPReq*)data;
DoQueuedCommands(pReq);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -