#include "pch.h" #include "mdl.h" #include "trekmdl.h" //#include "console.h" #ifndef MARKCU #include "consoledata.h" #endif ////////////////////////////////////////////////////////////////////////////// // // SwitchValuePane // ////////////////////////////////////////////////////////////////////////////// class SwitchValuePane : public ValuePane { protected: TMap > m_mapPanes; TRef m_pPaneCurrent; TRef m_pPaneDefault; int m_nValueCurrent; void UpdateLayout() { DefaultUpdateLayout(); } public: SwitchValuePane(Number* pvalue) : ValuePane(pvalue), m_pPaneDefault(NULL) { pvalue->Update(); NeedLayout(); NeedPaint(); m_nValueCurrent = (int)Number::Cast(pvalue)->GetValue(); } ZString GetFunctionName() { return "SwitchPane"; } void InsertPane(Pane* pPane, int nPaneID) { ZAssert(nPaneID != -1); // reserved m_mapPanes.Set(nPaneID, pPane); UpdatePane(); } void SetDefaultPane(Pane* pPane) { m_pPaneDefault = pPane; UpdatePane(); } private: void UpdatePane() { TRef pPane; if (!m_mapPanes.Find(m_nValueCurrent, pPane)) pPane = m_pPaneDefault; if (pPane != m_pPaneCurrent) { if (m_pPaneCurrent) RemoveChild(m_pPaneCurrent); if (pPane) InsertAtBottom(pPane); m_pPaneCurrent = pPane; } } void ChildChanged(Value* pvalue, Value* pvalueNew) { ZAssert(NULL == pvalueNew); ZAssert(GetChild(0) == pvalue); pvalue->Update(); m_nValueCurrent = (int)Number::Cast(pvalue)->GetValue(); UpdatePane(); } }; ////////////////////////////////////////////////////////////////////////////// // // ImageValuePane // ////////////////////////////////////////////////////////////////////////////// class ImageValuePane : public ValuePane { public: ImageValuePane(Image* pimage) : ValuePane(pimage) { } Image* GetImage() { return Image::Cast((Value*)GetChild(0)); } void SetImage(Image* pimage) { SetChild(0, pimage); } private: void ChildChanged(Value* pvalue, Value* pvalueNew) { Value::ChildChanged(pvalue, pvalueNew); NeedPaint(); NeedLayout(); } void UpdateLayout() { Update(); InternalSetSize( WinPoint::Cast(GetImage()->GetBounds().GetRect().Size()) ); Pane::UpdateLayout(); } void Paint(Surface* psurface) { psurface->BitBlt(WinPoint(0, 0), GetImage()->GetSurface()); } }; ////////////////////////////////////////////////////////////////////////////// // // StringValuePane // ////////////////////////////////////////////////////////////////////////////// class StringValuePane : public Value, public StringPane { protected: TRef m_pcolor; public: StringValuePane(StringValue* pvalue, ColorValue* pcolor, IEngineFont* pfont, WinPoint ptSize, Justification justify) : Value(pvalue, pcolor), StringPane((pvalue->Update(), pvalue->GetValue()), pfont, ptSize, justify), m_pcolor(pcolor) { pcolor->Update(); SetTextColor(pcolor->GetValue()); StringPane::SetString(pvalue->GetValue()); } StringValuePane(StringValue* pvalue, ColorValue* pcolor, IEngineFont* pfont) : Value(pvalue, pcolor), StringPane((pvalue->Update(), pvalue->GetValue()), pfont), m_pcolor(pcolor) { pcolor->Update(); SetTextColor(pcolor->GetValue()); StringPane::SetString(pvalue->GetValue()); } ZString GetFunctionName() { return "StringPane"; } virtual void SetString(const ZString& str) { StringPane::SetString(str); SetChild(0, new StringValue(str)); } private: void ChildChanged(Value* pvalue, Value* pvalueNew) { ZAssert(NULL == pvalueNew); pvalue->Update(); if (pvalue == m_pcolor) { ZAssert(pvalue == GetChild(1)); SetTextColor(m_pcolor->GetValue()); } else { ZAssert(pvalue == GetChild(0)); StringPane::SetString(StringValue::Cast(pvalue)->GetValue()); } } }; ////////////////////////////////////////////////////////////////////////////// // // GaugeValuePane // ////////////////////////////////////////////////////////////////////////////// class GaugeValuePane : public ValuePane { private: TRef m_psurface; float m_minValue; float m_maxValue; int m_value; int m_valueOld; int m_valueFlash; float m_timeLastChange; Color m_colorFlash; Color m_colorEmpty; public: GaugeValuePane(Surface* psurface, Number* pnumber, Number* ptime, const Color& colorFlash, const Color& colorEmpty) : ValuePane(pnumber, ptime), m_psurface(psurface), m_colorFlash(colorFlash), m_colorEmpty(colorEmpty), m_minValue(0.0f), m_maxValue(1.0f), m_value(0), m_valueOld(0), m_valueFlash(0), m_timeLastChange(ptime->GetValue()) { pnumber->Update(); SetValue(pnumber->GetValue(), true); assert(m_psurface); assert(m_minValue < m_maxValue); InternalSetSize(m_psurface->GetSize()); NeedPaint(); } protected: void Paint(Surface* psurface) { if (m_value != 0) { psurface->BitBlt( WinPoint(0, 0), m_psurface, WinRect(0, 0, m_value, YSize()) ); } if (m_value < m_valueFlash) { psurface->FillRect( WinRect( m_value, 0, m_valueFlash, YSize() ), m_colorFlash ); } } void SetValue(float v, bool fFlash) { m_value = (int)bound( (v - m_minValue) * ((float)XSize()) / (m_maxValue - m_minValue), 0.0f, (float)XSize() ); } void Update(float time) { if (m_value != m_valueOld) { if (m_value < m_valueOld) { m_valueFlash = m_valueOld; } else { m_valueFlash = m_value; } m_timeLastChange = time; m_valueOld = m_value; NeedPaint(); } if (m_value != m_valueFlash && time - m_timeLastChange > 0.25f) { m_valueFlash = m_value; NeedPaint(); } } private: void ChildChanged(Value* pvalue, Value* pvalueNew) { ZAssert(NULL == pvalueNew); if (pvalue == GetChild(0)) // number changed { pvalue->Update(); SetValue(Number::Cast(pvalue)->GetValue(), true); } else // time changed { ZAssert(GetChild(1) == pvalue); pvalue->Update(); Update(Number::Cast(pvalue)->GetValue()); } } }; ////////////////////////////////////////////////////////////////////////////// // // Factories // ////////////////////////////////////////////////////////////////////////////// class SwitchPaneFactory : public IFunction { public: TRef Apply(ObjectStack& stack) { TRef pnumber; CastTo(pnumber, (IObject*)stack.Pop()); TRef plist; CastTo(plist, (IObject*)stack.Pop()); TRef ppane = new SwitchValuePane(pnumber); plist->GetFirst(); while (plist->GetCurrent() != NULL) { IObjectPair* ppair; CastTo(ppair, plist->GetCurrent()); TRef ppaneChild; CastTo(ppaneChild, (Pane*)ppair->GetFirst()); TRef pnumberChildID = Number::Cast(ppair->GetSecond()); ppane->InsertPane(ppaneChild, (int)pnumberChildID->GetValue()); plist->GetNext(); } if (stack.GetCount() > 0) { TRef ppaneDefault; CastTo(ppaneDefault, (Pane*)(IObject*)stack.Pop()); ppane->SetDefaultPane(ppaneDefault); } return (Pane*)ppane; } }; class StringPaneFactory : public IFunction { public: TRef Apply(ObjectStack& stack) { TRef pstring; CastTo(pstring, (IObject*)stack.Pop()); TRef pcolor; CastTo(pcolor, (IObject*)stack.Pop()); TRef ppointSize; WinPoint ptSize; if (stack.GetCount() > 0) { CastTo(ppointSize, (IObject*)stack.Pop()); ptSize = WinPoint( (int)ppointSize->GetValue().X(), (int)ppointSize->GetValue().Y() ); } Justification justification = JustifyLeft(); if (stack.GetCount() > 0) { TRef pjustify = Number::Cast((IObject*)stack.Pop()); justification.SetWord((DWORD)pjustify->GetValue()); } TRef pfont = TrekResources::SmallFont(); if (stack.GetCount() > 0) { TRef pfontLocal; CastTo(pfontLocal, (IObject*)stack.Pop()); pfont = pfontLocal->GetValue(); } bool bRightClip = false; if (stack.GetCount() > 0) bRightClip = GetBoolean((IObject*)stack.Pop()); TRef ppane; if (ppointSize) { if (bRightClip) justification = JustifyLeftClipRight(); ppane = new StringValuePane(pstring, pcolor, pfont, ptSize, justification); } else ppane = new StringValuePane(pstring, pcolor, pfont); return (Pane*)ppane; } }; class GaugePaneFactory : public IFunction { public: TRef Apply(ObjectStack& stack) { TRef pimage = Image::Cast((Value*)(IObject*)stack.Pop()); TRef pnumber; CastTo(pnumber, (IObject*)stack.Pop()); Color colorFlash = GetColor((IObject*)stack.Pop()); Color colorEmpty = GetColor((IObject*)stack.Pop()); TRef ppane = new GaugeValuePane( pimage->GetSurface(), pnumber, GetWindow()->GetTime(), colorFlash, colorEmpty ); return (Pane*)ppane; } }; ////////////////////////////////////////////////////////////////////////////// // // ButtonPane // ////////////////////////////////////////////////////////////////////////////// namespace { class SoundIDEventSink : public IEventSink, public IIntegerEventSink { private: SoundID m_soundId; public: SoundIDEventSink(SoundID soundId) { m_soundId = soundId; }; bool OnEvent(IIntegerEventSource* pevent, int nCmd) { return OnEvent(pevent); } bool OnEvent(IEventSource* pevent) { GetWindow()->StartSound(m_soundId); // HACK: force the sound to start _now_ // (some buttons cause events that take 1/5 of a second or so to // happen, and the delay in the sonic feedback for the mouse click // is annoying). GetWindow()->SoundEngineUpdate(); return true; } }; }; TRef CreateTrekButton( ButtonFacePane* ppane, bool bToggle, SoundID soundClick, float repeatRate, float repeatDelay ) { TRef pbutton = CreateButton(ppane, bToggle, repeatRate, repeatDelay); pbutton->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pbutton->GetEventSource()->AddSink(new SoundIDEventSink(soundClick)); return pbutton; } TRef CreateTrekButton( Pane* ppaneUp, Pane* ppaneDown, bool bToggle, SoundID soundClick, float repeatRate, float repeatDelay ) { TRef pbutton = CreateButton(ppaneUp, ppaneDown, bToggle, repeatRate, repeatDelay); pbutton->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pbutton->GetEventSource()->AddSink(new SoundIDEventSink(soundClick)); return pbutton; } class ButtonPaneFactory : public IFunction { private: TRef m_pmodeler; public: ButtonPaneFactory(Modeler* pmodeler) : m_pmodeler(pmodeler) { } TRef Apply(ObjectStack& stack) { TRef pimage; CastTo(pimage, (Value*)(IObject*)stack.Pop()); TRef pnumberFaces; CastTo(pnumberFaces, (IObject*)stack.Pop()); TRef pboolToggle; CastTo(pboolToggle, (IObject*)stack.Pop()); DWORD dwFaces = (DWORD)pnumberFaces->GetValue(); return CreateTrekButton( CreateButtonFacePane( pimage->GetSurface(), dwFaces ), pboolToggle->GetValue(), (dwFaces & ButtonFaceCheckedDown) ? mouseclickSound : positiveButtonClickSound ); } }; ////////////////////////////////////////////////////////////////////////////// // // SoundButtonPane // ////////////////////////////////////////////////////////////////////////////// /* namespace { class SoundEventSink : public IEventSink, public IIntegerEventSink { private: TRef m_ptemplate; public: SoundEventSink(ISoundTemplate* ptemplate) : m_ptemplate(ptemplate) { }; bool OnEvent(IIntegerEventSource* pevent, int nCmd) { return OnEvent(pevent); } bool OnEvent(IEventSource* pevent) { GetWindow()->StartSound(m_ptemplate); // HACK: force the sound to start _now_ // (some buttons cause events that take 1/5 of a second or so to // happen, and the delay in the sonic feedback for the mouse click // is annoying). GetWindow()->SoundEngineUpdate(); return true; } }; }; */ class SoundButtonPaneFactory : public IFunction { private: TRef m_pmodeler; public: SoundButtonPaneFactory(Modeler* pmodeler) : m_pmodeler(pmodeler) { } TRef Apply(ObjectStack& stack) { TRef pimage; CastTo(pimage, (Value*)(IObject*)stack.Pop()); TRef pnumberFaces; CastTo(pnumberFaces, (IObject*)stack.Pop()); TRef pboolToggle; CastTo(pboolToggle, (IObject*)stack.Pop()); TRef pnumberClickSoundId; CastTo(pnumberClickSoundId, (IObject*)stack.Pop()); TRef pbutton = CreateButton( CreateButtonFacePane( pimage->GetSurface(), (DWORD)pnumberFaces->GetValue() ), pboolToggle->GetValue() ); pbutton->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pbutton->GetEventSource()->AddSink(new SoundIDEventSink((SoundID)pnumberClickSoundId->GetValue())); return pbutton; } }; ////////////////////////////////////////////////////////////////////////////// // // ButtonBarPane // ////////////////////////////////////////////////////////////////////////////// class ButtonBarPaneFactory : public IFunction { private: TRef m_pmodeler; public: ButtonBarPaneFactory(Modeler* pmodeler) : m_pmodeler(pmodeler) { } TRef Apply(ObjectStack& stack) { TRef pimage; CastTo(pimage, (Value*)(IObject*)stack.Pop()); TRef pnumberFaces; CastTo(pnumberFaces, (IObject*)stack.Pop()); bool bActAsTabs = false; TVector m_vecColumns; ParseIntVector((IObject*)stack.Pop(), m_vecColumns); if (stack.GetCount() > 0) { TRef pbooleanActAsTabs; CastTo(pbooleanActAsTabs, (IObject*)stack.Pop()); bActAsTabs = pbooleanActAsTabs->GetValue(); } TRef pbuttonbar = CreateButtonBarPane( pimage->GetSurface(), (DWORD)pnumberFaces->GetValue(), m_vecColumns, bActAsTabs ); pbuttonbar->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pbuttonbar->GetEventSource()->AddSink(new SoundIDEventSink(mouseclickSound)); return pbuttonbar; } }; ////////////////////////////////////////////////////////////////////////////// // // ImageComboPane // ////////////////////////////////////////////////////////////////////////////// class ImageComboPaneFactory : public IFunction { private: TRef m_pmodeler; TRef m_ppopupContainer; public: ImageComboPaneFactory( Modeler* pmodeler, IPopupContainer* ppopupContainer ) : m_pmodeler(pmodeler), m_ppopupContainer(ppopupContainer) { } TRef Apply(ObjectStack& stack) { TRef pimage; CastTo(pimage, (Value*)(IObject*)stack.Pop()); TRef pfont; CastTo(pfont, (IObject*)stack.Pop()); TRef pcombo = CreateComboPane( m_pmodeler, m_ppopupContainer, pfont->GetValue(), WinPoint(0, 0), CreateImageComboFacePane(pimage) ); pcombo->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pcombo->GetMenuSelectEventSource()->AddSink(new SoundIDEventSink(mouseclickSound)); return pcombo; } }; ////////////////////////////////////////////////////////////////////////////// // // StringComboPane // ////////////////////////////////////////////////////////////////////////////// class StringComboPaneFactory : public IFunction { private: TRef m_pmodeler; TRef m_ppopupContainer; public: StringComboPaneFactory( Modeler* pmodeler, IPopupContainer* ppopupContainer ) : m_pmodeler(pmodeler), m_ppopupContainer(ppopupContainer) { } TRef Apply(ObjectStack& stack) { TRef ppointFace; CastTo(ppointFace, (IObject*)stack.Pop()); TRef ppoint; CastTo(ppoint, (IObject*)stack.Pop()); TRef pfont; CastTo(pfont, (IObject*)stack.Pop()); TRef pcolor; CastTo(pcolor, (IObject*)stack.Pop()); TRef pcombo = CreateComboPane( m_pmodeler, m_ppopupContainer, pfont->GetValue(), WinPoint::Cast(ppoint->GetValue()), CreateStringComboFacePane( WinPoint::Cast(ppointFace->GetValue()), pfont->GetValue(), pcolor->GetValue(), false ) ); pcombo->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pcombo->GetMenuSelectEventSource()->AddSink(new SoundIDEventSink(mouseclickSound)); return pcombo; } }; ////////////////////////////////////////////////////////////////////////////// // // StringColorComboPane // ////////////////////////////////////////////////////////////////////////////// class StringColorComboPaneFactory : public IFunction { private: TRef m_pmodeler; TRef m_ppopupContainer; public: StringColorComboPaneFactory( Modeler* pmodeler, IPopupContainer* ppopupContainer ) : m_pmodeler(pmodeler), m_ppopupContainer(ppopupContainer) { } TRef Apply(ObjectStack& stack) { TRef ppointFace; CastTo(ppointFace, (IObject*)stack.Pop()); TRef ppoint; CastTo(ppoint, (IObject*)stack.Pop()); TRef pfont; CastTo(pfont, (IObject*)stack.Pop()); TRef pcolor; CastTo(pcolor, (IObject*)stack.Pop()); TRef pcombo = CreateComboPane( m_pmodeler, m_ppopupContainer, pfont->GetValue(), WinPoint::Cast(ppoint->GetValue()), CreateStringComboFacePane( WinPoint::Cast(ppointFace->GetValue()), pfont->GetValue(), pcolor->GetValue(), true ) ); pcombo->GetMouseEnterWhileEnabledEventSource()->AddSink(new SoundIDEventSink(mouseoverSound)); pcombo->GetMenuSelectEventSource()->AddSink(new SoundIDEventSink(mouseclickSound)); return pcombo; } }; ////////////////////////////////////////////////////////////////////////////// // // Misc // ////////////////////////////////////////////////////////////////////////////// void ExportPaneFactories(INameSpace* pns) { // // Display sides // pns->AddMember("SideLeft", new Number((float)ATLeft )); pns->AddMember("SideTopLeft", new Number((float)ATTopLeft )); pns->AddMember("SideTop", new Number((float)ATTop )); pns->AddMember("SideTopRight", new Number((float)ATTopRight )); pns->AddMember("SideRight", new Number((float)ATRight )); pns->AddMember("SideBottomRight", new Number((float)ATBottomRight)); pns->AddMember("SideBottom", new Number((float)ATBottom )); pns->AddMember("SideBottomLeft", new Number((float)ATBottomLeft )); pns->AddMember("SideCenter", new Number((float)ATCenter )); // add our 'primitive' panes pns->AddMember("StringPane", new StringPaneFactory()); pns->AddMember("GaugePane", new GaugePaneFactory()); pns->AddMember("SwitchPane", new SwitchPaneFactory()); pns->AddMember("ButtonPane", new ButtonPaneFactory(GetModeler())); pns->AddMember("SoundButtonPane", new SoundButtonPaneFactory(GetModeler())); pns->AddMember("ButtonBarPane",new ButtonBarPaneFactory(GetModeler())); pns->AddMember("ImageComboPane", new ImageComboPaneFactory(GetModeler(), GetWindow()->GetPopupContainer())); pns->AddMember("StringComboPane", new StringComboPaneFactory(GetModeler(), GetWindow()->GetPopupContainer())); pns->AddMember("StringColorComboPane", new StringColorComboPaneFactory(GetModeler(), GetWindow()->GetPopupContainer())); // add our 'specialty' panes #ifndef MARKCU1 pns->AddMember("SectorMapPane", new SectorMapPaneFactory()); pns->AddMember("SectorInfoPane", new SectorInfoPaneFactory()); pns->AddMember("PartInfoPane", new PartInfoPaneFactory()); pns->AddMember("PurchasesPane", new PurchasesPaneFactory()); pns->AddMember("SelectionPane", new SelectionPaneFactory()); pns->AddMember("SelectModelPane", new SelectModelPaneFactory()); pns->AddMember("ChatListPane", new ChatListPaneFactory()); pns->AddMember("InventoryImage", new InventoryImageFactory()); #endif }