1 /*
2  * NodeTimeSensor.cpp
3  *
4  * Copyright (C) 1999 Stephen F. White
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program (see the file "COPYING" for details); if
18  * not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19  * Cambridge, MA 02139, USA.
20  */
21 
22 #include <stdio.h>
23 #include "stdafx.h"
24 
25 #include "NodeTimeSensor.h"
26 #include "Proto.h"
27 #include "Scene.h"
28 #include "FieldValue.h"
29 #include "SFTime.h"
30 #include "SFBool.h"
31 #include "SFFloat.h"
32 #include "Field.h"
33 #include "ExposedField.h"
34 
35 #ifndef DBL_MIN
36 # include <float.h>
37 #endif
38 
ProtoTimeSensor(Scene * scene)39 ProtoTimeSensor::ProtoTimeSensor(Scene *scene)
40   : WonderlandExportProto(scene, "TimeSensor")
41 {
42     cycleInterval.set(
43           addExposedField(SFTIME, "cycleInterval", new SFTime(1.0),
44                           new SFTime(DBL_MIN)));
45     setFieldFlags(cycleInterval, FF_4KIDS);
46 
47     enabled.set(
48           addExposedField(SFBOOL, "enabled", new SFBool(true)));
49     setFieldFlags(enabled, EIF_WONDERLAND_SUPPORTED);
50 
51     loop.set(
52           addExposedField(SFBOOL, "loop", new SFBool(false)));
53     setFieldFlags(loop, FF_4KIDS);
54 
55     pauseTime.set(
56           addExposedField(SFTIME, "pauseTime", new SFTime(0.0)));
57     setFieldFlags(pauseTime, FF_X3D_ONLY);
58     resumeTime.set(
59           addExposedField(SFTIME, "resumeTime", new SFTime(0.0)));
60     setFieldFlags(resumeTime, FF_X3D_ONLY);
61     startTime.set(
62           addExposedField(SFTIME, "startTime", new SFTime(0.0f)));
63     setFieldFlags(startTime, EIF_RECOMMENDED | EIF_WONDERLAND_SUPPORTED);
64     stopTime.set(
65           addExposedField(SFTIME, "stopTime", new SFTime(0.0f)));
66     setFieldFlags(stopTime, EIF_RECOMMENDED | EIF_WONDERLAND_SUPPORTED);
67 
68     first.set(
69           addExposedField(SFBOOL, "first", new SFBool(true)));
70     setFieldFlags(first, FF_X3DOM_ONLY);
71 
72     firstCycle.set(
73           addExposedField(SFFLOAT, "firstCycle", new SFFloat(0.0f)));
74     setFieldFlags(firstCycle, FF_X3DOM_ONLY);
75 
76     addEventOut(SFTIME, "cycleTime");
77     addEventOut(SFTIME, "elapsedTime", FF_X3D_ONLY);
78     fraction_changed.set(addEventOut(SFFLOAT, "fraction_changed",
79                          EOF_RECOMMENDED | EOF_WONDERLAND_SUPPORTED));
80 
81     addEventOut(SFBOOL, "isActive", EOF_WONDERLAND_SUPPORTED);
82     addEventOut(SFBOOL, "isPaused", FF_X3D_ONLY);
83     time.set(addEventOut(SFTIME, "time", EOF_WONDERLAND_SUPPORTED));
84 }
85 
86 Node *
create(Scene * scene)87 ProtoTimeSensor::create(Scene *scene)
88 {
89     return new NodeTimeSensor(scene, this);
90 }
91 
NodeTimeSensor(Scene * scene,Proto * def)92 NodeTimeSensor::NodeTimeSensor(Scene *scene, Proto *def)
93   : Node(scene, def)
94 {
95     m_active = false;
96     m_startTime = 0;
97     m_stopTime = 0;
98     m_delay = 0;
99 }
100 
101 void
preDraw()102 NodeTimeSensor::preDraw()
103 {
104     if (enabled() && enabled()->getValue())
105         m_scene->addTimeSensor(this);
106 }
107 
108 float
getFraction(double t)109 NodeTimeSensor::getFraction(double t)
110 {
111     float fraction = 0;
112 
113     double dstopTime = m_stopTime + m_delay;
114 
115     if (enabled()->getValue()) {
116         if ((t < m_stopTime) || ((m_stopTime <= m_startTime) &&
117                                 loop()->getValue()))
118             m_active = true;
119         if (t - m_startTime < m_delay)
120             m_active = false;
121         if (m_active) {
122             if ((t >= dstopTime) &&
123                 dstopTime > m_startTime && !loop()->getValue()) {
124                 m_active = false;
125             }
126             double temp = (t - m_startTime - m_delay) /
127                           cycleInterval()->getValue();
128             fraction = temp - floor(temp);
129             if (fraction == 0.0 && (t > m_startTime))
130                 fraction = 1.0;
131         }
132     }
133     return fraction;
134 }
135 
136 void
setTime(double t)137 NodeTimeSensor::setTime(double t)
138 {
139     float fraction = getFraction(t);
140 
141     sendEvent(fraction_changed_Field(), t, new SFFloat(fraction));
142     sendEvent(time_Field(), t, new SFTime(t));
143 }
144 
145 void
checkStart(bool loop,double startTime,double stopTime,double t,double delay)146 NodeTimeSensor::checkStart(bool loop, double startTime, double stopTime,
147                            double t, double delay)
148 {
149     if ((t < m_stopTime) || ((stopTime <= startTime) && loop)) {
150         m_active = true;
151         m_startTime = t + delay;
152         m_stopTime = stopTime;
153     } else {
154         m_active = false;
155         m_startTime = startTime + delay;
156         m_stopTime = stopTime;
157     }
158     m_delay = delay;
159 }
160 
161 void
start(double t)162 NodeTimeSensor::start(double t)
163 {
164     checkStart(loop()->getValue(), startTime()->getValue(),
165                stopTime()->getValue(), t);
166 }
167 
168 void
updateStart(int field,FieldValue * value,double t)169 NodeTimeSensor::updateStart(int field, FieldValue *value, double t)
170 {
171     if (m_scene)
172         if (m_scene->isParsing())
173             return;
174     checkStart(loop()->getValue(), startTime()->getValue(),
175                stopTime()->getValue(), t);
176 }
177 
178 int
getProfile(void) const179 NodeTimeSensor::getProfile(void) const
180 {
181     return PROFILE_INTERCHANGE;
182 }
183 
184 
185 int
getComponentLevel(void) const186 NodeTimeSensor::getComponentLevel(void) const
187 {
188     if (hasOutput("isPaused"))
189         return 2;
190     if (!isDefault(pauseTime_Field()))
191         return 2;
192     if (!isDefault(resumeTime_Field()))
193         return 2;
194     return -1;
195 }
196 
197 const char*
getComponentName(void) const198 NodeTimeSensor::getComponentName(void) const
199 {
200     static const char* name = "Time";
201     return name;
202 }
203 
204 
205 
206 
207 
208