00001 /* 00002 SagaEngine library 00003 Copyright (c) 2002-2006 Skalden Studio AS 00004 00005 This software is provided 'as-is', without any express or implied 00006 warranty. In no event will the authors be held liable for any 00007 damages arising from the use of this software. 00008 00009 Permission is granted to distribute the library under the terms of the 00010 Q Public License version 1.0. Be sure to read and understand the license 00011 before using the library. It should be included here, or you may read it 00012 at http://www.trolltech.com/products/qt/licenses/licensing/qpl 00013 00014 The original version of this library can be located at: 00015 http://www.sagaengine.com/ 00016 00017 Rune Myrland 00018 rune@skalden.com 00019 */ 00020 00021 00022 #include "ActionComponent.hpp" 00023 #include "ActionAndParameter.hpp" 00024 #include "../schema/SimSchema.hpp" 00025 00026 00027 namespace se_core { 00028 00029 ActionComponent 00030 ::ActionComponent(Composite* owner) 00031 : Component(sct_ACTION, owner), feed_(0) { 00032 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00033 presentActionScheduledComplete_[i] = 0; 00034 } 00035 } 00036 00037 00038 ActionComponent 00039 ::~ActionComponent() { 00040 } 00041 00042 00043 void ActionComponent 00044 ::cleanup() { 00045 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00046 clearPlannedAction(i); 00047 } 00048 disrupt(); 00049 } 00050 00051 00052 void ActionComponent 00053 ::scheduleNextAction(short channel) { 00054 // Actions still in action queue after 00055 // scheduleForDestruction may try to plan 00056 // further actions 00057 if(isDead()) return; 00058 Assert(plannedAction_[channel].hasAction()); 00059 presentAction_[channel] = plannedAction_[channel]; 00060 plannedAction_[channel].resetAction(); 00061 00062 // Add to action queue 00063 const Action* a = presentAction_[channel].action(); 00064 Parameter& p = presentAction_[channel].parameter(); 00065 p.resetActionStage(); 00066 p.setChannel(channel); 00067 // 00068 a->prepare(*this, p); 00069 if(!a->doPause(*this, p)) { 00070 presentActionScheduledComplete_[channel] 00071 = SimSchema::actionQueue[channel].add(*this, a->duration(*this, p)); 00072 } 00073 // 00074 } 00075 00076 00077 void ActionComponent 00078 ::continueAction(long when, short channel) { 00079 // Add to action queue 00080 const Action* a = presentAction_[channel].action(); 00081 Parameter& p = presentAction_[channel].parameter(); 00082 p.incrActionStage(); 00083 if(!a->doPause(*this, p)) { 00084 presentActionScheduledComplete_[channel] 00085 = SimSchema::actionQueue[channel].add(*this, a->duration(*this, p)); 00086 } 00087 } 00088 00089 00090 void ActionComponent 00091 ::unpause(short channel) { 00092 const Action* a = presentAction_[channel].action(); 00093 Parameter& p = presentAction_[channel].parameter(); 00094 presentActionScheduledComplete_[channel] 00095 = SimSchema::actionQueue[channel].add(*this, a->duration(*this, p)); 00096 } 00097 00098 void ActionComponent 00099 ::planAction(short channel, const Action& action, const Parameter* parameter) const { 00100 plannedAction_[channel].setAction(action); 00101 if(parameter) { 00102 plannedAction_[channel].copyParameter(*parameter); 00103 } 00104 if(!presentAction_[channel].hasAction() && plannedAction_[channel].hasAction()) { 00105 const_cast<ActionComponent&>(*this).scheduleNextAction(channel); 00106 } 00107 } 00108 00109 00110 void ActionComponent 00111 ::planAction(short channel, const ActionAndParameter& action) const { 00112 if(!action.hasAction()) 00113 return; 00114 plannedAction_[channel].set(action); 00115 if(!presentAction_[channel].hasAction() && plannedAction_[channel].hasAction()) { 00116 const_cast<ActionComponent&>(*this).scheduleNextAction(channel); 00117 } 00118 } 00119 00120 00121 void ActionComponent 00122 ::planActionIfNone(short channel, const ActionAndParameter& action) const { 00123 if(!plannedAction_[ channel ].hasAction()) 00124 planAction(channel, action); 00125 } 00126 00127 00128 void ActionComponent 00129 ::clearPlannedAction(short channel) const { 00130 plannedAction_[channel].resetAction(); 00131 } 00132 00133 00134 void ActionComponent 00135 ::disrupt() { 00136 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00137 disrupt(i); 00138 } 00139 } 00140 00141 00142 void ActionComponent 00143 ::resume() { 00144 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00145 presentAction_[ i ].setDisrupted(false); 00146 if(!presentAction_[ i ].hasAction()) { 00147 nextScriptAction(i); 00148 if(plannedAction_[i].hasAction()) { 00149 scheduleNextAction(i); 00150 } 00151 } 00152 } 00153 } 00154 00155 00156 bool ActionComponent 00157 ::disrupt(short channel) { 00158 if(!presentAction_[ channel ].hasAction()) return true; 00159 // Actions are only removed from ActionQueue if it is in a future 00160 // initiative. If it is in the initiative presently performed, it 00161 // will not be touched... 00162 bool didDisrupt = SimSchema::actionQueue[ channel ].disrupt(*this); 00163 if(didDisrupt) { 00164 const Action* a = presentAction_[channel].action(); 00165 Parameter& p = presentAction_[channel].parameter(); 00166 a->disrupt(*this, p); 00167 presentAction_[channel].resetAction(); 00168 } 00169 presentAction_[ channel ].setDisrupted(true); 00170 return didDisrupt; 00171 } 00172 00173 00174 void ActionComponent 00175 ::nextScriptAction(short channel) { 00176 if(!feed_) return; 00177 ActionAndParameter& aap = plannedAction_[channel]; 00178 feed_->nextAction(*this, channel, aap); 00179 if(aap.hasAction()) { 00180 if(!presentAction_[channel].hasAction()) { 00181 scheduleNextAction(channel); 00182 } 00183 } 00184 } 00185 00186 00187 void ActionComponent 00188 ::setActionFeed(ActionFeed* feed) { 00189 AssertFatal(feed_ == 0, "Should only have one action feed"); 00190 feed_ = feed; 00191 } 00192 00193 00194 void ActionComponent 00195 ::setScriptActive(bool state) { 00196 if(state) { 00197 if(feed_) { 00198 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00199 presentAction_[i].setDisrupted(false); 00200 nextScriptAction(i); 00201 } 00202 } 00203 } 00204 else { 00205 // Clear action in all channels 00206 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00207 clearPlannedAction(i); 00208 } 00209 // Disrupt actions in progress 00210 //disrupt(); 00211 } 00212 } 00213 00214 00215 void ActionComponent 00216 ::setActive(bool state) { 00217 LogDetail(owner_->name() << " " << state); 00218 setScriptActive(state); 00219 } 00220 00221 00222 void ActionComponent 00223 ::castFeedbackEvent(int type) { 00224 for(int i = 0; i < CHANNEL_COUNT; ++i) { 00225 if(presentAction_[ i ].hasAction()) { 00226 const Action* a = presentAction_[i].action(); 00227 Parameter& p = presentAction_[i].parameter(); 00228 a->feedbackEvent(*this, p, type); 00229 } 00230 } 00231 } 00232 }
Home Page | SagaEngine trunk (updated nightly) reference generated Sun Dec 2 20:06:10 2007 by Doxygen version 1.3.9.1.