//------------------------------------------------------------------------------
// emRes.h
//
// Copyright (C) 2006-2008,2010,2012,2014,2018 Oliver Hamann.
//
// Homepage: http://eaglemode.sourceforge.net/
//
// This program is free software: you can redistribute it and/or modify it under
// the terms of the GNU General Public License version 3 as published by the
// Free Software Foundation.
//
// This program is distributed in the hope that it will be useful, but WITHOUT
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU General Public License version 3 for
// more details.
//
// You should have received a copy of the GNU General Public License version 3
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//------------------------------------------------------------------------------
#ifndef emRes_h
#define emRes_h
#ifndef emImage_h
#include <emCore/emImage.h>
#endif
#ifndef emModel_h
#include <emCore/emModel.h>
#endif
//==============================================================================
//========================= Resource image acquisition =========================
//==============================================================================
emImage emGetResImage(emRootContext & rootContext, const emString & filePath,
int channelCount=-1);
emImage emTryGetResImage(emRootContext & rootContext, const emString & filePath,
int channelCount=-1);
// Get a resource image. An image file is loaded and cached in the root
// context for quick shared re-use. This means, if the image is already
// cached, it is not loaded again and a shallow copy of that image is
// returned. The image is removed from the cache some time after there
// are no remaining shallow copies. The first version of the function
// calls emFatalError if the loading fails. The second version throws an
// exception instead. The image file format must be Targa (tga).
// ??? A future version should even support other file formats by making
// ??? use of the file model interfaces.
// Arguments:
// rootContext - The root context.
// filePath - Path to the file. Must be Targa format (tga).
// channelCount - Number of channels the image and image file must
// have. -1 means to accept any channel count.
// Returns: The image.
emImage emGetInsResImage(emRootContext & rootContext, const char * prj,
const char * subPath, int channelCount=-1);
emImage emTryGetInsResImage(emRootContext & rootContext, const char * prj,
const char * subPath,
int channelCount=-1);
// Get an installed resource image. This is like
// em[Try]GetResImage(
// rootContext,
// emGetInstallPath(EM_IDT_RES,prj,subPath),
// channelCount
// );
//==============================================================================
//======================== Resource acquisition basics =========================
//==============================================================================
class emResModelBase : public emModel {
protected:
emResModelBase(emContext & context, const emString & name);
void Touch();
virtual unsigned int GetDataRefCount() const = 0;
virtual bool Cycle();
private:
class PollTimer : public emModel {
public:
static emRef<PollTimer> Acquire(emRootContext & rootContext);
emTimer Timer;
protected:
PollTimer(emContext & context, const emString & name);
virtual ~PollTimer();
};
};
template <class CLS> class emResModel : public emResModelBase {
public:
// This template class can be used when implementing functions like
// emGetResImage. The class CLS must be like emImage, emString, emArray
// and emList. That means, it must have a copy operator and a copy
// constructor which perform shallow copies, and it must have the method
// GetDataRefCount. The latter is polled from time to time by the
// internal clean-up mechanism. The context can be non-root here, this
// may be restricted at higher level. Note that several problems of
// caching can be solved easily by the emModel concept (even see
// emVarModel). This resource concept is meant only for situation where
// holding a model reference would not be practicable.
static emRef<emResModel<CLS> > Acquire(emContext & context,
const emString & name);
static emRef<emResModel<CLS> > Lookup(emContext & context,
const char * name);
static emRef<emResModel<CLS> > LookupInherited(emContext & context,
const char * name);
const CLS & Get();
void Set(const CLS & res);
// Both methods are resetting the auto-delete mechanism.
// (Therefore the Get method is non-const)
protected:
emResModel(emContext & context, const emString & name);
virtual unsigned int GetDataRefCount() const;
private:
CLS Res;
};
//==============================================================================
//============================== Implementations ===============================
//==============================================================================
inline void emResModelBase::Touch()
{
if (GetMinCommonLifetime()!=UINT_MAX) SetMinCommonLifetime(UINT_MAX);
}
template <class CLS> emRef<emResModel<CLS> > emResModel<CLS>::Acquire(
emContext & context, const emString & name
)
{
EM_IMPL_ACQUIRE_COMMON(emResModel,context,name)
}
template <class CLS>
emRef<emResModel<CLS> > emResModel<CLS>::Lookup(
emContext & context, const char * name
)
{
return emRef<emResModel>(
(emResModel*)context.Lookup(typeid(emResModel),name)
);
}
template <class CLS>
emRef<emResModel<CLS> > emResModel<CLS>::LookupInherited(
emContext & context, const char * name
)
{
return emRef<emResModel>(
(emResModel*)context.LookupInherited(typeid(emResModel),name)
);
}
template <class CLS> inline const CLS & emResModel<CLS>::Get()
{
Touch();
return Res;
}
template <class CLS> void emResModel<CLS>::Set(const CLS & res)
{
Touch();
Res=res;
}
template <class CLS> emResModel<CLS>::emResModel(
emContext & context, const emString & name
)
: emResModelBase(context,name)
{
}
template <class CLS> unsigned int emResModel<CLS>::GetDataRefCount() const
{
return Res.GetDataRefCount();
}
#endif